Skip to content

Commit

Permalink
[PPC] Fix layering issues between MCTargetDesc and CodeGen
Browse files Browse the repository at this point in the history
See issue llvm#64166 for more information about the layering issue.

The PPCMCTargetDesc library was including CodeGen headers such as
PPCInstrInfo.h and calling inline functions in them. This doesn't work
in the Bazel build, and is error-prone. If the inline function moves to
a cpp file, it will result in linker errors.

To address the issue, I moved several inline functions to
PPCMCTargetDesc.cpp, and declared them in the PPC namespace in
PPCMCTargetDesc.h, which seemed like the most straightforward fix.

Differential Revision: https://reviews.llvm.org/D156488
  • Loading branch information
rnk committed Aug 30, 2023
1 parent 1d1f230 commit cda23c0
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 267 deletions.
3 changes: 1 addition & 2 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
//
//===----------------------------------------------------------------------===//


#include "PPCELFStreamer.h"
#include "PPCFixupKinds.h"
#include "PPCInstrInfo.h"
#include "PPCMCCodeEmitter.h"
#include "PPCMCTargetDesc.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
Expand Down
8 changes: 3 additions & 5 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
#include "MCTargetDesc/PPCInstPrinter.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCPredicates.h"
#include "PPCInstrInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
Expand Down Expand Up @@ -646,8 +645,7 @@ void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
if (Op.isReg()) {
unsigned Reg = Op.getReg();
if (!ShowVSRNumsAsVR)
Reg = PPCInstrInfo::getRegNumForOperand(MII.get(MI->getOpcode()),
Reg, OpNo);
Reg = PPC::getRegNumForOperand(MII.get(MI->getOpcode()), Reg, OpNo);

const char *RegName;
RegName = getVerboseConditionRegName(Reg, MRI.getEncodingValue(Reg));
Expand All @@ -656,7 +654,7 @@ void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
if (showRegistersWithPercentPrefix(RegName))
O << "%";
if (!showRegistersWithPrefix())
RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
RegName = PPC::stripRegisterPrefix(RegName);

O << RegName;
return;
Expand Down
111 changes: 101 additions & 10 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@

#include "PPCMCCodeEmitter.h"
#include "MCTargetDesc/PPCFixupKinds.h"
#include "PPCInstrInfo.h"
#include "PPCMCTargetDesc.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down Expand Up @@ -47,16 +49,108 @@ getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
if (MO.isReg() || MO.isImm())
return getMachineOpValue(MI, MO, Fixups, STI);

const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo *>(&MCII);
unsigned Opcode = MI.getOpcode();
// Add a fixup for the branch target.
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
(InstrInfo->isNoTOCCallInstr(Opcode)
(isNoTOCCallInstr(MI)
? (MCFixupKind)PPC::fixup_ppc_br24_notoc
: (MCFixupKind)PPC::fixup_ppc_br24)));
return 0;
}

/// Check if Opcode corresponds to a call instruction that should be marked
/// with the NOTOC relocation.
bool PPCMCCodeEmitter::isNoTOCCallInstr(const MCInst &MI) const {
unsigned Opcode = MI.getOpcode();
if (!MCII.get(Opcode).isCall())
return false;

switch (Opcode) {
default:
#ifndef NDEBUG
llvm_unreachable("Unknown call opcode");
#endif
return false;
case PPC::BL8_NOTOC:
case PPC::BL8_NOTOC_TLS:
case PPC::BL8_NOTOC_RM:
return true;
#ifndef NDEBUG
case PPC::BL8:
case PPC::BL:
case PPC::BL8_TLS:
case PPC::BL_TLS:
case PPC::BLA8:
case PPC::BLA:
case PPC::BCCL:
case PPC::BCCLA:
case PPC::BCL:
case PPC::BCLn:
case PPC::BL8_NOP:
case PPC::BL_NOP:
case PPC::BL8_NOP_TLS:
case PPC::BLA8_NOP:
case PPC::BCTRL8:
case PPC::BCTRL:
case PPC::BCCCTRL8:
case PPC::BCCCTRL:
case PPC::BCCTRL8:
case PPC::BCCTRL:
case PPC::BCCTRL8n:
case PPC::BCCTRLn:
case PPC::BL8_RM:
case PPC::BLA8_RM:
case PPC::BL8_NOP_RM:
case PPC::BLA8_NOP_RM:
case PPC::BCTRL8_RM:
case PPC::BCTRL8_LDinto_toc:
case PPC::BCTRL8_LDinto_toc_RM:
case PPC::BL8_TLS_:
case PPC::TCRETURNdi8:
case PPC::TCRETURNai8:
case PPC::TCRETURNri8:
case PPC::TAILBCTR8:
case PPC::TAILB8:
case PPC::TAILBA8:
case PPC::BCLalways:
case PPC::BLRL:
case PPC::BCCLRL:
case PPC::BCLRL:
case PPC::BCLRLn:
case PPC::BDZL:
case PPC::BDNZL:
case PPC::BDZLA:
case PPC::BDNZLA:
case PPC::BDZLp:
case PPC::BDNZLp:
case PPC::BDZLAp:
case PPC::BDNZLAp:
case PPC::BDZLm:
case PPC::BDNZLm:
case PPC::BDZLAm:
case PPC::BDNZLAm:
case PPC::BDZLRL:
case PPC::BDNZLRL:
case PPC::BDZLRLp:
case PPC::BDNZLRLp:
case PPC::BDZLRLm:
case PPC::BDNZLRLm:
case PPC::BL_RM:
case PPC::BLA_RM:
case PPC::BL_NOP_RM:
case PPC::BCTRL_RM:
case PPC::TCRETURNdi:
case PPC::TCRETURNai:
case PPC::TCRETURNri:
case PPC::BCTRL_LWZinto_toc:
case PPC::BCTRL_LWZinto_toc_RM:
case PPC::TAILBCTR:
case PPC::TAILB:
case PPC::TAILBA:
return false;
#endif
}
}

unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
Expand Down Expand Up @@ -372,7 +466,7 @@ get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
}

// Get the index for this operand in this instruction. This is needed for
// computing the register number in PPCInstrInfo::getRegNumForOperand() for
// computing the register number in PPC::getRegNumForOperand() for
// any instructions that use a different numbering scheme for registers in
// different operands.
static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) {
Expand All @@ -397,8 +491,7 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
unsigned OpNo = getOpIdxForMO(MI, MO);
unsigned Reg =
PPCInstrInfo::getRegNumForOperand(MCII.get(MI.getOpcode()),
MO.getReg(), OpNo);
PPC::getRegNumForOperand(MCII.get(MI.getOpcode()), MO.getReg(), OpNo);
return CTX.getRegisterInfo()->getEncodingValue(Reg);
}

Expand Down Expand Up @@ -443,9 +536,7 @@ unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const {
}

bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const {
unsigned Opcode = MI.getOpcode();
const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo*>(&MCII);
return InstrInfo->isPrefixed(Opcode);
return MCII.get(MI.getOpcode()).TSFlags & PPCII::Prefixed;
}

#include "PPCGenMCCodeEmitter.inc"
4 changes: 4 additions & 0 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ class PPCMCCodeEmitter : public MCCodeEmitter {

// Is this instruction a prefixed instruction.
bool isPrefixedInstruction(const MCInst &MI) const;

/// Check if Opcode corresponds to a call instruction that should be marked
/// with the NOTOC relocation.
bool isNoTOCCallInstr(const MCInst &MI) const;
};

} // namespace llvm
Expand Down
84 changes: 84 additions & 0 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,90 @@ using namespace llvm;
#define GET_REGINFO_MC_DESC
#include "PPCGenRegisterInfo.inc"

/// stripRegisterPrefix - This method strips the character prefix from a
/// register name so that only the number is left. Used by for linux asm.
const char *PPC::stripRegisterPrefix(const char *RegName) {
switch (RegName[0]) {
case 'a':
if (RegName[1] == 'c' && RegName[2] == 'c')
return RegName + 3;
break;
case 'f':
if (RegName[1] == 'p')
return RegName + 2;
[[fallthrough]];
case 'r':
case 'v':
if (RegName[1] == 's') {
if (RegName[2] == 'p')
return RegName + 3;
return RegName + 2;
}
return RegName + 1;
case 'c':
if (RegName[1] == 'r')
return RegName + 2;
break;
case 'w':
// For wacc and wacc_hi
if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') {
if (RegName[4] == '_')
return RegName + 7;
else
return RegName + 4;
}
break;
case 'd':
// For dmr, dmrp, dmrrow, dmrrowp
if (RegName[1] == 'm' && RegName[2] == 'r') {
if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' &&
RegName[6] == 'p')
return RegName + 7;
else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w')
return RegName + 6;
else if (RegName[3] == 'p')
return RegName + 4;
else
return RegName + 3;
}
break;
}

return RegName;
}

/// getRegNumForOperand - some operands use different numbering schemes
/// for the same registers. For example, a VSX instruction may have any of
/// vs0-vs63 allocated whereas an Altivec instruction could only have
/// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual
/// register number needed for the opcode/operand number combination.
/// The operand number argument will be useful when we need to extend this
/// to instructions that use both Altivec and VSX numbering (for different
/// operands).
unsigned PPC::getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg,
unsigned OpNo) {
int16_t regClass = Desc.operands()[OpNo].RegClass;
switch (regClass) {
// We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31,
// VSX32-VSX63 during encoding/disassembling
case PPC::VSSRCRegClassID:
case PPC::VSFRCRegClassID:
if (PPC::isVFRegister(Reg))
return PPC::VSX32 + (Reg - PPC::VF0);
break;
// We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31,
// VSX32-VSX63 during encoding/disassembling
case PPC::VSRCRegClassID:
if (PPC::isVRRegister(Reg))
return PPC::VSX32 + (Reg - PPC::V0);
break;
// Other RegClass doesn't need mapping
default:
break;
}
return Reg;
}

PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}

// Pin the vtable to this file.
Expand Down
Loading

0 comments on commit cda23c0

Please sign in to comment.