diff options
author | Jim Grosbach <grosbach@apple.com> | 2012-05-18 19:12:01 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2012-05-18 19:12:01 +0000 |
commit | 3e96531186ba574b0c25a4be62d24b8b7d752c9f (patch) | |
tree | 7d7125c9e62b05642d228d02100138e98c3da272 | |
parent | 18e2f6e94cf9dc48bfc6dfa3848971aa88e334da (diff) |
Refactor data-in-code annotations.
Use a dedicated MachO load command to annotate data-in-code regions.
This is the same format the linker produces for final executable images,
allowing consistency of representation and use of introspection tools
for both object and executable files.
Data-in-code regions are annotated via ".data_region"/".end_data_region"
directive pairs, with an optional region type.
data_region_directive := ".data_region" { region_type }
region_type := "jt8" | "jt16" | "jt32" | "jta32"
end_data_region_directive := ".end_data_region"
The previous handling of ARM-style "$d.*" labels was broken and has
been removed. Specifically, it didn't handle ARM vs. Thumb mode when
marking the end of the section.
rdar://11459456
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157062 91177308-0d34-0410-b5e6-96231b3b80d8
28 files changed, 411 insertions, 215 deletions
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 16964c3c9d..ae0dad2fd1 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -147,6 +147,11 @@ namespace llvm { // FIXME: Make this a more general encoding setting? bool AllowUTF8; + /// UseDataRegionDirectives - This is true if data region markers should + /// be printed as ".data_region/.end_data_region" directives. If false, + /// use "$d/$a" labels instead. + bool UseDataRegionDirectives; + //===--- Data Emission Directives -------------------------------------===// /// ZeroDirective - this should be set to the directive used to get some @@ -172,18 +177,6 @@ namespace llvm { const char *Data32bitsDirective; // Defaults to "\t.long\t" const char *Data64bitsDirective; // Defaults to "\t.quad\t" - /// [Data|Code]Begin - These magic labels are used to marked a region as - /// data or code, and are used to provide additional information for - /// correct disassembly on targets that like to mix data and code within - /// a segment. These labels will be implicitly suffixed by the streamer - /// to give them unique names. - const char *DataBegin; // Defaults to "$d." - const char *CodeBegin; // Defaults to "$a." - const char *JT8Begin; // Defaults to "$a." - const char *JT16Begin; // Defaults to "$a." - const char *JT32Begin; // Defaults to "$a." - bool SupportsDataRegions; - /// GPRel64Directive - if non-null, a directive that is used to emit a word /// which should be relocated as a 64-bit GP-relative offset, e.g. .gpdword /// on Mips. @@ -384,14 +377,6 @@ namespace llvm { const char *getGPRel64Directive() const { return GPRel64Directive; } const char *getGPRel32Directive() const { return GPRel32Directive; } - /// [Code|Data]Begin label name accessors. - const char *getCodeBeginLabelName() const { return CodeBegin; } - const char *getDataBeginLabelName() const { return DataBegin; } - const char *getJumpTable8BeginLabelName() const { return JT8Begin; } - const char *getJumpTable16BeginLabelName() const { return JT16Begin; } - const char *getJumpTable32BeginLabelName() const { return JT32Begin; } - bool getSupportsDataRegions() const { return SupportsDataRegions; } - /// getNonexecutableStackSection - Targets can implement this method to /// specify a section to switch to if the translation unit doesn't have any /// trampolines that require an executable stack. @@ -488,6 +473,9 @@ namespace llvm { bool doesAllowUTF8() const { return AllowUTF8; } + bool doesSupportDataRegionDirectives() const { + return UseDataRegionDirectives; + } const char *getZeroDirective() const { return ZeroDirective; } diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index d139173c3e..4ab7f91f72 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -651,6 +651,16 @@ struct IndirectSymbolData { MCSectionData *SectionData; }; +// FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk +// to one another. +struct DataRegionData { + // This enum should be kept in sync w/ the mach-o definition in + // llvm/Object/MachOFormat.h. + enum KindTy { Data = 1, JumpTable8, JumpTable16, JumpTable32 } Kind; + MCSymbol *Start; + MCSymbol *End; +}; + class MCAssembler { friend class MCAsmLayout; @@ -668,6 +678,10 @@ public: const_indirect_symbol_iterator; typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; + typedef std::vector<DataRegionData>::const_iterator + const_data_region_iterator; + typedef std::vector<DataRegionData>::iterator data_region_iterator; + private: MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT void operator=(const MCAssembler&); // DO NOT IMPLEMENT @@ -698,6 +712,7 @@ private: std::vector<IndirectSymbolData> IndirectSymbols; + std::vector<DataRegionData> DataRegions; /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -884,6 +899,33 @@ public: size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} + /// @name Data Region List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector<DataRegionData> &getDataRegions() { + return DataRegions; + } + + data_region_iterator data_region_begin() { + return DataRegions.begin(); + } + const_data_region_iterator data_region_begin() const { + return DataRegions.begin(); + } + + data_region_iterator data_region_end() { + return DataRegions.end(); + } + const_data_region_iterator data_region_end() const { + return DataRegions.end(); + } + + size_t data_region_size() const { return DataRegions.size(); } + + /// @} /// @name Backend Data Access /// @{ diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index b586319193..59545d31a6 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -161,6 +161,10 @@ namespace llvm { /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); + /// getUniqueSymbolID() - Return a unique identifier for use in constructing + /// symbol names. + unsigned getUniqueSymbolID() { return NextUniqueID++; } + /// CreateDirectionalLocalSymbol - Create the definition of a directional /// local symbol for numbered label (used for "1:" definitions). MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h index 9180d1b369..0461766c2f 100644 --- a/include/llvm/MC/MCDirectives.h +++ b/include/llvm/MC/MCDirectives.h @@ -52,6 +52,14 @@ enum MCAssemblerFlag { MCAF_Code64 ///< .code64 (X86) }; +enum MCDataRegionType { + MCDR_DataRegion, ///< .data_region + MCDR_DataRegionJT8, ///< .data_region jt8 + MCDR_DataRegionJT16, ///< .data_region jt16 + MCDR_DataRegionJT32, ///< .data_region jt32 + MCDR_DataRegionEnd ///< .end_data_region +}; + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 9bb598f546..949d90700e 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -179,6 +179,9 @@ public: void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); + void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset, + uint32_t DataSize); + // FIXME: We really need to improve the relocation validation. Basically, we // want to implement a separate computation which evaluates the relocation // entry as the linker would, and verifies that the resultant fixup value is diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 25956008e0..44c5fefaa1 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -69,22 +69,7 @@ namespace llvm { SmallVector<std::pair<const MCSection *, const MCSection *>, 4> SectionStack; - unsigned UniqueCodeBeginSuffix; - unsigned UniqueDataBeginSuffix; - protected: - /// Indicator of whether the previous data-or-code indicator was for - /// code or not. Used to determine when we need to emit a new indicator. - enum DataType { - Data, - Code, - JumpTable8, - JumpTable16, - JumpTable32 - }; - DataType RegionIndicator; - - MCStreamer(MCContext &Ctx); const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, @@ -241,47 +226,15 @@ namespace llvm { /// used in an assignment. virtual void EmitLabel(MCSymbol *Symbol); - /// EmitDataRegion - Emit a label that marks the beginning of a data - /// region. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitDataRegion(); - - /// EmitJumpTable8Region - Emit a label that marks the beginning of a - /// jump table composed of 8-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable8Region(); - - /// EmitJumpTable16Region - Emit a label that marks the beginning of a - /// jump table composed of 16-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable16Region(); - - /// EmitJumpTable32Region - Emit a label that marks the beginning of a - /// jump table composed of 32-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable32Region(); - - /// EmitCodeRegion - Emit a label that marks the beginning of a code - /// region. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $a.1: - virtual void EmitCodeRegion(); - - /// ForceCodeRegion - Forcibly sets the current region mode to code. Used - /// at function entry points. - void ForceCodeRegion() { RegionIndicator = Code; } - - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// EmitAssemblerFlag - Note in the output the specified @p Flag + /// EmitAssemblerFlag - Note in the output the specified @p Flag. virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + /// EmitDataRegion - Note in the output the specified region @p Kind. + virtual void EmitDataRegion(MCDataRegionType Kind) {} + /// EmitThumbFunc - Note in the output that the specified @p Func is /// a Thumb mode function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func) = 0; diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index 089cde92a0..f30d431b69 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -97,7 +97,8 @@ namespace macho { DysymtabLoadCommandSize = 80, Nlist32Size = 12, Nlist64Size = 16, - RelocationInfoSize = 8 + RelocationInfoSize = 8, + LinkeditLoadCommandSize = 16 }; /// \brief Constants for header magic field. @@ -140,7 +141,8 @@ namespace macho { LCT_UUID = 0x1b, LCT_CodeSignature = 0x1d, LCT_SegmentSplitInfo = 0x1e, - LCT_FunctionStarts = 0x26 + LCT_FunctionStarts = 0x26, + LCT_DataInCode = 0x29 }; /// \brief Load command structure. @@ -280,6 +282,18 @@ namespace macho { }; /// @} + /// @name Data-in-code Table Entry + /// @{ + + // See <mach-o/loader.h>. + enum DataRegionType { Data = 1, JumpTable8, JumpTable16, JumpTable32 }; + struct DataInCodeTableEntry { + uint32_t Offset; /* from mach_header to start of data region */ + uint16_t Length; /* number of bytes in data region */ + uint16_t Kind; /* a DataRegionType value */ + }; + + /// @} /// @name Indirect Symbol Table /// @{ diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h index 0560402743..86f150a294 100644 --- a/include/llvm/Object/MachOObject.h +++ b/include/llvm/Object/MachOObject.h @@ -174,6 +174,9 @@ public: void ReadSymbol64TableEntry( uint64_t SymbolTableOffset, unsigned Index, InMemoryStruct<macho::Symbol64TableEntry> &Res) const; + void ReadDataInCodeTableEntry( + uint64_t TableOffset, unsigned Index, + InMemoryStruct<macho::DataInCodeTableEntry> &Res) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; /// @} diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index b0b2ff4882..ae498dd27d 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -475,10 +475,8 @@ void AsmPrinter::EmitFunctionHeader() { void AsmPrinter::EmitFunctionEntryLabel() { // The function label could have already been emitted if two symbols end up // conflicting due to asm renaming. Detect this and emit an error. - if (CurrentFnSym->isUndefined()) { - OutStreamer.ForceCodeRegion(); + if (CurrentFnSym->isUndefined()) return OutStreamer.EmitLabel(CurrentFnSym); - } report_fatal_error("'" + Twine(CurrentFnSym->getName()) + "' label emitted multiple times to assembly file"); @@ -1085,15 +1083,6 @@ void AsmPrinter::EmitJumpTableInfo() { EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData()))); - // If we know the form of the jump table, go ahead and tag it as such. - if (!JTInDiffSection) { - if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32) { - OutStreamer.EmitJumpTable32Region(); - } else { - OutStreamer.EmitDataRegion(); - } - } - for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 2456858ded..d9c1d51d18 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -50,6 +50,7 @@ MCAsmInfo::MCAsmInfo() { AllowNameToStartWithDigit = false; AllowPeriodsInName = true; AllowUTF8 = true; + UseDataRegionDirectives = false; ZeroDirective = "\t.zero\t"; AsciiDirective = "\t.ascii\t"; AscizDirective = "\t.asciz\t"; @@ -57,12 +58,6 @@ MCAsmInfo::MCAsmInfo() { Data16bitsDirective = "\t.short\t"; Data32bitsDirective = "\t.long\t"; Data64bitsDirective = "\t.quad\t"; - DataBegin = "$d."; - CodeBegin = "$a."; - JT8Begin = "$d."; - JT16Begin = "$d."; - JT32Begin = "$d."; - SupportsDataRegions = false; SunStyleELFSectionSwitchSyntax = false; UsesELFSectionDirectiveForBSS = false; AlignDirective = "\t.align\t"; diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 89413652ef..678e75af5d 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -36,8 +36,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { SupportsDebugInformation = true; DwarfSectionOffsetDirective = "\t.secrel32\t"; HasMicrosoftFastStdCallMangling = true; - - SupportsDataRegions = false; } void MCAsmInfoMicrosoft::anchor() { } diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index 4d675929e1..73ef7ba060 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -43,13 +43,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HasMachoTBSSDirective = true; // Uses .tbss HasStaticCtorDtorReferenceInStaticMode = true; - CodeBegin = "L$start$code$"; - DataBegin = "L$start$data$"; - JT8Begin = "L$start$jt8$"; - JT16Begin = "L$start$jt16$"; - JT32Begin = "L$start$jt32$"; - SupportsDataRegions = true; - // FIXME: Darwin 10 and newer don't need this. LinkerRequiresNonEmptyDwarfLines = true; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 3ce84c2cd9..9497b6be49 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -138,6 +138,7 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitDataRegion(MCDataRegionType Kind); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); @@ -352,6 +353,21 @@ void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { EmitEOL(); } +void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { + MCContext &Ctx = getContext(); + const MCAsmInfo &MAI = Ctx.getAsmInfo(); + if (!MAI.doesSupportDataRegionDirectives()) + return; + switch (Kind) { + case MCDR_DataRegion: OS << "\t.data_region"; break; + case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break; + case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break; + case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break; + case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break; + } + EmitEOL(); +} + void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { // This needs to emit to a temporary string to get properly quoted // MCSymbols when they have spaces in them. diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 6c4d0e33a1..6ac9d9d51c 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -13,6 +13,8 @@ #include "MCELF.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index bc6cf77321..970aa8baf4 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -1,4 +1,3 @@ -//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===// // // The LLVM Compiler Infrastructure // @@ -33,6 +32,8 @@ class MCMachOStreamer : public MCObjectStreamer { private: virtual void EmitInstToData(const MCInst &Inst); + void EmitDataRegion(DataRegionData::KindTy Kind); + void EmitDataRegionEnd(); public: MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter) @@ -46,6 +47,7 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitDataRegion(MCDataRegionType Kind); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); @@ -138,6 +140,26 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeMask); } +void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { + // Create a temporary label to mark the start of the data region. + MCSymbol *Start = getContext().CreateTempSymbol(); + EmitLabel(Start); + // Record the region for the object writer to use. + DataRegionData Data = { Kind, Start, NULL }; + std::vector<DataRegionData> &Regions = getAssembler().getDataRegions(); + Regions.push_back(Data); +} + +void MCMachOStreamer::EmitDataRegionEnd() { + std::vector<DataRegionData> &Regions = getAssembler().getDataRegions(); + assert(Regions.size() && "Mismatched .end_data_region!"); + DataRegionData &Data = Regions.back(); + assert(Data.End == NULL && "Mismatched .end_data_region!"); + // Create a temporary label to mark the end of the data region. + Data.End = getContext().CreateTempSymbol(); + EmitLabel(Data.End); +} + void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { // Let the target do whatever target specific stuff it needs to do. getAssembler().getBackend().handleAssemblerFlag(Flag); @@ -153,6 +175,26 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { } } +void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { + switch (Kind) { + case MCDR_DataRegion: + EmitDataRegion(DataRegionData::Data); + return; + case MCDR_DataRegionJT8: + EmitDataRegion(DataRegionData::JumpTable8); + return; + case MCDR_DataRegionJT16: + EmitDataRegion(DataRegionData::JumpTable16); + return; + case MCDR_DataRegionJT32: + EmitDataRegion(DataRegionData::JumpTable32); + return; + case MCDR_DataRegionEnd: + EmitDataRegionEnd(); + return; + } +} + void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { // Remember that the function is a thumb function. Fixup and relocation // values will need adjusted. diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 6f450682cb..5662fea86c 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -14,6 +14,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/MemoryBuffer.h" @@ -56,6 +57,9 @@ public: AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss"); AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegion>(".data_region"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegionEnd>(".end_data_region"); + // Special section directives. AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const"); AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>(".const_data"); @@ -113,6 +117,8 @@ public: bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); bool ParseDirectiveTBSS(StringRef, SMLoc); bool ParseDirectiveZerofill(StringRef, SMLoc); + bool ParseDirectiveDataRegion(StringRef, SMLoc); + bool ParseDirectiveDataRegionEnd(StringRef, SMLoc); // Named Section Directive bool ParseSectionDirectiveConst(StringRef, SMLoc) { @@ -659,6 +665,42 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { return false; } +/// ParseDirectiveDataRegion +/// ::= .data_region [ ( jt8 | jt16 | jt32 ) ] +bool DarwinAsmParser::ParseDirectiveDataRegion(StringRef, SMLoc) { + if (getLexer().is(AsmToken::EndOfStatement)) { + Lex(); + getStreamer().EmitDataRegion(MCDR_DataRegion); + return false; + } + StringRef RegionType; + SMLoc Loc = getParser().getTok().getLoc(); + if (getParser().ParseIdentifier(RegionType)) + return TokError("expected region type after '.data_region' directive"); + int Kind = StringSwitch<int>(RegionType) + .Case("jt8", MCDR_DataRegionJT8) + .Case("jt16", MCDR_DataRegionJT16) + .Case("jt32", MCDR_DataRegionJT32) + .Default(-1); + if (Kind == -1) + return Error(Loc, "unknown region type in '.data_region' directive"); + Lex(); + + getStreamer().EmitDataRegion((MCDataRegionType)Kind); + return false; +} + +/// ParseDirectiveDataRegionEnd +/// ::= .end_data_region +bool DarwinAsmParser::ParseDirectiveDataRegionEnd(StringRef, SMLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.end_data_region' directive"); + + Lex(); + getStreamer().EmitDataRegion(MCDR_DataRegionEnd); + return false; +} + namespace llvm { MCAsmParserExtension *createDarwinAsmParser() { diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 43e62ff89a..e363f28f77 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -20,12 +20,9 @@ #include <cstdlib> using namespace llvm; -MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), EmitEHFrame(true), - EmitDebugFrame(false), - CurrentW64UnwindInfo(0), - LastSymbol(0), - UniqueCodeBeginSuffix(0), - UniqueDataBeginSuffix(0) { +MCStreamer::MCStreamer(MCContext &Ctx) + : Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), + CurrentW64UnwindInfo(0), LastSymbol(0) { const MCSection *section = NULL; SectionStack.push_back(std::make_pair(section, section)); } @@ -183,85 +180,6 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol) { LastSymbol = Symbol; } -void MCStreamer::EmitDataRegion() { - if (RegionIndicator == Data) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = Context.GetOrCreateSymbol(MAI.getDataBeginLabelName() + - Twine(UniqueDataBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = Data; -} - -void MCStreamer::EmitCodeRegion() { - if (RegionIndicator == Code) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = Context.GetOrCreateSymbol(MAI.getCodeBeginLabelName() + - Twine(UniqueCodeBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = Code; -} - -void MCStreamer::EmitJumpTable8Region() { - if (RegionIndicator == JumpTable8) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = - Context.GetOrCreateSymbol(MAI.getJumpTable8BeginLabelName() + - Twine(UniqueDataBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = JumpTable8; -} - -void MCStreamer::EmitJumpTable16Region() { - if (RegionIndicator == JumpTable16) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = - Context.GetOrCreateSymbol(MAI.getJumpTable16BeginLabelName() + - Twine(UniqueDataBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = JumpTable16; -} - - -void MCStreamer::EmitJumpTable32Region() { - if (RegionIndicator == JumpTable32) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = - Context.GetOrCreateSymbol(MAI.getJumpTable32BeginLabelName() + - Twine(UniqueDataBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = JumpTable32; -} - void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); @@ -283,7 +201,6 @@ void MCStreamer::EmitCFIStartProc() { EmitCFIStartProcImpl(Frame); FrameInfos.push_back(Frame); - RegionIndicator = Code; } void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 8e4066c894..5820a224c5 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -21,6 +21,7 @@ #include "llvm/MC/MCMachOSymbolFlags.h" #include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include <vector> @@ -351,6 +352,21 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, Write32(Address); } +void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type, + uint32_t DataOffset, + uint32_t DataSize) { + uint64_t Start = OS.tell(); + (void) Start; + + Write32(Type); + Write32(macho::LinkeditLoadCommandSize); + Write32(DataOffset); + Write32(DataSize); |