Index: lib/Target/ARM/ARMAsmPrinter.cpp |
=================================================================== |
--- lib/Target/ARM/ARMAsmPrinter.cpp (revision 116749) |
+++ lib/Target/ARM/ARMAsmPrinter.cpp (working copy) |
@@ -38,6 +38,7 @@ |
#include "llvm/MC/MCSectionMachO.h" |
#include "llvm/MC/MCStreamer.h" |
#include "llvm/MC/MCSymbol.h" |
+#include "llvm/MC/MCAssembler.h" |
#include "llvm/Target/Mangler.h" |
#include "llvm/Target/TargetData.h" |
#include "llvm/Target/TargetMachine.h" |
@@ -48,6 +49,7 @@ |
#include "llvm/ADT/StringExtras.h" |
#include "llvm/Support/CommandLine.h" |
#include "llvm/Support/Debug.h" |
+#include "llvm/Support/ELF.h" |
#include "llvm/Support/ErrorHandling.h" |
#include "llvm/Support/raw_ostream.h" |
#include <cctype> |
@@ -79,7 +81,9 @@ |
public: |
explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) |
- : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) { |
+ : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL), |
+ headFragment(NULL), currFileFragment(NULL), |
+ currSectionFragment(NULL), currSymbolFragment(NULL) { |
Subtarget = &TM.getSubtarget<ARMSubtarget>(); |
} |
@@ -108,14 +112,33 @@ |
void EmitEndOfAsmFile(Module &M); |
private: |
+ |
// Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() |
+ // Helper for ELF .s/.o only |
void emitAttributes(); |
void emitTextAttribute(ARMBuildAttrs::SpecialAttr attr, StringRef v); |
void emitAttribute(ARMBuildAttrs::AttrType attr, int v); |
- // Helper for ELF .o only |
void emitARMAttributeSection(); |
+ // Slots for keeping state for above member funcs. |
+ MCDataFragment *headFragment; |
+ |
+ // Fixme: do we ever need more than one of each? |
+ MCDataFragment *currFileFragment, |
+ *currSectionFragment, *currSymbolFragment; |
+ |
+ // Section-global offset counters |
+ int currOffset; |
+ int attrDataStartOffset; |
+ |
+ // Helper routine for the emit*() functions above |
+ MCDataFragment *addAttrSubsec(MCSectionData *AttrSecData, |
+ ARMBuildAttrs::AttrType attr, |
+ int SecOrSym=0); |
+ |
+ int fixupAttrSizes(); |
+ int fixupAttrSize(MCDataFragment *F, int secLenOffset, int lenAdjust); |
public: |
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); |
@@ -530,6 +553,14 @@ |
emitAttribute(ARMBuildAttrs::ABI_VFP_args, 1); |
} |
// FIXME: Should we signal R9 usage? |
+ |
+ // FIXME: This is just a freebie set by GNU/ARM as for ELF/.o only. |
+ // LLVM never emitted this explicitly for .s |
+ if (!OutStreamer.hasRawTextSupport()) { |
+ emitAttribute(ARMBuildAttrs::DIV_use, 1); |
+ } |
+ |
+ (void) fixupAttrSizes(); |
} |
void ARMAsmPrinter::emitARMAttributeSection() { |
@@ -549,16 +580,52 @@ |
(getObjFileLowering()); |
OutStreamer.SwitchSection(TLOFELF.getAttributesSection()); |
- // Fixme: Still more to do here. |
+ |
+ MCObjectStreamer *ELFStreamer = static_cast<MCObjectStreamer*>(&OutStreamer); |
+ MCAssembler *Asm = &ELFStreamer->getAssembler(); |
+ |
+ bool newSec = false; |
+ MCSectionData *AttrSecData = |
+ &(Asm->getOrCreateSectionData(*TLOFELF.getAttributesSection(), &newSec)); |
+ |
+ headFragment = new MCDataFragment(AttrSecData); |
+ SmallString<32> *FC = &headFragment->getContents(); |
+ |
+ (*FC) += ((char)ARMBuildAttrs::Format_Version); |
+ |
+ FC->append(sizeof(ELF::Elf32_Word), 0); |
+ |
+ FC->append(ARMBuildAttrs::Vendor_Name, |
+ ARMBuildAttrs::Vendor_Name_End); |
+ |
+ currFileFragment = |
+ addAttrSubsec(AttrSecData, ARMBuildAttrs::File); |
} |
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"); |
+ switch (attr) { |
+ // These all go into the File subsection |
+ case ARMBuildAttrs::VFP_arch: |
+ case ARMBuildAttrs::ABI_FP_denormal: |
+ case ARMBuildAttrs::ABI_FP_exceptions: |
+ case ARMBuildAttrs::ABI_FP_number_model: |
+ case ARMBuildAttrs::ABI_align8_needed: |
+ case ARMBuildAttrs::ABI_align8_preserved: |
+ case ARMBuildAttrs::ABI_HardFP_use: |
+ case ARMBuildAttrs::ABI_VFP_args: |
+ case ARMBuildAttrs::DIV_use: { |
+ assert(currFileFragment && "No File subsection found"); |
+ SmallString<32> *FC = &currFileFragment->getContents(); |
+ (*FC) += static_cast<char>(attr); |
+ (*FC) += static_cast<char>(0xFF & v); |
+ }; break; |
+ default: assert(0 && "Unsupported ARMBuildAttrs::AttrType"); break; |
+ } |
} |
} |
@@ -572,11 +639,75 @@ |
OutStreamer.EmitRawText("\t.cpu " + val); |
} |
} else { |
- // FIXME: ELF |
+ // .o |
+ if (val == "generic") { |
+ assert(currFileFragment && "No File subsection found"); |
+ SmallString<32> *FC = &currFileFragment->getContents(); |
+ (*FC) += static_cast<char>(ARMBuildAttrs::CPU_arch); |
+ (*FC) += static_cast<char>(ARMBuildAttrs::v4T); |
+ |
+ (*FC) += static_cast<char>(ARMBuildAttrs::ARM_ISA_use); |
+ (*FC) += static_cast<char>(1); |
+ |
+ (*FC) += static_cast<char>(ARMBuildAttrs::THUMB_ISA_use); |
+ (*FC) += static_cast<char>(1); |
+ } else { |
+ assert(0 && "unsupported .cpu attribute for ELF/.o"); |
+ } |
} |
} |
} |
+MCDataFragment *ARMAsmPrinter::addAttrSubsec(MCSectionData *AttrSecData, |
+ ARMBuildAttrs::AttrType attr, |
+ int SecOrSym) { |
+ MCDataFragment *rtn = new MCDataFragment(AttrSecData); |
+ SmallString<32> *FC = &rtn->getContents(); |
+ |
+ (*FC) += static_cast<char>(ARMBuildAttrs::File); |
+ FC->append(sizeof(ELF::Elf32_Word), 0); |
+ |
+ switch (attr) { |
+ case ARMBuildAttrs::File: break; |
+ case ARMBuildAttrs::Section: |
+ case ARMBuildAttrs::Symbol: { |
+ (*FC) += (0xFF & SecOrSym); |
+ (*FC) += (0xFF & (SecOrSym >> 8)); |
+ (*FC) += (0xFF & (SecOrSym >> 16)); |
+ (*FC) += (0xFF & (SecOrSym >> 24)); |
+ |
+ (*FC) += 0; |
+ } break; |
+ default: assert(0 && "Unknown .ARM.attributes subsection"); break; |
+ } |
+ |
+ return rtn; |
+} |
+ |
+int ARMAsmPrinter::fixupAttrSizes() { |
+ int SFileAttr = fixupAttrSize(currFileFragment, 1, 0); |
+ int SSecAttr = fixupAttrSize(currSectionFragment, 1, 0); |
+ int SSymAttr = fixupAttrSize(currSymbolFragment, 1, 0); |
+ int Shead = fixupAttrSize(headFragment, 1, |
+ (SFileAttr + SSecAttr + SSymAttr - 1)); |
+ return Shead; |
+} |
+ |
+int ARMAsmPrinter::fixupAttrSize(MCDataFragment *F, |
+ int secLenOffset, int lenAdjust) { |
+ if (F) { |
+ SmallString<32> *FC = &F->getContents(); |
+ |
+ int S = (int)(FC->size() + lenAdjust); |
+ (*FC)[secLenOffset+0] = 0xFF & S; |
+ (*FC)[secLenOffset+1] = 0xFF & (S>>8); |
+ (*FC)[secLenOffset+2] = 0xFF & (S>>16); |
+ (*FC)[secLenOffset+3] = 0xFF & (S>>24); |
+ return S + lenAdjust; |
+ } |
+ return 0; |
+} |
+ |
//===----------------------------------------------------------------------===// |
static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, |