Files
clang-p2996/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
Chen Zheng 4b932d84f4 [PowerPC] redesign the target flags (#69695)
12 bit is not enough for PPC's target specific flags. If 8 bit for the
bitmask flags, 4 bit for the direct mask, PPC can total have 16 direct
mask and 8 bitmask. Not enough for PPC, see this issue in
https://github.com/llvm/llvm-project/pull/66316

Redesign how PPC target set the target specific flags. With this patch,
all ppc target flags are direct flags. No bitmask flag in PPC anymore.

This patch aligns with some targets like X86 which also has many target
specific flags.

The patch also fixes a bug related to flag `MO_TLSGDM_FLAG` and `MO_LO`.
They are the same value and the test case changes in this PR shows the
bug.
2023-12-07 12:47:25 +08:00

220 lines
8.0 KiB
C++

//===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains code to lower PPC MachineInstrs to their corresponding
// MCInst records.
//
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/PPCMCExpr.h"
#include "PPC.h"
#include "PPCSubtarget.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;
static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO,
AsmPrinter &AP) {
if (MO.isGlobal()) {
// Get the symbol from the global, accounting for XCOFF-specific
// intricacies (see TargetLoweringObjectFileXCOFF::getTargetSymbol).
const GlobalValue *GV = MO.getGlobal();
return AP.getSymbol(GV);
}
assert(MO.isSymbol() && "Isn't a symbol reference");
SmallString<128> Name;
const DataLayout &DL = AP.getDataLayout();
Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL);
MCContext &Ctx = AP.OutContext;
MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
return Sym;
}
static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
AsmPrinter &Printer) {
MCContext &Ctx = Printer.OutContext;
MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
unsigned access = MO.getTargetFlags();
switch (access) {
case PPCII::MO_TPREL_LO:
RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO;
break;
case PPCII::MO_TPREL_HA:
RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA;
break;
case PPCII::MO_DTPREL_LO:
RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO;
break;
case PPCII::MO_TLSLD_LO:
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO;
break;
case PPCII::MO_TOC_LO:
RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
break;
case PPCII::MO_TLS:
RefKind = MCSymbolRefExpr::VK_PPC_TLS;
break;
case PPCII::MO_TLS_PCREL_FLAG:
RefKind = MCSymbolRefExpr::VK_PPC_TLS_PCREL;
break;
}
const TargetMachine &TM = Printer.TM;
if (MO.getTargetFlags() == PPCII::MO_PLT)
RefKind = MCSymbolRefExpr::VK_PLT;
else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PCREL;
else if (MO.getTargetFlags() == PPCII::MO_GOT_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL;
else if (MO.getTargetFlags() == PPCII::MO_TPREL_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_TPREL;
else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL;
else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL;
else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL;
else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG) {
assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");
TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());
// For the local-exec TLS model, we may generate the offset from the TLS
// base as an immediate operand (instead of using a TOC entry).
// Set the relocation type in case the result is used for purposes other
// than a TOC reference. In TOC reference cases, this result is discarded.
if (Model == TLSModel::LocalExec)
RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE;
}
const MachineInstr *MI = MO.getParent();
const MachineFunction *MF = MI->getMF();
const Module *M = MF->getFunction().getParent();
const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>());
unsigned MIOpcode = MI->getOpcode();
assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) &&
"BL8_NOTOC is only valid when using PC Relative Calls.");
if (Subtarget->isUsingPCRelativeCalls()) {
if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 ||
MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 ||
MIOpcode == PPC::BL8_NOTOC || MIOpcode == PPC::BL8_NOTOC_RM) {
RefKind = MCSymbolRefExpr::VK_PPC_NOTOC;
}
if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_PCREL_OPT;
}
const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx);
// If -msecure-plt -fPIC, add 32768 to symbol.
if (Subtarget->isSecurePlt() && TM.isPositionIndependent() &&
M->getPICLevel() == PICLevel::BigPIC &&
MO.getTargetFlags() == PPCII::MO_PLT)
Expr =
MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx);
if (!MO.isJTI() && MO.getOffset())
Expr = MCBinaryExpr::createAdd(Expr,
MCConstantExpr::create(MO.getOffset(), Ctx),
Ctx);
// Subtract off the PIC base if required.
if (MO.getTargetFlags() == PPCII::MO_PIC_FLAG ||
MO.getTargetFlags() == PPCII::MO_PIC_HA_FLAG ||
MO.getTargetFlags() == PPCII::MO_PIC_LO_FLAG) {
const MachineFunction *MF = MO.getParent()->getParent()->getParent();
const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx);
Expr = MCBinaryExpr::createSub(Expr, PB, Ctx);
}
// Add ha16() / lo16() markers if required.
switch (access) {
case PPCII::MO_LO:
case PPCII::MO_PIC_LO_FLAG:
Expr = PPCMCExpr::createLo(Expr, Ctx);
break;
case PPCII::MO_HA:
case PPCII::MO_PIC_HA_FLAG:
Expr = PPCMCExpr::createHa(Expr, Ctx);
break;
}
return MCOperand::createExpr(Expr);
}
void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP) {
OutMI.setOpcode(MI->getOpcode());
for (const MachineOperand &MO : MI->operands()) {
MCOperand MCOp;
if (LowerPPCMachineOperandToMCOperand(MO, MCOp, AP))
OutMI.addOperand(MCOp);
}
}
bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO,
MCOperand &OutMO, AsmPrinter &AP) {
switch (MO.getType()) {
default:
llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register:
assert(!MO.getSubReg() && "Subregs should be eliminated!");
assert(MO.getReg() > PPC::NoRegister &&
MO.getReg() < PPC::NUM_TARGET_REGS &&
"Invalid register for this target!");
// Ignore all implicit register operands.
if (MO.isImplicit())
return false;
OutMO = MCOperand::createReg(MO.getReg());
return true;
case MachineOperand::MO_Immediate:
OutMO = MCOperand::createImm(MO.getImm());
return true;
case MachineOperand::MO_MachineBasicBlock:
OutMO = MCOperand::createExpr(
MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext));
return true;
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol:
OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP);
return true;
case MachineOperand::MO_JumpTableIndex:
OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP);
return true;
case MachineOperand::MO_ConstantPoolIndex:
OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP);
return true;
case MachineOperand::MO_BlockAddress:
OutMO =
GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
return true;
case MachineOperand::MO_MCSymbol:
OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP);
return true;
case MachineOperand::MO_RegisterMask:
return false;
}
}