LLVM API Documentation
00001 //===-- IA64AsmPrinter.cpp - Print out IA64 LLVM as assembly --------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains a printer that converts from our internal representation 00011 // of machine-dependent LLVM code to assembly accepted by the GNU binutils 'gas' 00012 // assembler. The Intel 'ias' and HP-UX 'as' assemblers *may* choke on this 00013 // output, but if so that's a bug I'd like to hear about: please file a bug 00014 // report in bugzilla. FYI, the not too bad 'ias' assembler is bundled with 00015 // the Intel C/C++ compiler for Itanium Linux. 00016 // 00017 //===----------------------------------------------------------------------===// 00018 00019 #define DEBUG_TYPE "asm-printer" 00020 #include "IA64.h" 00021 #include "IA64TargetMachine.h" 00022 #include "llvm/Module.h" 00023 #include "llvm/Type.h" 00024 #include "llvm/CodeGen/AsmPrinter.h" 00025 #include "llvm/CodeGen/MachineFunctionPass.h" 00026 #include "llvm/Target/TargetAsmInfo.h" 00027 #include "llvm/Target/TargetMachine.h" 00028 #include "llvm/Support/Mangler.h" 00029 #include "llvm/Support/raw_ostream.h" 00030 #include "llvm/ADT/Statistic.h" 00031 using namespace llvm; 00032 00033 STATISTIC(EmittedInsts, "Number of machine instrs printed"); 00034 00035 namespace { 00036 struct IA64AsmPrinter : public AsmPrinter { 00037 std::set<std::string> ExternalFunctionNames, ExternalObjectNames; 00038 00039 IA64AsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T) 00040 : AsmPrinter(O, TM, T) { 00041 } 00042 00043 virtual const char *getPassName() const { 00044 return "IA64 Assembly Printer"; 00045 } 00046 00047 /// printInstruction - This method is automatically generated by tablegen 00048 /// from the instruction set description. This method returns true if the 00049 /// machine instruction was sufficiently described to print it, otherwise it 00050 /// returns false. 00051 bool printInstruction(const MachineInstr *MI); 00052 00053 // This method is used by the tablegen'erated instruction printer. 00054 void printOperand(const MachineInstr *MI, unsigned OpNo){ 00055 const MachineOperand &MO = MI->getOperand(OpNo); 00056 if (MO.getType() == MachineOperand::MO_Register) { 00057 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && 00058 "Not physref??"); 00059 //XXX Bug Workaround: See note in Printer::doInitialization about %. 00060 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; 00061 } else { 00062 printOp(MO); 00063 } 00064 } 00065 00066 void printS8ImmOperand(const MachineInstr *MI, unsigned OpNo) { 00067 int val=(unsigned int)MI->getOperand(OpNo).getImm(); 00068 if(val>=128) val=val-256; // if negative, flip sign 00069 O << val; 00070 } 00071 void printS14ImmOperand(const MachineInstr *MI, unsigned OpNo) { 00072 int val=(unsigned int)MI->getOperand(OpNo).getImm(); 00073 if(val>=8192) val=val-16384; // if negative, flip sign 00074 O << val; 00075 } 00076 void printS22ImmOperand(const MachineInstr *MI, unsigned OpNo) { 00077 int val=(unsigned int)MI->getOperand(OpNo).getImm(); 00078 if(val>=2097152) val=val-4194304; // if negative, flip sign 00079 O << val; 00080 } 00081 void printU64ImmOperand(const MachineInstr *MI, unsigned OpNo) { 00082 O << (uint64_t)MI->getOperand(OpNo).getImm(); 00083 } 00084 void printS64ImmOperand(const MachineInstr *MI, unsigned OpNo) { 00085 // XXX : nasty hack to avoid GPREL22 "relocation truncated to fit" linker 00086 // errors - instead of add rX = @gprel(CPI<whatever>), r1;; we now 00087 // emit movl rX = @gprel(CPI<whatever);; 00088 // add rX = rX, r1; 00089 // this gives us 64 bits instead of 22 (for the add long imm) to play 00090 // with, which shuts up the linker. The problem is that the constant 00091 // pool entries aren't immediates at this stage, so we check here. 00092 // If it's an immediate, print it the old fashioned way. If it's 00093 // not, we print it as a constant pool index. 00094 if (MI->getOperand(OpNo).isImm()) { 00095 O << (int64_t)MI->getOperand(OpNo).getImm(); 00096 } else { // this is a constant pool reference: FIXME: assert this 00097 printOp(MI->getOperand(OpNo)); 00098 } 00099 } 00100 00101 void printGlobalOperand(const MachineInstr *MI, unsigned OpNo) { 00102 printOp(MI->getOperand(OpNo), false); // this is NOT a br.call instruction 00103 } 00104 00105 void printCallOperand(const MachineInstr *MI, unsigned OpNo) { 00106 printOp(MI->getOperand(OpNo), true); // this is a br.call instruction 00107 } 00108 00109 void printMachineInstruction(const MachineInstr *MI); 00110 void printOp(const MachineOperand &MO, bool isBRCALLinsn= false); 00111 void printModuleLevelGV(const GlobalVariable* GVar); 00112 bool runOnMachineFunction(MachineFunction &F); 00113 bool doInitialization(Module &M); 00114 bool doFinalization(Module &M); 00115 }; 00116 } // end of anonymous namespace 00117 00118 00119 // Include the auto-generated portion of the assembly writer. 00120 #include "IA64GenAsmWriter.inc" 00121 00122 /// runOnMachineFunction - This uses the printMachineInstruction() 00123 /// method to print assembly for each instruction. 00124 /// 00125 bool IA64AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 00126 SetupMachineFunction(MF); 00127 O << "\n\n"; 00128 00129 // Print out constants referenced by the function 00130 EmitConstantPool(MF.getConstantPool()); 00131 00132 const Function *F = MF.getFunction(); 00133 SwitchToSection(TAI->SectionForGlobal(F)); 00134 00135 // Print out labels for the function. 00136 EmitAlignment(5); 00137 O << "\t.global\t" << CurrentFnName << '\n'; 00138 00139 printVisibility(CurrentFnName, F->getVisibility()); 00140 00141 O << "\t.type\t" << CurrentFnName << ", @function\n"; 00142 O << CurrentFnName << ":\n"; 00143 00144 // Print out code for the function. 00145 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 00146 I != E; ++I) { 00147 // Print a label for the basic block if there are any predecessors. 00148 if (!I->pred_empty()) { 00149 printBasicBlockLabel(I, true, true); 00150 O << '\n'; 00151 } 00152 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 00153 II != E; ++II) { 00154 // Print the assembly for the instruction. 00155 printMachineInstruction(II); 00156 } 00157 } 00158 00159 // We didn't modify anything. 00160 return false; 00161 } 00162 00163 void IA64AsmPrinter::printOp(const MachineOperand &MO, 00164 bool isBRCALLinsn /* = false */) { 00165 const TargetRegisterInfo &RI = *TM.getRegisterInfo(); 00166 switch (MO.getType()) { 00167 case MachineOperand::MO_Register: 00168 O << RI.get(MO.getReg()).AsmName; 00169 return; 00170 00171 case MachineOperand::MO_Immediate: 00172 O << MO.getImm(); 00173 return; 00174 case MachineOperand::MO_MachineBasicBlock: 00175 printBasicBlockLabel(MO.getMBB()); 00176 return; 00177 case MachineOperand::MO_ConstantPoolIndex: { 00178 O << "@gprel(" << TAI->getPrivateGlobalPrefix() 00179 << "CPI" << getFunctionNumber() << "_" << MO.getIndex() << ")"; 00180 return; 00181 } 00182 00183 case MachineOperand::MO_GlobalAddress: { 00184 00185 // functions need @ltoff(@fptr(fn_name)) form 00186 GlobalValue *GV = MO.getGlobal(); 00187 Function *F = dyn_cast<Function>(GV); 00188 00189 bool Needfptr=false; // if we're computing an address @ltoff(X), do 00190 // we need to decorate it so it becomes 00191 // @ltoff(@fptr(X)) ? 00192 if (F && !isBRCALLinsn /*&& F->isDeclaration()*/) 00193 Needfptr=true; 00194 00195 // if this is the target of a call instruction, we should define 00196 // the function somewhere (GNU gas has no problem without this, but 00197 // Intel ias rightly complains of an 'undefined symbol') 00198 00199 if (F /*&& isBRCALLinsn*/ && F->isDeclaration()) 00200 ExternalFunctionNames.insert(Mang->getValueName(MO.getGlobal())); 00201 else 00202 if (GV->isDeclaration()) // e.g. stuff like 'stdin' 00203 ExternalObjectNames.insert(Mang->getValueName(MO.getGlobal())); 00204 00205 if (!isBRCALLinsn) 00206 O << "@ltoff("; 00207 if (Needfptr) 00208 O << "@fptr("; 00209 O << Mang->getValueName(MO.getGlobal()); 00210 00211 if (Needfptr && !isBRCALLinsn) 00212 O << "#))"; // close both fptr( and ltoff( 00213 else { 00214 if (Needfptr) 00215 O << "#)"; // close only fptr( 00216 if (!isBRCALLinsn) 00217 O << "#)"; // close only ltoff( 00218 } 00219 00220 int Offset = MO.getOffset(); 00221 if (Offset > 0) 00222 O << " + " << Offset; 00223 else if (Offset < 0) 00224 O << " - " << -Offset; 00225 return; 00226 } 00227 case MachineOperand::MO_ExternalSymbol: 00228 O << MO.getSymbolName(); 00229 ExternalFunctionNames.insert(MO.getSymbolName()); 00230 return; 00231 default: 00232 O << "<AsmPrinter: unknown operand type: " << MO.getType() << " >"; return; 00233 } 00234 } 00235 00236 /// printMachineInstruction -- Print out a single IA64 LLVM instruction 00237 /// MI to the current output stream. 00238 /// 00239 void IA64AsmPrinter::printMachineInstruction(const MachineInstr *MI) { 00240 ++EmittedInsts; 00241 00242 // Call the autogenerated instruction printer routines. 00243 printInstruction(MI); 00244 } 00245 00246 bool IA64AsmPrinter::doInitialization(Module &M) { 00247 bool Result = AsmPrinter::doInitialization(M); 00248 00249 O << "\n.ident \"LLVM-ia64\"\n\n" 00250 << "\t.psr lsb\n" // should be "msb" on HP-UX, for starters 00251 << "\t.radix C\n" 00252 << "\t.psr abi64\n"; // we only support 64 bits for now 00253 return Result; 00254 } 00255 00256 void IA64AsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { 00257 const TargetData *TD = TM.getTargetData(); 00258 00259 if (!GVar->hasInitializer()) 00260 return; // External global require no code 00261 00262 // Check to see if this is a special global used by LLVM, if so, emit it. 00263 if (EmitSpecialLLVMGlobal(GVar)) 00264 return; 00265 00266 O << "\n\n"; 00267 std::string name = Mang->getValueName(GVar); 00268 Constant *C = GVar->getInitializer(); 00269 unsigned Size = TD->getTypePaddedSize(C->getType()); 00270 unsigned Align = TD->getPreferredAlignmentLog(GVar); 00271 00272 printVisibility(name, GVar->getVisibility()); 00273 00274 SwitchToSection(TAI->SectionForGlobal(GVar)); 00275 00276 if (C->isNullValue() && !GVar->hasSection()) { 00277 if (!GVar->isThreadLocal() && 00278 (GVar->hasLocalLinkage() || GVar->mayBeOverridden())) { 00279 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. 00280 00281 if (GVar->hasLocalLinkage()) { 00282 O << "\t.lcomm " << name << "#," << Size 00283 << ',' << (1 << Align); 00284 O << '\n'; 00285 } else { 00286 O << "\t.common " << name << "#," << Size 00287 << ',' << (1 << Align); 00288 O << '\n'; 00289 } 00290 00291 return; 00292 } 00293 } 00294 00295 switch (GVar->getLinkage()) { 00296 case GlobalValue::LinkOnceLinkage: 00297 case GlobalValue::CommonLinkage: 00298 case GlobalValue::WeakLinkage: 00299 // Nonnull linkonce -> weak 00300 O << "\t.weak " << name << '\n'; 00301 break; 00302 case GlobalValue::AppendingLinkage: 00303 // FIXME: appending linkage variables should go into a section of 00304 // their name or something. For now, just emit them as external. 00305 case GlobalValue::ExternalLinkage: 00306 // If external or appending, declare as a global symbol 00307 O << TAI->getGlobalDirective() << name << '\n'; 00308 // FALL THROUGH 00309 case GlobalValue::InternalLinkage: 00310 case GlobalValue::PrivateLinkage: 00311 break; 00312 case GlobalValue::GhostLinkage: 00313 cerr << "GhostLinkage cannot appear in IA64AsmPrinter!\n"; 00314 abort(); 00315 case GlobalValue::DLLImportLinkage: 00316 cerr << "DLLImport linkage is not supported by this target!\n"; 00317 abort(); 00318 case GlobalValue::DLLExportLinkage: 00319 cerr << "DLLExport linkage is not supported by this target!\n"; 00320 abort(); 00321 default: 00322 assert(0 && "Unknown linkage type!"); 00323 } 00324 00325 EmitAlignment(Align, GVar); 00326 00327 if (TAI->hasDotTypeDotSizeDirective()) { 00328 O << "\t.type " << name << ",@object\n"; 00329 O << "\t.size " << name << ',' << Size << '\n'; 00330 } 00331 00332 O << name << ":\n"; 00333 EmitGlobalConstant(C); 00334 } 00335 00336 00337 bool IA64AsmPrinter::doFinalization(Module &M) { 00338 // Print out module-level global variables here. 00339 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); 00340 I != E; ++I) 00341 printModuleLevelGV(I); 00342 00343 // we print out ".global X \n .type X, @function" for each external function 00344 O << "\n\n// br.call targets referenced (and not defined) above: \n"; 00345 for (std::set<std::string>::iterator i = ExternalFunctionNames.begin(), 00346 e = ExternalFunctionNames.end(); i!=e; ++i) { 00347 O << "\t.global " << *i << "\n\t.type " << *i << ", @function\n"; 00348 } 00349 O << "\n\n"; 00350 00351 // we print out ".global X \n .type X, @object" for each external object 00352 O << "\n\n// (external) symbols referenced (and not defined) above: \n"; 00353 for (std::set<std::string>::iterator i = ExternalObjectNames.begin(), 00354 e = ExternalObjectNames.end(); i!=e; ++i) { 00355 O << "\t.global " << *i << "\n\t.type " << *i << ", @object\n"; 00356 } 00357 O << "\n\n"; 00358 00359 return AsmPrinter::doFinalization(M); 00360 } 00361 00362 /// createIA64CodePrinterPass - Returns a pass that prints the IA64 00363 /// assembly code for a MachineFunction to the given output stream, using 00364 /// the given target machine description. 00365 /// 00366 FunctionPass *llvm::createIA64CodePrinterPass(raw_ostream &o, 00367 IA64TargetMachine &tm) { 00368 return new IA64AsmPrinter(o, tm, tm.getTargetAsmInfo()); 00369 }