X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FPowerPC%2FPPCAsmPrinter.cpp;h=7c1e20427723d645de0f6677863ef039b4ef3864;hb=94b9550a32d189704a8eae55505edf62662c0534;hp=c84c6fb15986bb9a39742120e6a46608ce4f2db6;hpb=55a7ec33d7cafa703a1b6e6410d7c26d5b7ded0b;p=oota-llvm.git diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index c84c6fb1598..7c1e2042772 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -18,326 +18,216 @@ #define DEBUG_TYPE "asmprinter" #include "PPC.h" -#include "PPCPredicates.h" #include "PPCTargetMachine.h" #include "PPCSubtarget.h" +#include "MCTargetDesc/PPCPredicates.h" +#include "llvm/Analysis/DebugInfo.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/MachineDebugInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.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/MRegisterInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/Statistic.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/StringExtras.h" -#include +#include "llvm/ADT/StringSet.h" +#include "llvm/ADT/SmallString.h" +#include "InstPrinter/PPCInstPrinter.h" using namespace llvm; namespace { - Statistic EmittedInsts("asm-printer", "Number of machine instrs printed"); - - struct VISIBILITY_HIDDEN PPCAsmPrinter : public AsmPrinter { - std::set FnStubs, GVStubs; + class PPCAsmPrinter : public AsmPrinter { + protected: + DenseMap TOC; const PPCSubtarget &Subtarget; - - // Necessary for external weak linkage support - std::set ExtWeakSymbols; - - PPCAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) - : AsmPrinter(O, TM, T), Subtarget(TM.getSubtarget()) { - } + uint64_t TOCLabelID; + public: + explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer), + Subtarget(TM.getSubtarget()), TOCLabelID(0) {} 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(); - } + virtual void EmitInstruction(const MachineInstr *MI); + + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); - /// 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); - - void printOperand(const MachineInstr *MI, unsigned OpNo) { - const MachineOperand &MO = MI->getOperand(OpNo); - if (MO.isRegister()) { - assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??"); - O << TM.getRegisterInfo()->get(MO.getReg()).Name; - } else if (MO.isImmediate()) { - O << MO.getImmedValue(); - } else { - printOp(MO); - } - } - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); - - - void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo) { - char value = MI->getOperand(OpNo).getImmedValue(); - value = (value << (32-5)) >> (32-5); - O << (int)value; - } - void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) { - unsigned char value = MI->getOperand(OpNo).getImmedValue(); - assert(value <= 31 && "Invalid u5imm argument!"); - O << (unsigned int)value; - } - void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo) { - unsigned char value = MI->getOperand(OpNo).getImmedValue(); - assert(value <= 63 && "Invalid u6imm argument!"); - O << (unsigned int)value; - } - void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo) { - O << (short)MI->getOperand(OpNo).getImmedValue(); - } - void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo) { - O << (unsigned short)MI->getOperand(OpNo).getImmedValue(); - } - void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo) { - if (MI->getOperand(OpNo).isImmediate()) { - O << (short)(MI->getOperand(OpNo).getImmedValue()*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).getImmedValue()*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->isExternal() || GV->hasWeakLinkage() || - GV->hasLinkOnceLinkage()))) { - // Dynamically-resolved functions need a stub for the function. - std::string Name = Mang->getValueName(GV); - FnStubs.insert(Name); - O << "L" << Name << "$stub"; - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(Name); - return; - } - } - if (MO.getType() == MachineOperand::MO_ExternalSymbol) { - std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName(); - FnStubs.insert(Name); - O << "L" << Name << "$stub"; - return; - } + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + + MachineLocation getDebugValueLocation(const MachineInstr *MI) const { + MachineLocation Location; + assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); + // Frame address. Currently handles register +- offset only. + if (MI->getOperand(0).isReg() && MI->getOperand(2).isImm()) + Location.set(MI->getOperand(0).getReg(), MI->getOperand(2).getImm()); + else { + DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); } - - printOp(MI->getOperand(OpNo)); - } - void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo) { - O << (int)MI->getOperand(OpNo).getImmedValue()*4; + return Location; } - 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 { - O << "ha16("; - printOp(MI->getOperand(OpNo)); - if (TM.getRelocationModel() == Reloc::PIC_) - O << "-\"L" << getFunctionNumber() << "$pb\")"; - else - O << ')'; - } - } - void printSymbolLo(const MachineInstr *MI, unsigned OpNo) { - if (MI->getOperand(OpNo).isImmediate()) { - printS16ImmOperand(MI, OpNo); - } else { - O << "lo16("; - printOp(MI->getOperand(OpNo)); - if (TM.getRelocationModel() == Reloc::PIC_) - O << "-\"L" << getFunctionNumber() << "$pb\")"; - else - O << ')'; - } - } - 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); - if (MO.getReg() == PPC::R0) - O << '0'; - else - O << TM.getRegisterInfo()->get(MO.getReg()).Name; - 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; }; - /// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS - /// X - struct VISIBILITY_HIDDEN DarwinAsmPrinter : public PPCAsmPrinter { - - DwarfWriter DW; + /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux + class PPCLinuxAsmPrinter : public PPCAsmPrinter { + public: + explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : PPCAsmPrinter(TM, Streamer) {} - DarwinAsmPrinter(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 doFinalization(Module &M); + + virtual void EmitFunctionEntryLabel(); + }; + + /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac + /// OS X + class PPCDarwinAsmPrinter : public PPCAsmPrinter { + public: + explicit PPCDarwinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : PPCAsmPrinter(TM, Streamer) {} + 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); - } + void EmitStartOfAsmFile(Module &M); - /// getSectionForFunction - Return the section that we should emit the - /// specified function body into. - virtual std::string getSectionForFunction(const Function &F) const; + void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs); }; } // end of anonymous namespace -// Include the auto-generated portion of the assembly writer -#include "PPCGenAsmWriter.inc" +/// stripRegisterPrefix - This method strips the character prefix from a +/// register name so that only the number is left. Used by for linux asm. +static 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; +} -void PPCAsmPrinter::printOp(const MachineOperand &MO) { +void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(OpNo); + switch (MO.getType()) { + case MachineOperand::MO_Register: { + const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg()); + // 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; + return; + } case MachineOperand::MO_Immediate: - cerr << "printOp() does not handle immediate values\n"; - abort(); + O << MO.getImm(); return; case MachineOperand::MO_MachineBasicBlock: - printBasicBlockLabel(MO.getMachineBasicBlock()); + O << *MO.getMBB()->getSymbol(); return; case MachineOperand::MO_JumpTableIndex: - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getJumpTableIndex(); + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); // FIXME: PIC relocation model return; case MachineOperand::MO_ConstantPoolIndex: - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << MO.getConstantPoolIndex(); + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << MO.getIndex(); + return; + case MachineOperand::MO_BlockAddress: + O << *GetBlockAddressSymbol(MO.getBlockAddress()); return; - case MachineOperand::MO_ExternalSymbol: + 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); - O << "L" << Name << "$non_lazy_ptr"; + if (TM.getRelocationModel() == Reloc::Static) { + O << *GetExternalSymbolSymbol(MO.getSymbolName()); return; } - O << TAI->getGlobalPrefix() << MO.getSymbolName(); + + MCSymbol *NLPSym = + OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+ + MO.getSymbolName()+"$non_lazy_ptr"); + MachineModuleInfoImpl::StubValueTy &StubSym = + MMI->getObjFileInfo().getGVStubEntry(NLPSym); + if (StubSym.getPointer() == 0) + StubSym = MachineModuleInfoImpl:: + StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true); + + O << *NLPSym; 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); + const GlobalValue *GV = MO.getGlobal(); + MCSymbol *SymToPrint; // External or weakly linked global variables need non-lazily-resolved stubs - if (TM.getRelocationModel() != Reloc::Static) { - if (((GV->isExternal() || GV->hasWeakLinkage() || - GV->hasLinkOnceLinkage()))) { - GVStubs.insert(Name); - O << "L" << Name << "$non_lazy_ptr"; - return; + if (TM.getRelocationModel() != Reloc::Static && + (GV->isDeclaration() || GV->isWeakForLinker())) { + if (!GV->hasHiddenVisibility()) { + SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + MachineModuleInfoImpl::StubValueTy &StubSym = + MMI->getObjFileInfo() + .getGVStubEntry(SymToPrint); + if (StubSym.getPointer() == 0) + StubSym = MachineModuleInfoImpl:: + StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); + } else if (GV->isDeclaration() || GV->hasCommonLinkage() || + GV->hasAvailableExternallyLinkage()) { + SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + + MachineModuleInfoImpl::StubValueTy &StubSym = + MMI->getObjFileInfo(). + getHiddenGVStubEntry(SymToPrint); + if (StubSym.getPointer() == 0) + StubSym = MachineModuleInfoImpl:: + StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); + } else { + SymToPrint = Mang->getSymbol(GV); } + } else { + SymToPrint = Mang->getSymbol(GV); } - O << Name; - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(Name); + O << *SymToPrint; + + printOffset(MO.getOffset(), O); return; } @@ -350,417 +240,447 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) { /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { // 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 'L': // Write second word of DImode reference. + case 'c': // Don't print "$" before a global var name or constant. + break; // PPC never has a prefix. + case 'L': // Write second word of DImode reference. // Verify that this operand has two consecutive registers. - if (!MI->getOperand(OpNo).isRegister() || + if (!MI->getOperand(OpNo).isReg() || OpNo+1 == MI->getNumOperands() || - !MI->getOperand(OpNo+1).isRegister()) + !MI->getOperand(OpNo+1).isReg()) 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).isImm()) + O << "i"; + return false; } } - - printOperand(MI, OpNo); + + printOperand(MI, OpNo, O); return false; } +// At the moment, all inline asm memory operands are a single register. +// In any case, the output of this routine should always be just one +// assembler operand. + bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { + unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - printMemRegReg(MI, OpNo); + assert(MI->getOperand(OpNo).isReg()); + O << "0("; + printOperand(MI, OpNo, O); + O << ")"; 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 +/// EmitInstruction -- 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).getImmedValue(); - unsigned char MB = MI->getOperand(3).getImmedValue(); - unsigned char ME = MI->getOperand(4).getImmedValue(); - if (SH <= 31 && MB == 0 && ME == (31-SH)) { - O << "slwi "; FoundMnemonic = true; - } - if (SH <= 31 && MB == (32-SH) && ME == 31) { - O << "srwi "; 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 << "mr "; - printOperand(MI, 0); - O << ", "; - printOperand(MI, 1); - O << "\n"; - return; - } - } else if (MI->getOpcode() == PPC::RLDICR) { - unsigned char SH = MI->getOperand(2).getImmedValue(); - unsigned char ME = MI->getOperand(3).getImmedValue(); - // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH - if (63-SH == ME) { - O << "sldi "; - printOperand(MI, 0); - O << ", "; - printOperand(MI, 1); - O << ", " << (unsigned int)SH << "\n"; - return; - } +void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { + MCInst TmpInst; + + // Lower multi-instruction pseudo operations. + switch (MI->getOpcode()) { + default: break; + case TargetOpcode::DBG_VALUE: { + if (!isVerbose() || !OutStreamer.hasRawTextSupport()) return; + + SmallString<32> Str; + raw_svector_ostream O(Str); + unsigned NOps = MI->getNumOperands(); + assert(NOps==4); + O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; + // cast away const; DIetc do not take const operands for some reason. + DIVariable V(const_cast(MI->getOperand(NOps-1).getMetadata())); + O << V.getName(); + O << " <- "; + // Frame address. Currently handles register +- offset only. + assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); + O << '['; printOperand(MI, 0, O); O << '+'; printOperand(MI, 1, O); + O << ']'; + O << "+"; + printOperand(MI, NOps-2, O); + OutStreamer.EmitRawText(O.str()); + return; + } + + case PPC::MovePCtoLR: + case PPC::MovePCtoLR8: { + // Transform %LR = MovePCtoLR + // Into this, where the label is the PIC base: + // bl L1$pb + // L1$pb: + MCSymbol *PICBase = MF->getPICBaseSymbol(); + + // Emit the 'bl'. + TmpInst.setOpcode(PPC::BL_Darwin); // Darwin vs SVR4 doesn't matter here. + + + // FIXME: We would like an efficient form for this, so we don't have to do + // a lot of extra uniquing. + TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr:: + Create(PICBase, OutContext))); + OutStreamer.EmitInstruction(TmpInst); + + // Emit the label. + OutStreamer.EmitLabel(PICBase); + return; + } + case PPC::LDtoc: { + // Transform %X3 = LDtoc , %X2 + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); + + // Change the opcode to LD, and the global address operand to be a + // reference to the TOC entry we will synthesize later. + TmpInst.setOpcode(PPC::LD); + const MachineOperand &MO = MI->getOperand(1); + assert(MO.isGlobal()); + + // Map symbol -> label of TOC entry. + MCSymbol *&TOCEntry = TOC[Mang->getSymbol(MO.getGlobal())]; + if (TOCEntry == 0) + TOCEntry = GetTempSymbol("C", TOCLabelID++); + + const MCExpr *Exp = + MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC, + OutContext); + TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); + OutStreamer.EmitInstruction(TmpInst); + return; + } + + case PPC::MFCRpseud: + // Transform: %R3 = MFCRpseud %CR7 + // Into: %R3 = MFCR ;; cr7 + OutStreamer.AddComment(PPCInstPrinter:: + getRegisterName(MI->getOperand(1).getReg())); + TmpInst.setOpcode(PPC::MFCR); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + OutStreamer.EmitInstruction(TmpInst); + return; } - if (printInstruction(MI)) - return; // Printer was automatically generated - - assert(0 && "Unhandled instruction in asm writer!"); - abort(); - return; + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); + OutStreamer.EmitInstruction(TmpInst); } +void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { + if (!Subtarget.isPPC64()) // linux/ppc32 - Normal entry label. + return AsmPrinter::EmitFunctionEntryLabel(); + + // Emit an official procedure descriptor. + // FIXME 64-bit SVR4: Use MCSection here! + OutStreamer.EmitRawText(StringRef("\t.section\t\".opd\",\"aw\"")); + OutStreamer.EmitRawText(StringRef("\t.align 3")); + OutStreamer.EmitLabel(CurrentFnSym); + OutStreamer.EmitRawText("\t.quad .L." + Twine(CurrentFnSym->getName()) + + ",.TOC.@tocbase"); + OutStreamer.EmitRawText(StringRef("\t.previous")); + OutStreamer.EmitRawText(".L." + Twine(CurrentFnSym->getName()) + ":"); +} -std::string DarwinAsmPrinter::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 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions"; - } -} +bool PPCLinuxAsmPrinter::doFinalization(Module &M) { + const TargetData *TD = TM.getTargetData(); -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - DW.SetDebugInfo(&getAnalysis()); + bool isPPC64 = TD->getPointerSizeInBits() == 64; - SetupMachineFunction(MF); - O << "\n\n"; - - // Print out constants referenced by the function - EmitConstantPool(MF.getConstantPool()); + if (isPPC64 && !TOC.empty()) { + // FIXME 64-bit SVR4: Use MCSection here? + OutStreamer.EmitRawText(StringRef("\t.section\t\".toc\",\"aw\"")); - // 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; - } - EmitAlignment(4, 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); + // FIXME: This is nondeterminstic! + for (DenseMap::iterator I = TOC.begin(), + E = TOC.end(); I != E; ++I) { + OutStreamer.EmitLabel(I->second); + OutStreamer.EmitRawText("\t.tc " + Twine(I->first->getName()) + + "[TC]," + I->first->getName()); } } - // 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; + return AsmPrinter::doFinalization(M); } +void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { + static const char *const CPUDirectives[] = { + "", + "ppc", + "ppc601", + "ppc602", + "ppc603", + "ppc7400", + "ppc750", + "ppc970", + "ppc64" + }; -bool DarwinAsmPrinter::doInitialization(Module &M) { - const std::string &CPU = Subtarget.getCPU(); - - if (CPU != "generic") - O << "\t.machine ppc" << CPU << "\n"; - else if (Subtarget.isGigaProcessor()) - O << "\t.machine ppc970\n"; - else if (Subtarget.isPPC64()) - O << "\t.machine ppc64\n"; - else if (Subtarget.hasAltivec()) - O << "\t.machine ppc7400\n"; - else - O << "\t.machine ppc\n"; - - AsmPrinter::doInitialization(M); - - // Darwin wants symbols to be quoted if they have complex names. - Mang->setUseQuotes(true); + 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."); + // FIXME: This is a total hack, finish mc'izing the PPC backend. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive])); + // 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(".section __TEXT,__textcoal_nt,coalesced," - "pure_instructions"); + const TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); if (TM.getRelocationModel() == Reloc::PIC_) { - SwitchToTextSection(".section __TEXT,__picsymbolstub1,symbol_stubs," - "pure_instructions,32"); + OutStreamer.SwitchSection( + OutContext.getMachOSection("__TEXT", "__picsymbolstub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 32, SectionKind::getText())); } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { - SwitchToTextSection(".section __TEXT,__symbol_stub1,symbol_stubs," - "pure_instructions,16"); + OutStreamer.SwitchSection( + OutContext.getMachOSection("__TEXT","__symbol_stub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 16, SectionKind::getText())); } - SwitchToTextSection(TAI->getTextSection()); - - // Emit initial debug information. - DW.BeginModule(&M); - return false; + OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); } -bool DarwinAsmPrinter::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.globl " << name << '\n'; - O << "\t.zerofill __DATA, __common, " << name << ", " - << Size << ", " << Align; - } else if (I->hasInternalLinkage()) { - SwitchToDataSection("\t.data", I); - O << TAI->getLCOMMDirective() << name << "," << Size << "," << Align; - } else { - SwitchToDataSection("\t.data", I); - O << ".comm " << name << "," << Size; - } - O << "\t\t; '" << I->getName() << "'\n"; - } else { - switch (I->getLinkage()) { - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: - O << "\t.globl " << name << '\n' - << "\t.weak_definition " << name << '\n'; - SwitchToDataSection(".section __DATA,__datacoal_nt,coalesced", 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.globl " << name << "\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; - } - } - - SwitchToDataSection("\t.data", I); - break; - default: - cerr << "Unknown linkage type!"; - abort(); - } - - EmitAlignment(Align, I); - O << name << ":\t\t\t\t; '" << 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(Mang->getValueName(GV)); - - EmitGlobalConstant(C); - O << '\n'; - } - } +static MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) { + // Remove $stub suffix, add $lazy_ptr. + SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()-5); + TmpStr += "$lazy_ptr"; + return Ctx.GetOrCreateSymbol(TmpStr.str()); +} - if (TAI->getWeakRefDirective()) { - if (ExtWeakSymbols.begin() != ExtWeakSymbols.end()) - SwitchToDataSection(""); - for (std::set::iterator i = ExtWeakSymbols.begin(), - e = ExtWeakSymbols.end(); i != e; ++i) { - O << TAI->getWeakRefDirective() << *i << "\n"; - } - } +static MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) { + // Add $tmp suffix to $stub, yielding $stub$tmp. + SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()); + TmpStr += "$tmp"; + return Ctx.GetOrCreateSymbol(TmpStr.str()); +} - bool isPPC64 = TD->getPointerSizeInBits() == 64; +void PPCDarwinAsmPrinter:: +EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { + bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; + + const TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + // .lazy_symbol_pointer + const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection(); + // 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(".section __TEXT,__picsymbolstub1,symbol_stubs," - "pure_instructions,32"); + const MCSection *StubSection = + OutContext.getMachOSection("__TEXT", "__picsymbolstub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 32, SectionKind::getText()); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + OutStreamer.SwitchSection(StubSection); EmitAlignment(4); - O << "L" << *i << "$stub:\n"; - O << "\t.indirect_symbol " << *i << "\n"; - O << "\tmflr r0\n"; - O << "\tbcl 20,31,L0$" << *i << "\n"; - O << "L0$" << *i << ":\n"; - O << "\tmflr r11\n"; - O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n"; - O << "\tmtlr r0\n"; - if (isPPC64) - O << "\tldu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n"; - else - O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n"; - O << "\tmtctr r12\n"; - O << "\tbctr\n"; - SwitchToDataSection(".lazy_symbol_pointer"); - O << "L" << *i << "$lazy_ptr:\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(".section __TEXT,__symbol_stub1,symbol_stubs," - "pure_instructions,16"); - EmitAlignment(4); - O << "L" << *i << "$stub:\n"; - O << "\t.indirect_symbol " << *i << "\n"; - O << "\tlis r11,ha16(L" << *i << "$lazy_ptr)\n"; + + MCSymbol *Stub = Stubs[i].first; + MCSymbol *RawSym = Stubs[i].second.getPointer(); + MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); + MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); + + OutStreamer.EmitLabel(Stub); + OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + // FIXME: MCize this. + OutStreamer.EmitRawText(StringRef("\tmflr r0")); + OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName())); + OutStreamer.EmitLabel(AnonSymbol); + OutStreamer.EmitRawText(StringRef("\tmflr r11")); + OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+ + "-" + AnonSymbol->getName() + ")"); + OutStreamer.EmitRawText(StringRef("\tmtlr r0")); + if (isPPC64) - O << "\tldu r12,lo16(L" << *i << "$lazy_ptr)(r11)\n"; + OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + + "-" + AnonSymbol->getName() + ")(r11)"); else - O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr)(r11)\n"; - O << "\tmtctr r12\n"; - O << "\tbctr\n"; - SwitchToDataSection(".lazy_symbol_pointer"); - O << "L" << *i << "$lazy_ptr:\n"; - O << "\t.indirect_symbol " << *i << "\n"; + OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + + "-" + AnonSymbol->getName() + ")(r11)"); + OutStreamer.EmitRawText(StringRef("\tmtctr r12")); + OutStreamer.EmitRawText(StringRef("\tbctr")); + + OutStreamer.SwitchSection(LSPSection); + OutStreamer.EmitLabel(LazyPtr); + OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + if (isPPC64) - O << "\t.quad dyld_stub_binding_helper\n"; + OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); else - O << "\t.long dyld_stub_binding_helper\n"; + OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); } + OutStreamer.AddBlankLine(); + return; + } + + const MCSection *StubSection = + OutContext.getMachOSection("__TEXT","__symbol_stub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 16, SectionKind::getText()); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + MCSymbol *Stub = Stubs[i].first; + MCSymbol *RawSym = Stubs[i].second.getPointer(); + MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); + + OutStreamer.SwitchSection(StubSection); + EmitAlignment(4); + OutStreamer.EmitLabel(Stub); + OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")"); + if (isPPC64) + OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + + ")(r11)"); + else + OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + + ")(r11)"); + OutStreamer.EmitRawText(StringRef("\tmtctr r12")); + OutStreamer.EmitRawText(StringRef("\tbctr")); + OutStreamer.SwitchSection(LSPSection); + OutStreamer.EmitLabel(LazyPtr); + OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + + if (isPPC64) + OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); + else + OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); } + + OutStreamer.AddBlankLine(); +} - O << "\n"; - // Output stubs for external and common global variables. - if (GVStubs.begin() != GVStubs.end()) { - SwitchToDataSection(".non_lazy_symbol_pointer"); - for (std::set::iterator I = GVStubs.begin(), - E = GVStubs.end(); I != E; ++I) { - O << "L" << *I << "$non_lazy_ptr:\n"; - O << "\t.indirect_symbol " << *I << "\n"; - if (isPPC64) - O << "\t.quad\t0\n"; - else - O << "\t.long\t0\n"; - +bool PPCDarwinAsmPrinter::doFinalization(Module &M) { + bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; + + // Darwin/PPC always uses mach-o. + const TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + MachineModuleInfoMachO &MMIMacho = + MMI->getObjFileInfo(); + + MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList(); + if (!Stubs.empty()) + EmitFunctionStubs(Stubs); + + if (MAI->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) { + MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr"); + MachineModuleInfoImpl::StubValueTy &StubSym = + MMIMacho.getGVStubEntry(NLPSym); + StubSym = MachineModuleInfoImpl::StubValueTy(Mang->getSymbol(*I), true); + } } } - // Emit initial debug information. - DW.EndModule(); + // Output stubs for dynamically-linked functions. + Stubs = MMIMacho.GetGVStubList(); + + // Output macho stubs for external and common global variables. + if (!Stubs.empty()) { + // Switch with ".non_lazy_symbol_pointer" directive. + OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); + EmitAlignment(isPPC64 ? 3 : 2); + + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + // L_foo$stub: + OutStreamer.EmitLabel(Stubs[i].first); + // .indirect_symbol _foo + MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; + OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); + + if (MCSym.getInt()) + // External to current translation unit. + OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); + else + // Internal to current translation unit. + // + // When we place the LSDA into the TEXT section, the type info pointers + // need to be indirect and pc-rel. We accomplish this by using NLPs. + // However, sometimes the types are local to the file. So we need to + // fill in the value for the NLP in those cases. + OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), + OutContext), + isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); + } + + Stubs.clear(); + OutStreamer.AddBlankLine(); + } + + Stubs = MMIMacho.GetHiddenGVStubList(); + if (!Stubs.empty()) { + OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); + EmitAlignment(isPPC64 ? 3 : 2); + + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + // L_foo$stub: + OutStreamer.EmitLabel(Stubs[i].first); + // .long _foo + OutStreamer.EmitValue(MCSymbolRefExpr:: + Create(Stubs[i].second.getPointer(), + OutContext), + isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); + } + + Stubs.clear(); + OutStreamer.AddBlankLine(); + } // 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"; + OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); - AsmPrinter::doFinalization(M); - return false; // success + return AsmPrinter::doFinalization(M); } - - -/// createDarwinCodePrinterPass - Returns a pass that prints the PPC assembly -/// code for a MachineFunction to the given output stream, in a format that the +/// 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) { - return new DarwinAsmPrinter(o, tm, tm.getTargetAsmInfo()); +static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, + MCStreamer &Streamer) { + const PPCSubtarget *Subtarget = &tm.getSubtarget(); + + if (Subtarget->isDarwin()) + return new PPCDarwinAsmPrinter(tm, Streamer); + return new PPCLinuxAsmPrinter(tm, Streamer); } +// Force static initialization. +extern "C" void LLVMInitializePowerPCAsmPrinter() { + TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass); + TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass); +}