simpal01 created this revision. Herald added subscribers: abidh, kristof.beyls. Herald added a project: All. simpal01 requested review of this revision. Herald added subscribers: cfe-commits, MaskRay. Herald added a project: clang.
When linking a big-endian image for Arm, clang has to select between BE8 and BE32 formats. The default is dependent on the selected target architecture. For ARMv6 and later architectures the default is BE8, for older architectures the default is BE32. For BE8 and BE32, compiler outputs a big endian ELF relocatable object file with the instructions and data both big endian. The difference is that at link time, for BE8 a linker must endian reverse the instructions to little endian. For BE8, the clang has to pass --be8 to the linker for Arm. At the moment clang is not passing the --be8 flag to linker for the baremetal target architectures above ArmV6 for Arm. This patch passes through --be8 and -BE or EL to the linker, taking into account the target and the -mbig-endian and -mlittle-endian flag. Also there are few more changes in the baremetal driver so that the code can cope with AArch64 being big-endian as well. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D154786 Files: clang/lib/Driver/ToolChains/Arch/ARM.cpp clang/lib/Driver/ToolChains/Arch/ARM.h clang/lib/Driver/ToolChains/BareMetal.cpp clang/lib/Driver/ToolChains/Gnu.cpp clang/test/Driver/baremetal.cpp
Index: clang/test/Driver/baremetal.cpp =================================================================== --- clang/test/Driver/baremetal.cpp +++ clang/test/Driver/baremetal.cpp @@ -15,7 +15,7 @@ // CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECk-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include" // CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp" -// CHECK-V6M-C-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-C-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for" // CHECK-V6M-C-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib" // CHECK-V6M-C-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal" @@ -34,7 +34,7 @@ // CHECK-ARMV7M-PER-TARGET: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-ARMV7M-PER-TARGET: "-isysroot" "[[SYSROOT:[^"]*]]" // CHECK-ARMV7M-PER-TARGET: "-x" "c++" "{{.*}}baremetal.cpp" -// CHECK-ARMV7M-PER-TARGET: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-ARMV7M-PER-TARGET: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-ARMV7M-PER-TARGET: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib" // CHECK-ARMV7M-PER-TARGET: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}armv7m-vendor-none-eabi // CHECK-ARMV7M-PER-TARGET: "-lc" "-lm" "-lclang_rt.builtins" @@ -42,7 +42,7 @@ // RUN: %clangxx %s -### --target=armv6m-none-eabi 2>&1 \ // RUN: --sysroot=%S/Inputs/baremetal_arm | FileCheck --check-prefix=CHECK-V6M-DEFAULTCXX %s // CHECK-V6M-DEFAULTCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" -// CHECK-V6M-DEFAULTCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-DEFAULTCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" // CHECK-V6M-DEFAULTCXX-SAME: "-L[[RESOURCE_DIR]]{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind" @@ -53,7 +53,7 @@ // CHECK-V6M-LIBCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-V6M-LIBCXX-NOT: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}{{[^v].*}}" // CHECK-V6M-LIBCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" -// CHECK-V6M-LIBCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-LIBCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" // CHECK-V6M-LIBCXX-SAME: "-L[[RESOURCE_DIR]]{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-V6M-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind" @@ -66,7 +66,7 @@ // CHECK-V6M-LIBSTDCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-V6M-LIBSTDCXX-NOT: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECK-V6M-LIBSTDCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}6.0.0" -// CHECK-V6M-LIBSTDCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-LIBSTDCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" // CHECK-V6M-LIBSTDCXX-SAME: "-L[[RESOURCE_DIR]]{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind" @@ -77,7 +77,7 @@ // RUN: -nodefaultlibs \ // RUN: | FileCheck --check-prefix=CHECK-V6M-NDL %s // CHECK-V6M-NDL: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" -// CHECK-V6M-NDL: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-NDL: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-NDL-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" // CHECK-V6M-NDL-SAME: "-L[[RESOURCE_DIR]]{{[/\\]+}}lib{{[/\\]+}}baremetal" @@ -117,6 +117,75 @@ // RUN: | FileCheck %s --check-prefix=CHECK-SYSROOT-INC // CHECK-SYSROOT-INC-NOT: "-internal-isystem" "include" +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armebv7-none-eabi \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s +// CHECK-ARMV7EB: "{{.*}}ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "--be8" "-EB" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7-none-eabi \ +// RUN: -mbig-endian \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armebv7-none-eabi \ +// RUN: -mbig-endian \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7-none-eabi \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s +// CHECK-ARMV7EL: "{{.*}}ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" +// CHECK-ARMV7EL-NOT: "--be8" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armebv7-none-eabi \ +// RUN: -mlittle-endian \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7-none-eabi \ +// RUN: -mlittle-endian \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=aarch64_be-none-elf \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s +// CHECK-AARCH64BE: "{{.*}}ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EB" +// CHECK-AARCH64BE-NOT: "--be8" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=aarch64-none-elf \ +// RUN: -mbig-endian \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=aarch64_be-none-elf \ +// RUN: -mbig-endian \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=aarch64-none-elf \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s +// CHECK-AARCH64LE: "{{.*}}ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" +// CHECK-AARCH64LE-NOT: "--be8" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=aarch64_be-none-elf \ +// RUN: -mlittle-endian \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s + // RUN: %clang -no-canonical-prefixes %s -### --target=aarch64-none-elf 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64-NO-HOST-INC %s // Verify that the bare metal driver does not include any host system paths: Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -220,30 +220,6 @@ // The types are (hopefully) good enough. } -// On Arm the endianness of the output file is determined by the target and -// can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and -// '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a -// normalized triple so we must handle the flag here. -static bool isArmBigEndian(const llvm::Triple &Triple, - const ArgList &Args) { - bool IsBigEndian = false; - switch (Triple.getArch()) { - case llvm::Triple::armeb: - case llvm::Triple::thumbeb: - IsBigEndian = true; - [[fallthrough]]; - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian, - options::OPT_mbig_endian)) - IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian); - break; - default: - break; - } - return IsBigEndian; -} - static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) { switch (T.getArch()) { case llvm::Triple::x86: @@ -258,7 +234,8 @@ case llvm::Triple::thumb: case llvm::Triple::armeb: case llvm::Triple::thumbeb: - return isArmBigEndian(T, Args) ? "armelfb_linux_eabi" : "armelf_linux_eabi"; + return tools::arm::isArmBigEndian(T, Args) ? "armelfb_linux_eabi" + : "armelf_linux_eabi"; case llvm::Triple::m68k: return "m68kelf"; case llvm::Triple::ppc: @@ -448,7 +425,7 @@ CmdArgs.push_back("-s"); if (Triple.isARM() || Triple.isThumb() || Triple.isAArch64()) { - bool IsBigEndian = isArmBigEndian(Triple, Args); + bool IsBigEndian = arm::isArmBigEndian(Triple, Args); if (IsBigEndian) arm::appendBE8LinkFlag(Args, CmdArgs, Triple); IsBigEndian = IsBigEndian || Arch == llvm::Triple::aarch64_be; @@ -820,7 +797,7 @@ case llvm::Triple::thumb: case llvm::Triple::thumbeb: { const llvm::Triple &Triple2 = getToolChain().getTriple(); - CmdArgs.push_back(isArmBigEndian(Triple2, Args) ? "-EB" : "-EL"); + CmdArgs.push_back(arm::isArmBigEndian(Triple2, Args) ? "-EB" : "-EL"); switch (Triple2.getSubArch()) { case llvm::Triple::ARMSubArch_v7: CmdArgs.push_back("-mfpu=neon"); Index: clang/lib/Driver/ToolChains/BareMetal.cpp =================================================================== --- clang/lib/Driver/ToolChains/BareMetal.cpp +++ clang/lib/Driver/ToolChains/BareMetal.cpp @@ -12,6 +12,7 @@ #include "Gnu.h" #include "clang/Driver/InputInfo.h" +#include "Arch/ARM.h" #include "Arch/RISCV.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -115,10 +116,12 @@ } } -/// Is the triple {arm,thumb}-none-none-{eabi,eabihf} ? +/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ? static bool isARMBareMetal(const llvm::Triple &Triple) { if (Triple.getArch() != llvm::Triple::arm && - Triple.getArch() != llvm::Triple::thumb) + Triple.getArch() != llvm::Triple::thumb && + Triple.getArch() != llvm::Triple::armeb && + Triple.getArch() != llvm::Triple::thumbeb) return false; if (Triple.getVendor() != llvm::Triple::UnknownVendor) @@ -134,9 +137,10 @@ return true; } -/// Is the triple aarch64-none-elf? +/// Is the triple {aarch64.aarch64_be}-none-elf? static bool isAArch64BareMetal(const llvm::Triple &Triple) { - if (Triple.getArch() != llvm::Triple::aarch64) + if (Triple.getArch() != llvm::Triple::aarch64 && + Triple.getArch() != llvm::Triple::aarch64_be) return false; if (Triple.getVendor() != llvm::Triple::UnknownVendor) @@ -427,10 +431,21 @@ auto &TC = static_cast<const toolchains::BareMetal &>(getToolChain()); + const llvm::Triple::ArchType Arch = TC.getArch(); + const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); + AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); CmdArgs.push_back("-Bstatic"); + if (Triple.isARM() || Triple.isThumb() || Triple.isAArch64()) { + bool IsBigEndian = arm::isArmBigEndian(Triple, Args); + if (IsBigEndian) + arm::appendBE8LinkFlag(Args, CmdArgs, Triple); + IsBigEndian = IsBigEndian || Arch == llvm::Triple::aarch64_be; + CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL"); + } + Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); Index: clang/lib/Driver/ToolChains/Arch/ARM.h =================================================================== --- clang/lib/Driver/ToolChains/Arch/ARM.h +++ clang/lib/Driver/ToolChains/Arch/ARM.h @@ -14,6 +14,7 @@ #include "llvm/Option/Option.h" #include "llvm/TargetParser/ARMTargetParser.h" #include "llvm/TargetParser/Triple.h" +//#include "llvm/Option/ArgList.h" #include <string> #include <vector> @@ -73,6 +74,7 @@ int getARMSubArchVersionNumber(const llvm::Triple &Triple); bool isARMMProfile(const llvm::Triple &Triple); bool isARMAProfile(const llvm::Triple &Triple); +bool isArmBigEndian(const llvm::Triple &Triple, const llvm::opt::ArgList &Args); } // end namespace arm } // end namespace tools Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -32,6 +32,29 @@ return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M; } +// On Arm the endianness of the output file is determined by the target and +// can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and +// '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a +// normalized triple so we must handle the flag here. +bool arm::isArmBigEndian(const llvm::Triple &Triple, const ArgList &Args) { + bool IsBigEndian = false; + switch (Triple.getArch()) { + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + IsBigEndian = true; + [[fallthrough]]; + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian, + options::OPT_mbig_endian)) + IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian); + break; + default: + break; + } + return IsBigEndian; +} + // True if A-profile. bool arm::isARMAProfile(const llvm::Triple &Triple) { llvm::StringRef Arch = Triple.getArchName();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits