1 //===-- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly --===// 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 Hexagon assembly language. This printer is 12 // the output mechanism used by `llc'. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #define DEBUG_TYPE "asm-printer" 17 #include "Hexagon.h" 18 #include "HexagonAsmPrinter.h" 19 #include "HexagonMachineFunctionInfo.h" 20 #include "HexagonTargetMachine.h" 21 #include "HexagonSubtarget.h" 22 #include "MCTargetDesc/HexagonMCInst.h" 23 #include "InstPrinter/HexagonInstPrinter.h" 24 #include "llvm/ADT/SmallString.h" 25 #include "llvm/ADT/SmallVector.h" 26 #include "llvm/ADT/StringExtras.h" 27 #include "llvm/Analysis/ConstantFolding.h" 28 #include "llvm/Assembly/Writer.h" 29 #include "llvm/CodeGen/AsmPrinter.h" 30 #include "llvm/CodeGen/MachineFunctionPass.h" 31 #include "llvm/CodeGen/MachineInstr.h" 32 #include "llvm/CodeGen/MachineInstrBuilder.h" 33 #include "llvm/CodeGen/MachineModuleInfo.h" 34 #include "llvm/IR/Constants.h" 35 #include "llvm/IR/DataLayout.h" 36 #include "llvm/IR/DerivedTypes.h" 37 #include "llvm/IR/Module.h" 38 #include "llvm/MC/MCAsmInfo.h" 39 #include "llvm/MC/MCContext.h" 40 #include "llvm/MC/MCExpr.h" 41 #include "llvm/MC/MCInst.h" 42 #include "llvm/MC/MCSection.h" 43 #include "llvm/MC/MCStreamer.h" 44 #include "llvm/MC/MCSymbol.h" 45 #include "llvm/Support/CommandLine.h" 46 #include "llvm/Support/Compiler.h" 47 #include "llvm/Support/Debug.h" 48 #include "llvm/Support/Format.h" 49 #include "llvm/Support/MathExtras.h" 50 #include "llvm/Support/TargetRegistry.h" 51 #include "llvm/Support/raw_ostream.h" 52 #include "llvm/Target/Mangler.h" 53 #include "llvm/Target/TargetInstrInfo.h" 54 #include "llvm/Target/TargetLoweringObjectFile.h" 55 #include "llvm/Target/TargetOptions.h" 56 #include "llvm/Target/TargetRegisterInfo.h" 57 58 using namespace llvm; 59 60 static cl::opt<bool> AlignCalls( 61 "hexagon-align-calls", cl::Hidden, cl::init(true), 62 cl::desc("Insert falign after call instruction for Hexagon target")); 63 64 void HexagonAsmPrinter::EmitAlignment(unsigned NumBits, 65 const GlobalValue *GV) const { 66 // For basic block level alignment, use ".falign". 67 if (!GV) { 68 OutStreamer.EmitRawText(StringRef("\t.falign")); 69 return; 70 } 71 72 AsmPrinter::EmitAlignment(NumBits, GV); 73 } 74 75 void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, 76 raw_ostream &O) { 77 const MachineOperand &MO = MI->getOperand(OpNo); 78 79 switch (MO.getType()) { 80 default: llvm_unreachable ("<unknown operand type>"); 81 case MachineOperand::MO_Register: 82 O << HexagonInstPrinter::getRegisterName(MO.getReg()); 83 return; 84 case MachineOperand::MO_Immediate: 85 O << MO.getImm(); 86 return; 87 case MachineOperand::MO_MachineBasicBlock: 88 O << *MO.getMBB()->getSymbol(); 89 return; 90 case MachineOperand::MO_JumpTableIndex: 91 O << *GetJTISymbol(MO.getIndex()); 92 // FIXME: PIC relocation model. 93 return; 94 case MachineOperand::MO_ConstantPoolIndex: 95 O << *GetCPISymbol(MO.getIndex()); 96 return; 97 case MachineOperand::MO_ExternalSymbol: 98 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 99 return; 100 case MachineOperand::MO_GlobalAddress: 101 // Computing the address of a global symbol, not calling it. 102 O << *Mang->getSymbol(MO.getGlobal()); 103 printOffset(MO.getOffset(), O); 104 return; 105 } 106 } 107 108 // 109 // isBlockOnlyReachableByFallthrough - We need to override this since the 110 // default AsmPrinter does not print labels for any basic block that 111 // is only reachable by a fall through. That works for all cases except 112 // for the case in which the basic block is reachable by a fall through but 113 // through an indirect from a jump table. In this case, the jump table 114 // will contain a label not defined by AsmPrinter. 115 // 116 bool HexagonAsmPrinter:: 117 isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { 118 if (MBB->hasAddressTaken()) { 119 return false; 120 } 121 return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); 122 } 123 124 125 /// PrintAsmOperand - Print out an operand for an inline asm expression. 126 /// 127 bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 128 unsigned AsmVariant, 129 const char *ExtraCode, 130 raw_ostream &OS) { 131 // Does this asm operand have a single letter operand modifier? 132 if (ExtraCode && ExtraCode[0]) { 133 if (ExtraCode[1] != 0) return true; // Unknown modifier. 134 135 switch (ExtraCode[0]) { 136 default: 137 // See if this is a generic print operand 138 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS); 139 case 'c': // Don't print "$" before a global var name or constant. 140 // Hexagon never has a prefix. 141 printOperand(MI, OpNo, OS); 142 return false; 143 case 'L': // Write second word of DImode reference. 144 // Verify that this operand has two consecutive registers. 145 if (!MI->getOperand(OpNo).isReg() || 146 OpNo+1 == MI->getNumOperands() || 147 !MI->getOperand(OpNo+1).isReg()) 148 return true; 149 ++OpNo; // Return the high-part. 150 break; 151 case 'I': 152 // Write 'i' if an integer constant, otherwise nothing. Used to print 153 // addi vs add, etc. 154 if (MI->getOperand(OpNo).isImm()) 155 OS << "i"; 156 return false; 157 } 158 } 159 160 printOperand(MI, OpNo, OS); 161 return false; 162 } 163 164 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 165 unsigned OpNo, unsigned AsmVariant, 166 const char *ExtraCode, 167 raw_ostream &O) { 168 if (ExtraCode && ExtraCode[0]) 169 return true; // Unknown modifier. 170 171 const MachineOperand &Base = MI->getOperand(OpNo); 172 const MachineOperand &Offset = MI->getOperand(OpNo+1); 173 174 if (Base.isReg()) 175 printOperand(MI, OpNo, O); 176 else 177 llvm_unreachable("Unimplemented"); 178 179 if (Offset.isImm()) { 180 if (Offset.getImm()) 181 O << " + #" << Offset.getImm(); 182 } 183 else 184 llvm_unreachable("Unimplemented"); 185 186 return false; 187 } 188 189 void HexagonAsmPrinter::printPredicateOperand(const MachineInstr *MI, 190 unsigned OpNo, 191 raw_ostream &O) { 192 llvm_unreachable("Unimplemented"); 193 } 194 195 196 /// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to 197 /// the current output stream. 198 /// 199 void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { 200 if (MI->isBundle()) { 201 std::vector<const MachineInstr*> BundleMIs; 202 203 const MachineBasicBlock *MBB = MI->getParent(); 204 MachineBasicBlock::const_instr_iterator MII = MI; 205 ++MII; 206 unsigned int IgnoreCount = 0; 207 while (MII != MBB->end() && MII->isInsideBundle()) { 208 const MachineInstr *MInst = MII; 209 if (MInst->getOpcode() == TargetOpcode::DBG_VALUE || 210 MInst->getOpcode() == TargetOpcode::IMPLICIT_DEF) { 211 IgnoreCount++; 212 ++MII; 213 continue; 214 } 215 //BundleMIs.push_back(&*MII); 216 BundleMIs.push_back(MInst); 217 ++MII; 218 } 219 unsigned Size = BundleMIs.size(); 220 assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); 221 for (unsigned Index = 0; Index < Size; Index++) { 222 HexagonMCInst MCI; 223 MCI.setPacketStart(Index == 0); 224 MCI.setPacketEnd(Index == (Size-1)); 225 226 HexagonLowerToMC(BundleMIs[Index], MCI, *this); 227 OutStreamer.EmitInstruction(MCI); 228 } 229 } 230 else { 231 HexagonMCInst MCI; 232 if (MI->getOpcode() == Hexagon::ENDLOOP0) { 233 MCI.setPacketStart(true); 234 MCI.setPacketEnd(true); 235 } 236 HexagonLowerToMC(MI, MCI, *this); 237 OutStreamer.EmitInstruction(MCI); 238 } 239 240 return; 241 } 242 243 /// PrintUnmangledNameSafely - Print out the printable characters in the name. 244 /// Don't print things like \n or \0. 245 // static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) { 246 // for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); 247 // Name != E; ++Name) 248 // if (isprint(*Name)) 249 // OS << *Name; 250 // } 251 252 253 void HexagonAsmPrinter::printAddrModeBasePlusOffset(const MachineInstr *MI, 254 int OpNo, raw_ostream &O) { 255 const MachineOperand &MO1 = MI->getOperand(OpNo); 256 const MachineOperand &MO2 = MI->getOperand(OpNo+1); 257 258 O << HexagonInstPrinter::getRegisterName(MO1.getReg()) 259 << " + #" 260 << MO2.getImm(); 261 } 262 263 264 void HexagonAsmPrinter::printGlobalOperand(const MachineInstr *MI, int OpNo, 265 raw_ostream &O) { 266 const MachineOperand &MO = MI->getOperand(OpNo); 267 assert( (MO.getType() == MachineOperand::MO_GlobalAddress) && 268 "Expecting global address"); 269 270 O << *Mang->getSymbol(MO.getGlobal()); 271 if (MO.getOffset() != 0) { 272 O << " + "; 273 O << MO.getOffset(); 274 } 275 } 276 277 void HexagonAsmPrinter::printJumpTable(const MachineInstr *MI, int OpNo, 278 raw_ostream &O) { 279 const MachineOperand &MO = MI->getOperand(OpNo); 280 assert( (MO.getType() == MachineOperand::MO_JumpTableIndex) && 281 "Expecting jump table index"); 282 283 // Hexagon_TODO: Do we need name mangling? 284 O << *GetJTISymbol(MO.getIndex()); 285 } 286 287 void HexagonAsmPrinter::printConstantPool(const MachineInstr *MI, int OpNo, 288 raw_ostream &O) { 289 const MachineOperand &MO = MI->getOperand(OpNo); 290 assert( (MO.getType() == MachineOperand::MO_ConstantPoolIndex) && 291 "Expecting constant pool index"); 292 293 // Hexagon_TODO: Do we need name mangling? 294 O << *GetCPISymbol(MO.getIndex()); 295 } 296 297 static MCInstPrinter *createHexagonMCInstPrinter(const Target &T, 298 unsigned SyntaxVariant, 299 const MCAsmInfo &MAI, 300 const MCInstrInfo &MII, 301 const MCRegisterInfo &MRI, 302 const MCSubtargetInfo &STI) { 303 if (SyntaxVariant == 0) 304 return(new HexagonInstPrinter(MAI, MII, MRI)); 305 else 306 return NULL; 307 } 308 309 extern "C" void LLVMInitializeHexagonAsmPrinter() { 310 RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget); 311 312 TargetRegistry::RegisterMCInstPrinter(TheHexagonTarget, 313 createHexagonMCInstPrinter); 314 } 315