diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -98,11 +98,12 @@ SmallVector BundleGroups; }; -MCELFStreamer *createARMELFStreamer(MCContext &Context, +MCELFStreamer *createARMELFStreamer(const Triple &T, MCContext &Context, std::unique_ptr TAB, std::unique_ptr OW, std::unique_ptr Emitter, - bool RelaxAll, bool IsThumb, bool IsAndroid); + bool RelaxAll, bool IsThumb, + bool IsAndroid); } // end namespace llvm diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -435,10 +435,10 @@ ARMELFStreamer(MCContext &Context, std::unique_ptr TAB, std::unique_ptr OW, std::unique_ptr Emitter, bool IsThumb, - bool IsAndroid) + bool IsAndroid, const Triple &TargetTriple) : MCELFStreamer(Context, std::move(TAB), std::move(OW), std::move(Emitter)), - IsThumb(IsThumb), IsAndroid(IsAndroid) { + IsThumb(IsThumb), IsAndroid(IsAndroid), TargetTriple(TargetTriple) { EHReset(); } @@ -579,6 +579,8 @@ } } + unsigned computeELFHeaderFlags() const; + /// If a label is defined before the .type directive sets the label's type /// then the label can't be recorded as thumb function when the label is /// defined. We override emitSymbolAttribute() which is called as part of the @@ -701,6 +703,7 @@ bool IsThumb; bool IsAndroid; + Triple TargetTriple; int64_t MappingSymbolCounter = 0; DenseMap> @@ -1191,6 +1194,36 @@ MCELFStreamer::finishImpl(); } +unsigned ARMELFStreamer::computeELFHeaderFlags() const { + // FIXME: This should eventually end up somewhere else where more + // intelligent flag decisions can be made. For now we are just maintaining + // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default. + unsigned e_flags = ELF::EF_ARM_EABI_VER5; + + // See: ARMBaseTargetMachine::isTargetHardFloat(). + if ((TargetTriple.isOSBinFormatMachO() && TargetTriple.getSubArch() == Triple::ARMSubArch_v7em) || TargetTriple + .isOSWindows() /* || TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16; */) { + e_flags |= ELF::EF_ARM_ABI_FLOAT_HARD; + } else { + switch (TargetTriple.getEnvironment()) { + case Triple::GNUEABIHF: + case Triple::MuslEABIHF: + case Triple::EABIHF: + e_flags |= ELF::EF_ARM_ABI_FLOAT_HARD; + break; + + case Triple::GNUEABI: + case Triple::MuslEABI: + case Triple::EABI: + e_flags |= ELF::EF_ARM_ABI_FLOAT_SOFT; + break; + + default:; + } + } + return e_flags; +} + void ARMELFStreamer::reset() { MCTargetStreamer &TS = *getTargetStreamer(); ARMTargetStreamer &ATS = static_cast(TS); @@ -1199,10 +1232,11 @@ MCELFStreamer::reset(); LastMappingSymbols.clear(); LastEMSInfo.reset(); + // MCELFStreamer clear's the assembler's e_flags. However, for // arm we manually set the ABI version on streamer creation, so // do the same here - getAssembler().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5); + getAssembler().setELFHeaderEFlags(computeELFHeaderFlags()); } inline void ARMELFStreamer::SwitchToEHSection(StringRef Prefix, @@ -1521,7 +1555,8 @@ return new ARMTargetStreamer(S); } -MCELFStreamer *createARMELFStreamer(MCContext &Context, +MCELFStreamer *createARMELFStreamer(const Triple &TargetTriple, + MCContext &Context, std::unique_ptr TAB, std::unique_ptr OW, std::unique_ptr Emitter, @@ -1529,11 +1564,11 @@ bool IsAndroid) { ARMELFStreamer *S = new ARMELFStreamer(Context, std::move(TAB), std::move(OW), - std::move(Emitter), IsThumb, IsAndroid); + std::move(Emitter), IsThumb, IsAndroid, TargetTriple); // FIXME: This should eventually end up somewhere else where more // intelligent flag decisions can be made. For now we are just maintaining // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default. - S->getAssembler().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5); + S->getAssembler().setELFHeaderEFlags(S->computeELFHeaderFlags()); if (RelaxAll) S->getAssembler().setRelaxAll(true); diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -356,7 +356,7 @@ std::unique_ptr &&Emitter, bool RelaxAll) { return createARMELFStreamer( - Ctx, std::move(MAB), std::move(OW), std::move(Emitter), false, + T, Ctx, std::move(MAB), std::move(OW), std::move(Emitter), false, (T.getArch() == Triple::thumb || T.getArch() == Triple::thumbeb), T.isAndroid()); } diff --git a/llvm/test/MC/ARM/elf-eflags-eabi.s b/llvm/test/MC/ARM/elf-eflags-eabi.s --- a/llvm/test/MC/ARM/elf-eflags-eabi.s +++ b/llvm/test/MC/ARM/elf-eflags-eabi.s @@ -9,6 +9,10 @@ @ %bb.0: @ %entry b foo -@@@ make sure the EF_ARM_EABIMASK comes out OK +@@@ make sure the EF_ARM_EABIMASK and EF_ARM_ABI_FLOAT_SOFT come out OK @OBJ: ElfHeader { -@OBJ: Flags [ (0x5000000) +@OBJ: Flags [ (0x5000200) +@OBJ-NEXT: 0x200 +@OBJ-NEXT: 0x1000000 +@OBJ-NEXT: 0x4000000 +@OBJ-NEXT: ] diff --git a/llvm/test/MC/ARM/elf-eflags-eabi.s b/llvm/test/MC/ARM/elf-eflags-eabihf.s copy from llvm/test/MC/ARM/elf-eflags-eabi.s copy to llvm/test/MC/ARM/elf-eflags-eabihf.s --- a/llvm/test/MC/ARM/elf-eflags-eabi.s +++ b/llvm/test/MC/ARM/elf-eflags-eabihf.s @@ -1,4 +1,4 @@ -@ RUN: llvm-mc %s -triple=armv7-linux-gnueabi -filetype=obj -o - | \ +@ RUN: llvm-mc %s -triple=armv7-linux-gnueabihf -filetype=obj -o - | \ @ RUN: llvm-readobj -h - | FileCheck -check-prefix=OBJ %s .syntax unified .text @@ -9,6 +9,10 @@ @ %bb.0: @ %entry b foo -@@@ make sure the EF_ARM_EABIMASK comes out OK +@@@ make sure the EF_ARM_EABIMASK and EF_ARM_ABI_FLOAT_HARD come out OK @OBJ: ElfHeader { -@OBJ: Flags [ (0x5000000) +@OBJ: Flags [ (0x5000400) +@OBJ-NEXT: 0x400 +@OBJ-NEXT: 0x1000000 +@OBJ-NEXT: 0x4000000 +@OBJ-NEXT: ]