xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
181ad6265SDimitry Andric //=- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to an MCInst -=//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric // This file contains code to lower LoongArch MachineInstrs to their
1081ad6265SDimitry Andric // corresponding MCInst records.
1181ad6265SDimitry Andric //
1281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric #include "LoongArch.h"
1581ad6265SDimitry Andric #include "LoongArchSubtarget.h"
16*bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h"
17*bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchMCExpr.h"
1881ad6265SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
1981ad6265SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
2081ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
2181ad6265SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
2281ad6265SDimitry Andric #include "llvm/MC/MCContext.h"
2381ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric using namespace llvm;
2681ad6265SDimitry Andric 
27753f127fSDimitry Andric static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
28753f127fSDimitry Andric                                     const AsmPrinter &AP) {
29753f127fSDimitry Andric   MCContext &Ctx = AP.OutContext;
30*bdd1243dSDimitry Andric   LoongArchMCExpr::VariantKind Kind;
31753f127fSDimitry Andric 
32*bdd1243dSDimitry Andric   switch (MO.getTargetFlags()) {
33*bdd1243dSDimitry Andric   default:
34*bdd1243dSDimitry Andric     llvm_unreachable("Unknown target flag on GV operand");
35*bdd1243dSDimitry Andric   case LoongArchII::MO_None:
36*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_None;
37*bdd1243dSDimitry Andric     break;
38*bdd1243dSDimitry Andric   case LoongArchII::MO_CALL:
39*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_CALL;
40*bdd1243dSDimitry Andric     break;
41*bdd1243dSDimitry Andric   case LoongArchII::MO_CALL_PLT:
42*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_CALL_PLT;
43*bdd1243dSDimitry Andric     break;
44*bdd1243dSDimitry Andric   case LoongArchII::MO_PCREL_HI:
45*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_PCALA_HI20;
46*bdd1243dSDimitry Andric     break;
47*bdd1243dSDimitry Andric   case LoongArchII::MO_PCREL_LO:
48*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
49*bdd1243dSDimitry Andric     break;
50*bdd1243dSDimitry Andric   case LoongArchII::MO_GOT_PC_HI:
51*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20;
52*bdd1243dSDimitry Andric     break;
53*bdd1243dSDimitry Andric   case LoongArchII::MO_GOT_PC_LO:
54*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12;
55*bdd1243dSDimitry Andric     break;
56*bdd1243dSDimitry Andric   case LoongArchII::MO_LE_HI:
57*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
58*bdd1243dSDimitry Andric     break;
59*bdd1243dSDimitry Andric   case LoongArchII::MO_LE_LO:
60*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12;
61*bdd1243dSDimitry Andric     break;
62*bdd1243dSDimitry Andric   case LoongArchII::MO_IE_PC_HI:
63*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20;
64*bdd1243dSDimitry Andric     break;
65*bdd1243dSDimitry Andric   case LoongArchII::MO_IE_PC_LO:
66*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
67*bdd1243dSDimitry Andric     break;
68*bdd1243dSDimitry Andric   case LoongArchII::MO_LD_PC_HI:
69*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20;
70*bdd1243dSDimitry Andric     break;
71*bdd1243dSDimitry Andric   case LoongArchII::MO_GD_PC_HI:
72*bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
73*bdd1243dSDimitry Andric     break;
74*bdd1243dSDimitry Andric     // TODO: Handle more target-flags.
75*bdd1243dSDimitry Andric   }
76753f127fSDimitry Andric 
77753f127fSDimitry Andric   const MCExpr *ME =
78753f127fSDimitry Andric       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
79753f127fSDimitry Andric 
80753f127fSDimitry Andric   if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
81753f127fSDimitry Andric     ME = MCBinaryExpr::createAdd(
82753f127fSDimitry Andric         ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
83753f127fSDimitry Andric 
84*bdd1243dSDimitry Andric   if (Kind != LoongArchMCExpr::VK_LoongArch_None)
85*bdd1243dSDimitry Andric     ME = LoongArchMCExpr::create(ME, Kind, Ctx);
86753f127fSDimitry Andric   return MCOperand::createExpr(ME);
87753f127fSDimitry Andric }
88753f127fSDimitry Andric 
8981ad6265SDimitry Andric bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
9081ad6265SDimitry Andric                                                    MCOperand &MCOp,
9181ad6265SDimitry Andric                                                    const AsmPrinter &AP) {
9281ad6265SDimitry Andric   switch (MO.getType()) {
9381ad6265SDimitry Andric   default:
9481ad6265SDimitry Andric     report_fatal_error(
9581ad6265SDimitry Andric         "lowerLoongArchMachineOperandToMCOperand: unknown operand type");
9681ad6265SDimitry Andric   case MachineOperand::MO_Register:
9781ad6265SDimitry Andric     // Ignore all implicit register operands.
9881ad6265SDimitry Andric     if (MO.isImplicit())
9981ad6265SDimitry Andric       return false;
10081ad6265SDimitry Andric     MCOp = MCOperand::createReg(MO.getReg());
10181ad6265SDimitry Andric     break;
10281ad6265SDimitry Andric   case MachineOperand::MO_RegisterMask:
10381ad6265SDimitry Andric     // Regmasks are like implicit defs.
10481ad6265SDimitry Andric     return false;
10581ad6265SDimitry Andric   case MachineOperand::MO_Immediate:
10681ad6265SDimitry Andric     MCOp = MCOperand::createImm(MO.getImm());
10781ad6265SDimitry Andric     break;
10881ad6265SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
109753f127fSDimitry Andric     MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP);
110753f127fSDimitry Andric     break;
111753f127fSDimitry Andric   case MachineOperand::MO_GlobalAddress:
112753f127fSDimitry Andric     MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP);
113753f127fSDimitry Andric     break;
114753f127fSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
115753f127fSDimitry Andric     MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP);
116753f127fSDimitry Andric     break;
117753f127fSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
118753f127fSDimitry Andric     MCOp = lowerSymbolOperand(
119753f127fSDimitry Andric         MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
120753f127fSDimitry Andric     break;
121753f127fSDimitry Andric   case MachineOperand::MO_BlockAddress:
122*bdd1243dSDimitry Andric     MCOp = lowerSymbolOperand(
123*bdd1243dSDimitry Andric         MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
124*bdd1243dSDimitry Andric     break;
12581ad6265SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
126*bdd1243dSDimitry Andric     MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);
12781ad6265SDimitry Andric     break;
12881ad6265SDimitry Andric   }
12981ad6265SDimitry Andric   return true;
13081ad6265SDimitry Andric }
13181ad6265SDimitry Andric 
13281ad6265SDimitry Andric bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI,
13381ad6265SDimitry Andric                                               MCInst &OutMI, AsmPrinter &AP) {
13481ad6265SDimitry Andric   OutMI.setOpcode(MI->getOpcode());
13581ad6265SDimitry Andric 
13681ad6265SDimitry Andric   for (const MachineOperand &MO : MI->operands()) {
13781ad6265SDimitry Andric     MCOperand MCOp;
13881ad6265SDimitry Andric     if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP))
13981ad6265SDimitry Andric       OutMI.addOperand(MCOp);
14081ad6265SDimitry Andric   }
14181ad6265SDimitry Andric   return false;
14281ad6265SDimitry Andric }
143