X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FPowerPC%2FPPCAsmPrinter.cpp;h=717b831086d39ef2a8899adfb5de45c3a98ebfb2;hb=88276b887c426cf5d998b705a14663bfa38f8efd;hp=03fc210984295a3aaae7c1ac5ff2ca9743361ddc;hpb=c3306120cc66b1c5bc73bd0e95e1f613e27b12dc;p=oota-llvm.git diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 03fc2109842..717b831086d 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1,10 +1,10 @@ -//===-- PPC32AsmPrinter.cpp - Print machine instrs to PowerPC assembly ----===// -// +//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly --------=// +// // 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 contains a printer that converts from our internal representation @@ -17,51 +17,59 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "asmprinter" -#include "PowerPC.h" -#include "PPC32TargetMachine.h" +#include "PPC.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/MachineConstantPool.h" +#include "llvm/CodeGen/MachineDebugInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/Mangler.h" -#include "Support/CommandLine.h" -#include "Support/Debug.h" -#include "Support/Statistic.h" -#include "Support/StringExtras.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/MRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include using namespace llvm; namespace { Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); - struct PPC32AsmPrinter : public AsmPrinter { - std::set FnStubs, GVStubs, LinkOnceStubs; - std::set Strings; + class PPCAsmPrinter : public AsmPrinter { + public: + std::set FnStubs, GVStubs; + + PPCAsmPrinter(std::ostream &O, TargetMachine &TM) + : AsmPrinter(O, TM) {} - PPC32AsmPrinter(std::ostream &O, TargetMachine &TM) - : AsmPrinter(O, TM), LabelNumber(0) { - CommentString = ";"; - GlobalPrefix = "_"; - ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. - Data64bitsDirective = 0; // we can't emit a 64-bit unit - AlignmentIsInBytes = false; // Alignment is by power of 2. + virtual const char *getPassName() const { + return "PowerPC Assembly Printer"; } - /// Unique incrementer for label values for referencing Global values. - /// - unsigned LabelNumber; - - virtual const char *getPassName() const { - return "PPC32 Assembly Printer"; + PPCTargetMachine &getTM() { + return static_cast(TM); } - PPC32TargetMachine &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 @@ -71,14 +79,13 @@ namespace { bool printInstruction(const MachineInstr *MI); void printMachineInstruction(const MachineInstr *MI); - void printOp(const MachineOperand &MO, bool LoadAddrOp = false); - void printImmOp(const MachineOperand &MO, unsigned ArgType); + void printOp(const MachineOperand &MO); - void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ + void printOperand(const MachineInstr *MI, unsigned OpNo){ const MachineOperand &MO = MI->getOperand(OpNo); if (MO.getType() == MachineOperand::MO_MachineRegister) { assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??"); - O << LowercaseString(TM.getRegisterInfo()->get(MO.getReg()).Name); + O << TM.getRegisterInfo()->get(MO.getReg()).Name; } else if (MO.isImmediate()) { O << MO.getImmedValue(); } else { @@ -86,95 +93,196 @@ namespace { } } - void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo, - MVT::ValueType VT) { + 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(0 <= value && 31 >= value && "Invalid u5imm argument!"); + assert(value <= 63 && "Invalid u6imm argument!"); O << (unsigned int)value; } - void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, - MVT::ValueType VT) { + 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) { + O << (short)MI->getOperand(OpNo).getImmedValue()*4; + } + 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(); + } else { + printOp(MI->getOperand(OpNo)); + } + } + void printCallOperand(const MachineInstr *MI, unsigned OpNo) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (!PPCGenerateStaticCode) { + 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"; + return; + } + } + if (MO.getType() == MachineOperand::MO_ExternalSymbol) { + std::string Name(GlobalPrefix); Name += MO.getSymbolName(); + FnStubs.insert(Name); + O << "L" << Name << "$stub"; + return; + } + } + + printOp(MI->getOperand(OpNo)); + } + void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo) { + O << (int)MI->getOperand(OpNo).getImmedValue()*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 { + O << "ha16("; + printOp(MI->getOperand(OpNo)); + if (PICEnabled) + 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 (PICEnabled) + 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, currently empty + void printMemRegImm(const MachineInstr *MI, unsigned OpNo) { + printSymbolLo(MI, OpNo); + O << '('; + 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); + } + + virtual bool runOnMachineFunction(MachineFunction &F) = 0; + virtual bool doFinalization(Module &M) = 0; + }; + + /// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS + /// X + /// + struct DarwinAsmPrinter : public PPCAsmPrinter { + + DarwinAsmPrinter(std::ostream &O, TargetMachine &TM) + : PPCAsmPrinter(O, TM) { + CommentString = ";"; + GlobalPrefix = "_"; + PrivateGlobalPrefix = "L"; // Marker for constant pool idxs + ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. + Data64bitsDirective = 0; // we can't emit a 64-bit unit + AlignmentIsInBytes = false; // Alignment is by power of 2. + ConstantPoolSection = "\t.const\t"; + LCOMMDirective = "\t.lcomm\t"; + StaticCtorsSection = ".mod_init_func"; + StaticDtorsSection = ".mod_term_func"; + } - void printConstantPool(MachineConstantPool *MCP); - bool runOnMachineFunction(MachineFunction &F); + virtual const char *getPassName() const { + return "Darwin PPC Assembly Printer"; + } + + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); bool doFinalization(Module &M); }; -} // end of anonymous namespace -/// createPPC32AsmPrinterPass - Returns a pass that prints the PPC -/// assembly code for a MachineFunction to the given output stream, -/// using the given target machine description. This should work -/// regardless of whether the function is in SSA form or not. -/// -FunctionPass *llvm::createPPC32AsmPrinter(std::ostream &o, TargetMachine &tm) { - return new PPC32AsmPrinter(o, tm); -} + /// AIXAsmPrinter - PowerPC assembly printer, customized for AIX + /// + struct AIXAsmPrinter : public PPCAsmPrinter { + /// Map for labels corresponding to global variables + /// + std::map GVToLabelMap; -// Include the auto-generated portion of the assembly writer -#include "PowerPCGenAsmWriter.inc" + AIXAsmPrinter(std::ostream &O, TargetMachine &TM) + : PPCAsmPrinter(O, TM) { + CommentString = "#"; + GlobalPrefix = "."; + ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. + Data64bitsDirective = 0; // we can't emit a 64-bit unit + AlignmentIsInBytes = false; // Alignment is by power of 2. + ConstantPoolSection = "\t.const\t"; + } + + virtual const char *getPassName() const { + return "AIX PPC Assembly Printer"; + } + + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); + }; +} // end of anonymous namespace -/// printConstantPool - Print to the current output stream assembly -/// representations of the constants in the constant pool MCP. This is -/// used to print out constants which have been "spilled to memory" by -/// the code generator. +/// createDarwinAsmPrinterPass - 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. /// -void PPC32AsmPrinter::printConstantPool(MachineConstantPool *MCP) { - const std::vector &CP = MCP->getConstants(); - const TargetData &TD = TM.getTargetData(); - - if (CP.empty()) return; - - for (unsigned i = 0, e = CP.size(); i != e; ++i) { - O << "\t.const\n"; - emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType())); - O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString - << *CP[i] << "\n"; - emitGlobalConstant(CP[i]); - } +FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) { + return new DarwinAsmPrinter(o, tm); } -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. +/// createAIXAsmPrinterPass - Returns a pass that prints the PPC assembly code +/// for a MachineFunction to the given output stream, in a format that the +/// AIX 5L assembler can deal with. /// -bool PPC32AsmPrinter::runOnMachineFunction(MachineFunction &MF) { - setupMachineFunction(MF); - O << "\n\n"; - - // Print out constants referenced by the function - printConstantPool(MF.getConstantPool()); - - // Print out labels for the function. - O << "\t.text\n"; - emitAlignment(2); - O << "\t.globl\t" << CurrentFnName << "\n"; - O << CurrentFnName << ":\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. - O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" - << CommentString << " " << I->getBasicBlock()->getName() << "\n"; - for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); - II != E; ++II) { - // Print the assembly for the instruction. - O << "\t"; - printMachineInstruction(II); - } - } - ++LabelNumber; - - // We didn't modify anything. - return false; +FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, TargetMachine &tm) { + return new AIXAsmPrinter(o, tm); } -void PPC32AsmPrinter::printOp(const MachineOperand &MO, - bool LoadAddrOp /* = false */) { +// Include the auto-generated portion of the assembly writer +#include "PPCGenAsmWriter.inc" + +void PPCAsmPrinter::printOp(const MachineOperand &MO) { const MRegisterInfo &RI = *TM.getRegisterInfo(); int new_symbol; - + switch (MO.getType()) { case MachineOperand::MO_VirtualRegister: if (Value *V = MO.getVRegValueOrNull()) { @@ -184,7 +292,7 @@ void PPC32AsmPrinter::printOp(const MachineOperand &MO, // FALLTHROUGH case MachineOperand::MO_MachineRegister: case MachineOperand::MO_CCRegister: - O << LowercaseString(RI.get(MO.getReg()).Name); + O << RI.get(MO.getReg()).Name; return; case MachineOperand::MO_SignExtendedImmed: @@ -197,313 +305,408 @@ void PPC32AsmPrinter::printOp(const MachineOperand &MO, std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs"; abort(); return; - + case MachineOperand::MO_MachineBasicBlock: { MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); - O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) - << "_" << MBBOp->getNumber() << "\t; " - << MBBOp->getBasicBlock()->getName(); + O << PrivateGlobalPrefix << "BB" << getFunctionNumber() << "_" + << MBBOp->getNumber() << "\t; " << MBBOp->getBasicBlock()->getName(); return; } case MachineOperand::MO_ConstantPoolIndex: - O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex(); + O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() + << '_' << MO.getConstantPoolIndex(); return; - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); + // Computing the address of an external symbol, not calling it. + if (!PPCGenerateStaticCode) { + std::string Name(GlobalPrefix); Name += MO.getSymbolName(); + GVStubs.insert(Name); + O << "L" << Name << "$non_lazy_ptr"; + return; + } + O << GlobalPrefix << 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); - // Dynamically-resolved functions need a stub for the function. Be - // wary however not to output $stub for external functions whose addresses - // are taken. Those should be emitted as $non_lazy_ptr below. - Function *F = dyn_cast(GV); - if (F && F->isExternal() && !LoadAddrOp && - getTM().CalledFunctions.count(F)) { - FnStubs.insert(Name); - O << "L" << Name << "$stub"; - return; - } - - // External global variables need a non-lazily-resolved stub - if (GV->isExternal() && getTM().AddressTaken.count(GV)) { - GVStubs.insert(Name); - O << "L" << Name << "$non_lazy_ptr"; - return; - } - - if (F && LoadAddrOp && getTM().AddressTaken.count(GV)) { - LinkOnceStubs.insert(Name); - O << "L" << Name << "$non_lazy_ptr"; - return; + // External or weakly linked global variables need non-lazily-resolved stubs + if (!PPCGenerateStaticCode) { + if (((GV->isExternal() || GV->hasWeakLinkage() || + GV->hasLinkOnceLinkage()))) { + GVStubs.insert(Name); + O << "L" << Name << "$non_lazy_ptr"; + return; + } } - - O << Mang->getValueName(GV); + + O << Name; return; } - + default: O << ""; return; } } -void PPC32AsmPrinter::printImmOp(const MachineOperand &MO, unsigned ArgType) { - int Imm = MO.getImmedValue(); - if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) { - O << (short)Imm; - } else { - O << Imm; - } -} - /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to /// the current output stream. /// -void PPC32AsmPrinter::printMachineInstruction(const MachineInstr *MI) { +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; + } + } + if (printInstruction(MI)) return; // Printer was automatically generated - - unsigned Opcode = MI->getOpcode(); - const TargetInstrInfo &TII = *TM.getInstrInfo(); - const TargetInstrDescriptor &Desc = TII.get(Opcode); - unsigned i; - - unsigned ArgCount = MI->getNumOperands(); - unsigned ArgType[] = { - (Desc.TSFlags >> PPCII::Arg0TypeShift) & PPCII::ArgTypeMask, - (Desc.TSFlags >> PPCII::Arg1TypeShift) & PPCII::ArgTypeMask, - (Desc.TSFlags >> PPCII::Arg2TypeShift) & PPCII::ArgTypeMask, - (Desc.TSFlags >> PPCII::Arg3TypeShift) & PPCII::ArgTypeMask, - (Desc.TSFlags >> PPCII::Arg4TypeShift) & PPCII::ArgTypeMask - }; - assert(((Desc.TSFlags & PPCII::VMX) == 0) && - "Instruction requires VMX support"); - assert(((Desc.TSFlags & PPCII::PPC64) == 0) && - "Instruction requires 64 bit support"); - - // CALLpcrel and CALLindirect are handled specially here to print only the - // appropriate number of args that the assembler expects. This is because - // may have many arguments appended to record the uses of registers that are - // holding arguments to the called function. - if (Opcode == PPC::COND_BRANCH) { - std::cerr << "Error: untranslated conditional branch psuedo instruction!\n"; - abort(); - } else if (Opcode == PPC::IMPLICIT_DEF) { - --EmittedInsts; // Not an actual machine instruction - O << "; IMPLICIT DEF "; - printOp(MI->getOperand(0)); - O << "\n"; - return; - } else if (Opcode == PPC::CALLpcrel) { - O << TII.getName(Opcode) << " "; - printOp(MI->getOperand(0)); - O << "\n"; - return; - } else if (Opcode == PPC::CALLindirect) { - O << TII.getName(Opcode) << " "; - printImmOp(MI->getOperand(0), ArgType[0]); - O << ", "; - printImmOp(MI->getOperand(1), ArgType[0]); - O << "\n"; - return; - } else if (Opcode == PPC::MovePCtoLR) { - ++EmittedInsts; // Actually two machine instructions - // FIXME: should probably be converted to cout.width and cout.fill - O << "bl \"L0000" << LabelNumber << "$pb\"\n"; - O << "\"L0000" << LabelNumber << "$pb\":\n"; - O << "\tmflr "; - printOp(MI->getOperand(0)); - O << "\n"; - return; + + assert(0 && "Unhandled instruction in asm writer!"); + abort(); + return; +} + + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + SetupMachineFunction(MF); + O << "\n\n"; + + // Print out dwarf file info + MachineDebugInfo &DebugInfo = MF.getDebugInfo(); + std::vector Sources = DebugInfo.getSourceFiles(); + for (unsigned i = 0, N = Sources.size(); i < N; i++) { + O << "\t; .file\t" << (i + 1) << "," << "\"" << Sources[i] << "\"" << "\n"; } - O << TII.getName(Opcode) << " "; - if (Opcode == PPC::LOADHiAddr) { - printOp(MI->getOperand(0)); - O << ", "; - if (MI->getOperand(1).getReg() == PPC::R0) - O << "0"; - else - printOp(MI->getOperand(1)); - O << ", ha16(" ; - printOp(MI->getOperand(2), true /* LoadAddrOp */); - O << "-\"L0000" << LabelNumber << "$pb\")\n"; - } else if (ArgCount == 3 && (MI->getOperand(2).isConstantPoolIndex() - || MI->getOperand(2).isGlobalAddress())) { - printOp(MI->getOperand(0)); - O << ", lo16("; - printOp(MI->getOperand(2), true /* LoadAddrOp */); - O << "-\"L0000" << LabelNumber << "$pb\")"; - O << "("; - if (MI->getOperand(1).getReg() == PPC::R0) - O << "0"; - else - printOp(MI->getOperand(1)); - O << ")\n"; - } else if (ArgCount == 3 && ArgType[1] == PPCII::Disimm16) { - printOp(MI->getOperand(0)); - O << ", "; - printImmOp(MI->getOperand(1), ArgType[1]); - O << "("; - if (MI->getOperand(2).hasAllocatedReg() && - MI->getOperand(2).getReg() == PPC::R0) - O << "0"; - else - printOp(MI->getOperand(2)); - O << ")\n"; - } else { - for (i = 0; i < ArgCount; ++i) { - // addi and friends - if (i == 1 && ArgCount == 3 && ArgType[2] == PPCII::Simm16 && - MI->getOperand(1).hasAllocatedReg() && - MI->getOperand(1).getReg() == PPC::R0) { - O << "0"; - // for long branch support, bc $+8 - } else if (i == 1 && ArgCount == 2 && MI->getOperand(1).isImmediate() && - TII.isBranch(MI->getOpcode())) { - O << "$+8"; - assert(8 == MI->getOperand(i).getImmedValue() - && "branch off PC not to pc+8?"); - //printOp(MI->getOperand(i)); - } else if (MI->getOperand(i).isImmediate()) { - printImmOp(MI->getOperand(i), ArgType[i]); - } else { - printOp(MI->getOperand(i)); - } - if (ArgCount - 1 == i) - O << "\n"; - else - O << ", "; + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + // Print out labels for the function. + const Function *F = MF.getFunction(); + switch (F->getLinkage()) { + default: assert(0 && "Unknown linkage type!"); + case Function::InternalLinkage: // Symbols default to internal. + SwitchSection(".text", F); + EmitAlignment(4, F); + break; + case Function::ExternalLinkage: + SwitchSection(".text", F); + EmitAlignment(4, F); + O << "\t.globl\t" << CurrentFnName << "\n"; + break; + case Function::WeakLinkage: + case Function::LinkOnceLinkage: + SwitchSection(".section __TEXT,__textcoal_nt,coalesced,pure_instructions", + F); + O << "\t.globl\t" << CurrentFnName << "\n"; + O << "\t.weak_definition\t" << CurrentFnName << "\n"; + break; + } + O << CurrentFnName << ":\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()) { + O << PrivateGlobalPrefix << "BB" << getFunctionNumber() << '_' + << I->getNumber() << ":\t"; + if (!I->getBasicBlock()->getName().empty()) + O << CommentString << " " << I->getBasicBlock()->getName(); + 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); } } - return; + + // We didn't modify anything. + return false; } -// SwitchSection - Switch to the specified section of the executable if we are -// not already in it! -// -static void SwitchSection(std::ostream &OS, std::string &CurSection, - const char *NewSection) { - if (CurSection != NewSection) { - CurSection = NewSection; - if (!CurSection.empty()) - OS << "\t" << NewSection << "\n"; - } + +bool DarwinAsmPrinter::doInitialization(Module &M) { + if (TM.getSubtarget().isGigaProcessor()) + O << "\t.machine ppc970\n"; + AsmPrinter::doInitialization(M); + + // Darwin wants symbols to be quoted if they have complex names. + Mang->setUseQuotes(true); + return false; } -bool PPC32AsmPrinter::doFinalization(Module &M) { +bool DarwinAsmPrinter::doFinalization(Module &M) { const TargetData &TD = TM.getTargetData(); - std::string CurSection; // Print out module-level global variables here. - for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) - if (I->hasInitializer()) { // External global require no code - O << "\n\n"; - std::string name = Mang->getValueName(I); - Constant *C = I->getInitializer(); - unsigned Size = TD.getTypeSize(C->getType()); - unsigned Align = TD.getTypeAlignmentShift(C->getType()); - - if (C->isNullValue() && /* FIXME: Verify correct */ - (I->hasInternalLinkage() || I->hasWeakLinkage())) { - SwitchSection(O, CurSection, ".data"); - if (I->hasInternalLinkage()) - O << ".lcomm " << name << "," << TD.getTypeSize(C->getType()) - << "," << Align; - else - O << ".comm " << name << "," << TD.getTypeSize(C->getType()); - O << "\t\t; "; - WriteAsOperand(O, I, true, true, &M); - O << "\n"; - } else { - switch (I->getLinkage()) { - case GlobalValue::LinkOnceLinkage: - O << ".section __TEXT,__textcoal_nt,coalesced,no_toc\n" - << ".weak_definition " << name << '\n' - << ".private_extern " << name << '\n' - << ".section __DATA,__datacoal_nt,coalesced,no_toc\n"; - LinkOnceStubs.insert(name); - break; - case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. - // Nonnull linkonce -> weak - O << "\t.weak " << name << "\n"; - SwitchSection(O, CurSection, ""); - O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\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: - SwitchSection(O, CurSection, ".data"); - break; - } - - emitAlignment(Align); - O << name << ":\t\t\t\t; "; - WriteAsOperand(O, I, true, true, &M); - O << " = "; - WriteAsOperand(O, C, false, false, &M); - O << "\n"; - emitGlobalConstant(C); + 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 (I->hasAppendingLinkage() && EmitSpecialLLVMGlobal(I)) + continue; + + O << '\n'; + std::string name = Mang->getValueName(I); + Constant *C = I->getInitializer(); + unsigned Size = TD.getTypeSize(C->getType()); + unsigned Align = TD.getTypeAlignmentShift(C->getType()); + + if (C->isNullValue() && /* FIXME: Verify correct */ + (I->hasInternalLinkage() || I->hasWeakLinkage() || + I->hasLinkOnceLinkage())) { + SwitchSection(".data", I); + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + if (I->hasInternalLinkage()) + O << LCOMMDirective << name << "," << Size << "," << Align; + else + O << ".comm " << name << "," << Size; + O << "\t\t; '" << I->getName() << "'\n"; + } else { + switch (I->getLinkage()) { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + O << ".globl " << name << '\n' + << ".weak_definition " << name << '\n' + << ".private_extern " << name << '\n'; + SwitchSection(".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: + SwitchSection(".data", I); + break; + default: + std::cerr << "Unknown linkage type!"; + abort(); } + + EmitAlignment(Align, I); + O << name << ":\t\t\t\t; '" << I->getName() << "'\n"; + EmitGlobalConstant(C); } + } // Output stubs for dynamically-linked functions - for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); - i != e; ++i) - { - O << ".data\n"; - O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"; - emitAlignment(2); - 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"; - O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n"; - O << "\tmtctr r12\n"; - O << "\tbctr\n"; - O << ".data\n"; - O << ".lazy_symbol_pointer\n"; - O << "L" << *i << "$lazy_ptr:\n"; - O << "\t.indirect_symbol " << *i << "\n"; - O << "\t.long dyld_stub_binding_helper\n"; + if (PICEnabled) { + for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); + i != e; ++i) { + SwitchSection(".section __TEXT,__picsymbolstub1,symbol_stubs," + "pure_instructions,32", 0); + EmitAlignment(2); + 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"; + O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n"; + O << "\tmtctr r12\n"; + O << "\tbctr\n"; + SwitchSection(".lazy_symbol_pointer", 0); + O << "L" << *i << "$lazy_ptr:\n"; + O << "\t.indirect_symbol " << *i << "\n"; + O << "\t.long dyld_stub_binding_helper\n"; + } + } else { + for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); + i != e; ++i) { + SwitchSection(".section __TEXT,__symbol_stub1,symbol_stubs," + "pure_instructions,16", 0); + EmitAlignment(4); + O << "L" << *i << "$stub:\n"; + O << "\t.indirect_symbol " << *i << "\n"; + O << "\tlis r11,ha16(L" << *i << "$lazy_ptr)\n"; + O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr)(r11)\n"; + O << "\tmtctr r12\n"; + O << "\tbctr\n"; + SwitchSection(".lazy_symbol_pointer", 0); + O << "L" << *i << "$lazy_ptr:\n"; + O << "\t.indirect_symbol " << *i << "\n"; + O << "\t.long dyld_stub_binding_helper\n"; + } } O << "\n"; - // Output stubs for external global variables - if (GVStubs.begin() != GVStubs.end()) - O << ".data\n.non_lazy_symbol_pointer\n"; - 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"; - O << "\t.long\t0\n"; + // Output stubs for external and common global variables. + if (GVStubs.begin() != GVStubs.end()) { + SwitchSection(".non_lazy_symbol_pointer", 0); + 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"; + O << "\t.long\t0\n"; + } } - - // Output stubs for link-once variables - if (LinkOnceStubs.begin() != LinkOnceStubs.end()) - O << ".data\n.align 2\n"; - for (std::set::iterator i = LinkOnceStubs.begin(), - e = LinkOnceStubs.end(); i != e; ++i) { - O << "L" << *i << "$non_lazy_ptr:\n" - << "\t.long\t" << *i << '\n'; + + // 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"; + + AsmPrinter::doFinalization(M); + return false; // success +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool AIXAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + SetupMachineFunction(MF); + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + // Print out header for the function. + O << "\t.csect .text[PR]\n" + << "\t.align 2\n" + << "\t.globl " << CurrentFnName << '\n' + << "\t.globl ." << CurrentFnName << '\n' + << "\t.csect " << CurrentFnName << "[DS],3\n" + << CurrentFnName << ":\n" + << "\t.llong ." << CurrentFnName << ", TOC[tc0], 0\n" + << "\t.csect .text[PR]\n" + << '.' << CurrentFnName << ":\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. + O << PrivateGlobalPrefix << "BB" << getFunctionNumber() << '_' + << I->getNumber() + << ":\t" << CommentString << I->getBasicBlock()->getName() << '\n'; + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << "\t"; + printMachineInstruction(II); + } } - + + O << "LT.." << CurrentFnName << ":\n" + << "\t.long 0\n" + << "\t.byte 0,0,32,65,128,0,0,0\n" + << "\t.long LT.." << CurrentFnName << "-." << CurrentFnName << '\n' + << "\t.short 3\n" + << "\t.byte \"" << CurrentFnName << "\"\n" + << "\t.align 2\n"; + + // We didn't modify anything. + return false; +} + +bool AIXAsmPrinter::doInitialization(Module &M) { + SwitchSection("", 0); + const TargetData &TD = TM.getTargetData(); + + O << "\t.machine \"ppc64\"\n" + << "\t.toc\n" + << "\t.csect .text[PR]\n"; + + // Print out module-level global variables + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->hasInitializer()) + continue; + + std::string Name = I->getName(); + Constant *C = I->getInitializer(); + // N.B.: We are defaulting to writable strings + if (I->hasExternalLinkage()) { + O << "\t.globl " << Name << '\n' + << "\t.csect .data[RW],3\n"; + } else { + O << "\t.csect _global.rw_c[RW],3\n"; + } + O << Name << ":\n"; + EmitGlobalConstant(C); + } + + // Output labels for globals + if (M.global_begin() != M.global_end()) O << "\t.toc\n"; + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + const GlobalVariable *GV = I; + // Do not output labels for unused variables + if (GV->isExternal() && GV->use_begin() == GV->use_end()) + continue; + + IncrementFunctionNumber(); + std::string Name = GV->getName(); + std::string Label = "LC.." + utostr(getFunctionNumber()); + GVToLabelMap[GV] = Label; + O << Label << ":\n" + << "\t.tc " << Name << "[TC]," << Name; + if (GV->isExternal()) O << "[RW]"; + O << '\n'; + } + + AsmPrinter::doInitialization(M); + return false; // success +} + +bool AIXAsmPrinter::doFinalization(Module &M) { + const TargetData &TD = TM.getTargetData(); + // Print out module-level global variables + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (I->hasInitializer() || I->hasExternalLinkage()) + continue; + + std::string Name = I->getName(); + if (I->hasInternalLinkage()) { + O << "\t.lcomm " << Name << ",16,_global.bss_c"; + } else { + O << "\t.comm " << Name << "," << TD.getTypeSize(I->getType()) + << "," << Log2_32((unsigned)TD.getTypeAlignment(I->getType())); + } + O << "\t\t" << CommentString << " "; + WriteAsOperand(O, I, false, true, &M); + O << "\n"; + } + + O << "_section_.text:\n" + << "\t.csect .data[RW],3\n" + << "\t.llong _section_.text\n"; AsmPrinter::doFinalization(M); return false; // success }