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