diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index 5ff52d8ab24..5c54724af07 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -26,10 +26,11 @@ namespace llvm { /// TargetAsmInfo - This class is intended to be used as a base class for asm /// properties and features specific to the target. class TargetAsmInfo { - protected: + public: //===------------------------------------------------------------------===// // Properties to be set by the target writer, used to configure asm printer. - // + // Should not be accessed by anything but a subclass of TargetAsmInfo. Use + // accessor functions. /// TextSection - Section directive for standard text. /// diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 885f0b1ef0e..194a499b8b4 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -282,6 +282,35 @@ namespace { virtual bool doFinalization(Module &M) = 0; }; + /// LinuxAsmPrinter - PowerPC assembly printer, customized for Linux + struct VISIBILITY_HIDDEN LinuxAsmPrinter : public PPCAsmPrinter { + + DwarfWriter DW; + + LinuxAsmPrinter(std::ostream &O, PPCTargetMachine &TM, + const TargetAsmInfo *T) + : PPCAsmPrinter(O, TM, T), DW(O, this, T) { + } + + virtual const char *getPassName() const { + return "Linux PPC Assembly Printer"; + } + + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + PPCAsmPrinter::getAnalysisUsage(AU); + } + + /// getSectionForFunction - Return the section that we should emit the + /// specified function body into. + virtual std::string getSectionForFunction(const Function &F) const; + }; + /// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS /// X struct VISIBILITY_HIDDEN DarwinAsmPrinter : public PPCAsmPrinter { @@ -491,7 +520,194 @@ void PPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) { return; } +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + DW.SetDebugInfo(&getAnalysis()); + SetupMachineFunction(MF); + O << "\n\n"; + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + // Print out labels for the function. + const Function *F = MF.getFunction(); + SwitchToTextSection(getSectionForFunction(*F).c_str(), F); + + switch (F->getLinkage()) { + default: assert(0 && "Unknown linkage type!"); + case Function::InternalLinkage: // Symbols default to internal. + break; + case Function::ExternalLinkage: + O << "\t.global\t" << CurrentFnName << '\n' + << "\t.type\t" << CurrentFnName << ", @function\n"; + break; + case Function::WeakLinkage: + case Function::LinkOnceLinkage: + O << "\t.global\t" << CurrentFnName << '\n'; + O << "\t.weak\t" << CurrentFnName << '\n'; + break; + } + EmitAlignment(2, F); + O << CurrentFnName << ":\n"; + + // Emit pre-function debug information. + DW.BeginFunction(&MF); + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + if (I != MF.begin()) { + printBasicBlockLabel(I, true); + O << '\n'; + } + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << "\t"; + printMachineInstruction(II); + } + } + + O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n"; + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(MF.getJumpTableInfo(), MF); + + // Emit post-function debug information. + DW.EndFunction(); + + // We didn't modify anything. + return false; +} + +bool LinuxAsmPrinter::doInitialization(Module &M) { + AsmPrinter::doInitialization(M); + + // GNU as handles section names wrapped in quotes + Mang->setUseQuotes(true); + + SwitchToTextSection(TAI->getTextSection()); + + // Emit initial debug information. + DW.BeginModule(&M); + return false; +} + +bool LinuxAsmPrinter::doFinalization(Module &M) { + const TargetData *TD = TM.getTargetData(); + + // Print out module-level global variables here. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->hasInitializer()) continue; // External global require no code + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(I)) + continue; + + std::string name = Mang->getValueName(I); + Constant *C = I->getInitializer(); + unsigned Size = TD->getTypeSize(C->getType()); + unsigned Align = TD->getPreferredAlignmentLog(I); + + if (C->isNullValue() && /* FIXME: Verify correct */ + (I->hasInternalLinkage() || I->hasWeakLinkage() || + I->hasLinkOnceLinkage() || + (I->hasExternalLinkage() && !I->hasSection()))) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + if (I->hasExternalLinkage()) { + O << "\t.global " << name << '\n'; + O << "\t.type " << name << ", @object\n"; + //O << "\t.zerofill __DATA, __common, " << name << ", " + // << Size << ", " << Align; + } else if (I->hasInternalLinkage()) { + SwitchToDataSection("\t.data", I); + O << TAI->getLCOMMDirective() << name << "," << Size; + } else { + SwitchToDataSection("\t.data", I); + O << ".comm " << name << "," << Size; + } + O << "\t\t" << TAI->getCommentString() << " '" << I->getName() << "'\n"; + } else { + switch (I->getLinkage()) { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + O << "\t.global " << name << '\n' + << "\t.type " << name << ", @object\n" + << "\t.weak " << name << '\n'; + SwitchToDataSection("\t.data", I); + break; + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol + O << "\t.global " << name << "\n" + << "\t.type " << name << ", @object\n"; + // FALL THROUGH + case GlobalValue::InternalLinkage: + if (I->isConstant()) { + const ConstantArray *CVA = dyn_cast(C); + if (TAI->getCStringSection() && CVA && CVA->isCString()) { + SwitchToDataSection(TAI->getCStringSection(), I); + break; + } + } + + // FIXME: special handling for ".ctors" & ".dtors" sections + if (I->hasSection() && + (I->getSection() == ".ctors" || + I->getSection() == ".dtors")) { + std::string SectionName = ".section " + I->getSection() + + ",\"aw\",@progbits"; + SwitchToDataSection(SectionName.c_str()); + } else { + SwitchToDataSection(TAI->getDataSection(), I); + } + break; + default: + cerr << "Unknown linkage type!"; + abort(); + } + + EmitAlignment(Align, I); + O << name << ":\t\t\t\t" << TAI->getCommentString() << " '" + << I->getName() << "'\n"; + + // If the initializer is a extern weak symbol, remember to emit the weak + // reference! + if (const GlobalValue *GV = dyn_cast(C)) + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + + EmitGlobalConstant(C); + O << '\n'; + } + } + + // TODO + + // Emit initial debug information. + DW.EndModule(); + + AsmPrinter::doFinalization(M); + return false; // success +} + +std::string LinuxAsmPrinter::getSectionForFunction(const Function &F) const { + switch (F.getLinkage()) { + default: assert(0 && "Unknown linkage type!"); + case Function::ExternalLinkage: + case Function::InternalLinkage: return TAI->getTextSection(); + case Function::WeakLinkage: + case Function::LinkOnceLinkage: + return ".text"; + } +} std::string DarwinAsmPrinter::getSectionForFunction(const Function &F) const { switch (F.getLinkage()) { @@ -786,6 +1002,12 @@ bool DarwinAsmPrinter::doFinalization(Module &M) { /// FunctionPass *llvm::createPPCAsmPrinterPass(std::ostream &o, PPCTargetMachine &tm) { - return new DarwinAsmPrinter(o, tm, tm.getTargetAsmInfo()); + const PPCSubtarget *Subtarget = &tm.getSubtarget(); + + if (Subtarget->isDarwin()) { + return new DarwinAsmPrinter(o, tm, tm.getTargetAsmInfo()); + } else { + return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo()); + } } diff --git a/lib/Target/PowerPC/PPCRegisterInfo.td b/lib/Target/PowerPC/PPCRegisterInfo.td index 51000f9a080..1950d073169 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/lib/Target/PowerPC/PPCRegisterInfo.td @@ -209,9 +209,9 @@ def VRSAVE: SPR<256, "VRsave">, DwarfRegNum<107>; // Allocate volatiles first // then nonvolatiles in reverse order since stmw/lmw save from rN to r31 def GPRC : RegisterClass<"PPC", [i32], 32, - [R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, + [R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R30, R29, R28, R27, R26, R25, R24, R23, R22, R21, R20, R19, R18, R17, - R16, R15, R14, R13, R31, R0, R1, LR]> + R16, R15, R14, R2, R13, R31, R0, R1, LR]> { let MethodProtos = [{ iterator allocation_order_begin(const MachineFunction &MF) const; @@ -224,6 +224,10 @@ def GPRC : RegisterClass<"PPC", [i32], 32, } GPRCClass::iterator GPRCClass::allocation_order_end(const MachineFunction &MF) const { + // In Linux, r2 is reserved for the OS. + if (!MF.getTarget().getSubtarget().isDarwin()) + return end()-6; + // On PPC64, r13 is the thread pointer. Never allocate this register. // Note that this is overconservative, as it also prevents allocation of // R31 when the FP is not needed. diff --git a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp index 1e380091448..3def0316a7a 100644 --- a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp +++ b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp @@ -16,24 +16,14 @@ #include "llvm/Function.h" using namespace llvm; -DarwinTargetAsmInfo::DarwinTargetAsmInfo(const PPCTargetMachine &TM) { +PPCTargetAsmInfo::PPCTargetAsmInfo(const PPCTargetMachine &TM) { bool isPPC64 = TM.getSubtargetImpl()->isPPC64(); - - CommentString = ";"; - GlobalPrefix = "_"; - PrivateGlobalPrefix = "L"; + ZeroDirective = "\t.space\t"; SetDirective = "\t.set"; Data64bitsDirective = isPPC64 ? "\t.quad\t" : 0; AlignmentIsInBytes = false; - ConstantPoolSection = "\t.const\t"; - JumpTableDataSection = ".const"; - CStringSection = "\t.cstring"; LCOMMDirective = "\t.lcomm\t"; - StaticCtorsSection = ".mod_init_func"; - StaticDtorsSection = ".mod_term_func"; - UsedDirective = "\t.no_dead_strip\t"; - WeakRefDirective = "\t.weak_reference\t"; InlineAsmStart = "# InlineAsm Start"; InlineAsmEnd = "# InlineAsm End"; @@ -52,3 +42,32 @@ DarwinTargetAsmInfo::DarwinTargetAsmInfo(const PPCTargetMachine &TM) { DwarfMacInfoSection = ".section __DWARF,__debug_macinfo,regular,debug"; } +DarwinTargetAsmInfo::DarwinTargetAsmInfo(const PPCTargetMachine &TM) +: PPCTargetAsmInfo(TM) +{ + CommentString = ";"; + GlobalPrefix = "_"; + PrivateGlobalPrefix = "L"; + ConstantPoolSection = "\t.const\t"; + JumpTableDataSection = ".const"; + CStringSection = "\t.cstring"; + StaticCtorsSection = ".mod_init_func"; + StaticDtorsSection = ".mod_term_func"; + UsedDirective = "\t.no_dead_strip\t"; + WeakRefDirective = "\t.weak_reference\t"; +} + +LinuxTargetAsmInfo::LinuxTargetAsmInfo(const PPCTargetMachine &TM) +: PPCTargetAsmInfo(TM) +{ + CommentString = "#"; + GlobalPrefix = ""; + PrivateGlobalPrefix = ""; + ConstantPoolSection = "\t.section .rodata.cst4\t"; + JumpTableDataSection = ".section .rodata.cst4"; + CStringSection = "\t.section\t.rodata"; + StaticCtorsSection = ".section\t.ctors,\"aw\",@progbits"; + StaticDtorsSection = ".section\t.dtors,\"aw\",@progbits"; + UsedDirective = "\t# .no_dead_strip\t"; + WeakRefDirective = "\t.weak\t"; +} diff --git a/lib/Target/PowerPC/PPCTargetAsmInfo.h b/lib/Target/PowerPC/PPCTargetAsmInfo.h index ed8574c40d6..6a680e2e44c 100644 --- a/lib/Target/PowerPC/PPCTargetAsmInfo.h +++ b/lib/Target/PowerPC/PPCTargetAsmInfo.h @@ -20,11 +20,19 @@ namespace llvm { // Forward declaration. class PPCTargetMachine; + + struct PPCTargetAsmInfo : public TargetAsmInfo { + PPCTargetAsmInfo(const PPCTargetMachine &TM); + }; - struct DarwinTargetAsmInfo : public TargetAsmInfo { + struct DarwinTargetAsmInfo : public PPCTargetAsmInfo { DarwinTargetAsmInfo(const PPCTargetMachine &TM); }; + struct LinuxTargetAsmInfo : public PPCTargetAsmInfo { + LinuxTargetAsmInfo(const PPCTargetMachine &TM); + }; + } // namespace llvm #endif diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index 8cf85d186fb..249a639f8cd 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -28,7 +28,10 @@ namespace { } const TargetAsmInfo *PPCTargetMachine::createTargetAsmInfo() const { - return new DarwinTargetAsmInfo(*this); + if (Subtarget.isDarwin()) + return new DarwinTargetAsmInfo(*this); + else + return new LinuxTargetAsmInfo(*this); } unsigned PPC32TargetMachine::getJITMatchQuality() { @@ -90,7 +93,7 @@ PPCTargetMachine::PPCTargetMachine(const Module &M, const std::string &FS, if (Subtarget.isDarwin()) setRelocationModel(Reloc::DynamicNoPIC); else - setRelocationModel(Reloc::PIC_); + setRelocationModel(Reloc::Static); } PPC32TargetMachine::PPC32TargetMachine(const Module &M, const std::string &FS)