| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 1 | //===-- PIC16AsmPrinter.cpp - PIC16 LLVM assembly writer ------------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
 | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
 | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | // This file contains a printer that converts from our internal representation | 
 | 11 | // of machine-dependent LLVM code to PIC16 assembly language. | 
 | 12 | // | 
 | 13 | //===----------------------------------------------------------------------===// | 
 | 14 |  | 
 | 15 | #define DEBUG_TYPE "asm-printer" | 
 | 16 | #include "PIC16.h" | 
 | 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" | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 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" | 
 | 38 | #include <cctype> | 
 | 39 |  | 
 | 40 | using namespace llvm; | 
 | 41 |  | 
 | 42 | STATISTIC(EmittedInsts, "Number of machine instrs printed"); | 
 | 43 |  | 
 | 44 | namespace { | 
 | 45 |   struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter { | 
 | 46 |     PIC16AsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) | 
 | 47 |       : AsmPrinter(O, TM, T) { | 
 | 48 |     } | 
 | 49 |  | 
 | 50 |  | 
 | 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(). | 
 | 54 |     /// | 
 | 55 |     typedef std::map<const Value *, unsigned> ValueMapTy; | 
 | 56 |     ValueMapTy NumberForBB; | 
 | 57 |  | 
 | 58 |     /// Keeps the set of GlobalValues that require non-lazy-pointers for | 
 | 59 |     /// indirect access. | 
 | 60 |     std::set<std::string> GVNonLazyPtrs; | 
 | 61 |  | 
 | 62 |     /// Keeps the set of external function GlobalAddresses that the asm | 
 | 63 |     /// printer should generate stubs for. | 
 | 64 |     std::set<std::string> FnStubs; | 
 | 65 |  | 
 | 66 |     /// True if asm printer is printing a series of CONSTPOOL_ENTRY. | 
 | 67 |     bool InCPMode; | 
 | 68 |      | 
 | 69 |     virtual const char *getPassName() const { | 
 | 70 |       return "PIC16 Assembly Printer"; | 
 | 71 |     } | 
 | 72 |  | 
 | 73 |     void printOperand(const MachineInstr *MI, int opNum, | 
 | 74 |                       const char *Modifier = 0); | 
 | 75 |  | 
 | 76 |     void printSOImmOperand(const MachineInstr *MI, int opNum); | 
 | 77 |  | 
 | 78 |     void printAddrModeOperand(const MachineInstr *MI, int OpNo); | 
 | 79 |  | 
 | 80 |     void printRegisterList(const MachineInstr *MI, int opNum); | 
 | 81 |     void printCPInstOperand(const MachineInstr *MI, int opNum, | 
 | 82 |                             const char *Modifier); | 
 | 83 |  | 
 | 84 |  | 
 | 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); | 
 | 90 |  | 
 | 91 |     virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); | 
 | 92 |      | 
 | 93 |     void getAnalysisUsage(AnalysisUsage &AU) const; | 
 | 94 |  | 
 | 95 |     public: | 
 | 96 |     void SwitchToTextSection(const char *NewSection,  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 97 |                              const GlobalValue *GV = NULL);     | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 98 |     void SwitchToDataSection(const char *NewSection,  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 99 |                              const GlobalValue *GV = NULL); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 100 |     void SwitchToDataOvrSection(const char *NewSection,  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 101 |                                 const GlobalValue *GV = NULL); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 102 |   }; | 
 | 103 | } // end of anonymous namespace | 
 | 104 |  | 
 | 105 | #include "PIC16GenAsmWriter.inc" | 
 | 106 |  | 
 | 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. | 
 | 111 | /// | 
 | 112 | FunctionPass *llvm::createPIC16CodePrinterPass(std::ostream &o, | 
 | 113 |                                                PIC16TargetMachine &tm) { | 
 | 114 |   return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo()); | 
 | 115 | } | 
 | 116 |  | 
 | 117 | void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const  | 
 | 118 | { | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 119 |   // FIXME: Currently unimplemented. | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 120 | } | 
 | 121 |  | 
 | 122 |  | 
 | 123 | void PIC16AsmPrinter :: | 
 | 124 | EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)  | 
 | 125 | { | 
 | 126 |   printDataDirective(MCPV->getType()); | 
 | 127 |  | 
 | 128 |   PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV; | 
 | 129 |   GlobalValue *GV = ACPV->getGV(); | 
 | 130 |   std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix(); | 
 | 131 |   if (!GV) | 
 | 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"; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 139 |   } else { | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 140 |     O << Name; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 141 |   } | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 142 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 143 |   if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 144 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 145 |   if (ACPV->getPCAdjustment() != 0) { | 
 | 146 |     O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" | 
 | 147 |       << utostr(ACPV->getLabelId()) | 
 | 148 |       << "+" << (unsigned)ACPV->getPCAdjustment(); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 149 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 150 |     if (ACPV->mustAddCurrentAddress()) | 
 | 151 |       O << "-."; | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 152 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 153 |     O << ")"; | 
 | 154 |   } | 
 | 155 |   O << "\n"; | 
 | 156 |  | 
 | 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); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 161 | } | 
 | 162 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 163 | /// emitFunctionStart - Emit the directives used by ASM on the start of  | 
 | 164 | /// functions. | 
 | 165 | void PIC16AsmPrinter::emitFunctionStart(MachineFunction &MF) | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 166 | { | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 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) { | 
 | 174 |       if (indexBegin == 0)                      | 
 | 175 |         SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(), | 
 | 176 |                                 F); | 
 | 177 |                   | 
 | 178 |         O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES"  | 
 | 179 |           << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ; | 
 | 180 |         indexBegin++; | 
 | 181 |     } | 
 | 182 |   } | 
 | 183 |   SwitchToTextSection(CurrentFnName.c_str(), F);   | 
 | 184 |   O << "_" << CurrentFnName << ":" ;  | 
 | 185 |   O << "\n"; | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 186 | } | 
 | 187 |  | 
 | 188 |  | 
 | 189 | /// runOnMachineFunction - This uses the printInstruction() | 
 | 190 | /// method to print assembly for each instruction. | 
 | 191 | /// | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 192 | bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF)  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 193 | { | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 194 |   SetupMachineFunction(MF); | 
 | 195 |   O << "\n"; | 
 | 196 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 197 |   // What's my mangled name? | 
 | 198 |   CurrentFnName = Mang->getValueName(MF.getFunction()); | 
 | 199 |  | 
 | 200 |   // Emit the function start directives | 
 | 201 |   emitFunctionStart(MF); | 
 | 202 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 203 |   // Print out code for the function. | 
 | 204 |   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
 | 205 |        I != E; ++I) { | 
 | 206 |     // Print a label for the basic block. | 
 | 207 |     if (I != MF.begin()) { | 
 | 208 |       printBasicBlockLabel(I, true); | 
 | 209 |       O << '\n'; | 
 | 210 |     } | 
 | 211 |     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); | 
 | 212 |          II != E; ++II) { | 
 | 213 |       // Print the assembly for the instruction. | 
 | 214 |       O << '\t'; | 
 | 215 |       printInstruction(II); | 
 | 216 |       ++EmittedInsts; | 
 | 217 |     } | 
 | 218 |   } | 
 | 219 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 220 |   // We didn't modify anything. | 
 | 221 |   return false; | 
 | 222 | } | 
 | 223 |  | 
 | 224 | void PIC16AsmPrinter:: | 
 | 225 | printOperand(const MachineInstr *MI, int opNum, const char *Modifier)  | 
 | 226 | { | 
 | 227 |   const MachineOperand &MO = MI->getOperand(opNum); | 
 | 228 |   const TargetRegisterInfo  &RI = *TM.getRegisterInfo(); | 
 | 229 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 230 |   switch (MO.getType()) { | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 231 |     case MachineOperand::MO_Register: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 232 |       if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) | 
 | 233 |         O << RI.get(MO.getReg()).Name; | 
 | 234 |       else | 
 | 235 |         assert(0 && "not implemented"); | 
 | 236 |       break; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 237 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 238 |     case MachineOperand::MO_Immediate:  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 239 |       if (!Modifier || strcmp(Modifier, "no_hash") != 0) | 
 | 240 |         O << "#"; | 
 | 241 |       O << (int)MO.getImm(); | 
 | 242 |       break; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 243 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 244 |     case MachineOperand::MO_MachineBasicBlock: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 245 |       printBasicBlockLabel(MO.getMBB()); | 
 | 246 |       return; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 247 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 248 |     case MachineOperand::MO_GlobalAddress:  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 249 |       O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset(); | 
 | 250 |       break; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 251 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 252 |     case MachineOperand::MO_ExternalSymbol:  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 253 |       O << MO.getSymbolName(); | 
 | 254 |       break; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 255 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 256 |     case MachineOperand::MO_ConstantPoolIndex: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 257 |       O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() | 
 | 258 |         << '_' << MO.getIndex(); | 
 | 259 |       break; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 260 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 261 |     case MachineOperand::MO_FrameIndex: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 262 |       O << "_" << CurrentFnName  | 
 | 263 |         << '+' << MO.getIndex(); | 
 | 264 |       break; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 265 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 266 |     case MachineOperand::MO_JumpTableIndex: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 267 |       O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() | 
 | 268 |         << '_' << MO.getIndex(); | 
 | 269 |       break; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 270 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 271 |     default: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 272 |       O << "<unknown operand type>"; abort ();  | 
 | 273 |       break; | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 274 |   } // end switch. | 
 | 275 | } | 
 | 276 |  | 
 | 277 | static void  | 
 | 278 | printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI)  | 
 | 279 | { | 
 | 280 |   assert(V < (1 << 12) && "Not a valid so_imm value!"); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 281 |    | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 282 |   O << (unsigned) V; | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 283 | } | 
 | 284 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 285 | /// printSOImmOperand - SOImm is 4-bit rotated amount in bits 8-11 with 8-bit | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 286 | /// immediate in bits 0-7. | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 287 | void PIC16AsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum)  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 288 | { | 
 | 289 |   const MachineOperand &MO = MI->getOperand(OpNum); | 
 | 290 |   assert(MO.isImmediate() && "Not a valid so_imm value!"); | 
 | 291 |   printSOImm(O, MO.getImm(), TAI); | 
 | 292 | } | 
 | 293 |  | 
 | 294 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 295 | void PIC16AsmPrinter::printAddrModeOperand(const MachineInstr *MI, int Op)  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 296 | { | 
 | 297 |   const MachineOperand &MO1 = MI->getOperand(Op); | 
 | 298 |   const MachineOperand &MO2 = MI->getOperand(Op+1); | 
 | 299 |  | 
 | 300 |   if (MO2.isFrameIndex ()) { | 
 | 301 |     printOperand(MI, Op+1); | 
 | 302 |     return; | 
 | 303 |   } | 
 | 304 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 305 |   if (!MO1.isRegister()) {    | 
 | 306 |     // FIXME: This is for CP entries, but isn't right. | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 307 |     printOperand(MI, Op); | 
 | 308 |     return; | 
 | 309 |   } | 
 | 310 |  | 
 | 311 |   // If this is Stack Slot | 
 | 312 |   if (MO1.isRegister()) {   | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 313 |     if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) { | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 314 |       O << CurrentFnName <<"_"<< MO2.getImm(); | 
 | 315 |       return; | 
 | 316 |     } | 
 | 317 |     O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; | 
 | 318 |     O << "+"; | 
 | 319 |     O << MO2.getImm(); | 
 | 320 |     O << "]"; | 
 | 321 |     return; | 
 | 322 |   } | 
 | 323 |  | 
 | 324 |   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; | 
 | 325 |   O << "]"; | 
 | 326 | } | 
 | 327 |  | 
 | 328 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 329 | void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum)  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 330 | { | 
 | 331 |   O << "{"; | 
 | 332 |   for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) { | 
 | 333 |     printOperand(MI, i); | 
 | 334 |     if (i != e-1) O << ", "; | 
 | 335 |   } | 
 | 336 |   O << "}"; | 
 | 337 | } | 
 | 338 |  | 
 | 339 | void PIC16AsmPrinter:: | 
 | 340 | printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier)  | 
 | 341 | { | 
 | 342 |   assert(Modifier && "This operand only works with a modifier!"); | 
 | 343 |  | 
 | 344 |   // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the | 
 | 345 |   // data itself. | 
 | 346 |   if (!strcmp(Modifier, "label")) { | 
 | 347 |     unsigned ID = MI->getOperand(OpNo).getImm(); | 
 | 348 |     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() | 
 | 349 |       << '_' << ID << ":\n"; | 
 | 350 |   } else { | 
 | 351 |     assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); | 
 | 352 |     unsigned CPI = MI->getOperand(OpNo).getIndex(); | 
 | 353 |  | 
 | 354 |     const MachineConstantPoolEntry &MCPE =  // Chasing pointers is fun? | 
 | 355 |       MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI]; | 
 | 356 |      | 
 | 357 |     if (MCPE.isMachineConstantPoolEntry()) | 
 | 358 |       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); | 
 | 359 |     else { | 
 | 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); | 
 | 365 |     } | 
 | 366 |   } | 
 | 367 | } | 
 | 368 |  | 
 | 369 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 370 | bool PIC16AsmPrinter::doInitialization(Module &M)  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 371 | { | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 372 |   bool Result = AsmPrinter::doInitialization(M); | 
 | 373 |   return Result; | 
 | 374 | } | 
 | 375 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 376 | bool PIC16AsmPrinter::doFinalization(Module &M)  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 377 | { | 
 | 378 |   const TargetData *TD = TM.getTargetData(); | 
 | 379 |  | 
 | 380 |   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); | 
 | 381 |        I != E; ++I) { | 
 | 382 |     if (!I->hasInitializer())   // External global require no code | 
 | 383 |       continue; | 
 | 384 |  | 
 | 385 |     if (EmitSpecialLLVMGlobal(I)) { | 
 | 386 |       continue; | 
 | 387 |     } | 
 | 388 |  | 
 | 389 |     std::string name = Mang->getValueName(I); | 
 | 390 |     Constant *C = I->getInitializer(); | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 391 |     const Type *Ty = C->getType(); | 
 | 392 |     unsigned Size = TD->getABITypeSize(Ty); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 393 |     unsigned Align = TD->getPreferredAlignmentLog(I); | 
 | 394 |  | 
 | 395 |     const char *VisibilityDirective = NULL; | 
 | 396 |     if (I->hasHiddenVisibility()) | 
 | 397 |       VisibilityDirective = TAI->getHiddenDirective(); | 
 | 398 |     else if (I->hasProtectedVisibility()) | 
 | 399 |       VisibilityDirective = TAI->getProtectedDirective(); | 
 | 400 |  | 
 | 401 |     if (VisibilityDirective) | 
 | 402 |       O << VisibilityDirective << name << "\n"; | 
 | 403 |  | 
 | 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"; | 
 | 410 |           continue; | 
 | 411 |         } | 
 | 412 |       } | 
 | 413 |  | 
 | 414 |       if (!I->hasSection() && | 
 | 415 |           (I->hasInternalLinkage() || I->hasWeakLinkage() || | 
| Dale Johannesen | aafce77 | 2008-05-14 20:12:51 +0000 | [diff] [blame] | 416 |            I->hasLinkOnceLinkage() || I->hasCommonLinkage())) { | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 417 |         if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it. | 
 | 418 |         if (!NoZerosInBSS && TAI->getBSSSection()) | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 419 |           SwitchToDataSection(M.getModuleIdentifier().c_str(), I); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 420 |         else | 
 | 421 |           SwitchToDataSection(TAI->getDataSection(), I); | 
 | 422 |         if (TAI->getLCOMMDirective() != NULL) { | 
 | 423 |           if (I->hasInternalLinkage()) { | 
 | 424 |             O << TAI->getLCOMMDirective() << name << "," << Size; | 
 | 425 |           } else | 
 | 426 |             O << TAI->getCOMMDirective()  << name << "," << Size; | 
 | 427 |         } else { | 
 | 428 |           if (I->hasInternalLinkage()) | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 429 |             O << "\t.local\t" << name << "\n"; | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 430 |  | 
 | 431 |           O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " "  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 432 |             << Size; | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 433 |           O << "\n\t\tGLOBAL" <<" "<< name; | 
 | 434 |           if (TAI->getCOMMDirectiveTakesAlignment()) | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 435 |             O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 436 |         } | 
 | 437 |         continue; | 
 | 438 |       } | 
 | 439 |     } | 
 | 440 |  | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 441 |     switch (I->getLinkage()) { | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 442 |     case GlobalValue::AppendingLinkage: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 443 |       // FIXME: appending linkage variables should go into a section of | 
 | 444 |       // their name or something.  For now, just emit them as external. | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 445 |       // FALL THROUGH | 
 | 446 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 447 |     case GlobalValue::ExternalLinkage: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 448 |       O << "\t.globl " << name << "\n"; | 
 | 449 |       // FALL THROUGH | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 450 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 451 |     case GlobalValue::InternalLinkage:  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 452 |       if (I->isConstant()) { | 
 | 453 |         const ConstantArray *CVA = dyn_cast<ConstantArray>(C); | 
 | 454 |         if (TAI->getCStringSection() && CVA && CVA->isCString()) { | 
 | 455 |           SwitchToDataSection(TAI->getCStringSection(), I); | 
 | 456 |           break; | 
 | 457 |         } | 
 | 458 |       } | 
 | 459 |       break; | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 460 |  | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 461 |     default: | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 462 |       assert(0 && "Unknown linkage type!"); | 
 | 463 |       break; | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 464 |     } // end switch. | 
 | 465 |  | 
 | 466 |     EmitAlignment(Align, I); | 
 | 467 |     O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName() | 
 | 468 |       << "\n"; | 
 | 469 |  | 
 | 470 |     // If the initializer is a extern weak symbol, remember to emit the weak | 
 | 471 |     // reference! | 
 | 472 |     if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) | 
 | 473 |       if (GV->hasExternalWeakLinkage()) | 
 | 474 |         ExtWeakSymbols.insert(GV); | 
 | 475 |  | 
 | 476 |     EmitGlobalConstant(C); | 
 | 477 |     O << '\n'; | 
 | 478 |   } // end for. | 
 | 479 |  | 
 | 480 |   O << "\n "<< "END"; | 
 | 481 |   return AsmPrinter::doFinalization(M); | 
 | 482 | } | 
 | 483 |  | 
 | 484 | void PIC16AsmPrinter:: | 
 | 485 | SwitchToTextSection(const char *NewSection, const GlobalValue *GV) | 
 | 486 | { | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 487 |   O << "\n"; | 
 | 488 |   if (NewSection && *NewSection) { | 
 | 489 |     std::string codeSection = "code_"; | 
 | 490 |     codeSection += NewSection; | 
 | 491 |     codeSection += " "; | 
 | 492 |     codeSection += "CODE"; | 
 | 493 |     AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV); | 
 | 494 |   }  | 
 | 495 |   else  | 
 | 496 |     AsmPrinter::SwitchToTextSection(NewSection, GV); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 497 | } | 
 | 498 |  | 
 | 499 | void PIC16AsmPrinter:: | 
 | 500 | SwitchToDataSection(const char *NewSection, const GlobalValue *GV) | 
 | 501 | { | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 502 |   // Need to append index for page. | 
 | 503 |   O << "\n"; | 
 | 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); | 
 | 509 |     } | 
 | 510 |     dataSection += " "; | 
 | 511 |     dataSection += "UDATA"; | 
 | 512 |     AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV); | 
 | 513 |   }  | 
 | 514 |   else | 
 | 515 |     AsmPrinter::SwitchToDataSection(NewSection, GV); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 516 | } | 
 | 517 |  | 
 | 518 | void PIC16AsmPrinter:: | 
 | 519 | SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV) | 
 | 520 | { | 
| Sanjiv Gupta | 2010b3e | 2008-05-14 11:31:39 +0000 | [diff] [blame] | 521 |   O << "\n"; | 
 | 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); | 
 | 527 |     }           | 
 | 528 |     dataSection += "_"; | 
 | 529 |     dataSection += CurrentFnName; | 
 | 530 |     dataSection += " "; | 
 | 531 |     dataSection += "UDATA_OVR"; | 
 | 532 |     AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV); | 
 | 533 |   }  | 
 | 534 |   else | 
 | 535 |     AsmPrinter::SwitchToDataSection(NewSection, GV); | 
| Sanjiv Gupta | 0e68771 | 2008-05-13 09:02:57 +0000 | [diff] [blame] | 536 | } |