| 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,
 | 
| 
 |