From ff4bc460c52c1f285d8a56da173641bf92d49e3f Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 10 Aug 2009 01:39:42 +0000 Subject: [PATCH] Make the big switch: Change MCSectionMachO to represent a section *semantically* instead of syntactically as a string. This means that it keeps track of the segment, section, flags, etc directly and asmprints them in the right format. This also includes parsing and validation support for llvm-mc and "attribute(section)", so we should now start getting errors about invalid section attributes from the compiler instead of the assembler on darwin. Still todo: 1) Uniquing of darwin mcsections 2) Move all the Darwin stuff out to MCSectionMachO.[cpp|h] 3) there are a few FIXMEs, for example what is the syntax to get the S_GB_ZEROFILL segment type? git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78547 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCSection.h | 153 +++++++++- .../llvm/Target/TargetLoweringObjectFile.h | 27 +- lib/MC/MCAsmStreamer.cpp | 4 +- lib/MC/MCSection.cpp | 269 +++++++++++++++++- lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp | 29 +- .../PowerPC/AsmPrinter/PPCAsmPrinter.cpp | 58 ++-- lib/Target/TargetLoweringObjectFile.cpp | 174 +++++++---- .../X86/AsmPrinter/X86ATTAsmPrinter.cpp | 12 +- test/CodeGen/ARM/ctors_dtors.ll | 8 +- test/CodeGen/ARM/stubs.ll | 4 +- test/CodeGen/PowerPC/available-externally.ll | 4 +- test/CodeGen/X86/2009-01-27-NullStrings.ll | 39 +-- test/CodeGen/X86/global-sections.ll | 10 +- tools/llvm-mc/AsmLexer.cpp | 11 + tools/llvm-mc/AsmLexer.h | 3 + tools/llvm-mc/AsmParser.cpp | 188 ++++++------ tools/llvm-mc/AsmParser.h | 4 +- tools/llvm-mc/llvm-mc.cpp | 9 +- 18 files changed, 724 insertions(+), 282 deletions(-) diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index 4d505028db3..8216b6894a4 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -67,25 +67,154 @@ namespace llvm { raw_ostream &OS) const; }; + + /// MCSectionMachO - This represents a section on a Mach-O system (used by + /// Mac OS X). On a Mac system, these are also described in + /// /usr/include/mach-o/loader.h. class MCSectionMachO : public MCSection { - std::string Name; + char SegmentName[16]; // Not necessarily null terminated! + char SectionName[16]; // Not necessarily null terminated! - /// IsDirective - This is true if the section name is a directive, not - /// something that should be printed with ".section". - /// - /// FIXME: This is a hack. Switch to a semantic view of the section instead - /// of a syntactic one. - bool IsDirective; + /// TypeAndAttributes - This is the SECTION_TYPE and SECTION_ATTRIBUTES + /// field of a section, drawn from the enums below. + unsigned TypeAndAttributes; - MCSectionMachO(const StringRef &Name, bool IsDirective, SectionKind K, - MCContext &Ctx); + /// Reserved2 - The 'reserved2' field of a section, used to represent the + /// size of stubs, for example. + unsigned Reserved2; + + MCSectionMachO(const StringRef &Segment, const StringRef &Section, + unsigned TAA, unsigned reserved2, SectionKind K) + : MCSection(K), TypeAndAttributes(TAA), Reserved2(reserved2) { + assert(Segment.size() <= 16 && Section.size() <= 16 && + "Segment or section string too long"); + for (unsigned i = 0; i != 16; ++i) { + if (i < Segment.size()) + SegmentName[i] = Segment[i]; + else + SegmentName[i] = 0; + + if (i < Section.size()) + SectionName[i] = Section[i]; + else + SectionName[i] = 0; + } + } public: - static MCSectionMachO *Create(const StringRef &Name, bool IsDirective, + static MCSectionMachO *Create(const StringRef &Segment, + const StringRef &Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind K, MCContext &Ctx); + + /// These are the section type and attributes fields. A MachO section can + /// have only one Type, but can have any of the attributes specified. + enum { + // TypeAndAttributes bitmasks. + SECTION_TYPE = 0x000000FFU, + SECTION_ATTRIBUTES = 0xFFFFFF00U, + + // Valid section types. + + /// S_REGULAR - Regular section. + S_REGULAR = 0x00U, + /// S_ZEROFILL - Zero fill on demand section. + S_ZEROFILL = 0x01U, + /// S_CSTRING_LITERALS - Section with literal C strings. + S_CSTRING_LITERALS = 0x02U, + /// S_4BYTE_LITERALS - Section with 4 byte literals. + S_4BYTE_LITERALS = 0x03U, + /// S_8BYTE_LITERALS - Section with 8 byte literals. + S_8BYTE_LITERALS = 0x04U, + /// S_LITERAL_POINTERS - Section with pointers to literals. + S_LITERAL_POINTERS = 0x05U, + /// S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers. + S_NON_LAZY_SYMBOL_POINTERS = 0x06U, + /// S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers. + S_LAZY_SYMBOL_POINTERS = 0x07U, + /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in + /// the Reserved2 field. + S_SYMBOL_STUBS = 0x08U, + /// S_SYMBOL_STUBS - Section with only function pointers for + /// initialization. + S_MOD_INIT_FUNC_POINTERS = 0x09U, + /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for + /// termination. + S_MOD_TERM_FUNC_POINTERS = 0x0AU, + /// S_COALESCED - Section contains symbols that are to be coalesced. + S_COALESCED = 0x0BU, + /// S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 + /// gigabytes). + S_GB_ZEROFILL = 0x0CU, + /// S_INTERPOSING - Section with only pairs of function pointers for + /// interposing. + S_INTERPOSING = 0x0DU, + /// S_16BYTE_LITERALS - Section with only 16 byte literals. + S_16BYTE_LITERALS = 0x0EU, + /// S_DTRACE_DOF - Section contains DTrace Object Format. + S_DTRACE_DOF = 0x0FU, + /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to + /// lazy loaded dylibs. + S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10U, - const std::string &getName() const { return Name; } - bool isDirective() const { return IsDirective; } + LAST_KNOWN_SECTION_TYPE = S_LAZY_DYLIB_SYMBOL_POINTERS, + + + // Valid section attributes. + + /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine + /// instructions. + S_ATTR_PURE_INSTRUCTIONS = 1U << 31, + /// S_ATTR_NO_TOC - Section contains coalesced symbols that are not to be + /// in a ranlib table of contents. + S_ATTR_NO_TOC = 1U << 30, + /// S_ATTR_STRIP_STATIC_SYMS - Ok to strip static symbols in this section + /// in files with the MY_DYLDLINK flag. + S_ATTR_STRIP_STATIC_SYMS = 1U << 29, + /// S_ATTR_NO_DEAD_STRIP - No dead stripping. + S_ATTR_NO_DEAD_STRIP = 1U << 28, + /// S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks. + S_ATTR_LIVE_SUPPORT = 1U << 27, + /// S_ATTR_SELF_MODIFYING_CODE - Used with i386 code stubs written on by + /// dyld. + S_ATTR_SELF_MODIFYING_CODE = 1U << 26, + /// S_ATTR_DEBUG - A debug section. + S_ATTR_DEBUG = 1U << 25, + /// S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions. + S_ATTR_SOME_INSTRUCTIONS = 1U << 10, + /// S_ATTR_EXT_RELOC - Section has external relocation entries. + S_ATTR_EXT_RELOC = 1U << 9, + /// S_ATTR_LOC_RELOC - Section has local relocation entries. + S_ATTR_LOC_RELOC = 1U << 8 + }; + + StringRef getSegmentName() const { + // SegmentName is not necessarily null terminated! + if (SegmentName[15]) + return StringRef(SegmentName, 16); + return StringRef(SegmentName); + } + StringRef getSectionName() const { + // SectionName is not necessarily null terminated! + if (SectionName[15]) + return StringRef(SectionName, 16); + return StringRef(SectionName); + } + + unsigned getTypeAndAttributes() const { return TypeAndAttributes; } + + + /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". + /// This is a string that can appear after a .section directive in a mach-o + /// flavored .s file. If successful, this fills in the specified Out + /// parameters and returns an empty string. When an invalid section + /// specifier is present, this returns a string indicating the problem. + static std::string ParseSectionSpecifier(StringRef Spec, // In. + StringRef &Segment, // Out. + StringRef &Section, // Out. + unsigned &TAA, // Out. + unsigned &StubSize); // Out. virtual void PrintSwitchToSection(const TargetAsmInfo &TAI, raw_ostream &OS) const; diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 0b6fd30a312..2ca196340d9 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -257,9 +257,30 @@ public: Mangler *) const; /// getMachOSection - Return the MCSection for the specified mach-o section. - /// FIXME: Switch this to a semantic view eventually. - const MCSection *getMachOSection(const char *Name, bool isDirective, - SectionKind K) const; + /// This requires the operands to be valid. + const MCSection *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + SectionKind K) const { + return getMachOSection(Segment, Section, TypeAndAttributes, 0, K); + } + const MCSection *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind K) const; + + /// getTextCoalSection - Return the "__TEXT,__textcoal_nt" section we put weak + /// symbols into. + const MCSection *getTextCoalSection() const { + return TextCoalSection; + } + + /// getLazySymbolPointerSection - Return the section corresponding to + /// the .lazy_symbol_pointer directive. + const MCSection *getLazySymbolPointerSection() const; + + /// getNonLazySymbolPointerSection - Return the section corresponding to + /// the .non_lazy_symbol_pointer directive. + const MCSection *getNonLazySymbolPointerSection() const; + }; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 0aed948d30d..7dcca7bd5c5 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -222,7 +222,9 @@ void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, OS << ".zerofill "; // This is a mach-o specific directive. - OS << '"' << ((MCSectionMachO*)Section)->getName() << '"'; + const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); + OS << '"' << MOSection->getSegmentName() << "," + << MOSection->getSectionName() << '"'; if (Symbol != NULL) { diff --git a/lib/MC/MCSection.cpp b/lib/MC/MCSection.cpp index 65e86d3b408..291e40d1f45 100644 --- a/lib/MC/MCSection.cpp +++ b/lib/MC/MCSection.cpp @@ -115,25 +115,272 @@ void MCSectionELF::PrintSwitchToSection(const TargetAsmInfo &TAI, // MCSectionMachO //===----------------------------------------------------------------------===// -MCSectionMachO *MCSectionMachO:: -Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) { - return new (Ctx) MCSectionMachO(Name, IsDirective, K, Ctx); -} +/// SectionTypeDescriptors - These are strings that describe the various section +/// types. This *must* be kept in order with and stay synchronized with the +/// section type list. +static const struct { + const char *AssemblerName, *EnumName; +} SectionTypeDescriptors[MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1] = { + { "regular", "S_REGULAR" }, // 0x00 + { 0, "S_ZEROFILL" }, // 0x01 + { "cstring_literals", "S_CSTRING_LITERALS" }, // 0x02 + { "4byte_literals", "S_4BYTE_LITERALS" }, // 0x03 + { "8byte_literals", "S_8BYTE_LITERALS" }, // 0x04 + { "literal_pointers", "S_LITERAL_POINTERS" }, // 0x05 + { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" }, // 0x06 + { "lazy_symbol_pointers", "S_LAZY_SYMBOL_POINTERS" }, // 0x07 + { "symbol_stubs", "S_SYMBOL_STUBS" }, // 0x08 + { "mod_init_funcs", "S_MOD_INIT_FUNC_POINTERS" }, // 0x09 + { "mod_term_funcs", "S_MOD_TERM_FUNC_POINTERS" }, // 0x0A + { "coalesced", "S_COALESCED" }, // 0x0B + { 0, /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C + { "interposing", "S_INTERPOSING" }, // 0x0D + { "16byte_literals", "S_16BYTE_LITERALS" }, // 0x0E + { 0, /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F + { 0, /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" } // 0x10 +}; -MCSectionMachO::MCSectionMachO(const StringRef &name, bool isDirective, - SectionKind K, MCContext &Ctx) - : MCSection(K), Name(name), IsDirective(isDirective) { - Ctx.SetSection(Name, this); + +/// SectionAttrDescriptors - This is an array of descriptors for section +/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed +/// by attribute, instead it is searched. The last entry has a zero AttrFlag +/// value. +static const struct { + unsigned AttrFlag; + const char *AssemblerName, *EnumName; +} SectionAttrDescriptors[] = { +#define ENTRY(ASMNAME, ENUM) \ + { MCSectionMachO::ENUM, ASMNAME, #ENUM }, +ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS) +ENTRY("no_toc", S_ATTR_NO_TOC) +ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS) +ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP) +ENTRY("live_support", S_ATTR_LIVE_SUPPORT) +ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE) +ENTRY("debug", S_ATTR_DEBUG) +ENTRY(0 /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) +ENTRY(0 /*FIXME*/, S_ATTR_EXT_RELOC) +ENTRY(0 /*FIXME*/, S_ATTR_LOC_RELOC) +#undef ENTRY + { 0, "none", 0 } +}; + + +MCSectionMachO *MCSectionMachO:: +Create(const StringRef &Segment, const StringRef &Section, + unsigned TypeAndAttributes, unsigned Reserved2, + SectionKind K, MCContext &Ctx) { + // S_SYMBOL_STUBS must be set for Reserved2 to be non-zero. + return new (Ctx) MCSectionMachO(Segment, Section, TypeAndAttributes, + Reserved2, K); } void MCSectionMachO::PrintSwitchToSection(const TargetAsmInfo &TAI, raw_ostream &OS) const { - if (!isDirective()) - OS << "\t.section\t" << getName() << '\n'; + OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); + + // Get the section type and attributes. + unsigned TAA = getTypeAndAttributes(); + if (TAA == 0) { + OS << '\n'; + return; + } + + OS << ','; + + unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE; + assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE && + "Invalid SectionType specified!"); + + if (SectionTypeDescriptors[SectionType].AssemblerName) + OS << SectionTypeDescriptors[SectionType].AssemblerName; else - OS << getName() << '\n'; + OS << "<<" << SectionTypeDescriptors[SectionType].EnumName << ">>"; + + // If we don't have any attributes, we're done. + unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES; + if (SectionAttrs == 0) { + // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as + // the attribute specifier. + if (Reserved2 != 0) + OS << ",none," << Reserved2; + OS << '\n'; + return; + } + + // Check each attribute to see if we have it. + char Separator = ','; + for (unsigned i = 0; SectionAttrDescriptors[i].AttrFlag; ++i) { + // Check to see if we have this attribute. + if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0) + continue; + + // Yep, clear it and print it. + SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag; + + OS << Separator; + if (SectionAttrDescriptors[i].AssemblerName) + OS << SectionAttrDescriptors[i].AssemblerName; + else + OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>"; + Separator = '+'; + } + + assert(SectionAttrs == 0 && "Unknown section attributes!"); + + // If we have a S_SYMBOL_STUBS size specified, print it. + if (Reserved2 != 0) + OS << ',' << Reserved2; + OS << '\n'; } +/// StripSpaces - This removes leading and trailing spaces from the StringRef. +static void StripSpaces(StringRef &Str) { + while (!Str.empty() && isspace(Str[0])) + Str = Str.substr(1); + while (!Str.empty() && isspace(Str.back())) + Str = Str.substr(0, Str.size()-1); +} + +/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". +/// This is a string that can appear after a .section directive in a mach-o +/// flavored .s file. If successful, this fills in the specified Out +/// parameters and returns an empty string. When an invalid section +/// specifier is present, this returns a string indicating the problem. +std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. + StringRef &Segment, // Out. + StringRef &Section, // Out. + unsigned &TAA, // Out. + unsigned &StubSize) { // Out. + // Find the first comma. + std::pair Comma = Spec.split(','); + + // If there is no comma, we fail. + if (Comma.second.empty()) + return "mach-o section specifier requires a segment and section " + "separated by a comma"; + + // Capture segment, remove leading and trailing whitespace. + Segment = Comma.first; + StripSpaces(Segment); + + // Verify that the segment is present and not too long. + if (Segment.empty() || Segment.size() > 16) + return "mach-o section specifier requires a segment whose length is " + "between 1 and 16 characters"; + + // Split the section name off from any attributes if present. + Comma = Comma.second.split(','); + + // Capture section, remove leading and trailing whitespace. + Section = Comma.first; + StripSpaces(Section); + + // Verify that the section is present and not too long. + if (Section.empty() || Section.size() > 16) + return "mach-o section specifier requires a section whose length is " + "between 1 and 16 characters"; + + // If there is no comma after the section, we're done. + TAA = 0; + StubSize = 0; + if (Comma.second.empty()) + return ""; + + // Otherwise, we need to parse the section type and attributes. + Comma = Comma.second.split(','); + + // Get the section type. + StringRef SectionType = Comma.first; + StripSpaces(SectionType); + + // Figure out which section type it is. + unsigned TypeID; + for (TypeID = 0; TypeID !=MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1; ++TypeID) + if (SectionTypeDescriptors[TypeID].AssemblerName && + SectionType == SectionTypeDescriptors[TypeID].AssemblerName) + break; + + // If we didn't find the section type, reject it. + if (TypeID > MCSectionMachO::LAST_KNOWN_SECTION_TYPE) + return "mach-o section specifier uses an unknown section type"; + + // Remember the TypeID. + TAA = TypeID; + + // If we have no comma after the section type, there are no attributes. + if (Comma.second.empty()) { + // S_SYMBOL_STUBS always require a symbol stub size specifier. + if (TAA == MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier of type 'symbol_stubs' requires a size " + "specifier"; + return ""; + } + + // Otherwise, we do have some attributes. Split off the size specifier if + // present. + Comma = Comma.second.split(','); + StringRef Attrs = Comma.first; + + // The attribute list is a '+' separated list of attributes. + std::pair Plus = Attrs.split('+'); + + while (1) { + StringRef Attr = Plus.first; + StripSpaces(Attr); + + // Look up the attribute. + for (unsigned i = 0; ; ++i) { + if (SectionAttrDescriptors[i].AttrFlag == 0) + return "mach-o section specifier has invalid attribute"; + + if (SectionAttrDescriptors[i].AssemblerName && + Attr == SectionAttrDescriptors[i].AssemblerName) { + TAA |= SectionAttrDescriptors[i].AttrFlag; + break; + } + } + + if (Plus.second.empty()) break; + Plus = Plus.second.split('+'); + }; + + // Okay, we've parsed the section attributes, see if we have a stub size spec. + if (Comma.second.empty()) { + // S_SYMBOL_STUBS always require a symbol stub size specifier. + if (TAA == MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier of type 'symbol_stubs' requires a size " + "specifier"; + return ""; + } + + // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS. + if ((TAA & MCSectionMachO::SECTION_TYPE) != MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier cannot have a stub size specified because " + "it does not have type 'symbol_stubs'"; + + // Okay, if we do, it must be a number. + StringRef StubSizeStr = Comma.second; + StripSpaces(StubSizeStr); + + // Convert the a null terminated buffer for strtoul. + char TmpBuffer[32]; + if (StubSizeStr.size() >= 32) + return"mach-o section specifier has a stub size specifier that is too long"; + + memcpy(TmpBuffer, StubSizeStr.data(), StubSizeStr.size()); + TmpBuffer[StubSizeStr.size()] = 0; + + char *EndPtr; + StubSize = strtoul(TmpBuffer, &EndPtr, 0); + + if (EndPtr[0] != 0) + return "mach-o section specifier has a malformed stub size"; + + return ""; +} + + //===----------------------------------------------------------------------===// // MCSectionCOFF //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index ca61d55b81c..9f7993865d2 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -1286,19 +1286,21 @@ bool ARMAsmPrinter::doFinalization(Module &M) { O << '\n'; if (!FnStubs.empty()) { - const MCSection *StubSection; - if (TM.getRelocationModel() == Reloc::PIC_) - StubSection = TLOFMacho.getMachOSection(".section __TEXT,__picsymbolstu" - "b4,symbol_stubs,none,16", true, - SectionKind::getText()); - else - StubSection = TLOFMacho.getMachOSection(".section __TEXT,__symbol_stub4" - ",symbol_stubs,none,12", true, - SectionKind::getText()); + unsigned StubSize = 12; + const char *StubSectionName = "__symbol_stub4"; + + if (TM.getRelocationModel() == Reloc::PIC_) { + StubSize = 16; + StubSectionName = "__picsymbolstub4"; + } + + const MCSection *StubSection + = TLOFMacho.getMachOSection("__TEXT", StubSectionName, + MCSectionMachO::S_SYMBOL_STUBS, + StubSize, SectionKind::getText()); const MCSection *LazySymbolPointerSection - = TLOFMacho.getMachOSection(".lazy_symbol_pointer", true, - SectionKind::getMetadata()); + = TLOFMacho.getLazySymbolPointerSection(); // Output stubs for dynamically-linked functions for (StringMap::iterator I = FnStubs.begin(), @@ -1333,9 +1335,8 @@ bool ARMAsmPrinter::doFinalization(Module &M) { // Output non-lazy-pointers for external and common global variables. if (!GVNonLazyPtrs.empty()) { - SwitchToSection(TLOFMacho.getMachOSection(".non_lazy_symbol_pointer", - true, - SectionKind::getMetadata())); + // Switch with ".non_lazy_symbol_pointer" directive. + SwitchToSection(TLOFMacho.getNonLazySymbolPointerSection()); for (StringMap::iterator I = GVNonLazyPtrs.begin(), E = GVNonLazyPtrs.end(); I != E; ++I) { O << I->second << ":\n"; diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp index 9884ca32bfa..73c9c03854b 100644 --- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -846,22 +846,19 @@ bool PPCDarwinAsmPrinter::doInitialization(Module &M) { // Prime text sections so they are adjacent. This reduces the likelihood a // large data or debug section causes a branch to exceed 16M limit. - TargetLoweringObjectFileMachO &TLOFMacho = static_cast(getObjFileLowering()); - SwitchToSection(TLOFMacho.getMachOSection("\t.section __TEXT,__textcoal_nt," - "coalesced,pure_instructions", true, - SectionKind::getText())); + SwitchToSection(TLOFMacho.getTextCoalSection()); if (TM.getRelocationModel() == Reloc::PIC_) { - SwitchToSection(TLOFMacho.getMachOSection("\t.section __TEXT,__picsymbolstu" - "b1,symbol_stubs," - "pure_instructions,32", true, - SectionKind::getText())); + SwitchToSection(TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 32, SectionKind::getText())); } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { - SwitchToSection(TLOFMacho.getMachOSection("\t.section __TEXT,__symbol_stub1" - ",symbol_stubs," - "pure_instructions,16", true, - SectionKind::getText())); + SwitchToSection(TLOFMacho.getMachOSection("__TEXT","__symbol_stub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 16, SectionKind::getText())); } SwitchToSection(getObjFileLowering().getTextSection()); @@ -985,17 +982,20 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { TargetLoweringObjectFileMachO &TLOFMacho = static_cast(getObjFileLowering()); + + const MCSection *LSPSection = 0; + if (!FnStubs.empty()) // .lazy_symbol_pointer + LSPSection = TLOFMacho.getLazySymbolPointerSection(); + + // Output stubs for dynamically-linked functions if (TM.getRelocationModel() == Reloc::PIC_ && !FnStubs.empty()) { const MCSection *StubSection = - TLOFMacho.getMachOSection("\t.section __TEXT,__picsymbolstub1," - "symbol_stubs,pure_instructions,32", true, - SectionKind::getText()); - const MCSection *LSPSection = - TLOFMacho.getMachOSection(".lazy_symbol_pointer", true, - SectionKind::getMetadata()); - - for (StringMap::iterator I = FnStubs.begin(), E = FnStubs.end(); + TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 32, SectionKind::getText()); + for (StringMap::iterator I = FnStubs.begin(), E = FnStubs.end(); I != E; ++I) { SwitchToSection(StubSection); EmitAlignment(4); @@ -1020,13 +1020,11 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n"; } } else if (!FnStubs.empty()) { - const MCSection *StubSection = - TLOFMacho.getMachOSection("\t.section __TEXT,__symbol_stub1,symbol_stubs," - "pure_instructions,16", true, - SectionKind::getText()); - const MCSection *LSPSection = - TLOFMacho.getMachOSection(".lazy_symbol_pointer", true, - SectionKind::getMetadata()); + const MCSection *StubSection = + TLOFMacho.getMachOSection("__TEXT","__symbol_stub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 16, SectionKind::getText()); for (StringMap::iterator I = FnStubs.begin(), E = FnStubs.end(); I != E; ++I) { @@ -1063,10 +1061,8 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { // Output macho stubs for external and common global variables. if (!GVStubs.empty()) { - const MCSection *TheSection = - TLOFMacho.getMachOSection(".non_lazy_symbol_pointer", true, - SectionKind::getMetadata()); - SwitchToSection(TheSection); + // Switch with ".non_lazy_symbol_pointer" directive. + SwitchToSection(TLOFMacho.getNonLazySymbolPointerSection()); for (StringMap::iterator I = GVStubs.begin(), E = GVStubs.end(); I != E; ++I) { O << I->second << ":\n"; diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index e41e7a958c6..2cde7d9a9ef 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -510,118 +510,176 @@ getSectionForConstant(SectionKind Kind) const { const MCSection *TargetLoweringObjectFileMachO:: -getMachOSection(const char *Name, bool isDirective, SectionKind Kind) const { - if (MCSection *S = getContext().GetSection(Name)) - return S; - return MCSectionMachO::Create(Name, isDirective, Kind, getContext()); +getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind Kind) const { + // FIXME: UNIQUE HERE. + //if (MCSection *S = getContext().GetSection(Name)) + // return S; + + return MCSectionMachO::Create(Segment, Section, TypeAndAttributes, Reserved2, + Kind, getContext()); } - void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, const TargetMachine &TM) { TargetLoweringObjectFile::Initialize(Ctx, TM); - TextSection = getMachOSection("\t.text", true, SectionKind::getText()); - DataSection = getMachOSection("\t.data", true, SectionKind::getDataRel()); - CStringSection = getMachOSection("\t.cstring", true, - SectionKind::getMergeable1ByteCString()); - UStringSection = getMachOSection("__TEXT,__ustring", false, - SectionKind::getMergeable2ByteCString()); - FourByteConstantSection = getMachOSection("\t.literal4\n", true, - SectionKind::getMergeableConst4()); - EightByteConstantSection = getMachOSection("\t.literal8\n", true, - SectionKind::getMergeableConst8()); + TextSection // .text + = getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + DataSection // .data + = getMachOSection("__DATA", "__data", 0, SectionKind::getDataRel()); + + CStringSection // .cstring + = getMachOSection("__TEXT", "__cstring", MCSectionMachO::S_CSTRING_LITERALS, + SectionKind::getMergeable1ByteCString()); + UStringSection + = getMachOSection("__TEXT","__ustring", 0, + SectionKind::getMergeable2ByteCString()); + FourByteConstantSection // .literal4 + = getMachOSection("__TEXT", "__literal4", MCSectionMachO::S_4BYTE_LITERALS, + SectionKind::getMergeableConst4()); + EightByteConstantSection // .literal8 + = getMachOSection("__TEXT", "__literal8", MCSectionMachO::S_8BYTE_LITERALS, + SectionKind::getMergeableConst8()); // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back // to using it in -static mode. + SixteenByteConstantSection = 0; if (TM.getRelocationModel() != Reloc::Static && TM.getTargetData()->getPointerSize() == 32) - SixteenByteConstantSection = - getMachOSection("\t.literal16\n", true, + SixteenByteConstantSection = // .literal16 + getMachOSection("__TEXT", "__literal16",MCSectionMachO::S_16BYTE_LITERALS, SectionKind::getMergeableConst16()); - else - SixteenByteConstantSection = 0; - ReadOnlySection = getMachOSection("\t.const", true, - SectionKind::getReadOnly()); + ReadOnlySection // .const + = getMachOSection("__TEXT", "__const", 0, SectionKind::getReadOnly()); - TextCoalSection = - getMachOSection("\t__TEXT,__textcoal_nt,coalesced,pure_instructions", - false, SectionKind::getText()); - ConstTextCoalSection = getMachOSection("\t__TEXT,__const_coal,coalesced", - false, SectionKind::getText()); - ConstDataCoalSection = getMachOSection("\t__DATA,__const_coal,coalesced", - false, SectionKind::getText()); - ConstDataSection = getMachOSection("\t.const_data", true, - SectionKind::getReadOnlyWithRel()); - DataCoalSection = getMachOSection("\t__DATA,__datacoal_nt,coalesced", - false, SectionKind::getDataRel()); + TextCoalSection + = getMachOSection("__TEXT", "__textcoal_nt", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + ConstTextCoalSection + = getMachOSection("__TEXT", "__const_coal", MCSectionMachO::S_COALESCED, + SectionKind::getText()); + ConstDataCoalSection + = getMachOSection("__DATA","__const_coal", MCSectionMachO::S_COALESCED, + SectionKind::getText()); + ConstDataSection // .const_data + = getMachOSection("__DATA", "__const", 0, + SectionKind::getReadOnlyWithRel()); + DataCoalSection + = getMachOSection("__DATA","__datacoal_nt", MCSectionMachO::S_COALESCED, + SectionKind::getDataRel()); if (TM.getRelocationModel() == Reloc::Static) { - StaticCtorSection = - getMachOSection(".constructor", true, SectionKind::getDataRel()); - StaticDtorSection = - getMachOSection(".destructor", true, SectionKind::getDataRel()); + StaticCtorSection + = getMachOSection("__TEXT", "__constructor", 0,SectionKind::getDataRel()); + StaticDtorSection + = getMachOSection("__TEXT", "__destructor", 0, SectionKind::getDataRel()); } else { - StaticCtorSection = - getMachOSection(".mod_init_func", true, SectionKind::getDataRel()); - StaticDtorSection = - getMachOSection(".mod_term_func", true, SectionKind::getDataRel()); + StaticCtorSection + = getMachOSection("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, + SectionKind::getDataRel()); + StaticDtorSection + = getMachOSection("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, + SectionKind::getDataRel()); } // Exception Handling. - LSDASection = getMachOSection("__DATA,__gcc_except_tab", false, + LSDASection = getMachOSection("__DATA", "__gcc_except_tab", 0, SectionKind::getDataRel()); EHFrameSection = - getMachOSection("__TEXT,__eh_frame,coalesced,no_toc+strip_static_syms" - "+live_support", false, SectionKind::getReadOnly()); + getMachOSection("__TEXT", "__eh_frame", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_NO_TOC | + MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | + MCSectionMachO::S_ATTR_LIVE_SUPPORT, + SectionKind::getReadOnly()); // Debug Information. - // FIXME: Don't use 'directive' syntax: need flags for debug/regular?? - // FIXME: Need __DWARF segment. DwarfAbbrevSection = - getMachOSection(".section __DWARF,__debug_abbrev,regular,debug", true, + getMachOSection("__DWARF", "__debug_abbrev", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfInfoSection = - getMachOSection(".section __DWARF,__debug_info,regular,debug", true, + getMachOSection("__DWARF", "__debug_info", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfLineSection = - getMachOSection(".section __DWARF,__debug_line,regular,debug", true, + getMachOSection("__DWARF", "__debug_line", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfFrameSection = - getMachOSection(".section __DWARF,__debug_frame,regular,debug", true, + getMachOSection("__DWARF", "__debug_frame", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfPubNamesSection = - getMachOSection(".section __DWARF,__debug_pubnames,regular,debug", true, + getMachOSection("__DWARF", "__debug_pubnames", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfPubTypesSection = - getMachOSection(".section __DWARF,__debug_pubtypes,regular,debug", true, + getMachOSection("__DWARF", "__debug_pubtypes", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfStrSection = - getMachOSection(".section __DWARF,__debug_str,regular,debug", true, + getMachOSection("__DWARF", "__debug_str", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfLocSection = - getMachOSection(".section __DWARF,__debug_loc,regular,debug", true, + getMachOSection("__DWARF", "__debug_loc", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfARangesSection = - getMachOSection(".section __DWARF,__debug_aranges,regular,debug", true, + getMachOSection("__DWARF", "__debug_aranges", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfRangesSection = - getMachOSection(".section __DWARF,__debug_ranges,regular,debug", true, + getMachOSection("__DWARF", "__debug_ranges", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfMacroInfoSection = - getMachOSection(".section __DWARF,__debug_macinfo,regular,debug", true, + getMachOSection("__DWARF", "__debug_macinfo", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfDebugInlineSection = - getMachOSection(".section __DWARF,__debug_inlined,regular,debug", true, + getMachOSection("__DWARF", "__debug_inlined", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); } +/// getLazySymbolPointerSection - Return the section corresponding to +/// the .lazy_symbol_pointer directive. +const MCSection *TargetLoweringObjectFileMachO:: +getLazySymbolPointerSection() const { + return getMachOSection("__DATA", "__la_symbol_ptr", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); +} + +/// getNonLazySymbolPointerSection - Return the section corresponding to +/// the .non_lazy_symbol_pointer directive. +const MCSection *TargetLoweringObjectFileMachO:: +getNonLazySymbolPointerSection() const { + return getMachOSection("__DATA", "__nl_symbol_ptr", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); +} + + const MCSection *TargetLoweringObjectFileMachO:: getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { - return getMachOSection(GV->getSection().c_str(), false, Kind); + // Parse the section specifier and create it if valid. + StringRef Segment, Section; + unsigned TAA, StubSize; + std::string ErrorCode = + MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section, + TAA, StubSize); + if (ErrorCode.empty()) + return getMachOSection(Segment, Section, TAA, StubSize, Kind); + + + // If invalid, report the error with llvm_report_error. + llvm_report_error("Global variable '" + GV->getNameStr() + + "' has an invalid section specifier '" + GV->getSection() + + "': " + ErrorCode + "."); + // Fall back to dropping it into the data section. + return DataSection; } const MCSection *TargetLoweringObjectFileMachO:: diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp index 59cff0fc591..ae0e599edfb 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp @@ -918,9 +918,11 @@ bool X86ATTAsmPrinter::doFinalization(Module &M) { // Output stubs for dynamically-linked functions if (!FnStubs.empty()) { const MCSection *TheSection = - TLOFMacho.getMachOSection("\t.section __IMPORT,__jump_table,symbol_stubs," - "self_modifying_code+pure_instructions,5", true, - SectionKind::getMetadata()); + TLOFMacho.getMachOSection("__IMPORT", "__jump_table", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_SELF_MODIFYING_CODE | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 5, SectionKind::getMetadata()); SwitchToSection(TheSection); for (StringMap::iterator I = FnStubs.begin(), E = FnStubs.end(); I != E; ++I) @@ -932,8 +934,8 @@ bool X86ATTAsmPrinter::doFinalization(Module &M) { // Output stubs for external and common global variables. if (!GVStubs.empty()) { const MCSection *TheSection = - TLOFMacho.getMachOSection("\t.section __IMPORT,__pointers," - "non_lazy_symbol_pointers", true, + TLOFMacho.getMachOSection("__IMPORT", "__pointers", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, SectionKind::getMetadata()); SwitchToSection(TheSection); for (StringMap::iterator I = GVStubs.begin(), diff --git a/test/CodeGen/ARM/ctors_dtors.ll b/test/CodeGen/ARM/ctors_dtors.ll index 8ed98d9c558..714ca612638 100644 --- a/test/CodeGen/ARM/ctors_dtors.ll +++ b/test/CodeGen/ARM/ctors_dtors.ll @@ -1,9 +1,9 @@ -; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | FileCheck %s -check-prefix=DARWIN -; RUN: llvm-as < %s | llc -mtriple=arm-linux-gnu | FileCheck %s -check-prefix=ELF +; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | FileCheck %s -check-prefix=DARWIN +; RUN: llvm-as < %s | llc -mtriple=arm-linux-gnu | FileCheck %s -check-prefix=ELF ; RUN: llvm-as < %s | llc -mtriple=arm-linux-gnueabi | FileCheck %s -check-prefix=GNUEABI -; DARWIN: .mod_init_func -; DARWIN: .mod_term_func +; DARWIN: .section __DATA,__mod_init_func,mod_init_funcs +; DARWIN: .section __DATA,__mod_term_func,mod_term_funcs ; ELF: .section .ctors,"aw",%progbits ; ELF: .section .dtors,"aw",%progbits diff --git a/test/CodeGen/ARM/stubs.ll b/test/CodeGen/ARM/stubs.ll index 7c9cc239f06..baf6b7e63a1 100644 --- a/test/CodeGen/ARM/stubs.ll +++ b/test/CodeGen/ARM/stubs.ll @@ -39,7 +39,7 @@ define available_externally i32 @exact_log2(i64 %x) nounwind { ; PIC: L_exact_log2$slp: ; PIC: .long L_exact_log2$lazy_ptr-(L_exact_log2$scv+8) -; PIC: .lazy_symbol_pointer +; PIC: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers ; PIC: L_exact_log2$lazy_ptr: ; PIC: .indirect_symbol _exact_log2 ; PIC: .long dyld_stub_binding_helper @@ -55,7 +55,7 @@ define available_externally i32 @exact_log2(i64 %x) nounwind { ; DYNAMIC: L_exact_log2$slp: ; DYNAMIC: .long L_exact_log2$lazy_ptr -; DYNAMIC: .lazy_symbol_pointer +; DYNAMIC: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers ; DYNAMIC: L_exact_log2$lazy_ptr: ; DYNAMIC: .indirect_symbol _exact_log2 ; DYNAMIC: .long dyld_stub_binding_helper diff --git a/test/CodeGen/PowerPC/available-externally.ll b/test/CodeGen/PowerPC/available-externally.ll index e78d6a070d8..6c065293016 100644 --- a/test/CodeGen/PowerPC/available-externally.ll +++ b/test/CodeGen/PowerPC/available-externally.ll @@ -44,7 +44,7 @@ entry: ; PIC: mtctr r12 ; PIC: bctr -; PIC: .lazy_symbol_pointer +; PIC: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers ; PIC: L_exact_log2$lazy_ptr: ; PIC: .indirect_symbol _exact_log2 ; PIC: .long dyld_stub_binding_helper @@ -60,7 +60,7 @@ entry: ; DYNAMIC: mtctr r12 ; DYNAMIC: bctr -; DYNAMIC: .lazy_symbol_pointer +; DYNAMIC: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers ; DYNAMIC: L_exact_log2$lazy_ptr: ; DYNAMIC: .indirect_symbol _exact_log2 ; DYNAMIC: .long dyld_stub_binding_helper diff --git a/test/CodeGen/X86/2009-01-27-NullStrings.ll b/test/CodeGen/X86/2009-01-27-NullStrings.ll index b0c27d8903e..229d726b5cf 100644 --- a/test/CodeGen/X86/2009-01-27-NullStrings.ll +++ b/test/CodeGen/X86/2009-01-27-NullStrings.ll @@ -1,38 +1,7 @@ -; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin | grep {\\.cstring} | count 1 - %struct.A = type { } - %struct.NSString = type opaque - %struct.__builtin_CFString = type { i32*, i32, i8*, i32 } - %struct._objc_module = type { i32, i32, i8*, %struct._objc_symtab* } - %struct._objc_symtab = type { i32, %struct.objc_selector**, i16, i16 } - %struct.objc_object = type opaque - %struct.objc_selector = type opaque -@"\01L_unnamed_cfstring_0" = internal constant %struct.__builtin_CFString { i32* getelementptr ([0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr ([1 x i8]* @"\01LC", i32 0, i32 0), i32 0 }, section "__DATA, __cfstring" ; <%struct.__builtin_CFString*> [#uses=1] -@__CFConstantStringClassReference = external global [0 x i32] ; <[0 x i32]*> [#uses=1] -@"\01LC" = internal constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1] -@"\01L_OBJC_SELECTOR_REFERENCES_0" = internal global %struct.objc_selector* bitcast ([6 x i8]* @"\01L_OBJC_METH_VAR_NAME_0" to %struct.objc_selector*), section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4 ; <%struct.objc_selector**> [#uses=2] -@"\01L_OBJC_SYMBOLS" = internal global %struct._objc_symtab zeroinitializer, section "__OBJC,__symbols,regular,no_dead_strip", align 4 ; <%struct._objc_symtab*> [#uses=2] -@"\01L_OBJC_METH_VAR_NAME_0" = internal global [6 x i8] c"bork:\00", section "__TEXT,__cstring,cstring_literals", align 1 ; <[6 x i8]*> [#uses=2] -@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] zeroinitializer, section "__OBJC, __image_info,regular" ; <[2 x i32]*> [#uses=1] -@"\01L_OBJC_CLASS_NAME_0" = internal global [1 x i8] zeroinitializer, section "__TEXT,__cstring,cstring_literals", align 1 ; <[1 x i8]*> [#uses=1] -@"\01L_OBJC_MODULES" = internal global %struct._objc_module { i32 7, i32 16, i8* getelementptr ([1 x i8]* @"\01L_OBJC_CLASS_NAME_0", i32 0, i32 0), %struct._objc_symtab* @"\01L_OBJC_SYMBOLS" }, section "__OBJC,__module_info,regular,no_dead_strip", align 4 ; <%struct._objc_module*> [#uses=1] -@llvm.used = appending global [6 x i8*] [ i8* bitcast (%struct.objc_selector** @"\01L_OBJC_SELECTOR_REFERENCES_0" to i8*), i8* bitcast (%struct._objc_symtab* @"\01L_OBJC_SYMBOLS" to i8*), i8* getelementptr ([6 x i8]* @"\01L_OBJC_METH_VAR_NAME_0", i32 0, i32 0), i8* bitcast ([2 x i32]* @"\01L_OBJC_IMAGE_INFO" to i8*), i8* getelementptr ([1 x i8]* @"\01L_OBJC_CLASS_NAME_0", i32 0, i32 0), i8* bitcast (%struct._objc_module* @"\01L_OBJC_MODULES" to i8*) ], section "llvm.metadata" ; <[6 x i8*]*> [#uses=0] +; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin | FileCheck %s +; CHECK: .section __TEXT,__cstring,cstring_literals -define void @func(%struct.A* %a) nounwind { -entry: - %a_addr = alloca %struct.A* ; <%struct.A**> [#uses=2] - %a.0 = alloca %struct.objc_object* ; <%struct.objc_object**> [#uses=2] - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - store %struct.A* %a, %struct.A** %a_addr - %0 = load %struct.A** %a_addr, align 4 ; <%struct.A*> [#uses=1] - %1 = bitcast %struct.A* %0 to %struct.objc_object* ; <%struct.objc_object*> [#uses=1] - store %struct.objc_object* %1, %struct.objc_object** %a.0, align 4 - %2 = load %struct.objc_selector** @"\01L_OBJC_SELECTOR_REFERENCES_0", align 4 ; <%struct.objc_selector*> [#uses=1] - %3 = load %struct.objc_object** %a.0, align 4 ; <%struct.objc_object*> [#uses=1] - call void bitcast (%struct.objc_object* (%struct.objc_object*, %struct.objc_selector*, ...)* @objc_msgSend to void (%struct.objc_object*, %struct.objc_selector*, %struct.NSString*)*)(%struct.objc_object* %3, %struct.objc_selector* %2, %struct.NSString* bitcast (%struct.__builtin_CFString* @"\01L_unnamed_cfstring_0" to %struct.NSString*)) nounwind - br label %return +@x = internal constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1] -return: ; preds = %entry - ret void -} +@y = global [1 x i8]* @x -declare %struct.objc_object* @objc_msgSend(%struct.objc_object*, %struct.objc_selector*, ...) diff --git a/test/CodeGen/X86/global-sections.ll b/test/CodeGen/X86/global-sections.ll index 7d39a020952..0fcb17f1989 100644 --- a/test/CodeGen/X86/global-sections.ll +++ b/test/CodeGen/X86/global-sections.ll @@ -28,7 +28,7 @@ ; int * const G3 = &G1; @G3 = constant i32* @G1 -; DARWIN: .const_data +; DARWIN: .section __DATA,__const ; DARWIN: .globl _G3 ; DARWIN: _G3: ; DARWIN: .long _G1 @@ -37,7 +37,7 @@ ; _Complex long long const G4 = 34; @G4 = constant {i64,i64} { i64 34, i64 0 } -; DARWIN: .const +; DARWIN: .section __TEXT,__const ; DARWIN: _G4: ; DARWIN: .long 34 @@ -50,7 +50,7 @@ ; LINUX: G5: ; LINUX: .long 47 -; DARWIN: .data +; DARWIN: .section __DATA,__data ; DARWIN: .globl _G5 ; DARWIN: _G5: ; DARWIN: .long 47 @@ -88,7 +88,7 @@ @G7 = constant [10 x i8] c"abcdefghi\00" -; DARWIN: .cstring +; DARWIN: __TEXT,__cstring,cstring_literals ; DARWIN: .globl _G7 ; DARWIN: _G7: ; DARWIN: .asciz "abcdefghi" @@ -111,7 +111,7 @@ @G9 = constant [4 x i32] [ i32 1, i32 2, i32 3, i32 0 ] -; DARWIN: .const +; DARWIN: .section __TEXT,__const ; DARWIN: .globl _G9 ; DARWIN: _G9: diff --git a/tools/llvm-mc/AsmLexer.cpp b/tools/llvm-mc/AsmLexer.cpp index 28b0c1e3c93..5b394b6cc46 100644 --- a/tools/llvm-mc/AsmLexer.cpp +++ b/tools/llvm-mc/AsmLexer.cpp @@ -242,6 +242,17 @@ AsmToken AsmLexer::LexQuote() { return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart)); } +StringRef AsmLexer::LexUntilEndOfStatement() { + TokStart = CurPtr; + + while (*CurPtr != '#' && // Start of line comment. + *CurPtr != ';' && // End of statement marker. + *CurPtr != '\n' && + *CurPtr != '\r' && + (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) + ++CurPtr; + return StringRef(TokStart, CurPtr-TokStart); +} AsmToken AsmLexer::LexToken() { TokStart = CurPtr; diff --git a/tools/llvm-mc/AsmLexer.h b/tools/llvm-mc/AsmLexer.h index 4200137f640..905ff75ec9f 100644 --- a/tools/llvm-mc/AsmLexer.h +++ b/tools/llvm-mc/AsmLexer.h @@ -50,6 +50,9 @@ public: ~AsmLexer(); SMLoc getLoc() const; + + StringRef LexUntilEndOfStatement(); + /// EnterIncludeFile - Enter the specified file. This returns true on failure. bool EnterIncludeFile(const std::string &Filename); diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp index 8f6583a5916..153cdde779a 100644 --- a/tools/llvm-mc/AsmParser.cpp +++ b/tools/llvm-mc/AsmParser.cpp @@ -404,95 +404,104 @@ bool AsmParser::ParseStatement() { if (IDVal == ".text") // FIXME: This changes behavior based on the -static flag to the // assembler. - return ParseDirectiveSectionSwitch("__TEXT,__text", - "regular,pure_instructions"); + return ParseDirectiveSectionSwitch("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); if (IDVal == ".const") - return ParseDirectiveSectionSwitch("__TEXT,__const"); + return ParseDirectiveSectionSwitch("__TEXT", "__const", 0); if (IDVal == ".static_const") - return ParseDirectiveSectionSwitch("__TEXT,__static_const"); + return ParseDirectiveSectionSwitch("__TEXT", "__static_const", 0); if (IDVal == ".cstring") - return ParseDirectiveSectionSwitch("__TEXT,__cstring", - "cstring_literals"); + return ParseDirectiveSectionSwitch("__TEXT","__cstring", + MCSectionMachO::S_CSTRING_LITERALS); if (IDVal == ".literal4") - return ParseDirectiveSectionSwitch("__TEXT,__literal4", "4byte_literals"); + return ParseDirectiveSectionSwitch("__TEXT", "__literal4", + MCSectionMachO::S_4BYTE_LITERALS); if (IDVal == ".literal8") - return ParseDirectiveSectionSwitch("__TEXT,__literal8", "8byte_literals"); + return ParseDirectiveSectionSwitch("__TEXT", "__literal8", + MCSectionMachO::S_8BYTE_LITERALS); if (IDVal == ".literal16") - return ParseDirectiveSectionSwitch("__TEXT,__literal16", - "16byte_literals"); + return ParseDirectiveSectionSwitch("__TEXT","__literal16", + MCSectionMachO::S_16BYTE_LITERALS); if (IDVal == ".constructor") - return ParseDirectiveSectionSwitch("__TEXT,__constructor"); + return ParseDirectiveSectionSwitch("__TEXT","__constructor", 0); if (IDVal == ".destructor") - return ParseDirectiveSectionSwitch("__TEXT,__destructor"); + return ParseDirectiveSectionSwitch("__TEXT","__destructor", 0); if (IDVal == ".fvmlib_init0") - return ParseDirectiveSectionSwitch("__TEXT,__fvmlib_init0"); + return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0", 0); if (IDVal == ".fvmlib_init1") - return ParseDirectiveSectionSwitch("__TEXT,__fvmlib_init1"); - if (IDVal == ".symbol_stub") // FIXME: Different on PPC. - return ParseDirectiveSectionSwitch("__IMPORT,__jump_table,symbol_stubs", - "self_modifying_code+pure_instructions,5"); + return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1", 0); + if (IDVal == ".symbol_stub") + return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_SELF_MODIFYING_CODE | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + // FIXME: Different on PPC and ARM. + 16); // FIXME: .picsymbol_stub on PPC. if (IDVal == ".data") - return ParseDirectiveSectionSwitch("__DATA,__data"); + return ParseDirectiveSectionSwitch("__DATA", "__data", 0); if (IDVal == ".static_data") - return ParseDirectiveSectionSwitch("__DATA,__static_data"); + return ParseDirectiveSectionSwitch("__DATA", "__static_data", 0); if (IDVal == ".non_lazy_symbol_pointer") - return ParseDirectiveSectionSwitch("__DATA,__nl_symbol_pointer", - "non_lazy_symbol_pointers"); + return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_pointer", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS); if (IDVal == ".lazy_symbol_pointer") - return ParseDirectiveSectionSwitch("__DATA,__la_symbol_pointer", - "lazy_symbol_pointers"); + return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_pointer", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS); if (IDVal == ".dyld") - return ParseDirectiveSectionSwitch("__DATA,__dyld"); + return ParseDirectiveSectionSwitch("__DATA", "__dyld", 0); if (IDVal == ".mod_init_func") - return ParseDirectiveSectionSwitch("__DATA,__mod_init_func", - "mod_init_funcs"); + return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS); if (IDVal == ".mod_term_func") - return ParseDirectiveSectionSwitch("__DATA,__mod_term_func", - "mod_term_funcs"); + return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS); if (IDVal == ".const_data") - return ParseDirectiveSectionSwitch("__DATA,__const", "regular"); + return ParseDirectiveSectionSwitch("__DATA", "__const", 0); // FIXME: Verify attributes on sections. if (IDVal == ".objc_class") - return ParseDirectiveSectionSwitch("__OBJC,__class"); + return ParseDirectiveSectionSwitch("__OBJC", "__class", 0); if (IDVal == ".objc_meta_class") - return ParseDirectiveSectionSwitch("__OBJC,__meta_class"); + return ParseDirectiveSectionSwitch("__OBJC", "__meta_class", 0); if (IDVal == ".objc_cat_cls_meth") - return ParseDirectiveSectionSwitch("__OBJC,__cat_cls_meth"); + return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth", 0); if (IDVal == ".objc_cat_inst_meth") - return ParseDirectiveSectionSwitch("__OBJC,__cat_inst_meth"); + return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth", 0); if (IDVal == ".objc_protocol") - return ParseDirectiveSectionSwitch("__OBJC,__protocol"); + return ParseDirectiveSectionSwitch("__OBJC", "__protocol", 0); if (IDVal == ".objc_string_object") - return ParseDirectiveSectionSwitch("__OBJC,__string_object"); + return ParseDirectiveSectionSwitch("__OBJC", "__string_object", 0); if (IDVal == ".objc_cls_meth") - return ParseDirectiveSectionSwitch("__OBJC,__cls_meth"); + return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth", 0); if (IDVal == ".objc_inst_meth") - return ParseDirectiveSectionSwitch("__OBJC,__inst_meth"); + return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth", 0); if (IDVal == ".objc_cls_refs") - return ParseDirectiveSectionSwitch("__OBJC,__cls_refs"); + return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs", 0); if (IDVal == ".objc_message_refs") - return ParseDirectiveSectionSwitch("__OBJC,__message_refs"); + return ParseDirectiveSectionSwitch("__OBJC", "__message_refs", 0); if (IDVal == ".objc_symbols") - return ParseDirectiveSectionSwitch("__OBJC,__symbols"); + return ParseDirectiveSectionSwitch("__OBJC", "__symbols", 0); if (IDVal == ".objc_category") - return ParseDirectiveSectionSwitch("__OBJC,__category"); + return ParseDirectiveSectionSwitch("__OBJC", "__category", 0); if (IDVal == ".objc_class_vars") - return ParseDirectiveSectionSwitch("__OBJC,__class_vars"); + return ParseDirectiveSectionSwitch("__OBJC", "__class_vars", 0); if (IDVal == ".objc_instance_vars") - return ParseDirectiveSectionSwitch("__OBJC,__instance_vars"); + return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars", 0); if (IDVal == ".objc_module_info") - return ParseDirectiveSectionSwitch("__OBJC,__module_info"); + return ParseDirectiveSectionSwitch("__OBJC", "__module_info", 0); if (IDVal == ".objc_class_names") - return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals"); + return ParseDirectiveSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); if (IDVal == ".objc_meth_var_types") - return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals"); + return ParseDirectiveSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); if (IDVal == ".objc_meth_var_names") - return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals"); + return ParseDirectiveSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); if (IDVal == ".objc_selector_strs") - return ParseDirectiveSectionSwitch("__OBJC,__selector_strs"); + return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs", 0); // Assembler features if (IDVal == ".set") @@ -681,53 +690,52 @@ bool AsmParser::ParseDirectiveSet() { bool AsmParser::ParseDirectiveDarwinSection() { StringRef SectionName; - if (ParseIdentifier(SectionName)) + if (Lexer.isNot(AsmToken::Identifier)) return TokError("expected identifier after '.section' directive"); - std::string Section = SectionName; - - // FIXME: This doesn't work, we lose quoting on things - - // Accept a comma separated list of modifiers. - while (Lexer.is(AsmToken::Comma)) { - Lexer.Lex(); // Consume the comma. - - StringRef ModifierName; - if (ParseIdentifier(ModifierName)) - return TokError("expected identifier in '.section' directive"); - Section += ','; - Section += ModifierName; - } - + std::string SectionSpec = SectionName; + StringRef EOL = Lexer.LexUntilEndOfStatement(); + SectionSpec.append(EOL.begin(), EOL.end()); + Lexer.Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.section' directive"); Lexer.Lex(); + + StringRef Segment, Section; + unsigned TAA, StubSize; + std::string ErrorStr = + MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section, + TAA, StubSize); + + if (!ErrorStr.empty()) + return TokError(ErrorStr.c_str()); + + // FIXME: CACHE THESE. + // FIXME: Arch specific. - MCSection *S = Ctx.GetSection(Section); + MCSection *S = 0; //Ctx.GetSection(Section); if (S == 0) - S = MCSectionMachO::Create(Section, false, SectionKind(), Ctx); + S = MCSectionMachO::Create(Segment, Section, TAA, StubSize, + SectionKind(), Ctx); Out.SwitchSection(S); return false; } -bool AsmParser::ParseDirectiveSectionSwitch(const char *Section, - const char *Directives) { +bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment, + const char *Section, + unsigned TAA, unsigned StubSize) { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in section switching directive"); Lexer.Lex(); - std::string SectionStr = Section; - if (Directives && Directives[0]) { - SectionStr += ","; - SectionStr += Directives; - } - // FIXME: Arch specific. - MCSection *S = Ctx.GetSection(Section); + // FIXME: Cache this! + MCSection *S = 0; // Ctx.GetSection(Section); if (S == 0) - S = MCSectionMachO::Create(Section, false, SectionKind(), Ctx); + S = MCSectionMachO::Create(Segment, Section, TAA, StubSize, + SectionKind(), Ctx); Out.SwitchSection(S); return false; @@ -1090,35 +1098,28 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { if (Lexer.isNot(AsmToken::Identifier)) return TokError("expected segment name after '.zerofill' directive"); - std::string Section = Lexer.getTok().getString(); + StringRef Segment = Lexer.getTok().getString(); Lexer.Lex(); if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Section += ','; Lexer.Lex(); if (Lexer.isNot(AsmToken::Identifier)) return TokError("expected section name after comma in '.zerofill' " "directive"); - Section += Lexer.getTok().getString().str(); + StringRef Section = Lexer.getTok().getString(); Lexer.Lex(); - // FIXME: we will need to tell GetSection() that this is to be created with or - // must have the Mach-O section type of S_ZEROFILL. Something like the code - // below could be done but for now it is not as EmitZerofill() does not know - // how to deal with a section type in the section name like - // ParseDirectiveDarwinSection() allows. - // Section += ','; - // Section += "zerofill"; - // If this is the end of the line all that was wanted was to create the // the section but with no symbol. if (Lexer.is(AsmToken::EndOfStatement)) { - // FIXME: Arch specific. - MCSection *S = Ctx.GetSection(Section); + // FIXME: CACHE THIS. + MCSection *S = 0; //Ctx.GetSection(Section); if (S == 0) - S = MCSectionMachO::Create(Section, false, SectionKind(), Ctx); + S = MCSectionMachO::Create(Segment, Section, + MCSectionMachO::S_ZEROFILL, 0, + SectionKind(), Ctx); // Create the zerofill section but no symbol Out.EmitZerofill(S); @@ -1176,9 +1177,12 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { return Error(IDLoc, "invalid symbol redefinition"); // FIXME: Arch specific. - MCSection *S = Ctx.GetSection(Section); + // FIXME: CACHE. + MCSection *S = 0; //Ctx.GetSection(Section); if (S == 0) - S = MCSectionMachO::Create(Section, false, SectionKind(), Ctx); + S = MCSectionMachO::Create(Segment, Section, + MCSectionMachO::S_ZEROFILL, 0, + SectionKind(), Ctx); // Create the zerofill Symbol with Size and Pow2Alignment Out.EmitZerofill(S, Sym, Size, Pow2Alignment); diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h index c6f6f63e482..646001ce7ac 100644 --- a/tools/llvm-mc/AsmParser.h +++ b/tools/llvm-mc/AsmParser.h @@ -99,8 +99,8 @@ private: // Directive Parsing. bool ParseDirectiveDarwinSection(); // Darwin specific ".section". - bool ParseDirectiveSectionSwitch(const char *Section, - const char *Directives = 0); + bool ParseDirectiveSectionSwitch(const char *Segment, const char *Section, + unsigned TAA, unsigned StubSize = 0); bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz" bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ... bool ParseDirectiveFill(); // ".fill" diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 5f746f2e475..5bddea4c317 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -186,11 +186,10 @@ static int AssembleInput(const char *ProgName) { OwningPtr Str(createAsmStreamer(Ctx, outs())); // FIXME: Target hook & command line option for initial section. - Str.get()->SwitchSection(MCSectionMachO::Create("__TEXT,__text," - "regular,pure_instructions", - false, - SectionKind::getText(), - Ctx)); + Str.get()->SwitchSection(MCSectionMachO::Create("__TEXT","__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 0, SectionKind::getText(), + Ctx)); AsmParser Parser(SrcMgr, Ctx, *Str.get()); OwningPtr TAP(GetTargetAsmParser(ProgName, Parser));