1 //===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to the MSP430 assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "asm-printer"
17 #include "MSP430InstrInfo.h"
18 #include "MSP430InstPrinter.h"
19 #include "MSP430MCAsmInfo.h"
20 #include "MSP430MCInstLower.h"
21 #include "MSP430TargetMachine.h"
22 #include "llvm/Constants.h"
23 #include "llvm/DerivedTypes.h"
24 #include "llvm/Module.h"
25 #include "llvm/CodeGen/AsmPrinter.h"
26 #include "llvm/CodeGen/DwarfWriter.h"
27 #include "llvm/CodeGen/MachineModuleInfo.h"
28 #include "llvm/CodeGen/MachineFunctionPass.h"
29 #include "llvm/CodeGen/MachineConstantPool.h"
30 #include "llvm/CodeGen/MachineInstr.h"
31 #include "llvm/MC/MCInst.h"
32 #include "llvm/MC/MCStreamer.h"
33 #include "llvm/MC/MCSymbol.h"
34 #include "llvm/Target/TargetData.h"
35 #include "llvm/Target/TargetLoweringObjectFile.h"
36 #include "llvm/Target/TargetRegistry.h"
37 #include "llvm/ADT/Statistic.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Compiler.h"
40 #include "llvm/Support/FormattedStream.h"
41 #include "llvm/Support/Mangler.h"
42 #include "llvm/Support/ErrorHandling.h"
46 STATISTIC(EmittedInsts, "Number of machine instrs printed");
49 EnableMCInst("enable-msp430-mcinst-printer", cl::Hidden,
50 cl::desc("enable experimental mcinst gunk in the msp430 backend"));
53 class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter {
55 MSP430AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
56 const MCAsmInfo *MAI, bool V)
57 : AsmPrinter(O, TM, MAI, V) {}
59 virtual const char *getPassName() const {
60 return "MSP430 Assembly Printer";
63 void printMCInst(const MCInst *MI) {
64 MSP430InstPrinter(O, *MAI).printInstruction(MI);
66 void printOperand(const MachineInstr *MI, int OpNum,
67 const char* Modifier = 0);
68 void printSrcMemOperand(const MachineInstr *MI, int OpNum,
69 const char* Modifier = 0);
70 void printCCOperand(const MachineInstr *MI, int OpNum);
71 void printInstruction(const MachineInstr *MI); // autogenerated.
72 static const char *getRegisterName(unsigned RegNo);
74 void printMachineInstruction(const MachineInstr * MI);
75 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
77 const char *ExtraCode);
78 bool PrintAsmMemoryOperand(const MachineInstr *MI,
79 unsigned OpNo, unsigned AsmVariant,
80 const char *ExtraCode);
81 void printInstructionThroughMCStreamer(const MachineInstr *MI);
83 void emitFunctionHeader(const MachineFunction &MF);
84 bool runOnMachineFunction(MachineFunction &F);
86 virtual void PrintGlobalVariable(const GlobalVariable *GV) {
87 // FIXME: No support for global variables?
90 void getAnalysisUsage(AnalysisUsage &AU) const {
91 AsmPrinter::getAnalysisUsage(AU);
95 } // end of anonymous namespace
97 #include "MSP430GenAsmWriter.inc"
100 void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
101 const Function *F = MF.getFunction();
103 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
105 unsigned FnAlign = MF.getAlignment();
106 EmitAlignment(FnAlign, F);
108 switch (F->getLinkage()) {
109 default: llvm_unreachable("Unknown linkage type!");
110 case Function::InternalLinkage: // Symbols default to internal.
111 case Function::PrivateLinkage:
112 case Function::LinkerPrivateLinkage:
114 case Function::ExternalLinkage:
115 O << "\t.globl\t" << CurrentFnName << '\n';
117 case Function::LinkOnceAnyLinkage:
118 case Function::LinkOnceODRLinkage:
119 case Function::WeakAnyLinkage:
120 case Function::WeakODRLinkage:
121 O << "\t.weak\t" << CurrentFnName << '\n';
125 printVisibility(CurrentFnName, F->getVisibility());
127 O << "\t.type\t" << CurrentFnName << ",@function\n"
128 << CurrentFnName << ":\n";
131 bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
132 SetupMachineFunction(MF);
135 // Print the 'header' of function
136 emitFunctionHeader(MF);
138 // Print out code for the function.
139 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
141 // Print a label for the basic block.
142 EmitBasicBlockStart(I);
144 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
146 // Print the assembly for the instruction.
147 printMachineInstruction(II);
150 if (MAI->hasDotTypeDotSizeDirective())
151 O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
153 // We didn't modify anything
157 void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
160 processDebugLoc(MI, true);
162 // Call the autogenerated instruction printer routines.
164 printInstructionThroughMCStreamer(MI);
166 printInstruction(MI);
169 if (VerboseAsm && !MI->getDebugLoc().isUnknown())
173 processDebugLoc(MI, false);
176 void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
177 const char* Modifier) {
178 const MachineOperand &MO = MI->getOperand(OpNum);
179 switch (MO.getType()) {
180 case MachineOperand::MO_Register:
181 O << getRegisterName(MO.getReg());
183 case MachineOperand::MO_Immediate:
184 if (!Modifier || strcmp(Modifier, "nohash"))
188 case MachineOperand::MO_MachineBasicBlock:
189 GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
191 case MachineOperand::MO_GlobalAddress: {
192 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
193 std::string Name = Mang->getMangledName(MO.getGlobal());
194 uint64_t Offset = MO.getOffset();
196 O << (isMemOp ? '&' : '#');
198 O << '(' << Offset << '+';
206 case MachineOperand::MO_ExternalSymbol: {
207 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
208 std::string Name(MAI->getGlobalPrefix());
209 Name += MO.getSymbolName();
211 O << (isMemOp ? '&' : '#') << Name;
216 llvm_unreachable("Not implemented yet!");
220 void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
221 const char* Modifier) {
222 const MachineOperand &Base = MI->getOperand(OpNum);
223 const MachineOperand &Disp = MI->getOperand(OpNum+1);
226 printOperand(MI, OpNum, "mem");
227 else if (Disp.isImm() && !Base.getReg())
228 printOperand(MI, OpNum);
229 else if (Base.getReg()) {
231 printOperand(MI, OpNum + 1, "nohash");
233 printOperand(MI, OpNum);
237 printOperand(MI, OpNum);
240 llvm_unreachable("Unsupported memory operand");
243 void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
244 unsigned CC = MI->getOperand(OpNum).getImm();
248 llvm_unreachable("Unsupported CC code");
253 case MSP430::COND_NE:
256 case MSP430::COND_HS:
259 case MSP430::COND_LO:
262 case MSP430::COND_GE:
271 /// PrintAsmOperand - Print out an operand for an inline asm expression.
273 bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
275 const char *ExtraCode) {
276 // Does this asm operand have a single letter operand modifier?
277 if (ExtraCode && ExtraCode[0])
278 return true; // Unknown modifier.
280 printOperand(MI, OpNo);
284 bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
285 unsigned OpNo, unsigned AsmVariant,
286 const char *ExtraCode) {
287 if (ExtraCode && ExtraCode[0]) {
288 return true; // Unknown modifier.
290 printSrcMemOperand(MI, OpNo);
294 //===----------------------------------------------------------------------===//
295 void MSP430AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI)
298 MSP430MCInstLower MCInstLowering(OutContext, *Mang, getFunctionNumber(), *MAI);
300 switch (MI->getOpcode()) {
301 case TargetInstrInfo::DBG_LABEL:
302 case TargetInstrInfo::EH_LABEL:
303 case TargetInstrInfo::GC_LABEL:
306 case TargetInstrInfo::KILL:
308 case TargetInstrInfo::INLINEASM:
312 case TargetInstrInfo::IMPLICIT_DEF:
313 printImplicitDef(MI);
319 MCInstLowering.Lower(MI, TmpInst);
321 printMCInst(&TmpInst);
324 // Force static initialization.
325 extern "C" void LLVMInitializeMSP430AsmPrinter() {
326 RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);