1167465Smp//===-- M68kMCInstLower.cpp - M68k MachineInstr to MCInst -------*- C++ -*-===//
259243Sobrien//
359243Sobrien// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
459243Sobrien// See https://llvm.org/LICENSE.txt for license information.
559243Sobrien// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659243Sobrien//
759243Sobrien//===----------------------------------------------------------------------===//
859243Sobrien///
959243Sobrien/// \file
1059243Sobrien/// This file contains code to lower M68k MachineInstrs to their
11100616Smp/// corresponding MCInst records.
1259243Sobrien///
1359243Sobrien//===----------------------------------------------------------------------===//
1459243Sobrien
1559243Sobrien#include "M68kMCInstLower.h"
1659243Sobrien
1759243Sobrien#include "M68kAsmPrinter.h"
1859243Sobrien#include "M68kInstrInfo.h"
1959243Sobrien
2059243Sobrien#include "MCTargetDesc/M68kBaseInfo.h"
2159243Sobrien
2259243Sobrien#include "llvm/CodeGen/MachineFunction.h"
2359243Sobrien#include "llvm/CodeGen/MachineInstr.h"
2459243Sobrien#include "llvm/CodeGen/MachineOperand.h"
2559243Sobrien#include "llvm/IR/Mangler.h"
2659243Sobrien#include "llvm/MC/MCContext.h"
2759243Sobrien#include "llvm/MC/MCExpr.h"
2859243Sobrien#include "llvm/MC/MCInst.h"
2959243Sobrien
3059243Sobrienusing namespace llvm;
3159243Sobrien
3259243Sobrien#define DEBUG_TYPE "m68k-mc-inst-lower"
3359243Sobrien
3459243SobrienM68kMCInstLower::M68kMCInstLower(MachineFunction &MF, M68kAsmPrinter &AP)
3559243Sobrien    : Ctx(MF.getContext()), MF(MF), TM(MF.getTarget()), MAI(*TM.getMCAsmInfo()),
3659243Sobrien      AsmPrinter(AP) {}
3759243Sobrien
3859243SobrienMCSymbol *
3959243SobrienM68kMCInstLower::GetSymbolFromOperand(const MachineOperand &MO) const {
4059243Sobrien  assert((MO.isGlobal() || MO.isSymbol() || MO.isMBB()) &&
4159243Sobrien         "Isn't a symbol reference");
4259243Sobrien
4359243Sobrien  const auto &TT = TM.getTargetTriple();
4459243Sobrien  if (MO.isGlobal() && TT.isOSBinFormatELF())
4559243Sobrien    return AsmPrinter.getSymbolPreferLocal(*MO.getGlobal());
4659243Sobrien
4759243Sobrien  const DataLayout &DL = MF.getDataLayout();
4859243Sobrien
4959243Sobrien  MCSymbol *Sym = nullptr;
5059243Sobrien  SmallString<128> Name;
5159243Sobrien  StringRef Suffix;
5259243Sobrien
5359243Sobrien  if (!Suffix.empty())
5459243Sobrien    Name += DL.getPrivateGlobalPrefix();
5559243Sobrien
5659243Sobrien  if (MO.isGlobal()) {
5759243Sobrien    const GlobalValue *GV = MO.getGlobal();
5859243Sobrien    AsmPrinter.getNameWithPrefix(Name, GV);
5959243Sobrien  } else if (MO.isSymbol()) {
6059243Sobrien    Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL);
6159243Sobrien  } else if (MO.isMBB()) {
6259243Sobrien    assert(Suffix.empty());
6359243Sobrien    Sym = MO.getMBB()->getSymbol();
6459243Sobrien  }
6559243Sobrien
6659243Sobrien  Name += Suffix;
6759243Sobrien  if (!Sym)
6859243Sobrien    Sym = Ctx.getOrCreateSymbol(Name);
6959243Sobrien
7059243Sobrien  return Sym;
7159243Sobrien}
7259243Sobrien
7359243SobrienMCOperand M68kMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
7459243Sobrien                                              MCSymbol *Sym) const {
7559243Sobrien  // FIXME We would like an efficient form for this, so we don't have to do a
7659243Sobrien  // lot of extra uniquing. This fixme is originally from X86
7759243Sobrien  const MCExpr *Expr = nullptr;
7859243Sobrien  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
7959243Sobrien
8059243Sobrien  switch (MO.getTargetFlags()) {
8159243Sobrien  default:
8259243Sobrien    llvm_unreachable("Unknown target flag on GV operand");
8359243Sobrien  case M68kII::MO_NO_FLAG:
8459243Sobrien  case M68kII::MO_ABSOLUTE_ADDRESS:
8559243Sobrien  case M68kII::MO_PC_RELATIVE_ADDRESS:
8659243Sobrien    break;
8759243Sobrien  case M68kII::MO_GOTPCREL:
8859243Sobrien    RefKind = MCSymbolRefExpr::VK_GOTPCREL;
8959243Sobrien    break;
9059243Sobrien  case M68kII::MO_GOT:
9159243Sobrien    RefKind = MCSymbolRefExpr::VK_GOT;
9259243Sobrien    break;
9359243Sobrien  case M68kII::MO_GOTOFF:
9459243Sobrien    RefKind = MCSymbolRefExpr::VK_GOTOFF;
9559243Sobrien    break;
9659243Sobrien  case M68kII::MO_PLT:
9759243Sobrien    RefKind = MCSymbolRefExpr::VK_PLT;
9859243Sobrien    break;
9959243Sobrien  case M68kII::MO_TLSGD:
10059243Sobrien    RefKind = MCSymbolRefExpr::VK_TLSGD;
10159243Sobrien    break;
10259243Sobrien  case M68kII::MO_TLSLD:
10359243Sobrien    RefKind = MCSymbolRefExpr::VK_TLSLD;
10459243Sobrien    break;
10559243Sobrien  case M68kII::MO_TLSLDM:
10659243Sobrien    RefKind = MCSymbolRefExpr::VK_TLSLDM;
10759243Sobrien    break;
10859243Sobrien  case M68kII::MO_TLSIE:
10959243Sobrien    RefKind = MCSymbolRefExpr::VK_GOTTPOFF;
11059243Sobrien    break;
11159243Sobrien  case M68kII::MO_TLSLE:
11259243Sobrien    RefKind = MCSymbolRefExpr::VK_TPOFF;
11359243Sobrien    break;
11459243Sobrien  }
11559243Sobrien
11659243Sobrien  if (!Expr) {
11759243Sobrien    Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
11859243Sobrien  }
11959243Sobrien
12059243Sobrien  if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) {
12159243Sobrien    Expr = MCBinaryExpr::createAdd(
12259243Sobrien        Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
12359243Sobrien  }
12459243Sobrien
12559243Sobrien  return MCOperand::createExpr(Expr);
12659243Sobrien}
12759243Sobrien
12859243Sobrienstd::optional<MCOperand>
12959243SobrienM68kMCInstLower::LowerOperand(const MachineInstr *MI,
13059243Sobrien                              const MachineOperand &MO) const {
13159243Sobrien  switch (MO.getType()) {
13259243Sobrien  default:
13359243Sobrien    llvm_unreachable("unknown operand type");
13459243Sobrien  case MachineOperand::MO_Register:
13559243Sobrien    // Ignore all implicit register operands.
13659243Sobrien    if (MO.isImplicit())
13759243Sobrien      return std::nullopt;
13859243Sobrien    return MCOperand::createReg(MO.getReg());
13959243Sobrien  case MachineOperand::MO_Immediate:
14059243Sobrien    return MCOperand::createImm(MO.getImm());
14159243Sobrien  case MachineOperand::MO_MachineBasicBlock:
14259243Sobrien  case MachineOperand::MO_GlobalAddress:
14359243Sobrien  case MachineOperand::MO_ExternalSymbol:
14459243Sobrien    return LowerSymbolOperand(MO, GetSymbolFromOperand(MO));
14559243Sobrien  case MachineOperand::MO_MCSymbol:
14659243Sobrien    return LowerSymbolOperand(MO, MO.getMCSymbol());
14759243Sobrien  case MachineOperand::MO_JumpTableIndex:
14859243Sobrien    return LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()));
14959243Sobrien  case MachineOperand::MO_ConstantPoolIndex:
15059243Sobrien    return LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()));
15159243Sobrien  case MachineOperand::MO_BlockAddress:
15259243Sobrien    return LowerSymbolOperand(
15359243Sobrien        MO, AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()));
15459243Sobrien  case MachineOperand::MO_RegisterMask:
15559243Sobrien    // Ignore call clobbers.
15659243Sobrien    return std::nullopt;
15759243Sobrien  }
15859243Sobrien}
15959243Sobrien
16059243Sobrienvoid M68kMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
16159243Sobrien  unsigned Opcode = MI->getOpcode();
16259243Sobrien  OutMI.setOpcode(Opcode);
16359243Sobrien
16459243Sobrien  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
16559243Sobrien    const MachineOperand &MO = MI->getOperand(i);
16659243Sobrien    std::optional<MCOperand> MCOp = LowerOperand(MI, MO);
16759243Sobrien
16859243Sobrien    if (MCOp.has_value() && MCOp.value().isValid())
16959243Sobrien      OutMI.addOperand(MCOp.value());
17059243Sobrien  }
17159243Sobrien
17259243Sobrien  // TAILJMPj, TAILJMPq - Lower to the correct jump instructions.
17359243Sobrien  if (Opcode == M68k::TAILJMPj || Opcode == M68k::TAILJMPq) {
17459243Sobrien    assert(OutMI.getNumOperands() == 1 && "Unexpected number of operands");
17559243Sobrien    switch (Opcode) {
17659243Sobrien    case M68k::TAILJMPj:
17759243Sobrien      Opcode = M68k::JMP32j;
17859243Sobrien      break;
17959243Sobrien    case M68k::TAILJMPq:
18059243Sobrien      Opcode = M68k::BRA8;
18159243Sobrien      break;
18259243Sobrien    }
18359243Sobrien    OutMI.setOpcode(Opcode);
18459243Sobrien  }
18559243Sobrien}
18659243Sobrien