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