From: Rafael Espindola Date: Mon, 25 Oct 2010 17:50:35 +0000 (+0000) Subject: Add support for emitting ARM file attributes. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=cecbc3d28277ff4916326311cbf87335ed05d106;p=oota-llvm.git Add support for emitting ARM file attributes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117275 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index df6f8b15065..ce7949db638 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -299,6 +299,16 @@ enum { SHT_LOOS = 0x60000000, // Lowest operating system-specific type. SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type. + // Fixme: All this is duplicated in MCSectionELF. Why?? + // Exception Index table + SHT_ARM_EXIDX = 0x70000001U, + // BPABI DLL dynamic linking pre-emption map + SHT_ARM_PREEMPTMAP = 0x70000002U, + // Object file compatibility attributes + SHT_ARM_ATTRIBUTES = 0x70000003U, + SHT_ARM_DEBUGOVERLAY = 0x70000004U, + SHT_ARM_OVERLAYSECTION = 0x70000005U, + SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index db33af67d6f..4ccc281c49f 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -1200,12 +1200,10 @@ void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm, case ELF::SHT_STRTAB: case ELF::SHT_NOBITS: case ELF::SHT_NULL: + case ELF::SHT_ARM_ATTRIBUTES: // Nothing to do. break; - case ELF::SHT_HASH: - case ELF::SHT_GROUP: - case ELF::SHT_SYMTAB_SHNDX: default: assert(0 && "FIXME: sh_type value not supported!"); break; diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index 72f6e2b4ce7..4be02424752 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -55,12 +55,11 @@ void ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { } bool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { - assert(0 && "ARMAsmBackend::WriteNopData() unimplemented"); if ((Count % 4) != 0) { // Fixme: % 2 for Thumb? return false; } - return false; + return true; } } // end anonymous namespace diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index dab549110dd..7790484c58d 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -32,10 +32,12 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" @@ -63,6 +65,91 @@ namespace llvm { } namespace { + + // Per section and per symbol attributes are not supported. + // To implement them we would need the ability to delay this emission + // until the assembly file is fully parsed/generated as only then do we + // know the symbol and section numbers. + class AttributeEmitter { + public: + virtual void MaybeSwitchVendor(StringRef Vendor) = 0; + virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0; + virtual void Finish() = 0; + }; + + class AsmAttributeEmitter : public AttributeEmitter { + MCStreamer &Streamer; + + public: + AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {} + void MaybeSwitchVendor(StringRef Vendor) { } + + void EmitAttribute(unsigned Attribute, unsigned Value) { + Streamer.EmitRawText("\t.eabi_attribute " + + Twine(Attribute) + ", " + Twine(Value)); + } + + void Finish() { } + }; + + class ObjectAttributeEmitter : public AttributeEmitter { + MCObjectStreamer &Streamer; + size_t SectionStart; + size_t TagStart; + StringRef CurrentVendor; + SmallString<64> Contents; + + public: + ObjectAttributeEmitter(MCObjectStreamer &Streamer_) : + Streamer(Streamer_), CurrentVendor("") { } + + void MaybeSwitchVendor(StringRef Vendor) { + assert(!Vendor.empty() && "Vendor cannot be empty."); + + if (CurrentVendor.empty()) + CurrentVendor = Vendor; + else if (CurrentVendor == Vendor) + return; + else + Finish(); + + CurrentVendor = Vendor; + + SectionStart = Contents.size(); + + // Length of the data for this vendor. + Contents.append(4, (char)0); + + Contents.append(Vendor.begin(), Vendor.end()); + Contents += 0; + + Contents += ARMBuildAttrs::File; + + TagStart = Contents.size(); + + // Length of the data for this tag. + Contents.append(4, (char)0); + } + + void EmitAttribute(unsigned Attribute, unsigned Value) { + // FIXME: should be ULEB + Contents += Attribute; + Contents += Value; + } + + void Finish() { + size_t EndPos = Contents.size(); + + // FIXME: endian. + *((uint32_t*)&Contents[SectionStart]) = EndPos - SectionStart; + + // +1 since it includes the tag that came before it. + *((uint32_t*)&Contents[TagStart]) = EndPos - TagStart + 1; + + Streamer.EmitBytes(Contents, 0); + } + }; + class ARMAsmPrinter : public AsmPrinter { /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can @@ -110,8 +197,6 @@ namespace { private: // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() void emitAttributes(); - void emitTextAttribute(ARMBuildAttrs::SpecialAttr attr, StringRef v); - void emitAttribute(ARMBuildAttrs::AttrType attr, int v); // Helper for ELF .o only void emitARMAttributeSection(); @@ -502,34 +587,58 @@ void ARMAsmPrinter::emitAttributes() { emitARMAttributeSection(); + AttributeEmitter *AttrEmitter; + if (OutStreamer.hasRawTextSupport()) + AttrEmitter = new AsmAttributeEmitter(OutStreamer); + else { + MCObjectStreamer &O = static_cast(OutStreamer); + AttrEmitter = new ObjectAttributeEmitter(O); + } + + AttrEmitter->MaybeSwitchVendor("aeabi"); + std::string CPUString = Subtarget->getCPUString(); - emitTextAttribute(ARMBuildAttrs::SEL_CPU, CPUString); + if (OutStreamer.hasRawTextSupport()) { + if (CPUString != "generic") + OutStreamer.EmitRawText(StringRef("\t.cpu ") + CPUString); + } else { + assert(CPUString == "generic" && "Unsupported .cpu attribute for ELF/.o"); + // FIXME: Why these defaults? + AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v4T); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, 1); + AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 1); + } // FIXME: Emit FPU type if (Subtarget->hasVFP2()) - emitAttribute(ARMBuildAttrs::VFP_arch, 2); + AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 2); // Signal various FP modes. if (!UnsafeFPMath) { - emitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1); - emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1); } if (NoInfsFPMath && NoNaNsFPMath) - emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1); else - emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3); // 8-bytes alignment stuff. - emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); - emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); // Hard float. Use both S and D registers and conform to AAPCS-VFP. if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { - emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3); - emitAttribute(ARMBuildAttrs::ABI_VFP_args, 1); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1); } // FIXME: Should we signal R9 usage? + + AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1); + + AttrEmitter->Finish(); + delete AttrEmitter; } void ARMAsmPrinter::emitARMAttributeSection() { @@ -549,32 +658,9 @@ void ARMAsmPrinter::emitARMAttributeSection() { (getObjFileLowering()); OutStreamer.SwitchSection(TLOFELF.getAttributesSection()); - // Fixme: Still more to do here. -} -void ARMAsmPrinter::emitAttribute(ARMBuildAttrs::AttrType attr, int v) { - if (OutStreamer.hasRawTextSupport()) { - OutStreamer.EmitRawText("\t.eabi_attribute " + - Twine(attr) + ", " + Twine(v)); - - } else { - assert(0 && "ELF .ARM.attributes unimplemented"); - } -} - -void ARMAsmPrinter::emitTextAttribute(ARMBuildAttrs::SpecialAttr attr, - StringRef val) { - switch (attr) { - default: assert(0 && "Unimplemented ARMBuildAttrs::SpecialAttr"); break; - case ARMBuildAttrs::SEL_CPU: - if (OutStreamer.hasRawTextSupport()) { - if (val != "generic") { - OutStreamer.EmitRawText("\t.cpu " + val); - } - } else { - // FIXME: ELF - } - } + // Format version + OutStreamer.EmitIntValue(0x41, 1); } //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMBuildAttrs.h b/lib/Target/ARM/ARMBuildAttrs.h index 8c54298ceb4..c0444982d47 100644 --- a/lib/Target/ARM/ARMBuildAttrs.h +++ b/lib/Target/ARM/ARMBuildAttrs.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file contains enumerations and support routines for ARM build attributes -// as defined in ARM ABI addenda document (ABI release 2.07). +// as defined in ARM ABI addenda document (ABI release 2.08). // //===----------------------------------------------------------------------===// @@ -59,18 +59,39 @@ namespace ARMBuildAttrs { CPU_unaligned_access = 34, VFP_HP_extension = 36, ABI_FP_16bit_format = 38, + MPextension_use = 42, // was 70, 2.08 ABI + DIV_use = 44, nodefaults = 64, also_compatible_with = 65, T2EE_use = 66, conformance = 67, Virtualization_use = 68, - MPextension_use = 70 + MPextension_use_old = 70 }; // Magic numbers for .ARM.attributes enum AttrMagic { Format_Version = 0x41 }; + + // Legal Values for CPU_arch, (=6), uleb128 + enum CPUArch { + Pre_v4 = 0, + v4 = 1, // e.g. SA110 + v4T = 2, // e.g. ARM7TDMI + v5T = 3, // e.g. ARM9TDMI + v5TE = 4, // e.g. ARM946E_S + v5TEJ = 5, // e.g. ARM926EJ_S + v6 = 6, // e.g. ARM1136J_S + v6KZ = 7, // e.g. ARM1176JZ_S + v6T2 = 8, // e.g. ARM1156T2F_S + v6K = 9, // e.g. ARM1136J_S + v7 = 10, // e.g. Cortex A8, Cortex M3 + v6_M = 11, // e.g. Cortex M1 + v6S_M = 12, // v6_M with the System extensions + v7E_M = 13 // v7_M with DSP extensions + }; + } #endif // __TARGET_ARMBUILDATTRS_H__ diff --git a/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll b/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll new file mode 100644 index 00000000000..d854238c04c --- /dev/null +++ b/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll @@ -0,0 +1,19 @@ +; RUN: llc %s -mtriple=arm-linux-gnueabi -filetype=obj -o - | \ +; RUN: elf-dump --dump-section-data | FileCheck %s +; This tests that the extpected ARM attributes are emitted. +; +; CHECK: .ARM.attributes +; CHECK-NEXT: 0x70000003 +; CHECK-NEXT: 0x00000000 +; CHECK-NEXT: 0x00000000 +; CHECK-NEXT: 0x0000003c +; CHECK-NEXT: 0x00000022 +; CHECK-NEXT: 0x00000000 +; CHECK-NEXT: 0x00000000 +; CHECK-NEXT: 0x00000001 +; CHECK-NEXT: 0x00000000 +; CHECK-NEXT: '41210000 00616561 62690001 17000000 06020801 09011401 15011703 18011901 2c01' + +define i32 @f(i64 %z) { + ret i32 0 +}