blob: 151fafc4c5463dcc63e7715fb94feb325de5a65f [file] [log] [blame]
Sanjiv Gupta0e687712008-05-13 09:02:57 +00001//===-- PIC16AsmPrinter.cpp - PIC16 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 PIC16 assembly language.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "asm-printer"
16#include "PIC16.h"
17#include "PIC16TargetMachine.h"
18#include "PIC16ConstantPoolValue.h"
19#include "PIC16InstrInfo.h"
20#include "llvm/Constants.h"
21#include "llvm/DerivedTypes.h"
22#include "llvm/Module.h"
23#include "llvm/ADT/SetVector.h"
24#include "llvm/ADT/Statistic.h"
25#include "llvm/ADT/StringExtras.h"
26#include "llvm/CodeGen/AsmPrinter.h"
27#include "llvm/CodeGen/MachineFunctionPass.h"
28#include "llvm/CodeGen/MachineConstantPool.h"
29#include "llvm/CodeGen/MachineFrameInfo.h"
30#include "llvm/CodeGen/MachineInstr.h"
31#include "llvm/Support/CommandLine.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Support/Mangler.h"
34#include "llvm/Support/MathExtras.h"
35#include "llvm/Target/TargetAsmInfo.h"
36#include "llvm/Target/TargetData.h"
37#include "llvm/Target/TargetMachine.h"
38#include "llvm/Target/TargetOptions.h"
39#include <cctype>
40
41using namespace llvm;
42
43STATISTIC(EmittedInsts, "Number of machine instrs printed");
44
45namespace {
46 struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
47 PIC16AsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
48 : AsmPrinter(O, TM, T) {
49 }
50
51
52 /// We name each basic block in a Function with a unique number, so
53 /// that we can consistently refer to them later. This is cleared
54 /// at the beginning of each call to runOnMachineFunction().
55 ///
56 typedef std::map<const Value *, unsigned> ValueMapTy;
57 ValueMapTy NumberForBB;
58
59 /// Keeps the set of GlobalValues that require non-lazy-pointers for
60 /// indirect access.
61 std::set<std::string> GVNonLazyPtrs;
62
63 /// Keeps the set of external function GlobalAddresses that the asm
64 /// printer should generate stubs for.
65 std::set<std::string> FnStubs;
66
67 /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
68 bool InCPMode;
69
70 virtual const char *getPassName() const {
71 return "PIC16 Assembly Printer";
72 }
73
74 void printOperand(const MachineInstr *MI, int opNum,
75 const char *Modifier = 0);
76
77 void printSOImmOperand(const MachineInstr *MI, int opNum);
78
79 void printAddrModeOperand(const MachineInstr *MI, int OpNo);
80
81 void printRegisterList(const MachineInstr *MI, int opNum);
82 void printCPInstOperand(const MachineInstr *MI, int opNum,
83 const char *Modifier);
84
85
86 bool printInstruction(const MachineInstr *MI); // autogenerated.
87 void emitFunctionStart(MachineFunction &F);
88 bool runOnMachineFunction(MachineFunction &F);
89 bool doInitialization(Module &M);
90 bool doFinalization(Module &M);
91
92 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
93
94 void getAnalysisUsage(AnalysisUsage &AU) const;
95
96 public:
97 void SwitchToTextSection(const char *NewSection,
98 const GlobalValue *GV = NULL);
99 void SwitchToDataSection(const char *NewSection,
100 const GlobalValue *GV = NULL);
101 void SwitchToDataOvrSection(const char *NewSection,
102 const GlobalValue *GV = NULL);
103 };
104} // end of anonymous namespace
105
106#include "PIC16GenAsmWriter.inc"
107
108/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
109/// assembly code for a MachineFunction to the given output stream,
110/// using the given target machine description. This should work
111/// regardless of whether the function is in SSA form.
112///
113FunctionPass *llvm::createPIC16CodePrinterPass(std::ostream &o,
114 PIC16TargetMachine &tm) {
115 return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
116}
117
118void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const
119{
120 // Currently unimplemented.
121}
122
123
124void PIC16AsmPrinter ::
125EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
126{
127 printDataDirective(MCPV->getType());
128
129 PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV;
130 GlobalValue *GV = ACPV->getGV();
131 std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
132 if (!GV)
133 Name += ACPV->getSymbol();
134 if (ACPV->isNonLazyPointer()) {
135 GVNonLazyPtrs.insert(Name);
136 O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
137 } else if (ACPV->isStub()) {
138 FnStubs.insert(Name);
139 O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
140 } else
141 O << Name;
142 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
143
144 if (ACPV->getPCAdjustment() != 0) {
145 O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
146 << utostr(ACPV->getLabelId())
147 << "+" << (unsigned)ACPV->getPCAdjustment();
148
149 if (ACPV->mustAddCurrentAddress())
150 O << "-.";
151
152 O << ")";
153 }
154 O << "\n";
155
156 // If the constant pool value is a extern weak symbol, remember to emit
157 // the weak reference.
158 if (GV && GV->hasExternalWeakLinkage())
159 ExtWeakSymbols.insert(GV);
160}
161
162/// Emit the directives used by ASM on the start of functions
163void PIC16AsmPrinter:: emitFunctionStart(MachineFunction &MF)
164{
165 // Print out the label for the function.
166 const Function *F = MF.getFunction();
167 MachineFrameInfo *FrameInfo = MF.getFrameInfo();
168 if (FrameInfo->hasStackObjects()) {
169 int indexBegin = FrameInfo->getObjectIndexBegin();
170 int indexEnd = FrameInfo->getObjectIndexEnd();
171 while (indexBegin<indexEnd) {
172 if (indexBegin ==0)
173 SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(),
174 F);
175
176 O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES"
177 << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ;
178 indexBegin++;
179 }
180 }
181 SwitchToTextSection(CurrentFnName.c_str(), F);
182 O << "_" << CurrentFnName << ":" ;
183 O << "\n";
184}
185
186
187/// runOnMachineFunction - This uses the printInstruction()
188/// method to print assembly for each instruction.
189///
190bool PIC16AsmPrinter::
191runOnMachineFunction(MachineFunction &MF)
192{
193
194 // DW.SetModuleInfo(&getAnalysis<MachineModuleInfo>());
195 SetupMachineFunction(MF);
196 O << "\n";
197
198 // NOTE: we don't print out constant pools here, they are handled as
199 // instructions.
200 O << "\n";
201
202 // What's my mangled name?
203 CurrentFnName = Mang->getValueName(MF.getFunction());
204
205 // Emit the function start directives
206 emitFunctionStart(MF);
207
208 // Emit pre-function debug information.
209 // DW.BeginFunction(&MF);
210
211 // Print out code for the function.
212 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
213 I != E; ++I) {
214 // Print a label for the basic block.
215 if (I != MF.begin()) {
216 printBasicBlockLabel(I, true);
217 O << '\n';
218 }
219 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
220 II != E; ++II) {
221 // Print the assembly for the instruction.
222 O << '\t';
223 printInstruction(II);
224 ++EmittedInsts;
225 }
226 }
227
228 // Emit post-function debug information.
229 // DW.EndFunction();
230
231 // We didn't modify anything.
232 return false;
233}
234
235void PIC16AsmPrinter::
236printOperand(const MachineInstr *MI, int opNum, const char *Modifier)
237{
238 const MachineOperand &MO = MI->getOperand(opNum);
239 const TargetRegisterInfo &RI = *TM.getRegisterInfo();
240
241 switch (MO.getType())
242 {
243 case MachineOperand::MO_Register:
244 {
245 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
246 O << RI.get(MO.getReg()).Name;
247 else
248 assert(0 && "not implemented");
249 break;
250 }
251 case MachineOperand::MO_Immediate:
252 {
253 if (!Modifier || strcmp(Modifier, "no_hash") != 0)
254 O << "#";
255 O << (int)MO.getImm();
256 break;
257 }
258 case MachineOperand::MO_MachineBasicBlock:
259 {
260 printBasicBlockLabel(MO.getMBB());
261 return;
262 }
263 case MachineOperand::MO_GlobalAddress:
264 {
265 O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
266 break;
267 }
268 case MachineOperand::MO_ExternalSymbol:
269 {
270 O << MO.getSymbolName();
271 break;
272 }
273 case MachineOperand::MO_ConstantPoolIndex:
274 {
275 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
276 << '_' << MO.getIndex();
277 break;
278 }
279 case MachineOperand::MO_FrameIndex:
280 {
281 O << "_" << CurrentFnName
282 << '+' << MO.getIndex();
283 break;
284 }
285 case MachineOperand::MO_JumpTableIndex:
286 {
287 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
288 << '_' << MO.getIndex();
289 break;
290 }
291 default:
292 {
293 O << "<unknown operand type>"; abort ();
294 break;
295 }
296 } // end switch.
297}
298
299static void
300printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI)
301{
302 assert(V < (1 << 12) && "Not a valid so_imm value!");
303 unsigned Imm = V;
304
305 O << Imm;
306}
307
308/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
309/// immediate in bits 0-7.
310void PIC16AsmPrinter::
311printSOImmOperand(const MachineInstr *MI, int OpNum)
312{
313 const MachineOperand &MO = MI->getOperand(OpNum);
314 assert(MO.isImmediate() && "Not a valid so_imm value!");
315 printSOImm(O, MO.getImm(), TAI);
316}
317
318
319void PIC16AsmPrinter:: printAddrModeOperand(const MachineInstr *MI, int Op)
320{
321 const MachineOperand &MO1 = MI->getOperand(Op);
322 const MachineOperand &MO2 = MI->getOperand(Op+1);
323
324 if (MO2.isFrameIndex ()) {
325 printOperand(MI, Op+1);
326 return;
327 }
328
329 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
330 printOperand(MI, Op);
331 return;
332 }
333
334 // If this is Stack Slot
335 if (MO1.isRegister()) {
336 if(strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP")==0)
337 {
338 O << CurrentFnName <<"_"<< MO2.getImm();
339 return;
340 }
341 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
342 O << "+";
343 O << MO2.getImm();
344 O << "]";
345 return;
346 }
347
348 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
349 O << "]";
350}
351
352
353void PIC16AsmPrinter:: printRegisterList(const MachineInstr *MI, int opNum)
354{
355 O << "{";
356 for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
357 printOperand(MI, i);
358 if (i != e-1) O << ", ";
359 }
360 O << "}";
361}
362
363void PIC16AsmPrinter::
364printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier)
365{
366 assert(Modifier && "This operand only works with a modifier!");
367
368 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
369 // data itself.
370 if (!strcmp(Modifier, "label")) {
371 unsigned ID = MI->getOperand(OpNo).getImm();
372 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
373 << '_' << ID << ":\n";
374 } else {
375 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
376 unsigned CPI = MI->getOperand(OpNo).getIndex();
377
378 const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
379 MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
380
381 if (MCPE.isMachineConstantPoolEntry())
382 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
383 else {
384 EmitGlobalConstant(MCPE.Val.ConstVal);
385 // remember to emit the weak reference
386 if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
387 if (GV->hasExternalWeakLinkage())
388 ExtWeakSymbols.insert(GV);
389 }
390 }
391}
392
393
394bool PIC16AsmPrinter:: doInitialization(Module &M)
395{
396 // Emit initial debug information.
397 // DW.BeginModule(&M);
398
399 bool Result = AsmPrinter::doInitialization(M);
400 return Result;
401}
402
403bool PIC16AsmPrinter:: doFinalization(Module &M)
404{
405 const TargetData *TD = TM.getTargetData();
406
407 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
408 I != E; ++I) {
409 if (!I->hasInitializer()) // External global require no code
410 continue;
411
412 if (EmitSpecialLLVMGlobal(I)) {
413 continue;
414 }
415
416 std::string name = Mang->getValueName(I);
417 Constant *C = I->getInitializer();
418 const Type *Type = C->getType();
419 unsigned Size = TD->getABITypeSize(Type);
420 unsigned Align = TD->getPreferredAlignmentLog(I);
421
422 const char *VisibilityDirective = NULL;
423 if (I->hasHiddenVisibility())
424 VisibilityDirective = TAI->getHiddenDirective();
425 else if (I->hasProtectedVisibility())
426 VisibilityDirective = TAI->getProtectedDirective();
427
428 if (VisibilityDirective)
429 O << VisibilityDirective << name << "\n";
430
431 if (C->isNullValue()) {
432 if (I->hasExternalLinkage()) {
433 if (const char *Directive = TAI->getZeroFillDirective()) {
434 O << "\t.globl\t" << name << "\n";
435 O << Directive << "__DATA__, __common, " << name << ", "
436 << Size << ", " << Align << "\n";
437 continue;
438 }
439 }
440
441 if (!I->hasSection() &&
442 (I->hasInternalLinkage() || I->hasWeakLinkage() ||
443 I->hasLinkOnceLinkage())) {
444 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
445 if (!NoZerosInBSS && TAI->getBSSSection())
446 SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
447 else
448 SwitchToDataSection(TAI->getDataSection(), I);
449 if (TAI->getLCOMMDirective() != NULL) {
450 if (I->hasInternalLinkage()) {
451 O << TAI->getLCOMMDirective() << name << "," << Size;
452 } else
453 O << TAI->getCOMMDirective() << name << "," << Size;
454 } else {
455 if (I->hasInternalLinkage())
456 O << "\t.local\t" << name << "\n";
457
458 O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " "
459 << Size;
460 O << "\n\t\tGLOBAL" <<" "<< name;
461 if (TAI->getCOMMDirectiveTakesAlignment())
462 O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
463 }
464 continue;
465 }
466 }
467
468 switch (I->getLinkage())
469 {
470 case GlobalValue::AppendingLinkage:
471 {
472 // FIXME: appending linkage variables should go into a section of
473 // their name or something. For now, just emit them as external.
474 // Fall through
475 }
476 case GlobalValue::ExternalLinkage:
477 {
478 O << "\t.globl " << name << "\n";
479 // FALL THROUGH
480 }
481 case GlobalValue::InternalLinkage:
482 {
483 if (I->isConstant()) {
484 const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
485 if (TAI->getCStringSection() && CVA && CVA->isCString()) {
486 SwitchToDataSection(TAI->getCStringSection(), I);
487 break;
488 }
489 }
490 break;
491 }
492 default:
493 {
494 assert(0 && "Unknown linkage type!");
495 break;
496 }
497 } // end switch.
498
499 EmitAlignment(Align, I);
500 O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
501 << "\n";
502
503 // If the initializer is a extern weak symbol, remember to emit the weak
504 // reference!
505 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
506 if (GV->hasExternalWeakLinkage())
507 ExtWeakSymbols.insert(GV);
508
509 EmitGlobalConstant(C);
510 O << '\n';
511 } // end for.
512
513 O << "\n "<< "END";
514 return AsmPrinter::doFinalization(M);
515}
516
517void PIC16AsmPrinter::
518SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
519{
520 O << "\n";
521 if (NewSection && *NewSection) {
522 std::string codeSection = "code_";
523 codeSection += NewSection;
524 codeSection += " ";
525 codeSection += "CODE";
526 AsmPrinter::SwitchToTextSection(codeSection.c_str(),GV);
527 }
528 else
529 AsmPrinter::SwitchToTextSection(NewSection,GV);
530}
531
532void PIC16AsmPrinter::
533SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
534{
535 //Need to append index for page
536 O << "\n";
537 if (NewSection && *NewSection) {
538 std::string dataSection ="udata_";
539 dataSection+=NewSection;
540 if (dataSection.substr(dataSection.length()-2).compare(".o") == 0) {
541 dataSection = dataSection.substr(0,dataSection.length()-2);
542 }
543 dataSection += " ";
544 dataSection += "UDATA";
545 AsmPrinter::SwitchToDataSection(dataSection.c_str(),GV);
546 }
547 else
548 AsmPrinter::SwitchToDataSection(NewSection,GV);
549}
550
551void PIC16AsmPrinter::
552SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
553{
554 O << "\n";
555 if (NewSection && *NewSection) {
556 std::string dataSection = "frame_";
557 dataSection += NewSection;
558 if (dataSection.substr(dataSection.length()-2).compare(".o") == 0) {
559 dataSection = dataSection.substr(0,dataSection.length()-2);
560 }
561 dataSection += "_";
562 dataSection += CurrentFnName;
563 dataSection += " ";
564 dataSection += "UDATA_OVR";
565 AsmPrinter::SwitchToDataSection(dataSection.c_str(),GV);
566 }
567 else
568 AsmPrinter::SwitchToDataSection(NewSection,GV);
569}