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/Statistic.h"
24 #include "llvm/ADT/StringExtras.h"
25 #include "llvm/CodeGen/AsmPrinter.h"
26 #include "llvm/CodeGen/MachineFunctionPass.h"
27 #include "llvm/CodeGen/MachineConstantPool.h"
28 #include "llvm/CodeGen/MachineFrameInfo.h"
29 #include "llvm/CodeGen/MachineInstr.h"
30 #include "llvm/Support/CommandLine.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/Mangler.h"
33 #include "llvm/Support/MathExtras.h"
34 #include "llvm/Target/TargetAsmInfo.h"
35 #include "llvm/Target/TargetData.h"
36 #include "llvm/Target/TargetMachine.h"
37 #include "llvm/Target/TargetOptions.h"
42 STATISTIC(EmittedInsts, "Number of machine instrs printed");
45 struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
46 PIC16AsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
47 : AsmPrinter(O, TM, T) {
51 /// We name each basic block in a Function with a unique number, so
52 /// that we can consistently refer to them later. This is cleared
53 /// at the beginning of each call to runOnMachineFunction().
55 typedef std::map<const Value *, unsigned> ValueMapTy;
56 ValueMapTy NumberForBB;
58 /// Keeps the set of GlobalValues that require non-lazy-pointers for
60 std::set<std::string> GVNonLazyPtrs;
62 /// Keeps the set of external function GlobalAddresses that the asm
63 /// printer should generate stubs for.
64 std::set<std::string> FnStubs;
66 /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
69 virtual const char *getPassName() const {
70 return "PIC16 Assembly Printer";
73 void printOperand(const MachineInstr *MI, int opNum,
74 const char *Modifier = 0);
76 void printSOImmOperand(const MachineInstr *MI, int opNum);
78 void printAddrModeOperand(const MachineInstr *MI, int OpNo);
80 void printRegisterList(const MachineInstr *MI, int opNum);
81 void printCPInstOperand(const MachineInstr *MI, int opNum,
82 const char *Modifier);
85 bool printInstruction(const MachineInstr *MI); // autogenerated.
86 void emitFunctionStart(MachineFunction &F);
87 bool runOnMachineFunction(MachineFunction &F);
88 bool doInitialization(Module &M);
89 bool doFinalization(Module &M);
91 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
93 void getAnalysisUsage(AnalysisUsage &AU) const;
96 void SwitchToTextSection(const char *NewSection,
97 const GlobalValue *GV = NULL);
98 void SwitchToDataSection(const char *NewSection,
99 const GlobalValue *GV = NULL);
100 void SwitchToDataOvrSection(const char *NewSection,
101 const GlobalValue *GV = NULL);
103 } // end of anonymous namespace
105 #include "PIC16GenAsmWriter.inc"
107 /// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
108 /// assembly code for a MachineFunction to the given output stream,
109 /// using the given target machine description. This should work
110 /// regardless of whether the function is in SSA form.
112 FunctionPass *llvm::createPIC16CodePrinterPass(std::ostream &o,
113 PIC16TargetMachine &tm) {
114 return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
117 void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const
119 // FIXME: Currently unimplemented.
123 void PIC16AsmPrinter ::
124 EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
126 printDataDirective(MCPV->getType());
128 PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV;
129 GlobalValue *GV = ACPV->getGV();
130 std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
132 Name += ACPV->getSymbol();
133 if (ACPV->isNonLazyPointer()) {
134 GVNonLazyPtrs.insert(Name);
135 O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
136 } else if (ACPV->isStub()) {
137 FnStubs.insert(Name);
138 O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
143 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
145 if (ACPV->getPCAdjustment() != 0) {
146 O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
147 << utostr(ACPV->getLabelId())
148 << "+" << (unsigned)ACPV->getPCAdjustment();
150 if (ACPV->mustAddCurrentAddress())
157 // If the constant pool value is a extern weak symbol, remember to emit
158 // the weak reference.
159 if (GV && GV->hasExternalWeakLinkage())
160 ExtWeakSymbols.insert(GV);
163 /// emitFunctionStart - Emit the directives used by ASM on the start of
165 void PIC16AsmPrinter::emitFunctionStart(MachineFunction &MF)
167 // Print out the label for the function.
168 const Function *F = MF.getFunction();
169 MachineFrameInfo *FrameInfo = MF.getFrameInfo();
170 if (FrameInfo->hasStackObjects()) {
171 int indexBegin = FrameInfo->getObjectIndexBegin();
172 int indexEnd = FrameInfo->getObjectIndexEnd();
173 while (indexBegin < indexEnd) {
175 SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(),
178 O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES"
179 << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ;
183 SwitchToTextSection(CurrentFnName.c_str(), F);
184 O << "_" << CurrentFnName << ":" ;
189 /// runOnMachineFunction - This uses the printInstruction()
190 /// method to print assembly for each instruction.
192 bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF)
194 SetupMachineFunction(MF);
197 // What's my mangled name?
198 CurrentFnName = Mang->getValueName(MF.getFunction());
200 // Emit the function start directives
201 emitFunctionStart(MF);
203 // Print out code for the function.
204 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
206 // Print a label for the basic block.
207 if (I != MF.begin()) {
208 printBasicBlockLabel(I, true);
211 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
213 // Print the assembly for the instruction.
215 printInstruction(II);
220 // We didn't modify anything.
224 void PIC16AsmPrinter::
225 printOperand(const MachineInstr *MI, int opNum, const char *Modifier)
227 const MachineOperand &MO = MI->getOperand(opNum);
228 const TargetRegisterInfo &RI = *TM.getRegisterInfo();
230 switch (MO.getType()) {
231 case MachineOperand::MO_Register:
232 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
233 O << RI.get(MO.getReg()).Name;
235 assert(0 && "not implemented");
238 case MachineOperand::MO_Immediate:
239 if (!Modifier || strcmp(Modifier, "no_hash") != 0)
241 O << (int)MO.getImm();
244 case MachineOperand::MO_MachineBasicBlock:
245 printBasicBlockLabel(MO.getMBB());
248 case MachineOperand::MO_GlobalAddress:
249 O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
252 case MachineOperand::MO_ExternalSymbol:
253 O << MO.getSymbolName();
256 case MachineOperand::MO_ConstantPoolIndex:
257 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
258 << '_' << MO.getIndex();
261 case MachineOperand::MO_FrameIndex:
262 O << "_" << CurrentFnName
263 << '+' << MO.getIndex();
266 case MachineOperand::MO_JumpTableIndex:
267 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
268 << '_' << MO.getIndex();
272 O << "<unknown operand type>"; abort ();
278 printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI)
280 assert(V < (1 << 12) && "Not a valid so_imm value!");
285 /// printSOImmOperand - SOImm is 4-bit rotated amount in bits 8-11 with 8-bit
286 /// immediate in bits 0-7.
287 void PIC16AsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum)
289 const MachineOperand &MO = MI->getOperand(OpNum);
290 assert(MO.isImmediate() && "Not a valid so_imm value!");
291 printSOImm(O, MO.getImm(), TAI);
295 void PIC16AsmPrinter::printAddrModeOperand(const MachineInstr *MI, int Op)
297 const MachineOperand &MO1 = MI->getOperand(Op);
298 const MachineOperand &MO2 = MI->getOperand(Op+1);
300 if (MO2.isFrameIndex ()) {
301 printOperand(MI, Op+1);
305 if (!MO1.isRegister()) {
306 // FIXME: This is for CP entries, but isn't right.
307 printOperand(MI, Op);
311 // If this is Stack Slot
312 if (MO1.isRegister()) {
313 if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) {
314 O << CurrentFnName <<"_"<< MO2.getImm();
317 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
324 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
329 void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum)
332 for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
334 if (i != e-1) O << ", ";
339 void PIC16AsmPrinter::
340 printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier)
342 assert(Modifier && "This operand only works with a modifier!");
344 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
346 if (!strcmp(Modifier, "label")) {
347 unsigned ID = MI->getOperand(OpNo).getImm();
348 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
349 << '_' << ID << ":\n";
351 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
352 unsigned CPI = MI->getOperand(OpNo).getIndex();
354 const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
355 MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
357 if (MCPE.isMachineConstantPoolEntry())
358 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
360 EmitGlobalConstant(MCPE.Val.ConstVal);
361 // remember to emit the weak reference
362 if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
363 if (GV->hasExternalWeakLinkage())
364 ExtWeakSymbols.insert(GV);
370 bool PIC16AsmPrinter::doInitialization(Module &M)
372 bool Result = AsmPrinter::doInitialization(M);
376 bool PIC16AsmPrinter::doFinalization(Module &M)
378 const TargetData *TD = TM.getTargetData();
380 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
382 if (!I->hasInitializer()) // External global require no code
385 if (EmitSpecialLLVMGlobal(I)) {
389 std::string name = Mang->getValueName(I);
390 Constant *C = I->getInitializer();
391 const Type *Ty = C->getType();
392 unsigned Size = TD->getABITypeSize(Ty);
393 unsigned Align = TD->getPreferredAlignmentLog(I);
395 const char *VisibilityDirective = NULL;
396 if (I->hasHiddenVisibility())
397 VisibilityDirective = TAI->getHiddenDirective();
398 else if (I->hasProtectedVisibility())
399 VisibilityDirective = TAI->getProtectedDirective();
401 if (VisibilityDirective)
402 O << VisibilityDirective << name << "\n";
404 if (C->isNullValue()) {
405 if (I->hasExternalLinkage()) {
406 if (const char *Directive = TAI->getZeroFillDirective()) {
407 O << "\t.globl\t" << name << "\n";
408 O << Directive << "__DATA__, __common, " << name << ", "
409 << Size << ", " << Align << "\n";
414 if (!I->hasSection() &&
415 (I->hasInternalLinkage() || I->hasWeakLinkage() ||
416 I->hasLinkOnceLinkage() || I->hasCommonLinkage())) {
417 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
418 if (!NoZerosInBSS && TAI->getBSSSection())
419 SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
421 SwitchToDataSection(TAI->getDataSection(), I);
422 if (TAI->getLCOMMDirective() != NULL) {
423 if (I->hasInternalLinkage()) {
424 O << TAI->getLCOMMDirective() << name << "," << Size;
426 O << TAI->getCOMMDirective() << name << "," << Size;
428 if (I->hasInternalLinkage())
429 O << "\t.local\t" << name << "\n";
431 O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " "
433 O << "\n\t\tGLOBAL" <<" "<< name;
434 if (TAI->getCOMMDirectiveTakesAlignment())
435 O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
441 switch (I->getLinkage()) {
442 case GlobalValue::AppendingLinkage:
443 // FIXME: appending linkage variables should go into a section of
444 // their name or something. For now, just emit them as external.
447 case GlobalValue::ExternalLinkage:
448 O << "\t.globl " << name << "\n";
451 case GlobalValue::InternalLinkage:
452 if (I->isConstant()) {
453 const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
454 if (TAI->getCStringSection() && CVA && CVA->isCString()) {
455 SwitchToDataSection(TAI->getCStringSection(), I);
462 assert(0 && "Unknown linkage type!");
466 EmitAlignment(Align, I);
467 O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
470 // If the initializer is a extern weak symbol, remember to emit the weak
472 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
473 if (GV->hasExternalWeakLinkage())
474 ExtWeakSymbols.insert(GV);
476 EmitGlobalConstant(C);
481 return AsmPrinter::doFinalization(M);
484 void PIC16AsmPrinter::
485 SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
488 if (NewSection && *NewSection) {
489 std::string codeSection = "code_";
490 codeSection += NewSection;
492 codeSection += "CODE";
493 AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV);
496 AsmPrinter::SwitchToTextSection(NewSection, GV);
499 void PIC16AsmPrinter::
500 SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
502 // Need to append index for page.
504 if (NewSection && *NewSection) {
505 std::string dataSection = "udata_";
506 dataSection += NewSection;
507 if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
508 dataSection = dataSection.substr(0, dataSection.length() - 2);
511 dataSection += "UDATA";
512 AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
515 AsmPrinter::SwitchToDataSection(NewSection, GV);
518 void PIC16AsmPrinter::
519 SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
522 if (NewSection && *NewSection) {
523 std::string dataSection = "frame_";
524 dataSection += NewSection;
525 if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
526 dataSection = dataSection.substr(0, dataSection.length() - 2);
529 dataSection += CurrentFnName;
531 dataSection += "UDATA_OVR";
532 AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
535 AsmPrinter::SwitchToDataSection(NewSection, GV);