LLVM API Documentation
00001 //===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains a printer that converts from our internal representation 00011 // of machine-dependent LLVM code to the MSP430 assembly language. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "MSP430.h" 00016 #include "InstPrinter/MSP430InstPrinter.h" 00017 #include "MSP430InstrInfo.h" 00018 #include "MSP430MCInstLower.h" 00019 #include "MSP430TargetMachine.h" 00020 #include "llvm/CodeGen/AsmPrinter.h" 00021 #include "llvm/CodeGen/MachineConstantPool.h" 00022 #include "llvm/CodeGen/MachineFunctionPass.h" 00023 #include "llvm/CodeGen/MachineInstr.h" 00024 #include "llvm/CodeGen/MachineModuleInfo.h" 00025 #include "llvm/IR/Constants.h" 00026 #include "llvm/IR/DerivedTypes.h" 00027 #include "llvm/IR/Mangler.h" 00028 #include "llvm/IR/Module.h" 00029 #include "llvm/MC/MCAsmInfo.h" 00030 #include "llvm/MC/MCInst.h" 00031 #include "llvm/MC/MCStreamer.h" 00032 #include "llvm/MC/MCSymbol.h" 00033 #include "llvm/Support/TargetRegistry.h" 00034 #include "llvm/Support/raw_ostream.h" 00035 using namespace llvm; 00036 00037 #define DEBUG_TYPE "asm-printer" 00038 00039 namespace { 00040 class MSP430AsmPrinter : public AsmPrinter { 00041 public: 00042 MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 00043 : AsmPrinter(TM, Streamer) {} 00044 00045 const char *getPassName() const override { 00046 return "MSP430 Assembly Printer"; 00047 } 00048 00049 void printOperand(const MachineInstr *MI, int OpNum, 00050 raw_ostream &O, const char* Modifier = nullptr); 00051 void printSrcMemOperand(const MachineInstr *MI, int OpNum, 00052 raw_ostream &O); 00053 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 00054 unsigned AsmVariant, const char *ExtraCode, 00055 raw_ostream &O) override; 00056 bool PrintAsmMemoryOperand(const MachineInstr *MI, 00057 unsigned OpNo, unsigned AsmVariant, 00058 const char *ExtraCode, raw_ostream &O) override; 00059 void EmitInstruction(const MachineInstr *MI) override; 00060 }; 00061 } // end of anonymous namespace 00062 00063 00064 void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 00065 raw_ostream &O, const char *Modifier) { 00066 const MachineOperand &MO = MI->getOperand(OpNum); 00067 switch (MO.getType()) { 00068 default: llvm_unreachable("Not implemented yet!"); 00069 case MachineOperand::MO_Register: 00070 O << MSP430InstPrinter::getRegisterName(MO.getReg()); 00071 return; 00072 case MachineOperand::MO_Immediate: 00073 if (!Modifier || strcmp(Modifier, "nohash")) 00074 O << '#'; 00075 O << MO.getImm(); 00076 return; 00077 case MachineOperand::MO_MachineBasicBlock: 00078 O << *MO.getMBB()->getSymbol(); 00079 return; 00080 case MachineOperand::MO_GlobalAddress: { 00081 bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 00082 uint64_t Offset = MO.getOffset(); 00083 00084 // If the global address expression is a part of displacement field with a 00085 // register base, we should not emit any prefix symbol here, e.g. 00086 // mov.w &foo, r1 00087 // vs 00088 // mov.w glb(r1), r2 00089 // Otherwise (!) msp430-as will silently miscompile the output :( 00090 if (!Modifier || strcmp(Modifier, "nohash")) 00091 O << (isMemOp ? '&' : '#'); 00092 if (Offset) 00093 O << '(' << Offset << '+'; 00094 00095 O << *getSymbol(MO.getGlobal()); 00096 00097 if (Offset) 00098 O << ')'; 00099 00100 return; 00101 } 00102 } 00103 } 00104 00105 void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 00106 raw_ostream &O) { 00107 const MachineOperand &Base = MI->getOperand(OpNum); 00108 const MachineOperand &Disp = MI->getOperand(OpNum+1); 00109 00110 // Print displacement first 00111 00112 // Imm here is in fact global address - print extra modifier. 00113 if (Disp.isImm() && !Base.getReg()) 00114 O << '&'; 00115 printOperand(MI, OpNum+1, O, "nohash"); 00116 00117 // Print register base field 00118 if (Base.getReg()) { 00119 O << '('; 00120 printOperand(MI, OpNum, O); 00121 O << ')'; 00122 } 00123 } 00124 00125 /// PrintAsmOperand - Print out an operand for an inline asm expression. 00126 /// 00127 bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 00128 unsigned AsmVariant, 00129 const char *ExtraCode, raw_ostream &O) { 00130 // Does this asm operand have a single letter operand modifier? 00131 if (ExtraCode && ExtraCode[0]) 00132 return true; // Unknown modifier. 00133 00134 printOperand(MI, OpNo, O); 00135 return false; 00136 } 00137 00138 bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 00139 unsigned OpNo, unsigned AsmVariant, 00140 const char *ExtraCode, 00141 raw_ostream &O) { 00142 if (ExtraCode && ExtraCode[0]) { 00143 return true; // Unknown modifier. 00144 } 00145 printSrcMemOperand(MI, OpNo, O); 00146 return false; 00147 } 00148 00149 //===----------------------------------------------------------------------===// 00150 void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 00151 MSP430MCInstLower MCInstLowering(OutContext, *this); 00152 00153 MCInst TmpInst; 00154 MCInstLowering.Lower(MI, TmpInst); 00155 EmitToStreamer(OutStreamer, TmpInst); 00156 } 00157 00158 // Force static initialization. 00159 extern "C" void LLVMInitializeMSP430AsmPrinter() { 00160 RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target); 00161 }