1 //===-- SystemZMCInstLower.cpp - Lower 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 #include "SystemZMCInstLower.h" 11 #include "SystemZAsmPrinter.h" 12 #include "llvm/MC/MCExpr.h" 13 #include "llvm/MC/MCStreamer.h" 14 #include "llvm/Target/Mangler.h" 15 16 using namespace llvm; 17 18 // If Opcode is an interprocedural reference that can be shortened, 19 // return the short form, otherwise return 0. 20 static unsigned getShortenedInstr(unsigned Opcode) { 21 switch (Opcode) { 22 case SystemZ::BRASL: return SystemZ::BRAS; 23 } 24 return Opcode; 25 } 26 27 // Return the VK_* enumeration for MachineOperand target flags Flags. 28 static MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) { 29 switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) { 30 case 0: 31 return MCSymbolRefExpr::VK_None; 32 case SystemZII::MO_GOT: 33 return MCSymbolRefExpr::VK_GOT; 34 } 35 llvm_unreachable("Unrecognised MO_ACCESS_MODEL"); 36 } 37 38 SystemZMCInstLower::SystemZMCInstLower(Mangler *mang, MCContext &ctx, 39 SystemZAsmPrinter &asmprinter) 40 : Mang(mang), Ctx(ctx), AsmPrinter(asmprinter) {} 41 42 MCOperand SystemZMCInstLower::lowerSymbolOperand(const MachineOperand &MO, 43 const MCSymbol *Symbol, 44 int64_t Offset) const { 45 MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags()); 46 const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); 47 if (Offset) { 48 const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 49 Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); 50 } 51 return MCOperand::CreateExpr(Expr); 52 } 53 54 MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const { 55 switch (MO.getType()) { 56 default: 57 llvm_unreachable("unknown operand type"); 58 59 case MachineOperand::MO_Register: 60 return MCOperand::CreateReg(MO.getReg()); 61 62 case MachineOperand::MO_Immediate: 63 return MCOperand::CreateImm(MO.getImm()); 64 65 case MachineOperand::MO_MachineBasicBlock: 66 return lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), 67 /* MO has no offset field */0); 68 69 case MachineOperand::MO_GlobalAddress: 70 return lowerSymbolOperand(MO, Mang->getSymbol(MO.getGlobal()), 71 MO.getOffset()); 72 73 case MachineOperand::MO_ExternalSymbol: { 74 StringRef Name = MO.getSymbolName(); 75 return lowerSymbolOperand(MO, AsmPrinter.GetExternalSymbolSymbol(Name), 76 MO.getOffset()); 77 } 78 79 case MachineOperand::MO_JumpTableIndex: 80 return lowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()), 81 /* MO has no offset field */0); 82 83 case MachineOperand::MO_ConstantPoolIndex: 84 return lowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()), 85 MO.getOffset()); 86 87 case MachineOperand::MO_BlockAddress: { 88 const BlockAddress *BA = MO.getBlockAddress(); 89 return lowerSymbolOperand(MO, AsmPrinter.GetBlockAddressSymbol(BA), 90 MO.getOffset()); 91 } 92 } 93 } 94 95 void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { 96 unsigned Opcode = MI->getOpcode(); 97 // When emitting binary code, start with the shortest form of an instruction 98 // and then relax it where necessary. 99 if (!AsmPrinter.OutStreamer.hasRawTextSupport()) 100 Opcode = getShortenedInstr(Opcode); 101 OutMI.setOpcode(Opcode); 102 for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { 103 const MachineOperand &MO = MI->getOperand(I); 104 // Ignore all implicit register operands. 105 if (!MO.isReg() || !MO.isImplicit()) 106 OutMI.addOperand(lowerOperand(MO)); 107 } 108 } 109