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