SparcAsmPrinter.cpp revision 3ed469ccd7b028a030b550d84b7336d146f5d8fa
10ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===// 29fe80482a1adfd555ec60b563cd9b6641528d2e2Behdad Esfahbod// 30ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// The LLVM Compiler Infrastructure 40ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// 50ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// This file was developed by the LLVM research group and is distributed under 60ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// the University of Illinois Open Source License. See LICENSE.TXT for details. 70ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// 80ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien//===----------------------------------------------------------------------===// 90ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// 100ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// This file contains a printer that converts from our internal representation 110ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// of machine-dependent LLVM code to GAS-format SPARC assembly language. 120ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien// 130ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien//===----------------------------------------------------------------------===// 140ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 150ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "Sparc.h" 160ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "SparcInstrInfo.h" 170ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Constants.h" 180ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/DerivedTypes.h" 190ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Module.h" 200ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Assembly/Writer.h" 210ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/CodeGen/AsmPrinter.h" 220ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/CodeGen/MachineFunctionPass.h" 230ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/CodeGen/MachineConstantPool.h" 240ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/CodeGen/MachineInstr.h" 250ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Target/TargetAsmInfo.h" 260ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Target/TargetData.h" 270ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Target/TargetMachine.h" 280ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Support/Mangler.h" 290ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/ADT/Statistic.h" 300ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/ADT/StringExtras.h" 310ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Support/CommandLine.h" 320ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "llvm/Support/MathExtras.h" 330ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include <cctype> 340ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include <iostream> 350ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levienusing namespace llvm; 360ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 370ae9e064ddee691abed9dd70f57475e2e926e86bRaph Leviennamespace { 380ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); 390ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 400ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien struct VISIBILITY_HIDDEN SparcAsmPrinter : public AsmPrinter { 410ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien SparcAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) 420ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien : AsmPrinter(O, TM, T) { 430ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 440ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 450ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien /// We name each basic block in a Function with a unique number, so 460ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien /// that we can consistently refer to them later. This is cleared 470ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien /// at the beginning of each call to runOnMachineFunction(). 480ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien /// 490ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien typedef std::map<const Value *, unsigned> ValueMapTy; 500ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien ValueMapTy NumberForBB; 510ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 520ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien virtual const char *getPassName() const { 530ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return "Sparc Assembly Printer"; 540ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 550ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 560ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien void printOperand(const MachineInstr *MI, int opNum); 570ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien void printMemOperand(const MachineInstr *MI, int opNum, 580ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien const char *Modifier = 0); 590ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien void printCCOperand(const MachineInstr *MI, int opNum); 600ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 610ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien bool printInstruction(const MachineInstr *MI); // autogenerated. 620ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien bool runOnMachineFunction(MachineFunction &F); 630ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien bool doInitialization(Module &M); 640ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien bool doFinalization(Module &M); 650ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien }; 660ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien} // end of anonymous namespace 670ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 680ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien#include "SparcGenAsmWriter.inc" 690ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 700ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien/// createSparcCodePrinterPass - Returns a pass that prints the SPARC 710ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien/// assembly code for a MachineFunction to the given output stream, 720ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien/// using the given target machine description. This should work 730ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien/// regardless of whether the function is in SSA form. 740ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien/// 750ae9e064ddee691abed9dd70f57475e2e926e86bRaph LevienFunctionPass *llvm::createSparcCodePrinterPass(std::ostream &o, 760ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien TargetMachine &tm) { 770ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return new SparcAsmPrinter(o, tm, tm.getTargetAsmInfo()); 780ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien} 790ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 800ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien/// runOnMachineFunction - This uses the printMachineInstruction() 810ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien/// method to print assembly for each instruction. 820ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien/// 830ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levienbool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 840ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien SetupMachineFunction(MF); 850ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 860ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Print out constants referenced by the function 870ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien EmitConstantPool(MF.getConstantPool()); 880ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 890ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // BBNumber is used here so that a given Printer will never give two 900ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // BBs the same name. (If you have a better way, please let me know!) 910ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien static unsigned BBNumber = 0; 920ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 930ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\n\n"; 940ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // What's my mangled name? 950ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien CurrentFnName = Mang->getValueName(MF.getFunction()); 960ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 970ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Print out the label for the function. 980ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien const Function *F = MF.getFunction(); 990ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien SwitchToTextSection(getSectionForFunction(*F).c_str(), F); 1000ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien EmitAlignment(4, F); 1010ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.globl\t" << CurrentFnName << "\n"; 1020ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.type\t" << CurrentFnName << ", #function\n"; 1030ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << CurrentFnName << ":\n"; 1040ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1050ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Number each basic block so that we can consistently refer to them 1060ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // in PC-relative references. 1070ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // FIXME: Why not use the MBB numbers? 1080ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien NumberForBB.clear(); 1090ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 1100ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien I != E; ++I) { 1110ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien NumberForBB[I->getBasicBlock()] = BBNumber++; 1120ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 1130ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1140ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Print out code for the function. 1150ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 1160ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien I != E; ++I) { 1170ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Print a label for the basic block. 1180ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (I != MF.begin()) { 1190ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien printBasicBlockLabel(I, true); 1200ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << '\n'; 1210ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 1220ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 1230ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien II != E; ++II) { 1240ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Print the assembly for the instruction. 1250ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t"; 1260ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien printInstruction(II); 1270ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien ++EmittedInsts; 1280ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 1290ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 1300ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1310ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // We didn't modify anything. 1320ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return false; 1330ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien} 1340ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1350ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levienvoid SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { 1360ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien const MachineOperand &MO = MI->getOperand (opNum); 1370ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien const MRegisterInfo &RI = *TM.getRegisterInfo(); 1380ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien bool CloseParen = false; 1390ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (MI->getOpcode() == SP::SETHIi && !MO.isRegister() && !MO.isImmediate()) { 1400ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "%hi("; 1410ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien CloseParen = true; 1420ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) 1430ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien && !MO.isRegister() && !MO.isImmediate()) { 1440ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "%lo("; 1450ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien CloseParen = true; 1460ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 1470ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien switch (MO.getType()) { 1480ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case MachineOperand::MO_Register: 1490ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (MRegisterInfo::isPhysicalRegister(MO.getReg())) 1500ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "%" << LowercaseString (RI.get(MO.getReg()).Name); 1510ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien else 1520ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "%reg" << MO.getReg(); 1530ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien break; 1540ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1550ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case MachineOperand::MO_Immediate: 1560ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << (int)MO.getImmedValue(); 1570ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien break; 1580ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case MachineOperand::MO_MachineBasicBlock: 1590ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien printBasicBlockLabel(MO.getMachineBasicBlock()); 1600ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return; 1610ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case MachineOperand::MO_GlobalAddress: 1620ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << Mang->getValueName(MO.getGlobal()); 1630ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien break; 1640ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case MachineOperand::MO_ExternalSymbol: 1650ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << MO.getSymbolName(); 1660ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien break; 1670ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case MachineOperand::MO_ConstantPoolIndex: 1680ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" 1690ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien << MO.getConstantPoolIndex(); 1700ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien break; 1710ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien default: 1720ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "<unknown operand type>"; abort (); break; 1730ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 1740ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (CloseParen) O << ")"; 1750ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien} 1760ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1770ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levienvoid SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, 1780ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien const char *Modifier) { 1790ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien printOperand(MI, opNum); 1800ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1810ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // If this is an ADD operand, emit it like normal operands. 1820ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (Modifier && !strcmp(Modifier, "arith")) { 1830ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << ", "; 1840ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien printOperand(MI, opNum+1); 1850ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return; 1860ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 1870ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1880ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (MI->getOperand(opNum+1).isRegister() && 1890ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien MI->getOperand(opNum+1).getReg() == SP::G0) 1900ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return; // don't print "+%g0" 1910ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (MI->getOperand(opNum+1).isImmediate() && 1920ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien MI->getOperand(opNum+1).getImmedValue() == 0) 1930ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return; // don't print "+0" 1940ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 1950ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "+"; 1960ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (MI->getOperand(opNum+1).isGlobalAddress() || 1970ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien MI->getOperand(opNum+1).isConstantPoolIndex()) { 1980ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "%lo("; 1990ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien printOperand(MI, opNum+1); 2000ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << ")"; 2010ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } else { 2020ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien printOperand(MI, opNum+1); 2030ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 2040ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien} 2050ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2060ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levienvoid SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { 2070ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien int CC = (int)MI->getOperand(opNum).getImmedValue(); 2080ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << SPARCCondCodeToString((SPCC::CondCodes)CC); 2090ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien} 2100ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2110ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2120ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2130ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levienbool SparcAsmPrinter::doInitialization(Module &M) { 2140ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien Mang = new Mangler(M); 2150ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return false; // success 2160ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien} 2170ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2180ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levienbool SparcAsmPrinter::doFinalization(Module &M) { 2190ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien const TargetData *TD = TM.getTargetData(); 2200ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2210ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Print out module-level global variables here. 2220ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); 2230ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien I != E; ++I) 2240ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (I->hasInitializer()) { // External global require no code 2250ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Check to see if this is a special global used by LLVM, if so, emit it. 2260ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (EmitSpecialLLVMGlobal(I)) 2270ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien continue; 2280ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2290ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\n\n"; 2300ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien std::string name = Mang->getValueName(I); 2310ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien Constant *C = I->getInitializer(); 2320ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien unsigned Size = TD->getTypeSize(C->getType()); 2330ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien unsigned Align = TD->getTypeAlignment(C->getType()); 2340ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2350ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (C->isNullValue() && 2360ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || 2370ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien I->hasWeakLinkage() /* FIXME: Verify correct */)) { 2380ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien SwitchToDataSection(".data", I); 2390ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (I->hasInternalLinkage()) 2400ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.local " << name << "\n"; 2410ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2420ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.comm " << name << "," << TD->getTypeSize(C->getType()) 2430ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien << "," << (unsigned)TD->getTypeAlignment(C->getType()); 2440ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t\t! "; 2450ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien WriteAsOperand(O, I, true, true, &M); 2460ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\n"; 2470ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } else { 2480ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien switch (I->getLinkage()) { 2490ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case GlobalValue::LinkOnceLinkage: 2500ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. 2510ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // Nonnull linkonce -> weak 2520ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.weak " << name << "\n"; 2530ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien SwitchToDataSection("", I); 2540ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.section\t\".llvm.linkonce.d." << name 2550ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien << "\",\"aw\",@progbits\n"; 2560ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien break; 2570ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2580ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case GlobalValue::AppendingLinkage: 2590ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // FIXME: appending linkage variables should go into a section of 2600ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // their name or something. For now, just emit them as external. 2610ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case GlobalValue::ExternalLinkage: 2620ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // If external or appending, declare as a global symbol 2630ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.globl " << name << "\n"; 2640ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien // FALL THROUGH 2650ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case GlobalValue::InternalLinkage: 2660ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien if (C->isNullValue()) 2670ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien SwitchToDataSection(".bss", I); 2680ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien else 2690ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien SwitchToDataSection(".data", I); 2700ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien break; 2710ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case GlobalValue::GhostLinkage: 2720ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien std::cerr << "Should not have any unmaterialized functions!\n"; 2730ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien abort(); 2740ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case GlobalValue::DLLImportLinkage: 2750ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien std::cerr << "DLLImport linkage is not supported by this target!\n"; 2760ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien abort(); 2770ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien case GlobalValue::DLLExportLinkage: 2780ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien std::cerr << "DLLExport linkage is not supported by this target!\n"; 2790ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien abort(); 2800ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien default: 2810ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien assert(0 && "Unknown linkage type!"); 2820ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 2830ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2840ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.align " << Align << "\n"; 2850ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.type " << name << ",#object\n"; 2860ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\t.size " << name << "," << Size << "\n"; 2870ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << name << ":\t\t\t\t! "; 2880ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien WriteAsOperand(O, I, true, true, &M); 2890ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien O << "\n"; 2900ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien EmitGlobalConstant(C); 2910ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 2920ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien } 2930ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien 2940ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien AsmPrinter::doFinalization(M); 2950ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien return false; // success 2960ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien} 2970ae9e064ddee691abed9dd70f57475e2e926e86bRaph Levien