1 //===-- LanaiAsmPrinter.cpp - Lanai 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 the Lanai assembly language. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "InstPrinter/LanaiInstPrinter.h" 16 #include "Lanai.h" 17 #include "LanaiInstrInfo.h" 18 #include "LanaiMCInstLower.h" 19 #include "LanaiTargetMachine.h" 20 #include "llvm/CodeGen/AsmPrinter.h" 21 #include "llvm/CodeGen/MachineConstantPool.h" 22 #include "llvm/CodeGen/MachineFunctionPass.h" 23 #include "llvm/CodeGen/MachineInstr.h" 24 #include "llvm/CodeGen/MachineModuleInfo.h" 25 #include "llvm/IR/Constants.h" 26 #include "llvm/IR/DerivedTypes.h" 27 #include "llvm/IR/Mangler.h" 28 #include "llvm/IR/Module.h" 29 #include "llvm/MC/MCAsmInfo.h" 30 #include "llvm/MC/MCInst.h" 31 #include "llvm/MC/MCInstBuilder.h" 32 #include "llvm/MC/MCStreamer.h" 33 #include "llvm/MC/MCSymbol.h" 34 #include "llvm/Support/TargetRegistry.h" 35 #include "llvm/Support/raw_ostream.h" 36 37 #define DEBUG_TYPE "asm-printer" 38 39 using namespace llvm; 40 41 namespace { 42 class LanaiAsmPrinter : public AsmPrinter { 43 public: 44 explicit LanaiAsmPrinter(TargetMachine &TM, 45 std::unique_ptr<MCStreamer> Streamer) 46 : AsmPrinter(TM, std::move(Streamer)) {} 47 48 const char *getPassName() const override { return "Lanai Assembly Printer"; } 49 50 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, 51 const char *Modifier = 0); 52 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 53 unsigned AsmVariant, const char *ExtraCode, 54 raw_ostream &O) override; 55 void EmitInstruction(const MachineInstr *MI) override; 56 bool isBlockOnlyReachableByFallthrough( 57 const MachineBasicBlock *MBB) const override; 58 59 private: 60 void customEmitInstruction(const MachineInstr *MI); 61 void emitCallInstruction(const MachineInstr *MI); 62 }; 63 } // end of anonymous namespace 64 65 void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 66 raw_ostream &O, const char *Modifier) { 67 const MachineOperand &MO = MI->getOperand(OpNum); 68 unsigned TF = MO.getTargetFlags(); 69 70 switch (MO.getType()) { 71 case MachineOperand::MO_Register: 72 O << LanaiInstPrinter::getRegisterName(MO.getReg()); 73 break; 74 75 case MachineOperand::MO_Immediate: 76 O << MO.getImm(); 77 break; 78 79 case MachineOperand::MO_MachineBasicBlock: 80 O << *MO.getMBB()->getSymbol(); 81 break; 82 83 case MachineOperand::MO_GlobalAddress: 84 if (TF == LanaiII::MO_PLT) 85 O << "plt(" << *getSymbol(MO.getGlobal()) << ")"; 86 else 87 O << *getSymbol(MO.getGlobal()); 88 break; 89 90 case MachineOperand::MO_BlockAddress: { 91 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); 92 O << BA->getName(); 93 break; 94 } 95 96 case MachineOperand::MO_ExternalSymbol: 97 if (TF == LanaiII::MO_PLT) 98 O << "plt(" << *GetExternalSymbolSymbol(MO.getSymbolName()) << ")"; 99 else 100 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 101 break; 102 103 case MachineOperand::MO_JumpTableIndex: 104 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' 105 << MO.getIndex(); 106 break; 107 108 case MachineOperand::MO_ConstantPoolIndex: 109 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' 110 << MO.getIndex(); 111 return; 112 113 default: 114 llvm_unreachable("<unknown operand type>"); 115 } 116 } 117 118 // PrintAsmOperand - Print out an operand for an inline asm expression. 119 // 120 bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 121 unsigned AsmVariant, 122 const char *ExtraCode, raw_ostream &O) { 123 // Does this asm operand have a single letter operand modifier? 124 if (ExtraCode && ExtraCode[0]) { 125 if (ExtraCode[1]) 126 return true; // Unknown modifier. 127 128 switch (ExtraCode[0]) { 129 // The highest-numbered register of a pair. 130 case 'H': { 131 if (OpNo == 0) 132 return true; 133 const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1); 134 if (!FlagsOP.isImm()) 135 return true; 136 unsigned Flags = FlagsOP.getImm(); 137 unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); 138 if (NumVals != 2) 139 return true; 140 unsigned RegOp = OpNo + 1; 141 if (RegOp >= MI->getNumOperands()) 142 return true; 143 const MachineOperand &MO = MI->getOperand(RegOp); 144 if (!MO.isReg()) 145 return true; 146 unsigned Reg = MO.getReg(); 147 O << LanaiInstPrinter::getRegisterName(Reg); 148 return false; 149 } 150 default: 151 return true; // Unknown modifier. 152 } 153 } 154 printOperand(MI, OpNo, O); 155 return false; 156 } 157 158 //===----------------------------------------------------------------------===// 159 void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) { 160 assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) && 161 "Unsupported call function"); 162 163 LanaiMCInstLower MCInstLowering(OutContext, *Mang, *this); 164 MCSubtargetInfo STI = getSubtargetInfo(); 165 // Insert save rca instruction immediately before the call. 166 // TODO: We should generate a pc-relative mov instruction here instead 167 // of pc + 16 (should be mov .+16 %rca). 168 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO) 169 .addReg(Lanai::RCA) 170 .addReg(Lanai::PC) 171 .addImm(16), 172 STI); 173 174 // Push rca onto the stack. 175 // st %rca, [--%sp] 176 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::SW_RI) 177 .addReg(Lanai::RCA) 178 .addReg(Lanai::SP) 179 .addImm(-4) 180 .addImm(LPAC::makePreOp(LPAC::ADD)), 181 STI); 182 183 // Lower the call instruction. 184 if (MI->getOpcode() == Lanai::CALL) { 185 MCInst TmpInst; 186 MCInstLowering.Lower(MI, TmpInst); 187 TmpInst.setOpcode(Lanai::BT); 188 OutStreamer->EmitInstruction(TmpInst, STI); 189 } else { 190 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_R) 191 .addReg(Lanai::PC) 192 .addReg(MI->getOperand(0).getReg()) 193 .addReg(Lanai::R0) 194 .addImm(LPCC::ICC_T), 195 STI); 196 } 197 } 198 199 void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) { 200 LanaiMCInstLower MCInstLowering(OutContext, *Mang, *this); 201 MCSubtargetInfo STI = getSubtargetInfo(); 202 MCInst TmpInst; 203 MCInstLowering.Lower(MI, TmpInst); 204 OutStreamer->EmitInstruction(TmpInst, STI); 205 } 206 207 void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) { 208 MachineBasicBlock::const_instr_iterator I = MI->getIterator(); 209 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); 210 211 do { 212 if (I->isCall()) { 213 emitCallInstruction(&*I); 214 continue; 215 } 216 217 customEmitInstruction(&*I); 218 } while ((++I != E) && I->isInsideBundle()); 219 } 220 221 // isBlockOnlyReachableByFallthough - Return true if the basic block has 222 // exactly one predecessor and the control transfer mechanism between 223 // the predecessor and this block is a fall-through. 224 // FIXME: could the overridden cases be handled in AnalyzeBranch? 225 bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough( 226 const MachineBasicBlock *MBB) const { 227 // The predecessor has to be immediately before this block. 228 const MachineBasicBlock *Pred = *MBB->pred_begin(); 229 230 // If the predecessor is a switch statement, assume a jump table 231 // implementation, so it is not a fall through. 232 if (const BasicBlock *B = Pred->getBasicBlock()) 233 if (isa<SwitchInst>(B->getTerminator())) 234 return false; 235 236 // Check default implementation 237 if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB)) 238 return false; 239 240 // Otherwise, check the last instruction. 241 // Check if the last terminator is an unconditional branch. 242 MachineBasicBlock::const_iterator I = Pred->end(); 243 while (I != Pred->begin() && !(--I)->isTerminator()) { 244 } 245 246 return !I->isBarrier(); 247 } 248 249 // Force static initialization. 250 extern "C" void LLVMInitializeLanaiAsmPrinter() { 251 RegisterAsmPrinter<LanaiAsmPrinter> X(TheLanaiTarget); 252 } 253