142205Sdes//===-- SystemZMCInstLower.cpp - Lower MachineInstr to MCInst -------------===//
2230132Suqs//
342205Sdes// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
442205Sdes// See https://llvm.org/LICENSE.txt for license information.
542205Sdes// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
642205Sdes//
742205Sdes//===----------------------------------------------------------------------===//
842205Sdes
942205Sdes#include "SystemZMCInstLower.h"
1042205Sdes#include "SystemZAsmPrinter.h"
1142205Sdes#include "llvm/IR/Mangler.h"
1242205Sdes#include "llvm/MC/MCExpr.h"
1342205Sdes#include "llvm/MC/MCInst.h"
1442205Sdes#include "llvm/MC/MCStreamer.h"
1542205Sdes
1642205Sdesusing namespace llvm;
1742205Sdes
1842205Sdes// Return the VK_* enumeration for MachineOperand target flags Flags.
1942205Sdesstatic MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) {
2042205Sdes  switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) {
2142205Sdes    case 0:
2242205Sdes      return MCSymbolRefExpr::VK_None;
2342205Sdes    case SystemZII::MO_GOT:
2442205Sdes      return MCSymbolRefExpr::VK_GOT;
2542205Sdes    case SystemZII::MO_INDNTPOFF:
2642205Sdes      return MCSymbolRefExpr::VK_INDNTPOFF;
2742205Sdes  }
2850477Speter  llvm_unreachable("Unrecognised MO_ACCESS_MODEL");
2942205Sdes}
3042205Sdes
3142205SdesSystemZMCInstLower::SystemZMCInstLower(MCContext &ctx,
3242205Sdes                                       SystemZAsmPrinter &asmprinter)
3342205Sdes  : Ctx(ctx), AsmPrinter(asmprinter) {}
3442205Sdes
3542205Sdesconst MCExpr *
3648104SyokotaSystemZMCInstLower::getExpr(const MachineOperand &MO,
3748104Syokota                            MCSymbolRefExpr::VariantKind Kind) const {
3842205Sdes  const MCSymbol *Symbol;
3948104Syokota  bool HasOffset = true;
4048104Syokota  switch (MO.getType()) {
4148104Syokota  case MachineOperand::MO_MachineBasicBlock:
4242205Sdes    Symbol = MO.getMBB()->getSymbol();
4386120Sdes    HasOffset = false;
44110235Salfred    break;
45110235Salfred
46110235Salfred  case MachineOperand::MO_GlobalAddress:
4786122Sdes    Symbol = AsmPrinter.getSymbol(MO.getGlobal());
4886122Sdes    break;
4942205Sdes
5086122Sdes  case MachineOperand::MO_ExternalSymbol:
5186122Sdes    Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
5286122Sdes    break;
5386122Sdes
54166868Sphilip  case MachineOperand::MO_JumpTableIndex:
55166868Sphilip    Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
56166868Sphilip    HasOffset = false;
57174985Swkoszek    break;
58166868Sphilip
59166868Sphilip  case MachineOperand::MO_ConstantPoolIndex:
6086120Sdes    Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
6193011Samorita    break;
6286120Sdes
6386120Sdes  case MachineOperand::MO_BlockAddress:
6442205Sdes    Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
6542205Sdes    break;
6642504Syokota
6742205Sdes  default:
6886120Sdes    llvm_unreachable("unknown operand type");
6986122Sdes  }
7086122Sdes  const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, Ctx);
7186122Sdes  if (HasOffset)
7286122Sdes    if (int64_t Offset = MO.getOffset()) {
7386122Sdes      const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
74174985Swkoszek      Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
7542205Sdes    }
7642205Sdes  return Expr;
7742504Syokota}
7842504Syokota
7942205SdesMCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
8093115Sbrooks  switch (MO.getType()) {
8193011Samorita  case MachineOperand::MO_Register:
82166868Sphilip    return MCOperand::createReg(MO.getReg());
8393011Samorita
8486120Sdes  case MachineOperand::MO_Immediate:
8586120Sdes    return MCOperand::createImm(MO.getImm());
8686120Sdes
8786120Sdes  default: {
88174985Swkoszek    MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags());
89174985Swkoszek    return MCOperand::createExpr(getExpr(MO, Kind));
90174985Swkoszek  }
9186120Sdes  }
9286120Sdes}
9393011Samorita
9493011Samoritavoid SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
9586120Sdes  OutMI.setOpcode(MI->getOpcode());
9693011Samorita  for (const MachineOperand &MO : MI->operands())
97166868Sphilip    // Ignore all implicit register operands.
9893011Samorita    if (!MO.isReg() || !MO.isImplicit())
9993011Samorita      OutMI.addOperand(lowerOperand(MO));
10093011Samorita}
10193011Samorita