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/Support/raw_ostream.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(raw_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(raw_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(raw_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.isImm() && "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);
302 printOperand(MI, Op+1);
307 // FIXME: This is for CP entries, but isn't right.
308 printOperand(MI, Op);
312 // If this is Stack Slot
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 SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
420 if (TAI->getLCOMMDirective() != NULL) {
421 if (I->hasInternalLinkage()) {
422 O << TAI->getLCOMMDirective() << name << "," << Size;
424 O << TAI->getCOMMDirective() << name << "," << Size;
426 if (I->hasInternalLinkage())
427 O << "\t.local\t" << name << "\n";
429 O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " "
431 O << "\n\t\tGLOBAL" <<" "<< name;
432 if (TAI->getCOMMDirectiveTakesAlignment())
433 O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
439 switch (I->getLinkage()) {
440 case GlobalValue::AppendingLinkage:
441 // FIXME: appending linkage variables should go into a section of
442 // their name or something. For now, just emit them as external.
445 case GlobalValue::ExternalLinkage:
446 O << "\t.globl " << name << "\n";
449 case GlobalValue::InternalLinkage:
453 assert(0 && "Unknown linkage type!");
457 EmitAlignment(Align, I);
458 O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
461 // If the initializer is a extern weak symbol, remember to emit the weak
463 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
464 if (GV->hasExternalWeakLinkage())
465 ExtWeakSymbols.insert(GV);
467 EmitGlobalConstant(C);
472 return AsmPrinter::doFinalization(M);
475 void PIC16AsmPrinter::
476 SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
479 if (NewSection && *NewSection) {
480 std::string codeSection = "code_";
481 codeSection += NewSection;
483 codeSection += "CODE";
484 AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV);
487 AsmPrinter::SwitchToTextSection(NewSection, GV);
490 void PIC16AsmPrinter::
491 SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
493 // Need to append index for page.
495 if (NewSection && *NewSection) {
496 std::string dataSection = "udata_";
497 dataSection += NewSection;
498 if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
499 dataSection = dataSection.substr(0, dataSection.length() - 2);
502 dataSection += "UDATA";
503 AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
506 AsmPrinter::SwitchToDataSection(NewSection, GV);
509 void PIC16AsmPrinter::
510 SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
513 if (NewSection && *NewSection) {
514 std::string dataSection = "frame_";
515 dataSection += NewSection;
516 if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
517 dataSection = dataSection.substr(0, dataSection.length() - 2);
520 dataSection += CurrentFnName;
522 dataSection += "UDATA_OVR";
523 AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
526 AsmPrinter::SwitchToDataSection(NewSection, GV);