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