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 "HexagonSubtarget.h" 21 #include "HexagonTargetMachine.h" 22 #include "InstPrinter/HexagonInstPrinter.h" 23 #include "MCTargetDesc/HexagonMCInst.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/CodeGen/AsmPrinter.h" 29 #include "llvm/CodeGen/MachineFunctionPass.h" 30 #include "llvm/CodeGen/MachineInstr.h" 31 #include "llvm/CodeGen/MachineInstrBuilder.h" 32 #include "llvm/CodeGen/MachineModuleInfo.h" 33 #include "llvm/IR/Constants.h" 34 #include "llvm/IR/DataLayout.h" 35 #include "llvm/IR/DerivedTypes.h" 36 #include "llvm/IR/Mangler.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/TargetInstrInfo.h" 53 #include "llvm/Target/TargetLoweringObjectFile.h" 54 #include "llvm/Target/TargetOptions.h" 55 #include "llvm/Target/TargetRegisterInfo.h" 56 57 using namespace llvm; 58 59 static cl::opt<bool> AlignCalls( 60 "hexagon-align-calls", cl::Hidden, cl::init(true), 61 cl::desc("Insert falign after call instruction for Hexagon target")); 62 63 void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, 64 raw_ostream &O) { 65 const MachineOperand &MO = MI->getOperand(OpNo); 66 67 switch (MO.getType()) { 68 default: llvm_unreachable ("<unknown operand type>"); 69 case MachineOperand::MO_Register: 70 O << HexagonInstPrinter::getRegisterName(MO.getReg()); 71 return; 72 case MachineOperand::MO_Immediate: 73 O << MO.getImm(); 74 return; 75 case MachineOperand::MO_MachineBasicBlock: 76 O << *MO.getMBB()->getSymbol(); 77 return; 78 case MachineOperand::MO_ConstantPoolIndex: 79 O << *GetCPISymbol(MO.getIndex()); 80 return; 81 case MachineOperand::MO_GlobalAddress: 82 // Computing the address of a global symbol, not calling it. 83 O << *getSymbol(MO.getGlobal()); 84 printOffset(MO.getOffset(), O); 85 return; 86 } 87 } 88 89 // 90 // isBlockOnlyReachableByFallthrough - We need to override this since the 91 // default AsmPrinter does not print labels for any basic block that 92 // is only reachable by a fall through. That works for all cases except 93 // for the case in which the basic block is reachable by a fall through but 94 // through an indirect from a jump table. In this case, the jump table 95 // will contain a label not defined by AsmPrinter. 96 // 97 bool HexagonAsmPrinter:: 98 isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { 99 if (MBB->hasAddressTaken()) { 100 return false; 101 } 102 return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); 103 } 104 105 106 /// PrintAsmOperand - Print out an operand for an inline asm expression. 107 /// 108 bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 109 unsigned AsmVariant, 110 const char *ExtraCode, 111 raw_ostream &OS) { 112 // Does this asm operand have a single letter operand modifier? 113 if (ExtraCode && ExtraCode[0]) { 114 if (ExtraCode[1] != 0) return true; // Unknown modifier. 115 116 switch (ExtraCode[0]) { 117 default: 118 // See if this is a generic print operand 119 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS); 120 case 'c': // Don't print "$" before a global var name or constant. 121 // Hexagon never has a prefix. 122 printOperand(MI, OpNo, OS); 123 return false; 124 case 'L': // Write second word of DImode reference. 125 // Verify that this operand has two consecutive registers. 126 if (!MI->getOperand(OpNo).isReg() || 127 OpNo+1 == MI->getNumOperands() || 128 !MI->getOperand(OpNo+1).isReg()) 129 return true; 130 ++OpNo; // Return the high-part. 131 break; 132 case 'I': 133 // Write 'i' if an integer constant, otherwise nothing. Used to print 134 // addi vs add, etc. 135 if (MI->getOperand(OpNo).isImm()) 136 OS << "i"; 137 return false; 138 } 139 } 140 141 printOperand(MI, OpNo, OS); 142 return false; 143 } 144 145 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 146 unsigned OpNo, unsigned AsmVariant, 147 const char *ExtraCode, 148 raw_ostream &O) { 149 if (ExtraCode && ExtraCode[0]) 150 return true; // Unknown modifier. 151 152 const MachineOperand &Base = MI->getOperand(OpNo); 153 const MachineOperand &Offset = MI->getOperand(OpNo+1); 154 155 if (Base.isReg()) 156 printOperand(MI, OpNo, O); 157 else 158 llvm_unreachable("Unimplemented"); 159 160 if (Offset.isImm()) { 161 if (Offset.getImm()) 162 O << " + #" << Offset.getImm(); 163 } 164 else 165 llvm_unreachable("Unimplemented"); 166 167 return false; 168 } 169 170 171 /// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to 172 /// the current output stream. 173 /// 174 void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { 175 if (MI->isBundle()) { 176 std::vector<const MachineInstr*> BundleMIs; 177 178 const MachineBasicBlock *MBB = MI->getParent(); 179 MachineBasicBlock::const_instr_iterator MII = MI; 180 ++MII; 181 unsigned int IgnoreCount = 0; 182 while (MII != MBB->end() && MII->isInsideBundle()) { 183 const MachineInstr *MInst = MII; 184 if (MInst->getOpcode() == TargetOpcode::DBG_VALUE || 185 MInst->getOpcode() == TargetOpcode::IMPLICIT_DEF) { 186 IgnoreCount++; 187 ++MII; 188 continue; 189 } 190 //BundleMIs.push_back(&*MII); 191 BundleMIs.push_back(MInst); 192 ++MII; 193 } 194 unsigned Size = BundleMIs.size(); 195 assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); 196 for (unsigned Index = 0; Index < Size; Index++) { 197 HexagonMCInst MCI; 198 MCI.setPacketStart(Index == 0); 199 MCI.setPacketEnd(Index == (Size-1)); 200 201 HexagonLowerToMC(BundleMIs[Index], MCI, *this); 202 EmitToStreamer(OutStreamer, MCI); 203 } 204 } 205 else { 206 HexagonMCInst MCI; 207 if (MI->getOpcode() == Hexagon::ENDLOOP0) { 208 MCI.setPacketStart(true); 209 MCI.setPacketEnd(true); 210 } 211 HexagonLowerToMC(MI, MCI, *this); 212 EmitToStreamer(OutStreamer, MCI); 213 } 214 215 return; 216 } 217 218 static MCInstPrinter *createHexagonMCInstPrinter(const Target &T, 219 unsigned SyntaxVariant, 220 const MCAsmInfo &MAI, 221 const MCInstrInfo &MII, 222 const MCRegisterInfo &MRI, 223 const MCSubtargetInfo &STI) { 224 if (SyntaxVariant == 0) 225 return(new HexagonInstPrinter(MAI, MII, MRI)); 226 else 227 return NULL; 228 } 229 230 extern "C" void LLVMInitializeHexagonAsmPrinter() { 231 RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget); 232 233 TargetRegistry::RegisterMCInstPrinter(TheHexagonTarget, 234 createHexagonMCInstPrinter); 235 } 236