//===-- SystemZMCInstLower.cpp - Lower MachineInstr to MCInst -------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "SystemZMCInstLower.h" #include "SystemZAsmPrinter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Target/Mangler.h" using namespace llvm; // Where relaxable pairs of reloc-generating instructions exist, // we tend to use the longest form by default, since that produces // correct assembly in cases where no relaxation is performed. // If Opcode is one such instruction, return the opcode for the // shortest possible form instead, otherwise return Opcode itself. static unsigned getShortenedInstr(unsigned Opcode) { switch (Opcode) { case SystemZ::BRCL: return SystemZ::BRC; case SystemZ::JG: return SystemZ::J; case SystemZ::BRASL: return SystemZ::BRAS; } return Opcode; } // Return the VK_* enumeration for MachineOperand target flags Flags. static MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) { switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) { case 0: return MCSymbolRefExpr::VK_None; case SystemZII::MO_GOT: return MCSymbolRefExpr::VK_GOT; } llvm_unreachable("Unrecognised MO_ACCESS_MODEL"); } SystemZMCInstLower::SystemZMCInstLower(Mangler *mang, MCContext &ctx, SystemZAsmPrinter &asmprinter) : Mang(mang), Ctx(ctx), AsmPrinter(asmprinter) {} MCOperand SystemZMCInstLower::lowerSymbolOperand(const MachineOperand &MO, const MCSymbol *Symbol, int64_t Offset) const { MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags()); const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); if (Offset) { const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); } return MCOperand::CreateExpr(Expr); } MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const { switch (MO.getType()) { default: llvm_unreachable("unknown operand type"); case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) return MCOperand(); return MCOperand::CreateReg(MO.getReg()); case MachineOperand::MO_Immediate: return MCOperand::CreateImm(MO.getImm()); case MachineOperand::MO_MachineBasicBlock: return lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), /* MO has no offset field */0); case MachineOperand::MO_GlobalAddress: return lowerSymbolOperand(MO, Mang->getSymbol(MO.getGlobal()), MO.getOffset()); case MachineOperand::MO_ExternalSymbol: { StringRef Name = MO.getSymbolName(); return lowerSymbolOperand(MO, AsmPrinter.GetExternalSymbolSymbol(Name), MO.getOffset()); } case MachineOperand::MO_JumpTableIndex: return lowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()), /* MO has no offset field */0); case MachineOperand::MO_ConstantPoolIndex: return lowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()), MO.getOffset()); case MachineOperand::MO_BlockAddress: { const BlockAddress *BA = MO.getBlockAddress(); return lowerSymbolOperand(MO, AsmPrinter.GetBlockAddressSymbol(BA), MO.getOffset()); } } } void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { unsigned Opcode = MI->getOpcode(); // When emitting binary code, start with the shortest form of an instruction // and then relax it where necessary. if (!AsmPrinter.OutStreamer.hasRawTextSupport()) Opcode = getShortenedInstr(Opcode); OutMI.setOpcode(Opcode); for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { const MachineOperand &MO = MI->getOperand(I); MCOperand MCOp = lowerOperand(MO); if (MCOp.isValid()) OutMI.addOperand(MCOp); } }