1251607Sdim//===-- SystemZMCInstLower.cpp - Lower MachineInstr to MCInst -------------===// 2251607Sdim// 3251607Sdim// The LLVM Compiler Infrastructure 4251607Sdim// 5251607Sdim// This file is distributed under the University of Illinois Open Source 6251607Sdim// License. See LICENSE.TXT for details. 7251607Sdim// 8251607Sdim//===----------------------------------------------------------------------===// 9251607Sdim 10251607Sdim#include "SystemZMCInstLower.h" 11251607Sdim#include "SystemZAsmPrinter.h" 12251607Sdim#include "llvm/MC/MCExpr.h" 13251607Sdim#include "llvm/MC/MCStreamer.h" 14251607Sdim#include "llvm/Target/Mangler.h" 15251607Sdim 16251607Sdimusing namespace llvm; 17251607Sdim 18251607Sdim// Where relaxable pairs of reloc-generating instructions exist, 19251607Sdim// we tend to use the longest form by default, since that produces 20251607Sdim// correct assembly in cases where no relaxation is performed. 21251607Sdim// If Opcode is one such instruction, return the opcode for the 22251607Sdim// shortest possible form instead, otherwise return Opcode itself. 23251607Sdimstatic unsigned getShortenedInstr(unsigned Opcode) { 24251607Sdim switch (Opcode) { 25251607Sdim case SystemZ::BRCL: return SystemZ::BRC; 26251607Sdim case SystemZ::JG: return SystemZ::J; 27251607Sdim case SystemZ::BRASL: return SystemZ::BRAS; 28251607Sdim } 29251607Sdim return Opcode; 30251607Sdim} 31251607Sdim 32251607Sdim// Return the VK_* enumeration for MachineOperand target flags Flags. 33251607Sdimstatic MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) { 34251607Sdim switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) { 35251607Sdim case 0: 36251607Sdim return MCSymbolRefExpr::VK_None; 37251607Sdim case SystemZII::MO_GOT: 38251607Sdim return MCSymbolRefExpr::VK_GOT; 39251607Sdim } 40251607Sdim llvm_unreachable("Unrecognised MO_ACCESS_MODEL"); 41251607Sdim} 42251607Sdim 43251607SdimSystemZMCInstLower::SystemZMCInstLower(Mangler *mang, MCContext &ctx, 44251607Sdim SystemZAsmPrinter &asmprinter) 45251607Sdim : Mang(mang), Ctx(ctx), AsmPrinter(asmprinter) {} 46251607Sdim 47251607SdimMCOperand SystemZMCInstLower::lowerSymbolOperand(const MachineOperand &MO, 48251607Sdim const MCSymbol *Symbol, 49251607Sdim int64_t Offset) const { 50251607Sdim MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags()); 51251607Sdim const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); 52251607Sdim if (Offset) { 53251607Sdim const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 54251607Sdim Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); 55251607Sdim } 56251607Sdim return MCOperand::CreateExpr(Expr); 57251607Sdim} 58251607Sdim 59251607SdimMCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const { 60251607Sdim switch (MO.getType()) { 61251607Sdim default: 62251607Sdim llvm_unreachable("unknown operand type"); 63251607Sdim 64251607Sdim case MachineOperand::MO_Register: 65251607Sdim // Ignore all implicit register operands. 66251607Sdim if (MO.isImplicit()) 67251607Sdim return MCOperand(); 68251607Sdim return MCOperand::CreateReg(MO.getReg()); 69251607Sdim 70251607Sdim case MachineOperand::MO_Immediate: 71251607Sdim return MCOperand::CreateImm(MO.getImm()); 72251607Sdim 73251607Sdim case MachineOperand::MO_MachineBasicBlock: 74251607Sdim return lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), 75251607Sdim /* MO has no offset field */0); 76251607Sdim 77251607Sdim case MachineOperand::MO_GlobalAddress: 78251607Sdim return lowerSymbolOperand(MO, Mang->getSymbol(MO.getGlobal()), 79251607Sdim MO.getOffset()); 80251607Sdim 81251607Sdim case MachineOperand::MO_ExternalSymbol: { 82251607Sdim StringRef Name = MO.getSymbolName(); 83251607Sdim return lowerSymbolOperand(MO, AsmPrinter.GetExternalSymbolSymbol(Name), 84251607Sdim MO.getOffset()); 85251607Sdim } 86251607Sdim 87251607Sdim case MachineOperand::MO_JumpTableIndex: 88251607Sdim return lowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()), 89251607Sdim /* MO has no offset field */0); 90251607Sdim 91251607Sdim case MachineOperand::MO_ConstantPoolIndex: 92251607Sdim return lowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()), 93251607Sdim MO.getOffset()); 94251607Sdim 95251607Sdim case MachineOperand::MO_BlockAddress: { 96251607Sdim const BlockAddress *BA = MO.getBlockAddress(); 97251607Sdim return lowerSymbolOperand(MO, AsmPrinter.GetBlockAddressSymbol(BA), 98251607Sdim MO.getOffset()); 99251607Sdim } 100251607Sdim } 101251607Sdim} 102251607Sdim 103251607Sdimvoid SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { 104251607Sdim unsigned Opcode = MI->getOpcode(); 105251607Sdim // When emitting binary code, start with the shortest form of an instruction 106251607Sdim // and then relax it where necessary. 107251607Sdim if (!AsmPrinter.OutStreamer.hasRawTextSupport()) 108251607Sdim Opcode = getShortenedInstr(Opcode); 109251607Sdim OutMI.setOpcode(Opcode); 110251607Sdim for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { 111251607Sdim const MachineOperand &MO = MI->getOperand(I); 112251607Sdim MCOperand MCOp = lowerOperand(MO); 113251607Sdim if (MCOp.isValid()) 114251607Sdim OutMI.addOperand(MCOp); 115251607Sdim } 116251607Sdim} 117