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