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 #include "PIC16AsmPrinter.h"
16 #include "PIC16TargetAsmInfo.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Function.h"
19 #include "llvm/Module.h"
20 #include "llvm/CodeGen/DwarfWriter.h"
21 #include "llvm/CodeGen/MachineFrameInfo.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include "llvm/Support/Mangler.h"
24 #include "llvm/CodeGen/DwarfWriter.h"
25 #include "llvm/CodeGen/MachineModuleInfo.h"
29 #include "PIC16GenAsmWriter.inc"
31 bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
36 /// runOnMachineFunction - This uses the printInstruction()
37 /// method to print assembly for each instruction.
39 bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
42 // This calls the base class function required to be called at beginning
43 // of runOnMachineFunction.
44 SetupMachineFunction(MF);
46 // Get the mangled name.
47 const Function *F = MF.getFunction();
48 CurrentFnName = Mang->getValueName(F);
50 // Emit the function variables.
52 const char *codeSection = PAN::getCodeSectionName(CurrentFnName).c_str();
54 const Section *fCodeSection = TAI->getNamedSection(codeSection,
57 // Start the Code Section.
58 SwitchToSection (fCodeSection);
60 // Emit the frame address of the function at the beginning of code.
61 O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
62 O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
64 // Emit function start label.
65 O << CurrentFnName << ":\n";
67 // Print out code for the function.
68 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
70 // Print a label for the basic block.
71 if (I != MF.begin()) {
72 printBasicBlockLabel(I, true);
76 // For emitting line directives, we need to keep track of the current
77 // source line. When it changes then only emit the line directive.
79 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
81 // Emit the line directive if source line changed.
82 const DebugLoc DL = II->getDebugLoc();
83 if (!DL.isUnknown()) {
84 unsigned line = MF.getDebugLocTuple(DL).Line;
85 if (line != CurLine) {
86 O << "\t.line " << line << "\n";
91 // Print the assembly for the instruction.
92 printMachineInstruction(II);
95 return false; // we didn't modify anything.
98 /// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
99 /// assembly code for a MachineFunction to the given output stream,
100 /// using the given target machine description. This should work
101 /// regardless of whether the function is in SSA form.
103 FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
104 PIC16TargetMachine &tm,
105 CodeGenOpt::Level OptLevel,
107 return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
111 // printOperand - print operand of insn.
112 void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
113 const MachineOperand &MO = MI->getOperand(opNum);
115 switch (MO.getType()) {
116 case MachineOperand::MO_Register:
117 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
118 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
120 assert(0 && "not implemented");
123 case MachineOperand::MO_Immediate:
124 O << (int)MO.getImm();
127 case MachineOperand::MO_GlobalAddress: {
128 O << Mang->getValueName(MO.getGlobal());
131 case MachineOperand::MO_ExternalSymbol: {
132 const char *Sname = MO.getSymbolName();
134 // If its a libcall name, record it to decls section.
135 if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) {
136 Decls.push_back(Sname);
142 case MachineOperand::MO_MachineBasicBlock:
143 printBasicBlockLabel(MO.getMBB());
147 assert(0 && " Operand type not supported.");
151 void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
152 int CC = (int)MI->getOperand(opNum).getImm();
153 O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
156 void PIC16AsmPrinter::printDecls(void) {
157 // If no libcalls used, return.
158 if (Decls.empty()) return;
160 O << TAI->getCommentString() << "External decls for libcalls - BEGIN." <<"\n";
161 // Remove duplicate entries.
164 for (std::list<const char*>::const_iterator I = Decls.begin();
165 I != Decls.end(); I++) {
166 O << TAI->getExternDirective() << *I << "\n";
167 O << TAI->getExternDirective() << PAN::getArgsLabel(*I) << "\n";
168 O << TAI->getExternDirective() << PAN::getRetvalLabel(*I) << "\n";
170 O << TAI->getCommentString() << "External decls for libcalls - END." <<"\n";
173 bool PIC16AsmPrinter::doInitialization (Module &M) {
174 bool Result = AsmPrinter::doInitialization(M);
175 // FIXME:: This is temporary solution to generate the include file.
176 // The processor should be passed to llc as in input and the header file
177 // should be generated accordingly.
178 O << "\t#include P16F1937.INC\n";
179 MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
181 DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
182 assert(DW && "Dwarf Writer is not available");
183 DW->BeginModule(&M, MMI, O, this, TAI);
185 // Set the section names for all globals.
186 for (Module::global_iterator I = M.global_begin(), E = M.global_end();
188 I->setSection(TAI->SectionForGlobal(I)->getName());
191 EmitExternsAndGlobals (M);
199 void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
200 // Emit declarations for external functions.
201 O << TAI->getCommentString() << "External defs and decls - BEGIN." <<"\n";
202 for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
203 std::string Name = Mang->getValueName(I);
204 if (Name.compare("@abort") == 0)
207 // If it is llvm intrinsic call then don't emit
208 if (Name.find("llvm.") != std::string::npos)
211 if (! (I->isDeclaration() || I->hasExternalLinkage()))
214 const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
215 TAI->getGlobalDirective();
217 O << directive << Name << "\n";
218 O << directive << PAN::getRetvalLabel(Name) << "\n";
219 O << directive << PAN::getArgsLabel(Name) << "\n";
222 // Emit header file to include declaration of library functions
223 // FIXME: find out libcall names.
224 // O << "\t#include C16IntrinsicCalls.INC\n";
226 // Emit declarations for external variable declarations and definitions.
227 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
229 // Any variables reaching here with ".auto." in its name is a local scope
230 // variable and should not be printed in global data section.
231 std::string Name = Mang->getValueName(I);
232 if (PAN::isLocalName(Name))
235 if (!(I->isDeclaration() || I->hasExternalLinkage() ||
236 I->hasCommonLinkage()))
239 const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
240 TAI->getGlobalDirective();
241 O << directive << Name << "\n";
243 O << TAI->getCommentString() << "External defs and decls - END." <<"\n";
246 void PIC16AsmPrinter::EmitRomData (Module &M)
248 const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
250 std::vector<const GlobalVariable*> Items = PTAI->ROSection->Items;
251 if (! Items.size()) return;
253 // Print ROData ection.
255 SwitchToSection(PTAI->ROSection->S_);
256 for (unsigned j = 0; j < Items.size(); j++) {
257 O << Mang->getValueName(Items[j]);
258 Constant *C = Items[j]->getInitializer();
259 int AddrSpace = Items[j]->getType()->getAddressSpace();
260 EmitGlobalConstant(C, AddrSpace);
264 bool PIC16AsmPrinter::doFinalization(Module &M) {
266 O << "\t" << "END\n";
267 bool Result = AsmPrinter::doFinalization(M);
271 void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
272 const Function *F = MF.getFunction();
273 std::string FuncName = Mang->getValueName(F);
274 const TargetData *TD = TM.getTargetData();
275 // Emit the data section name.
277 const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str();
279 const Section *fPDataSection = TAI->getNamedSection(SectionName,
280 SectionFlags::Writeable);
281 SwitchToSection(fPDataSection);
283 // Emit function frame label
284 O << PAN::getFrameLabel(CurrentFnName) << ":\n";
286 const Type *RetType = F->getReturnType();
287 unsigned RetSize = 0;
288 if (RetType->getTypeID() != Type::VoidTyID)
289 RetSize = TD->getTypeAllocSize(RetType);
291 //Emit function return value space
292 // FIXME: Do not emit RetvalLable when retsize is zero. To do this
293 // we will need to avoid printing a global directive for Retval label
294 // in emitExternandGloblas.
296 O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n";
298 O << PAN::getRetvalLabel(CurrentFnName) << ": \n";
300 // Emit variable to hold the space for function arguments
301 unsigned ArgSize = 0;
302 for (Function::const_arg_iterator argi = F->arg_begin(),
303 arge = F->arg_end(); argi != arge ; ++argi) {
304 const Type *Ty = argi->getType();
305 ArgSize += TD->getTypeAllocSize(Ty);
308 O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n";
310 // Emit temporary space
311 int TempSize = PTLI->GetTmpSize();
313 O << PAN::getTempdataLabel(CurrentFnName) << " RES " << TempSize <<"\n";
316 void PIC16AsmPrinter::EmitIData (Module &M) {
317 const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
319 // Print all IDATA sections.
320 std::vector <PIC16Section *>IDATASections = PTAI->IDATASections;
321 for (unsigned i = 0; i < IDATASections.size(); i++) {
323 SwitchToSection(IDATASections[i]->S_);
324 std::vector<const GlobalVariable*> Items = IDATASections[i]->Items;
325 for (unsigned j = 0; j < Items.size(); j++) {
326 std::string Name = Mang->getValueName(Items[j]);
327 Constant *C = Items[j]->getInitializer();
328 int AddrSpace = Items[j]->getType()->getAddressSpace();
330 EmitGlobalConstant(C, AddrSpace);
335 void PIC16AsmPrinter::EmitUData (Module &M) {
336 const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
337 const TargetData *TD = TM.getTargetData();
339 // Print all BSS sections.
340 std::vector <PIC16Section *>BSSSections = PTAI->BSSSections;
341 for (unsigned i = 0; i < BSSSections.size(); i++) {
343 SwitchToSection(BSSSections[i]->S_);
344 std::vector<const GlobalVariable*> Items = BSSSections[i]->Items;
345 for (unsigned j = 0; j < Items.size(); j++) {
346 std::string Name = Mang->getValueName(Items[j]);
347 Constant *C = Items[j]->getInitializer();
348 const Type *Ty = C->getType();
349 unsigned Size = TD->getTypeAllocSize(Ty);
351 O << Name << " " <<"RES"<< " " << Size ;
357 void PIC16AsmPrinter::EmitAutos (Module &M)
359 // Section names for all globals are already set.
361 const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
362 const TargetData *TD = TM.getTargetData();
364 // Now print all Autos sections.
365 std::vector <PIC16Section *>AutosSections = PTAI->AutosSections;
366 for (unsigned i = 0; i < AutosSections.size(); i++) {
368 SwitchToSection(AutosSections[i]->S_);
369 std::vector<const GlobalVariable*> Items = AutosSections[i]->Items;
370 for (unsigned j = 0; j < Items.size(); j++) {
371 std::string VarName = Mang->getValueName(Items[j]);
372 Constant *C = Items[j]->getInitializer();
373 const Type *Ty = C->getType();
374 unsigned Size = TD->getTypeAllocSize(Ty);
375 // Emit memory reserve directive.
376 O << VarName << " RES " << Size << "\n";