diff options
Diffstat (limited to 'lib/Target')
52 files changed, 1409 insertions, 1230 deletions
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 226f161..3b1be76 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -34,6 +34,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/VectorExtras.h" #include "llvm/Support/ErrorHandling.h" @@ -103,8 +104,14 @@ void ARMTargetLowering::addQRTypeForNEON(MVT VT) { addTypeForNEON(VT, MVT::v2f64, MVT::v4i32); } +static TargetLoweringObjectFile *createTLOF(TargetMachine &TM) { + if (TM.getSubtarget<ARMSubtarget>().isTargetDarwin()) + return new TargetLoweringObjectFileMachO(); + return new TargetLoweringObjectFileELF(true); +} + ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) - : TargetLowering(TM), ARMPCLabelIndex(0) { + : TargetLowering(TM, createTLOF(TM)), ARMPCLabelIndex(0) { Subtarget = &TM.getSubtarget<ARMSubtarget>(); if (Subtarget->isTargetDarwin()) { diff --git a/lib/Target/ARM/ARMTargetAsmInfo.cpp b/lib/Target/ARM/ARMTargetAsmInfo.cpp index 87f8a68..34c1874 100644 --- a/lib/Target/ARM/ARMTargetAsmInfo.cpp +++ b/lib/Target/ARM/ARMTargetAsmInfo.cpp @@ -59,8 +59,6 @@ ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM): ARMTargetAsmInfo<ELFTargetAsmInfo>(TM) { Subtarget = &TM.getSubtarget<ARMSubtarget>(); - BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); - NeedsSet = false; HasLEB128 = true; AbsoluteDebugSectionOffsets = true; diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 1154aaf..d82b758 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -29,6 +29,7 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" @@ -1127,7 +1128,7 @@ void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { if (Subtarget->isTargetELF()) O << "\t.type " << name << ",%object\n"; - const Section *TheSection = TAI->SectionForGlobal(GVar); + const Section *TheSection = getObjFileLowering().SectionForGlobal(GVar, TM); SwitchToSection(TheSection); // FIXME: get this stuff from section kind flags. @@ -1154,7 +1155,7 @@ void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { O << TAI->getCOMMDirective() << name << "," << Size << ',' << Align; } else { - SwitchToSection(TAI->SectionForGlobal(GVar)); + SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM)); O << "\t.globl " << name << '\n' << TAI->getWeakDefDirective() << name << '\n'; EmitAlignment(Align, GVar); @@ -1285,7 +1286,7 @@ bool ARMAsmPrinter::doFinalization(Module &M) { } if (!HiddenGVNonLazyPtrs.empty()) { - SwitchToSection(TAI->getDataSection()); + SwitchToSection(getObjFileLowering().getDataSection()); for (StringMap<std::string>::iterator I = HiddenGVNonLazyPtrs.begin(), E = HiddenGVNonLazyPtrs.end(); I != E; ++I) { EmitAlignment(2); diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 310a4a6..f7a38c2 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Module.h" @@ -30,6 +31,17 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; + +class TargetLoweringObjectFileAlpha : public TargetLoweringObjectFile { +public: + TargetLoweringObjectFileAlpha() { + TextSection = getOrCreateSection("_text", true, SectionKind::Text); + DataSection = getOrCreateSection("_data", true, SectionKind::DataRel); + } +}; + + + /// AddLiveIn - This helper function adds the specified physical register to the /// MachineFunction as a live in value. It also creates a corresponding virtual /// register for it. @@ -41,7 +53,8 @@ static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, return VReg; } -AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) { +AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) + : TargetLowering(TM, new TargetLoweringObjectFileAlpha()) { // Set up the TargetLowering object. //I am having problems with shr n i8 1 setShiftAmountType(MVT::i64); diff --git a/lib/Target/Alpha/AlphaTargetAsmInfo.cpp b/lib/Target/Alpha/AlphaTargetAsmInfo.cpp index 12fadfb..6499552 100644 --- a/lib/Target/Alpha/AlphaTargetAsmInfo.cpp +++ b/lib/Target/Alpha/AlphaTargetAsmInfo.cpp @@ -23,7 +23,4 @@ AlphaTargetAsmInfo::AlphaTargetAsmInfo(const AlphaTargetMachine &TM) JumpTableDirective = ".gprel32"; JumpTableDataSection = "\t.section .rodata\n"; WeakRefDirective = "\t.weak\t"; - - TextSection = getOrCreateSection("_text", true, SectionKind::Text); - DataSection = getOrCreateSection("_data", true, SectionKind::DataRel); } diff --git a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp index 08a2c34..a37dee7 100644 --- a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp +++ b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Support/Compiler.h" @@ -138,7 +139,7 @@ bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) { // Print out labels for the function. const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); EmitAlignment(MF.getAlignment(), F); switch (F->getLinkage()) { @@ -214,7 +215,7 @@ void AlphaAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { unsigned Align = TD->getPreferredAlignmentLog(GVar); // 0: Switch to section - SwitchToSection(TAI->SectionForGlobal(GVar)); + SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM)); // 1: Check visibility printVisibility(name, GVar->getVisibility()); diff --git a/lib/Target/CMakeLists.txt b/lib/Target/CMakeLists.txt index 98df86c..f5c94f2 100644 --- a/lib/Target/CMakeLists.txt +++ b/lib/Target/CMakeLists.txt @@ -10,6 +10,7 @@ add_llvm_library(LLVMTarget TargetFrameInfo.cpp TargetInstrInfo.cpp TargetIntrinsicInfo.cpp + TargetLoweringObjectFile.cpp TargetMachOWriterInfo.cpp TargetMachine.cpp TargetRegisterInfo.cpp diff --git a/lib/Target/COFFTargetAsmInfo.cpp b/lib/Target/COFFTargetAsmInfo.cpp index cd7356d..f1f742e 100644 --- a/lib/Target/COFFTargetAsmInfo.cpp +++ b/lib/Target/COFFTargetAsmInfo.cpp @@ -19,9 +19,6 @@ using namespace llvm; COFFTargetAsmInfo::COFFTargetAsmInfo(const TargetMachine &TM) : TargetAsmInfo(TM) { - TextSection = getOrCreateSection("_text", true, SectionKind::Text); - DataSection = getOrCreateSection("_data", true, SectionKind::DataRel); - GlobalPrefix = "_"; LCOMMDirective = "\t.lcomm\t"; COMMDirectiveTakesAlignment = false; @@ -53,57 +50,3 @@ COFFTargetAsmInfo::COFFTargetAsmInfo(const TargetMachine &TM) DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"dr\""; } -void COFFTargetAsmInfo::getSectionFlagsAsString(SectionKind Kind, - SmallVectorImpl<char> &Str) const { - // FIXME: Inefficient. - std::string Res = ",\""; - if (Kind.isText()) - Res += 'x'; - if (Kind.isWriteable()) - Res += 'w'; - Res += "\""; - - Str.append(Res.begin(), Res.end()); -} - -//===----------------------------------------------------------------------===// -// Move to AsmPrinter (mangler access). -//===----------------------------------------------------------------------===// - -#include "llvm/GlobalVariable.h" - -static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { - if (Kind.isText()) - return ".text$linkonce"; - if (Kind.isWriteable()) - return ".data$linkonce"; - return ".rdata$linkonce"; -} - -const Section * -COFFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind) const { - assert(!Kind.isThreadLocal() && "Doesn't support TLS"); - - // If this global is linkonce/weak and the target handles this by emitting it - // into a 'uniqued' section name, create and return the section now. - if (Kind.isWeak()) { - const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); - // FIXME: Use mangler interface (PR4584). - std::string Name = Prefix+GV->getNameStr(); - return getOrCreateSection(Name.c_str(), false, Kind.getKind()); - } - - if (Kind.isText()) - return getTextSection(); - - if (Kind.isBSS()) - if (const Section *S = getBSSSection_()) - return S; - - if (Kind.isReadOnly()) - if (const Section *S = getReadOnlySection()) - return S; - - return getDataSection(); -} diff --git a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp index fd1df76..e53543c 100644 --- a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp +++ b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp @@ -34,9 +34,10 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" @@ -427,7 +428,7 @@ LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) // Print out labels for the function. const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); EmitAlignment(MF.getAlignment(), F); switch (F->getLinkage()) { @@ -525,7 +526,7 @@ void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { unsigned Size = TD->getTypeAllocSize(Type); unsigned Align = TD->getPreferredAlignmentLog(GVar); - SwitchToSection(TAI->SectionForGlobal(GVar)); + SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM)); if (C->isNullValue() && /* FIXME: Verify correct */ !GVar->hasSection() && diff --git a/lib/Target/CellSPU/SPUISelLowering.cpp b/lib/Target/CellSPU/SPUISelLowering.cpp index d0aad07..50ba00f 100644 --- a/lib/Target/CellSPU/SPUISelLowering.cpp +++ b/lib/Target/CellSPU/SPUISelLowering.cpp @@ -15,8 +15,9 @@ #include "SPUISelLowering.h" #include "SPUTargetMachine.h" #include "SPUFrameInfo.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/VectorExtras.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" #include "llvm/CallingConv.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -24,15 +25,13 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/Intrinsics.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/VectorExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetOptions.h" - #include <map> using namespace llvm; @@ -125,9 +124,8 @@ namespace { } SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM) - : TargetLowering(TM), - SPUTM(TM) -{ + : TargetLowering(TM, new TargetLoweringObjectFileELF()), + SPUTM(TM) { // Fold away setcc operations if possible. setPow2DivIsCheap(); diff --git a/lib/Target/CellSPU/SPUTargetAsmInfo.cpp b/lib/Target/CellSPU/SPUTargetAsmInfo.cpp index 534d18e..1d71605 100644 --- a/lib/Target/CellSPU/SPUTargetAsmInfo.cpp +++ b/lib/Target/CellSPU/SPUTargetAsmInfo.cpp @@ -33,10 +33,6 @@ SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) : HasLEB128 = true; HasDotLocAndDotFile = true; - // BSS section needs to be emitted as ".section" - BSSSection = "\t.section\t.bss"; - BSSSection_ = getOrCreateSection("\t.bss", false, SectionKind::BSS); - SupportsDebugInformation = true; NeedsSet = true; DwarfAbbrevSection = "\t.section .debug_abbrev,\"\",@progbits"; diff --git a/lib/Target/DarwinTargetAsmInfo.cpp b/lib/Target/DarwinTargetAsmInfo.cpp index 5429e65..aa93c0d 100644 --- a/lib/Target/DarwinTargetAsmInfo.cpp +++ b/lib/Target/DarwinTargetAsmInfo.cpp @@ -27,32 +27,7 @@ using namespace llvm; DarwinTargetAsmInfo::DarwinTargetAsmInfo(const TargetMachine &TM) : TargetAsmInfo(TM) { - TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); - DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel); - - CStringSection_ = getOrCreateSection("\t.cstring", true, - SectionKind::MergeableCString); - FourByteConstantSection = getOrCreateSection("\t.literal4\n", true, - SectionKind::MergeableConst4); - EightByteConstantSection = getOrCreateSection("\t.literal8\n", true, - SectionKind::MergeableConst8); - SixteenByteConstantSection = - getOrCreateSection("\t.literal16\n", true, SectionKind::MergeableConst16); - - ReadOnlySection = getOrCreateSection("\t.const", true, SectionKind::ReadOnly); - - TextCoalSection = - getOrCreateSection("\t__TEXT,__textcoal_nt,coalesced,pure_instructions", - false, SectionKind::Text); - ConstTextCoalSection = getOrCreateSection("\t__TEXT,__const_coal,coalesced", - false, SectionKind::Text); - ConstDataCoalSection = getOrCreateSection("\t__DATA,__const_coal,coalesced", - false, SectionKind::Text); - ConstDataSection = getOrCreateSection("\t.const_data", true, - SectionKind::ReadOnlyWithRel); - DataCoalSection = getOrCreateSection("\t__DATA,__datacoal_nt,coalesced", - false, SectionKind::DataRel); - + // Common settings for all Darwin targets. // Syntax: GlobalPrefix = "_"; @@ -124,79 +99,3 @@ bool DarwinTargetAsmInfo::emitUsedDirectiveFor(const GlobalValue* GV, return true; } -const Section* -DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind) const { - assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); - - if (Kind.isText()) - return Kind.isWeak() ? TextCoalSection : TextSection; - - // If this is weak/linkonce, put this in a coalescable section, either in text - // or data depending on if it is writable. - if (Kind.isWeak()) { - if (Kind.isReadOnly()) - return ConstTextCoalSection; - return DataCoalSection; - } - - // FIXME: Alignment check should be handled by section classifier. - if (Kind.isMergeableCString()) - return MergeableStringSection(cast<GlobalVariable>(GV)); - - if (Kind.isMergeableConst()) { - if (Kind.isMergeableConst4()) - return FourByteConstantSection; - if (Kind.isMergeableConst8()) - return EightByteConstantSection; - if (Kind.isMergeableConst16()) - return SixteenByteConstantSection; - return ReadOnlySection; // .const - } - - // FIXME: ROData -> const in -static mode that is relocatable but they happen - // by the static linker. Why not mergeable? - if (Kind.isReadOnly()) - return getReadOnlySection(); - - // If this is marked const, put it into a const section. But if the dynamic - // linker needs to write to it, put it in the data segment. - if (Kind.isReadOnlyWithRel()) - return ConstDataSection; - - // Otherwise, just drop the variable in the normal data section. - return DataSection; -} - -const Section* -DarwinTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const { - const TargetData *TD = TM.getTargetData(); - Constant *C = cast<GlobalVariable>(GV)->getInitializer(); - const Type *Ty = cast<ArrayType>(C->getType())->getElementType(); - - unsigned Size = TD->getTypeAllocSize(Ty); - if (Size) { - unsigned Align = TD->getPreferredAlignment(GV); - if (Align <= 32) - return getCStringSection_(); - } - - return getReadOnlySection(); -} - -const Section * -DarwinTargetAsmInfo::getSectionForMergeableConstant(SectionKind Kind) const { - // If this constant requires a relocation, we have to put it in the data - // segment, not in the text segment. - if (Kind.isDataRel()) - return ConstDataSection; - - if (Kind.isMergeableConst4()) - return FourByteConstantSection; - if (Kind.isMergeableConst8()) - return EightByteConstantSection; - if (Kind.isMergeableConst16()) - return SixteenByteConstantSection; - return ReadOnlySection; // .const -} - diff --git a/lib/Target/ELFTargetAsmInfo.cpp b/lib/Target/ELFTargetAsmInfo.cpp index 556b494..e3259bd 100644 --- a/lib/Target/ELFTargetAsmInfo.cpp +++ b/lib/Target/ELFTargetAsmInfo.cpp @@ -18,217 +18,4 @@ using namespace llvm; ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM) : TargetAsmInfo(TM) { - - TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); - DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel); - ReadOnlySection = - getOrCreateSection("\t.rodata", false, SectionKind::ReadOnly); - TLSDataSection = - getOrCreateSection("\t.tdata", false, SectionKind::ThreadData); - TLSBSSSection = getOrCreateSection("\t.tbss", false, SectionKind::ThreadBSS); - - DataRelSection = getOrCreateSection("\t.data.rel", false, - SectionKind::DataRel); - DataRelLocalSection = getOrCreateSection("\t.data.rel.local", false, - SectionKind::DataRelLocal); - DataRelROSection = getOrCreateSection("\t.data.rel.ro", false, - SectionKind::ReadOnlyWithRel); - DataRelROLocalSection = - getOrCreateSection("\t.data.rel.ro.local", false, - SectionKind::ReadOnlyWithRelLocal); - - MergeableConst4Section = getOrCreateSection(".rodata.cst4", false, - SectionKind::MergeableConst4); - MergeableConst8Section = getOrCreateSection(".rodata.cst8", false, - SectionKind::MergeableConst8); - MergeableConst16Section = getOrCreateSection(".rodata.cst16", false, - SectionKind::MergeableConst16); -} - -/// getFlagsForNamedSection - If this target wants to be able to infer -/// section flags based on the name of the section specified for a global -/// variable, it can implement this. -SectionKind::Kind ELFTargetAsmInfo::getKindForNamedSection(const char *Name, - SectionKind::Kind K) const { - if (Name[0] != '.') return K; - - // Some lame default implementation based on some magic section names. - if (strncmp(Name, ".gnu.linkonce.b.", 16) == 0 || - strncmp(Name, ".llvm.linkonce.b.", 17) == 0 || - strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 || - strncmp(Name, ".llvm.linkonce.sb.", 18) == 0) - return SectionKind::BSS; - - if (strcmp(Name, ".tdata") == 0 || - strncmp(Name, ".tdata.", 7) == 0 || - strncmp(Name, ".gnu.linkonce.td.", 17) == 0 || - strncmp(Name, ".llvm.linkonce.td.", 18) == 0) - return SectionKind::ThreadData; - - if (strcmp(Name, ".tbss") == 0 || - strncmp(Name, ".tbss.", 6) == 0 || - strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 || - strncmp(Name, ".llvm.linkonce.tb.", 18) == 0) - return SectionKind::ThreadBSS; - - return K; -} - - -void ELFTargetAsmInfo::getSectionFlagsAsString(SectionKind Kind, - SmallVectorImpl<char> &Str) const { - Str.push_back(','); - Str.push_back('"'); - - if (!Kind.isMetadata()) - Str.push_back('a'); - if (Kind.isText()) - Str.push_back('x'); - if (Kind.isWriteable()) - Str.push_back('w'); - if (Kind.isMergeableConst() || Kind.isMergeableCString()) - Str.push_back('M'); - if (Kind.isMergeableCString()) - Str.push_back('S'); - if (Kind.isThreadLocal()) - Str.push_back('T'); - - Str.push_back('"'); - Str.push_back(','); - - // If comment string is '@', e.g. as on ARM - use '%' instead - if (strcmp(CommentString, "@") == 0) - Str.push_back('%'); - else - Str.push_back('@'); - - const char *KindStr; - if (Kind.isBSS()) - KindStr = "nobits"; - else - KindStr = "progbits"; - - Str.append(KindStr, KindStr+strlen(KindStr)); - - if (Kind.isMergeableCString()) { - // TODO: Eventually handle multiple byte character strings. For now, all - // mergable C strings are single byte. - Str.push_back(','); - Str.push_back('1'); - } else if (Kind.isMergeableConst4()) { - Str.push_back(','); - Str.push_back('4'); - } else if (Kind.isMergeableConst8()) { - Str.push_back(','); - Str.push_back('8'); - } else if (Kind.isMergeableConst16()) { - Str.push_back(','); - Str.push_back('1'); - Str.push_back('6'); - } } - - - -//===----------------------------------------------------------------------===// -// Move to AsmPrinter (mangler access). -//===----------------------------------------------------------------------===// - -#include "llvm/DerivedTypes.h" -#include "llvm/GlobalVariable.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/ADT/StringExtras.h" - -static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { - if (Kind.isText()) return ".gnu.linkonce.t."; - if (Kind.isReadOnly()) return ".gnu.linkonce.r."; - - if (Kind.isThreadData()) return ".gnu.linkonce.td."; - if (Kind.isThreadBSS()) return ".gnu.linkonce.tb."; - - if (Kind.isBSS()) return ".gnu.linkonce.b."; - if (Kind.isDataNoRel()) return ".gnu.linkonce.d."; - if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local."; - if (Kind.isDataRel()) return ".gnu.linkonce.d.rel."; - if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local."; - - assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); - return ".gnu.linkonce.d.rel.ro."; -} - -const Section* -ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind) const { - - // If this global is linkonce/weak and the target handles this by emitting it - // into a 'uniqued' section name, create and return the section now. - if (Kind.isWeak()) { - const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); - // FIXME: Use mangler interface (PR4584). - std::string Name = Prefix+GV->getNameStr(); - return getOrCreateSection(Name.c_str(), false, Kind.getKind()); - } - - if (Kind.isText()) return TextSection; - if (Kind.isMergeableCString()) { - const TargetData *TD = TM.getTargetData(); - Constant *C = cast<GlobalVariable>(GV)->getInitializer(); - const Type *Ty = cast<ArrayType>(C->getType())->getElementType(); - - unsigned Size = TD->getTypeAllocSize(Ty); - if (Size <= 16) { - assert(getCStringSection() && "Should have string section prefix"); - - // We also need alignment here. - // FIXME: this is getting the alignment of the character, not the - // alignment of the string!! - unsigned Align = TD->getPrefTypeAlignment(Ty); - if (Align < Size) - Align = Size; - - std::string Name = getCStringSection() + utostr(Size) + '.' + - utostr(Align); - return getOrCreateSection(Name.c_str(), false, - SectionKind::MergeableCString); - } - - return getReadOnlySection(); - } - - if (Kind.isMergeableConst()) { - if (Kind.isMergeableConst4()) - return MergeableConst4Section; - if (Kind.isMergeableConst8()) - return MergeableConst8Section; - if (Kind.isMergeableConst16()) - return MergeableConst16Section; - return ReadOnlySection; // .const - } - - if (Kind.isReadOnly()) return getReadOnlySection(); - - - if (Kind.isThreadData()) return TLSDataSection; - if (Kind.isThreadBSS()) return TLSBSSSection; - - if (Kind.isBSS()) return getBSSSection_(); - - - if (Kind.isDataNoRel()) return DataSection; - if (Kind.isDataRelLocal()) return DataRelLocalSection; - if (Kind.isDataRel()) return DataRelSection; - if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; - - assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); - return DataRelROSection; -} - -/// getSectionForMergeableConstant - Given a Mergeable constant with the -/// specified size and relocation information, return a section that it -/// should be placed in. -const Section * -ELFTargetAsmInfo::getSectionForMergeableConstant(SectionKind Kind) const { - return SelectSectionForGlobal(0, Kind); -} - diff --git a/lib/Target/MSP430/MSP430AsmPrinter.cpp b/lib/Target/MSP430/MSP430AsmPrinter.cpp index bb112bc..81bc81b 100644 --- a/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Compiler.h" @@ -77,7 +78,7 @@ namespace { void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); unsigned FnAlign = MF.getAlignment(); EmitAlignment(FnAlign, F); diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index 7476db9..9413060 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -31,13 +31,15 @@ #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/VectorExtras.h" using namespace llvm; MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) : - TargetLowering(tm), Subtarget(*tm.getSubtargetImpl()), TM(tm) { + TargetLowering(tm, new TargetLoweringObjectFileELF()), + Subtarget(*tm.getSubtargetImpl()), TM(tm) { // Set up the register classes. addRegisterClass(MVT::i8, MSP430::GR8RegisterClass); diff --git a/lib/Target/MSP430/MSP430TargetAsmInfo.cpp b/lib/Target/MSP430/MSP430TargetAsmInfo.cpp index cd3cdcf..43a521d 100644 --- a/lib/Target/MSP430/MSP430TargetAsmInfo.cpp +++ b/lib/Target/MSP430/MSP430TargetAsmInfo.cpp @@ -17,6 +17,4 @@ using namespace llvm; MSP430TargetAsmInfo::MSP430TargetAsmInfo(const TargetMachine &TM) : ELFTargetAsmInfo(TM) { AlignmentIsInBytes = false; - - BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); } diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp index 9eda5e2..d0f0487 100644 --- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp @@ -31,6 +31,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" @@ -211,12 +212,10 @@ emitCurrentABIString(void) } /// Emit the directives used by GAS on the start of functions -void MipsAsmPrinter:: -emitFunctionStart(MachineFunction &MF) -{ +void MipsAsmPrinter::emitFunctionStart(MachineFunction &MF) { // Print out the label for the function. const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); // 2 bits aligned EmitAlignment(MF.getAlignment(), F); @@ -485,7 +484,7 @@ void MipsAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { printVisibility(name, GVar->getVisibility()); - SwitchToSection(TAI->SectionForGlobal(GVar)); + SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM)); if (C->isNullValue() && !GVar->hasSection()) { if (!GVar->isThreadLocal() && diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index f6d171b..ca94d39 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -30,15 +30,13 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; -const char *MipsTargetLowering:: -getTargetNodeName(unsigned Opcode) const -{ - switch (Opcode) - { +const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { case MipsISD::JmpLink : return "MipsISD::JmpLink"; case MipsISD::Hi : return "MipsISD::Hi"; case MipsISD::Lo : return "MipsISD::Lo"; @@ -55,8 +53,8 @@ getTargetNodeName(unsigned Opcode) const } MipsTargetLowering:: -MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM) -{ +MipsTargetLowering(MipsTargetMachine &TM) + : TargetLowering(TM, new TargetLoweringObjectFileELF()) { Subtarget = &TM.getSubtarget<MipsSubtarget>(); // Mips does not have i1 type, so use i32 for diff --git a/lib/Target/Mips/MipsTargetAsmInfo.cpp b/lib/Target/Mips/MipsTargetAsmInfo.cpp index 26f4b3b..1fa02f2 100644 --- a/lib/Target/Mips/MipsTargetAsmInfo.cpp +++ b/lib/Target/Mips/MipsTargetAsmInfo.cpp @@ -30,8 +30,6 @@ MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM) BSSSection = "\t.section\t.bss"; CStringSection = ".rodata.str"; - BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); - if (!TM.getSubtarget<MipsSubtarget>().hasABICall()) JumpTableDirective = "\t.word\t"; else diff --git a/lib/Target/PIC16/CMakeLists.txt b/lib/Target/PIC16/CMakeLists.txt index 00d737a..ba1dfb4 100644 --- a/lib/Target/PIC16/CMakeLists.txt +++ b/lib/Target/PIC16/CMakeLists.txt @@ -21,4 +21,5 @@ add_llvm_target(PIC16 PIC16Subtarget.cpp PIC16TargetAsmInfo.cpp PIC16TargetMachine.cpp + PIC16TargetObjectFile.cpp ) diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp index ec86585..7fad6f3 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp @@ -25,11 +25,20 @@ #include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetLoweringObjectFile.h" using namespace llvm; #include "PIC16GenAsmWriter.inc" +PIC16AsmPrinter::PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const TargetAsmInfo *T, bool V) +: AsmPrinter(O, TM, T, V), DbgInfo(O, T) { + PTLI = static_cast<const PIC16TargetLowering*>(TM.getTargetLowering()); + PTAI = static_cast<const PIC16TargetAsmInfo*>(T); + PTOF = static_cast<const PIC16TargetObjectFile*>(&PTLI->getObjFileLowering()); +} + bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) { printInstruction(MI); return true; @@ -59,10 +68,12 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { EmitAutos(CurrentFnName); // Now emit the instructions of function in its code section. - const char *codeSection = PAN::getCodeSectionName(CurrentFnName).c_str(); + std::string T = PAN::getCodeSectionName(CurrentFnName); + const char *codeSection = T.c_str(); const Section *fCodeSection = - TAI->getOrCreateSection(codeSection, false, SectionKind::Text); + getObjFileLowering().getOrCreateSection(codeSection, false, + SectionKind::Text); // Start the Code Section. O << "\n"; SwitchToSection(fCodeSection); @@ -211,9 +222,8 @@ bool PIC16AsmPrinter::doInitialization(Module &M) { // Set the section names for all globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) { - I->setSection(TAI->SectionForGlobal(I)->getName()); - } + I != E; ++I) + I->setSection(getObjFileLowering().SectionForGlobal(I, TM)->getName()); DbgInfo.BeginModule(M); EmitFunctionDecls(M); @@ -256,7 +266,7 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) { // Emit variables imported from other Modules. void PIC16AsmPrinter::EmitUndefinedVars(Module &M) { - std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDecls->Items; + std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDecls->Items; if (!Items.size()) return; O << "\n" << TAI->getCommentString() << "Imported Variables - BEGIN" << "\n"; @@ -268,7 +278,7 @@ void PIC16AsmPrinter::EmitUndefinedVars(Module &M) { // Emit variables defined in this module and are available to other modules. void PIC16AsmPrinter::EmitDefinedVars(Module &M) { - std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDefs->Items; + std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDefs->Items; if (!Items.size()) return; O << "\n" << TAI->getCommentString() << "Exported Variables - BEGIN" << "\n"; @@ -281,12 +291,12 @@ void PIC16AsmPrinter::EmitDefinedVars(Module &M) { // Emit initialized data placed in ROM. void PIC16AsmPrinter::EmitRomData(Module &M) { // Print ROM Data section. - const std::vector<PIC16Section*> &ROSections = PTAI->ROSections; + const std::vector<PIC16Section*> &ROSections = PTOF->ROSections; for (unsigned i = 0; i < ROSections.size(); i++) { const std::vector<const GlobalVariable*> &Items = ROSections[i]->Items; if (!Items.size()) continue; O << "\n"; - SwitchToSection(PTAI->ROSections[i]->S_); + SwitchToSection(PTOF->ROSections[i]->S_); for (unsigned j = 0; j < Items.size(); j++) { O << Mang->getMangledName(Items[j]); Constant *C = Items[j]->getInitializer(); @@ -310,10 +320,12 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { const TargetData *TD = TM.getTargetData(); // Emit the data section name. O << "\n"; - const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str(); + std::string T = PAN::getFrameSectionName(CurrentFnName); + const char *SectionName = T.c_str(); const Section *fPDataSection = - TAI->getOrCreateSection(SectionName, false, SectionKind::DataRel); + getObjFileLowering().getOrCreateSection(SectionName, false, + SectionKind::DataRel); SwitchToSection(fPDataSection); // Emit function frame label @@ -352,7 +364,7 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { void PIC16AsmPrinter::EmitIData(Module &M) { // Print all IDATA sections. - const std::vector<PIC16Section*> &IDATASections = PTAI->IDATASections; + const std::vector<PIC16Section*> &IDATASections = PTOF->IDATASections; for (unsigned i = 0; i < IDATASections.size(); i++) { O << "\n"; if (IDATASections[i]->S_->getName().find("llvm.") != std::string::npos) @@ -373,7 +385,7 @@ void PIC16AsmPrinter::EmitUData(Module &M) { const TargetData *TD = TM.getTargetData(); // Print all BSS sections. - const std::vector<PIC16Section*> &BSSSections = PTAI->BSSSections; + const std::vector<PIC16Section*> &BSSSections = PTOF->BSSSections; for (unsigned i = 0; i < BSSSections.size(); i++) { O << "\n"; SwitchToSection(BSSSections[i]->S_); @@ -395,7 +407,7 @@ void PIC16AsmPrinter::EmitAutos(std::string FunctName) { // Now print Autos section for this function. std::string SectionName = PAN::getAutosSectionName(FunctName); - const std::vector<PIC16Section*> &AutosSections = PTAI->AutosSections; + const std::vector<PIC16Section*> &AutosSections = PTOF->AutosSections; for (unsigned i = 0; i < AutosSections.size(); i++) { O << "\n"; if (AutosSections[i]->S_->getName() == SectionName) { @@ -422,7 +434,7 @@ void PIC16AsmPrinter::EmitRemainingAutos() { const TargetData *TD = TM.getTargetData(); // Now print Autos section for this function. - std::vector <PIC16Section *>AutosSections = PTAI->AutosSections; + std::vector <PIC16Section *>AutosSections = PTOF->AutosSections; for (unsigned i = 0; i < AutosSections.size(); i++) { // if the section is already printed then don't print again diff --git a/lib/Target/PIC16/PIC16AsmPrinter.h b/lib/Target/PIC16/PIC16AsmPrinter.h index 0e05940..c365b5a 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.h +++ b/lib/Target/PIC16/PIC16AsmPrinter.h @@ -18,6 +18,7 @@ #include "PIC16.h" #include "PIC16TargetMachine.h" #include "PIC16DebugInfo.h" +#include "PIC16TargetObjectFile.h" #include "llvm/Analysis/DebugInfo.h" #include "PIC16TargetAsmInfo.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -28,13 +29,10 @@ #include <string> namespace llvm { - struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter { + class VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter { + public: explicit PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - const TargetAsmInfo *T, bool V) - : AsmPrinter(O, TM, T, V), DbgInfo(O, T) { - PTLI = static_cast<const PIC16TargetLowering *> (TM.getTargetLowering()); - PTAI = static_cast<const PIC16TargetAsmInfo *> (T); - } + const TargetAsmInfo *T, bool V); private: virtual const char *getPassName() const { return "PIC16 Assembly Printer"; @@ -66,6 +64,7 @@ namespace llvm { } private: + PIC16TargetObjectFile *PTOF; PIC16TargetLowering *PTLI; PIC16DbgInfo DbgInfo; const PIC16TargetAsmInfo *PTAI; diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp index 13d9654..f194dc8 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.cpp +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "pic16-lower" - #include "PIC16ISelLowering.h" +#include "PIC16TargetObjectFile.h" #include "PIC16TargetMachine.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalValue.h" @@ -123,7 +123,7 @@ static const char *getIntrinsicName(unsigned opcode) { // PIC16TargetLowering Constructor. PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) - : TargetLowering(TM), TmpSize(0) { + : TargetLowering(TM, new PIC16TargetObjectFile(TM)), TmpSize(0) { Subtarget = &TM.getSubtarget<PIC16Subtarget>(); diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp index 5a4387a..9912543 100644 --- a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp +++ b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp @@ -31,36 +31,26 @@ PIC16TargetAsmInfo(const PIC16TargetMachine &TM) Data16bitsDirective = " dw "; Data32bitsDirective = " dl "; Data64bitsDirective = NULL; - RomData8bitsDirective = " dw "; - RomData16bitsDirective = " rom_di "; - RomData32bitsDirective = " rom_dl "; ZeroDirective = NULL; AsciiDirective = " dt "; AscizDirective = NULL; - BSSSection_ = getOrCreateSection("udata.# UDATA", false, SectionKind::BSS); - ReadOnlySection = getOrCreateSection("romdata.# ROMDATA", false, - SectionKind::ReadOnly); - DataSection = getOrCreateSection("idata.# IDATA", false,SectionKind::DataRel); SwitchToSectionDirective = ""; - // Need because otherwise a .text symbol is emitted by DwarfWriter - // in BeginModule, and gpasm cribbs for that .text symbol. - TextSection = getOrCreateSection("", true, SectionKind::Text); - PIC16Section *ROSection = new PIC16Section(getReadOnlySection()); - ROSections.push_back(ROSection); - // FIXME: I don't know what the classification of these sections really is. - ExternalVarDecls = new PIC16Section(getOrCreateSection("ExternalVarDecls", - false, - SectionKind::Metadata)); - ExternalVarDefs = new PIC16Section(getOrCreateSection("ExternalVarDefs", - false, - SectionKind::Metadata)); + RomData8bitsDirective = " dw "; + RomData16bitsDirective = " rom_di "; + RomData32bitsDirective = " rom_dl "; + + // Set it to false because we weed to generate c file name and not bc file // name. HasSingleParameterDotFile = false; } -const char *PIC16TargetAsmInfo::getRomDirective(unsigned Size) const { +const char *PIC16TargetAsmInfo:: +getDataASDirective(unsigned Size, unsigned AS) const { + if (AS != PIC16ISD::ROM_SPACE) + return 0; + switch (Size) { case 8: return RomData8bitsDirective; case 16: return RomData16bitsDirective; @@ -69,369 +59,3 @@ const char *PIC16TargetAsmInfo::getRomDirective(unsigned Size) const { } } - -const char *PIC16TargetAsmInfo:: -getDataASDirective(unsigned Size, unsigned AS) const { - if (AS == PIC16ISD::ROM_SPACE) - return getRomDirective(Size); - return NULL; -} - -const Section * -PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const { - assert(GV->hasInitializer() && "This global doesn't need space"); - Constant *C = GV->getInitializer(); - assert(C->isNullValue() && "Unitialized globals has non-zero initializer"); - - // Find how much space this global needs. - const TargetData *TD = TM.getTargetData(); - const Type *Ty = C->getType(); - unsigned ValSize = TD->getTypeAllocSize(Ty); - - // Go through all BSS Sections and assign this variable - // to the first available section having enough space. - PIC16Section *FoundBSS = NULL; - for (unsigned i = 0; i < BSSSections.size(); i++) { - if (DataBankSize - BSSSections[i]->Size >= ValSize) { - FoundBSS = BSSSections[i]; - break; - } - } - - // No BSS section spacious enough was found. Crate a new one. - if (!FoundBSS) { - std::string name = PAN::getUdataSectionName(BSSSections.size()); - const Section *NewSection = getOrCreateSection(name.c_str(), false, - // FIXME. - SectionKind::Metadata); - - FoundBSS = new PIC16Section(NewSection); - - // Add this newly created BSS section to the list of BSSSections. - BSSSections.push_back(FoundBSS); - } - - // Insert the GV into this BSS. - FoundBSS->Items.push_back(GV); - FoundBSS->Size += ValSize; - return FoundBSS->S_; -} - -const Section * -PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const { - assert(GV->hasInitializer() && "This global doesn't need space"); - Constant *C = GV->getInitializer(); - assert(!C->isNullValue() && "initialized globals has zero initializer"); - assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE && - "can split initialized RAM data only"); - - // Find how much space this global needs. - const TargetData *TD = TM.getTargetData(); - const Type *Ty = C->getType(); - unsigned ValSize = TD->getTypeAllocSize(Ty); - - // Go through all IDATA Sections and assign this variable - // to the first available section having enough space. - PIC16Section *FoundIDATA = NULL; - for (unsigned i = 0; i < IDATASections.size(); i++) { - if (DataBankSize - IDATASections[i]->Size >= ValSize) { - FoundIDATA = IDATASections[i]; - break; - } - } - - // No IDATA section spacious enough was found. Crate a new one. - if (!FoundIDATA) { - std::string name = PAN::getIdataSectionName(IDATASections.size()); - const Section *NewSection = getOrCreateSection(name.c_str(), - false, - // FIXME. - SectionKind::Metadata); - - FoundIDATA = new PIC16Section(NewSection); - - // Add this newly created IDATA section to the list of IDATASections. - IDATASections.push_back(FoundIDATA); - } - - // Insert the GV into this IDATA. - FoundIDATA->Items.push_back(GV); - FoundIDATA->Size += ValSize; - return FoundIDATA->S_; -} - -// Get the section for an automatic variable of a function. -// For PIC16 they are globals only with mangled names. -const Section * -PIC16TargetAsmInfo::getSectionForAuto(const GlobalVariable *GV) const { - - const std::string name = PAN::getSectionNameForSym(GV->getName()); - - // Go through all Auto Sections and assign this variable - // to the appropriate section. - PIC16Section *FoundAutoSec = NULL; - for (unsigned i = 0; i < AutosSections.size(); i++) { - if (AutosSections[i]->S_->getName() == name) { - FoundAutoSec = AutosSections[i]; - break; - } - } - - // No Auto section was found. Crate a new one. - if (!FoundAutoSec) { - const Section *NewSection = getOrCreateSection(name.c_str(), - // FIXME. - false, - SectionKind::Metadata); - - FoundAutoSec = new PIC16Section(NewSection); - - // Add this newly created autos section to the list of AutosSections. - AutosSections.push_back(FoundAutoSec); - } - - // Insert the auto into this section. - FoundAutoSec->Items.push_back(GV); - - return FoundAutoSec->S_; -} - - -// Override default implementation to put the true globals into -// multiple data sections if required. -const Section* -PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1, - SectionKind Kind) const { - // We select the section based on the initializer here, so it really - // has to be a GlobalVariable. - const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1); - if (!GV) - return TargetAsmInfo::SelectSectionForGlobal(GV1, Kind); - - // Record External Var Decls. - if (GV->isDeclaration()) { - ExternalVarDecls->Items.push_back(GV); - return ExternalVarDecls->S_; - } - - assert(GV->hasInitializer() && "A def without initializer?"); - - // First, if this is an automatic variable for a function, get the section - // name for it and return. - std::string name = GV->getName(); - if (PAN::isLocalName(name)) - return getSectionForAuto(GV); - - // Record Exteranl Var Defs. - if (GV->hasExternalLinkage() || GV->hasCommonLinkage()) - ExternalVarDefs->Items.push_back(GV); - - // See if this is an uninitialized global. - const Constant *C = GV->getInitializer(); - if (C->isNullValue()) - return getBSSSectionForGlobal(GV); - - // If this is initialized data in RAM. Put it in the correct IDATA section. - if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) - return getIDATASectionForGlobal(GV); - - // This is initialized data in rom, put it in the readonly section. - if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) - return getROSectionForGlobal(GV); - - // Else let the default implementation take care of it. - return TargetAsmInfo::SelectSectionForGlobal(GV, Kind); -} - -PIC16TargetAsmInfo::~PIC16TargetAsmInfo() { - for (unsigned i = 0; i < BSSSections.size(); i++) - delete BSSSections[i]; - for (unsigned i = 0; i < IDATASections.size(); i++) - delete IDATASections[i]; - for (unsigned i = 0; i < AutosSections.size(); i++) - delete AutosSections[i]; - for (unsigned i = 0; i < ROSections.size(); i++) - delete ROSections[i]; - delete ExternalVarDecls; - delete ExternalVarDefs; -} - - -/// getSpecialCasedSectionGlobals - Allow the target to completely override -/// section assignment of a global. -const Section * -PIC16TargetAsmInfo::getSpecialCasedSectionGlobals(const GlobalValue *GV, - SectionKind Kind) const { - // If GV has a sectin name or section address create that section now. - if (GV->hasSection()) { - if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) { - std::string SectName = GVar->getSection(); - // If address for a variable is specified, get the address and create - // section. - std::string AddrStr = "Address="; - if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) { - std::string SectAddr = SectName.substr(AddrStr.length()); - return CreateSectionForGlobal(GVar, SectAddr); - } - - // Create the section specified with section attribute. - return CreateSectionForGlobal(GVar); - } - } - - return 0; -} - -// Create a new section for global variable. If Addr is given then create -// section at that address else create by name. -const Section * -PIC16TargetAsmInfo::CreateSectionForGlobal(const GlobalVariable *GV, - const std::string &Addr) const { - // See if this is an uninitialized global. - const Constant *C = GV->getInitializer(); - if (C->isNullValue()) - return CreateBSSSectionForGlobal(GV, Addr); - - // If this is initialized data in RAM. Put it in the correct IDATA section. - if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) - return CreateIDATASectionForGlobal(GV, Addr); - - // This is initialized data in rom, put it in the readonly section. - if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) - return CreateROSectionForGlobal(GV, Addr); - - // Else let the default implementation take care of it. - return TargetAsmInfo::SectionForGlobal(GV); -} - -// Create uninitialized section for a variable. -const Section * -PIC16TargetAsmInfo::CreateBSSSectionForGlobal(const GlobalVariable *GV, - std::string Addr) const { - assert(GV->hasInitializer() && "This global doesn't need space"); - assert(GV->getInitializer()->isNullValue() && - "Unitialized global has non-zero initializer"); - std::string Name; - // If address is given then create a section at that address else create a - // section by section name specified in GV. - PIC16Section *FoundBSS = NULL; - if (Addr.empty()) { - Name = GV->getSection() + " UDATA"; - for (unsigned i = 0; i < BSSSections.size(); i++) { - if (BSSSections[i]->S_->getName() == Name) { - FoundBSS = BSSSections[i]; - break; - } - } - } else { - std::string Prefix = GV->getNameStr() + "." + Addr + "."; - Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr; - } - - PIC16Section *NewBSS = FoundBSS; - if (NewBSS == NULL) { - const Section *NewSection = getOrCreateSection(Name.c_str(), - false, SectionKind::BSS); - NewBSS = new PIC16Section(NewSection); - BSSSections.push_back(NewBSS); - } - - // Insert the GV into this BSS. - NewBSS->Items.push_back(GV); - - // We do not want to put any GV without explicit section into this section - // so set its size to DatabankSize. - NewBSS->Size = DataBankSize; - return NewBSS->S_; -} - -// Get rom section for a variable. Currently there can be only one rom section -// unless a variable explicitly requests a section. -const Section * -PIC16TargetAsmInfo::getROSectionForGlobal(const GlobalVariable *GV) const { - ROSections[0]->Items.push_back(GV); - return ROSections[0]->S_; -} - -// Create initialized data section for a variable. -const Section * -PIC16TargetAsmInfo::CreateIDATASectionForGlobal(const GlobalVariable *GV, - std::string Addr) const { - assert(GV->hasInitializer() && "This global doesn't need space"); - assert(!GV->getInitializer()->isNullValue() && - "initialized global has zero initializer"); - assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE && - "can be used for initialized RAM data only"); - - std::string Name; - // If address is given then create a section at that address else create a - // section by section name specified in GV. - PIC16Section *FoundIDATASec = NULL; - if (Addr.empty()) { - Name = GV->getSection() + " IDATA"; - for (unsigned i = 0; i < IDATASections.size(); i++) { - if (IDATASections[i]->S_->getName() == Name) { - FoundIDATASec = IDATASections[i]; - break; - } - } - } else { - std::string Prefix = GV->getNameStr() + "." + Addr + "."; - Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr; - } - - PIC16Section *NewIDATASec = FoundIDATASec; - if (NewIDATASec == NULL) { - const Section *NewSection = getOrCreateSection(Name.c_str(), - false, - // FIXME: - SectionKind::Metadata); - NewIDATASec = new PIC16Section(NewSection); - IDATASections.push_back(NewIDATASec); - } - // Insert the GV into this IDATA Section. - NewIDATASec->Items.push_back(GV); - // We do not want to put any GV without explicit section into this section - // so set its size to DatabankSize. - NewIDATASec->Size = DataBankSize; - return NewIDATASec->S_; -} - -// Create a section in rom for a variable. -const Section * -PIC16TargetAsmInfo::CreateROSectionForGlobal(const GlobalVariable *GV, - std::string Addr) const { - assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE && - "can be used for ROM data only"); - - std::string Name; - // If address is given then create a section at that address else create a - // section by section name specified in GV. - PIC16Section *FoundROSec = NULL; - if (Addr.empty()) { - Name = GV->getSection() + " ROMDATA"; - for (unsigned i = 1; i < ROSections.size(); i++) { - if (ROSections[i]->S_->getName() == Name) { - FoundROSec = ROSections[i]; - break; - } - } - } else { - std::string Prefix = GV->getNameStr() + "." + Addr + "."; - Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr; - } - - PIC16Section *NewRomSec = FoundROSec; - if (NewRomSec == NULL) { - const Section *NewSection = getOrCreateSection(Name.c_str(), - false, - SectionKind::ReadOnly); - NewRomSec = new PIC16Section(NewSection); - ROSections.push_back(NewRomSec); - } - - // Insert the GV into this ROM Section. - NewRomSec->Items.push_back(GV); - return NewRomSec->S_; -} - diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.h b/lib/Target/PIC16/PIC16TargetAsmInfo.h index 1ced3bf..8fb9e0c 100644 --- a/lib/Target/PIC16/PIC16TargetAsmInfo.h +++ b/lib/Target/PIC16/PIC16TargetAsmInfo.h @@ -14,91 +14,22 @@ #ifndef PIC16TARGETASMINFO_H #define PIC16TARGETASMINFO_H -#include "PIC16.h" #include "llvm/Target/TargetAsmInfo.h" -#include <vector> -#include "llvm/Module.h" namespace llvm { - enum { DataBankSize = 80 }; - // Forward declaration. class PIC16TargetMachine; - class GlobalVariable; - - /// PIC16 Splits the global data into mulitple udata and idata sections. - /// Each udata and idata section needs to contain a list of globals that - /// they contain, in order to avoid scanning over all the global values - /// again and printing only those that match the current section. - /// Keeping values inside the sections make printing a section much easier. - struct PIC16Section { - const Section *S_; // Connection to actual Section. - unsigned Size; // Total size of the objects contained. - bool SectionPrinted; - std::vector<const GlobalVariable*> Items; - - PIC16Section(const Section *s) { - S_ = s; - Size = 0; - SectionPrinted = false; - } - bool isPrinted() const { return SectionPrinted; } - void setPrintedStatus(bool status) { SectionPrinted = status; } - }; - struct PIC16TargetAsmInfo : public TargetAsmInfo { - std::string getSectionNameForSym(const std::string &Sym) const; - PIC16TargetAsmInfo(const PIC16TargetMachine &TM); - mutable std::vector<PIC16Section *> BSSSections; - mutable std::vector<PIC16Section *> IDATASections; - mutable std::vector<PIC16Section *> AutosSections; - mutable std::vector<PIC16Section *> ROSections; - mutable PIC16Section *ExternalVarDecls; - mutable PIC16Section *ExternalVarDefs; - virtual ~PIC16TargetAsmInfo(); - - private: + class PIC16TargetAsmInfo : public TargetAsmInfo { const char *RomData8bitsDirective; const char *RomData16bitsDirective; const char *RomData32bitsDirective; - const char *getRomDirective(unsigned size) const; - virtual const char *getDataASDirective(unsigned size, unsigned AS) const; - const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const; - const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const; - const Section *getSectionForAuto(const GlobalVariable *GV) const; - const Section *CreateBSSSectionForGlobal(const GlobalVariable *GV, - std::string Addr = "") const; - const Section *CreateIDATASectionForGlobal(const GlobalVariable *GV, - std::string Addr = "") const; - const Section *getROSectionForGlobal(const GlobalVariable *GV) const; - const Section *CreateROSectionForGlobal(const GlobalVariable *GV, - std::string Addr = "") const; - virtual const Section *SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind) const; - const Section *CreateSectionForGlobal(const GlobalVariable *GV, - const std::string &Addr = "") const; - public: - void SetSectionForGVs(Module &M); - const std::vector<PIC16Section*> &getBSSSections() const { - return BSSSections; - } - const std::vector<PIC16Section*> &getIDATASections() const { - return IDATASections; - } - const std::vector<PIC16Section*> &getAutosSections() const { - return AutosSections; - } - const std::vector<PIC16Section*> &getROSections() const { - return ROSections; - } - - /// getSpecialCasedSectionGlobals - Allow the target to completely override - /// section assignment of a global. - virtual const Section * - getSpecialCasedSectionGlobals(const GlobalValue *GV, - SectionKind Kind) const; + public: + PIC16TargetAsmInfo(const PIC16TargetMachine &TM); + + virtual const char *getDataASDirective(unsigned size, unsigned AS) const; }; } // namespace llvm diff --git a/lib/Target/PIC16/PIC16TargetObjectFile.cpp b/lib/Target/PIC16/PIC16TargetObjectFile.cpp new file mode 100644 index 0000000..efc03ac --- /dev/null +++ b/lib/Target/PIC16/PIC16TargetObjectFile.cpp @@ -0,0 +1,401 @@ +//===-- PIC16TargetObjectFile.cpp - PIC16 object files --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PIC16TargetObjectFile.h" +#include "PIC16ISelLowering.h" +#include "PIC16TargetMachine.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +using namespace llvm; + + +PIC16TargetObjectFile::PIC16TargetObjectFile(const PIC16TargetMachine &tm) +: TM (tm) { + BSSSection_ = getOrCreateSection("udata.# UDATA", false, SectionKind::BSS); + ReadOnlySection = getOrCreateSection("romdata.# ROMDATA", false, + SectionKind::ReadOnly); + DataSection = getOrCreateSection("idata.# IDATA", false,SectionKind::DataRel); + + // Need because otherwise a .text symbol is emitted by DwarfWriter + // in BeginModule, and gpasm cribbs for that .text symbol. + TextSection = getOrCreateSection("", true, SectionKind::Text); + + + PIC16Section *ROSection = new PIC16Section(ReadOnlySection); + ROSections.push_back(ROSection); + + // FIXME: I don't know what the classification of these sections really is. + ExternalVarDecls = new PIC16Section(getOrCreateSection("ExternalVarDecls", + false, + SectionKind::Metadata)); + ExternalVarDefs = new PIC16Section(getOrCreateSection("ExternalVarDefs", + false, + SectionKind::Metadata)); +} + + +const Section * +PIC16TargetObjectFile::getBSSSectionForGlobal(const GlobalVariable *GV) const { + assert(GV->hasInitializer() && "This global doesn't need space"); + Constant *C = GV->getInitializer(); + assert(C->isNullValue() && "Unitialized globals has non-zero initializer"); + + // Find how much space this global needs. + const TargetData *TD = TM.getTargetData(); + const Type *Ty = C->getType(); + unsigned ValSize = TD->getTypeAllocSize(Ty); + + // Go through all BSS Sections and assign this variable + // to the first available section having enough space. + PIC16Section *FoundBSS = NULL; + for (unsigned i = 0; i < BSSSections.size(); i++) { + if (DataBankSize - BSSSections[i]->Size >= ValSize) { + FoundBSS = BSSSections[i]; + break; + } + } + + // No BSS section spacious enough was found. Crate a new one. + if (!FoundBSS) { + std::string name = PAN::getUdataSectionName(BSSSections.size()); + const Section *NewSection = getOrCreateSection(name.c_str(), false, + // FIXME. + SectionKind::Metadata); + + FoundBSS = new PIC16Section(NewSection); + + // Add this newly created BSS section to the list of BSSSections. + BSSSections.push_back(FoundBSS); + } + + // Insert the GV into this BSS. + FoundBSS->Items.push_back(GV); + FoundBSS->Size += ValSize; + return FoundBSS->S_; +} + +const Section * +PIC16TargetObjectFile::getIDATASectionForGlobal(const GlobalVariable *GV) const{ + assert(GV->hasInitializer() && "This global doesn't need space"); + Constant *C = GV->getInitializer(); + assert(!C->isNullValue() && "initialized globals has zero initializer"); + assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE && + "can split initialized RAM data only"); + + // Find how much space this global needs. + const TargetData *TD = TM.getTargetData(); + const Type *Ty = C->getType(); + unsigned ValSize = TD->getTypeAllocSize(Ty); + + // Go through all IDATA Sections and assign this variable + // to the first available section having enough space. + PIC16Section *FoundIDATA = NULL; + for (unsigned i = 0; i < IDATASections.size(); i++) { + if (DataBankSize - IDATASections[i]->Size >= ValSize) { + FoundIDATA = IDATASections[i]; + break; + } + } + + // No IDATA section spacious enough was found. Crate a new one. + if (!FoundIDATA) { + std::string name = PAN::getIdataSectionName(IDATASections.size()); + const Section *NewSection = getOrCreateSection(name.c_str(), + false, + // FIXME. + SectionKind::Metadata); + + FoundIDATA = new PIC16Section(NewSection); + + // Add this newly created IDATA section to the list of IDATASections. + IDATASections.push_back(FoundIDATA); + } + + // Insert the GV into this IDATA. + FoundIDATA->Items.push_back(GV); + FoundIDATA->Size += ValSize; + return FoundIDATA->S_; +} + +// Get the section for an automatic variable of a function. +// For PIC16 they are globals only with mangled names. +const Section * +PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable *GV) const { + + const std::string name = PAN::getSectionNameForSym(GV->getName()); + + // Go through all Auto Sections and assign this variable + // to the appropriate section. + PIC16Section *FoundAutoSec = NULL; + for (unsigned i = 0; i < AutosSections.size(); i++) { + if (AutosSections[i]->S_->getName() == name) { + FoundAutoSec = AutosSections[i]; + break; + } + } + + // No Auto section was found. Crate a new one. + if (!FoundAutoSec) { + const Section *NewSection = getOrCreateSection(name.c_str(), + // FIXME. + false, + SectionKind::Metadata); + + FoundAutoSec = new PIC16Section(NewSection); + + // Add this newly created autos section to the list of AutosSections. + AutosSections.push_back(FoundAutoSec); + } + + // Insert the auto into this section. + FoundAutoSec->Items.push_back(GV); + + return FoundAutoSec->S_; +} + + +// Override default implementation to put the true globals into +// multiple data sections if required. +const Section* +PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1, + SectionKind Kind, + const TargetMachine &TM) const { + // We select the section based on the initializer here, so it really + // has to be a GlobalVariable. + const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1); + if (!GV) + return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Kind, TM); + + // Record External Var Decls. + if (GV->isDeclaration()) { + ExternalVarDecls->Items.push_back(GV); + return ExternalVarDecls->S_; + } + + assert(GV->hasInitializer() && "A def without initializer?"); + + // First, if this is an automatic variable for a function, get the section + // name for it and return. + std::string name = GV->getName(); + if (PAN::isLocalName(name)) + return getSectionForAuto(GV); + + // Record Exteranl Var Defs. + if (GV->hasExternalLinkage() || GV->hasCommonLinkage()) + ExternalVarDefs->Items.push_back(GV); + + // See if this is an uninitialized global. + const Constant *C = GV->getInitializer(); + if (C->isNullValue()) + return getBSSSectionForGlobal(GV); + + // If this is initialized data in RAM. Put it in the correct IDATA section. + if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) + return getIDATASectionForGlobal(GV); + + // This is initialized data in rom, put it in the readonly section. + if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) + return getROSectionForGlobal(GV); + + // Else let the default implementation take care of it. + return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, TM); +} + +PIC16TargetObjectFile::~PIC16TargetObjectFile() { + for (unsigned i = 0; i < BSSSections.size(); i++) + delete BSSSections[i]; + for (unsigned i = 0; i < IDATASections.size(); i++) + delete IDATASections[i]; + for (unsigned i = 0; i < AutosSections.size(); i++) + delete AutosSections[i]; + for (unsigned i = 0; i < ROSections.size(); i++) + delete ROSections[i]; + delete ExternalVarDecls; + delete ExternalVarDefs; +} + + +/// getSpecialCasedSectionGlobals - Allow the target to completely override +/// section assignment of a global. +const Section * +PIC16TargetObjectFile::getSpecialCasedSectionGlobals(const GlobalValue *GV, + SectionKind Kind) const { + // If GV has a sectin name or section address create that section now. + if (GV->hasSection()) { + if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) { + std::string SectName = GVar->getSection(); + // If address for a variable is specified, get the address and create + // section. + std::string AddrStr = "Address="; + if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) { + std::string SectAddr = SectName.substr(AddrStr.length()); + return CreateSectionForGlobal(GVar, SectAddr); + } + + // Create the section specified with section attribute. + return CreateSectionForGlobal(GVar); + } + } + + return 0; +} + +// Create a new section for global variable. If Addr is given then create +// section at that address else create by name. +const Section * +PIC16TargetObjectFile::CreateSectionForGlobal(const GlobalVariable *GV, + const std::string &Addr) const { + // See if this is an uninitialized global. + const Constant *C = GV->getInitializer(); + if (C->isNullValue()) + return CreateBSSSectionForGlobal(GV, Addr); + + // If this is initialized data in RAM. Put it in the correct IDATA section. + if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) + return CreateIDATASectionForGlobal(GV, Addr); + + // This is initialized data in rom, put it in the readonly section. + if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) + return CreateROSectionForGlobal(GV, Addr); + + // Else let the default implementation take care of it. + return TargetLoweringObjectFile::SectionForGlobal(GV, TM); +} + +// Create uninitialized section for a variable. +const Section * +PIC16TargetObjectFile::CreateBSSSectionForGlobal(const GlobalVariable *GV, + std::string Addr) const { + assert(GV->hasInitializer() && "This global doesn't need space"); + assert(GV->getInitializer()->isNullValue() && + "Unitialized global has non-zero initializer"); + std::string Name; + // If address is given then create a section at that address else create a + // section by section name specified in GV. + PIC16Section *FoundBSS = NULL; + if (Addr.empty()) { + Name = GV->getSection() + " UDATA"; + for (unsigned i = 0; i < BSSSections.size(); i++) { + if (BSSSections[i]->S_->getName() == Name) { + FoundBSS = BSSSections[i]; + break; + } + } + } else { + std::string Prefix = GV->getNameStr() + "." + Addr + "."; + Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr; + } + + PIC16Section *NewBSS = FoundBSS; + if (NewBSS == NULL) { + const Section *NewSection = getOrCreateSection(Name.c_str(), + false, SectionKind::BSS); + NewBSS = new PIC16Section(NewSection); + BSSSections.push_back(NewBSS); + } + + // Insert the GV into this BSS. + NewBSS->Items.push_back(GV); + + // We do not want to put any GV without explicit section into this section + // so set its size to DatabankSize. + NewBSS->Size = DataBankSize; + return NewBSS->S_; +} + +// Get rom section for a variable. Currently there can be only one rom section +// unless a variable explicitly requests a section. +const Section * +PIC16TargetObjectFile::getROSectionForGlobal(const GlobalVariable *GV) const { + ROSections[0]->Items.push_back(GV); + return ROSections[0]->S_; +} + +// Create initialized data section for a variable. +const Section * +PIC16TargetObjectFile::CreateIDATASectionForGlobal(const GlobalVariable *GV, + std::string Addr) const { + assert(GV->hasInitializer() && "This global doesn't need space"); + assert(!GV->getInitializer()->isNullValue() && + "initialized global has zero initializer"); + assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE && + "can be used for initialized RAM data only"); + + std::string Name; + // If address is given then create a section at that address else create a + // section by section name specified in GV. + PIC16Section *FoundIDATASec = NULL; + if (Addr.empty()) { + Name = GV->getSection() + " IDATA"; + for (unsigned i = 0; i < IDATASections.size(); i++) { + if (IDATASections[i]->S_->getName() == Name) { + FoundIDATASec = IDATASections[i]; + break; + } + } + } else { + std::string Prefix = GV->getNameStr() + "." + Addr + "."; + Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr; + } + + PIC16Section *NewIDATASec = FoundIDATASec; + if (NewIDATASec == NULL) { + const Section *NewSection = getOrCreateSection(Name.c_str(), + false, + // FIXME: + SectionKind::Metadata); + NewIDATASec = new PIC16Section(NewSection); + IDATASections.push_back(NewIDATASec); + } + // Insert the GV into this IDATA Section. + NewIDATASec->Items.push_back(GV); + // We do not want to put any GV without explicit section into this section + // so set its size to DatabankSize. + NewIDATASec->Size = DataBankSize; + return NewIDATASec->S_; +} + +// Create a section in rom for a variable. +const Section * +PIC16TargetObjectFile::CreateROSectionForGlobal(const GlobalVariable *GV, + std::string Addr) const { + assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE && + "can be used for ROM data only"); + + std::string Name; + // If address is given then create a section at that address else create a + // section by section name specified in GV. + PIC16Section *FoundROSec = NULL; + if (Addr.empty()) { + Name = GV->getSection() + " ROMDATA"; + for (unsigned i = 1; i < ROSections.size(); i++) { + if (ROSections[i]->S_->getName() == Name) { + FoundROSec = ROSections[i]; + break; + } + } + } else { + std::string Prefix = GV->getNameStr() + "." + Addr + "."; + Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr; + } + + PIC16Section *NewRomSec = FoundROSec; + if (NewRomSec == NULL) { + const Section *NewSection = getOrCreateSection(Name.c_str(), + false, + SectionKind::ReadOnly); + NewRomSec = new PIC16Section(NewSection); + ROSections.push_back(NewRomSec); + } + + // Insert the GV into this ROM Section. + NewRomSec->Items.push_back(GV); + return NewRomSec->S_; +} + diff --git a/lib/Target/PIC16/PIC16TargetObjectFile.h b/lib/Target/PIC16/PIC16TargetObjectFile.h new file mode 100644 index 0000000..77aea78 --- /dev/null +++ b/lib/Target/PIC16/PIC16TargetObjectFile.h @@ -0,0 +1,100 @@ +//===-- PIC16TargetObjectFile.h - PIC16 Object Info -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_PIC16_TARGETOBJECTFILE_H +#define LLVM_TARGET_PIC16_TARGETOBJECTFILE_H + +#include "llvm/Target/TargetLoweringObjectFile.h" +#include <vector> + +namespace llvm { + class GlobalVariable; + class Module; + class PIC16TargetMachine; + + enum { DataBankSize = 80 }; + + /// PIC16 Splits the global data into mulitple udata and idata sections. + /// Each udata and idata section needs to contain a list of globals that + /// they contain, in order to avoid scanning over all the global values + /// again and printing only those that match the current section. + /// Keeping values inside the sections make printing a section much easier. + /// + /// FIXME: Reimplement by inheriting from MCSection. + /// + struct PIC16Section { + const Section *S_; // Connection to actual Section. + unsigned Size; // Total size of the objects contained. + bool SectionPrinted; + std::vector<const GlobalVariable*> Items; + + PIC16Section(const Section *s) { + S_ = s; + Size = 0; + SectionPrinted = false; + } + bool isPrinted() const { return SectionPrinted; } + void setPrintedStatus(bool status) { SectionPrinted = status; } + }; + + class PIC16TargetObjectFile : public TargetLoweringObjectFile { + const PIC16TargetMachine &TM; + public: + mutable std::vector<PIC16Section*> BSSSections; + mutable std::vector<PIC16Section*> IDATASections; + mutable std::vector<PIC16Section*> AutosSections; + mutable std::vector<PIC16Section*> ROSections; + mutable PIC16Section *ExternalVarDecls; + mutable PIC16Section *ExternalVarDefs; + + PIC16TargetObjectFile(const PIC16TargetMachine &TM); + ~PIC16TargetObjectFile(); + + /// getSpecialCasedSectionGlobals - Allow the target to completely override + /// section assignment of a global. + virtual const Section * + getSpecialCasedSectionGlobals(const GlobalValue *GV, + SectionKind Kind) const; + virtual const Section *SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, + const TargetMachine&) const; + private: + std::string getSectionNameForSym(const std::string &Sym) const; + + const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const; + const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const; + const Section *getSectionForAuto(const GlobalVariable *GV) const; + const Section *CreateBSSSectionForGlobal(const GlobalVariable *GV, + std::string Addr = "") const; + const Section *CreateIDATASectionForGlobal(const GlobalVariable *GV, + std::string Addr = "") const; + const Section *getROSectionForGlobal(const GlobalVariable *GV) const; + const Section *CreateROSectionForGlobal(const GlobalVariable *GV, + std::string Addr = "") const; + const Section *CreateSectionForGlobal(const GlobalVariable *GV, + const std::string &Addr = "") const; + public: + void SetSectionForGVs(Module &M); + const std::vector<PIC16Section*> &getBSSSections() const { + return BSSSections; + } + const std::vector<PIC16Section*> &getIDATASections() const { + return IDATASections; + } + const std::vector<PIC16Section*> &getAutosSections() const { + return AutosSections; + } + const std::vector<PIC16Section*> &getROSections() const { + return ROSections; + } + + }; +} // end namespace llvm + +#endif diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp index bc0a794..a1b0780 100644 --- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -40,6 +40,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetOptions.h" @@ -590,7 +591,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { // Print out labels for the function. const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); switch (F->getLinkage()) { default: llvm_unreachable("Unknown linkage type!"); @@ -639,7 +640,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { // Print out jump tables referenced by the function. EmitJumpTableInfo(MF.getJumpTableInfo(), MF); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); // Emit post-function debug information. DW->EndFunction(&MF); @@ -681,7 +682,7 @@ void PPCLinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { unsigned Size = TD->getTypeAllocSize(Type); unsigned Align = TD->getPreferredAlignmentLog(GVar); - SwitchToSection(TAI->SectionForGlobal(GVar)); + SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM)); if (C->isNullValue() && /* FIXME: Verify correct */ !GVar->hasSection() && @@ -762,7 +763,7 @@ bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { // Print out labels for the function. const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); switch (F->getLinkage()) { default: llvm_unreachable("Unknown linkage type!"); @@ -861,7 +862,7 @@ bool PPCDarwinAsmPrinter::doInitialization(Module &M) { SwitchToTextSection("\t.section __TEXT,__symbol_stub1,symbol_stubs," "pure_instructions,16"); } - SwitchToSection(TAI->getTextSection()); + SwitchToSection(getObjFileLowering().getTextSection()); return Result; } @@ -891,7 +892,7 @@ void PPCDarwinAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { unsigned Size = TD->getTypeAllocSize(Type); unsigned Align = TD->getPreferredAlignmentLog(GVar); - const Section *TheSection = TAI->SectionForGlobal(GVar); + const Section *TheSection = getObjFileLowering().SectionForGlobal(GVar, TM); SwitchToSection(TheSection); if (C->isNullValue() && /* FIXME: Verify correct */ @@ -1051,7 +1052,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { } if (!HiddenGVStubs.empty()) { - SwitchToSection(TAI->getDataSection()); + SwitchToSection(getObjFileLowering().getDataSection()); EmitAlignment(isPPC64 ? 3 : 2); for (StringMap<std::string>::iterator I = HiddenGVStubs.begin(), E = HiddenGVStubs.end(); I != E; ++I) { diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 8beddd6..fa1989b 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -31,6 +31,7 @@ #include "llvm/Intrinsics.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -56,8 +57,15 @@ static cl::opt<bool> EnablePPCPreinc("enable-ppc-preinc", cl::desc("enable preincrement load/store generation on PPC (experimental)"), cl::Hidden); +static TargetLoweringObjectFile *CreateTLOF(const PPCTargetMachine &TM) { + if (TM.getSubtargetImpl()->isDarwin()) + return new TargetLoweringObjectFileMachO(); + return new TargetLoweringObjectFileELF(false, true); +} + + PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) - : TargetLowering(TM), PPCSubTarget(*TM.getSubtargetImpl()) { + : TargetLowering(TM, CreateTLOF(TM)), PPCSubTarget(*TM.getSubtargetImpl()) { setPow2DivIsCheap(); diff --git a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp index a56f965..5ddd120 100644 --- a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp +++ b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp @@ -70,9 +70,6 @@ PPCLinuxTargetAsmInfo::PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM) : WeakRefDirective = "\t.weak\t"; BSSSection = "\t.section\t\".sbss\",\"aw\",@nobits"; - // PPC/Linux normally uses named section for BSS. - BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); - // Debug Information AbsoluteDebugSectionOffsets = true; SupportsDebugInformation = true; diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp index ad99cca..7569eee 100644 --- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp @@ -26,6 +26,7 @@ #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" @@ -95,7 +96,7 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) { // Print out the label for the function. const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); EmitAlignment(MF.getAlignment(), F); O << "\t.globl\t" << CurrentFnName << '\n'; @@ -229,7 +230,7 @@ void SparcAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { printVisibility(name, GVar->getVisibility()); - SwitchToSection(TAI->SectionForGlobal(GVar)); + SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM)); if (C->isNullValue() && !GVar->hasSection()) { if (!GVar->isThreadLocal() && diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index fe7bf93..16d9229 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/ADT/VectorExtras.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -548,9 +549,31 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { } } +class TargetLoweringObjectFileSparc : public TargetLoweringObjectFileELF { +public: + void getSectionFlagsAsString(SectionKind Kind, + SmallVectorImpl<char> &Str) const { + if (Kind.isMergeableConst() || Kind.isMergeableCString()) + return TargetLoweringObjectFileELF::getSectionFlagsAsString(Kind, Str); + + // FIXME: Inefficient. + std::string Res; + if (!Kind.isMetadata()) + Res += ",#alloc"; + if (Kind.isText()) + Res += ",#execinstr"; + if (Kind.isWriteable()) + Res += ",#write"; + if (Kind.isThreadLocal()) + Res += ",#tls"; + + Str.append(Res.begin(), Res.end()); + } +}; + SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) - : TargetLowering(TM) { + : TargetLowering(TM, new TargetLoweringObjectFileSparc()) { // Set up the register classes. addRegisterClass(MVT::i32, SP::IntRegsRegisterClass); diff --git a/lib/Target/Sparc/SparcTargetAsmInfo.cpp b/lib/Target/Sparc/SparcTargetAsmInfo.cpp index 59897e6..169eda7 100644 --- a/lib/Target/Sparc/SparcTargetAsmInfo.cpp +++ b/lib/Target/Sparc/SparcTargetAsmInfo.cpp @@ -25,27 +25,6 @@ SparcELFTargetAsmInfo::SparcELFTargetAsmInfo(const TargetMachine &TM) ConstantPoolSection = "\t.section \".rodata\",#alloc\n"; COMMDirectiveTakesAlignment = true; CStringSection=".rodata.str"; - - // Sparc normally uses named section for BSS. - BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); } -void SparcELFTargetAsmInfo::getSectionFlagsAsString(SectionKind Kind, - SmallVectorImpl<char> &Str) const { - if (Kind.isMergeableConst() || Kind.isMergeableCString()) - return ELFTargetAsmInfo::getSectionFlagsAsString(Kind, Str); - - // FIXME: Inefficient. - std::string Res; - if (!Kind.isMetadata()) - Res += ",#alloc"; - if (Kind.isText()) - Res += ",#execinstr"; - if (Kind.isWriteable()) - Res += ",#write"; - if (Kind.isThreadLocal()) - Res += ",#tls"; - - Str.append(Res.begin(), Res.end()); -} diff --git a/lib/Target/Sparc/SparcTargetAsmInfo.h b/lib/Target/Sparc/SparcTargetAsmInfo.h index 943dcef..ae646c3 100644 --- a/lib/Target/Sparc/SparcTargetAsmInfo.h +++ b/lib/Target/Sparc/SparcTargetAsmInfo.h @@ -23,10 +23,6 @@ namespace llvm { struct SparcELFTargetAsmInfo : public ELFTargetAsmInfo { explicit SparcELFTargetAsmInfo(const TargetMachine &TM); - - virtual void getSectionFlagsAsString(SectionKind Kind, - SmallVectorImpl<char> &Str) const; - }; } // namespace llvm diff --git a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp index 7a16684..9a9a4b7 100644 --- a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp +++ b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Compiler.h" @@ -82,7 +83,7 @@ void SystemZAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { unsigned FnAlign = MF.getAlignment(); const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); EmitAlignment(FnAlign, F); @@ -330,7 +331,7 @@ void SystemZAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { O << "\t.type\t" << name << ",@object\n"; - SwitchToSection(TAI->SectionForGlobal(GVar)); + SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM)); if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() && diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 8a159d7..38b4c30 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -31,13 +31,15 @@ #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Support/Debug.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Support/Debug.h" #include "llvm/ADT/VectorExtras.h" using namespace llvm; SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) : - TargetLowering(tm), Subtarget(*tm.getSubtargetImpl()), TM(tm) { + TargetLowering(tm, new TargetLoweringObjectFileELF()), + Subtarget(*tm.getSubtargetImpl()), TM(tm) { RegInfo = TM.getRegisterInfo(); diff --git a/lib/Target/SystemZ/SystemZTargetAsmInfo.cpp b/lib/Target/SystemZ/SystemZTargetAsmInfo.cpp index 0079586..25048b8 100644 --- a/lib/Target/SystemZ/SystemZTargetAsmInfo.cpp +++ b/lib/Target/SystemZ/SystemZTargetAsmInfo.cpp @@ -27,6 +27,4 @@ SystemZTargetAsmInfo::SystemZTargetAsmInfo(const SystemZTargetMachine &TM) PCSymbol = "."; NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits"; - - BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); } diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp index 1cb085b..e71bd01 100644 --- a/lib/Target/TargetAsmInfo.cpp +++ b/lib/Target/TargetAsmInfo.cpp @@ -30,10 +30,6 @@ using namespace llvm; TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm) : TM(tm) { BSSSection = "\t.bss"; - BSSSection_ = 0; - ReadOnlySection = 0; - TLSDataSection = 0; - TLSBSSSection = 0; ZeroFillDirective = 0; NonexecutableStackDirective = 0; NeedsSet = false; @@ -78,7 +74,6 @@ TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm) : TM(tm) { JumpTableDataSection = "\t.section .rodata"; JumpTableDirective = 0; CStringSection = 0; - CStringSection_ = 0; // FIXME: Flags are ELFish - replace with normal section stuff. StaticCtorsSection = "\t.section .ctors,\"aw\",@progbits"; StaticDtorsSection = "\t.section .dtors,\"aw\",@progbits"; @@ -158,219 +153,6 @@ unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason, return dwarf::DW_EH_PE_absptr; } -static bool isSuitableForBSS(const GlobalVariable *GV) { - Constant *C = GV->getInitializer(); - - // Must have zero initializer. - if (!C->isNullValue()) - return false; - - // Leave constant zeros in readonly constant sections, so they can be shared. - if (GV->isConstant()) - return false; - - // If the global has an explicit section specified, don't put it in BSS. - if (!GV->getSection().empty()) - return false; - - // If -nozero-initialized-in-bss is specified, don't ever use BSS. - if (NoZerosInBSS) - return false; - - // Otherwise, put it in BSS! - return true; -} - -static bool isConstantString(const Constant *C) { - // First check: is we have constant array of i8 terminated with zero - const ConstantArray *CVA = dyn_cast<ConstantArray>(C); - // Check, if initializer is a null-terminated string - if (CVA && CVA->isCString()) - return true; - - // Another possibility: [1 x i8] zeroinitializer - if (isa<ConstantAggregateZero>(C)) - if (const ArrayType *Ty = dyn_cast<ArrayType>(C->getType())) - return (Ty->getElementType() == Type::Int8Ty && - Ty->getNumElements() == 1); - - return false; -} - -static SectionKind::Kind SectionKindForGlobal(const GlobalValue *GV, - const TargetMachine &TM) { - Reloc::Model ReloModel = TM.getRelocationModel(); - - // Early exit - functions should be always in text sections. - const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); - if (GVar == 0) - return SectionKind::Text; - - - // Handle thread-local data first. - if (GVar->isThreadLocal()) { - if (isSuitableForBSS(GVar)) - return SectionKind::ThreadBSS; - return SectionKind::ThreadData; - } - - // Variable can be easily put to BSS section. - if (isSuitableForBSS(GVar)) - return SectionKind::BSS; - - Constant *C = GVar->getInitializer(); - - // If the global is marked constant, we can put it into a mergable section, - // a mergable string section, or general .data if it contains relocations. - if (GVar->isConstant()) { - // If the initializer for the global contains something that requires a - // relocation, then we may have to drop this into a wriable data section - // even though it is marked const. - switch (C->getRelocationInfo()) { - default: llvm_unreachable("unknown relocation info kind"); - case Constant::NoRelocation: - // If initializer is a null-terminated string, put it in a "cstring" - // section if the target has it. - if (isConstantString(C)) - return SectionKind::MergeableCString; - - // Otherwise, just drop it into a mergable constant section. If we have - // a section for this size, use it, otherwise use the arbitrary sized - // mergable section. - switch (TM.getTargetData()->getTypeAllocSize(C->getType())) { - case 4: return SectionKind::MergeableConst4; - case 8: return SectionKind::MergeableConst8; - case 16: return SectionKind::MergeableConst16; - default: return SectionKind::MergeableConst; - } - - case Constant::LocalRelocation: - // In static relocation model, the linker will resolve all addresses, so - // the relocation entries will actually be constants by the time the app - // starts up. However, we can't put this into a mergable section, because - // the linker doesn't take relocations into consideration when it tries to - // merge entries in the section. - if (ReloModel == Reloc::Static) - return SectionKind::ReadOnly; - - // Otherwise, the dynamic linker needs to fix it up, put it in the - // writable data.rel.local section. - return SectionKind::ReadOnlyWithRelLocal; - - case Constant::GlobalRelocations: - // In static relocation model, the linker will resolve all addresses, so - // the relocation entries will actually be constants by the time the app - // starts up. However, we can't put this into a mergable section, because - // the linker doesn't take relocations into consideration when it tries to - // merge entries in the section. - if (ReloModel == Reloc::Static) - return SectionKind::ReadOnly; - - // Otherwise, the dynamic linker needs to fix it up, put it in the - // writable data.rel section. - return SectionKind::ReadOnlyWithRel; - } - } - - // Okay, this isn't a constant. If the initializer for the global is going - // to require a runtime relocation by the dynamic linker, put it into a more - // specific section to improve startup time of the app. This coalesces these - // globals together onto fewer pages, improving the locality of the dynamic - // linker. - if (ReloModel == Reloc::Static) - return SectionKind::DataNoRel; - - switch (C->getRelocationInfo()) { - default: llvm_unreachable("unknown relocation info kind"); - case Constant::NoRelocation: - return SectionKind::DataNoRel; - case Constant::LocalRelocation: - return SectionKind::DataRelLocal; - case Constant::GlobalRelocations: - return SectionKind::DataRel; - } -} - -/// SectionForGlobal - This method computes the appropriate section to emit -/// the specified global variable or function definition. This should not -/// be passed external (or available externally) globals. -const Section *TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const { - assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() && - "Can only be used for global definitions"); - - SectionKind::Kind GVKind = SectionKindForGlobal(GV, TM); - - SectionKind Kind = SectionKind::get(GVKind, GV->isWeakForLinker(), - GV->hasSection()); - - - // Select section name. - if (GV->hasSection()) { - // If the target has special section hacks for specifically named globals, - // return them now. - if (const Section *TS = getSpecialCasedSectionGlobals(GV, Kind)) - return TS; - - // If the target has magic semantics for certain section names, make sure to - // pick up the flags. This allows the user to write things with attribute - // section and still get the appropriate section flags printed. - GVKind = getKindForNamedSection(GV->getSection().c_str(), GVKind); - - return getOrCreateSection(GV->getSection().c_str(), false, GVKind); - } - - - // Use default section depending on the 'type' of global - return SelectSectionForGlobal(GV, Kind); -} - -// Lame default implementation. Calculate the section name for global. -const Section* -TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind) const { - assert(!Kind.isThreadLocal() && "Doesn't support TLS"); - - if (Kind.isText()) - return getTextSection(); - - if (Kind.isBSS()) - if (const Section *S = getBSSSection_()) - return S; - - if (Kind.isReadOnly()) - if (const Section *S = getReadOnlySection()) - return S; - - return getDataSection(); -} - -/// getSectionForMergableConstant - Given a mergable constant with the -/// specified size and relocation information, return a section that it -/// should be placed in. -const Section * -TargetAsmInfo::getSectionForMergeableConstant(SectionKind Kind) const { - if (Kind.isReadOnly()) - if (const Section *S = getReadOnlySection()) - return S; - - return getDataSection(); -} - - -const Section *TargetAsmInfo::getOrCreateSection(const char *Name, - bool isDirective, - SectionKind::Kind Kind) const { - Section &S = Sections[Name]; - - // This is newly-created section, set it up properly. - if (S.Name.empty()) { - S.Kind = SectionKind::get(Kind, false /*weak*/, !isDirective); - S.Name = Name; - } - - return &S; -} - unsigned TargetAsmInfo::getULEB128Size(unsigned Value) { unsigned Size = 0; do { diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp new file mode 100644 index 0000000..b1d9c9a --- /dev/null +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -0,0 +1,647 @@ +//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Generic Code +//===----------------------------------------------------------------------===// + +TargetLoweringObjectFile::TargetLoweringObjectFile() { + TextSection = 0; + DataSection = 0; + BSSSection_ = 0; + ReadOnlySection = 0; + TLSDataSection = 0; + TLSBSSSection = 0; + CStringSection_ = 0; +} + +TargetLoweringObjectFile::~TargetLoweringObjectFile() { +} + +static bool isSuitableForBSS(const GlobalVariable *GV) { + Constant *C = GV->getInitializer(); + + // Must have zero initializer. + if (!C->isNullValue()) + return false; + + // Leave constant zeros in readonly constant sections, so they can be shared. + if (GV->isConstant()) + return false; + + // If the global has an explicit section specified, don't put it in BSS. + if (!GV->getSection().empty()) + return false; + + // If -nozero-initialized-in-bss is specified, don't ever use BSS. + if (NoZerosInBSS) + return false; + + // Otherwise, put it in BSS! + return true; +} + +static bool isConstantString(const Constant *C) { + // First check: is we have constant array of i8 terminated with zero + const ConstantArray *CVA = dyn_cast<ConstantArray>(C); + // Check, if initializer is a null-terminated string + if (CVA && CVA->isCString()) + return true; + + // Another possibility: [1 x i8] zeroinitializer + if (isa<ConstantAggregateZero>(C)) + if (const ArrayType *Ty = dyn_cast<ArrayType>(C->getType())) + return (Ty->getElementType() == Type::Int8Ty && + Ty->getNumElements() == 1); + + return false; +} + +static SectionKind::Kind SectionKindForGlobal(const GlobalValue *GV, + const TargetMachine &TM) { + Reloc::Model ReloModel = TM.getRelocationModel(); + + // Early exit - functions should be always in text sections. + const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); + if (GVar == 0) + return SectionKind::Text; + + + // Handle thread-local data first. + if (GVar->isThreadLocal()) { + if (isSuitableForBSS(GVar)) + return SectionKind::ThreadBSS; + return SectionKind::ThreadData; + } + + // Variable can be easily put to BSS section. + if (isSuitableForBSS(GVar)) + return SectionKind::BSS; + + Constant *C = GVar->getInitializer(); + + // If the global is marked constant, we can put it into a mergable section, + // a mergable string section, or general .data if it contains relocations. + if (GVar->isConstant()) { + // If the initializer for the global contains something that requires a + // relocation, then we may have to drop this into a wriable data section + // even though it is marked const. + switch (C->getRelocationInfo()) { + default: llvm_unreachable("unknown relocation info kind"); + case Constant::NoRelocation: + // If initializer is a null-terminated string, put it in a "cstring" + // section if the target has it. + if (isConstantString(C)) + return SectionKind::MergeableCString; + + // Otherwise, just drop it into a mergable constant section. If we have + // a section for this size, use it, otherwise use the arbitrary sized + // mergable section. + switch (TM.getTargetData()->getTypeAllocSize(C->getType())) { + case 4: return SectionKind::MergeableConst4; + case 8: return SectionKind::MergeableConst8; + case 16: return SectionKind::MergeableConst16; + default: return SectionKind::MergeableConst; + } + + case Constant::LocalRelocation: + // In static relocation model, the linker will resolve all addresses, so + // the relocation entries will actually be constants by the time the app + // starts up. However, we can't put this into a mergable section, because + // the linker doesn't take relocations into consideration when it tries to + // merge entries in the section. + if (ReloModel == Reloc::Static) + return SectionKind::ReadOnly; + + // Otherwise, the dynamic linker needs to fix it up, put it in the + // writable data.rel.local section. + return SectionKind::ReadOnlyWithRelLocal; + + case Constant::GlobalRelocations: + // In static relocation model, the linker will resolve all addresses, so + // the relocation entries will actually be constants by the time the app + // starts up. However, we can't put this into a mergable section, because + // the linker doesn't take relocations into consideration when it tries to + // merge entries in the section. + if (ReloModel == Reloc::Static) + return SectionKind::ReadOnly; + + // Otherwise, the dynamic linker needs to fix it up, put it in the + // writable data.rel section. + return SectionKind::ReadOnlyWithRel; + } + } + + // Okay, this isn't a constant. If the initializer for the global is going + // to require a runtime relocation by the dynamic linker, put it into a more + // specific section to improve startup time of the app. This coalesces these + // globals together onto fewer pages, improving the locality of the dynamic + // linker. + if (ReloModel == Reloc::Static) + return SectionKind::DataNoRel; + + switch (C->getRelocationInfo()) { + default: llvm_unreachable("unknown relocation info kind"); + case Constant::NoRelocation: + return SectionKind::DataNoRel; + case Constant::LocalRelocation: + return SectionKind::DataRelLocal; + case Constant::GlobalRelocations: + return SectionKind::DataRel; + } +} + +/// SectionForGlobal - This method computes the appropriate section to emit +/// the specified global variable or function definition. This should not +/// be passed external (or available externally) globals. +const Section *TargetLoweringObjectFile:: +SectionForGlobal(const GlobalValue *GV, const TargetMachine &TM) const { + assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() && + "Can only be used for global definitions"); + + SectionKind::Kind GVKind = SectionKindForGlobal(GV, TM); + + SectionKind Kind = SectionKind::get(GVKind, GV->isWeakForLinker(), + GV->hasSection()); + + + // Select section name. + if (GV->hasSection()) { + // If the target has special section hacks for specifically named globals, + // return them now. + if (const Section *TS = getSpecialCasedSectionGlobals(GV, Kind)) + return TS; + + // If the target has magic semantics for certain section names, make sure to + // pick up the flags. This allows the user to write things with attribute + // section and still get the appropriate section flags printed. + GVKind = getKindForNamedSection(GV->getSection().c_str(), GVKind); + + return getOrCreateSection(GV->getSection().c_str(), false, GVKind); + } + + + // Use default section depending on the 'type' of global + return SelectSectionForGlobal(GV, Kind, TM); +} + +// Lame default implementation. Calculate the section name for global. +const Section* +TargetLoweringObjectFile::SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, + const TargetMachine &TM) const{ + assert(!Kind.isThreadLocal() && "Doesn't support TLS"); + + if (Kind.isText()) + return getTextSection(); + + if (Kind.isBSS() && BSSSection_ != 0) + return BSSSection_; + + if (Kind.isReadOnly() && ReadOnlySection != 0) + return ReadOnlySection; + + return getDataSection(); +} + +/// getSectionForMergableConstant - Given a mergable constant with the +/// specified size and relocation information, return a section that it +/// should be placed in. +const Section * +TargetLoweringObjectFile:: +getSectionForMergeableConstant(SectionKind Kind) const { + if (Kind.isReadOnly() && ReadOnlySection != 0) + return ReadOnlySection; + + return DataSection; +} + + +const Section *TargetLoweringObjectFile:: +getOrCreateSection(const char *Name, bool isDirective, + SectionKind::Kind Kind) const { + Section &S = Sections[Name]; + + // This is newly-created section, set it up properly. + if (S.Name.empty()) { + S.Kind = SectionKind::get(Kind, false /*weak*/, !isDirective); + S.Name = Name; + } + + return &S; +} + + + +//===----------------------------------------------------------------------===// +// ELF +//===----------------------------------------------------------------------===// + +TargetLoweringObjectFileELF::TargetLoweringObjectFileELF(bool atIsCommentChar, + bool HasCrazyBSS) + : AtIsCommentChar(atIsCommentChar) { + + if (!HasCrazyBSS) + BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); + else + // PPC/Linux doesn't support the .bss directive, it needs .section .bss. + // FIXME: Does .section .bss work everywhere?? + BSSSection_ = getOrCreateSection("\t.bss", false, SectionKind::BSS); + + + TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); + DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel); + ReadOnlySection = + getOrCreateSection("\t.rodata", false, SectionKind::ReadOnly); + TLSDataSection = + getOrCreateSection("\t.tdata", false, SectionKind::ThreadData); + CStringSection_ = getOrCreateSection("\t.rodata.str", true, + SectionKind::MergeableCString); + + TLSBSSSection = getOrCreateSection("\t.tbss", false, SectionKind::ThreadBSS); + + DataRelSection = getOrCreateSection("\t.data.rel", false, + SectionKind::DataRel); + DataRelLocalSection = getOrCreateSection("\t.data.rel.local", false, + SectionKind::DataRelLocal); + DataRelROSection = getOrCreateSection("\t.data.rel.ro", false, + SectionKind::ReadOnlyWithRel); + DataRelROLocalSection = + getOrCreateSection("\t.data.rel.ro.local", false, + SectionKind::ReadOnlyWithRelLocal); + + MergeableConst4Section = getOrCreateSection(".rodata.cst4", false, + SectionKind::MergeableConst4); + MergeableConst8Section = getOrCreateSection(".rodata.cst8", false, + SectionKind::MergeableConst8); + MergeableConst16Section = getOrCreateSection(".rodata.cst16", false, + SectionKind::MergeableConst16); +} + + +SectionKind::Kind TargetLoweringObjectFileELF:: +getKindForNamedSection(const char *Name, SectionKind::Kind K) const { + if (Name[0] != '.') return K; + + // Some lame default implementation based on some magic section names. + if (strncmp(Name, ".gnu.linkonce.b.", 16) == 0 || + strncmp(Name, ".llvm.linkonce.b.", 17) == 0 || + strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 || + strncmp(Name, ".llvm.linkonce.sb.", 18) == 0) + return SectionKind::BSS; + + if (strcmp(Name, ".tdata") == 0 || + strncmp(Name, ".tdata.", 7) == 0 || + strncmp(Name, ".gnu.linkonce.td.", 17) == 0 || + strncmp(Name, ".llvm.linkonce.td.", 18) == 0) + return SectionKind::ThreadData; + + if (strcmp(Name, ".tbss") == 0 || + strncmp(Name, ".tbss.", 6) == 0 || + strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 || + strncmp(Name, ".llvm.linkonce.tb.", 18) == 0) + return SectionKind::ThreadBSS; + + return K; +} + +void TargetLoweringObjectFileELF:: +getSectionFlagsAsString(SectionKind Kind, SmallVectorImpl<char> &Str) const { + Str.push_back(','); + Str.push_back('"'); + + if (!Kind.isMetadata()) + Str.push_back('a'); + if (Kind.isText()) + Str.push_back('x'); + if (Kind.isWriteable()) + Str.push_back('w'); + if (Kind.isMergeableConst() || Kind.isMergeableCString()) + Str.push_back('M'); + if (Kind.isMergeableCString()) + Str.push_back('S'); + if (Kind.isThreadLocal()) + Str.push_back('T'); + + Str.push_back('"'); + Str.push_back(','); + + // If comment string is '@', e.g. as on ARM - use '%' instead + if (AtIsCommentChar) + Str.push_back('%'); + else + Str.push_back('@'); + + const char *KindStr; + if (Kind.isBSS()) + KindStr = "nobits"; + else + KindStr = "progbits"; + + Str.append(KindStr, KindStr+strlen(KindStr)); + + if (Kind.isMergeableCString()) { + // TODO: Eventually handle multiple byte character strings. For now, all + // mergable C strings are single byte. + Str.push_back(','); + Str.push_back('1'); + } else if (Kind.isMergeableConst4()) { + Str.push_back(','); + Str.push_back('4'); + } else if (Kind.isMergeableConst8()) { + Str.push_back(','); + Str.push_back('8'); + } else if (Kind.isMergeableConst16()) { + Str.push_back(','); + Str.push_back('1'); + Str.push_back('6'); + } +} + + +static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) return ".gnu.linkonce.t."; + if (Kind.isReadOnly()) return ".gnu.linkonce.r."; + + if (Kind.isThreadData()) return ".gnu.linkonce.td."; + if (Kind.isThreadBSS()) return ".gnu.linkonce.tb."; + + if (Kind.isBSS()) return ".gnu.linkonce.b."; + if (Kind.isDataNoRel()) return ".gnu.linkonce.d."; + if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local."; + if (Kind.isDataRel()) return ".gnu.linkonce.d.rel."; + if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local."; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return ".gnu.linkonce.d.rel.ro."; +} + +const Section *TargetLoweringObjectFileELF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + const TargetMachine &TM) const { + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (Kind.isWeak()) { + const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); + // FIXME: Use mangler interface (PR4584). + std::string Name = Prefix+GV->getNameStr(); + return getOrCreateSection(Name.c_str(), false, Kind.getKind()); + } + + if (Kind.isText()) return TextSection; + if (Kind.isMergeableCString()) { + Constant *C = cast<GlobalVariable>(GV)->getInitializer(); + + // FIXME: This is completely wrong. Why is it comparing the size of the + // character type to 1? + /// cast<ArrayType>(C->getType())->getNumElements(); + uint64_t Size = 1; + if (Size <= 16) { + assert(CStringSection_ && "Should have string section prefix"); + + // We also need alignment here. + // FIXME: this is getting the alignment of the character, not the + // alignment of the global! + unsigned Align = + TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV)); + + std::string Name = CStringSection_->getName() + utostr(Size) + '.' + + utostr(Align); + return getOrCreateSection(Name.c_str(), false, + SectionKind::MergeableCString); + } + + return ReadOnlySection; + } + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4()) + return MergeableConst4Section; + if (Kind.isMergeableConst8()) + return MergeableConst8Section; + if (Kind.isMergeableConst16()) + return MergeableConst16Section; + return ReadOnlySection; // .const + } + + if (Kind.isReadOnly()) return ReadOnlySection; + + if (Kind.isThreadData()) return TLSDataSection; + if (Kind.isThreadBSS()) return TLSBSSSection; + + if (Kind.isBSS()) return BSSSection_; + + if (Kind.isDataNoRel()) return DataSection; + if (Kind.isDataRelLocal()) return DataRelLocalSection; + if (Kind.isDataRel()) return DataRelSection; + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +/// getSectionForMergeableConstant - Given a mergeable constant with the +/// specified size and relocation information, return a section that it +/// should be placed in. +const Section *TargetLoweringObjectFileELF:: +getSectionForMergeableConstant(SectionKind Kind) const { + if (Kind.isMergeableConst4()) + return MergeableConst4Section; + if (Kind.isMergeableConst8()) + return MergeableConst8Section; + if (Kind.isMergeableConst16()) + return MergeableConst16Section; + if (Kind.isReadOnly()) + return ReadOnlySection; + + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +//===----------------------------------------------------------------------===// +// MachO +//===----------------------------------------------------------------------===// + +TargetLoweringObjectFileMachO:: +TargetLoweringObjectFileMachO() { + TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); + DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel); + + CStringSection_ = getOrCreateSection("\t.cstring", true, + SectionKind::MergeableCString); + FourByteConstantSection = getOrCreateSection("\t.literal4\n", true, + SectionKind::MergeableConst4); + EightByteConstantSection = getOrCreateSection("\t.literal8\n", true, + SectionKind::MergeableConst8); + SixteenByteConstantSection = + getOrCreateSection("\t.literal16\n", true, SectionKind::MergeableConst16); + + ReadOnlySection = getOrCreateSection("\t.const", true, SectionKind::ReadOnly); + + TextCoalSection = + getOrCreateSection("\t__TEXT,__textcoal_nt,coalesced,pure_instructions", + false, SectionKind::Text); + ConstTextCoalSection = getOrCreateSection("\t__TEXT,__const_coal,coalesced", + false, SectionKind::Text); + ConstDataCoalSection = getOrCreateSection("\t__DATA,__const_coal,coalesced", + false, SectionKind::Text); + ConstDataSection = getOrCreateSection("\t.const_data", true, + SectionKind::ReadOnlyWithRel); + DataCoalSection = getOrCreateSection("\t__DATA,__datacoal_nt,coalesced", + false, SectionKind::DataRel); +} + +const Section * +TargetLoweringObjectFileMachO::SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, + const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); + + if (Kind.isText()) + return Kind.isWeak() ? TextCoalSection : TextSection; + + // If this is weak/linkonce, put this in a coalescable section, either in text + // or data depending on if it is writable. + if (Kind.isWeak()) { + if (Kind.isReadOnly()) + return ConstTextCoalSection; + return DataCoalSection; + } + + // FIXME: Alignment check should be handled by section classifier. + if (Kind.isMergeableCString()) { + Constant *C = cast<GlobalVariable>(GV)->getInitializer(); + const Type *Ty = cast<ArrayType>(C->getType())->getElementType(); + const TargetData &TD = *TM.getTargetData(); + unsigned Size = TD.getTypeAllocSize(Ty); + if (Size) { + unsigned Align = TD.getPreferredAlignment(cast<GlobalVariable>(GV)); + if (Align <= 32) + return CStringSection_; + } + + return ReadOnlySection; + } + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16()) + return SixteenByteConstantSection; + return ReadOnlySection; // .const + } + + // FIXME: ROData -> const in -static mode that is relocatable but they happen + // by the static linker. Why not mergeable? + if (Kind.isReadOnly()) + return ReadOnlySection; + + // If this is marked const, put it into a const section. But if the dynamic + // linker needs to write to it, put it in the data segment. + if (Kind.isReadOnlyWithRel()) + return ConstDataSection; + + // Otherwise, just drop the variable in the normal data section. + return DataSection; +} + +const Section * +TargetLoweringObjectFileMachO:: +getSectionForMergeableConstant(SectionKind Kind) const { + // If this constant requires a relocation, we have to put it in the data + // segment, not in the text segment. + if (Kind.isDataRel()) + return ConstDataSection; + + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16()) + return SixteenByteConstantSection; + return ReadOnlySection; // .const +} + +//===----------------------------------------------------------------------===// +// COFF +//===----------------------------------------------------------------------===// + +TargetLoweringObjectFileCOFF::TargetLoweringObjectFileCOFF() { + TextSection = getOrCreateSection("_text", true, SectionKind::Text); + DataSection = getOrCreateSection("_data", true, SectionKind::DataRel); +} + +void TargetLoweringObjectFileCOFF:: +getSectionFlagsAsString(SectionKind Kind, SmallVectorImpl<char> &Str) const { + // FIXME: Inefficient. + std::string Res = ",\""; + if (Kind.isText()) + Res += 'x'; + if (Kind.isWriteable()) + Res += 'w'; + Res += "\""; + + Str.append(Res.begin(), Res.end()); +} + +static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) + return ".text$linkonce"; + if (Kind.isWriteable()) + return ".data$linkonce"; + return ".rdata$linkonce"; +} + + +const Section *TargetLoweringObjectFileCOFF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Doesn't support TLS"); + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (Kind.isWeak()) { + const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind); + // FIXME: Use mangler interface (PR4584). + std::string Name = Prefix+GV->getNameStr(); + return getOrCreateSection(Name.c_str(), false, Kind.getKind()); + } + + if (Kind.isText()) + return getTextSection(); + + if (Kind.isBSS()) + if (const Section *S = BSSSection_) + return S; + + if (Kind.isReadOnly() && ReadOnlySection != 0) + return ReadOnlySection; + + return getDataSection(); +} + diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp index 88c6434..a93510b 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp @@ -37,6 +37,7 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Mangler.h" #include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -166,7 +167,7 @@ void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { if (Subtarget->isTargetCygMing()) DecorateCygMingName(CurrentFnName, F); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); switch (F->getLinkage()) { default: llvm_unreachable("Unknown linkage type!"); case Function::InternalLinkage: // Symbols default to internal. @@ -782,7 +783,7 @@ void X86ATTAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { if (Subtarget->isTargetELF()) O << "\t.type\t" << name << ",@object\n"; - const Section *TheSection = TAI->SectionForGlobal(GVar); + const Section *TheSection = getObjFileLowering().SectionForGlobal(GVar, TM); SwitchToSection(TheSection); if (C->isNullValue() && !GVar->hasSection() && @@ -931,7 +932,7 @@ bool X86ATTAsmPrinter::doFinalization(Module &M) { } if (!HiddenGVStubs.empty()) { - SwitchToSection(TAI->getDataSection()); + SwitchToSection(getObjFileLowering().getDataSection()); EmitAlignment(2); for (StringMap<std::string>::iterator I = HiddenGVStubs.begin(), E = HiddenGVStubs.end(); I != E; ++I) diff --git a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp index 6b09b64..337fc79 100644 --- a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Mangler.h" #include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -513,7 +514,7 @@ void X86IntelAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) { O << "\tpublic " << name << "\n"; // FALL THROUGH case GlobalValue::InternalLinkage: - SwitchToSection(TAI->getDataSection()); + SwitchToSection(getObjFileLowering().getDataSection()); break; default: llvm_unreachable("Unknown linkage type!"); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 42bd7dc..29f5765 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" @@ -50,8 +51,23 @@ DisableMMX("disable-mmx", cl::Hidden, cl::desc("Disable use of MMX")); static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, SDValue V2); +static TargetLoweringObjectFile *createTLOF(X86TargetMachine &TM) { + switch (TM.getSubtarget<X86Subtarget>().TargetType) { + default: llvm_unreachable("unknown subtarget type"); + case X86Subtarget::isDarwin: + return new TargetLoweringObjectFileMachO(); + case X86Subtarget::isELF: + return new TargetLoweringObjectFileELF(); + case X86Subtarget::isMingw: + case X86Subtarget::isCygwin: + case X86Subtarget::isWindows: + return new TargetLoweringObjectFileCOFF(); + } + +} + X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) - : TargetLowering(TM) { + : TargetLowering(TM, createTLOF(TM)) { Subtarget = &TM.getSubtarget<X86Subtarget>(); X86ScalarSSEf64 = Subtarget->hasSSE2(); X86ScalarSSEf32 = Subtarget->hasSSE1(); diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp index 40c46bb..b4f503b 100644 --- a/lib/Target/X86/X86TargetAsmInfo.cpp +++ b/lib/Target/X86/X86TargetAsmInfo.cpp @@ -121,8 +121,6 @@ X86ELFTargetAsmInfo::X86ELFTargetAsmInfo(const X86TargetMachine &TM) : // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) - BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); - // Debug Information AbsoluteDebugSectionOffsets = true; SupportsDebugInformation = true; @@ -252,9 +250,6 @@ X86WinTargetAsmInfo::X86WinTargetAsmInfo(const X86TargetMachine &TM): AlignmentIsInBytes = true; - TextSection = getOrCreateSection("_text", true, SectionKind::Text); - DataSection = getOrCreateSection("_data", true, SectionKind::DataRel); - JumpTableDataSection = NULL; SwitchToSectionDirective = ""; TextSectionStartSuffix = "\tSEGMENT PARA 'CODE'"; diff --git a/lib/Target/X86/X86TargetAsmInfo.h b/lib/Target/X86/X86TargetAsmInfo.h index 0847660..9b4e809 100644 --- a/lib/Target/X86/X86TargetAsmInfo.h +++ b/lib/Target/X86/X86TargetAsmInfo.h @@ -33,8 +33,6 @@ namespace llvm { } }; - typedef X86TargetAsmInfo<TargetAsmInfo> X86GenericTargetAsmInfo; - EXTERN_TEMPLATE_INSTANTIATION(class X86TargetAsmInfo<TargetAsmInfo>); struct X86DarwinTargetAsmInfo : public X86TargetAsmInfo<DarwinTargetAsmInfo> { @@ -58,7 +56,7 @@ namespace llvm { }; - struct X86WinTargetAsmInfo : public X86GenericTargetAsmInfo { + struct X86WinTargetAsmInfo : public X86TargetAsmInfo<TargetAsmInfo> { explicit X86WinTargetAsmInfo(const X86TargetMachine &TM); }; diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index a720e6e..ee0daed 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -32,20 +32,18 @@ extern "C" void LLVMInitializeX86Target() { const TargetAsmInfo *X86TargetMachine::createTargetAsmInfo() const { if (Subtarget.isFlavorIntel()) return new X86WinTargetAsmInfo(*this); - else - switch (Subtarget.TargetType) { - case X86Subtarget::isDarwin: - return new X86DarwinTargetAsmInfo(*this); - case X86Subtarget::isELF: - return new X86ELFTargetAsmInfo(*this); - case X86Subtarget::isMingw: - case X86Subtarget::isCygwin: - return new X86COFFTargetAsmInfo(*this); - case X86Subtarget::isWindows: - return new X86WinTargetAsmInfo(*this); - default: - return new X86GenericTargetAsmInfo(*this); - } + switch (Subtarget.TargetType) { + default: llvm_unreachable("unknown subtarget type"); + case X86Subtarget::isDarwin: + return new X86DarwinTargetAsmInfo(*this); + case X86Subtarget::isELF: + return new X86ELFTargetAsmInfo(*this); + case X86Subtarget::isMingw: + case X86Subtarget::isCygwin: + return new X86COFFTargetAsmInfo(*this); + case X86Subtarget::isWindows: + return new X86WinTargetAsmInfo(*this); + } } X86_32TargetMachine::X86_32TargetMachine(const Target &T, const Module &M, diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index a7aba14..f4e4c22 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -20,4 +20,5 @@ add_llvm_target(XCore XCoreSubtarget.cpp XCoreTargetAsmInfo.cpp XCoreTargetMachine.cpp + XCoreTargetObjectFile.cpp ) diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index 5f24842..d57151c 100644 --- a/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -28,6 +28,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Support/Mangler.h" #include "llvm/ADT/Statistic.h" @@ -133,7 +134,7 @@ void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) { const TargetData *TD = TM.getTargetData(); - SwitchToSection(TAI->SectionForGlobal(GV)); + SwitchToSection(getObjFileLowering().SectionForGlobal(GV, TM)); std::string name = Mang->getMangledName(GV); Constant *C = GV->getInitializer(); @@ -204,7 +205,7 @@ void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) { // Print out the label for the function. const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM)); // Mark the start of the function O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n"; diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index e4e7f27..eaab849 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -16,6 +16,7 @@ #include "XCoreISelLowering.h" #include "XCoreMachineFunctionInfo.h" #include "XCore.h" +#include "XCoreTargetObjectFile.h" #include "XCoreTargetMachine.h" #include "XCoreSubtarget.h" #include "llvm/DerivedTypes.h" @@ -55,7 +56,8 @@ getTargetNodeName(unsigned Opcode) const } XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) - : TargetLowering(XTM), + : TargetLowering(XTM, + new XCoreTargetObjectFile(XTM.getSubtargetImpl()->isXS1A())), TM(XTM), Subtarget(*XTM.getSubtargetImpl()) { diff --git a/lib/Target/XCore/XCoreTargetAsmInfo.cpp b/lib/Target/XCore/XCoreTargetAsmInfo.cpp index fee0a22..fd8c9d7 100644 --- a/lib/Target/XCore/XCoreTargetAsmInfo.cpp +++ b/lib/Target/XCore/XCoreTargetAsmInfo.cpp @@ -1,4 +1,4 @@ -//===-- XCoreTargetAsmInfo.cpp - XCore asm properties -----------*- C++ -*-===// +//===-- XCoreTargetAsmInfo.cpp - XCore asm properties ---------------------===// // // The LLVM Compiler Infrastructure // @@ -6,41 +6,13 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file contains the declarations of the XCoreTargetAsmInfo properties. -// We use the small section flag for the CP relative and DP relative -// flags. If a section is small and writable then it is DP relative. If a -// section is small and not writable then it is CP relative. -// -//===----------------------------------------------------------------------===// #include "XCoreTargetAsmInfo.h" -#include "XCoreTargetMachine.h" -#include "llvm/GlobalVariable.h" -#include "llvm/ADT/StringExtras.h" - using namespace llvm; -XCoreTargetAsmInfo::XCoreTargetAsmInfo(const XCoreTargetMachine &TM) +XCoreTargetAsmInfo::XCoreTargetAsmInfo(const TargetMachine &TM) : ELFTargetAsmInfo(TM) { SupportsDebugInformation = true; - TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); - DataSection = getOrCreateSection("\t.dp.data", false, SectionKind::DataRel); - BSSSection_ = getOrCreateSection("\t.dp.bss", false, SectionKind::BSS); - - // TLS globals are lowered in the backend to arrays indexed by the current - // thread id. After lowering they require no special handling by the linker - // and can be placed in the standard data / bss sections. - TLSDataSection = DataSection; - TLSBSSSection = BSSSection_; - - if (TM.getSubtargetImpl()->isXS1A()) - // FIXME: Why is this writable??? - ReadOnlySection = getOrCreateSection("\t.dp.rodata", false, - SectionKind::DataRel); - else - ReadOnlySection = getOrCreateSection("\t.cp.rodata", false, - SectionKind::ReadOnly); Data16bitsDirective = "\t.short\t"; Data32bitsDirective = "\t.long\t"; Data64bitsDirective = 0; diff --git a/lib/Target/XCore/XCoreTargetAsmInfo.h b/lib/Target/XCore/XCoreTargetAsmInfo.h index 6d38340..f220815 100644 --- a/lib/Target/XCore/XCoreTargetAsmInfo.h +++ b/lib/Target/XCore/XCoreTargetAsmInfo.h @@ -18,13 +18,9 @@ namespace llvm { - // Forward declarations. - class XCoreTargetMachine; - class XCoreSubtarget; - class XCoreTargetAsmInfo : public ELFTargetAsmInfo { public: - explicit XCoreTargetAsmInfo(const XCoreTargetMachine &TM); + explicit XCoreTargetAsmInfo(const TargetMachine &TM); }; } // namespace llvm diff --git a/lib/Target/XCore/XCoreTargetObjectFile.cpp b/lib/Target/XCore/XCoreTargetObjectFile.cpp new file mode 100644 index 0000000..89880c2 --- /dev/null +++ b/lib/Target/XCore/XCoreTargetObjectFile.cpp @@ -0,0 +1,32 @@ +//===-- XCoreTargetObjectFile.cpp - XCore object files --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "XCoreTargetObjectFile.h" +using namespace llvm; + + +XCoreTargetObjectFile::XCoreTargetObjectFile(bool isXS1A) { + TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); + DataSection = getOrCreateSection("\t.dp.data", false, SectionKind::DataRel); + BSSSection_ = getOrCreateSection("\t.dp.bss", false, SectionKind::BSS); + + // TLS globals are lowered in the backend to arrays indexed by the current + // thread id. After lowering they require no special handling by the linker + // and can be placed in the standard data / bss sections. + TLSDataSection = DataSection; + TLSBSSSection = BSSSection_; + + if (isXS1A) + // FIXME: Why is this writable ("datarel")??? + ReadOnlySection = getOrCreateSection("\t.dp.rodata", false, + SectionKind::DataRel); + else + ReadOnlySection = getOrCreateSection("\t.cp.rodata", false, + SectionKind::ReadOnly); +}
\ No newline at end of file diff --git a/lib/Target/XCore/XCoreTargetObjectFile.h b/lib/Target/XCore/XCoreTargetObjectFile.h new file mode 100644 index 0000000..af40e11 --- /dev/null +++ b/lib/Target/XCore/XCoreTargetObjectFile.h @@ -0,0 +1,25 @@ +//===-- llvm/Target/XCoreTargetObjectFile.h - XCore Object Info -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_XCORE_TARGETOBJECTFILE_H +#define LLVM_TARGET_XCORE_TARGETOBJECTFILE_H + +#include "llvm/Target/TargetLoweringObjectFile.h" + +namespace llvm { + + class XCoreTargetObjectFile : public TargetLoweringObjectFileELF { + public: + XCoreTargetObjectFile(bool isXS1A); + + // TODO: Classify globals as xcore wishes. + }; +} // end namespace llvm + +#endif |