From 06be997654120c92f99850bf1a1704a2042ef639 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sun, 17 Aug 2008 13:54:28 +0000 Subject: Factor out asmprinter out of ppc git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54887 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/AsmPrinter/Makefile | 15 + lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp | 1127 +++++++++++++++++++++++ lib/Target/PowerPC/Makefile | 4 +- lib/Target/PowerPC/PPCAsmPrinter.cpp | 1119 ---------------------- lib/Target/PowerPC/PPCTargetMachine.cpp | 24 +- lib/Target/PowerPC/PPCTargetMachine.h | 14 +- 6 files changed, 1176 insertions(+), 1127 deletions(-) create mode 100644 lib/Target/PowerPC/AsmPrinter/Makefile create mode 100644 lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp delete mode 100644 lib/Target/PowerPC/PPCAsmPrinter.cpp (limited to 'lib/Target') diff --git a/lib/Target/PowerPC/AsmPrinter/Makefile b/lib/Target/PowerPC/AsmPrinter/Makefile new file mode 100644 index 0000000000..640bf02acc --- /dev/null +++ b/lib/Target/PowerPC/AsmPrinter/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/X86/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMPowerPCAsmPrinter + +# Hack: we need to include 'main' x86 target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp new file mode 100644 index 0000000000..c5ed305a8d --- /dev/null +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -0,0 +1,1127 @@ +//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly --------=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to PowerPC assembly language. This printer is +// the output mechanism used by `llc'. +// +// Documentation at http://developer.apple.com/documentation/DeveloperTools/ +// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asmprinter" +#include "PPC.h" +#include "PPCPredicates.h" +#include "PPCTargetMachine.h" +#include "PPCSubtarget.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +namespace { + struct VISIBILITY_HIDDEN PPCAsmPrinter : public AsmPrinter { + std::set FnStubs, GVStubs; + const PPCSubtarget &Subtarget; + + PPCAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) + : AsmPrinter(O, TM, T), Subtarget(TM.getSubtarget()) { + } + + virtual const char *getPassName() const { + return "PowerPC Assembly Printer"; + } + + PPCTargetMachine &getTM() { + return static_cast(TM); + } + + unsigned enumRegToMachineReg(unsigned enumReg) { + switch (enumReg) { + default: assert(0 && "Unhandled register!"); break; + case PPC::CR0: return 0; + case PPC::CR1: return 1; + case PPC::CR2: return 2; + case PPC::CR3: return 3; + case PPC::CR4: return 4; + case PPC::CR5: return 5; + case PPC::CR6: return 6; + case PPC::CR7: return 7; + } + abort(); + } + + /// printInstruction - This method is automatically generated by tablegen + /// from the instruction set description. This method returns true if the + /// machine instruction was sufficiently described to print it, otherwise it + /// returns false. + bool printInstruction(const MachineInstr *MI); + + void printMachineInstruction(const MachineInstr *MI); + void printOp(const MachineOperand &MO); + + /// stripRegisterPrefix - This method strips the character prefix from a + /// register name so that only the number is left. Used by for linux asm. + const char *stripRegisterPrefix(const char *RegName) { + switch (RegName[0]) { + case 'r': + case 'f': + case 'v': return RegName + 1; + case 'c': if (RegName[1] == 'r') return RegName + 2; + } + + return RegName; + } + + /// printRegister - Print register according to target requirements. + /// + void printRegister(const MachineOperand &MO, bool R0AsZero) { + unsigned RegNo = MO.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); + + // If we should use 0 for R0. + if (R0AsZero && RegNo == PPC::R0) { + O << "0"; + return; + } + + const char *RegName = TM.getRegisterInfo()->get(RegNo).AsmName; + // Linux assembler (Others?) does not take register mnemonics. + // FIXME - What about special registers used in mfspr/mtspr? + if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); + O << RegName; + } + + void printOperand(const MachineInstr *MI, unsigned OpNo) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (MO.isRegister()) { + printRegister(MO, false); + } else if (MO.isImmediate()) { + O << MO.getImm(); + } else { + printOp(MO); + } + } + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + + + void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo) { + char value = MI->getOperand(OpNo).getImm(); + value = (value << (32-5)) >> (32-5); + O << (int)value; + } + void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) { + unsigned char value = MI->getOperand(OpNo).getImm(); + assert(value <= 31 && "Invalid u5imm argument!"); + O << (unsigned int)value; + } + void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo) { + unsigned char value = MI->getOperand(OpNo).getImm(); + assert(value <= 63 && "Invalid u6imm argument!"); + O << (unsigned int)value; + } + void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo) { + O << (short)MI->getOperand(OpNo).getImm(); + } + void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo) { + O << (unsigned short)MI->getOperand(OpNo).getImm(); + } + void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo) { + if (MI->getOperand(OpNo).isImmediate()) { + O << (short)(MI->getOperand(OpNo).getImm()*4); + } else { + O << "lo16("; + printOp(MI->getOperand(OpNo)); + if (TM.getRelocationModel() == Reloc::PIC_) + O << "-\"L" << getFunctionNumber() << "$pb\")"; + else + O << ')'; + } + } + void printBranchOperand(const MachineInstr *MI, unsigned OpNo) { + // Branches can take an immediate operand. This is used by the branch + // selection pass to print $+8, an eight byte displacement from the PC. + if (MI->getOperand(OpNo).isImmediate()) { + O << "$+" << MI->getOperand(OpNo).getImm()*4; + } else { + printOp(MI->getOperand(OpNo)); + } + } + void printCallOperand(const MachineInstr *MI, unsigned OpNo) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (TM.getRelocationModel() != Reloc::Static) { + if (MO.getType() == MachineOperand::MO_GlobalAddress) { + GlobalValue *GV = MO.getGlobal(); + if (((GV->isDeclaration() || GV->hasWeakLinkage() || + GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) { + // Dynamically-resolved functions need a stub for the function. + std::string Name = Mang->getValueName(GV); + FnStubs.insert(Name); + printSuffixedName(Name, "$stub"); + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + return; + } + } + if (MO.getType() == MachineOperand::MO_ExternalSymbol) { + std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName(); + FnStubs.insert(Name); + printSuffixedName(Name, "$stub"); + return; + } + } + + printOp(MI->getOperand(OpNo)); + } + void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo) { + O << (int)MI->getOperand(OpNo).getImm()*4; + } + void printPICLabel(const MachineInstr *MI, unsigned OpNo) { + O << "\"L" << getFunctionNumber() << "$pb\"\n"; + O << "\"L" << getFunctionNumber() << "$pb\":"; + } + void printSymbolHi(const MachineInstr *MI, unsigned OpNo) { + if (MI->getOperand(OpNo).isImmediate()) { + printS16ImmOperand(MI, OpNo); + } else { + if (Subtarget.isDarwin()) O << "ha16("; + printOp(MI->getOperand(OpNo)); + if (TM.getRelocationModel() == Reloc::PIC_) + O << "-\"L" << getFunctionNumber() << "$pb\""; + if (Subtarget.isDarwin()) + O << ')'; + else + O << "@ha"; + } + } + void printSymbolLo(const MachineInstr *MI, unsigned OpNo) { + if (MI->getOperand(OpNo).isImmediate()) { + printS16ImmOperand(MI, OpNo); + } else { + if (Subtarget.isDarwin()) O << "lo16("; + printOp(MI->getOperand(OpNo)); + if (TM.getRelocationModel() == Reloc::PIC_) + O << "-\"L" << getFunctionNumber() << "$pb\""; + if (Subtarget.isDarwin()) + O << ')'; + else + O << "@l"; + } + } + void printcrbitm(const MachineInstr *MI, unsigned OpNo) { + unsigned CCReg = MI->getOperand(OpNo).getReg(); + unsigned RegNo = enumRegToMachineReg(CCReg); + O << (0x80 >> RegNo); + } + // The new addressing mode printers. + void printMemRegImm(const MachineInstr *MI, unsigned OpNo) { + printSymbolLo(MI, OpNo); + O << '('; + if (MI->getOperand(OpNo+1).isRegister() && + MI->getOperand(OpNo+1).getReg() == PPC::R0) + O << "0"; + else + printOperand(MI, OpNo+1); + O << ')'; + } + void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo) { + if (MI->getOperand(OpNo).isImmediate()) + printS16X4ImmOperand(MI, OpNo); + else + printSymbolLo(MI, OpNo); + O << '('; + if (MI->getOperand(OpNo+1).isRegister() && + MI->getOperand(OpNo+1).getReg() == PPC::R0) + O << "0"; + else + printOperand(MI, OpNo+1); + O << ')'; + } + + void printMemRegReg(const MachineInstr *MI, unsigned OpNo) { + // When used as the base register, r0 reads constant zero rather than + // the value contained in the register. For this reason, the darwin + // assembler requires that we print r0 as 0 (no r) when used as the base. + const MachineOperand &MO = MI->getOperand(OpNo); + printRegister(MO, true); + O << ", "; + printOperand(MI, OpNo+1); + } + + void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier); + + virtual bool runOnMachineFunction(MachineFunction &F) = 0; + virtual bool doFinalization(Module &M) = 0; + + virtual void EmitExternalGlobal(const GlobalVariable *GV); + }; + + /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux + struct VISIBILITY_HIDDEN PPCLinuxAsmPrinter : public PPCAsmPrinter { + + DwarfWriter DW; + MachineModuleInfo *MMI; + + PPCLinuxAsmPrinter(std::ostream &O, PPCTargetMachine &TM, + const TargetAsmInfo *T) + : PPCAsmPrinter(O, TM, T), DW(O, this, T), MMI(0) { + } + + 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; + void printModuleLevelGV(const GlobalVariable* GVar); + }; + + /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac + /// OS X + struct VISIBILITY_HIDDEN PPCDarwinAsmPrinter : public PPCAsmPrinter { + + DwarfWriter DW; + MachineModuleInfo *MMI; + + PPCDarwinAsmPrinter(std::ostream &O, PPCTargetMachine &TM, + const TargetAsmInfo *T) + : PPCAsmPrinter(O, TM, T), DW(O, this, T), MMI(0) { + } + + virtual const char *getPassName() const { + return "Darwin 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; + void printModuleLevelGV(const GlobalVariable* GVar); + }; +} // end of anonymous namespace + +// Include the auto-generated portion of the assembly writer +#include "PPCGenAsmWriter.inc" + +void PPCAsmPrinter::printOp(const MachineOperand &MO) { + switch (MO.getType()) { + case MachineOperand::MO_Immediate: + cerr << "printOp() does not handle immediate values\n"; + abort(); + return; + + case MachineOperand::MO_MachineBasicBlock: + printBasicBlockLabel(MO.getMBB()); + return; + case MachineOperand::MO_JumpTableIndex: + O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + // FIXME: PIC relocation model + return; + case MachineOperand::MO_ConstantPoolIndex: + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << MO.getIndex(); + return; + case MachineOperand::MO_ExternalSymbol: + // Computing the address of an external symbol, not calling it. + if (TM.getRelocationModel() != Reloc::Static) { + std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName(); + GVStubs.insert(Name); + printSuffixedName(Name, "$non_lazy_ptr"); + return; + } + O << TAI->getGlobalPrefix() << MO.getSymbolName(); + return; + case MachineOperand::MO_GlobalAddress: { + // Computing the address of a global symbol, not calling it. + GlobalValue *GV = MO.getGlobal(); + std::string Name = Mang->getValueName(GV); + + // External or weakly linked global variables need non-lazily-resolved stubs + if (TM.getRelocationModel() != Reloc::Static) { + if (((GV->isDeclaration() || GV->hasWeakLinkage() || + GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) { + GVStubs.insert(Name); + printSuffixedName(Name, "$non_lazy_ptr"); + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + return; + } + } + O << Name; + + if (MO.getOffset() > 0) + O << "+" << MO.getOffset(); + else if (MO.getOffset() < 0) + O << MO.getOffset(); + + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + return; + } + + default: + O << ""; + return; + } +} + +/// EmitExternalGlobal - In this case we need to use the indirect symbol. +/// +void PPCAsmPrinter::EmitExternalGlobal(const GlobalVariable *GV) { + std::string Name = getGlobalLinkName(GV); + if (TM.getRelocationModel() != Reloc::Static) { + GVStubs.insert(Name); + printSuffixedName(Name, "$non_lazy_ptr"); + return; + } + O << Name; +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'c': // Don't print "$" before a global var name or constant. + // PPC never has a prefix. + printOperand(MI, OpNo); + return false; + case 'L': // Write second word of DImode reference. + // Verify that this operand has two consecutive registers. + if (!MI->getOperand(OpNo).isRegister() || + OpNo+1 == MI->getNumOperands() || + !MI->getOperand(OpNo+1).isRegister()) + return true; + ++OpNo; // Return the high-part. + break; + case 'I': + // Write 'i' if an integer constant, otherwise nothing. Used to print + // addi vs add, etc. + if (MI->getOperand(OpNo).isImmediate()) + O << "i"; + return false; + } + } + + printOperand(MI, OpNo); + return false; +} + +bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + if (MI->getOperand(OpNo).isRegister()) + printMemRegReg(MI, OpNo); + else + printMemRegImm(MI, OpNo); + return false; +} + +void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier) { + assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!"); + unsigned Code = MI->getOperand(OpNo).getImm(); + if (!strcmp(Modifier, "cc")) { + switch ((PPC::Predicate)Code) { + case PPC::PRED_ALWAYS: return; // Don't print anything for always. + case PPC::PRED_LT: O << "lt"; return; + case PPC::PRED_LE: O << "le"; return; + case PPC::PRED_EQ: O << "eq"; return; + case PPC::PRED_GE: O << "ge"; return; + case PPC::PRED_GT: O << "gt"; return; + case PPC::PRED_NE: O << "ne"; return; + case PPC::PRED_UN: O << "un"; return; + case PPC::PRED_NU: O << "nu"; return; + } + + } else { + assert(!strcmp(Modifier, "reg") && + "Need to specify 'cc' or 'reg' as predicate op modifier!"); + // Don't print the register for 'always'. + if (Code == PPC::PRED_ALWAYS) return; + printOperand(MI, OpNo+1); + } +} + + +/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to +/// the current output stream. +/// +void PPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + + // Check for slwi/srwi mnemonics. + if (MI->getOpcode() == PPC::RLWINM) { + bool FoundMnemonic = false; + unsigned char SH = MI->getOperand(2).getImm(); + unsigned char MB = MI->getOperand(3).getImm(); + unsigned char ME = MI->getOperand(4).getImm(); + if (SH <= 31 && MB == 0 && ME == (31-SH)) { + O << "\tslwi "; FoundMnemonic = true; + } + if (SH <= 31 && MB == (32-SH) && ME == 31) { + O << "\tsrwi "; FoundMnemonic = true; + SH = 32-SH; + } + if (FoundMnemonic) { + printOperand(MI, 0); + O << ", "; + printOperand(MI, 1); + O << ", " << (unsigned int)SH << '\n'; + return; + } + } else if (MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) { + if (MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { + O << "\tmr "; + printOperand(MI, 0); + O << ", "; + printOperand(MI, 1); + O << '\n'; + return; + } + } else if (MI->getOpcode() == PPC::RLDICR) { + unsigned char SH = MI->getOperand(2).getImm(); + unsigned char ME = MI->getOperand(3).getImm(); + // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH + if (63-SH == ME) { + O << "\tsldi "; + printOperand(MI, 0); + O << ", "; + printOperand(MI, 1); + O << ", " << (unsigned int)SH << '\n'; + return; + } + } + + if (printInstruction(MI)) + return; // Printer was automatically generated + + assert(0 && "Unhandled instruction in asm writer!"); + abort(); + return; +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + + 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; + } + + printVisibility(CurrentFnName, F->getVisibility()); + + 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, true); + O << '\n'; + } + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + 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 PPCLinuxAsmPrinter::doInitialization(Module &M) { + bool Result = AsmPrinter::doInitialization(M); + + // Emit initial debug information. + DW.BeginModule(&M); + + // AsmPrinter::doInitialization should have done this analysis. + MMI = getAnalysisToUpdate(); + assert(MMI); + DW.SetModuleInfo(MMI); + + // GNU as handles section names wrapped in quotes + Mang->setUseQuotes(true); + + SwitchToTextSection(TAI->getTextSection()); + + return Result; +} + +/// PrintUnmangledNameSafely - Print out the printable characters in the name. +/// Don't print things like \n or \0. +static void PrintUnmangledNameSafely(const Value *V, std::ostream &OS) { + for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); + Name != E; ++Name) + if (isprint(*Name)) + OS << *Name; +} + +void PPCLinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { + const TargetData *TD = TM.getTargetData(); + + if (!GVar->hasInitializer()) + return; // External global require no code + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GVar)) + return; + + std::string name = Mang->getValueName(GVar); + std::string SectionName = TAI->SectionForGlobal(GVar); + + printVisibility(name, GVar->getVisibility()); + + Constant *C = GVar->getInitializer(); + const Type *Type = C->getType(); + unsigned Size = TD->getABITypeSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(GVar); + + SwitchToDataSection(SectionName.c_str()); + + if (C->isNullValue() && /* FIXME: Verify correct */ + !GVar->hasSection() && + (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() || + GVar->isWeakForLinker())) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (GVar->hasExternalLinkage()) { + O << "\t.global " << name << '\n'; + O << "\t.type " << name << ", @object\n"; + O << name << ":\n"; + O << "\t.zero " << Size << '\n'; + } else if (GVar->hasInternalLinkage()) { + O << TAI->getLCOMMDirective() << name << ',' << Size; + } else { + O << ".comm " << name << ',' << Size; + } + O << "\t\t" << TAI->getCommentString() << " '"; + PrintUnmangledNameSafely(GVar, O); + O << "'\n"; + return; + } + + switch (GVar->getLinkage()) { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + case GlobalValue::CommonLinkage: + O << "\t.global " << name << '\n' + << "\t.type " << name << ", @object\n" + << "\t.weak " << name << '\n'; + 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: + break; + default: + cerr << "Unknown linkage type!"; + abort(); + } + + EmitAlignment(Align, GVar); + O << name << ":\t\t\t\t" << TAI->getCommentString() << " '"; + PrintUnmangledNameSafely(GVar, O); + O << "'\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'; +} + +bool PPCLinuxAsmPrinter::doFinalization(Module &M) { + // Print out module-level global variables here. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + printModuleLevelGV(I); + + // TODO + + // Emit initial debug information. + DW.EndModule(); + + return AsmPrinter::doFinalization(M); +} + +std::string PPCLinuxAsmPrinter::getSectionForFunction(const Function &F) const { + return TAI->SectionForGlobal(&F); +} + +std::string PPCDarwinAsmPrinter::getSectionForFunction(const Function &F) const { + return TAI->SectionForGlobal(&F); +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + 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.globl\t" << CurrentFnName << '\n'; + break; + case Function::WeakLinkage: + case Function::LinkOnceLinkage: + O << "\t.globl\t" << CurrentFnName << '\n'; + O << "\t.weak_definition\t" << CurrentFnName << '\n'; + break; + } + + printVisibility(CurrentFnName, F->getVisibility()); + + EmitAlignment(OptimizeForSize ? 2 : 4, F); + O << CurrentFnName << ":\n"; + + // Emit pre-function debug information. + DW.BeginFunction(&MF); + + // If the function is empty, then we need to emit *something*. Otherwise, the + // function's label might be associated with something that it wasn't meant to + // be associated with. We emit a noop in this situation. + MachineFunction::iterator I = MF.begin(); + + if (++I == MF.end() && MF.front().empty()) + O << "\tnop\n"; + + // 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, true); + O << '\n'; + } + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + // Print the assembly for the instruction. + printMachineInstruction(II); + } + } + + // 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 PPCDarwinAsmPrinter::doInitialization(Module &M) { + static const char *const CPUDirectives[] = { + "", + "ppc", + "ppc601", + "ppc602", + "ppc603", + "ppc7400", + "ppc750", + "ppc970", + "ppc64" + }; + + unsigned Directive = Subtarget.getDarwinDirective(); + if (Subtarget.isGigaProcessor() && Directive < PPC::DIR_970) + Directive = PPC::DIR_970; + if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400) + Directive = PPC::DIR_7400; + if (Subtarget.isPPC64() && Directive < PPC::DIR_970) + Directive = PPC::DIR_64; + assert(Directive <= PPC::DIR_64 && "Directive out of range."); + O << "\t.machine " << CPUDirectives[Directive] << '\n'; + + bool Result = AsmPrinter::doInitialization(M); + + // Emit initial debug information. + DW.BeginModule(&M); + + // We need this for Personality functions. + // AsmPrinter::doInitialization should have done this analysis. + MMI = getAnalysisToUpdate(); + assert(MMI); + DW.SetModuleInfo(MMI); + + // Darwin wants symbols to be quoted if they have complex names. + Mang->setUseQuotes(true); + + // Prime text sections so they are adjacent. This reduces the likelihood a + // large data or debug section causes a branch to exceed 16M limit. + SwitchToTextSection("\t.section __TEXT,__textcoal_nt,coalesced," + "pure_instructions"); + if (TM.getRelocationModel() == Reloc::PIC_) { + SwitchToTextSection("\t.section __TEXT,__picsymbolstub1,symbol_stubs," + "pure_instructions,32"); + } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { + SwitchToTextSection("\t.section __TEXT,__symbol_stub1,symbol_stubs," + "pure_instructions,16"); + } + SwitchToTextSection(TAI->getTextSection()); + + return Result; +} + +void PPCDarwinAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { + const TargetData *TD = TM.getTargetData(); + + if (!GVar->hasInitializer()) + return; // External global require no code + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GVar)) { + if (TM.getRelocationModel() == Reloc::Static) { + if (GVar->getName() == "llvm.global_ctors") + O << ".reference .constructors_used\n"; + else if (GVar->getName() == "llvm.global_dtors") + O << ".reference .destructors_used\n"; + } + return; + } + + std::string name = Mang->getValueName(GVar); + std::string SectionName = TAI->SectionForGlobal(GVar); + + printVisibility(name, GVar->getVisibility()); + + Constant *C = GVar->getInitializer(); + const Type *Type = C->getType(); + unsigned Size = TD->getABITypeSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(GVar); + + SwitchToDataSection(SectionName.c_str()); + + if (C->isNullValue() && /* FIXME: Verify correct */ + !GVar->hasSection() && + (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() || + GVar->isWeakForLinker())) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (GVar->hasExternalLinkage()) { + O << "\t.globl " << name << '\n'; + O << "\t.zerofill __DATA, __common, " << name << ", " + << Size << ", " << Align; + } else if (GVar->hasInternalLinkage()) { + O << TAI->getLCOMMDirective() << name << ',' << Size << ',' << Align; + } else if (!GVar->hasCommonLinkage()) { + O << "\t.globl " << name << '\n' + << TAI->getWeakDefDirective() << name << '\n'; + EmitAlignment(Align, GVar); + O << name << ":\t\t\t\t" << TAI->getCommentString() << " "; + PrintUnmangledNameSafely(GVar, O); + O << '\n'; + EmitGlobalConstant(C); + return; + } else { + O << ".comm " << name << ',' << Size; + // Darwin 9 and above support aligned common data. + if (Subtarget.isDarwin9()) + O << ',' << Align; + } + O << "\t\t" << TAI->getCommentString() << " '"; + PrintUnmangledNameSafely(GVar, O); + O << "'\n"; + return; + } + + switch (GVar->getLinkage()) { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + case GlobalValue::CommonLinkage: + O << "\t.globl " << name << '\n' + << "\t.weak_definition " << name << '\n'; + 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.globl " << name << '\n'; + // FALL THROUGH + case GlobalValue::InternalLinkage: + break; + default: + cerr << "Unknown linkage type!"; + abort(); + } + + EmitAlignment(Align, GVar); + O << name << ":\t\t\t\t" << TAI->getCommentString() << " '"; + PrintUnmangledNameSafely(GVar, O); + O << "'\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'; +} + +bool PPCDarwinAsmPrinter::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) + printModuleLevelGV(I); + + bool isPPC64 = TD->getPointerSizeInBits() == 64; + + // Output stubs for dynamically-linked functions + if (TM.getRelocationModel() == Reloc::PIC_) { + for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); + i != e; ++i) { + SwitchToTextSection("\t.section __TEXT,__picsymbolstub1,symbol_stubs," + "pure_instructions,32"); + EmitAlignment(4); + std::string p = *i; + std::string L0p = (p[0]=='\"') ? "\"L0$" + p.substr(1) : "L0$" + p ; + printSuffixedName(p, "$stub"); + O << ":\n"; + O << "\t.indirect_symbol " << *i << '\n'; + O << "\tmflr r0\n"; + O << "\tbcl 20,31," << L0p << '\n'; + O << L0p << ":\n"; + O << "\tmflr r11\n"; + O << "\taddis r11,r11,ha16("; + printSuffixedName(p, "$lazy_ptr"); + O << "-" << L0p << ")\n"; + O << "\tmtlr r0\n"; + if (isPPC64) + O << "\tldu r12,lo16("; + else + O << "\tlwzu r12,lo16("; + printSuffixedName(p, "$lazy_ptr"); + O << "-" << L0p << ")(r11)\n"; + O << "\tmtctr r12\n"; + O << "\tbctr\n"; + SwitchToDataSection(".lazy_symbol_pointer"); + printSuffixedName(p, "$lazy_ptr"); + O << ":\n"; + O << "\t.indirect_symbol " << *i << '\n'; + if (isPPC64) + O << "\t.quad dyld_stub_binding_helper\n"; + else + O << "\t.long dyld_stub_binding_helper\n"; + } + } else { + for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); + i != e; ++i) { + SwitchToTextSection("\t.section __TEXT,__symbol_stub1,symbol_stubs," + "pure_instructions,16"); + EmitAlignment(4); + std::string p = *i; + printSuffixedName(p, "$stub"); + O << ":\n"; + O << "\t.indirect_symbol " << *i << '\n'; + O << "\tlis r11,ha16("; + printSuffixedName(p, "$lazy_ptr"); + O << ")\n"; + if (isPPC64) + O << "\tldu r12,lo16("; + else + O << "\tlwzu r12,lo16("; + printSuffixedName(p, "$lazy_ptr"); + O << ")(r11)\n"; + O << "\tmtctr r12\n"; + O << "\tbctr\n"; + SwitchToDataSection(".lazy_symbol_pointer"); + printSuffixedName(p, "$lazy_ptr"); + O << ":\n"; + O << "\t.indirect_symbol " << *i << '\n'; + if (isPPC64) + O << "\t.quad dyld_stub_binding_helper\n"; + else + O << "\t.long dyld_stub_binding_helper\n"; + } + } + + O << '\n'; + + if (TAI->doesSupportExceptionHandling() && MMI) { + // Add the (possibly multiple) personalities to the set of global values. + // Only referenced functions get into the Personalities list. + const std::vector& Personalities = MMI->getPersonalities(); + + for (std::vector::const_iterator I = Personalities.begin(), + E = Personalities.end(); I != E; ++I) + if (*I) GVStubs.insert("_" + (*I)->getName()); + } + + // Output stubs for external and common global variables. + if (!GVStubs.empty()) { + SwitchToDataSection(".non_lazy_symbol_pointer"); + for (std::set::iterator I = GVStubs.begin(), + E = GVStubs.end(); I != E; ++I) { + std::string p = *I; + printSuffixedName(p, "$non_lazy_ptr"); + O << ":\n"; + O << "\t.indirect_symbol " << *I << '\n'; + if (isPPC64) + O << "\t.quad\t0\n"; + else + O << "\t.long\t0\n"; + } + } + + // Emit initial debug information. + DW.EndModule(); + + // Funny Darwin hack: This flag tells the linker that no global symbols + // contain code that falls through to other global symbols (e.g. the obvious + // implementation of multiple entry points). If this doesn't occur, the + // linker can safely perform dead code stripping. Since LLVM never generates + // code that does this, it is always safe to set. + O << "\t.subsections_via_symbols\n"; + + return AsmPrinter::doFinalization(M); +} + + + +/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code +/// for a MachineFunction to the given output stream, in a format that the +/// Darwin assembler can deal with. +/// +FunctionPass *llvm::createPPCAsmPrinterPass(std::ostream &o, + PPCTargetMachine &tm) { + const PPCSubtarget *Subtarget = &tm.getSubtarget(); + + if (Subtarget->isDarwin()) { + return new PPCDarwinAsmPrinter(o, tm, tm.getTargetAsmInfo()); + } else { + return new PPCLinuxAsmPrinter(o, tm, tm.getTargetAsmInfo()); + } +} + +namespace { + static struct Register { + Register() { + PPCTargetMachine::registerAsmPrinter(createPPCAsmPrinterPass); + } + } Registrator; +} diff --git a/lib/Target/PowerPC/Makefile b/lib/Target/PowerPC/Makefile index 6cf3fa32d2..2ec959c14b 100644 --- a/lib/Target/PowerPC/Makefile +++ b/lib/Target/PowerPC/Makefile @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## LEVEL = ../../.. -LIBRARYNAME = LLVMPowerPC +LIBRARYNAME = LLVMPowerPCCodegen TARGET = PPC # Make sure that tblgen is run, first thing. @@ -17,4 +17,6 @@ BUILT_SOURCES = PPCGenInstrNames.inc PPCGenRegisterNames.inc \ PPCGenInstrInfo.inc PPCGenDAGISel.inc \ PPCGenSubtarget.inc PPCGenCallingConv.inc +DIRS = AsmPrinter + include $(LEVEL)/Makefile.common diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp deleted file mode 100644 index 1c545903b5..0000000000 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ /dev/null @@ -1,1119 +0,0 @@ -//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly --------=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a printer that converts from our internal representation -// of machine-dependent LLVM code to PowerPC assembly language. This printer is -// the output mechanism used by `llc'. -// -// Documentation at http://developer.apple.com/documentation/DeveloperTools/ -// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asmprinter" -#include "PPC.h" -#include "PPCPredicates.h" -#include "PPCTargetMachine.h" -#include "PPCSubtarget.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Support/Mangler.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringExtras.h" -#include -using namespace llvm; - -STATISTIC(EmittedInsts, "Number of machine instrs printed"); - -namespace { - struct VISIBILITY_HIDDEN PPCAsmPrinter : public AsmPrinter { - std::set FnStubs, GVStubs; - const PPCSubtarget &Subtarget; - - PPCAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) - : AsmPrinter(O, TM, T), Subtarget(TM.getSubtarget()) { - } - - virtual const char *getPassName() const { - return "PowerPC Assembly Printer"; - } - - PPCTargetMachine &getTM() { - return static_cast(TM); - } - - unsigned enumRegToMachineReg(unsigned enumReg) { - switch (enumReg) { - default: assert(0 && "Unhandled register!"); break; - case PPC::CR0: return 0; - case PPC::CR1: return 1; - case PPC::CR2: return 2; - case PPC::CR3: return 3; - case PPC::CR4: return 4; - case PPC::CR5: return 5; - case PPC::CR6: return 6; - case PPC::CR7: return 7; - } - abort(); - } - - /// printInstruction - This method is automatically generated by tablegen - /// from the instruction set description. This method returns true if the - /// machine instruction was sufficiently described to print it, otherwise it - /// returns false. - bool printInstruction(const MachineInstr *MI); - - void printMachineInstruction(const MachineInstr *MI); - void printOp(const MachineOperand &MO); - - /// stripRegisterPrefix - This method strips the character prefix from a - /// register name so that only the number is left. Used by for linux asm. - const char *stripRegisterPrefix(const char *RegName) { - switch (RegName[0]) { - case 'r': - case 'f': - case 'v': return RegName + 1; - case 'c': if (RegName[1] == 'r') return RegName + 2; - } - - return RegName; - } - - /// printRegister - Print register according to target requirements. - /// - void printRegister(const MachineOperand &MO, bool R0AsZero) { - unsigned RegNo = MO.getReg(); - assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); - - // If we should use 0 for R0. - if (R0AsZero && RegNo == PPC::R0) { - O << "0"; - return; - } - - const char *RegName = TM.getRegisterInfo()->get(RegNo).AsmName; - // Linux assembler (Others?) does not take register mnemonics. - // FIXME - What about special registers used in mfspr/mtspr? - if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); - O << RegName; - } - - void printOperand(const MachineInstr *MI, unsigned OpNo) { - const MachineOperand &MO = MI->getOperand(OpNo); - if (MO.isRegister()) { - printRegister(MO, false); - } else if (MO.isImmediate()) { - O << MO.getImm(); - } else { - printOp(MO); - } - } - - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); - bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); - - - void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo) { - char value = MI->getOperand(OpNo).getImm(); - value = (value << (32-5)) >> (32-5); - O << (int)value; - } - void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) { - unsigned char value = MI->getOperand(OpNo).getImm(); - assert(value <= 31 && "Invalid u5imm argument!"); - O << (unsigned int)value; - } - void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo) { - unsigned char value = MI->getOperand(OpNo).getImm(); - assert(value <= 63 && "Invalid u6imm argument!"); - O << (unsigned int)value; - } - void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo) { - O << (short)MI->getOperand(OpNo).getImm(); - } - void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo) { - O << (unsigned short)MI->getOperand(OpNo).getImm(); - } - void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo) { - if (MI->getOperand(OpNo).isImmediate()) { - O << (short)(MI->getOperand(OpNo).getImm()*4); - } else { - O << "lo16("; - printOp(MI->getOperand(OpNo)); - if (TM.getRelocationModel() == Reloc::PIC_) - O << "-\"L" << getFunctionNumber() << "$pb\")"; - else - O << ')'; - } - } - void printBranchOperand(const MachineInstr *MI, unsigned OpNo) { - // Branches can take an immediate operand. This is used by the branch - // selection pass to print $+8, an eight byte displacement from the PC. - if (MI->getOperand(OpNo).isImmediate()) { - O << "$+" << MI->getOperand(OpNo).getImm()*4; - } else { - printOp(MI->getOperand(OpNo)); - } - } - void printCallOperand(const MachineInstr *MI, unsigned OpNo) { - const MachineOperand &MO = MI->getOperand(OpNo); - if (TM.getRelocationModel() != Reloc::Static) { - if (MO.getType() == MachineOperand::MO_GlobalAddress) { - GlobalValue *GV = MO.getGlobal(); - if (((GV->isDeclaration() || GV->hasWeakLinkage() || - GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) { - // Dynamically-resolved functions need a stub for the function. - std::string Name = Mang->getValueName(GV); - FnStubs.insert(Name); - printSuffixedName(Name, "$stub"); - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(GV); - return; - } - } - if (MO.getType() == MachineOperand::MO_ExternalSymbol) { - std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName(); - FnStubs.insert(Name); - printSuffixedName(Name, "$stub"); - return; - } - } - - printOp(MI->getOperand(OpNo)); - } - void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo) { - O << (int)MI->getOperand(OpNo).getImm()*4; - } - void printPICLabel(const MachineInstr *MI, unsigned OpNo) { - O << "\"L" << getFunctionNumber() << "$pb\"\n"; - O << "\"L" << getFunctionNumber() << "$pb\":"; - } - void printSymbolHi(const MachineInstr *MI, unsigned OpNo) { - if (MI->getOperand(OpNo).isImmediate()) { - printS16ImmOperand(MI, OpNo); - } else { - if (Subtarget.isDarwin()) O << "ha16("; - printOp(MI->getOperand(OpNo)); - if (TM.getRelocationModel() == Reloc::PIC_) - O << "-\"L" << getFunctionNumber() << "$pb\""; - if (Subtarget.isDarwin()) - O << ')'; - else - O << "@ha"; - } - } - void printSymbolLo(const MachineInstr *MI, unsigned OpNo) { - if (MI->getOperand(OpNo).isImmediate()) { - printS16ImmOperand(MI, OpNo); - } else { - if (Subtarget.isDarwin()) O << "lo16("; - printOp(MI->getOperand(OpNo)); - if (TM.getRelocationModel() == Reloc::PIC_) - O << "-\"L" << getFunctionNumber() << "$pb\""; - if (Subtarget.isDarwin()) - O << ')'; - else - O << "@l"; - } - } - void printcrbitm(const MachineInstr *MI, unsigned OpNo) { - unsigned CCReg = MI->getOperand(OpNo).getReg(); - unsigned RegNo = enumRegToMachineReg(CCReg); - O << (0x80 >> RegNo); - } - // The new addressing mode printers. - void printMemRegImm(const MachineInstr *MI, unsigned OpNo) { - printSymbolLo(MI, OpNo); - O << '('; - if (MI->getOperand(OpNo+1).isRegister() && - MI->getOperand(OpNo+1).getReg() == PPC::R0) - O << "0"; - else - printOperand(MI, OpNo+1); - O << ')'; - } - void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo) { - if (MI->getOperand(OpNo).isImmediate()) - printS16X4ImmOperand(MI, OpNo); - else - printSymbolLo(MI, OpNo); - O << '('; - if (MI->getOperand(OpNo+1).isRegister() && - MI->getOperand(OpNo+1).getReg() == PPC::R0) - O << "0"; - else - printOperand(MI, OpNo+1); - O << ')'; - } - - void printMemRegReg(const MachineInstr *MI, unsigned OpNo) { - // When used as the base register, r0 reads constant zero rather than - // the value contained in the register. For this reason, the darwin - // assembler requires that we print r0 as 0 (no r) when used as the base. - const MachineOperand &MO = MI->getOperand(OpNo); - printRegister(MO, true); - O << ", "; - printOperand(MI, OpNo+1); - } - - void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier); - - virtual bool runOnMachineFunction(MachineFunction &F) = 0; - virtual bool doFinalization(Module &M) = 0; - - virtual void EmitExternalGlobal(const GlobalVariable *GV); - }; - - /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux - struct VISIBILITY_HIDDEN PPCLinuxAsmPrinter : public PPCAsmPrinter { - - DwarfWriter DW; - MachineModuleInfo *MMI; - - PPCLinuxAsmPrinter(std::ostream &O, PPCTargetMachine &TM, - const TargetAsmInfo *T) - : PPCAsmPrinter(O, TM, T), DW(O, this, T), MMI(0) { - } - - 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; - void printModuleLevelGV(const GlobalVariable* GVar); - }; - - /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac - /// OS X - struct VISIBILITY_HIDDEN PPCDarwinAsmPrinter : public PPCAsmPrinter { - - DwarfWriter DW; - MachineModuleInfo *MMI; - - PPCDarwinAsmPrinter(std::ostream &O, PPCTargetMachine &TM, - const TargetAsmInfo *T) - : PPCAsmPrinter(O, TM, T), DW(O, this, T), MMI(0) { - } - - virtual const char *getPassName() const { - return "Darwin 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; - void printModuleLevelGV(const GlobalVariable* GVar); - }; -} // end of anonymous namespace - -// Include the auto-generated portion of the assembly writer -#include "PPCGenAsmWriter.inc" - -void PPCAsmPrinter::printOp(const MachineOperand &MO) { - switch (MO.getType()) { - case MachineOperand::MO_Immediate: - cerr << "printOp() does not handle immediate values\n"; - abort(); - return; - - case MachineOperand::MO_MachineBasicBlock: - printBasicBlockLabel(MO.getMBB()); - return; - case MachineOperand::MO_JumpTableIndex: - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - // FIXME: PIC relocation model - return; - case MachineOperand::MO_ConstantPoolIndex: - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << MO.getIndex(); - return; - case MachineOperand::MO_ExternalSymbol: - // Computing the address of an external symbol, not calling it. - if (TM.getRelocationModel() != Reloc::Static) { - std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName(); - GVStubs.insert(Name); - printSuffixedName(Name, "$non_lazy_ptr"); - return; - } - O << TAI->getGlobalPrefix() << MO.getSymbolName(); - return; - case MachineOperand::MO_GlobalAddress: { - // Computing the address of a global symbol, not calling it. - GlobalValue *GV = MO.getGlobal(); - std::string Name = Mang->getValueName(GV); - - // External or weakly linked global variables need non-lazily-resolved stubs - if (TM.getRelocationModel() != Reloc::Static) { - if (((GV->isDeclaration() || GV->hasWeakLinkage() || - GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) { - GVStubs.insert(Name); - printSuffixedName(Name, "$non_lazy_ptr"); - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(GV); - return; - } - } - O << Name; - - if (MO.getOffset() > 0) - O << "+" << MO.getOffset(); - else if (MO.getOffset() < 0) - O << MO.getOffset(); - - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(GV); - return; - } - - default: - O << ""; - return; - } -} - -/// EmitExternalGlobal - In this case we need to use the indirect symbol. -/// -void PPCAsmPrinter::EmitExternalGlobal(const GlobalVariable *GV) { - std::string Name = getGlobalLinkName(GV); - if (TM.getRelocationModel() != Reloc::Static) { - GVStubs.insert(Name); - printSuffixedName(Name, "$non_lazy_ptr"); - return; - } - O << Name; -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - switch (ExtraCode[0]) { - default: return true; // Unknown modifier. - case 'c': // Don't print "$" before a global var name or constant. - // PPC never has a prefix. - printOperand(MI, OpNo); - return false; - case 'L': // Write second word of DImode reference. - // Verify that this operand has two consecutive registers. - if (!MI->getOperand(OpNo).isRegister() || - OpNo+1 == MI->getNumOperands() || - !MI->getOperand(OpNo+1).isRegister()) - return true; - ++OpNo; // Return the high-part. - break; - case 'I': - // Write 'i' if an integer constant, otherwise nothing. Used to print - // addi vs add, etc. - if (MI->getOperand(OpNo).isImmediate()) - O << "i"; - return false; - } - } - - printOperand(MI, OpNo); - return false; -} - -bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. - if (MI->getOperand(OpNo).isRegister()) - printMemRegReg(MI, OpNo); - else - printMemRegImm(MI, OpNo); - return false; -} - -void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier) { - assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!"); - unsigned Code = MI->getOperand(OpNo).getImm(); - if (!strcmp(Modifier, "cc")) { - switch ((PPC::Predicate)Code) { - case PPC::PRED_ALWAYS: return; // Don't print anything for always. - case PPC::PRED_LT: O << "lt"; return; - case PPC::PRED_LE: O << "le"; return; - case PPC::PRED_EQ: O << "eq"; return; - case PPC::PRED_GE: O << "ge"; return; - case PPC::PRED_GT: O << "gt"; return; - case PPC::PRED_NE: O << "ne"; return; - case PPC::PRED_UN: O << "un"; return; - case PPC::PRED_NU: O << "nu"; return; - } - - } else { - assert(!strcmp(Modifier, "reg") && - "Need to specify 'cc' or 'reg' as predicate op modifier!"); - // Don't print the register for 'always'. - if (Code == PPC::PRED_ALWAYS) return; - printOperand(MI, OpNo+1); - } -} - - -/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to -/// the current output stream. -/// -void PPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) { - ++EmittedInsts; - - // Check for slwi/srwi mnemonics. - if (MI->getOpcode() == PPC::RLWINM) { - bool FoundMnemonic = false; - unsigned char SH = MI->getOperand(2).getImm(); - unsigned char MB = MI->getOperand(3).getImm(); - unsigned char ME = MI->getOperand(4).getImm(); - if (SH <= 31 && MB == 0 && ME == (31-SH)) { - O << "\tslwi "; FoundMnemonic = true; - } - if (SH <= 31 && MB == (32-SH) && ME == 31) { - O << "\tsrwi "; FoundMnemonic = true; - SH = 32-SH; - } - if (FoundMnemonic) { - printOperand(MI, 0); - O << ", "; - printOperand(MI, 1); - O << ", " << (unsigned int)SH << '\n'; - return; - } - } else if (MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) { - if (MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { - O << "\tmr "; - printOperand(MI, 0); - O << ", "; - printOperand(MI, 1); - O << '\n'; - return; - } - } else if (MI->getOpcode() == PPC::RLDICR) { - unsigned char SH = MI->getOperand(2).getImm(); - unsigned char ME = MI->getOperand(3).getImm(); - // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH - if (63-SH == ME) { - O << "\tsldi "; - printOperand(MI, 0); - O << ", "; - printOperand(MI, 1); - O << ", " << (unsigned int)SH << '\n'; - return; - } - } - - if (printInstruction(MI)) - return; // Printer was automatically generated - - assert(0 && "Unhandled instruction in asm writer!"); - abort(); - return; -} - -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - - 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; - } - - printVisibility(CurrentFnName, F->getVisibility()); - - 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, true); - O << '\n'; - } - for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); - II != E; ++II) { - // Print the assembly for the instruction. - 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 PPCLinuxAsmPrinter::doInitialization(Module &M) { - bool Result = AsmPrinter::doInitialization(M); - - // Emit initial debug information. - DW.BeginModule(&M); - - // AsmPrinter::doInitialization should have done this analysis. - MMI = getAnalysisToUpdate(); - assert(MMI); - DW.SetModuleInfo(MMI); - - // GNU as handles section names wrapped in quotes - Mang->setUseQuotes(true); - - SwitchToTextSection(TAI->getTextSection()); - - return Result; -} - -/// PrintUnmangledNameSafely - Print out the printable characters in the name. -/// Don't print things like \n or \0. -static void PrintUnmangledNameSafely(const Value *V, std::ostream &OS) { - for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); - Name != E; ++Name) - if (isprint(*Name)) - OS << *Name; -} - -void PPCLinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - std::string name = Mang->getValueName(GVar); - std::string SectionName = TAI->SectionForGlobal(GVar); - - printVisibility(name, GVar->getVisibility()); - - Constant *C = GVar->getInitializer(); - const Type *Type = C->getType(); - unsigned Size = TD->getABITypeSize(Type); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - SwitchToDataSection(SectionName.c_str()); - - if (C->isNullValue() && /* FIXME: Verify correct */ - !GVar->hasSection() && - (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() || - GVar->isWeakForLinker())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasExternalLinkage()) { - O << "\t.global " << name << '\n'; - O << "\t.type " << name << ", @object\n"; - O << name << ":\n"; - O << "\t.zero " << Size << '\n'; - } else if (GVar->hasInternalLinkage()) { - O << TAI->getLCOMMDirective() << name << ',' << Size; - } else { - O << ".comm " << name << ',' << Size; - } - O << "\t\t" << TAI->getCommentString() << " '"; - PrintUnmangledNameSafely(GVar, O); - O << "'\n"; - return; - } - - switch (GVar->getLinkage()) { - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: - case GlobalValue::CommonLinkage: - O << "\t.global " << name << '\n' - << "\t.type " << name << ", @object\n" - << "\t.weak " << name << '\n'; - 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: - break; - default: - cerr << "Unknown linkage type!"; - abort(); - } - - EmitAlignment(Align, GVar); - O << name << ":\t\t\t\t" << TAI->getCommentString() << " '"; - PrintUnmangledNameSafely(GVar, O); - O << "'\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'; -} - -bool PPCLinuxAsmPrinter::doFinalization(Module &M) { - // Print out module-level global variables here. - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - printModuleLevelGV(I); - - // TODO - - // Emit initial debug information. - DW.EndModule(); - - return AsmPrinter::doFinalization(M); -} - -std::string PPCLinuxAsmPrinter::getSectionForFunction(const Function &F) const { - return TAI->SectionForGlobal(&F); -} - -std::string PPCDarwinAsmPrinter::getSectionForFunction(const Function &F) const { - return TAI->SectionForGlobal(&F); -} - -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - 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.globl\t" << CurrentFnName << '\n'; - break; - case Function::WeakLinkage: - case Function::LinkOnceLinkage: - O << "\t.globl\t" << CurrentFnName << '\n'; - O << "\t.weak_definition\t" << CurrentFnName << '\n'; - break; - } - - printVisibility(CurrentFnName, F->getVisibility()); - - EmitAlignment(OptimizeForSize ? 2 : 4, F); - O << CurrentFnName << ":\n"; - - // Emit pre-function debug information. - DW.BeginFunction(&MF); - - // If the function is empty, then we need to emit *something*. Otherwise, the - // function's label might be associated with something that it wasn't meant to - // be associated with. We emit a noop in this situation. - MachineFunction::iterator I = MF.begin(); - - if (++I == MF.end() && MF.front().empty()) - O << "\tnop\n"; - - // 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, true); - O << '\n'; - } - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - // Print the assembly for the instruction. - printMachineInstruction(II); - } - } - - // 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 PPCDarwinAsmPrinter::doInitialization(Module &M) { - static const char *const CPUDirectives[] = { - "", - "ppc", - "ppc601", - "ppc602", - "ppc603", - "ppc7400", - "ppc750", - "ppc970", - "ppc64" - }; - - unsigned Directive = Subtarget.getDarwinDirective(); - if (Subtarget.isGigaProcessor() && Directive < PPC::DIR_970) - Directive = PPC::DIR_970; - if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400) - Directive = PPC::DIR_7400; - if (Subtarget.isPPC64() && Directive < PPC::DIR_970) - Directive = PPC::DIR_64; - assert(Directive <= PPC::DIR_64 && "Directive out of range."); - O << "\t.machine " << CPUDirectives[Directive] << '\n'; - - bool Result = AsmPrinter::doInitialization(M); - - // Emit initial debug information. - DW.BeginModule(&M); - - // We need this for Personality functions. - // AsmPrinter::doInitialization should have done this analysis. - MMI = getAnalysisToUpdate(); - assert(MMI); - DW.SetModuleInfo(MMI); - - // Darwin wants symbols to be quoted if they have complex names. - Mang->setUseQuotes(true); - - // Prime text sections so they are adjacent. This reduces the likelihood a - // large data or debug section causes a branch to exceed 16M limit. - SwitchToTextSection("\t.section __TEXT,__textcoal_nt,coalesced," - "pure_instructions"); - if (TM.getRelocationModel() == Reloc::PIC_) { - SwitchToTextSection("\t.section __TEXT,__picsymbolstub1,symbol_stubs," - "pure_instructions,32"); - } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { - SwitchToTextSection("\t.section __TEXT,__symbol_stub1,symbol_stubs," - "pure_instructions,16"); - } - SwitchToTextSection(TAI->getTextSection()); - - return Result; -} - -void PPCDarwinAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) { - if (TM.getRelocationModel() == Reloc::Static) { - if (GVar->getName() == "llvm.global_ctors") - O << ".reference .constructors_used\n"; - else if (GVar->getName() == "llvm.global_dtors") - O << ".reference .destructors_used\n"; - } - return; - } - - std::string name = Mang->getValueName(GVar); - std::string SectionName = TAI->SectionForGlobal(GVar); - - printVisibility(name, GVar->getVisibility()); - - Constant *C = GVar->getInitializer(); - const Type *Type = C->getType(); - unsigned Size = TD->getABITypeSize(Type); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - SwitchToDataSection(SectionName.c_str()); - - if (C->isNullValue() && /* FIXME: Verify correct */ - !GVar->hasSection() && - (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() || - GVar->isWeakForLinker())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasExternalLinkage()) { - O << "\t.globl " << name << '\n'; - O << "\t.zerofill __DATA, __common, " << name << ", " - << Size << ", " << Align; - } else if (GVar->hasInternalLinkage()) { - O << TAI->getLCOMMDirective() << name << ',' << Size << ',' << Align; - } else if (!GVar->hasCommonLinkage()) { - O << "\t.globl " << name << '\n' - << TAI->getWeakDefDirective() << name << '\n'; - EmitAlignment(Align, GVar); - O << name << ":\t\t\t\t" << TAI->getCommentString() << " "; - PrintUnmangledNameSafely(GVar, O); - O << '\n'; - EmitGlobalConstant(C); - return; - } else { - O << ".comm " << name << ',' << Size; - // Darwin 9 and above support aligned common data. - if (Subtarget.isDarwin9()) - O << ',' << Align; - } - O << "\t\t" << TAI->getCommentString() << " '"; - PrintUnmangledNameSafely(GVar, O); - O << "'\n"; - return; - } - - switch (GVar->getLinkage()) { - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: - case GlobalValue::CommonLinkage: - O << "\t.globl " << name << '\n' - << "\t.weak_definition " << name << '\n'; - 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.globl " << name << '\n'; - // FALL THROUGH - case GlobalValue::InternalLinkage: - break; - default: - cerr << "Unknown linkage type!"; - abort(); - } - - EmitAlignment(Align, GVar); - O << name << ":\t\t\t\t" << TAI->getCommentString() << " '"; - PrintUnmangledNameSafely(GVar, O); - O << "'\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'; -} - -bool PPCDarwinAsmPrinter::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) - printModuleLevelGV(I); - - bool isPPC64 = TD->getPointerSizeInBits() == 64; - - // Output stubs for dynamically-linked functions - if (TM.getRelocationModel() == Reloc::PIC_) { - for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); - i != e; ++i) { - SwitchToTextSection("\t.section __TEXT,__picsymbolstub1,symbol_stubs," - "pure_instructions,32"); - EmitAlignment(4); - std::string p = *i; - std::string L0p = (p[0]=='\"') ? "\"L0$" + p.substr(1) : "L0$" + p ; - printSuffixedName(p, "$stub"); - O << ":\n"; - O << "\t.indirect_symbol " << *i << '\n'; - O << "\tmflr r0\n"; - O << "\tbcl 20,31," << L0p << '\n'; - O << L0p << ":\n"; - O << "\tmflr r11\n"; - O << "\taddis r11,r11,ha16("; - printSuffixedName(p, "$lazy_ptr"); - O << "-" << L0p << ")\n"; - O << "\tmtlr r0\n"; - if (isPPC64) - O << "\tldu r12,lo16("; - else - O << "\tlwzu r12,lo16("; - printSuffixedName(p, "$lazy_ptr"); - O << "-" << L0p << ")(r11)\n"; - O << "\tmtctr r12\n"; - O << "\tbctr\n"; - SwitchToDataSection(".lazy_symbol_pointer"); - printSuffixedName(p, "$lazy_ptr"); - O << ":\n"; - O << "\t.indirect_symbol " << *i << '\n'; - if (isPPC64) - O << "\t.quad dyld_stub_binding_helper\n"; - else - O << "\t.long dyld_stub_binding_helper\n"; - } - } else { - for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); - i != e; ++i) { - SwitchToTextSection("\t.section __TEXT,__symbol_stub1,symbol_stubs," - "pure_instructions,16"); - EmitAlignment(4); - std::string p = *i; - printSuffixedName(p, "$stub"); - O << ":\n"; - O << "\t.indirect_symbol " << *i << '\n'; - O << "\tlis r11,ha16("; - printSuffixedName(p, "$lazy_ptr"); - O << ")\n"; - if (isPPC64) - O << "\tldu r12,lo16("; - else - O << "\tlwzu r12,lo16("; - printSuffixedName(p, "$lazy_ptr"); - O << ")(r11)\n"; - O << "\tmtctr r12\n"; - O << "\tbctr\n"; - SwitchToDataSection(".lazy_symbol_pointer"); - printSuffixedName(p, "$lazy_ptr"); - O << ":\n"; - O << "\t.indirect_symbol " << *i << '\n'; - if (isPPC64) - O << "\t.quad dyld_stub_binding_helper\n"; - else - O << "\t.long dyld_stub_binding_helper\n"; - } - } - - O << '\n'; - - if (TAI->doesSupportExceptionHandling() && MMI) { - // Add the (possibly multiple) personalities to the set of global values. - // Only referenced functions get into the Personalities list. - const std::vector& Personalities = MMI->getPersonalities(); - - for (std::vector::const_iterator I = Personalities.begin(), - E = Personalities.end(); I != E; ++I) - if (*I) GVStubs.insert("_" + (*I)->getName()); - } - - // Output stubs for external and common global variables. - if (!GVStubs.empty()) { - SwitchToDataSection(".non_lazy_symbol_pointer"); - for (std::set::iterator I = GVStubs.begin(), - E = GVStubs.end(); I != E; ++I) { - std::string p = *I; - printSuffixedName(p, "$non_lazy_ptr"); - O << ":\n"; - O << "\t.indirect_symbol " << *I << '\n'; - if (isPPC64) - O << "\t.quad\t0\n"; - else - O << "\t.long\t0\n"; - } - } - - // Emit initial debug information. - DW.EndModule(); - - // Funny Darwin hack: This flag tells the linker that no global symbols - // contain code that falls through to other global symbols (e.g. the obvious - // implementation of multiple entry points). If this doesn't occur, the - // linker can safely perform dead code stripping. Since LLVM never generates - // code that does this, it is always safe to set. - O << "\t.subsections_via_symbols\n"; - - return AsmPrinter::doFinalization(M); -} - - - -/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code -/// for a MachineFunction to the given output stream, in a format that the -/// Darwin assembler can deal with. -/// -FunctionPass *llvm::createPPCAsmPrinterPass(std::ostream &o, - PPCTargetMachine &tm) { - const PPCSubtarget *Subtarget = &tm.getSubtarget(); - - if (Subtarget->isDarwin()) { - return new PPCDarwinAsmPrinter(o, tm, tm.getTargetAsmInfo()); - } else { - return new PPCLinuxAsmPrinter(o, tm, tm.getTargetAsmInfo()); - } -} diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index 7c90eca3c4..7857848674 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -26,6 +26,9 @@ X("ppc32", " PowerPC 32"); static RegisterTarget Y("ppc64", " PowerPC 64"); +// No assembler printer by default +PPCTargetMachine::AsmPrinterCtorFn PPCTargetMachine::AsmPrinterCtor = 0; + const TargetAsmInfo *PPCTargetMachine::createTargetAsmInfo() const { if (Subtarget.isDarwin()) return new PPCDarwinTargetAsmInfo(*this); @@ -132,7 +135,10 @@ bool PPCTargetMachine::addPreEmitPass(PassManagerBase &PM, bool Fast) { bool PPCTargetMachine::addAssemblyEmitter(PassManagerBase &PM, bool Fast, std::ostream &Out) { - PM.add(createPPCAsmPrinterPass(Out, *this)); + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(Out, *this)); + return false; } @@ -158,8 +164,12 @@ bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM, bool Fast, // Machine code emitter pass for PowerPC. PM.add(createPPCCodeEmitterPass(*this, MCE)); - if (DumpAsm) - PM.add(createPPCAsmPrinterPass(*cerr.stream(), *this)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(*cerr.stream(), *this)); + } + return false; } @@ -167,7 +177,11 @@ bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, bool Fast, bool DumpAsm, MachineCodeEmitter &MCE) { // Machine code emitter pass for PowerPC. PM.add(createPPCCodeEmitterPass(*this, MCE)); - if (DumpAsm) - PM.add(createPPCAsmPrinterPass(*cerr.stream(), *this)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(*cerr.stream(), *this)); + } + return false; } diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h index ac2c2aa723..58fd55d552 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.h +++ b/lib/Target/PowerPC/PPCTargetMachine.h @@ -41,7 +41,13 @@ class PPCTargetMachine : public LLVMTargetMachine { protected: virtual const TargetAsmInfo *createTargetAsmInfo() const; - + + // To avoid having target depend on the asmprinter stuff libraries, asmprinter + // set this functions to ctor pointer at startup time if they are linked in. + typedef FunctionPass *(*AsmPrinterCtorFn)(std::ostream &o, + PPCTargetMachine &tm); + static AsmPrinterCtorFn AsmPrinterCtor; + public: PPCTargetMachine(const Module &M, const std::string &FS, bool is64Bit); @@ -63,7 +69,11 @@ public: virtual const PPCMachOWriterInfo *getMachOWriterInfo() const { return &MachOWriterInfo; } - + + static void registerAsmPrinter(AsmPrinterCtorFn F) { + AsmPrinterCtor = F; + } + // Pass Pipeline Configuration virtual bool addInstSelector(PassManagerBase &PM, bool Fast); virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast); -- cgit v1.2.3