[llvm-commits] [llvm] r117275 - in /llvm/trunk: include/llvm/Support/ELF.h lib/MC/ELFObjectWriter.cpp lib/Target/ARM/ARMAsmBackend.cpp lib/Target/ARM/ARMAsmPrinter.cpp lib/Target/ARM/ARMBuildAttrs.h test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll

Rafael Espindola rafael.espindola at gmail.com
Mon Oct 25 10:50:35 PDT 2010


Author: rafael
Date: Mon Oct 25 12:50:35 2010
New Revision: 117275

URL: http://llvm.org/viewvc/llvm-project?rev=117275&view=rev
Log:
Add support for emitting ARM file attributes.

Added:
    llvm/trunk/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll
Modified:
    llvm/trunk/include/llvm/Support/ELF.h
    llvm/trunk/lib/MC/ELFObjectWriter.cpp
    llvm/trunk/lib/Target/ARM/ARMAsmBackend.cpp
    llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
    llvm/trunk/lib/Target/ARM/ARMBuildAttrs.h

Modified: llvm/trunk/include/llvm/Support/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ELF.h?rev=117275&r1=117274&r2=117275&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ELF.h (original)
+++ llvm/trunk/include/llvm/Support/ELF.h Mon Oct 25 12:50:35 2010
@@ -299,6 +299,16 @@
   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.

Modified: llvm/trunk/lib/MC/ELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/ELFObjectWriter.cpp?rev=117275&r1=117274&r2=117275&view=diff
==============================================================================
--- llvm/trunk/lib/MC/ELFObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/ELFObjectWriter.cpp Mon Oct 25 12:50:35 2010
@@ -1200,12 +1200,10 @@
     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;

Modified: llvm/trunk/lib/Target/ARM/ARMAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmBackend.cpp?rev=117275&r1=117274&r2=117275&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMAsmBackend.cpp Mon Oct 25 12:50:35 2010
@@ -55,12 +55,11 @@
 }
 
 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
 

Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp?rev=117275&r1=117274&r2=117275&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Mon Oct 25 12:50:35 2010
@@ -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 {
+
+  // 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 @@
   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 @@
 
   emitARMAttributeSection();
 
+  AttributeEmitter *AttrEmitter;
+  if (OutStreamer.hasRawTextSupport())
+    AttrEmitter = new AsmAttributeEmitter(OutStreamer);
+  else {
+    MCObjectStreamer &O = static_cast<MCObjectStreamer&>(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 @@
     (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);
 }
 
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/Target/ARM/ARMBuildAttrs.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBuildAttrs.h?rev=117275&r1=117274&r2=117275&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBuildAttrs.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBuildAttrs.h Mon Oct 25 12:50:35 2010
@@ -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 @@
     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__

Added: llvm/trunk/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll?rev=117275&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll Mon Oct 25 12:50:35 2010
@@ -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
+}





More information about the llvm-commits mailing list