MipsMCInstLower.cpp revision ce1a538ab5b7ae7e0ed48d18c02571280fe105aa
1//===-- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ---------===// 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 code to lower Mips MachineInstrs to their corresponding 11// MCInst records. 12// 13//===----------------------------------------------------------------------===// 14 15#include "MipsAsmPrinter.h" 16#include "MipsInstrInfo.h" 17#include "MipsMCInstLower.h" 18#include "llvm/CodeGen/MachineFunction.h" 19#include "llvm/CodeGen/MachineInstr.h" 20#include "llvm/CodeGen/MachineOperand.h" 21#include "llvm/MC/MCContext.h" 22#include "llvm/MC/MCExpr.h" 23#include "llvm/MC/MCInst.h" 24#include "llvm/Target/Mangler.h" 25using namespace llvm; 26 27MipsMCInstLower::MipsMCInstLower(Mangler *mang, const MachineFunction &mf, 28 MipsAsmPrinter &asmprinter) 29 : Ctx(mf.getContext()), Mang(mang), AsmPrinter(asmprinter) {} 30 31MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, 32 MachineOperandType MOTy, 33 unsigned Offset) const { 34 MCSymbolRefExpr::VariantKind Kind; 35 const MCSymbol *Symbol; 36 37 switch(MO.getTargetFlags()) { 38 default: assert(0 && "Invalid target flag!"); 39 case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break; 40 case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break; 41 case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break; 42 case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break; 43 case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; 44 case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break; 45 case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break; 46 case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; 47 case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; 48 case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; 49 case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break; 50 case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break; 51 case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; 52 case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; 53 case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; 54 } 55 56 switch (MOTy) { 57 case MachineOperand::MO_MachineBasicBlock: 58 Symbol = MO.getMBB()->getSymbol(); 59 break; 60 61 case MachineOperand::MO_GlobalAddress: 62 Symbol = Mang->getSymbol(MO.getGlobal()); 63 break; 64 65 case MachineOperand::MO_BlockAddress: 66 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); 67 break; 68 69 case MachineOperand::MO_ExternalSymbol: 70 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); 71 break; 72 73 case MachineOperand::MO_JumpTableIndex: 74 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); 75 break; 76 77 case MachineOperand::MO_ConstantPoolIndex: 78 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); 79 if (MO.getOffset()) 80 Offset += MO.getOffset(); 81 break; 82 83 default: 84 llvm_unreachable("<unknown operand type>"); 85 } 86 87 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); 88 89 if (!Offset) 90 return MCOperand::CreateExpr(MCSym); 91 92 // Assume offset is never negative. 93 assert(Offset > 0); 94 95 const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 96 const MCBinaryExpr *AddExpr = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, Ctx); 97 return MCOperand::CreateExpr(AddExpr); 98} 99 100// Lower ".cpload $reg" to 101// "lui $gp, %hi(_gp_disp)" 102// "addiu $gp, $gp, %lo(_gp_disp)" 103// "addu $gp. $gp, $reg" 104void MipsMCInstLower::LowerCPLOAD(const MachineInstr *MI, 105 SmallVector<MCInst, 4>& MCInsts) { 106 MCInst Lui, Addiu, Addu; 107 StringRef SymName("_gp_disp"); 108 const MCSymbol *Symbol = Ctx.GetOrCreateSymbol(SymName); 109 const MCSymbolRefExpr *MCSym; 110 111 // lui $gp, %hi(_gp_disp) 112 Lui.setOpcode(Mips::LUi); 113 Lui.addOperand(MCOperand::CreateReg(Mips::GP)); 114 MCSym = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_Mips_ABS_HI, Ctx); 115 Lui.addOperand(MCOperand::CreateExpr(MCSym)); 116 MCInsts.push_back(Lui); 117 118 // addiu $gp, $gp, %lo(_gp_disp) 119 Addiu.setOpcode(Mips::ADDiu); 120 Addiu.addOperand(MCOperand::CreateReg(Mips::GP)); 121 Addiu.addOperand(MCOperand::CreateReg(Mips::GP)); 122 MCSym = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_Mips_ABS_LO, Ctx); 123 Addiu.addOperand(MCOperand::CreateExpr(MCSym)); 124 MCInsts.push_back(Addiu); 125 126 // addu $gp. $gp, $reg 127 Addu.setOpcode(Mips::ADDu); 128 Addu.addOperand(MCOperand::CreateReg(Mips::GP)); 129 Addu.addOperand(MCOperand::CreateReg(Mips::GP)); 130 const MachineOperand &MO = MI->getOperand(0); 131 assert(MO.isReg() && "CPLOAD's operand must be a register."); 132 Addu.addOperand(MCOperand::CreateReg(MO.getReg())); 133 MCInsts.push_back(Addu); 134} 135 136// Lower ".cprestore offset" to "sw $gp, offset($sp)". 137void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, MCInst &OutMI) { 138 OutMI.clear(); 139 OutMI.setOpcode(Mips::SW); 140 OutMI.addOperand(MCOperand::CreateReg(Mips::GP)); 141 OutMI.addOperand(MCOperand::CreateReg(Mips::SP)); 142 const MachineOperand &MO = MI->getOperand(0); 143 assert(MO.isImm() && "CPRESTORE's operand must be an immediate."); 144 OutMI.addOperand(MCOperand::CreateImm(MO.getImm())); 145} 146 147 148MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO) const { 149 MachineOperandType MOTy = MO.getType(); 150 151 switch (MOTy) { 152 default: 153 assert(0 && "unknown operand type"); 154 break; 155 case MachineOperand::MO_Register: 156 // Ignore all implicit register operands. 157 if (MO.isImplicit()) break; 158 return MCOperand::CreateReg(MO.getReg()); 159 case MachineOperand::MO_Immediate: 160 return MCOperand::CreateImm(MO.getImm()); 161 case MachineOperand::MO_MachineBasicBlock: 162 case MachineOperand::MO_GlobalAddress: 163 case MachineOperand::MO_ExternalSymbol: 164 case MachineOperand::MO_JumpTableIndex: 165 case MachineOperand::MO_ConstantPoolIndex: 166 case MachineOperand::MO_BlockAddress: 167 return LowerSymbolOperand(MO, MOTy, 0); 168 } 169 170 return MCOperand(); 171} 172 173void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 174 OutMI.setOpcode(MI->getOpcode()); 175 176 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 177 const MachineOperand &MO = MI->getOperand(i); 178 MCOperand MCOp = LowerOperand(MO); 179 180 if (MCOp.isValid()) 181 OutMI.addOperand(MCOp); 182 } 183} 184