MSP430AsmPrinter.cpp revision 1deea5f3a7191eeeb076d81cc9647d0e661650df
1//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file contains a printer that converts from our internal representation 11// of machine-dependent LLVM code to the MSP430 assembly language. 12// 13//===----------------------------------------------------------------------===// 14 15#define DEBUG_TYPE "asm-printer" 16#include "MSP430.h" 17#include "MSP430InstrInfo.h" 18#include "MSP430TargetMachine.h" 19#include "llvm/Constants.h" 20#include "llvm/DerivedTypes.h" 21#include "llvm/Module.h" 22#include "llvm/CodeGen/AsmPrinter.h" 23#include "llvm/CodeGen/DwarfWriter.h" 24#include "llvm/CodeGen/MachineModuleInfo.h" 25#include "llvm/CodeGen/MachineFunctionPass.h" 26#include "llvm/CodeGen/MachineConstantPool.h" 27#include "llvm/CodeGen/MachineInstr.h" 28#include "llvm/Target/TargetAsmInfo.h" 29#include "llvm/Target/TargetData.h" 30#include "llvm/ADT/Statistic.h" 31#include "llvm/Support/Compiler.h" 32#include "llvm/Support/Mangler.h" 33#include "llvm/Support/raw_ostream.h" 34 35using namespace llvm; 36 37STATISTIC(EmittedInsts, "Number of machine instrs printed"); 38 39namespace { 40 class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter { 41 public: 42 MSP430AsmPrinter(raw_ostream &O, MSP430TargetMachine &TM, 43 const TargetAsmInfo *TAI, bool Fast, bool Verbose) 44 : AsmPrinter(O, TM, TAI, Fast, Verbose) {} 45 46 virtual const char *getPassName() const { 47 return "MSP430 Assembly Printer"; 48 } 49 50 void printOperand(const MachineInstr *MI, int OpNum, 51 const char* Modifier = 0); 52 void printSrcMemOperand(const MachineInstr *MI, int OpNum, 53 const char* Modifier = 0); 54 bool printInstruction(const MachineInstr *MI); // autogenerated. 55 void printMachineInstruction(const MachineInstr * MI); 56 bool runOnMachineFunction(MachineFunction &F); 57 bool doInitialization(Module &M); 58 bool doFinalization(Module &M); 59 60 void getAnalysisUsage(AnalysisUsage &AU) const { 61 AsmPrinter::getAnalysisUsage(AU); 62 AU.setPreservesAll(); 63 } 64 }; 65} // end of anonymous namespace 66 67#include "MSP430GenAsmWriter.inc" 68 69/// createMSP430CodePrinterPass - Returns a pass that prints the MSP430 70/// assembly code for a MachineFunction to the given output stream, 71/// using the given target machine description. This should work 72/// regardless of whether the function is in SSA form. 73/// 74FunctionPass *llvm::createMSP430CodePrinterPass(raw_ostream &o, 75 MSP430TargetMachine &tm, 76 bool fast, bool verbose) { 77 return new MSP430AsmPrinter(o, tm, tm.getTargetAsmInfo(), fast, verbose); 78} 79 80bool MSP430AsmPrinter::doInitialization(Module &M) { 81 Mang = new Mangler(M, "", TAI->getPrivateGlobalPrefix()); 82 return false; // success 83} 84 85 86bool MSP430AsmPrinter::doFinalization(Module &M) { 87 return AsmPrinter::doFinalization(M); 88} 89 90bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 91 // Print out code for the function. 92 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 93 I != E; ++I) { 94 // Print a label for the basic block. 95 if (I != MF.begin()) { 96 printBasicBlockLabel(I, true , true); 97 O << '\n'; 98 } 99 100 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 101 II != E; ++II) { 102 // Print the assembly for the instruction. 103 O << "\t"; 104 printMachineInstruction(II); 105 } 106 107 // Each Basic Block is separated by a newline 108 O << '\n'; 109 } 110 111 // We didn't modify anything 112 return false; 113} 114 115void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) { 116 ++EmittedInsts; 117 118 // Call the autogenerated instruction printer routines. 119 if (printInstruction(MI)) 120 return; 121 122 assert(0 && "Should not happen"); 123} 124 125void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 126 const char* Modifier) { 127 const MachineOperand &MO = MI->getOperand(OpNum); 128 switch (MO.getType()) { 129 case MachineOperand::MO_Register: 130 assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && 131 "Virtual registers should be already mapped!"); 132 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; 133 return; 134 case MachineOperand::MO_Immediate: 135 if (!Modifier || strcmp(Modifier, "nohash")) 136 O << '#'; 137 O << MO.getImm(); 138 return; 139 case MachineOperand::MO_MachineBasicBlock: 140 printBasicBlockLabel(MO.getMBB()); 141 return; 142 case MachineOperand::MO_GlobalAddress: { 143 bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 144 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 145 std::string Name = Mang->getValueName(MO.getGlobal()); 146 assert(MO.getOffset() == 0 && "No offsets allowed!"); 147 148 if (isCallOp) 149 O << '#'; 150 else if (isMemOp) 151 O << '&'; 152 153 O << Name; 154 155 return; 156 } 157 default: 158 assert(0 && "Not implemented yet!"); 159 } 160} 161 162void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 163 const char* Modifier) { 164 const MachineOperand &Disp = MI->getOperand(OpNum); 165 const MachineOperand &Base = MI->getOperand(OpNum+1); 166 167 if (Disp.isGlobal()) 168 printOperand(MI, OpNum, "mem"); 169 else if (Disp.isImm() && !Base.getReg()) 170 printOperand(MI, OpNum); 171 else if (Base.getReg()) { 172 if (Disp.getImm()) { 173 printOperand(MI, OpNum, "nohash"); 174 O << '('; 175 printOperand(MI, OpNum + 1); 176 O << ')'; 177 } else { 178 O << '@'; 179 printOperand(MI, OpNum + 1); 180 } 181 } else 182 assert(0 && "Unsupported memory operand"); 183} 184 185