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