Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
213799 views
//===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains code to lower PPC MachineInstrs to their corresponding9// MCInst records.10//11//===----------------------------------------------------------------------===//1213#include "MCTargetDesc/PPCMCAsmInfo.h"14#include "PPC.h"15#include "PPCMachineFunctionInfo.h"16#include "PPCSubtarget.h"17#include "llvm/ADT/SmallString.h"18#include "llvm/ADT/Twine.h"19#include "llvm/CodeGen/AsmPrinter.h"20#include "llvm/CodeGen/MachineFunction.h"21#include "llvm/CodeGen/MachineModuleInfoImpls.h"22#include "llvm/CodeGen/TargetLowering.h"23#include "llvm/IR/DataLayout.h"24#include "llvm/IR/GlobalValue.h"25#include "llvm/IR/Mangler.h"26#include "llvm/IR/Module.h"27#include "llvm/MC/MCAsmInfo.h"28#include "llvm/MC/MCExpr.h"29#include "llvm/MC/MCInst.h"30#include "llvm/Target/TargetLoweringObjectFile.h"31using namespace llvm;3233static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO,34AsmPrinter &AP) {35if (MO.isGlobal()) {36// Get the symbol from the global, accounting for XCOFF-specific37// intricacies (see TargetLoweringObjectFileXCOFF::getTargetSymbol).38const GlobalValue *GV = MO.getGlobal();39return AP.getSymbol(GV);40}4142assert(MO.isSymbol() && "Isn't a symbol reference");4344SmallString<128> Name;45const DataLayout &DL = AP.getDataLayout();46Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL);4748MCContext &Ctx = AP.OutContext;49MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);50return Sym;51}5253static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,54AsmPrinter &Printer) {55MCContext &Ctx = Printer.OutContext;56PPCMCExpr::Specifier RefKind = PPC::S_None;5758unsigned access = MO.getTargetFlags();5960switch (access) {61case PPCII::MO_TPREL_LO:62RefKind = PPC::S_TPREL_LO;63break;64case PPCII::MO_TPREL_HA:65RefKind = PPC::S_TPREL_HA;66break;67case PPCII::MO_DTPREL_LO:68RefKind = PPC::S_DTPREL_LO;69break;70case PPCII::MO_TLSLD_LO:71RefKind = PPC::S_GOT_TLSLD_LO;72break;73case PPCII::MO_TOC_LO:74RefKind = PPC::S_TOC_LO;75break;76case PPCII::MO_TLS:77RefKind = PPC::S_TLS;78break;79case PPCII::MO_TLS_PCREL_FLAG:80RefKind = PPC::S_TLS_PCREL;81break;82}8384const TargetMachine &TM = Printer.TM;85const MachineInstr *MI = MO.getParent();86const MachineFunction *MF = MI->getMF();8788if (MO.getTargetFlags() == PPCII::MO_PLT)89RefKind = PPC::S_PLT;90else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG)91RefKind = PPC::S_PCREL;92else if (MO.getTargetFlags() == PPCII::MO_GOT_PCREL_FLAG)93RefKind = PPC::S_GOT_PCREL;94else if (MO.getTargetFlags() == PPCII::MO_TPREL_PCREL_FLAG)95RefKind = PPC::S_TPREL;96else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG)97RefKind = PPC::S_GOT_TLSGD_PCREL;98else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG)99RefKind = PPC::S_GOT_TLSLD_PCREL;100else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG)101RefKind = PPC::S_GOT_TPREL_PCREL;102else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG ||103MO.getTargetFlags() == PPCII::MO_TLSLD_FLAG) {104assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");105TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());106const PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();107// For the local-[exec|dynamic] TLS model, we may generate the offset from108// the TLS base as an immediate operand (instead of using a TOC entry). Set109// the relocation type in case the result is used for purposes other than a110// TOC reference. In TOC reference cases, this result is discarded.111if (Model == TLSModel::LocalExec)112RefKind = PPC::S_AIX_TLSLE;113else if (Model == TLSModel::LocalDynamic &&114FuncInfo->isAIXFuncUseTLSIEForLD())115// On AIX, TLS model opt may have turned local-dynamic accesses into116// initial-exec accesses.117RefKind = PPC::S_AIX_TLSIE;118else if (Model == TLSModel::LocalDynamic)119RefKind = PPC::S_AIX_TLSLD;120}121122const Module *M = MF->getFunction().getParent();123const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>());124125unsigned MIOpcode = MI->getOpcode();126assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) &&127"BL8_NOTOC is only valid when using PC Relative Calls.");128if (Subtarget->isUsingPCRelativeCalls()) {129if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 ||130MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 ||131MIOpcode == PPC::BL8_NOTOC || MIOpcode == PPC::BL8_NOTOC_RM) {132RefKind = PPC::S_NOTOC;133}134if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG)135RefKind = PPC::S_PCREL_OPT;136}137138const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx);139// If -msecure-plt -fPIC, add 32768 to symbol.140if (Subtarget->isSecurePlt() && TM.isPositionIndependent() &&141M->getPICLevel() == PICLevel::BigPIC &&142MO.getTargetFlags() == PPCII::MO_PLT)143Expr =144MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx);145146if (!MO.isJTI() && MO.getOffset())147Expr = MCBinaryExpr::createAdd(Expr,148MCConstantExpr::create(MO.getOffset(), Ctx),149Ctx);150151// Subtract off the PIC base if required.152if (MO.getTargetFlags() == PPCII::MO_PIC_FLAG ||153MO.getTargetFlags() == PPCII::MO_PIC_HA_FLAG ||154MO.getTargetFlags() == PPCII::MO_PIC_LO_FLAG) {155const MachineFunction *MF = MO.getParent()->getParent()->getParent();156157const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx);158Expr = MCBinaryExpr::createSub(Expr, PB, Ctx);159}160161// Add ha16() / lo16() markers if required.162switch (access) {163case PPCII::MO_LO:164case PPCII::MO_PIC_LO_FLAG:165Expr = MCSpecifierExpr::create(Expr, PPC::S_LO, Ctx);166break;167case PPCII::MO_HA:168case PPCII::MO_PIC_HA_FLAG:169Expr = MCSpecifierExpr::create(Expr, PPC::S_HA, Ctx);170break;171}172173return MCOperand::createExpr(Expr);174}175176void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,177AsmPrinter &AP) {178OutMI.setOpcode(MI->getOpcode());179180for (const MachineOperand &MO : MI->operands()) {181MCOperand MCOp;182if (LowerPPCMachineOperandToMCOperand(MO, MCOp, AP))183OutMI.addOperand(MCOp);184}185}186187bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO,188MCOperand &OutMO, AsmPrinter &AP) {189switch (MO.getType()) {190default:191llvm_unreachable("unknown operand type");192case MachineOperand::MO_Register:193assert(!MO.getSubReg() && "Subregs should be eliminated!");194assert(MO.getReg() > PPC::NoRegister &&195MO.getReg() < PPC::NUM_TARGET_REGS &&196"Invalid register for this target!");197// ISA instructions refer to the containing dmr reg.198if (PPC::isDMRROWpRegister(MO.getReg())) {199OutMO =200MCOperand::createReg(PPC::DMR0 + (MO.getReg() - PPC::DMRROWp0) / 4);201return true;202}203// Ignore all implicit register operands.204if (MO.isImplicit())205return false;206OutMO = MCOperand::createReg(MO.getReg());207return true;208case MachineOperand::MO_Immediate:209OutMO = MCOperand::createImm(MO.getImm());210return true;211case MachineOperand::MO_MachineBasicBlock:212OutMO = MCOperand::createExpr(213MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext));214return true;215case MachineOperand::MO_GlobalAddress:216case MachineOperand::MO_ExternalSymbol:217OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP);218return true;219case MachineOperand::MO_JumpTableIndex:220OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP);221return true;222case MachineOperand::MO_ConstantPoolIndex:223OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP);224return true;225case MachineOperand::MO_BlockAddress:226OutMO =227GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);228return true;229case MachineOperand::MO_MCSymbol:230OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP);231return true;232case MachineOperand::MO_RegisterMask:233return false;234}235}236237238