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/Support/raw_ostream.h"
18 #include "llvm/Support/Mangler.h"
19 #include "llvm/Function.h"
20 #include "llvm/Module.h"
21 #include "llvm/CodeGen/MachineFrameInfo.h"
22 #include "llvm/DerivedTypes.h"
26 #include "PIC16GenAsmWriter.inc"
28 bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
29 std::string NewBankselLabel;
30 unsigned Operands = MI->getNumOperands();
32 // Global address or external symbol should be second operand from last
33 // if we want to print banksel for it.
34 const MachineOperand &Op = MI->getOperand(Operands-2);
35 unsigned OpType = Op.getType();
36 if (OpType == MachineOperand::MO_GlobalAddress ||
37 OpType == MachineOperand::MO_ExternalSymbol) {
38 if (OpType == MachineOperand::MO_GlobalAddress )
39 NewBankselLabel = Mang->getValueName(Op.getGlobal());
41 NewBankselLabel = Op.getSymbolName();
43 // Operand after global address or external symbol should be banksel.
44 // Value 1 for this operand means we need to generate banksel else do not
46 const MachineOperand &BS = MI->getOperand(Operands-1);
47 if (((int)BS.getImm() == 1) &&
48 (strcmp (CurrentBankselLabelInBasicBlock.c_str(),
49 NewBankselLabel.c_str()))) {
50 CurrentBankselLabelInBasicBlock = NewBankselLabel;
52 printOperand(MI, Operands-2);
61 /// runOnMachineFunction - This uses the printInstruction()
62 /// method to print assembly for each instruction.
64 bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
65 // This calls the base class function required to be called at beginning
66 // of runOnMachineFunction.
67 SetupMachineFunction(MF);
69 // Get the mangled name.
70 const Function *F = MF.getFunction();
71 CurrentFnName = Mang->getValueName(F);
73 // Emit the function variables.
75 std::string codeSection;
76 codeSection = "code." + CurrentFnName + ".#";
78 SwitchToTextSection (codeSection.c_str(),F);
80 // Print out code for the function.
81 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
83 // Print a label for the basic block.
84 if (I != MF.begin()) {
85 printBasicBlockLabel(I, true);
89 O << CurrentFnName << ":\n";
90 CurrentBankselLabelInBasicBlock = "";
91 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
93 // Print the assembly for the instruction.
94 printMachineInstruction(II);
97 return false; // we didn't modify anything.
100 /// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
101 /// assembly code for a MachineFunction to the given output stream,
102 /// using the given target machine description. This should work
103 /// regardless of whether the function is in SSA form.
105 FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
106 PIC16TargetMachine &tm) {
107 return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
110 void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
111 const MachineOperand &MO = MI->getOperand(opNum);
113 switch (MO.getType()) {
114 case MachineOperand::MO_Register:
115 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
116 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
118 assert(0 && "not implemented");
121 case MachineOperand::MO_Immediate:
122 O << (int)MO.getImm();
125 case MachineOperand::MO_GlobalAddress:
126 O << Mang->getValueName(MO.getGlobal());
129 case MachineOperand::MO_ExternalSymbol:
130 O << MO.getSymbolName();
134 assert(0 && " Operand type not supported.");
138 bool PIC16AsmPrinter::doInitialization (Module &M) {
139 bool Result = AsmPrinter::doInitialization(M);
140 // FIXME:: This is temporary solution to generate the include file.
141 // The processor should be passed to llc as in input and the header file
142 // should be generated accordingly.
143 O << "\t#include P16F1937.INC\n";
144 EmitExternsAndGlobals (M);
151 void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
152 // Emit declarations for external functions.
153 O << "section.0" <<"\n";
154 for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
155 std::string Name = Mang->getValueName(I);
156 if (Name.compare("abort") == 0)
158 if (I->isDeclaration()) {
159 O << "\textern " <<Name << "\n";
160 O << "\textern " << Name << ".retval\n";
161 O << "\textern " << Name << ".args\n";
163 else if (I->hasExternalLinkage()) {
164 O << "\tglobal " << Name << "\n";
165 O << "\tglobal " << Name << ".retval\n";
166 O << "\tglobal " << Name << ".args\n";
169 // Emit declarations for external globals.
170 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
172 std::string Name = Mang->getValueName(I);
173 if (I->isDeclaration())
174 O << "\textern "<< Name << "\n";
175 else if (I->getLinkage() == GlobalValue::CommonLinkage)
176 O << "\tglobal "<< Name << "\n";
179 void PIC16AsmPrinter::EmitInitData (Module &M) {
180 std::string iDataSection = "idata.#";
181 SwitchToDataSection(iDataSection.c_str());
182 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
184 if (!I->hasInitializer()) // External global require no code.
187 Constant *C = I->getInitializer();
188 const PointerType *PtrTy = I->getType();
189 int AddrSpace = PtrTy->getAddressSpace();
191 if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
193 if (EmitSpecialLLVMGlobal(I))
196 // Any variables reaching here with "." in its name is a local scope
197 // variable and should not be printed in global data section.
198 std::string name = Mang->getValueName(I);
199 if (name.find(".") != std::string::npos)
203 EmitGlobalConstant(C);
208 void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) {
209 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
210 unsigned BitWidth = CI->getBitWidth();
211 int Val = CI->getZExtValue();
213 // Expecting db directive here. In case of romdata we need to pad the
219 else if (BitWidth == 16) {
220 unsigned Element1, Element2;
221 Element1 = 0x00ff & Val;
222 Element2 = 0x00ff & (Val >> 8);
224 O << 0 <<", "<<Element1 <<", "<< 0 <<", "<< Element2;
226 O << Element1 <<", "<< Element2;
228 else if (BitWidth == 32) {
229 unsigned Element1, Element2, Element3, Element4;
230 Element1 = 0x00ff & Val;
231 Element2 = 0x00ff & (Val >> 8);
232 Element3 = 0x00ff & (Val >> 16);
233 Element4 = 0x00ff & (Val >> 24);
235 O << 0 <<", "<< Element1 <<", "<< 0 <<", "<< Element2 <<", "<< 0
236 <<", "<< Element3 <<", "<< 0 <<", "<< Element4;
238 O << Element1 <<", "<< Element2 <<", "<< Element3 <<", "<< Element4;
242 AsmPrinter::EmitConstantValueOnly(CV);
245 void PIC16AsmPrinter::EmitRomData (Module &M)
247 std::string romDataSection = "romdata.#";
248 SwitchToRomDataSection(romDataSection.c_str());
250 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
252 if (!I->hasInitializer()) // External global require no code.
255 Constant *C = I->getInitializer();
256 const PointerType *PtrTy = I->getType();
257 int AddrSpace = PtrTy->getAddressSpace();
258 if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_SPACE)) {
260 if (EmitSpecialLLVMGlobal(I))
263 // Any variables reaching here with "." in its name is a local scope
264 // variable and should not be printed in global data section.
265 std::string name = Mang->getValueName(I);
266 if (name.find(".") != std::string::npos)
270 EmitGlobalConstant(C);
278 void PIC16AsmPrinter::EmitUnInitData (Module &M)
280 std::string uDataSection = "udata.#";
281 SwitchToUDataSection(uDataSection.c_str());
282 const TargetData *TD = TM.getTargetData();
284 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
286 if (!I->hasInitializer()) // External global require no code.
289 Constant *C = I->getInitializer();
290 if (C->isNullValue()) {
292 if (EmitSpecialLLVMGlobal(I))
295 // Any variables reaching here with "." in its name is a local scope
296 // variable and should not be printed in global data section.
297 std::string name = Mang->getValueName(I);
298 if (name.find(".") != std::string::npos)
301 const Type *Ty = C->getType();
302 unsigned Size = TD->getTypePaddedSize(Ty);
303 O << name << " " <<"RES"<< " " << Size ;
309 bool PIC16AsmPrinter::doFinalization(Module &M) {
310 O << "\t" << "END\n";
311 bool Result = AsmPrinter::doFinalization(M);
315 void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
316 const Function *F = MF.getFunction();
317 std::string FuncName = Mang->getValueName(F);
318 const Module *M = F->getParent();
319 const TargetData *TD = TM.getTargetData();
321 // Emit the data section name.
323 std::string fDataSection = "fdata." + CurrentFnName + ".#";
324 SwitchToUDataSection(fDataSection.c_str(), F);
326 //Emit function return value.
327 O << CurrentFnName << ".retval:\n";
328 const Type *RetType = F->getReturnType();
329 if (RetType->getTypeID() != Type::VoidTyID) {
330 unsigned RetSize = TD->getTypePaddedSize(RetType);
332 O << CurrentFnName << ".retval" << " RES " << RetSize;
334 // Emit function arguments.
335 O << CurrentFnName << ".args:\n";
336 for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
338 std::string ArgName = Mang->getValueName(AI);
339 const Type *ArgTy = AI->getType();
340 unsigned ArgSize = TD->getTypePaddedSize(ArgTy);
341 O << CurrentFnName << ".args." << ArgName << " RES " << ArgSize;
343 // Emit the function variables.
345 // In PIC16 all the function arguments and local variables are global.
346 // Therefore to get the variable belonging to this function entire
347 // global list will be traversed and variables belonging to this function
348 // will be emitted in the current data section.
349 for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
351 std::string VarName = Mang->getValueName(I);
353 // The variables of a function are of form FuncName.* . If this variable
354 // does not belong to this function then continue.
355 if (!(VarName.find(FuncName + ".") == 0 ? true : false))
358 Constant *C = I->getInitializer();
359 const Type *Ty = C->getType();
360 unsigned Size = TD->getTypePaddedSize(Ty);
361 // Emit memory reserve directive.
362 O << VarName << " RES " << Size << "\n";
364 emitFunctionTempData(MF);
367 void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
368 // Emit temporary variables.
369 MachineFrameInfo *FrameInfo = MF.getFrameInfo();
370 if (FrameInfo->hasStackObjects()) {
371 int indexBegin = FrameInfo->getObjectIndexBegin();
372 int indexEnd = FrameInfo->getObjectIndexEnd();
374 if (indexBegin < indexEnd)
375 O << CurrentFnName << ".tmp RES"<< " "
376 <<indexEnd - indexBegin <<"\n";
378 while (indexBegin < indexEnd) {
379 O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
387 /// The function is same as AsmPrinter::SwitchtoDataSection except the call
388 /// to getUDataSectionStartSuffix.
389 void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection,
390 const GlobalValue *GV) {
392 if (GV && GV->hasSection())
393 NS = TAI->getSwitchToSectionDirective() + GV->getSection();
397 // If we're already in this section, we're done.
398 if (CurrentSection == NS) return;
400 // Close the current section, if applicable.
401 if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
402 O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
406 if (!CurrentSection.empty()){}
407 O << CurrentSection << (static_cast<const PIC16TargetAsmInfo *>(TAI))->
408 getUDataSectionStartSuffix() << '\n';
410 IsInTextSection = false;
413 /// The function is same as AsmPrinter::SwitchtoDataSection except the call
414 /// to getRomDataSectionStartSuffix.
415 void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection,
416 const GlobalValue *GV) {
418 if (GV && GV->hasSection())
419 NS = TAI->getSwitchToSectionDirective() + GV->getSection();
423 // If we're already in this section, we're done.
424 if (CurrentSection == NS) return;
426 // Close the current section, if applicable.
427 if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
428 O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
432 if (!CurrentSection.empty()) {}
433 O << CurrentSection << (static_cast< const PIC16TargetAsmInfo *>(TAI))->
434 getRomDataSectionStartSuffix() << '\n';
436 IsInTextSection = false;