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