blob: 4a32bebde533c0ce814ca2f4cefad22c4f80a9c4 [file] [log] [blame]
Daniel Dunbar5680b4f2009-07-25 06:49:55 +00001//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
Anton Korobeynikov10138002009-05-03 12:57:15 +00002//
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"
Anton Korobeynikovdaaa2f02009-10-21 00:10:47 +000018#include "MSP430InstPrinter.h"
Chris Lattner7b26fce2009-08-22 20:48:53 +000019#include "MSP430MCAsmInfo.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000020#include "MSP430TargetMachine.h"
21#include "llvm/Constants.h"
22#include "llvm/DerivedTypes.h"
23#include "llvm/Module.h"
24#include "llvm/CodeGen/AsmPrinter.h"
25#include "llvm/CodeGen/DwarfWriter.h"
26#include "llvm/CodeGen/MachineModuleInfo.h"
27#include "llvm/CodeGen/MachineFunctionPass.h"
28#include "llvm/CodeGen/MachineConstantPool.h"
29#include "llvm/CodeGen/MachineInstr.h"
Chris Lattner4b7dadb2009-08-19 05:49:37 +000030#include "llvm/MC/MCStreamer.h"
Chris Lattner4cd44982009-09-13 17:14:04 +000031#include "llvm/MC/MCSymbol.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000032#include "llvm/Target/TargetData.h"
Chris Lattner5e693ed2009-07-28 03:13:23 +000033#include "llvm/Target/TargetLoweringObjectFile.h"
Daniel Dunbar5680b4f2009-07-25 06:49:55 +000034#include "llvm/Target/TargetRegistry.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000035#include "llvm/ADT/Statistic.h"
36#include "llvm/Support/Compiler.h"
David Greenea31f96c2009-07-14 20:18:05 +000037#include "llvm/Support/FormattedStream.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000038#include "llvm/Support/Mangler.h"
Torok Edwin56d06592009-07-11 20:10:48 +000039#include "llvm/Support/ErrorHandling.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000040
41using namespace llvm;
42
43STATISTIC(EmittedInsts, "Number of machine instrs printed");
44
45namespace {
46 class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter {
47 public:
Daniel Dunbar15c3e712009-07-15 23:17:20 +000048 MSP430AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
Chris Lattnere9a75a62009-08-22 21:43:10 +000049 const MCAsmInfo *MAI, bool V)
50 : AsmPrinter(O, TM, MAI, V) {}
Anton Korobeynikov10138002009-05-03 12:57:15 +000051
52 virtual const char *getPassName() const {
53 return "MSP430 Assembly Printer";
54 }
55
Anton Korobeynikovdaaa2f02009-10-21 00:10:47 +000056 void printMCInst(const MCInst *MI) {
57 MSP430InstPrinter(O, *MAI).printInstruction(MI);
58 }
Anton Korobeynikov31ecd232009-05-03 13:06:03 +000059 void printOperand(const MachineInstr *MI, int OpNum,
60 const char* Modifier = 0);
61 void printSrcMemOperand(const MachineInstr *MI, int OpNum,
62 const char* Modifier = 0);
Anton Korobeynikovb6321e152009-05-03 13:12:23 +000063 void printCCOperand(const MachineInstr *MI, int OpNum);
Chris Lattnerb94284b2009-08-08 01:32:19 +000064 void printInstruction(const MachineInstr *MI); // autogenerated.
Chris Lattnerad10b3b2009-09-13 20:19:22 +000065 static const char *getRegisterName(unsigned RegNo);
Chris Lattner06c5eed2009-09-13 20:08:00 +000066
Anton Korobeynikov10138002009-05-03 12:57:15 +000067 void printMachineInstruction(const MachineInstr * MI);
Anton Korobeynikova0e01be2009-08-26 13:44:29 +000068 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
69 unsigned AsmVariant,
70 const char *ExtraCode);
Anton Korobeynikov3525a4a2009-10-11 19:13:34 +000071 bool PrintAsmMemoryOperand(const MachineInstr *MI,
72 unsigned OpNo, unsigned AsmVariant,
73 const char *ExtraCode);
Anton Korobeynikov48e21c52009-05-03 13:17:11 +000074
75 void emitFunctionHeader(const MachineFunction &MF);
Anton Korobeynikov10138002009-05-03 12:57:15 +000076 bool runOnMachineFunction(MachineFunction &F);
Anton Korobeynikov10138002009-05-03 12:57:15 +000077
Chris Lattner100865e2009-07-21 18:38:57 +000078 virtual void PrintGlobalVariable(const GlobalVariable *GV) {
79 // FIXME: No support for global variables?
80 }
81
Anton Korobeynikov10138002009-05-03 12:57:15 +000082 void getAnalysisUsage(AnalysisUsage &AU) const {
83 AsmPrinter::getAnalysisUsage(AU);
84 AU.setPreservesAll();
85 }
86 };
87} // end of anonymous namespace
88
89#include "MSP430GenAsmWriter.inc"
90
Anton Korobeynikov10138002009-05-03 12:57:15 +000091
Anton Korobeynikov48e21c52009-05-03 13:17:11 +000092void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
93 const Function *F = MF.getFunction();
94
Chris Lattner4b7dadb2009-08-19 05:49:37 +000095 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
Anton Korobeynikov48e21c52009-05-03 13:17:11 +000096
Bill Wendling31ceb1b2009-06-30 22:38:32 +000097 unsigned FnAlign = MF.getAlignment();
Anton Korobeynikov48e21c52009-05-03 13:17:11 +000098 EmitAlignment(FnAlign, F);
99
100 switch (F->getLinkage()) {
Torok Edwinfbcc6632009-07-14 16:55:14 +0000101 default: llvm_unreachable("Unknown linkage type!");
Anton Korobeynikov48e21c52009-05-03 13:17:11 +0000102 case Function::InternalLinkage: // Symbols default to internal.
103 case Function::PrivateLinkage:
Bill Wendlinga3c6f6b2009-07-20 01:03:30 +0000104 case Function::LinkerPrivateLinkage:
Anton Korobeynikov48e21c52009-05-03 13:17:11 +0000105 break;
106 case Function::ExternalLinkage:
107 O << "\t.globl\t" << CurrentFnName << '\n';
108 break;
109 case Function::LinkOnceAnyLinkage:
110 case Function::LinkOnceODRLinkage:
111 case Function::WeakAnyLinkage:
112 case Function::WeakODRLinkage:
113 O << "\t.weak\t" << CurrentFnName << '\n';
114 break;
115 }
116
117 printVisibility(CurrentFnName, F->getVisibility());
118
119 O << "\t.type\t" << CurrentFnName << ",@function\n"
120 << CurrentFnName << ":\n";
121}
122
Anton Korobeynikovc9427822009-05-03 13:01:41 +0000123bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Anton Korobeynikov48e21c52009-05-03 13:17:11 +0000124 SetupMachineFunction(MF);
Anton Korobeynikov3c48ea72009-05-03 13:17:31 +0000125 O << "\n\n";
Anton Korobeynikov48e21c52009-05-03 13:17:11 +0000126
127 // Print the 'header' of function
128 emitFunctionHeader(MF);
129
Anton Korobeynikovc9427822009-05-03 13:01:41 +0000130 // Print out code for the function.
131 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
132 I != E; ++I) {
133 // Print a label for the basic block.
Dan Gohman10d3dc52009-10-06 17:38:38 +0000134 EmitBasicBlockStart(I);
Anton Korobeynikovc9427822009-05-03 13:01:41 +0000135
136 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
Anton Korobeynikov3c48ea72009-05-03 13:17:31 +0000137 II != E; ++II)
Anton Korobeynikovc9427822009-05-03 13:01:41 +0000138 // Print the assembly for the instruction.
Anton Korobeynikovc9427822009-05-03 13:01:41 +0000139 printMachineInstruction(II);
Anton Korobeynikovc9427822009-05-03 13:01:41 +0000140 }
141
Chris Lattnere9a75a62009-08-22 21:43:10 +0000142 if (MAI->hasDotTypeDotSizeDirective())
Anton Korobeynikov48e21c52009-05-03 13:17:11 +0000143 O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
144
Anton Korobeynikov10138002009-05-03 12:57:15 +0000145 // We didn't modify anything
146 return false;
147}
148
Anton Korobeynikovd7afd692009-05-03 13:02:04 +0000149void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
Anton Korobeynikov10138002009-05-03 12:57:15 +0000150 ++EmittedInsts;
151
Devang Patel051454a2009-10-06 02:19:11 +0000152 processDebugLoc(MI, true);
Chris Lattner321bc992009-09-09 23:14:36 +0000153
Anton Korobeynikov10138002009-05-03 12:57:15 +0000154 // Call the autogenerated instruction printer routines.
Chris Lattnerb1692dc2009-08-08 00:05:42 +0000155 printInstruction(MI);
Anton Korobeynikova58a3f92009-10-11 19:14:02 +0000156
Chris Lattner321bc992009-09-09 23:14:36 +0000157 if (VerboseAsm && !MI->getDebugLoc().isUnknown())
158 EmitComments(*MI);
159 O << '\n';
Devang Patel051454a2009-10-06 02:19:11 +0000160
161 processDebugLoc(MI, false);
Anton Korobeynikov10138002009-05-03 12:57:15 +0000162}
Anton Korobeynikovd7afd692009-05-03 13:02:04 +0000163
Anton Korobeynikov31ecd232009-05-03 13:06:03 +0000164void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
165 const char* Modifier) {
Anton Korobeynikovd7afd692009-05-03 13:02:04 +0000166 const MachineOperand &MO = MI->getOperand(OpNum);
167 switch (MO.getType()) {
168 case MachineOperand::MO_Register:
Chris Lattnereb2cc682009-09-13 20:31:40 +0000169 O << getRegisterName(MO.getReg());
Anton Korobeynikovb5613922009-05-03 13:08:13 +0000170 return;
Anton Korobeynikovd7afd692009-05-03 13:02:04 +0000171 case MachineOperand::MO_Immediate:
Anton Korobeynikov31ecd232009-05-03 13:06:03 +0000172 if (!Modifier || strcmp(Modifier, "nohash"))
173 O << '#';
174 O << MO.getImm();
Anton Korobeynikovb5613922009-05-03 13:08:13 +0000175 return;
Anton Korobeynikovd7afd692009-05-03 13:02:04 +0000176 case MachineOperand::MO_MachineBasicBlock:
Chris Lattner4cd44982009-09-13 17:14:04 +0000177 GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
Anton Korobeynikovb5613922009-05-03 13:08:13 +0000178 return;
179 case MachineOperand::MO_GlobalAddress: {
180 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
Chris Lattner8c9a96b2009-07-14 18:17:16 +0000181 std::string Name = Mang->getMangledName(MO.getGlobal());
Anton Korobeynikova58a3f92009-10-11 19:14:02 +0000182 uint64_t Offset = MO.getOffset();
Anton Korobeynikovb5613922009-05-03 13:08:13 +0000183
Anton Korobeynikova58a3f92009-10-11 19:14:02 +0000184 O << (isMemOp ? '&' : '#');
185 if (Offset)
186 O << '(' << Offset << '+';
Anton Korobeynikovb5613922009-05-03 13:08:13 +0000187
188 O << Name;
Anton Korobeynikova58a3f92009-10-11 19:14:02 +0000189 if (Offset)
190 O << ')';
Anton Korobeynikovb5613922009-05-03 13:08:13 +0000191
192 return;
193 }
Anton Korobeynikovba0e81d2009-05-03 13:14:46 +0000194 case MachineOperand::MO_ExternalSymbol: {
Anton Korobeynikova58a3f92009-10-11 19:14:02 +0000195 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
Chris Lattnere9a75a62009-08-22 21:43:10 +0000196 std::string Name(MAI->getGlobalPrefix());
Anton Korobeynikovba0e81d2009-05-03 13:14:46 +0000197 Name += MO.getSymbolName();
Anton Korobeynikova58a3f92009-10-11 19:14:02 +0000198
199 O << (isMemOp ? '&' : '#') << Name;
200
Anton Korobeynikovba0e81d2009-05-03 13:14:46 +0000201 return;
202 }
Anton Korobeynikovd7afd692009-05-03 13:02:04 +0000203 default:
Torok Edwinfbcc6632009-07-14 16:55:14 +0000204 llvm_unreachable("Not implemented yet!");
Anton Korobeynikovd7afd692009-05-03 13:02:04 +0000205 }
206}
Anton Korobeynikov31ecd232009-05-03 13:06:03 +0000207
208void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
209 const char* Modifier) {
Anton Korobeynikoved656712009-05-03 13:09:40 +0000210 const MachineOperand &Base = MI->getOperand(OpNum);
211 const MachineOperand &Disp = MI->getOperand(OpNum+1);
Anton Korobeynikov31ecd232009-05-03 13:06:03 +0000212
Anton Korobeynikoved656712009-05-03 13:09:40 +0000213 if (Base.isGlobal())
Anton Korobeynikov6399a3d2009-05-03 13:09:10 +0000214 printOperand(MI, OpNum, "mem");
215 else if (Disp.isImm() && !Base.getReg())
216 printOperand(MI, OpNum);
217 else if (Base.getReg()) {
218 if (Disp.getImm()) {
Anton Korobeynikoved656712009-05-03 13:09:40 +0000219 printOperand(MI, OpNum + 1, "nohash");
Anton Korobeynikov6399a3d2009-05-03 13:09:10 +0000220 O << '(';
Anton Korobeynikoved656712009-05-03 13:09:40 +0000221 printOperand(MI, OpNum);
Anton Korobeynikov6399a3d2009-05-03 13:09:10 +0000222 O << ')';
223 } else {
224 O << '@';
Anton Korobeynikoved656712009-05-03 13:09:40 +0000225 printOperand(MI, OpNum);
Anton Korobeynikov6399a3d2009-05-03 13:09:10 +0000226 }
227 } else
Torok Edwinfbcc6632009-07-14 16:55:14 +0000228 llvm_unreachable("Unsupported memory operand");
Anton Korobeynikov31ecd232009-05-03 13:06:03 +0000229}
230
Anton Korobeynikovb6321e152009-05-03 13:12:23 +0000231void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
232 unsigned CC = MI->getOperand(OpNum).getImm();
233
234 switch (CC) {
235 default:
Torok Edwinfbcc6632009-07-14 16:55:14 +0000236 llvm_unreachable("Unsupported CC code");
Anton Korobeynikovb6321e152009-05-03 13:12:23 +0000237 break;
238 case MSP430::COND_E:
Anton Korobeynikov8847e3e2009-05-03 13:16:54 +0000239 O << "eq";
Anton Korobeynikovb6321e152009-05-03 13:12:23 +0000240 break;
241 case MSP430::COND_NE:
242 O << "ne";
243 break;
244 case MSP430::COND_HS:
245 O << "hs";
246 break;
247 case MSP430::COND_LO:
248 O << "lo";
249 break;
250 case MSP430::COND_GE:
251 O << "ge";
252 break;
253 case MSP430::COND_L:
254 O << 'l';
255 break;
256 }
257}
Daniel Dunbar5680b4f2009-07-25 06:49:55 +0000258
Anton Korobeynikova0e01be2009-08-26 13:44:29 +0000259/// PrintAsmOperand - Print out an operand for an inline asm expression.
260///
261bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
262 unsigned AsmVariant,
263 const char *ExtraCode) {
264 // Does this asm operand have a single letter operand modifier?
265 if (ExtraCode && ExtraCode[0])
266 return true; // Unknown modifier.
267
268 printOperand(MI, OpNo);
269 return false;
270}
271
Anton Korobeynikov3525a4a2009-10-11 19:13:34 +0000272bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
273 unsigned OpNo, unsigned AsmVariant,
274 const char *ExtraCode) {
275 if (ExtraCode && ExtraCode[0]) {
276 return true; // Unknown modifier.
277 }
278 printSrcMemOperand(MI, OpNo);
279 return false;
280}
281
Anton Korobeynikovc1524d42009-08-14 19:06:50 +0000282// Force static initialization.
283extern "C" void LLVMInitializeMSP430AsmPrinter() {
284 RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
Daniel Dunbar5680b4f2009-07-25 06:49:55 +0000285}