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 // Ignore all implicit register operands. 61 if (MO.isImplicit()) 62 return MCOperand(); 63 return MCOperand::CreateReg(MO.getReg()); 64 65 case MachineOperand::MO_Immediate: 66 return MCOperand::CreateImm(MO.getImm()); 67 68 case MachineOperand::MO_MachineBasicBlock: 69 return lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), 70 /* MO has no offset field */0); 71 72 case MachineOperand::MO_GlobalAddress: 73 return lowerSymbolOperand(MO, Mang->getSymbol(MO.getGlobal()), 74 MO.getOffset()); 75 76 case MachineOperand::MO_ExternalSymbol: { 77 StringRef Name = MO.getSymbolName(); 78 return lowerSymbolOperand(MO, AsmPrinter.GetExternalSymbolSymbol(Name), 79 MO.getOffset()); 80 } 81 82 case MachineOperand::MO_JumpTableIndex: 83 return lowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()), 84 /* MO has no offset field */0); 85 86 case MachineOperand::MO_ConstantPoolIndex: 87 return lowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()), 88 MO.getOffset()); 89 90 case MachineOperand::MO_BlockAddress: { 91 const BlockAddress *BA = MO.getBlockAddress(); 92 return lowerSymbolOperand(MO, AsmPrinter.GetBlockAddressSymbol(BA), 93 MO.getOffset()); 94 } 95 } 96 } 97 98 void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { 99 unsigned Opcode = MI->getOpcode(); 100 // When emitting binary code, start with the shortest form of an instruction 101 // and then relax it where necessary. 102 if (!AsmPrinter.OutStreamer.hasRawTextSupport()) 103 Opcode = getShortenedInstr(Opcode); 104 OutMI.setOpcode(Opcode); 105 for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { 106 const MachineOperand &MO = MI->getOperand(I); 107 MCOperand MCOp = lowerOperand(MO); 108 if (MCOp.isValid()) 109 OutMI.addOperand(MCOp); 110 } 111 } 112