forked from OSchip/llvm-project
[AIX][Power10] Restrict prefixed instructions from crossing the 64byte boundary
This patch adds the support to restrict prefixed instruction from crossing the 64 byte boundary: - Add the infrastructure to register a custom XCOFF streamer - Add a custom XCOFF streamer for PowerPC to allow us to intercept instructions as they are being emitted and align all 8 byte instructions to a 64 byte boundary if required by adding a 4 byte nop. Reviewed By: stefanp Differential Revision: https://reviews.llvm.org/D101107
This commit is contained in:
parent
21da04f701
commit
241c2da406
|
@ -183,6 +183,12 @@ public:
|
|||
std::unique_ptr<MCAsmBackend> &&TAB,
|
||||
std::unique_ptr<MCObjectWriter> &&OW,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
|
||||
using XCOFFStreamerCtorTy =
|
||||
MCStreamer *(*)(const Triple &T, MCContext &Ctx,
|
||||
std::unique_ptr<MCAsmBackend> &&TAB,
|
||||
std::unique_ptr<MCObjectWriter> &&OW,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
|
||||
|
||||
using NullTargetStreamerCtorTy = MCTargetStreamer *(*)(MCStreamer &S);
|
||||
using AsmTargetStreamerCtorTy = MCTargetStreamer *(*)(
|
||||
MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint,
|
||||
|
@ -270,6 +276,7 @@ private:
|
|||
MachOStreamerCtorTy MachOStreamerCtorFn = nullptr;
|
||||
ELFStreamerCtorTy ELFStreamerCtorFn = nullptr;
|
||||
WasmStreamerCtorTy WasmStreamerCtorFn = nullptr;
|
||||
XCOFFStreamerCtorTy XCOFFStreamerCtorFn = nullptr;
|
||||
|
||||
/// Construction function for this target's null TargetStreamer, if
|
||||
/// registered (default = nullptr).
|
||||
|
@ -513,6 +520,10 @@ public:
|
|||
case Triple::GOFF:
|
||||
report_fatal_error("GOFF MCObjectStreamer not implemented yet");
|
||||
case Triple::XCOFF:
|
||||
if (XCOFFStreamerCtorFn)
|
||||
S = XCOFFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW),
|
||||
std::move(Emitter), RelaxAll);
|
||||
else
|
||||
S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW),
|
||||
std::move(Emitter), RelaxAll);
|
||||
break;
|
||||
|
@ -868,6 +879,10 @@ struct TargetRegistry {
|
|||
T.WasmStreamerCtorFn = Fn;
|
||||
}
|
||||
|
||||
static void RegisterXCOFFStreamer(Target &T, Target::XCOFFStreamerCtorTy Fn) {
|
||||
T.XCOFFStreamerCtorFn = Fn;
|
||||
}
|
||||
|
||||
static void RegisterNullTargetStreamer(Target &T,
|
||||
Target::NullTargetStreamerCtorTy Fn) {
|
||||
T.NullTargetStreamerCtorFn = Fn;
|
||||
|
|
|
@ -9,6 +9,7 @@ add_llvm_component_library(LLVMPowerPCDesc
|
|||
PPCELFObjectWriter.cpp
|
||||
PPCXCOFFObjectWriter.cpp
|
||||
PPCELFStreamer.cpp
|
||||
PPCXCOFFStreamer.cpp
|
||||
|
||||
LINK_COMPONENTS
|
||||
MC
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "MCTargetDesc/PPCMCAsmInfo.h"
|
||||
#include "PPCELFStreamer.h"
|
||||
#include "PPCTargetStreamer.h"
|
||||
#include "PPCXCOFFStreamer.h"
|
||||
#include "TargetInfo/PowerPCTargetInfo.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
@ -112,15 +113,23 @@ static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI,
|
|||
return MAI;
|
||||
}
|
||||
|
||||
static MCStreamer *createPPCMCStreamer(const Triple &T, MCContext &Context,
|
||||
static MCStreamer *
|
||||
createPPCELFStreamer(const Triple &T, MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> &&MAB,
|
||||
std::unique_ptr<MCObjectWriter> &&OW,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter,
|
||||
bool RelaxAll) {
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) {
|
||||
return createPPCELFStreamer(Context, std::move(MAB), std::move(OW),
|
||||
std::move(Emitter));
|
||||
}
|
||||
|
||||
static MCStreamer *createPPCXCOFFStreamer(
|
||||
const Triple &T, MCContext &Context, std::unique_ptr<MCAsmBackend> &&MAB,
|
||||
std::unique_ptr<MCObjectWriter> &&OW,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) {
|
||||
return createPPCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
|
||||
std::move(Emitter));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class PPCTargetAsmStreamer : public PPCTargetStreamer {
|
||||
|
@ -377,7 +386,10 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
|
|||
TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend);
|
||||
|
||||
// Register the elf streamer.
|
||||
TargetRegistry::RegisterELFStreamer(*T, createPPCMCStreamer);
|
||||
TargetRegistry::RegisterELFStreamer(*T, createPPCELFStreamer);
|
||||
|
||||
// Register the XCOFF streamer.
|
||||
TargetRegistry::RegisterXCOFFStreamer(*T, createPPCXCOFFStreamer);
|
||||
|
||||
// Register the object target streamer.
|
||||
TargetRegistry::RegisterObjectTargetStreamer(*T,
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
//===-------- PPCXCOFFStreamer.cpp - XCOFF Object Output ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a custom MCXCOFFStreamer for PowerPC.
|
||||
//
|
||||
// The purpose of the custom XCOFF streamer is to allow us to intercept
|
||||
// instructions as they are being emitted and align all 8 byte instructions
|
||||
// to a 64 byte boundary if required (by adding a 4 byte nop). This is important
|
||||
// because 8 byte instructions are not allowed to cross 64 byte boundaries
|
||||
// and by aligning anything that is within 4 bytes of the boundary we can
|
||||
// guarantee that the 8 byte instructions do not cross that boundary.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PPCXCOFFStreamer.h"
|
||||
#include "PPCMCCodeEmitter.h"
|
||||
#include "llvm/BinaryFormat/XCOFF.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSectionXCOFF.h"
|
||||
#include "llvm/MC/MCSymbolXCOFF.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
PPCXCOFFStreamer::PPCXCOFFStreamer(MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> MAB,
|
||||
std::unique_ptr<MCObjectWriter> OW,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter)
|
||||
: MCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
|
||||
std::move(Emitter)) {}
|
||||
|
||||
void PPCXCOFFStreamer::emitPrefixedInstruction(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) {
|
||||
// Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
|
||||
// before the boundary and the remaining 4-bytes are after the boundary). In
|
||||
// order to achieve this, a nop is added prior to any such boundary-crossing
|
||||
// prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
|
||||
// bytes when trying to do that. If alignment requires adding more than 4
|
||||
// bytes then the instruction won't be aligned.
|
||||
emitCodeAlignment(64, 4);
|
||||
|
||||
// Emit the instruction.
|
||||
// Since the previous emit created a new fragment then adding this instruction
|
||||
// also forces the addition of a new fragment. Inst is now the first
|
||||
// instruction in that new fragment.
|
||||
MCXCOFFStreamer::emitInstruction(Inst, STI);
|
||||
}
|
||||
|
||||
void PPCXCOFFStreamer::emitInstruction(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) {
|
||||
PPCMCCodeEmitter *Emitter =
|
||||
static_cast<PPCMCCodeEmitter *>(getAssembler().getEmitterPtr());
|
||||
|
||||
// Special handling is only for prefixed instructions.
|
||||
if (!Emitter->isPrefixedInstruction(Inst)) {
|
||||
MCXCOFFStreamer::emitInstruction(Inst, STI);
|
||||
return;
|
||||
}
|
||||
emitPrefixedInstruction(Inst, STI);
|
||||
}
|
||||
|
||||
MCXCOFFStreamer *
|
||||
llvm::createPPCXCOFFStreamer(MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> MAB,
|
||||
std::unique_ptr<MCObjectWriter> OW,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter) {
|
||||
return new PPCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
|
||||
std::move(Emitter));
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//===- PPCXCOFFStreamer.h - XCOFF Object Output -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a custom MCXCOFFStreamer for PowerPC.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_PPC_MCXCOFFSTREAMER_PPCXCOFFSTREAMER_H
|
||||
#define LLVM_LIB_TARGET_PPC_MCXCOFFSTREAMER_PPCXCOFFSTREAMER_H
|
||||
|
||||
#include "llvm/MC/MCXCOFFStreamer.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class PPCXCOFFStreamer : public MCXCOFFStreamer {
|
||||
public:
|
||||
PPCXCOFFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
|
||||
std::unique_ptr<MCObjectWriter> OW,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter);
|
||||
|
||||
void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
|
||||
|
||||
private:
|
||||
void emitPrefixedInstruction(const MCInst &Inst, const MCSubtargetInfo &STI);
|
||||
};
|
||||
|
||||
MCXCOFFStreamer *createPPCXCOFFStreamer(MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> MAB,
|
||||
std::unique_ptr<MCObjectWriter> OW,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_PPC_MCXCOFFSTREAMER_PPCXCOFFSTREAMER_H
|
|
@ -0,0 +1,74 @@
|
|||
# RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff -x mir -verify-machineinstrs \
|
||||
# RUN: -xcoff-traceback-table=false -start-before=ppc-branch-select -filetype=obj -o %t.o < %s
|
||||
# RUN: llvm-objdump -D -r --mcpu=pwr10 %t.o | FileCheck --check-prefix=DIS %s
|
||||
|
||||
---
|
||||
name: aix-prefixed-instruction-boundary
|
||||
alignment: 16
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '$x3', virtual-reg: '' }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: $x3
|
||||
renamable $x3 = LI8 2
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
renamable $x3 = LI8 2
|
||||
|
||||
renamable $x3 = PADDI8 $x3, 13
|
||||
BLR8 implicit $lr8, implicit $rm, implicit killed $x3
|
||||
...
|
||||
|
||||
# DIS: Disassembly of section .text:
|
||||
# DIS: 00000000 <.text>:
|
||||
# DIS-NEXT: 0: 38 60 00 02 li 3, 2
|
||||
# DIS-NEXT: 4: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: c: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 14: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 1c: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 24: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 2c: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 34: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 3c: 60 00 00 00 nop
|
||||
# DIS-NEXT: 40: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 48: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 50: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 58: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 60: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 68: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 70: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 78: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 80: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 88: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 90: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: 98: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: a0: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: a8: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: b0: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: b8: 38 60 00 02 li 3, 2
|
||||
# DIS-NEXT: bc: 60 00 00 00 nop
|
||||
# DIS-NEXT: c0: 06 00 00 00 38 63 00 0d paddi 3, 3, 13, 0
|
||||
# DIS-NEXT: c8: 4e 80 00 20 blr
|
Loading…
Reference in New Issue