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