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 35 using namespace llvm; 36 37 STATISTIC(EmittedInsts, "Number of machine instrs printed"); 38 39 namespace { 40 class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter { 41 public: 42 MSP430AsmPrinter(raw_ostream &O, MSP430TargetMachine &TM, 43 const TargetAsmInfo *TAI, bool V) 44 : AsmPrinter(O, TM, TAI, V) {} 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 void printCCOperand(const MachineInstr *MI, int OpNum); 55 bool printInstruction(const MachineInstr *MI); // autogenerated. 56 void printMachineInstruction(const MachineInstr * MI); 57 58 void emitFunctionHeader(const MachineFunction &MF); 59 bool runOnMachineFunction(MachineFunction &F); 60 bool doInitialization(Module &M); 61 bool doFinalization(Module &M); 62 63 void getAnalysisUsage(AnalysisUsage &AU) const { 64 AsmPrinter::getAnalysisUsage(AU); 65 AU.setPreservesAll(); 66 } 67 }; 68 } // end of anonymous namespace 69 70 #include "MSP430GenAsmWriter.inc" 71 72 /// createMSP430CodePrinterPass - Returns a pass that prints the MSP430 73 /// assembly code for a MachineFunction to the given output stream, 74 /// using the given target machine description. This should work 75 /// regardless of whether the function is in SSA form. 76 /// 77 FunctionPass *llvm::createMSP430CodePrinterPass(raw_ostream &o, 78 MSP430TargetMachine &tm, 79 bool verbose) { 80 return new MSP430AsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose); 81 } 82 83 bool MSP430AsmPrinter::doInitialization(Module &M) { 84 Mang = new Mangler(M, "", TAI->getPrivateGlobalPrefix()); 85 return false; // success 86 } 87 88 89 bool MSP430AsmPrinter::doFinalization(Module &M) { 90 return AsmPrinter::doFinalization(M); 91 } 92 93 void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { 94 const Function *F = MF.getFunction(); 95 96 SwitchToSection(TAI->SectionForGlobal(F)); 97 98 unsigned FnAlign = MF.getAlignment(); 99 EmitAlignment(FnAlign, F); 100 101 switch (F->getLinkage()) { 102 default: assert(0 && "Unknown linkage type!"); 103 case Function::InternalLinkage: // Symbols default to internal. 104 case Function::PrivateLinkage: 105 break; 106 case Function::ExternalLinkage: 107 O << "\t.globl\t" << CurrentFnName << '\n'; 108 break; 109 case Function::LinkOnceAnyLinkage: 110 case Function::LinkOnceODRLinkage: 111 case Function::WeakAnyLinkage: 112 case Function::WeakODRLinkage: 113 O << "\t.weak\t" << CurrentFnName << '\n'; 114 break; 115 } 116 117 printVisibility(CurrentFnName, F->getVisibility()); 118 119 O << "\t.type\t" << CurrentFnName << ",@function\n" 120 << CurrentFnName << ":\n"; 121 } 122 123 bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 124 SetupMachineFunction(MF); 125 O << "\n\n"; 126 127 // Print the 'header' of function 128 emitFunctionHeader(MF); 129 130 // Print out code for the function. 131 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 132 I != E; ++I) { 133 // Print a label for the basic block. 134 if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) { 135 // This is an entry block or a block that's only reachable via a 136 // fallthrough edge. In non-VerboseAsm mode, don't print the label. 137 } else { 138 printBasicBlockLabel(I, true, true, VerboseAsm); 139 O << '\n'; 140 } 141 142 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 143 II != E; ++II) 144 // Print the assembly for the instruction. 145 printMachineInstruction(II); 146 } 147 148 if (TAI->hasDotTypeDotSizeDirective()) 149 O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; 150 151 O.flush(); 152 153 // We didn't modify anything 154 return false; 155 } 156 157 void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) { 158 ++EmittedInsts; 159 160 // Call the autogenerated instruction printer routines. 161 if (printInstruction(MI)) 162 return; 163 164 assert(0 && "Should not happen"); 165 } 166 167 void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 168 const char* Modifier) { 169 const MachineOperand &MO = MI->getOperand(OpNum); 170 switch (MO.getType()) { 171 case MachineOperand::MO_Register: 172 assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && 173 "Virtual registers should be already mapped!"); 174 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; 175 return; 176 case MachineOperand::MO_Immediate: 177 if (!Modifier || strcmp(Modifier, "nohash")) 178 O << '#'; 179 O << MO.getImm(); 180 return; 181 case MachineOperand::MO_MachineBasicBlock: 182 printBasicBlockLabel(MO.getMBB()); 183 return; 184 case MachineOperand::MO_GlobalAddress: { 185 bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 186 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 187 std::string Name = Mang->getValueName(MO.getGlobal()); 188 assert(MO.getOffset() == 0 && "No offsets allowed!"); 189 190 if (isCallOp) 191 O << '#'; 192 else if (isMemOp) 193 O << '&'; 194 195 O << Name; 196 197 return; 198 } 199 case MachineOperand::MO_ExternalSymbol: { 200 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 201 std::string Name(TAI->getGlobalPrefix()); 202 Name += MO.getSymbolName(); 203 if (isCallOp) 204 O << '#'; 205 O << Name; 206 return; 207 } 208 default: 209 assert(0 && "Not implemented yet!"); 210 } 211 } 212 213 void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 214 const char* Modifier) { 215 const MachineOperand &Base = MI->getOperand(OpNum); 216 const MachineOperand &Disp = MI->getOperand(OpNum+1); 217 218 if (Base.isGlobal()) 219 printOperand(MI, OpNum, "mem"); 220 else if (Disp.isImm() && !Base.getReg()) 221 printOperand(MI, OpNum); 222 else if (Base.getReg()) { 223 if (Disp.getImm()) { 224 printOperand(MI, OpNum + 1, "nohash"); 225 O << '('; 226 printOperand(MI, OpNum); 227 O << ')'; 228 } else { 229 O << '@'; 230 printOperand(MI, OpNum); 231 } 232 } else 233 assert(0 && "Unsupported memory operand"); 234 } 235 236 void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) { 237 unsigned CC = MI->getOperand(OpNum).getImm(); 238 239 switch (CC) { 240 default: 241 assert(0 && "Unsupported CC code"); 242 break; 243 case MSP430::COND_E: 244 O << "eq"; 245 break; 246 case MSP430::COND_NE: 247 O << "ne"; 248 break; 249 case MSP430::COND_HS: 250 O << "hs"; 251 break; 252 case MSP430::COND_LO: 253 O << "lo"; 254 break; 255 case MSP430::COND_GE: 256 O << "ge"; 257 break; 258 case MSP430::COND_L: 259 O << 'l'; 260 break; 261 } 262 } 263