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