1 //===-- PIC16AsmPrinter.cpp - PIC16 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 PIC16 assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "asm-printer"
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"
43 STATISTIC(EmittedInsts, "Number of machine instrs printed");
46 struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
47 PIC16AsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
48 : AsmPrinter(O, TM, T) {
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().
56 typedef std::map<const Value *, unsigned> ValueMapTy;
57 ValueMapTy NumberForBB;
59 /// Keeps the set of GlobalValues that require non-lazy-pointers for
61 std::set<std::string> GVNonLazyPtrs;
63 /// Keeps the set of external function GlobalAddresses that the asm
64 /// printer should generate stubs for.
65 std::set<std::string> FnStubs;
67 /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
70 virtual const char *getPassName() const {
71 return "PIC16 Assembly Printer";
74 void printOperand(const MachineInstr *MI, int opNum,
75 const char *Modifier = 0);
77 void printSOImmOperand(const MachineInstr *MI, int opNum);
79 void printAddrModeOperand(const MachineInstr *MI, int OpNo);
81 void printRegisterList(const MachineInstr *MI, int opNum);
82 void printCPInstOperand(const MachineInstr *MI, int opNum,
83 const char *Modifier);
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);
92 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
94 void getAnalysisUsage(AnalysisUsage &AU) const;
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);
104 } // end of anonymous namespace
106 #include "PIC16GenAsmWriter.inc"
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.
113 FunctionPass *llvm::createPIC16CodePrinterPass(std::ostream &o,
114 PIC16TargetMachine &tm) {
115 return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
118 void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const
120 // FIXME: Currently unimplemented.
124 void PIC16AsmPrinter ::
125 EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
127 printDataDirective(MCPV->getType());
129 PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV;
130 GlobalValue *GV = ACPV->getGV();
131 std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
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";
144 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
146 if (ACPV->getPCAdjustment() != 0) {
147 O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
148 << utostr(ACPV->getLabelId())
149 << "+" << (unsigned)ACPV->getPCAdjustment();
151 if (ACPV->mustAddCurrentAddress())
158 // If the constant pool value is a extern weak symbol, remember to emit
159 // the weak reference.
160 if (GV && GV->hasExternalWeakLinkage())
161 ExtWeakSymbols.insert(GV);
164 /// emitFunctionStart - Emit the directives used by ASM on the start of
166 void PIC16AsmPrinter::emitFunctionStart(MachineFunction &MF)
168 // Print out the label for the function.
169 const Function *F = MF.getFunction();
170 MachineFrameInfo *FrameInfo = MF.getFrameInfo();
171 if (FrameInfo->hasStackObjects()) {
172 int indexBegin = FrameInfo->getObjectIndexBegin();
173 int indexEnd = FrameInfo->getObjectIndexEnd();
174 while (indexBegin < indexEnd) {
176 SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(),
179 O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES"
180 << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ;
184 SwitchToTextSection(CurrentFnName.c_str(), F);
185 O << "_" << CurrentFnName << ":" ;
190 /// runOnMachineFunction - This uses the printInstruction()
191 /// method to print assembly for each instruction.
193 bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF)
195 SetupMachineFunction(MF);
198 // What's my mangled name?
199 CurrentFnName = Mang->getValueName(MF.getFunction());
201 // Emit the function start directives
202 emitFunctionStart(MF);
204 // Print out code for the function.
205 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
207 // Print a label for the basic block.
208 if (I != MF.begin()) {
209 printBasicBlockLabel(I, true);
212 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
214 // Print the assembly for the instruction.
216 printInstruction(II);
221 // We didn't modify anything.
225 void PIC16AsmPrinter::
226 printOperand(const MachineInstr *MI, int opNum, const char *Modifier)
228 const MachineOperand &MO = MI->getOperand(opNum);
229 const TargetRegisterInfo &RI = *TM.getRegisterInfo();
231 switch (MO.getType()) {
232 case MachineOperand::MO_Register:
233 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
234 O << RI.get(MO.getReg()).Name;
236 assert(0 && "not implemented");
239 case MachineOperand::MO_Immediate:
240 if (!Modifier || strcmp(Modifier, "no_hash") != 0)
242 O << (int)MO.getImm();
245 case MachineOperand::MO_MachineBasicBlock:
246 printBasicBlockLabel(MO.getMBB());
249 case MachineOperand::MO_GlobalAddress:
250 O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
253 case MachineOperand::MO_ExternalSymbol:
254 O << MO.getSymbolName();
257 case MachineOperand::MO_ConstantPoolIndex:
258 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
259 << '_' << MO.getIndex();
262 case MachineOperand::MO_FrameIndex:
263 O << "_" << CurrentFnName
264 << '+' << MO.getIndex();
267 case MachineOperand::MO_JumpTableIndex:
268 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
269 << '_' << MO.getIndex();
273 O << "<unknown operand type>"; abort ();
279 printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI)
281 assert(V < (1 << 12) && "Not a valid so_imm value!");
286 /// printSOImmOperand - SOImm is 4-bit rotated amount in bits 8-11 with 8-bit
287 /// immediate in bits 0-7.
288 void PIC16AsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum)
290 const MachineOperand &MO = MI->getOperand(OpNum);
291 assert(MO.isImmediate() && "Not a valid so_imm value!");
292 printSOImm(O, MO.getImm(), TAI);
296 void PIC16AsmPrinter::printAddrModeOperand(const MachineInstr *MI, int Op)
298 const MachineOperand &MO1 = MI->getOperand(Op);
299 const MachineOperand &MO2 = MI->getOperand(Op+1);
301 if (MO2.isFrameIndex ()) {
302 printOperand(MI, Op+1);
306 if (!MO1.isRegister()) {
307 // FIXME: This is for CP entries, but isn't right.
308 printOperand(MI, Op);
312 // If this is Stack Slot
313 if (MO1.isRegister()) {
314 if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) {
315 O << CurrentFnName <<"_"<< MO2.getImm();
318 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
325 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
330 void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum)
333 for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
335 if (i != e-1) O << ", ";
340 void PIC16AsmPrinter::
341 printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier)
343 assert(Modifier && "This operand only works with a modifier!");
345 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
347 if (!strcmp(Modifier, "label")) {
348 unsigned ID = MI->getOperand(OpNo).getImm();
349 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
350 << '_' << ID << ":\n";
352 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
353 unsigned CPI = MI->getOperand(OpNo).getIndex();
355 const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
356 MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
358 if (MCPE.isMachineConstantPoolEntry())
359 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
361 EmitGlobalConstant(MCPE.Val.ConstVal);
362 // remember to emit the weak reference
363 if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
364 if (GV->hasExternalWeakLinkage())
365 ExtWeakSymbols.insert(GV);
371 bool PIC16AsmPrinter::doInitialization(Module &M)
373 bool Result = AsmPrinter::doInitialization(M);
377 bool PIC16AsmPrinter::doFinalization(Module &M)
379 const TargetData *TD = TM.getTargetData();
381 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
383 if (!I->hasInitializer()) // External global require no code
386 if (EmitSpecialLLVMGlobal(I)) {
390 std::string name = Mang->getValueName(I);
391 Constant *C = I->getInitializer();
392 const Type *Ty = C->getType();
393 unsigned Size = TD->getABITypeSize(Ty);
394 unsigned Align = TD->getPreferredAlignmentLog(I);
396 const char *VisibilityDirective = NULL;
397 if (I->hasHiddenVisibility())
398 VisibilityDirective = TAI->getHiddenDirective();
399 else if (I->hasProtectedVisibility())
400 VisibilityDirective = TAI->getProtectedDirective();
402 if (VisibilityDirective)
403 O << VisibilityDirective << name << "\n";
405 if (C->isNullValue()) {
406 if (I->hasExternalLinkage()) {
407 if (const char *Directive = TAI->getZeroFillDirective()) {
408 O << "\t.globl\t" << name << "\n";
409 O << Directive << "__DATA__, __common, " << name << ", "
410 << Size << ", " << Align << "\n";
415 if (!I->hasSection() &&
416 (I->hasInternalLinkage() || I->hasWeakLinkage() ||
417 I->hasLinkOnceLinkage() || I->hasCommonLinkage())) {
418 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
419 if (!NoZerosInBSS && TAI->getBSSSection())
420 SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
422 SwitchToDataSection(TAI->getDataSection(), I);
423 if (TAI->getLCOMMDirective() != NULL) {
424 if (I->hasInternalLinkage()) {
425 O << TAI->getLCOMMDirective() << name << "," << Size;
427 O << TAI->getCOMMDirective() << name << "," << Size;
429 if (I->hasInternalLinkage())
430 O << "\t.local\t" << name << "\n";
432 O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " "
434 O << "\n\t\tGLOBAL" <<" "<< name;
435 if (TAI->getCOMMDirectiveTakesAlignment())
436 O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
442 switch (I->getLinkage()) {
443 case GlobalValue::AppendingLinkage:
444 // FIXME: appending linkage variables should go into a section of
445 // their name or something. For now, just emit them as external.
448 case GlobalValue::ExternalLinkage:
449 O << "\t.globl " << name << "\n";
452 case GlobalValue::InternalLinkage:
453 if (I->isConstant()) {
454 const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
455 if (TAI->getCStringSection() && CVA && CVA->isCString()) {
456 SwitchToDataSection(TAI->getCStringSection(), I);
463 assert(0 && "Unknown linkage type!");
467 EmitAlignment(Align, I);
468 O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
471 // If the initializer is a extern weak symbol, remember to emit the weak
473 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
474 if (GV->hasExternalWeakLinkage())
475 ExtWeakSymbols.insert(GV);
477 EmitGlobalConstant(C);
482 return AsmPrinter::doFinalization(M);
485 void PIC16AsmPrinter::
486 SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
489 if (NewSection && *NewSection) {
490 std::string codeSection = "code_";
491 codeSection += NewSection;
493 codeSection += "CODE";
494 AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV);
497 AsmPrinter::SwitchToTextSection(NewSection, GV);
500 void PIC16AsmPrinter::
501 SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
503 // Need to append index for page.
505 if (NewSection && *NewSection) {
506 std::string dataSection = "udata_";
507 dataSection += NewSection;
508 if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
509 dataSection = dataSection.substr(0, dataSection.length() - 2);
512 dataSection += "UDATA";
513 AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
516 AsmPrinter::SwitchToDataSection(NewSection, GV);
519 void PIC16AsmPrinter::
520 SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
523 if (NewSection && *NewSection) {
524 std::string dataSection = "frame_";
525 dataSection += NewSection;
526 if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
527 dataSection = dataSection.substr(0, dataSection.length() - 2);
530 dataSection += CurrentFnName;
532 dataSection += "UDATA_OVR";
533 AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
536 AsmPrinter::SwitchToDataSection(NewSection, GV);