[RFC] Baremetal/None OS Type

Hi,

What are your opinions about a explicitly None or BareMetal OSType? (llvm::Triple::OSType)

Background
I wanted to compile some code with clang on Windows for amd64-none-elf target, which unexpectedly failed do to this issue.

Possible solutions

  • Introduce None as an explicit OSType: this results in some failed tests without special casing some weird combinations. (e.g.: this would fail, as it arm-none-eabi would mean arm-unknown-none-eabi instead of the current arm-none-unknown-eabi)
  • Introduce BareMetal or FreeStanding as an OSType, as in amd64-baremetal-elf or amd64-freestanding-elf. This has the advantage that it wouldn’t break any existing use cases with the disadvantage that this is not existing practice.
1 Like

I’m in favor of adding baremetal as a separate target, it makes it explicit what you are doing and doesn’t break anything

What’s the compiler and linker behaviors of baremetal/freestanding? Is there a specification? Do different architectures have different baremetal behaviors?

If you want to Linux like behavior without using gcc for the link action, you may use -nostdlib (e.g. clang --target=x86_64-pc-linux-gnu -fuse-ld=lld -nostdlib).

I haven’t done extensive testing but I have tried the workaround of using linux-elf and nostdlib. For whatever reason this results in executables that are notably larger than if it were compiled and linked as bare metal (using @Templar-von-Midgard 's branch), although it does work.

One example of a bare metal elf would be a multiboot compliant kernel, for which there is a specification, other boot protocols such as stivale can also use bare metal elf files

Comparing llvm-readelf -S output will be useful to know why the *-linux-gnu one is larger.

It may just have some different defaults, and shall not be difficult to make smaller.

One example of a bare metal elf would be a multiboot compliant kernel, for which there is a specification, other boot protocols such as stivale can also use bare metal elf files

I guess multiboot specification can be considered too specific to be defined as the “baremetal OS type”. Without a clear one, I’d avoid defining a baremetal OS type.

1 Like

I took a look at it, so it seems like the following two command lines would be similar:
clang++ -fuse-ld=lld --target=amd64-pc-baremetal-elf -nostdlib main.cpp
clang++ -fuse-ld=lld --target=amd64-pc-linux-elf -static -nostdlib -Xclang -funwind-tables=0 main.cpp
So there are some subtle differences here.
Also, conceptually, it is somewhat counterintuitive and just weird compiling a custom (ie. not linux) kernel with amd64-linux-elf.
Without -nostdlib the the crt objects are also added to the linker invocation (crt1.o, …).

For reference here are some invocations, with clang compiled from https://github.com/Templar-von-Midgard/llvm-project/tree/baremetal-ostype:

  • clang++ -fuse-ld=lld --target=amd64-pc-baremetal-elf -nostdlib main.cpp -###
clang version 15.0.0 (https://github.com/llvm/llvm-project.git 15c3bba04ff804b947dc687a6d274de7f8336036)
Target: amd64-pc-baremetal-elf
Thread model: posix
InstalledDir: ...\llvm-project\_build\RelWithDebInfo\bin
 "...\\llvm-project\\_build\\RelWithDebInfo\\bin\\clang++.exe" "-cc1" "-triple" "amd64-pc-baremetal-elf" "-emit-obj" "-mrelax-all" "--mrelax-relocations" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "main.cpp" "-mrelocation-model" "static" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-fno-verbose-asm" "-mconstructor-aliases" "-nostdsysteminc" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-mllvm" "-treat-scalable-fixed-error-as-warning" "-debugger-tuning=gdb" "-fcoverage-compilation-dir=...\\llvm-project" "-resource-dir" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0" "-internal-isystem" "...\\llvm-project\\_build\\RelWithDebInfo\\bin\\../lib/clang-runtimes\\amd64-pc-baremetal-elf\\include\\c++\\v1" "-internal-isystem" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0\\include" "-internal-isystem" "...\\llvm-project\\_build\\RelWithDebInfo\\bin\\../lib/clang-runtimes\\amd64-pc-baremetal-elf\\include" "-fdeprecated-macro" "-fdebug-compilation-dir=...\\llvm-project" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fcxx-exceptions" "-fexceptions" "-faddrsig" "-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o" "...\\Local\\Temp\\main-916c86.o" "-x" "c++" "main.cpp"
 "...\\apps\\llvm\\current\\bin\\ld.lld.exe" "...\\Local\\Temp\\main-916c86.o" "-Bstatic" "-L...\\llvm-project\\_build\\RelWithDebInfo\\bin\\../lib/clang-runtimes\\amd64-pc-baremetal-elf\\lib" "-L...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0\\lib\\baremetal" "-o" "a.out"
  • clang++ -fuse-ld=lld --target=amd64-pc-linux-elf -static -Xclang -funwind-tables=0 -nostdlib main.cpp -###
clang version 15.0.0 (https://github.com/llvm/llvm-project.git 15c3bba04ff804b947dc687a6d274de7f8336036)
Target: amd64-pc-linux-elf
Thread model: posix
InstalledDir: ...\llvm-project\_build\RelWithDebInfo\bin
 "...\\llvm-project\\_build\\RelWithDebInfo\\bin\\clang++.exe" "-cc1" "-triple" "amd64-pc-linux-elf" "-emit-obj" "-mrelax-all" "--mrelax-relocations" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "main.cpp" "-static-define" "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-funwind-tables=2" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-mllvm" "-treat-scalable-fixed-error-as-warning" "-debugger-tuning=gdb" "-fcoverage-compilation-dir=...\\llvm-project" "-resource-dir" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0" "-internal-isystem" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0\\include" "-internal-isystem" "/usr/local/include" "-internal-externc-isystem" "/include" "-internal-externc-isystem" "/usr/include" "-fdeprecated-macro" "-fdebug-compilation-dir=...\\llvm-project" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fcxx-exceptions" "-fexceptions" "-funwind-tables=0" "-faddrsig" "-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o" "...\\Local\\Temp\\main-fc2375.o" "-x" "c++" "main.cpp"
 "...\\apps\\llvm\\current\\bin\\ld.lld.exe" "--eh-frame-hdr" "-m" "elf_x86_64" "-static" "-o" "a.out" "...\\Local\\Temp\\main-fc2375.o"
  • clang++ -fuse-ld=lld --target=amd64-pc-baremetal-elf main.cpp -###
clang version 15.0.0 (https://github.com/llvm/llvm-project.git 15c3bba04ff804b947dc687a6d274de7f8336036)
Target: amd64-pc-baremetal-elf
Thread model: posix
InstalledDir: ...\llvm-project\_build\RelWithDebInfo\bin
 "...\\llvm-project\\_build\\RelWithDebInfo\\bin\\clang++.exe" "-cc1" "-triple" "amd64-pc-baremetal-elf" "-emit-obj" "-mrelax-all" "--mrelax-relocations" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "main.cpp" "-mrelocation-model" "static" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-fno-verbose-asm" "-mconstructor-aliases" "-nostdsysteminc" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-mllvm" "-treat-scalable-fixed-error-as-warning" "-debugger-tuning=gdb" "-fcoverage-compilation-dir=...\\llvm-project" "-resource-dir" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0" "-internal-isystem" "...\\llvm-project\\_build\\RelWithDebInfo\\bin\\../lib/clang-runtimes\\amd64-pc-baremetal-elf\\include\\c++\\v1" "-internal-isystem" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0\\include" "-internal-isystem" "...\\llvm-project\\_build\\RelWithDebInfo\\bin\\../lib/clang-runtimes\\amd64-pc-baremetal-elf\\include" "-fdeprecated-macro" "-fdebug-compilation-dir=...\\llvm-project" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fcxx-exceptions" "-fexceptions" "-faddrsig" "-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o" "...\\Local\\Temp\\main-1fed8d.o" "-x" "c++" "main.cpp"
 "...\\apps\\llvm\\current\\bin\\ld.lld.exe" "...\\Local\\Temp\\main-1fed8d.o" "-Bstatic" "-L...\\llvm-project\\_build\\RelWithDebInfo\\bin\\../lib/clang-runtimes\\amd64-pc-baremetal-elf\\lib" "-L...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0\\lib\\baremetal" "-lc++" "-lc++abi" "-lunwind" "-lc" "-lm" "-lclang_rt.builtins-amd64" "-o" "a.out"
  • clang++ -fuse-ld=lld --target=amd64-pc-linux-elf -static -rtlib=compiler-rt -Xclang -funwind-tables=0 main.cpp -###
clang version 15.0.0 (https://github.com/llvm/llvm-project.git 15c3bba04ff804b947dc687a6d274de7f8336036)
Target: amd64-pc-linux-elf
Thread model: posix
InstalledDir: ...\llvm-project\_build\RelWithDebInfo\bin
 "...\\llvm-project\\_build\\RelWithDebInfo\\bin\\clang++.exe" "-cc1" "-triple" "amd64-pc-linux-elf" "-emit-obj" "-mrelax-all" "--mrelax-relocations" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "main.cpp" "-static-define" "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-funwind-tables=2" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-mllvm" "-treat-scalable-fixed-error-as-warning" "-debugger-tuning=gdb" "-fcoverage-compilation-dir=...\\llvm-project" "-resource-dir" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0" "-internal-isystem" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0\\include" "-internal-isystem" "/usr/local/include" "-internal-externc-isystem" "/include" "-internal-externc-isystem" "/usr/include" "-fdeprecated-macro" "-fdebug-compilation-dir=...\\llvm-project" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fcxx-exceptions" "-fexceptions" "-funwind-tables=0" "-faddrsig" "-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o" "...\\Local\\Temp\\main-fdaab8.o" "-x" "c++" "main.cpp"
 "...\\apps\\llvm\\current\\bin\\ld.lld.exe" "--eh-frame-hdr" "-m" "elf_x86_64" "-static" "-o" "a.out" "crt1.o" "crti.o" "crtbeginT.o" "...\\Local\\Temp\\main-fdaab8.o" "-lstdc++" "-lm" "--start-group" "...\\llvm-project\\_build\\RelWithDebInfo\\lib\\clang\\15.0.0\\lib\\linux\\libclang_rt.builtins-x86_64.a" "-lc" "--end-group" "crtend.o" "crtn.o"