diff --git a/docs/superpowers/specs/2026-11-10-tms34010-llvm-design.md b/docs/superpowers/specs/2026-11-10-tms34010-llvm-design.md index 65ac05b..a86eede 100644 --- a/docs/superpowers/specs/2026-11-10-tms34010-llvm-design.md +++ b/docs/superpowers/specs/2026-11-10-tms34010-llvm-design.md @@ -199,10 +199,12 @@ early GEP-scaling pass. `p:32:16`) with **packed struct types** (`<{ … }>`), not globally 1-byte scalar alignment. `-fpack-struct=1` is the spike's approximation; the target should make packed structs the default. -- `char` signed; `enum` unsigned 32-bit; `_Bool` 8-bit (object alignment 2, - member alignment 1). `long long` is 64-bit but has no TI oracle. -- `_Alignof`/`alignof`: scalar objects report 2 bytes; a packed struct reports - 1 in the frontend because its LLVM type is `<{...}>`. The backend still aligns +- `char` signed; `enum` unsigned 32-bit; `_Bool` is 8-bit with LLVM `i8` + alignment (1 byte); TI C89 has no `_Bool`, so this is not ABI-visible. + `long long` is 64-bit but has no TI oracle. +- `_Alignof`/`alignof`: scalar objects other than `char` report 2 bytes; + `char` is 1 by C definition; a packed struct reports 1 in the frontend + because its LLVM type is `<{...}>`. The backend still aligns standalone globals, allocas and frame objects to 2 bytes. TI C89 has no `_Alignof`, so this is a documented modern-C difference, not an ABI break for ROM code; a custom AST layout hook can revisit it if user code depends on diff --git a/patches/llvm/0002-target-skeleton.patch b/patches/llvm/0002-target-skeleton.patch index e0593d0..21f906c 100644 --- a/patches/llvm/0002-target-skeleton.patch +++ b/patches/llvm/0002-target-skeleton.patch @@ -12,13 +12,14 @@ index c1e375b88..8eaaccbab 100644 X86 diff --git a/llvm/lib/Target/TMS34010/CMakeLists.txt b/llvm/lib/Target/TMS34010/CMakeLists.txt new file mode 100644 -index 000000000..9fecaf723 +index 000000000..d0bd50740 --- /dev/null +++ b/llvm/lib/Target/TMS34010/CMakeLists.txt -@@ -0,0 +1,18 @@ +@@ -0,0 +1,19 @@ +add_llvm_component_group(TMS34010) + +add_llvm_target(TMS34010CodeGen ++ TMS34010Subtarget.cpp + TMS34010TargetMachine.cpp + + LINK_COMPONENTS @@ -84,12 +85,65 @@ index 000000000..70e035b24 +} // namespace llvm + +#endif +diff --git a/llvm/lib/Target/TMS34010/TMS34010Subtarget.cpp b/llvm/lib/Target/TMS34010/TMS34010Subtarget.cpp +new file mode 100644 +index 000000000..322767368 +--- /dev/null ++++ b/llvm/lib/Target/TMS34010/TMS34010Subtarget.cpp +@@ -0,0 +1,2 @@ ++//===-- TMS34010Subtarget.cpp - TMS34010 subtarget ------------------------===// ++#include "TMS34010Subtarget.h" +diff --git a/llvm/lib/Target/TMS34010/TMS34010Subtarget.h b/llvm/lib/Target/TMS34010/TMS34010Subtarget.h +new file mode 100644 +index 000000000..7a5d1a2d5 +--- /dev/null ++++ b/llvm/lib/Target/TMS34010/TMS34010Subtarget.h +@@ -0,0 +1,39 @@ ++//===-- TMS34010Subtarget.h - TMS34010 subtarget ----------------*- C++ -*-===// ++#ifndef LLVM_LIB_TARGET_TMS34010_TMS34010SUBTARGET_H ++#define LLVM_LIB_TARGET_TMS34010_TMS34010SUBTARGET_H ++ ++#include "llvm/ADT/StringTable.h" ++#include "llvm/CodeGen/TargetSubtargetInfo.h" ++ ++namespace llvm { ++ ++class TMS34010Subtarget : public TargetSubtargetInfo { ++public: ++ TMS34010Subtarget(const Triple &TT, StringRef CPU, StringRef FS) ++ : TargetSubtargetInfo(TT, CPU, CPU, FS, StringTable(""), {}, {}, nullptr, ++ nullptr, nullptr, nullptr, nullptr, nullptr, ++ nullptr) {} ++ ++ const TargetRegisterInfo *getRegisterInfo() const override { return nullptr; } ++ ++ const FeatureBitset &getInlineIgnoreFeatures() const override { ++ static const FeatureBitset Empty; ++ return Empty; ++ } ++ const FeatureBitset &getInlineInverseFeatures() const override { ++ static const FeatureBitset Empty; ++ return Empty; ++ } ++ const FeatureBitset &getInlineMustMatchFeatures() const override { ++ static const FeatureBitset Empty; ++ return Empty; ++ } ++ ++ /// Bit-address IR already carries bit offsets. Do not let CodeGenPrepare ++ /// sink addresses back into byte-offset GEPs. ++ bool addrSinkUsingGEPs() const override { return false; } ++}; ++ ++} // namespace llvm ++ ++#endif diff --git a/llvm/lib/Target/TMS34010/TMS34010TargetMachine.cpp b/llvm/lib/Target/TMS34010/TMS34010TargetMachine.cpp new file mode 100644 -index 000000000..d2f39e236 +index 000000000..a22f8e13b --- /dev/null +++ b/llvm/lib/Target/TMS34010/TMS34010TargetMachine.cpp -@@ -0,0 +1,25 @@ +@@ -0,0 +1,26 @@ +//===-- TMS34010TargetMachine.cpp - TMS34010 target machine ---------------===// +#include "TMS34010TargetMachine.h" +#include "TargetInfo/TMS34010TargetInfo.h" @@ -104,7 +158,8 @@ index 000000000..d2f39e236 + const Target &T, const Triple &TT, StringRef CPU, StringRef FS, + const TargetOptions &Options, std::optional RM, + std::optional CM, CodeGenOptLevel OL, bool JIT) -+ : TargetMachine(T, TMS34010DataLayout, TT, CPU, FS, Options) { ++ : TargetMachine(T, TMS34010DataLayout, TT, CPU, FS, Options), ++ Subtarget(TT, CPU, FS) { + (void)RM; + (void)CM; + (void)OL; @@ -117,25 +172,32 @@ index 000000000..d2f39e236 +} diff --git a/llvm/lib/Target/TMS34010/TMS34010TargetMachine.h b/llvm/lib/Target/TMS34010/TMS34010TargetMachine.h new file mode 100644 -index 000000000..8504946e4 +index 000000000..7433abb7b --- /dev/null +++ b/llvm/lib/Target/TMS34010/TMS34010TargetMachine.h -@@ -0,0 +1,19 @@ +@@ -0,0 +1,26 @@ +//===-- TMS34010TargetMachine.h - TMS34010 target machine -------*- C++ -*-===// +#ifndef LLVM_LIB_TARGET_TMS34010_TMS34010TARGETMACHINE_H +#define LLVM_LIB_TARGET_TMS34010_TMS34010TARGETMACHINE_H + ++#include "TMS34010Subtarget.h" +#include "llvm/Target/TargetMachine.h" +#include + +namespace llvm { +class TMS34010TargetMachine : public TargetMachine { ++ TMS34010Subtarget Subtarget; ++ +public: + TMS34010TargetMachine(const Target &T, const Triple &TT, StringRef CPU, + StringRef FS, const TargetOptions &Options, + std::optional RM, + std::optional CM, CodeGenOptLevel OL, + bool JIT); ++ ++ const TMS34010Subtarget *getSubtargetImpl(const Function &) const override { ++ return &Subtarget; ++ } +}; +} // namespace llvm + diff --git a/patches/llvm/0003-clang-target.patch b/patches/llvm/0003-clang-target.patch index 4d98525..f6ab3ac 100644 --- a/patches/llvm/0003-clang-target.patch +++ b/patches/llvm/0003-clang-target.patch @@ -34,10 +34,10 @@ index 8c01cfca8..d5c7eae92 100644 case llvm::Triple::Linux: diff --git a/clang/lib/Basic/Targets/TMS34010.cpp b/clang/lib/Basic/Targets/TMS34010.cpp new file mode 100644 -index 000000000..97a30856c +index 000000000..d8cdb8242 --- /dev/null +++ b/clang/lib/Basic/Targets/TMS34010.cpp -@@ -0,0 +1,68 @@ +@@ -0,0 +1,71 @@ +//===--- TMS34010.cpp - Implement TMS34010 target feature support ---------===// +#include "TMS34010.h" +#include "clang/Basic/MacroBuilder.h" @@ -66,6 +66,9 @@ index 000000000..97a30856c + PointerWidth = 32; + PointerAlign = 16; + BoolWidth = 8; ++ // LLVM maps bool to i8 and the data layout fixes i8 at 1-byte alignment. ++ // BoolAlign = 16 makes Clang abort on that mismatch; TI C89 has no _Bool, ++ // so 1-byte alignment is not ABI-visible for ROM interop. + BoolAlign = 8; + SuitableAlign = 16; + WCharType = SignedInt; @@ -170,10 +173,10 @@ index 000000000..ef2f72596 +#endif diff --git a/clang/test/CodeGen/TMS34010/layout.c b/clang/test/CodeGen/TMS34010/layout.c new file mode 100644 -index 000000000..3dbf7f3e6 +index 000000000..eb47b142d --- /dev/null +++ b/clang/test/CodeGen/TMS34010/layout.c -@@ -0,0 +1,27 @@ +@@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple tms34010-unknown-none -ffreestanding -fsyntax-only %s +struct S { char c; int i; void *p; }; +enum E { E0 = 0, E1 = 1 }; @@ -192,6 +195,7 @@ index 000000000..3dbf7f3e6 +_Static_assert(sizeof(double) == 8, "double"); +_Static_assert(sizeof(long long) == 8, "long long"); +_Static_assert(sizeof(_Bool) == 1, "_Bool"); ++_Static_assert(_Alignof(_Bool) == 1, "_Bool align"); +_Static_assert(sizeof(__WCHAR_TYPE__) == 4, "wchar_t"); +_Static_assert(sizeof(__SIZE_TYPE__) == 4, "size_t"); +_Static_assert(sizeof(__PTRDIFF_TYPE__) == 4, "ptrdiff_t"); diff --git a/scripts/tests/m0/ptrdiff.c b/scripts/tests/m0/ptrdiff.c index 39933a7..5b58eeb 100644 --- a/scripts/tests/m0/ptrdiff.c +++ b/scripts/tests/m0/ptrdiff.c @@ -2,3 +2,4 @@ int int_diff(char *p) { return (int)(p + 1) - (int)p; } int int_diff4(int *p) { return (int)(p + 1) - (int)p; } long pd_char(char *a, char *b) { return a - b; } long pd_int(int *a, int *b) { return a - b; } +int late(char *p, char *q) { return (char *)((unsigned)p + 24) == q; } diff --git a/scripts/tests/m0/run.sh b/scripts/tests/m0/run.sh index 477bdc0..d6653db 100755 --- a/scripts/tests/m0/run.sh +++ b/scripts/tests/m0/run.sh @@ -13,12 +13,14 @@ grep -A2 'define.*@int_diff(' "$OUT/pdiff.ll" | grep -q 'ret i32 8' grep -A2 'define.*@int_diff4' "$OUT/pdiff.ll" | grep -q 'ret i32 32' grep -A6 'define.*@pd_char' "$OUT/pdiff.ll" | grep -Eq 'sdiv|ashr|udiv' grep -A6 'define.*@pd_int' "$OUT/pdiff.ll" | grep -Eq 'sdiv|ashr|udiv' +grep -Eq 'add i32 %bit.base[0-9]*, 24' "$OUT/pdiff.ll" "$TMS_OPT" -passes=verify -disable-output "$OUT/pdiff.ll" "$ROOT/scripts/tms-clang" -O2 -I "$ROOT/spike" -o "$OUT/xclient.ll" "$ROOT/spike/xclient.c" test "$(grep -c getelementptr "$OUT/xclient.ll")" -eq 0 grep -Eq 'add i32 %bit.base[0-9]*, 1056' "$OUT/xclient.ll" grep -Eq 'mul i32 [^,]+, 640' "$OUT/xclient.ll" +grep -Eq 'add i32 %bit.addr[0-9]*, 320' "$OUT/xclient.ll" "$TMS_OPT" -passes=verify -disable-output "$OUT/xclient.ll" "$ROOT/scripts/tms-clang" -O0 -o "$OUT/pdiff.o0.ll" "$ROOT/scripts/tests/m0/ptrdiff.c" diff --git a/spike/REPORT-23.md b/spike/REPORT-23.md index 2334cae..bd220df 100644 --- a/spike/REPORT-23.md +++ b/spike/REPORT-23.md @@ -83,6 +83,8 @@ CLANG=$PWD/build/llvm-build/bin/clang \ OPT=$PWD/build/llvm-build/bin/opt \ LLVMCONFIG=$PWD/build/llvm-build/bin/llvm-config \ CXX=$PWD/build/llvm-build/bin/clang++ \ +TMS_CLANG=$PWD/build/llvm-build/bin/clang \ +TMS_OPT=$PWD/build/llvm-build/bin/opt \ TMS_BITADDR=$PWD/tools/tms-bitaddr/tms-bitaddr \ ./spike/run.sh ``` diff --git a/spike/run.sh b/spike/run.sh index 5c6a6fb..bfb3fcc 100755 --- a/spike/run.sh +++ b/spike/run.sh @@ -43,6 +43,9 @@ echo "-- i386 pointer difference is still in bit units:" grep -A6 'define.*@ptr_diff' /tmp/ptrdiff.bits.O2.ll echo "== TMS target pointer difference (23.1.5, patched clang)" +TMS_CLANG=${TMS_CLANG:-$CC} +TMS_OPT=${TMS_OPT:-$OPT} +export TMS_CLANG TMS_OPT "$ROOT/scripts/tms-clang" -O2 -o /tmp/tms-m0.ll "$ROOT/scripts/tests/m0/ptrdiff.c" grep -A2 'define.*@int_diff(' /tmp/tms-m0.ll grep -A2 'define.*@int_diff4' /tmp/tms-m0.ll