diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-03-16 16:51:38 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-03-16 16:51:38 +0000 |
commit | 0f448b841684305c051796982f300c9bff959307 (patch) | |
tree | 458dd25677a43aef6390ecadb4423817f00e08b0 /lib/MC | |
parent | 9e2446b38c94db61b2416c28fee415c03663c11c (diff) | |
download | FreeBSD-src-0f448b841684305c051796982f300c9bff959307.zip FreeBSD-src-0f448b841684305c051796982f300c9bff959307.tar.gz |
Update LLVM to r98631.
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/MCAsmInfo.cpp | 1 | ||||
-rw-r--r-- | lib/MC/MCAsmInfoCOFF.cpp | 1 | ||||
-rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 9 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 462 | ||||
-rw-r--r-- | lib/MC/MCContext.cpp | 41 | ||||
-rw-r--r-- | lib/MC/MCExpr.cpp | 94 | ||||
-rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 65 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmLexer.cpp | 10 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 28 |
9 files changed, 470 insertions, 241 deletions
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index bda700b..c96ff82 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -69,6 +69,7 @@ MCAsmInfo::MCAsmInfo() { DwarfRequiresFrameSection = true; DwarfUsesInlineInfoSection = false; DwarfSectionOffsetDirective = 0; + HasMicrosoftFastStdCallMangling = false; AsmTransCBE = 0; } diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 9130493..5170206 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -35,4 +35,5 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { AbsoluteEHSectionOffsets = false; SupportsDebugInformation = true; DwarfSectionOffsetDirective = "\t.secrel32\t"; + HasMicrosoftFastStdCallMangling = true; } diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 66a0a24..7f39471 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -41,11 +41,10 @@ class MCAsmStreamer : public MCStreamer { public: MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, - const MCAsmInfo &mai, bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer, MCCodeEmitter *emitter, bool showInst) - : MCStreamer(Context), OS(os), MAI(mai), InstPrinter(printer), - Emitter(emitter), CommentStream(CommentToEmit), + : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), + InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit), IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm), ShowInst(showInst) { if (InstPrinter && IsVerboseAsm) @@ -654,9 +653,9 @@ void MCAsmStreamer::Finish() { MCStreamer *llvm::createAsmStreamer(MCContext &Context, formatted_raw_ostream &OS, - const MCAsmInfo &MAI, bool isLittleEndian, + bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *IP, MCCodeEmitter *CE, bool ShowInst) { - return new MCAsmStreamer(Context, OS, MAI, isLittleEndian, isVerboseAsm, + return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, IP, CE, ShowInst); } diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 00b02e0..4cf8b7e 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -9,6 +9,7 @@ #define DEBUG_TYPE "assembler" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSymbol.h" @@ -23,6 +24,8 @@ #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Debug.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmBackend.h" // FIXME: Gross. #include "../Target/X86/X86FixupKinds.h" @@ -49,8 +52,7 @@ static uint64_t WriteNopData(uint64_t Count, MachObjectWriter &MOW); static bool isVirtualSection(const MCSection &Section) { // FIXME: Lame. const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section); - unsigned Type = SMO.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; - return (Type == MCSectionMachO::S_ZEROFILL); + return (SMO.getType() == MCSectionMachO::S_ZEROFILL); } static unsigned getFixupKindLog2Size(unsigned Kind) { @@ -84,14 +86,19 @@ class MachObjectWriter { Header_Magic64 = 0xFEEDFACF }; - static const unsigned Header32Size = 28; - static const unsigned Header64Size = 32; - static const unsigned SegmentLoadCommand32Size = 56; - static const unsigned Section32Size = 68; - static const unsigned SymtabLoadCommandSize = 24; - static const unsigned DysymtabLoadCommandSize = 80; - static const unsigned Nlist32Size = 12; - static const unsigned RelocationInfoSize = 8; + enum { + Header32Size = 28, + Header64Size = 32, + SegmentLoadCommand32Size = 56, + SegmentLoadCommand64Size = 72, + Section32Size = 68, + Section64Size = 80, + SymtabLoadCommandSize = 24, + DysymtabLoadCommandSize = 80, + Nlist32Size = 12, + Nlist64Size = 16, + RelocationInfoSize = 8 + }; enum HeaderFileType { HFT_Object = 0x1 @@ -104,7 +111,8 @@ class MachObjectWriter { enum LoadCommandType { LCT_Segment = 0x1, LCT_Symtab = 0x2, - LCT_Dysymtab = 0xb + LCT_Dysymtab = 0xb, + LCT_Segment64 = 0x19 }; // See <mach-o/nlist.h>. @@ -159,11 +167,12 @@ class MachObjectWriter { }; raw_ostream &OS; - bool IsLSB; + unsigned Is64Bit : 1; + unsigned IsLSB : 1; public: - MachObjectWriter(raw_ostream &_OS, bool _IsLSB = true) - : OS(_OS), IsLSB(_IsLSB) { + MachObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool _IsLSB = true) + : OS(_OS), Is64Bit(_Is64Bit), IsLSB(_IsLSB) { } /// @name Helper Methods @@ -220,22 +229,23 @@ public: /// @} - void WriteHeader32(unsigned NumLoadCommands, unsigned LoadCommandsSize, - bool SubsectionsViaSymbols) { + void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize, + bool SubsectionsViaSymbols) { uint32_t Flags = 0; if (SubsectionsViaSymbols) Flags |= HF_SubsectionsViaSymbols; - // struct mach_header (28 bytes) + // struct mach_header (28 bytes) or + // struct mach_header_64 (32 bytes) uint64_t Start = OS.tell(); (void) Start; - Write32(Header_Magic32); + Write32(Is64Bit ? Header_Magic64 : Header_Magic32); // FIXME: Support cputype. - Write32(MachO::CPUTypeI386); + Write32(Is64Bit ? MachO::CPUTypeX86_64 : MachO::CPUTypeI386); // FIXME: Support cpusubtype. Write32(MachO::CPUSubType_I386_ALL); Write32(HFT_Object); @@ -243,48 +253,62 @@ public: // segment. Write32(LoadCommandsSize); Write32(Flags); + if (Is64Bit) + Write32(0); // reserved - assert(OS.tell() - Start == Header32Size); + assert(OS.tell() - Start == Is64Bit ? Header64Size : Header32Size); } - /// WriteSegmentLoadCommand32 - Write a 32-bit segment load command. + /// WriteSegmentLoadCommand - Write a segment load command. /// /// \arg NumSections - The number of sections in this segment. /// \arg SectionDataSize - The total size of the sections. - void WriteSegmentLoadCommand32(unsigned NumSections, - uint64_t VMSize, - uint64_t SectionDataStartOffset, - uint64_t SectionDataSize) { - // struct segment_command (56 bytes) + void WriteSegmentLoadCommand(unsigned NumSections, + uint64_t VMSize, + uint64_t SectionDataStartOffset, + uint64_t SectionDataSize) { + // struct segment_command (56 bytes) or + // struct segment_command_64 (72 bytes) uint64_t Start = OS.tell(); (void) Start; - Write32(LCT_Segment); - Write32(SegmentLoadCommand32Size + NumSections * Section32Size); + unsigned SegmentLoadCommandSize = Is64Bit ? SegmentLoadCommand64Size : + SegmentLoadCommand32Size; + Write32(Is64Bit ? LCT_Segment64 : LCT_Segment); + Write32(SegmentLoadCommandSize + + NumSections * (Is64Bit ? Section64Size : Section32Size)); WriteString("", 16); - Write32(0); // vmaddr - Write32(VMSize); // vmsize - Write32(SectionDataStartOffset); // file offset - Write32(SectionDataSize); // file size + if (Is64Bit) { + Write64(0); // vmaddr + Write64(VMSize); // vmsize + Write64(SectionDataStartOffset); // file offset + Write64(SectionDataSize); // file size + } else { + Write32(0); // vmaddr + Write32(VMSize); // vmsize + Write32(SectionDataStartOffset); // file offset + Write32(SectionDataSize); // file size + } Write32(0x7); // maxprot Write32(0x7); // initprot Write32(NumSections); Write32(0); // flags - assert(OS.tell() - Start == SegmentLoadCommand32Size); + assert(OS.tell() - Start == SegmentLoadCommandSize); } - void WriteSection32(const MCSectionData &SD, uint64_t FileOffset, - uint64_t RelocationsStart, unsigned NumRelocations) { + void WriteSection(const MCSectionData &SD, uint64_t FileOffset, + uint64_t RelocationsStart, unsigned NumRelocations) { // The offset is unused for virtual sections. if (isVirtualSection(SD.getSection())) { assert(SD.getFileSize() == 0 && "Invalid file size!"); FileOffset = 0; } - // struct section (68 bytes) + // struct section (68 bytes) or + // struct section_64 (80 bytes) uint64_t Start = OS.tell(); (void) Start; @@ -294,8 +318,13 @@ public: static_cast<const MCSectionMachO&>(SD.getSection()); WriteString(Section.getSectionName(), 16); WriteString(Section.getSegmentName(), 16); - Write32(SD.getAddress()); // address - Write32(SD.getSize()); // size + if (Is64Bit) { + Write64(SD.getAddress()); // address + Write64(SD.getSize()); // size + } else { + Write32(SD.getAddress()); // address + Write32(SD.getSize()); // size + } Write32(FileOffset); unsigned Flags = Section.getTypeAndAttributes(); @@ -309,8 +338,10 @@ public: Write32(Flags); Write32(0); // reserved1 Write32(Section.getStubSize()); // reserved2 + if (Is64Bit) + Write32(0); // reserved3 - assert(OS.tell() - Start == Section32Size); + assert(OS.tell() - Start == Is64Bit ? Section64Size : Section32Size); } void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, @@ -368,7 +399,7 @@ public: assert(OS.tell() - Start == DysymtabLoadCommandSize); } - void WriteNlist32(MachSymbolData &MSD) { + void WriteNlist(MachSymbolData &MSD) { MCSymbolData &Data = *MSD.SymbolData; const MCSymbol &Symbol = Data.getSymbol(); uint8_t Type = 0; @@ -399,7 +430,7 @@ public: if (Symbol.isAbsolute()) { llvm_unreachable("FIXME: Not yet implemented!"); } else { - Address = Data.getFragment()->getAddress() + Data.getOffset(); + Address = Data.getAddress(); } } else if (Data.isCommon()) { // Common symbols are encoded with the size in the address @@ -427,7 +458,10 @@ public: // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' // value. Write16(Flags); - Write32(Address); + if (Is64Bit) + Write64(Address); + else + Write32(Address); } struct MachRelocationEntry { @@ -437,7 +471,6 @@ public: void ComputeScatteredRelocationInfo(MCAssembler &Asm, MCFragment &Fragment, MCAsmFixup &Fixup, const MCValue &Target, - DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap, std::vector<MachRelocationEntry> &Relocs) { uint32_t Address = Fragment.getOffset() + Fixup.Offset; unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind); @@ -446,17 +479,17 @@ public: // See <reloc.h>. const MCSymbol *A = Target.getSymA(); - MCSymbolData *A_SD = SymbolMap.lookup(A); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); if (!A_SD->getFragment()) llvm_report_error("symbol '" + A->getName() + "' can not be undefined in a subtraction expression"); - uint32_t Value = A_SD->getFragment()->getAddress() + A_SD->getOffset(); + uint32_t Value = A_SD->getAddress(); uint32_t Value2 = 0; if (const MCSymbol *B = Target.getSymB()) { - MCSymbolData *B_SD = SymbolMap.lookup(B); + MCSymbolData *B_SD = &Asm.getSymbolData(*B); if (!B_SD->getFragment()) llvm_report_error("symbol '" + B->getName() + @@ -468,22 +501,9 @@ public: // relocation types from the linkers point of view, this is done solely // for pedantic compatibility with 'as'. Type = A_SD->isExternal() ? RIT_Difference : RIT_LocalDifference; - Value2 = B_SD->getFragment()->getAddress() + B_SD->getOffset(); + Value2 = B_SD->getAddress(); } - // The value which goes in the fixup is current value of the expression. - Fixup.FixedValue = Value - Value2 + Target.getConstant(); - if (IsPCRel) - Fixup.FixedValue -= Address; - - // If this fixup is a vanilla PC relative relocation for a local label, we - // don't need a relocation. - // - // FIXME: Implement proper atom support. - if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary() && - !Target.getSymB()) - return; - MachRelocationEntry MRE; MRE.Word0 = ((Address << 0) | (Type << 24) | @@ -507,14 +527,17 @@ public: void ComputeRelocationInfo(MCAssembler &Asm, MCDataFragment &Fragment, MCAsmFixup &Fixup, - DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap, std::vector<MachRelocationEntry> &Relocs) { unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind); unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); + // FIXME: Share layout object. + MCAsmLayout Layout(Asm); + + // Evaluate the fixup; if the value was resolved, no relocation is needed. MCValue Target; - if (!Fixup.Value->EvaluateAsRelocatable(Target)) - llvm_report_error("expected relocatable expression"); + if (Asm.EvaluateFixup(Layout, Fixup, &Fragment, Target, Fixup.FixedValue)) + return; // If this is a difference or a defined symbol plus an offset, then we need // a scattered relocation entry. @@ -525,7 +548,7 @@ public: (Target.getSymA() && !Target.getSymA()->isUndefined() && Offset)) return ComputeScatteredRelocationInfo(Asm, Fragment, Fixup, Target, - SymbolMap, Relocs); + Relocs); // See <reloc.h>. uint32_t Address = Fragment.getOffset() + Fixup.Offset; @@ -537,13 +560,13 @@ public: if (Target.isAbsolute()) { // constant // SymbolNum of 0 indicates the absolute section. // - // FIXME: When is this generated? + // FIXME: Currently, these are never generated (see code below). I cannot + // find a case where they are actually emitted. Type = RIT_Vanilla; Value = 0; - llvm_unreachable("FIXME: Not yet implemented!"); } else { const MCSymbol *Symbol = Target.getSymA(); - MCSymbolData *SD = SymbolMap.lookup(Symbol); + MCSymbolData *SD = &Asm.getSymbolData(*Symbol); if (Symbol->isUndefined()) { IsExtern = 1; @@ -559,24 +582,12 @@ public: if (&*it == SD->getFragment()->getParent()) break; assert(it != ie && "Unable to find section index!"); - Value = SD->getFragment()->getAddress() + SD->getOffset(); + Value = SD->getAddress(); } Type = RIT_Vanilla; } - // The value which goes in the fixup is current value of the expression. - Fixup.FixedValue = Value + Target.getConstant(); - if (IsPCRel) - Fixup.FixedValue -= Address; - - // If this fixup is a vanilla PC relative relocation for a local label, we - // don't need a relocation. - // - // FIXME: Implement proper atom support. - if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary()) - return; - // struct relocation_info (8 bytes) MachRelocationEntry MRE; MRE.Word0 = Address; @@ -588,8 +599,7 @@ public: Relocs.push_back(MRE); } - void BindIndirectSymbols(MCAssembler &Asm, - DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap) { + void BindIndirectSymbols(MCAssembler &Asm) { // This is the point where 'as' creates actual symbols for indirect symbols // (in the following two passes). It would be easier for us to do this // sooner when we see the attribute, but that makes getting the order in the @@ -604,14 +614,10 @@ public: const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(it->SectionData->getSection()); - unsigned Type = - Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; - if (Type != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) + if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) continue; - MCSymbolData *&Entry = SymbolMap[it->Symbol]; - if (!Entry) - Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm); + Asm.getOrCreateSymbolData(*it->Symbol); } // Then lazy symbol pointers and symbol stubs. @@ -621,21 +627,17 @@ public: const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(it->SectionData->getSection()); - unsigned Type = - Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; - if (Type != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && - Type != MCSectionMachO::S_SYMBOL_STUBS) + if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && + Section.getType() != MCSectionMachO::S_SYMBOL_STUBS) continue; - MCSymbolData *&Entry = SymbolMap[it->Symbol]; - if (!Entry) { - Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm); - - // Set the symbol type to undefined lazy, but only on construction. - // - // FIXME: Do not hardcode. - Entry->setFlags(Entry->getFlags() | 0x0001); - } + // Set the symbol type to undefined lazy, but only on construction. + // + // FIXME: Do not hardcode. + bool Created; + MCSymbolData &Entry = Asm.getOrCreateSymbolData(*it->Symbol, &Created); + if (Created) + Entry.setFlags(Entry.getFlags() | 0x0001); } } @@ -672,7 +674,10 @@ public: const MCSymbol &Symbol = it->getSymbol(); // Ignore assembler temporaries. - if (it->getSymbol().isTemporary()) + if (it->getSymbol().isTemporary() && + (!it->getFragment() || + !Asm.getBackend().doesSectionRequireSymbols( + it->getFragment()->getParent()->getSection()))) continue; if (!it->isExternal() && !Symbol.isUndefined()) @@ -708,7 +713,10 @@ public: const MCSymbol &Symbol = it->getSymbol(); // Ignore assembler temporaries. - if (it->getSymbol().isTemporary()) + if (it->getSymbol().isTemporary() && + (!it->getFragment() || + !Asm.getBackend().doesSectionRequireSymbols( + it->getFragment()->getParent()->getSection()))) continue; if (it->isExternal() || Symbol.isUndefined()) @@ -756,16 +764,8 @@ public: void WriteObject(MCAssembler &Asm) { unsigned NumSections = Asm.size(); - // Compute the symbol -> symbol data map. - // - // FIXME: This should not be here. - DenseMap<const MCSymbol*, MCSymbolData *> SymbolMap; - for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), - ie = Asm.symbol_end(); it != ie; ++it) - SymbolMap[&it->getSymbol()] = it; - // Create symbol data for any indirect symbols. - BindIndirectSymbols(Asm, SymbolMap); + BindIndirectSymbols(Asm); // Compute symbol table information. SmallString<256> StringTable; @@ -782,7 +782,8 @@ public: // The section data starts after the header, the segment load command (and // section headers) and the symbol table. unsigned NumLoadCommands = 1; - uint64_t LoadCommandsSize = + uint64_t LoadCommandsSize = Is64Bit ? + SegmentLoadCommand64Size + NumSections * Section64Size : SegmentLoadCommand32Size + NumSections * Section32Size; // Add the symbol table load command sizes, if used. @@ -793,7 +794,8 @@ public: // Compute the total size of the section data, as well as its file size and // vm size. - uint64_t SectionDataStart = Header32Size + LoadCommandsSize; + uint64_t SectionDataStart = (Is64Bit ? Header64Size : Header32Size) + + LoadCommandsSize; uint64_t SectionDataSize = 0; uint64_t SectionDataFileSize = 0; uint64_t VMSize = 0; @@ -819,10 +821,10 @@ public: SectionDataFileSize += SectionDataPadding; // Write the prolog, starting with the header and load command... - WriteHeader32(NumLoadCommands, LoadCommandsSize, - Asm.getSubsectionsViaSymbols()); - WriteSegmentLoadCommand32(NumSections, VMSize, - SectionDataStart, SectionDataSize); + WriteHeader(NumLoadCommands, LoadCommandsSize, + Asm.getSubsectionsViaSymbols()); + WriteSegmentLoadCommand(NumSections, VMSize, + SectionDataStart, SectionDataSize); // ... and then the section headers. // @@ -845,11 +847,11 @@ public: if (MCDataFragment *DF = dyn_cast<MCDataFragment>(&*it2)) for (unsigned i = 0, e = DF->fixup_size(); i != e; ++i) ComputeRelocationInfo(Asm, *DF, DF->getFixups()[e - i - 1], - SymbolMap, RelocInfos); + RelocInfos); unsigned NumRelocs = RelocInfos.size() - NumRelocsStart; uint64_t SectionStart = SectionDataStart + SD.getAddress(); - WriteSection32(SD, SectionStart, RelocTableEnd, NumRelocs); + WriteSection(SD, SectionStart, RelocTableEnd, NumRelocs); RelocTableEnd += NumRelocs * RelocationInfoSize; } @@ -876,7 +878,8 @@ public: // The string table is written after symbol table. uint64_t StringTableOffset = - SymbolTableOffset + NumSymTabSymbols * Nlist32Size; + SymbolTableOffset + NumSymTabSymbols * (Is64Bit ? Nlist64Size : + Nlist32Size); WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, StringTableOffset, StringTable.size()); @@ -909,12 +912,10 @@ public: // special handling. const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(it->SectionData->getSection()); - unsigned Type = - Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; - if (Type == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) { + if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) { // If this symbol is defined and internal, mark it as such. if (it->Symbol->isDefined() && - !SymbolMap.lookup(it->Symbol)->isExternal()) { + !Asm.getSymbolData(*it->Symbol).isExternal()) { uint32_t Flags = ISF_Local; if (it->Symbol->isAbsolute()) Flags |= ISF_Absolute; @@ -923,18 +924,18 @@ public: } } - Write32(SymbolMap[it->Symbol]->getIndex()); + Write32(Asm.getSymbolData(*it->Symbol).getIndex()); } // FIXME: Check that offsets match computed ones. // Write the symbol table entries. for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) - WriteNlist32(LocalSymbolData[i]); + WriteNlist(LocalSymbolData[i]); for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) - WriteNlist32(ExternalSymbolData[i]); + WriteNlist(ExternalSymbolData[i]); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) - WriteNlist32(UndefinedSymbolData[i]); + WriteNlist(UndefinedSymbolData[i]); // Write the string table. OS << StringTable.str(); @@ -1006,15 +1007,65 @@ MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, /* *** */ -MCAssembler::MCAssembler(MCContext &_Context, raw_ostream &_OS) - : Context(_Context), OS(_OS), SubsectionsViaSymbols(false) +MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, + raw_ostream &_OS) + : Context(_Context), Backend(_Backend), OS(_OS), SubsectionsViaSymbols(false) { } MCAssembler::~MCAssembler() { } +bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, MCAsmFixup &Fixup, + MCDataFragment *DF, + MCValue &Target, uint64_t &Value) const { + if (!Fixup.Value->EvaluateAsRelocatable(Target, &Layout)) + llvm_report_error("expected relocatable expression"); + + // FIXME: How do non-scattered symbols work in ELF? I presume the linker + // doesn't support small relocations, but then under what criteria does the + // assembler allow symbol differences? + + Value = Target.getConstant(); + + // FIXME: This "resolved" check isn't quite right. The assumption is that if + // we have a PCrel access to a temporary, then that temporary is in the same + // atom, and so the value is resolved. We need explicit atom's to implement + // this more precisely. + bool IsResolved = true, IsPCRel = isFixupKindPCRel(Fixup.Kind); + if (const MCSymbol *Symbol = Target.getSymA()) { + if (Symbol->isDefined()) + Value += getSymbolData(*Symbol).getAddress(); + else + IsResolved = false; + + // With scattered symbols, we assume anything that isn't a PCrel temporary + // access can have an arbitrary value. + if (getBackend().hasScatteredSymbols() && + (!IsPCRel || !Symbol->isTemporary())) + IsResolved = false; + } + if (const MCSymbol *Symbol = Target.getSymB()) { + if (Symbol->isDefined()) + Value -= getSymbolData(*Symbol).getAddress(); + else + IsResolved = false; + + // With scattered symbols, we assume anything that isn't a PCrel temporary + // access can have an arbitrary value. + if (getBackend().hasScatteredSymbols() && + (!IsPCRel || !Symbol->isTemporary())) + IsResolved = false; + } + + if (IsPCRel) + Value -= DF->getAddress() + Fixup.Offset; + + return IsResolved; +} + void MCAssembler::LayoutSection(MCSectionData &SD) { + MCAsmLayout Layout(*this); uint64_t Address = SD.getAddress(); for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) { @@ -1043,21 +1094,17 @@ void MCAssembler::LayoutSection(MCSectionData &SD) { case MCFragment::FT_Org: { MCOrgFragment &OF = cast<MCOrgFragment>(F); - MCValue Target; - if (!OF.getOffset().EvaluateAsRelocatable(Target)) - llvm_report_error("expected relocatable expression"); - - if (!Target.isAbsolute()) - llvm_unreachable("FIXME: Not yet implemented!"); - uint64_t OrgOffset = Target.getConstant(); - uint64_t Offset = Address - SD.getAddress(); + int64_t TargetLocation; + if (!OF.getOffset().EvaluateAsAbsolute(TargetLocation, &Layout)) + llvm_report_error("expected assembly-time absolute expression"); // FIXME: We need a way to communicate this error. - if (OrgOffset < Offset) - llvm_report_error("invalid .org offset '" + Twine(OrgOffset) + - "' (at offset '" + Twine(Offset) + "'"); + int64_t Offset = TargetLocation - F.getOffset(); + if (Offset < 0) + llvm_report_error("invalid .org offset '" + Twine(TargetLocation) + + "' (at offset '" + Twine(F.getOffset()) + "'"); - F.setFileSize(OrgOffset - Offset); + F.setFileSize(Offset); break; } @@ -1263,6 +1310,43 @@ void MCAssembler::Finish() { llvm::errs() << "assembler backend - pre-layout\n--\n"; dump(); }); + // Layout until everything fits. + while (LayoutOnce()) + continue; + + DEBUG_WITH_TYPE("mc-dump", { + llvm::errs() << "assembler backend - post-layout\n--\n"; + dump(); }); + + // Write the object file. + // + // FIXME: Factor out MCObjectWriter. + bool Is64Bit = StringRef(getBackend().getTarget().getName()) == "x86-64"; + MachObjectWriter MOW(OS, Is64Bit); + MOW.WriteObject(*this); + + OS.flush(); +} + +bool MCAssembler::FixupNeedsRelaxation(MCAsmFixup &Fixup, MCDataFragment *DF) { + // FIXME: Share layout object. + MCAsmLayout Layout(*this); + + // Currently we only need to relax X86::reloc_pcrel_1byte. + if (unsigned(Fixup.Kind) != X86::reloc_pcrel_1byte) + return false; + + // If we cannot resolve the fixup value, it requires relaxation. + MCValue Target; + uint64_t Value; + if (!EvaluateFixup(Layout, Fixup, DF, Target, Value)) + return true; + + // Otherwise, relax if the value is too big for a (signed) i8. + return int64_t(Value) != int64_t(int8_t(Value)); +} + +bool MCAssembler::LayoutOnce() { // Layout the concrete sections and fragments. uint64_t Address = 0; MCSectionData *Prev = 0; @@ -1304,20 +1388,94 @@ void MCAssembler::Finish() { SD.setAddress(Address); LayoutSection(SD); Address += SD.getSize(); - } - DEBUG_WITH_TYPE("mc-dump", { - llvm::errs() << "assembler backend - post-layout\n--\n"; - dump(); }); + // Scan the fixups in order and relax any that don't fit. + for (iterator it = begin(), ie = end(); it != ie; ++it) { + MCSectionData &SD = *it; - // Write the object file. - MachObjectWriter MOW(OS); - MOW.WriteObject(*this); + for (MCSectionData::iterator it2 = SD.begin(), + ie2 = SD.end(); it2 != ie2; ++it2) { + MCDataFragment *DF = dyn_cast<MCDataFragment>(it2); + if (!DF) + continue; - OS.flush(); -} + for (MCDataFragment::fixup_iterator it3 = DF->fixup_begin(), + ie3 = DF->fixup_end(); it3 != ie3; ++it3) { + MCAsmFixup &Fixup = *it3; + + // Check whether we need to relax this fixup. + if (!FixupNeedsRelaxation(Fixup, DF)) + continue; + + // Relax the instruction. + // + // FIXME: This is a huge temporary hack which just looks for x86 + // branches; the only thing we need to relax on x86 is + // 'X86::reloc_pcrel_1byte'. Once we have MCInst fragments, this will be + // replaced by a TargetAsmBackend hook (most likely tblgen'd) to relax + // an individual MCInst. + SmallVectorImpl<char> &C = DF->getContents(); + uint64_t PrevOffset = Fixup.Offset; + unsigned Amt = 0; + + // jcc instructions + if (unsigned(C[Fixup.Offset-1]) >= 0x70 && + unsigned(C[Fixup.Offset-1]) <= 0x7f) { + C[Fixup.Offset] = C[Fixup.Offset-1] + 0x10; + C[Fixup.Offset-1] = char(0x0f); + ++Fixup.Offset; + Amt = 4; + + // jmp rel8 + } else if (C[Fixup.Offset-1] == char(0xeb)) { + C[Fixup.Offset-1] = char(0xe9); + Amt = 3; + + } else + llvm_unreachable("unknown 1 byte pcrel instruction!"); + + Fixup.Value = MCBinaryExpr::Create( + MCBinaryExpr::Sub, Fixup.Value, + MCConstantExpr::Create(3, getContext()), + getContext()); + C.insert(C.begin() + Fixup.Offset, Amt, char(0)); + Fixup.Kind = MCFixupKind(X86::reloc_pcrel_4byte); + + // Update the remaining fixups, which have slid. + // + // FIXME: This is bad for performance, but will be eliminated by the + // move to MCInst specific fragments. + ++it3; + for (; it3 != ie3; ++it3) + it3->Offset += Amt; + + // Update all the symbols for this fragment, which may have slid. + // + // FIXME: This is really really bad for performance, but will be + // eliminated by the move to MCInst specific fragments. + for (MCAssembler::symbol_iterator it = symbol_begin(), + ie = symbol_end(); it != ie; ++it) { + MCSymbolData &SD = *it; + if (it->getFragment() != DF) + continue; + + if (SD.getOffset() > PrevOffset) + SD.setOffset(SD.getOffset() + Amt); + } + + // Restart layout. + // + // FIXME: This is O(N^2), but will be eliminated once we have a smart + // MCAsmLayout object. + return true; + } + } + } + + return false; +} // Debugging methods diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index 63264f6..70c89a2 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -8,14 +8,14 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" using namespace llvm; -MCContext::MCContext() { +MCContext::MCContext(const MCAsmInfo &mai) : MAI(mai), NextUniqueID(0) { } MCContext::~MCContext() { @@ -23,30 +23,41 @@ MCContext::~MCContext() { // we don't need to free them here. } -MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) { +MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name, bool isTemporary) { assert(!Name.empty() && "Normal symbols cannot be unnamed!"); - MCSymbol *&Entry = Symbols[Name]; - if (Entry) return Entry; + + // Do the lookup and get the entire StringMapEntry. We want access to the + // key if we are creating the entry. + StringMapEntry<MCSymbol*> &Entry = Symbols.GetOrCreateValue(Name); + if (Entry.getValue()) return Entry.getValue(); - return Entry = new (*this) MCSymbol(Name, false); + // Ok, the entry doesn't already exist. Have the MCSymbol object itself refer + // to the copy of the string that is embedded in the StringMapEntry. + MCSymbol *Result = new (*this) MCSymbol(Entry.getKey(), isTemporary); + Entry.setValue(Result); + return Result; } -MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { +MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name, bool isTemporary) { SmallString<128> NameSV; Name.toVector(NameSV); - return GetOrCreateSymbol(NameSV.str()); + return GetOrCreateSymbol(NameSV.str(), isTemporary); +} + +MCSymbol *MCContext::CreateTempSymbol() { + return GetOrCreateTemporarySymbol(Twine(MAI.getPrivateGlobalPrefix()) + + "tmp" + Twine(NextUniqueID++)); } MCSymbol *MCContext::GetOrCreateTemporarySymbol(StringRef Name) { - // If unnamed, just create a symbol. + // If there is no name, create a new anonymous symbol. + // FIXME: Remove this. This form of the method should always take a name. if (Name.empty()) - new (*this) MCSymbol("", true); - - // Otherwise create as usual. - MCSymbol *&Entry = Symbols[Name]; - if (Entry) return Entry; - return Entry = new (*this) MCSymbol(Name, true); + return GetOrCreateTemporarySymbol(Twine(MAI.getPrivateGlobalPrefix()) + + "tmp" + Twine(NextUniqueID++)); + + return GetOrCreateSymbol(Name, true); } MCSymbol *MCContext::GetOrCreateTemporarySymbol(const Twine &Name) { diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 4439eba..a2ed20b 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -8,11 +8,15 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCExpr.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmBackend.h" using namespace llvm; void MCExpr::print(raw_ostream &OS) const { @@ -24,7 +28,8 @@ void MCExpr::print(raw_ostream &OS) const { return; case MCExpr::SymbolRef: { - const MCSymbol &Sym = cast<MCSymbolRefExpr>(*this).getSymbol(); + const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); + const MCSymbol &Sym = SRE.getSymbol(); // Parenthesize names that start with $ so that they don't look like // absolute names. @@ -32,6 +37,10 @@ void MCExpr::print(raw_ostream &OS) const { OS << '(' << Sym << ')'; else OS << Sym; + + if (SRE.getKind() != MCSymbolRefExpr::VK_None) + OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + return; } @@ -124,28 +133,68 @@ const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { return new (Ctx) MCConstantExpr(Value); } +/* *** */ + const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, + VariantKind Kind, MCContext &Ctx) { - return new (Ctx) MCSymbolRefExpr(Sym); + return new (Ctx) MCSymbolRefExpr(Sym, Kind); } -const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, MCContext &Ctx) { - return Create(Ctx.GetOrCreateSymbol(Name), Ctx); +const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind, + MCContext &Ctx) { + return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx); } const MCSymbolRefExpr *MCSymbolRefExpr::CreateTemp(StringRef Name, + VariantKind Kind, MCContext &Ctx) { - return Create(Ctx.GetOrCreateTemporarySymbol(Name), Ctx); + return Create(Ctx.GetOrCreateTemporarySymbol(Name), Kind, Ctx); } +StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { + switch (Kind) { + default: + case VK_Invalid: return "<<invalid>>"; + case VK_None: return "<<none>>"; + + case VK_GOT: return "GOT"; + case VK_GOTOFF: return "GOTOFF"; + case VK_GOTPCREL: return "GOTPCREL"; + case VK_GOTTPOFF: return "GOTTPOFF"; + case VK_INDNTPOFF: return "INDNTPOFF"; + case VK_NTPOFF: return "NTPOFF"; + case VK_PLT: return "PLT"; + case VK_TLSGD: return "TLSGD"; + case VK_TPOFF: return "TPOFF"; + } +} + +MCSymbolRefExpr::VariantKind +MCSymbolRefExpr::getVariantKindForName(StringRef Name) { + return StringSwitch<VariantKind>(Name) + .Case("GOT", VK_GOT) + .Case("GOTOFF", VK_GOTOFF) + .Case("GOTPCREL", VK_GOTPCREL) + .Case("GOTTPOFF", VK_GOTTPOFF) + .Case("INDNTPOFF", VK_INDNTPOFF) + .Case("NTPOFF", VK_NTPOFF) + .Case("PLT", VK_PLT) + .Case("TLSGD", VK_TLSGD) + .Case("TPOFF", VK_TPOFF) + .Default(VK_Invalid); +} + +/* *** */ + void MCTargetExpr::Anchor() {} /* *** */ -bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { +bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const { MCValue Value; - if (!EvaluateAsRelocatable(Value) || !Value.isAbsolute()) + if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute()) return false; Res = Value.getConstant(); @@ -174,10 +223,11 @@ static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A, return true; } -bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { +bool MCExpr::EvaluateAsRelocatable(MCValue &Res, + const MCAsmLayout *Layout) const { switch (getKind()) { case Target: - return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res); + return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout); case Constant: Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); @@ -187,8 +237,24 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol(); // Evaluate recursively if this is a variable. - if (Sym.isVariable()) - return Sym.getValue()->EvaluateAsRelocatable(Res); + if (Sym.isVariable()) { + if (!Sym.getValue()->EvaluateAsRelocatable(Res, Layout)) + return false; + + // Absolutize symbol differences between defined symbols when we have a + // layout object and the target requests it. + if (Layout && Res.getSymB() && + Layout->getAssembler().getBackend().hasAbsolutizedSet() && + Res.getSymA()->isDefined() && Res.getSymB()->isDefined()) { + MCSymbolData &A = Layout->getAssembler().getSymbolData(*Res.getSymA()); + MCSymbolData &B = Layout->getAssembler().getSymbolData(*Res.getSymB()); + Res = MCValue::get(+ A.getFragment()->getAddress() + A.getOffset() + - B.getFragment()->getAddress() - B.getOffset() + + Res.getConstant()); + } + + return true; + } Res = MCValue::get(&Sym, 0, 0); return true; @@ -198,7 +264,7 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); MCValue Value; - if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value)) + if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout)) return false; switch (AUE->getOpcode()) { @@ -231,8 +297,8 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); MCValue LHSValue, RHSValue; - if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue) || - !ABE->getRHS()->EvaluateAsRelocatable(RHSValue)) + if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) || + !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout)) return false; // We only support a few operations on non-constant expressions, handle diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index a7a8a5d..73b1074 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -16,7 +16,6 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -48,8 +47,6 @@ private: MCAssembler Assembler; MCCodeEmitter *Emitter; MCSectionData *CurSectionData; - DenseMap<const MCSection*, MCSectionData*> SectionMap; - DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap; private: MCFragment *getCurrentFragment() const { @@ -61,27 +58,10 @@ private: return 0; } - MCSectionData &getSectionData(const MCSection &Section) { - MCSectionData *&Entry = SectionMap[&Section]; - - if (!Entry) - Entry = new MCSectionData(Section, &Assembler); - - return *Entry; - } - - MCSymbolData &getSymbolData(const MCSymbol &Symbol) { - MCSymbolData *&Entry = SymbolMap[&Symbol]; - - if (!Entry) - Entry = new MCSymbolData(Symbol, 0, 0, &Assembler); - - return *Entry; - } - public: - MCMachOStreamer(MCContext &Context, raw_ostream &_OS, MCCodeEmitter *_Emitter) - : MCStreamer(Context), Assembler(Context, _OS), Emitter(_Emitter), + MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &_OS, MCCodeEmitter *_Emitter) + : MCStreamer(Context), Assembler(Context, TAB, _OS), Emitter(_Emitter), CurSectionData(0) {} ~MCMachOStreamer() {} @@ -99,7 +79,8 @@ public: } case MCExpr::SymbolRef: - getSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); + Assembler.getOrCreateSymbolData( + cast<MCSymbolRefExpr>(Value)->getSymbol()); break; case MCExpr::Unary: @@ -164,7 +145,7 @@ void MCMachOStreamer::SwitchSection(const MCSection *Section) { if (Section == CurSection) return; CurSection = Section; - CurSectionData = &getSectionData(*Section); + CurSectionData = &Assembler.getOrCreateSectionData(*Section); } void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { @@ -175,7 +156,7 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { if (!F) F = new MCDataFragment(CurSectionData); - MCSymbolData &SD = getSymbolData(*Symbol); + MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol); assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); SD.setFragment(F); SD.setOffset(F->getContents().size()); @@ -203,7 +184,7 @@ void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { // FIXME: Lift context changes into super class. // FIXME: Set associated section. - Symbol->setValue(Value); + Symbol->setValue(AddValueSymbols(Value)); } void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, @@ -221,9 +202,9 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, } // Adding a symbol attribute always introduces the symbol, note that an - // important side effect of calling getSymbolData here is to register the - // symbol with the assembler. - MCSymbolData &SD = getSymbolData(*Symbol); + // important side effect of calling getOrCreateSymbolData here is to register + // the symbol with the assembler. + MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol); // The implementation of symbol attributes is designed to match 'as', but it // leaves much to desired. It doesn't really make sense to arbitrarily add and @@ -289,7 +270,7 @@ void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { // Encode the 'desc' value into the lowest implementation defined bits. assert(DescValue == (DescValue & SF_DescFlagsMask) && "Invalid .desc value!"); - getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask); + Assembler.getOrCreateSymbolData(*Symbol).setFlags(DescValue&SF_DescFlagsMask); } void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, @@ -297,14 +278,14 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - MCSymbolData &SD = getSymbolData(*Symbol); + MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol); SD.setExternal(true); SD.setCommon(Size, ByteAlignment); } void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, unsigned Size, unsigned ByteAlignment) { - MCSectionData &SectData = getSectionData(*Section); + MCSectionData &SectData = Assembler.getOrCreateSectionData(*Section); // The symbol may not be present, which only creates the section. if (!Symbol) @@ -314,7 +295,7 @@ void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - MCSymbolData &SD = getSymbolData(*Symbol); + MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol); MCFragment *F = new MCZeroFillFragment(Size, ByteAlignment, &SectData); SD.setFragment(F); @@ -346,9 +327,8 @@ void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size, for (unsigned i = 0; i != Size; ++i) DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); } else { - DF->getFixups().push_back(MCAsmFixup(DF->getContents().size(), - *AddValueSymbols(Value), - MCFixup::getKindForSize(Size))); + DF->addFixup(MCAsmFixup(DF->getContents().size(), *AddValueSymbols(Value), + MCFixup::getKindForSize(Size))); DF->getContents().resize(DF->getContents().size() + Size, 0); } } @@ -407,9 +387,8 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { DF = new MCDataFragment(CurSectionData); for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { MCFixup &F = Fixups[i]; - DF->getFixups().push_back(MCAsmFixup(DF->getContents().size()+F.getOffset(), - *F.getValue(), - F.getKind())); + DF->addFixup(MCAsmFixup(DF->getContents().size()+F.getOffset(), + *F.getValue(), F.getKind())); } DF->getContents().append(Code.begin(), Code.end()); } @@ -418,7 +397,7 @@ void MCMachOStreamer::Finish() { Assembler.Finish(); } -MCStreamer *llvm::createMachOStreamer(MCContext &Context, raw_ostream &OS, - MCCodeEmitter *CE) { - return new MCMachOStreamer(Context, OS, CE); +MCStreamer *llvm::createMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE) { + return new MCMachOStreamer(Context, TAB, OS, CE); } diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index 482eefd..22c8d76 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -140,8 +140,14 @@ AsmToken AsmLexer::LexDigit() { StringRef Result(TokStart, CurPtr - TokStart); long long Value; - if (Result.getAsInteger(10, Value)) - return ReturnError(TokStart, "Invalid decimal number"); + if (Result.getAsInteger(10, Value)) { + // We have to handle minint_as_a_positive_value specially, because + // - minint_as_a_positive_value = minint and it is valid. + if (Result == "9223372036854775808") + Value = -9223372036854775808ULL; + else + return ReturnError(TokStart, "Invalid decimal number"); + } return AsmToken(AsmToken::Integer, Result, Value); } diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index fc8d549..4ec5247 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -20,7 +20,6 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/SourceMgr.h" @@ -139,15 +138,14 @@ const AsmToken &AsmParser::Lex() { return *tok; } -bool AsmParser::Run() { - // Create the initial section. +bool AsmParser::Run(bool NoInitialTextSection) { + // Create the initial section, if requested. // - // FIXME: Support -n. // FIXME: Target hook & command line option for initial section. - Out.SwitchSection(getMachOSection("__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - 0, SectionKind::getText())); - + if (!NoInitialTextSection) + Out.SwitchSection(getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 0, SectionKind::getText())); // Prime the lexer. Lex(); @@ -264,19 +262,29 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { case AsmToken::String: case AsmToken::Identifier: { // This is a symbol reference. - MCSymbol *Sym = CreateSymbol(getTok().getIdentifier()); + std::pair<StringRef, StringRef> Split = getTok().getIdentifier().split('@'); + MCSymbol *Sym = CreateSymbol(Split.first); + + // Lookup the symbol variant if used. + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + if (Split.first.size() != getTok().getIdentifier().size()) + Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); + EndLoc = Lexer.getLoc(); Lex(); // Eat identifier. // If this is an absolute variable reference, substitute it now to preserve // semantics in the face of reassignment. if (Sym->getValue() && isa<MCConstantExpr>(Sym->getValue())) { + if (Variant) + return Error(EndLoc, "unexpected modified on variable reference"); + Res = Sym->getValue(); return false; } // Otherwise create a symbol ref. - Res = MCSymbolRefExpr::Create(Sym, getContext()); + Res = MCSymbolRefExpr::Create(Sym, Variant, getContext()); return false; } case AsmToken::Integer: |