You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
@ -1,206 +0,0 @@
|
||||
//===-- AMDGPUAsmBackend.cpp - AMDGPU Assembler Backend -------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
/// \file
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/AMDGPUFixupKinds.h"
|
||||
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class AMDGPUAsmBackend : public MCAsmBackend {
|
||||
public:
|
||||
AMDGPUAsmBackend(const Target &T)
|
||||
: MCAsmBackend() {}
|
||||
|
||||
unsigned getNumFixupKinds() const override { return AMDGPU::NumTargetFixupKinds; };
|
||||
|
||||
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsResolved) const override;
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override {
|
||||
return false;
|
||||
}
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
|
||||
|
||||
unsigned getMinimumNopSize() const override;
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
|
||||
};
|
||||
|
||||
} //End anonymous namespace
|
||||
|
||||
static unsigned getFixupKindNumBytes(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
case AMDGPU::fixup_si_sopp_br:
|
||||
return 2;
|
||||
case FK_SecRel_1:
|
||||
case FK_Data_1:
|
||||
return 1;
|
||||
case FK_SecRel_2:
|
||||
case FK_Data_2:
|
||||
return 2;
|
||||
case FK_SecRel_4:
|
||||
case FK_Data_4:
|
||||
case FK_PCRel_4:
|
||||
return 4;
|
||||
case FK_SecRel_8:
|
||||
case FK_Data_8:
|
||||
return 8;
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
|
||||
MCContext *Ctx) {
|
||||
int64_t SignedValue = static_cast<int64_t>(Value);
|
||||
|
||||
switch (static_cast<unsigned>(Fixup.getKind())) {
|
||||
case AMDGPU::fixup_si_sopp_br: {
|
||||
int64_t BrImm = (SignedValue - 4) / 4;
|
||||
|
||||
if (Ctx && !isInt<16>(BrImm))
|
||||
Ctx->reportError(Fixup.getLoc(), "branch size exceeds simm16");
|
||||
|
||||
return BrImm;
|
||||
}
|
||||
case FK_Data_1:
|
||||
case FK_Data_2:
|
||||
case FK_Data_4:
|
||||
case FK_Data_8:
|
||||
case FK_PCRel_4:
|
||||
case FK_SecRel_4:
|
||||
return Value;
|
||||
default:
|
||||
llvm_unreachable("unhandled fixup kind");
|
||||
}
|
||||
}
|
||||
|
||||
void AMDGPUAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target,
|
||||
MutableArrayRef<char> Data, uint64_t Value,
|
||||
bool IsResolved) const {
|
||||
Value = adjustFixupValue(Fixup, Value, &Asm.getContext());
|
||||
if (!Value)
|
||||
return; // Doesn't change encoding.
|
||||
|
||||
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
|
||||
|
||||
// Shift the value into position.
|
||||
Value <<= Info.TargetOffset;
|
||||
|
||||
unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
|
||||
uint32_t Offset = Fixup.getOffset();
|
||||
assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
|
||||
|
||||
// For each byte of the fragment that the fixup touches, mask in the bits from
|
||||
// the fixup value.
|
||||
for (unsigned i = 0; i != NumBytes; ++i)
|
||||
Data[Offset + i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
|
||||
}
|
||||
|
||||
const MCFixupKindInfo &AMDGPUAsmBackend::getFixupKindInfo(
|
||||
MCFixupKind Kind) const {
|
||||
const static MCFixupKindInfo Infos[AMDGPU::NumTargetFixupKinds] = {
|
||||
// name offset bits flags
|
||||
{ "fixup_si_sopp_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
|
||||
return Infos[Kind - FirstTargetFixupKind];
|
||||
}
|
||||
|
||||
unsigned AMDGPUAsmBackend::getMinimumNopSize() const {
|
||||
return 4;
|
||||
}
|
||||
|
||||
bool AMDGPUAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
|
||||
// If the count is not 4-byte aligned, we must be writing data into the text
|
||||
// section (otherwise we have unaligned instructions, and thus have far
|
||||
// bigger problems), so just write zeros instead.
|
||||
OW->WriteZeros(Count % 4);
|
||||
|
||||
// We are properly aligned, so write NOPs as requested.
|
||||
Count /= 4;
|
||||
|
||||
// FIXME: R600 support.
|
||||
// s_nop 0
|
||||
const uint32_t Encoded_S_NOP_0 = 0xbf800000;
|
||||
|
||||
for (uint64_t I = 0; I != Count; ++I)
|
||||
OW->write32(Encoded_S_NOP_0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ELFAMDGPUAsmBackend class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend {
|
||||
bool Is64Bit;
|
||||
bool HasRelocationAddend;
|
||||
uint8_t OSABI = ELF::ELFOSABI_NONE;
|
||||
|
||||
public:
|
||||
ELFAMDGPUAsmBackend(const Target &T, const Triple &TT) :
|
||||
AMDGPUAsmBackend(T), Is64Bit(TT.getArch() == Triple::amdgcn),
|
||||
HasRelocationAddend(TT.getOS() == Triple::AMDHSA) {
|
||||
switch (TT.getOS()) {
|
||||
case Triple::AMDHSA:
|
||||
OSABI = ELF::ELFOSABI_AMDGPU_HSA;
|
||||
break;
|
||||
case Triple::AMDPAL:
|
||||
OSABI = ELF::ELFOSABI_AMDGPU_PAL;
|
||||
break;
|
||||
case Triple::Mesa3D:
|
||||
OSABI = ELF::ELFOSABI_AMDGPU_MESA3D;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createObjectWriter(raw_pwrite_stream &OS) const override {
|
||||
return createAMDGPUELFObjectWriter(Is64Bit, OSABI, HasRelocationAddend, OS);
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
MCAsmBackend *llvm::createAMDGPUAsmBackend(const Target &T,
|
||||
const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options) {
|
||||
// Use 64-bit ELF for amdgcn
|
||||
return new ELFAMDGPUAsmBackend(T, STI.getTargetTriple());
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
//===- AMDGPUELFObjectWriter.cpp - AMDGPU ELF Writer ----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUMCTargetDesc.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class AMDGPUELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
AMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI, bool HasRelocationAddend);
|
||||
|
||||
protected:
|
||||
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const override;
|
||||
};
|
||||
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
AMDGPUELFObjectWriter::AMDGPUELFObjectWriter(bool Is64Bit,
|
||||
uint8_t OSABI,
|
||||
bool HasRelocationAddend)
|
||||
: MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_AMDGPU,
|
||||
HasRelocationAddend) {}
|
||||
|
||||
unsigned AMDGPUELFObjectWriter::getRelocType(MCContext &Ctx,
|
||||
const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
if (const auto *SymA = Target.getSymA()) {
|
||||
// SCRATCH_RSRC_DWORD[01] is a special global variable that represents
|
||||
// the scratch buffer.
|
||||
if (SymA->getSymbol().getName() == "SCRATCH_RSRC_DWORD0")
|
||||
return ELF::R_AMDGPU_ABS32_LO;
|
||||
|
||||
if (SymA->getSymbol().getName() == "SCRATCH_RSRC_DWORD1")
|
||||
return ELF::R_AMDGPU_ABS32_HI;
|
||||
}
|
||||
|
||||
switch (Target.getAccessVariant()) {
|
||||
default:
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_GOTPCREL:
|
||||
return ELF::R_AMDGPU_GOTPCREL;
|
||||
case MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_LO:
|
||||
return ELF::R_AMDGPU_GOTPCREL32_LO;
|
||||
case MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_HI:
|
||||
return ELF::R_AMDGPU_GOTPCREL32_HI;
|
||||
case MCSymbolRefExpr::VK_AMDGPU_REL32_LO:
|
||||
return ELF::R_AMDGPU_REL32_LO;
|
||||
case MCSymbolRefExpr::VK_AMDGPU_REL32_HI:
|
||||
return ELF::R_AMDGPU_REL32_HI;
|
||||
}
|
||||
|
||||
switch (Fixup.getKind()) {
|
||||
default: break;
|
||||
case FK_PCRel_4:
|
||||
return ELF::R_AMDGPU_REL32;
|
||||
case FK_Data_4:
|
||||
case FK_SecRel_4:
|
||||
return ELF::R_AMDGPU_ABS32;
|
||||
case FK_Data_8:
|
||||
return ELF::R_AMDGPU_ABS64;
|
||||
}
|
||||
|
||||
llvm_unreachable("unhandled relocation type");
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
llvm::createAMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
|
||||
bool HasRelocationAddend,
|
||||
raw_pwrite_stream &OS) {
|
||||
auto MOTW = llvm::make_unique<AMDGPUELFObjectWriter>(Is64Bit, OSABI,
|
||||
HasRelocationAddend);
|
||||
return createELFObjectWriter(std::move(MOTW), OS, true);
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
//===-------- AMDGPUELFStreamer.cpp - ELF Object Output -------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUELFStreamer.h"
|
||||
#include "Utils/AMDGPUBaseInfo.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
AMDGPUELFStreamer::AMDGPUELFStreamer(const Triple &T, MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter)
|
||||
: MCELFStreamer(Context, std::move(MAB), OS, std::move(Emitter)) {
|
||||
unsigned Arch = ELF::EF_AMDGPU_ARCH_NONE;
|
||||
switch (T.getArch()) {
|
||||
case Triple::r600:
|
||||
Arch = ELF::EF_AMDGPU_ARCH_R600;
|
||||
break;
|
||||
case Triple::amdgcn:
|
||||
Arch = ELF::EF_AMDGPU_ARCH_GCN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
MCAssembler &MCA = getAssembler();
|
||||
unsigned EFlags = MCA.getELFHeaderEFlags();
|
||||
EFlags &= ~ELF::EF_AMDGPU_ARCH;
|
||||
EFlags |= Arch;
|
||||
MCA.setELFHeaderEFlags(EFlags);
|
||||
}
|
||||
|
||||
MCELFStreamer *llvm::createAMDGPUELFStreamer(
|
||||
const Triple &T, MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
|
||||
raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter,
|
||||
bool RelaxAll) {
|
||||
return new AMDGPUELFStreamer(T, Context, std::move(MAB), OS,
|
||||
std::move(Emitter));
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
//===-------- AMDGPUELFStreamer.h - ELF 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 MCELFStreamer which allows us to insert some hooks before
|
||||
// emitting data into an actual object file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUELFSTREAMER_H
|
||||
#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUELFSTREAMER_H
|
||||
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmBackend;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCSubtargetInfo;
|
||||
|
||||
class AMDGPUELFStreamer : public MCELFStreamer {
|
||||
public:
|
||||
AMDGPUELFStreamer(const Triple &T, MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> MAB, raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter);
|
||||
};
|
||||
|
||||
MCELFStreamer *createAMDGPUELFStreamer(const Triple &T, MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter,
|
||||
bool RelaxAll);
|
||||
} // namespace llvm.
|
||||
|
||||
#endif
|
@ -1,28 +0,0 @@
|
||||
//===-- AMDGPUFixupKinds.h - AMDGPU Specific Fixup Entries ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUFIXUPKINDS_H
|
||||
#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUFIXUPKINDS_H
|
||||
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace AMDGPU {
|
||||
enum Fixups {
|
||||
/// 16-bit PC relative fixup for SOPP branch instructions.
|
||||
fixup_si_sopp_br = FirstTargetFixupKind,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,407 +0,0 @@
|
||||
//===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// \brief AMDGPU HSA Metadata Streamer.
|
||||
///
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUHSAMetadataStreamer.h"
|
||||
#include "AMDGPU.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
static cl::opt<bool> DumpHSAMetadata(
|
||||
"amdgpu-dump-hsa-metadata",
|
||||
cl::desc("Dump AMDGPU HSA Metadata"));
|
||||
static cl::opt<bool> VerifyHSAMetadata(
|
||||
"amdgpu-verify-hsa-metadata",
|
||||
cl::desc("Verify AMDGPU HSA Metadata"));
|
||||
|
||||
namespace AMDGPU {
|
||||
namespace HSAMD {
|
||||
|
||||
void MetadataStreamer::dump(StringRef HSAMetadataString) const {
|
||||
errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
|
||||
}
|
||||
|
||||
void MetadataStreamer::verify(StringRef HSAMetadataString) const {
|
||||
errs() << "AMDGPU HSA Metadata Parser Test: ";
|
||||
|
||||
HSAMD::Metadata FromHSAMetadataString;
|
||||
if (fromString(HSAMetadataString, FromHSAMetadataString)) {
|
||||
errs() << "FAIL\n";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string ToHSAMetadataString;
|
||||
if (toString(FromHSAMetadataString, ToHSAMetadataString)) {
|
||||
errs() << "FAIL\n";
|
||||
return;
|
||||
}
|
||||
|
||||
errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL")
|
||||
<< '\n';
|
||||
if (HSAMetadataString != ToHSAMetadataString) {
|
||||
errs() << "Original input: " << HSAMetadataString << '\n'
|
||||
<< "Produced output: " << ToHSAMetadataString << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
AccessQualifier MetadataStreamer::getAccessQualifier(StringRef AccQual) const {
|
||||
if (AccQual.empty())
|
||||
return AccessQualifier::Unknown;
|
||||
|
||||
return StringSwitch<AccessQualifier>(AccQual)
|
||||
.Case("read_only", AccessQualifier::ReadOnly)
|
||||
.Case("write_only", AccessQualifier::WriteOnly)
|
||||
.Case("read_write", AccessQualifier::ReadWrite)
|
||||
.Default(AccessQualifier::Default);
|
||||
}
|
||||
|
||||
AddressSpaceQualifier MetadataStreamer::getAddressSpaceQualifer(
|
||||
unsigned AddressSpace) const {
|
||||
if (AddressSpace == AMDGPUASI.PRIVATE_ADDRESS)
|
||||
return AddressSpaceQualifier::Private;
|
||||
if (AddressSpace == AMDGPUASI.GLOBAL_ADDRESS)
|
||||
return AddressSpaceQualifier::Global;
|
||||
if (AddressSpace == AMDGPUASI.CONSTANT_ADDRESS)
|
||||
return AddressSpaceQualifier::Constant;
|
||||
if (AddressSpace == AMDGPUASI.LOCAL_ADDRESS)
|
||||
return AddressSpaceQualifier::Local;
|
||||
if (AddressSpace == AMDGPUASI.FLAT_ADDRESS)
|
||||
return AddressSpaceQualifier::Generic;
|
||||
if (AddressSpace == AMDGPUASI.REGION_ADDRESS)
|
||||
return AddressSpaceQualifier::Region;
|
||||
|
||||
llvm_unreachable("Unknown address space qualifier");
|
||||
}
|
||||
|
||||
ValueKind MetadataStreamer::getValueKind(Type *Ty, StringRef TypeQual,
|
||||
StringRef BaseTypeName) const {
|
||||
if (TypeQual.find("pipe") != StringRef::npos)
|
||||
return ValueKind::Pipe;
|
||||
|
||||
return StringSwitch<ValueKind>(BaseTypeName)
|
||||
.Case("image1d_t", ValueKind::Image)
|
||||
.Case("image1d_array_t", ValueKind::Image)
|
||||
.Case("image1d_buffer_t", ValueKind::Image)
|
||||
.Case("image2d_t", ValueKind::Image)
|
||||
.Case("image2d_array_t", ValueKind::Image)
|
||||
.Case("image2d_array_depth_t", ValueKind::Image)
|
||||
.Case("image2d_array_msaa_t", ValueKind::Image)
|
||||
.Case("image2d_array_msaa_depth_t", ValueKind::Image)
|
||||
.Case("image2d_depth_t", ValueKind::Image)
|
||||
.Case("image2d_msaa_t", ValueKind::Image)
|
||||
.Case("image2d_msaa_depth_t", ValueKind::Image)
|
||||
.Case("image3d_t", ValueKind::Image)
|
||||
.Case("sampler_t", ValueKind::Sampler)
|
||||
.Case("queue_t", ValueKind::Queue)
|
||||
.Default(isa<PointerType>(Ty) ?
|
||||
(Ty->getPointerAddressSpace() ==
|
||||
AMDGPUASI.LOCAL_ADDRESS ?
|
||||
ValueKind::DynamicSharedPointer :
|
||||
ValueKind::GlobalBuffer) :
|
||||
ValueKind::ByValue);
|
||||
}
|
||||
|
||||
ValueType MetadataStreamer::getValueType(Type *Ty, StringRef TypeName) const {
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::IntegerTyID: {
|
||||
auto Signed = !TypeName.startswith("u");
|
||||
switch (Ty->getIntegerBitWidth()) {
|
||||
case 8:
|
||||
return Signed ? ValueType::I8 : ValueType::U8;
|
||||
case 16:
|
||||
return Signed ? ValueType::I16 : ValueType::U16;
|
||||
case 32:
|
||||
return Signed ? ValueType::I32 : ValueType::U32;
|
||||
case 64:
|
||||
return Signed ? ValueType::I64 : ValueType::U64;
|
||||
default:
|
||||
return ValueType::Struct;
|
||||
}
|
||||
}
|
||||
case Type::HalfTyID:
|
||||
return ValueType::F16;
|
||||
case Type::FloatTyID:
|
||||
return ValueType::F32;
|
||||
case Type::DoubleTyID:
|
||||
return ValueType::F64;
|
||||
case Type::PointerTyID:
|
||||
return getValueType(Ty->getPointerElementType(), TypeName);
|
||||
case Type::VectorTyID:
|
||||
return getValueType(Ty->getVectorElementType(), TypeName);
|
||||
default:
|
||||
return ValueType::Struct;
|
||||
}
|
||||
}
|
||||
|
||||
std::string MetadataStreamer::getTypeName(Type *Ty, bool Signed) const {
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::IntegerTyID: {
|
||||
if (!Signed)
|
||||
return (Twine('u') + getTypeName(Ty, true)).str();
|
||||
|
||||
auto BitWidth = Ty->getIntegerBitWidth();
|
||||
switch (BitWidth) {
|
||||
case 8:
|
||||
return "char";
|
||||
case 16:
|
||||
return "short";
|
||||
case 32:
|
||||
return "int";
|
||||
case 64:
|
||||
return "long";
|
||||
default:
|
||||
return (Twine('i') + Twine(BitWidth)).str();
|
||||
}
|
||||
}
|
||||
case Type::HalfTyID:
|
||||
return "half";
|
||||
case Type::FloatTyID:
|
||||
return "float";
|
||||
case Type::DoubleTyID:
|
||||
return "double";
|
||||
case Type::VectorTyID: {
|
||||
auto VecTy = cast<VectorType>(Ty);
|
||||
auto ElTy = VecTy->getElementType();
|
||||
auto NumElements = VecTy->getVectorNumElements();
|
||||
return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
|
||||
}
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32_t> MetadataStreamer::getWorkGroupDimensions(
|
||||
MDNode *Node) const {
|
||||
std::vector<uint32_t> Dims;
|
||||
if (Node->getNumOperands() != 3)
|
||||
return Dims;
|
||||
|
||||
for (auto &Op : Node->operands())
|
||||
Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
|
||||
return Dims;
|
||||
}
|
||||
|
||||
void MetadataStreamer::emitVersion() {
|
||||
auto &Version = HSAMetadata.mVersion;
|
||||
|
||||
Version.push_back(VersionMajor);
|
||||
Version.push_back(VersionMinor);
|
||||
}
|
||||
|
||||
void MetadataStreamer::emitPrintf(const Module &Mod) {
|
||||
auto &Printf = HSAMetadata.mPrintf;
|
||||
|
||||
auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
|
||||
if (!Node)
|
||||
return;
|
||||
|
||||
for (auto Op : Node->operands())
|
||||
if (Op->getNumOperands())
|
||||
Printf.push_back(cast<MDString>(Op->getOperand(0))->getString());
|
||||
}
|
||||
|
||||
void MetadataStreamer::emitKernelLanguage(const Function &Func) {
|
||||
auto &Kernel = HSAMetadata.mKernels.back();
|
||||
|
||||
// TODO: What about other languages?
|
||||
auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
|
||||
if (!Node || !Node->getNumOperands())
|
||||
return;
|
||||
auto Op0 = Node->getOperand(0);
|
||||
if (Op0->getNumOperands() <= 1)
|
||||
return;
|
||||
|
||||
Kernel.mLanguage = "OpenCL C";
|
||||
Kernel.mLanguageVersion.push_back(
|
||||
mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
|
||||
Kernel.mLanguageVersion.push_back(
|
||||
mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
|
||||
}
|
||||
|
||||
void MetadataStreamer::emitKernelAttrs(const Function &Func) {
|
||||
auto &Attrs = HSAMetadata.mKernels.back().mAttrs;
|
||||
|
||||
if (auto Node = Func.getMetadata("reqd_work_group_size"))
|
||||
Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
|
||||
if (auto Node = Func.getMetadata("work_group_size_hint"))
|
||||
Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
|
||||
if (auto Node = Func.getMetadata("vec_type_hint")) {
|
||||
Attrs.mVecTypeHint = getTypeName(
|
||||
cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
|
||||
mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
|
||||
}
|
||||
if (Func.hasFnAttribute("runtime-handle")) {
|
||||
Attrs.mRuntimeHandle =
|
||||
Func.getFnAttribute("runtime-handle").getValueAsString().str();
|
||||
}
|
||||
}
|
||||
|
||||
void MetadataStreamer::emitKernelArgs(const Function &Func) {
|
||||
for (auto &Arg : Func.args())
|
||||
emitKernelArg(Arg);
|
||||
|
||||
// TODO: What about other languages?
|
||||
if (!Func.getParent()->getNamedMetadata("opencl.ocl.version"))
|
||||
return;
|
||||
|
||||
auto &DL = Func.getParent()->getDataLayout();
|
||||
auto Int64Ty = Type::getInt64Ty(Func.getContext());
|
||||
|
||||
emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetX);
|
||||
emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetY);
|
||||
emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetZ);
|
||||
|
||||
auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
|
||||
AMDGPUASI.GLOBAL_ADDRESS);
|
||||
auto CallsPrintf = Func.getParent()->getNamedMetadata("llvm.printf.fmts");
|
||||
if (CallsPrintf)
|
||||
emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenPrintfBuffer);
|
||||
if (Func.hasFnAttribute("calls-enqueue-kernel")) {
|
||||
if (!CallsPrintf) {
|
||||
// Emit a dummy argument so that the remaining hidden arguments
|
||||
// have a fixed position relative to the first hidden argument.
|
||||
// This is to facilitate library code to access hidden arguments.
|
||||
emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
|
||||
}
|
||||
emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenDefaultQueue);
|
||||
emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenCompletionAction);
|
||||
}
|
||||
}
|
||||
|
||||
void MetadataStreamer::emitKernelArg(const Argument &Arg) {
|
||||
auto Func = Arg.getParent();
|
||||
auto ArgNo = Arg.getArgNo();
|
||||
const MDNode *Node;
|
||||
|
||||
StringRef Name;
|
||||
Node = Func->getMetadata("kernel_arg_name");
|
||||
if (Node && ArgNo < Node->getNumOperands())
|
||||
Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
|
||||
else if (Arg.hasName())
|
||||
Name = Arg.getName();
|
||||
|
||||
StringRef TypeName;
|
||||
Node = Func->getMetadata("kernel_arg_type");
|
||||
if (Node && ArgNo < Node->getNumOperands())
|
||||
TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
|
||||
|
||||
StringRef BaseTypeName;
|
||||
Node = Func->getMetadata("kernel_arg_base_type");
|
||||
if (Node && ArgNo < Node->getNumOperands())
|
||||
BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
|
||||
|
||||
StringRef AccQual;
|
||||
if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
|
||||
Arg.hasNoAliasAttr()) {
|
||||
AccQual = "read_only";
|
||||
} else {
|
||||
Node = Func->getMetadata("kernel_arg_access_qual");
|
||||
if (Node && ArgNo < Node->getNumOperands())
|
||||
AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
|
||||
}
|
||||
|
||||
StringRef TypeQual;
|
||||
Node = Func->getMetadata("kernel_arg_type_qual");
|
||||
if (Node && ArgNo < Node->getNumOperands())
|
||||
TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
|
||||
|
||||
emitKernelArg(Func->getParent()->getDataLayout(), Arg.getType(),
|
||||
getValueKind(Arg.getType(), TypeQual, BaseTypeName), Name,
|
||||
TypeName, BaseTypeName, AccQual, TypeQual);
|
||||
}
|
||||
|
||||
void MetadataStreamer::emitKernelArg(const DataLayout &DL, Type *Ty,
|
||||
ValueKind ValueKind, StringRef Name,
|
||||
StringRef TypeName, StringRef BaseTypeName,
|
||||
StringRef AccQual, StringRef TypeQual) {
|
||||
HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
|
||||
auto &Arg = HSAMetadata.mKernels.back().mArgs.back();
|
||||
|
||||
Arg.mName = Name;
|
||||
Arg.mTypeName = TypeName;
|
||||
Arg.mSize = DL.getTypeAllocSize(Ty);
|
||||
Arg.mAlign = DL.getABITypeAlignment(Ty);
|
||||
Arg.mValueKind = ValueKind;
|
||||
Arg.mValueType = getValueType(Ty, BaseTypeName);
|
||||
|
||||
if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
|
||||
auto ElTy = PtrTy->getElementType();
|
||||
if (PtrTy->getAddressSpace() == AMDGPUASI.LOCAL_ADDRESS && ElTy->isSized())
|
||||
Arg.mPointeeAlign = DL.getABITypeAlignment(ElTy);
|
||||
}
|
||||
|
||||
if (auto PtrTy = dyn_cast<PointerType>(Ty))
|
||||
Arg.mAddrSpaceQual = getAddressSpaceQualifer(PtrTy->getAddressSpace());
|
||||
|
||||
Arg.mAccQual = getAccessQualifier(AccQual);
|
||||
|
||||
// TODO: Emit Arg.mActualAccQual.
|
||||
|
||||
SmallVector<StringRef, 1> SplitTypeQuals;
|
||||
TypeQual.split(SplitTypeQuals, " ", -1, false);
|
||||
for (StringRef Key : SplitTypeQuals) {
|
||||
auto P = StringSwitch<bool*>(Key)
|
||||
.Case("const", &Arg.mIsConst)
|
||||
.Case("restrict", &Arg.mIsRestrict)
|
||||
.Case("volatile", &Arg.mIsVolatile)
|
||||
.Case("pipe", &Arg.mIsPipe)
|
||||
.Default(nullptr);
|
||||
if (P)
|
||||
*P = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MetadataStreamer::begin(const Module &Mod) {
|
||||
AMDGPUASI = getAMDGPUAS(Mod);
|
||||
emitVersion();
|
||||
emitPrintf(Mod);
|
||||
}
|
||||
|
||||
void MetadataStreamer::end() {
|
||||
std::string HSAMetadataString;
|
||||
if (toString(HSAMetadata, HSAMetadataString))
|
||||
return;
|
||||
|
||||
if (DumpHSAMetadata)
|
||||
dump(HSAMetadataString);
|
||||
if (VerifyHSAMetadata)
|
||||
verify(HSAMetadataString);
|
||||
}
|
||||
|
||||
void MetadataStreamer::emitKernel(
|
||||
const Function &Func,
|
||||
const Kernel::CodeProps::Metadata &CodeProps,
|
||||
const Kernel::DebugProps::Metadata &DebugProps) {
|
||||
if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL)
|
||||
return;
|
||||
|
||||
HSAMetadata.mKernels.push_back(Kernel::Metadata());
|
||||
auto &Kernel = HSAMetadata.mKernels.back();
|
||||
|
||||
Kernel.mName = Func.getName();
|
||||
Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str();
|
||||
emitKernelLanguage(Func);
|
||||
emitKernelAttrs(Func);
|
||||
emitKernelArgs(Func);
|
||||
HSAMetadata.mKernels.back().mCodeProps = CodeProps;
|
||||
HSAMetadata.mKernels.back().mDebugProps = DebugProps;
|
||||
}
|
||||
|
||||
} // end namespace HSAMD
|
||||
} // end namespace AMDGPU
|
||||
} // end namespace llvm
|
@ -1,96 +0,0 @@
|
||||
//===--- AMDGPUHSAMetadataStreamer.h ----------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// \brief AMDGPU HSA Metadata Streamer.
|
||||
///
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUHSAMETADATASTREAMER_H
|
||||
#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUHSAMETADATASTREAMER_H
|
||||
|
||||
#include "AMDGPU.h"
|
||||
#include "AMDKernelCodeT.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/AMDGPUMetadata.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Argument;
|
||||
class DataLayout;
|
||||
class Function;
|
||||
class MDNode;
|
||||
class Module;
|
||||
class Type;
|
||||
|
||||
namespace AMDGPU {
|
||||
namespace HSAMD {
|
||||
|
||||
class MetadataStreamer final {
|
||||
private:
|
||||
Metadata HSAMetadata;
|
||||
AMDGPUAS AMDGPUASI;
|
||||
|
||||
void dump(StringRef HSAMetadataString) const;
|
||||
|
||||
void verify(StringRef HSAMetadataString) const;
|
||||
|
||||
AccessQualifier getAccessQualifier(StringRef AccQual) const;
|
||||
|
||||
AddressSpaceQualifier getAddressSpaceQualifer(unsigned AddressSpace) const;
|
||||
|
||||
ValueKind getValueKind(Type *Ty, StringRef TypeQual,
|
||||
StringRef BaseTypeName) const;
|
||||
|
||||
ValueType getValueType(Type *Ty, StringRef TypeName) const;
|
||||
|
||||
std::string getTypeName(Type *Ty, bool Signed) const;
|
||||
|
||||
std::vector<uint32_t> getWorkGroupDimensions(MDNode *Node) const;
|
||||
|
||||
void emitVersion();
|
||||
|
||||
void emitPrintf(const Module &Mod);
|
||||
|
||||
void emitKernelLanguage(const Function &Func);
|
||||
|
||||
void emitKernelAttrs(const Function &Func);
|
||||
|
||||
void emitKernelArgs(const Function &Func);
|
||||
|
||||
void emitKernelArg(const Argument &Arg);
|
||||
|
||||
void emitKernelArg(const DataLayout &DL, Type *Ty, ValueKind ValueKind,
|
||||
StringRef Name = "", StringRef TypeName = "",
|
||||
StringRef BaseTypeName = "", StringRef AccQual = "",
|
||||
StringRef TypeQual = "");
|
||||
|
||||
public:
|
||||
MetadataStreamer() = default;
|
||||
~MetadataStreamer() = default;
|
||||
|
||||
const Metadata &getHSAMetadata() const {
|
||||
return HSAMetadata;
|
||||
}
|
||||
|
||||
void begin(const Module &Mod);
|
||||
|
||||
void end();
|
||||
|
||||
void emitKernel(const Function &Func,
|
||||
const Kernel::CodeProps::Metadata &CodeProps,
|
||||
const Kernel::DebugProps::Metadata &DebugProps);
|
||||
};
|
||||
|
||||
} // end namespace HSAMD
|
||||
} // end namespace AMDGPU
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUHSAMETADATASTREAMER_H
|
@ -1,47 +0,0 @@
|
||||
//===-- MCTargetDesc/AMDGPUMCAsmInfo.cpp - Assembly Info ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
/// \file
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUMCAsmInfo.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
AMDGPUMCAsmInfo::AMDGPUMCAsmInfo(const Triple &TT) : MCAsmInfoELF() {
|
||||
CodePointerSize = (TT.getArch() == Triple::amdgcn) ? 8 : 4;
|
||||
StackGrowsUp = true;
|
||||
HasSingleParameterDotFile = false;
|
||||
//===------------------------------------------------------------------===//
|
||||
MinInstAlignment = 4;
|
||||
MaxInstLength = (TT.getArch() == Triple::amdgcn) ? 8 : 16;
|
||||
SeparatorString = "\n";
|
||||
CommentString = ";";
|
||||
PrivateLabelPrefix = "";
|
||||
InlineAsmStart = ";#ASMSTART";
|
||||
InlineAsmEnd = ";#ASMEND";
|
||||
|
||||
//===--- Data Emission Directives -------------------------------------===//
|
||||
SunStyleELFSectionSwitchSyntax = true;
|
||||
UsesELFSectionDirectiveForBSS = true;
|
||||
|
||||
//===--- Global Variable Emission Directives --------------------------===//
|
||||
HasAggressiveSymbolFolding = true;
|
||||
COMMDirectiveAlignmentIsInBytes = false;
|
||||
HasNoDeadStrip = true;
|
||||
WeakRefDirective = ".weakref\t";
|
||||
//===--- Dwarf Emission Directives -----------------------------------===//
|
||||
SupportsDebugInformation = true;
|
||||
}
|
||||
|
||||
bool AMDGPUMCAsmInfo::shouldOmitSectionDirective(StringRef SectionName) const {
|
||||
return SectionName == ".hsatext" || SectionName == ".hsadata_global_agent" ||
|
||||
SectionName == ".hsadata_global_program" ||
|
||||
SectionName == ".hsarodata_readonly_agent" ||
|
||||
MCAsmInfo::shouldOmitSectionDirective(SectionName);
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
//===-- MCTargetDesc/AMDGPUMCAsmInfo.h - AMDGPU MCAsm Interface -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCASMINFO_H
|
||||
#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCASMINFO_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfoELF.h"
|
||||
namespace llvm {
|
||||
|
||||
class Triple;
|
||||
|
||||
// If you need to create another MCAsmInfo class, which inherits from MCAsmInfo,
|
||||
// you will need to make sure your new class sets PrivateGlobalPrefix to
|
||||
// a prefix that won't appear in a function name. The default value
|
||||
// for PrivateGlobalPrefix is 'L', so it will consider any function starting
|
||||
// with 'L' as a local symbol.
|
||||
class AMDGPUMCAsmInfo : public MCAsmInfoELF {
|
||||
public:
|
||||
explicit AMDGPUMCAsmInfo(const Triple &TT);
|
||||
bool shouldOmitSectionDirective(StringRef SectionName) const override;
|
||||
};
|
||||
} // namespace llvm
|
||||
#endif
|
@ -1,21 +0,0 @@
|
||||
//===-- AMDGPUCodeEmitter.cpp - AMDGPU Code Emitter interface -------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// \brief CodeEmitter interface for R600 and SI codegen.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUMCCodeEmitter.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// pin vtable to this file
|
||||
void AMDGPUMCCodeEmitter::anchor() {}
|
||||
|
@ -1,75 +0,0 @@
|
||||
//===-- AMDGPUCodeEmitter.h - AMDGPU Code Emitter interface -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// \brief CodeEmitter interface for R600 and SI codegen.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCCODEEMITTER_H
|
||||
#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCCODEEMITTER_H
|
||||
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCInst;
|
||||
class MCInstrInfo;
|
||||
class MCOperand;
|
||||
class MCSubtargetInfo;
|
||||
class FeatureBitset;
|
||||
|
||||
class AMDGPUMCCodeEmitter : public MCCodeEmitter {
|
||||
virtual void anchor();
|
||||
|
||||
protected:
|
||||
const MCInstrInfo &MCII;
|
||||
|
||||
AMDGPUMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {}
|
||||
|
||||
public:
|
||||
|
||||
uint64_t getBinaryCodeForInstr(const MCInst &MI,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
|
||||
void verifyInstructionPredicates(const MCInst &MI,
|
||||
uint64_t AvailableFeatures) const;
|
||||
};
|
||||
|
||||
} // End namespace llvm
|
||||
|
||||
#endif
|
@ -1,115 +0,0 @@
|
||||
//===-- AMDGPUMCTargetDesc.cpp - AMDGPU Target Descriptions ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// \brief This file provides AMDGPU specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUMCTargetDesc.h"
|
||||
#include "AMDGPUELFStreamer.h"
|
||||
#include "AMDGPUMCAsmInfo.h"
|
||||
#include "AMDGPUTargetStreamer.h"
|
||||
#include "InstPrinter/AMDGPUInstPrinter.h"
|
||||
#include "SIDefines.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MachineLocation.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define GET_INSTRINFO_MC_DESC
|
||||
#include "AMDGPUGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_MC_DESC
|
||||
#include "AMDGPUGenSubtargetInfo.inc"
|
||||
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#include "AMDGPUGenRegisterInfo.inc"
|
||||
|
||||
static MCInstrInfo *createAMDGPUMCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitAMDGPUMCInstrInfo(X);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createAMDGPUMCRegisterInfo(const Triple &TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitAMDGPUMCRegisterInfo(X, 0);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCSubtargetInfo *
|
||||
createAMDGPUMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
|
||||
return createAMDGPUMCSubtargetInfoImpl(TT, CPU, FS);
|
||||
}
|
||||
|
||||
static MCInstPrinter *createAMDGPUMCInstPrinter(const Triple &T,
|
||||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI) {
|
||||
return T.getArch() == Triple::r600 ? new R600InstPrinter(MAI, MII, MRI) :
|
||||
new AMDGPUInstPrinter(MAI, MII, MRI);
|
||||
}
|
||||
|
||||
static MCTargetStreamer *createAMDGPUAsmTargetStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS,
|
||||
MCInstPrinter *InstPrint,
|
||||
bool isVerboseAsm) {
|
||||
return new AMDGPUTargetAsmStreamer(S, OS);
|
||||
}
|
||||
|
||||
static MCTargetStreamer * createAMDGPUObjectTargetStreamer(
|
||||
MCStreamer &S,
|
||||
const MCSubtargetInfo &STI) {
|
||||
return new AMDGPUTargetELFStreamer(S);
|
||||
}
|
||||
|
||||
static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> &&MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter,
|
||||
bool RelaxAll) {
|
||||
return createAMDGPUELFStreamer(T, Context, std::move(MAB), OS,
|
||||
std::move(Emitter), RelaxAll);
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeAMDGPUTargetMC() {
|
||||
for (Target *T : {&getTheAMDGPUTarget(), &getTheGCNTarget()}) {
|
||||
RegisterMCAsmInfo<AMDGPUMCAsmInfo> X(*T);
|
||||
|
||||
TargetRegistry::RegisterMCInstrInfo(*T, createAMDGPUMCInstrInfo);
|
||||
TargetRegistry::RegisterMCRegInfo(*T, createAMDGPUMCRegisterInfo);
|
||||
TargetRegistry::RegisterMCSubtargetInfo(*T, createAMDGPUMCSubtargetInfo);
|
||||
TargetRegistry::RegisterMCInstPrinter(*T, createAMDGPUMCInstPrinter);
|
||||
TargetRegistry::RegisterMCAsmBackend(*T, createAMDGPUAsmBackend);
|
||||
TargetRegistry::RegisterELFStreamer(*T, createMCStreamer);
|
||||
}
|
||||
|
||||
// R600 specific registration
|
||||
TargetRegistry::RegisterMCCodeEmitter(getTheAMDGPUTarget(),
|
||||
createR600MCCodeEmitter);
|
||||
|
||||
// GCN specific registration
|
||||
TargetRegistry::RegisterMCCodeEmitter(getTheGCNTarget(),
|
||||
createSIMCCodeEmitter);
|
||||
|
||||
TargetRegistry::RegisterAsmTargetStreamer(getTheGCNTarget(),
|
||||
createAMDGPUAsmTargetStreamer);
|
||||
TargetRegistry::RegisterObjectTargetStreamer(
|
||||
getTheGCNTarget(), createAMDGPUObjectTargetStreamer);
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
//===-- AMDGPUMCTargetDesc.h - AMDGPU Target Descriptions -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// \brief Provides AMDGPU specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCTARGETDESC_H
|
||||
#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCTARGETDESC_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmBackend;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCObjectWriter;
|
||||
class MCRegisterInfo;
|
||||
class MCSubtargetInfo;
|
||||
class MCTargetOptions;
|
||||
class StringRef;
|
||||
class Target;
|
||||
class Triple;
|
||||
class raw_pwrite_stream;
|
||||
|
||||
Target &getTheAMDGPUTarget();
|
||||
Target &getTheGCNTarget();
|
||||
|
||||
MCCodeEmitter *createR600MCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx);
|
||||
|
||||
MCCodeEmitter *createSIMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx);
|
||||
|
||||
MCAsmBackend *createAMDGPUAsmBackend(const Target &T,
|
||||
const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options);
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createAMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
|
||||
bool HasRelocationAddend, raw_pwrite_stream &OS);
|
||||
} // End llvm namespace
|
||||
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "AMDGPUGenRegisterInfo.inc"
|
||||
#undef GET_REGINFO_ENUM
|
||||
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#define GET_INSTRINFO_OPERAND_ENUM
|
||||
#define GET_INSTRINFO_SCHED_ENUM
|
||||
#include "AMDGPUGenInstrInfo.inc"
|
||||
#undef GET_INSTRINFO_SCHED_ENUM
|
||||
#undef GET_INSTRINFO_OPERAND_ENUM
|
||||
#undef GET_INSTRINFO_ENUM
|
||||
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "AMDGPUGenSubtargetInfo.inc"
|
||||
#undef GET_SUBTARGETINFO_ENUM
|
||||
|
||||
#endif
|
@ -1,273 +0,0 @@
|
||||
//===-- AMDGPUTargetStreamer.cpp - Mips Target Streamer Methods -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides AMDGPU specific target streamer methods.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUTargetStreamer.h"
|
||||
#include "AMDGPU.h"
|
||||
#include "SIDefines.h"
|
||||
#include "Utils/AMDGPUBaseInfo.h"
|
||||
#include "Utils/AMDKernelCodeTUtils.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/MC/MCObjectFileInfo.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
|
||||
namespace llvm {
|
||||
#include "AMDGPUPTNote.h"
|
||||
}
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::AMDGPU;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AMDGPUTargetStreamer
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool AMDGPUTargetStreamer::EmitHSAMetadata(StringRef HSAMetadataString) {
|
||||
HSAMD::Metadata HSAMetadata;
|
||||
if (HSAMD::fromString(HSAMetadataString, HSAMetadata))
|
||||
return false;
|
||||
|
||||
return EmitHSAMetadata(HSAMetadata);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AMDGPUTargetAsmStreamer
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
AMDGPUTargetAsmStreamer::AMDGPUTargetAsmStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS)
|
||||
: AMDGPUTargetStreamer(S), OS(OS) { }
|
||||
|
||||
void
|
||||
AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
|
||||
uint32_t Minor) {
|
||||
OS << "\t.hsa_code_object_version " <<
|
||||
Twine(Major) << "," << Twine(Minor) << '\n';
|
||||
}
|
||||
|
||||
void
|
||||
AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
|
||||
uint32_t Minor,
|
||||
uint32_t Stepping,
|
||||
StringRef VendorName,
|
||||
StringRef ArchName) {
|
||||
OS << "\t.hsa_code_object_isa " <<
|
||||
Twine(Major) << "," << Twine(Minor) << "," << Twine(Stepping) <<
|
||||
",\"" << VendorName << "\",\"" << ArchName << "\"\n";
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
AMDGPUTargetAsmStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
|
||||
OS << "\t.amd_kernel_code_t\n";
|
||||
dumpAmdKernelCode(&Header, OS, "\t\t");
|
||||
OS << "\t.end_amd_kernel_code_t\n";
|
||||
}
|
||||
|
||||
void AMDGPUTargetAsmStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
|
||||
unsigned Type) {
|
||||
switch (Type) {
|
||||
default: llvm_unreachable("Invalid AMDGPU symbol type");
|
||||
case ELF::STT_AMDGPU_HSA_KERNEL:
|
||||
OS << "\t.amdgpu_hsa_kernel " << SymbolName << '\n' ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool AMDGPUTargetAsmStreamer::EmitISAVersion(StringRef IsaVersionString) {
|
||||
OS << "\t.amd_amdgpu_isa \"" << IsaVersionString << "\"\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AMDGPUTargetAsmStreamer::EmitHSAMetadata(
|
||||
const AMDGPU::HSAMD::Metadata &HSAMetadata) {
|
||||
std::string HSAMetadataString;
|
||||
if (HSAMD::toString(HSAMetadata, HSAMetadataString))
|
||||
return false;
|
||||
|
||||
OS << '\t' << HSAMD::AssemblerDirectiveBegin << '\n';
|
||||
OS << HSAMetadataString << '\n';
|
||||
OS << '\t' << HSAMD::AssemblerDirectiveEnd << '\n';
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AMDGPUTargetAsmStreamer::EmitPALMetadata(
|
||||
const PALMD::Metadata &PALMetadata) {
|
||||
std::string PALMetadataString;
|
||||
if (PALMD::toString(PALMetadata, PALMetadataString))
|
||||
return false;
|
||||
|
||||
OS << '\t' << PALMD::AssemblerDirective << PALMetadataString << '\n';
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AMDGPUTargetELFStreamer
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(MCStreamer &S)
|
||||
: AMDGPUTargetStreamer(S), Streamer(S) {}
|
||||
|
||||
MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() {
|
||||
return static_cast<MCELFStreamer &>(Streamer);
|
||||
}
|
||||
|
||||
void AMDGPUTargetELFStreamer::EmitAMDGPUNote(
|
||||
const MCExpr *DescSZ, unsigned NoteType,
|
||||
function_ref<void(MCELFStreamer &)> EmitDesc) {
|
||||
auto &S = getStreamer();
|
||||
auto &Context = S.getContext();
|
||||
|
||||
auto NameSZ = sizeof(ElfNote::NoteName);
|
||||
|
||||
S.PushSection();
|
||||
S.SwitchSection(Context.getELFSection(
|
||||
ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC));
|
||||
S.EmitIntValue(NameSZ, 4); // namesz
|
||||
S.EmitValue(DescSZ, 4); // descz
|
||||
S.EmitIntValue(NoteType, 4); // type
|
||||
S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ)); // name
|
||||
S.EmitValueToAlignment(4, 0, 1, 0); // padding 0
|
||||
EmitDesc(S); // desc
|
||||
S.EmitValueToAlignment(4, 0, 1, 0); // padding 0
|
||||
S.PopSection();
|
||||
}
|
||||
|
||||
void
|
||||
AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
|
||||
uint32_t Minor) {
|
||||
|
||||
EmitAMDGPUNote(
|
||||
MCConstantExpr::create(8, getContext()),
|
||||
ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION,
|
||||
[&](MCELFStreamer &OS){
|
||||
OS.EmitIntValue(Major, 4);
|
||||
OS.EmitIntValue(Minor, 4);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
|
||||
uint32_t Minor,
|
||||
uint32_t Stepping,
|
||||
StringRef VendorName,
|
||||
StringRef ArchName) {
|
||||
uint16_t VendorNameSize = VendorName.size() + 1;
|
||||
uint16_t ArchNameSize = ArchName.size() + 1;
|
||||
|
||||
unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) +
|
||||
sizeof(Major) + sizeof(Minor) + sizeof(Stepping) +
|
||||
VendorNameSize + ArchNameSize;
|
||||
|
||||
EmitAMDGPUNote(
|
||||
MCConstantExpr::create(DescSZ, getContext()),
|
||||
ElfNote::NT_AMDGPU_HSA_ISA,
|
||||
[&](MCELFStreamer &OS) {
|
||||
OS.EmitIntValue(VendorNameSize, 2);
|
||||
OS.EmitIntValue(ArchNameSize, 2);
|
||||
OS.EmitIntValue(Major, 4);
|
||||
OS.EmitIntValue(Minor, 4);
|
||||
OS.EmitIntValue(Stepping, 4);
|
||||
OS.EmitBytes(VendorName);
|
||||
OS.EmitIntValue(0, 1); // NULL terminate VendorName
|
||||
OS.EmitBytes(ArchName);
|
||||
OS.EmitIntValue(0, 1); // NULL terminte ArchName
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
|
||||
|
||||
MCStreamer &OS = getStreamer();
|
||||
OS.PushSection();
|
||||
OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header)));
|
||||
OS.PopSection();
|
||||
}
|
||||
|
||||
void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
|
||||
unsigned Type) {
|
||||
MCSymbolELF *Symbol = cast<MCSymbolELF>(
|
||||
getStreamer().getContext().getOrCreateSymbol(SymbolName));
|
||||
Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL);
|
||||
}
|
||||
|
||||
bool AMDGPUTargetELFStreamer::EmitISAVersion(StringRef IsaVersionString) {
|
||||
// Create two labels to mark the beginning and end of the desc field
|
||||
// and a MCExpr to calculate the size of the desc field.
|
||||
auto &Context = getContext();
|
||||
auto *DescBegin = Context.createTempSymbol();
|
||||
auto *DescEnd = Context.createTempSymbol();
|
||||
auto *DescSZ = MCBinaryExpr::createSub(
|
||||
MCSymbolRefExpr::create(DescEnd, Context),
|
||||
MCSymbolRefExpr::create(DescBegin, Context), Context);
|
||||
|
||||
EmitAMDGPUNote(
|
||||
DescSZ,
|
||||
ELF::NT_AMD_AMDGPU_ISA,
|
||||
[&](MCELFStreamer &OS) {
|
||||
OS.EmitLabel(DescBegin);
|
||||
OS.EmitBytes(IsaVersionString);
|
||||
OS.EmitLabel(DescEnd);
|
||||
}
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AMDGPUTargetELFStreamer::EmitHSAMetadata(
|
||||
const AMDGPU::HSAMD::Metadata &HSAMetadata) {
|
||||
std::string HSAMetadataString;
|
||||
if (HSAMD::toString(HSAMetadata, HSAMetadataString))
|
||||
return false;
|
||||
|
||||
// Create two labels to mark the beginning and end of the desc field
|
||||
// and a MCExpr to calculate the size of the desc field.
|
||||
auto &Context = getContext();
|
||||
auto *DescBegin = Context.createTempSymbol();
|
||||
auto *DescEnd = Context.createTempSymbol();
|
||||
auto *DescSZ = MCBinaryExpr::createSub(
|
||||
MCSymbolRefExpr::create(DescEnd, Context),
|
||||
MCSymbolRefExpr::create(DescBegin, Context), Context);
|
||||
|
||||
EmitAMDGPUNote(
|
||||
DescSZ,
|
||||
ELF::NT_AMD_AMDGPU_HSA_METADATA,
|
||||
[&](MCELFStreamer &OS) {
|
||||
OS.EmitLabel(DescBegin);
|
||||
OS.EmitBytes(HSAMetadataString);
|
||||
OS.EmitLabel(DescEnd);
|
||||
}
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AMDGPUTargetELFStreamer::EmitPALMetadata(
|
||||
const PALMD::Metadata &PALMetadata) {
|
||||
EmitAMDGPUNote(
|
||||
MCConstantExpr::create(PALMetadata.size() * sizeof(uint32_t), getContext()),
|
||||
ELF::NT_AMD_AMDGPU_PAL_METADATA,
|
||||
[&](MCELFStreamer &OS){
|
||||
for (auto I : PALMetadata)
|
||||
OS.EmitIntValue(I, sizeof(uint32_t));
|
||||
}
|
||||
);
|
||||
return true;
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
//===-- AMDGPUTargetStreamer.h - AMDGPU Target Streamer --------*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUTARGETSTREAMER_H
|
||||
#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUTARGETSTREAMER_H
|
||||
|
||||
#include "AMDKernelCodeT.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/AMDGPUMetadata.h"
|
||||
|
||||
namespace llvm {
|
||||
#include "AMDGPUPTNote.h"
|
||||
|
||||
class DataLayout;
|
||||
class Function;
|
||||
class MCELFStreamer;
|
||||
class MCSymbol;
|
||||
class MDNode;
|
||||
class Module;
|
||||
class Type;
|
||||
|
||||
class AMDGPUTargetStreamer : public MCTargetStreamer {
|
||||
protected:
|
||||
MCContext &getContext() const { return Streamer.getContext(); }
|
||||
|
||||
public:
|
||||
AMDGPUTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
|
||||
|
||||
virtual void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
|
||||
uint32_t Minor) = 0;
|
||||
|
||||
virtual void EmitDirectiveHSACodeObjectISA(uint32_t Major, uint32_t Minor,
|
||||
uint32_t Stepping,
|
||||
StringRef VendorName,
|
||||
StringRef ArchName) = 0;
|
||||
|
||||
virtual void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) = 0;
|
||||
|
||||
virtual void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) = 0;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
virtual bool EmitISAVersion(StringRef IsaVersionString) = 0;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
virtual bool EmitHSAMetadata(StringRef HSAMetadataString);
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
virtual bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) = 0;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
virtual bool EmitPALMetadata(const AMDGPU::PALMD::Metadata &PALMetadata) = 0;
|
||||
};
|
||||
|
||||
class AMDGPUTargetAsmStreamer final : public AMDGPUTargetStreamer {
|
||||
formatted_raw_ostream &OS;
|
||||
public:
|
||||
AMDGPUTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
|
||||
void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
|
||||
uint32_t Minor) override;
|
||||
|
||||
void EmitDirectiveHSACodeObjectISA(uint32_t Major, uint32_t Minor,
|
||||
uint32_t Stepping, StringRef VendorName,
|
||||
StringRef ArchName) override;
|
||||
|
||||
void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override;
|
||||
|
||||
void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
bool EmitISAVersion(StringRef IsaVersionString) override;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) override;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
bool EmitPALMetadata(const AMDGPU::PALMD::Metadata &PALMetadata) override;
|
||||
};
|
||||
|
||||
class AMDGPUTargetELFStreamer final : public AMDGPUTargetStreamer {
|
||||
MCStreamer &Streamer;
|
||||
|
||||
void EmitAMDGPUNote(const MCExpr *DescSize, unsigned NoteType,
|
||||
function_ref<void(MCELFStreamer &)> EmitDesc);
|
||||
|
||||
public:
|
||||
AMDGPUTargetELFStreamer(MCStreamer &S);
|
||||
|
||||
MCELFStreamer &getStreamer();
|
||||
|
||||
void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
|
||||
uint32_t Minor) override;
|
||||
|
||||
void EmitDirectiveHSACodeObjectISA(uint32_t Major, uint32_t Minor,
|
||||
uint32_t Stepping, StringRef VendorName,
|
||||
StringRef ArchName) override;
|
||||
|
||||
void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override;
|
||||
|
||||
void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
bool EmitISAVersion(StringRef IsaVersionString) override;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) override;
|
||||
|
||||
/// \returns True on success, false on failure.
|
||||
bool EmitPALMetadata(const AMDGPU::PALMD::Metadata &PALMetadata) override;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
@ -1,12 +0,0 @@
|
||||
add_llvm_library(LLVMAMDGPUDesc
|
||||
AMDGPUAsmBackend.cpp
|
||||
AMDGPUELFObjectWriter.cpp
|
||||
AMDGPUELFStreamer.cpp
|
||||
AMDGPUHSAMetadataStreamer.cpp
|
||||
AMDGPUMCAsmInfo.cpp
|
||||
AMDGPUMCCodeEmitter.cpp
|
||||
AMDGPUMCTargetDesc.cpp
|
||||
AMDGPUTargetStreamer.cpp
|
||||
R600MCCodeEmitter.cpp
|
||||
SIMCCodeEmitter.cpp
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/AMDGPU/MCTargetDesc/LLVMBuild.txt -------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = AMDGPUDesc
|
||||
parent = AMDGPU
|
||||
required_libraries = Core MC AMDGPUAsmPrinter AMDGPUInfo AMDGPUUtils Support
|
||||
add_to_library_groups = AMDGPU
|
@ -1,189 +0,0 @@
|
||||
//===- R600MCCodeEmitter.cpp - Code Emitter for R600->Cayman GPU families -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
///
|
||||
/// \brief The R600 code emitter produces machine code that can be executed
|
||||
/// directly on the GPU device.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/AMDGPUFixupKinds.h"
|
||||
#include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
|
||||
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
|
||||
#include "R600Defines.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/EndianStream.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class R600MCCodeEmitter : public AMDGPUMCCodeEmitter {
|
||||
const MCRegisterInfo &MRI;
|
||||
|
||||
public:
|
||||
R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri)
|
||||
: AMDGPUMCCodeEmitter(mcii), MRI(mri) {}
|
||||
R600MCCodeEmitter(const R600MCCodeEmitter &) = delete;
|
||||
R600MCCodeEmitter &operator=(const R600MCCodeEmitter &) = delete;
|
||||
|
||||
/// \brief Encode the instruction and write it to the OS.
|
||||
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
||||
/// \returns the encoding for an MCOperand.
|
||||
uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
||||
private:
|
||||
void Emit(uint32_t value, raw_ostream &OS) const;
|
||||
void Emit(uint64_t value, raw_ostream &OS) const;
|
||||
|
||||
unsigned getHWReg(unsigned regNo) const;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
enum RegElement {
|
||||
ELEMENT_X = 0,
|
||||
ELEMENT_Y,
|
||||
ELEMENT_Z,
|
||||
ELEMENT_W
|
||||
};
|
||||
|
||||
enum FCInstr {
|
||||
FC_IF_PREDICATE = 0,
|
||||
FC_ELSE,
|
||||
FC_ENDIF,
|
||||
FC_BGNLOOP,
|
||||
FC_ENDLOOP,
|
||||
FC_BREAK_PREDICATE,
|
||||
FC_CONTINUE
|
||||
};
|
||||
|
||||
MCCodeEmitter *llvm::createR600MCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx) {
|
||||
return new R600MCCodeEmitter(MCII, MRI);
|
||||
}
|
||||
|
||||
void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
verifyInstructionPredicates(MI,
|
||||
computeAvailableFeatures(STI.getFeatureBits()));
|
||||
|
||||
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
|
||||
if (MI.getOpcode() == AMDGPU::RETURN ||
|
||||
MI.getOpcode() == AMDGPU::FETCH_CLAUSE ||
|
||||
MI.getOpcode() == AMDGPU::ALU_CLAUSE ||
|
||||
MI.getOpcode() == AMDGPU::BUNDLE ||
|
||||
MI.getOpcode() == AMDGPU::KILL) {
|
||||
return;
|
||||
} else if (IS_VTX(Desc)) {
|
||||
uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI);
|
||||
uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
|
||||
if (!(STI.getFeatureBits()[AMDGPU::FeatureCaymanISA])) {
|
||||
InstWord2 |= 1 << 19; // Mega-Fetch bit
|
||||
}
|
||||
|
||||
Emit(InstWord01, OS);
|
||||
Emit(InstWord2, OS);
|
||||
Emit((uint32_t) 0, OS);
|
||||
} else if (IS_TEX(Desc)) {
|
||||
int64_t Sampler = MI.getOperand(14).getImm();
|
||||
|
||||
int64_t SrcSelect[4] = {
|
||||
MI.getOperand(2).getImm(),
|
||||
MI.getOperand(3).getImm(),
|
||||
MI.getOperand(4).getImm(),
|
||||
MI.getOperand(5).getImm()
|
||||
};
|
||||
int64_t Offsets[3] = {
|
||||
MI.getOperand(6).getImm() & 0x1F,
|
||||
MI.getOperand(7).getImm() & 0x1F,
|
||||
MI.getOperand(8).getImm() & 0x1F
|
||||
};
|
||||
|
||||
uint64_t Word01 = getBinaryCodeForInstr(MI, Fixups, STI);
|
||||
uint32_t Word2 = Sampler << 15 | SrcSelect[ELEMENT_X] << 20 |
|
||||
SrcSelect[ELEMENT_Y] << 23 | SrcSelect[ELEMENT_Z] << 26 |
|
||||
SrcSelect[ELEMENT_W] << 29 | Offsets[0] << 0 | Offsets[1] << 5 |
|
||||
Offsets[2] << 10;
|
||||
|
||||
Emit(Word01, OS);
|
||||
Emit(Word2, OS);
|
||||
Emit((uint32_t) 0, OS);
|
||||
} else {
|
||||
uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI);
|
||||
if ((STI.getFeatureBits()[AMDGPU::FeatureR600ALUInst]) &&
|
||||
((Desc.TSFlags & R600_InstFlag::OP1) ||
|
||||
Desc.TSFlags & R600_InstFlag::OP2)) {
|
||||
uint64_t ISAOpCode = Inst & (0x3FFULL << 39);
|
||||
Inst &= ~(0x3FFULL << 39);
|
||||
Inst |= ISAOpCode << 1;
|
||||
}
|
||||
Emit(Inst, OS);
|
||||
}
|
||||
}
|
||||
|
||||
void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const {
|
||||
support::endian::Writer<support::little>(OS).write(Value);
|
||||
}
|
||||
|
||||
void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const {
|
||||
support::endian::Writer<support::little>(OS).write(Value);
|
||||
}
|
||||
|
||||
unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const {
|
||||
return MRI.getEncodingValue(RegNo) & HW_REG_MASK;
|
||||
}
|
||||
|
||||
uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
|
||||
const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
if (MO.isReg()) {
|
||||
if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags))
|
||||
return MRI.getEncodingValue(MO.getReg());
|
||||
return getHWReg(MO.getReg());
|
||||
}
|
||||
|
||||
if (MO.isExpr()) {
|
||||
// We put rodata at the end of code section, then map the entire
|
||||
// code secetion as vtx buf. Thus the section relative address is the
|
||||
// correct one.
|
||||
// Each R600 literal instruction has two operands
|
||||
// We can't easily get the order of the current one, so compare against
|
||||
// the first one and adjust offset.
|
||||
const unsigned offset = (&MO == &MI.getOperand(0)) ? 0 : 4;
|
||||
Fixups.push_back(MCFixup::create(offset, MO.getExpr(), FK_SecRel_4, MI.getLoc()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(MO.isImm());
|
||||
return MO.getImm();
|
||||
}
|
||||
|
||||
#define ENABLE_INSTR_PREDICATE_VERIFIER
|
||||
#include "AMDGPUGenMCCodeEmitter.inc"
|
@ -1,429 +0,0 @@
|
||||
//===-- SIMCCodeEmitter.cpp - SI Code Emitter -----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// \brief The SI code emitter produces machine code that can be executed
|
||||
/// directly on the GPU device.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPU.h"
|
||||
#include "MCTargetDesc/AMDGPUFixupKinds.h"
|
||||
#include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
|
||||
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
|
||||
#include "Utils/AMDGPUBaseInfo.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrDesc.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/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class SIMCCodeEmitter : public AMDGPUMCCodeEmitter {
|
||||
const MCRegisterInfo &MRI;
|
||||
|
||||
/// \brief Encode an fp or int literal
|
||||
uint32_t getLitEncoding(const MCOperand &MO, const MCOperandInfo &OpInfo,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
public:
|
||||
SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
|
||||
MCContext &ctx)
|
||||
: AMDGPUMCCodeEmitter(mcii), MRI(mri) {}
|
||||
SIMCCodeEmitter(const SIMCCodeEmitter &) = delete;
|
||||
SIMCCodeEmitter &operator=(const SIMCCodeEmitter &) = delete;
|
||||
|
||||
/// \brief Encode the instruction and write it to the OS.
|
||||
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
||||
/// \returns the encoding for an MCOperand.
|
||||
uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
||||
/// \brief Use a fixup to encode the simm16 field for SOPP branch
|
||||
/// instructions.
|
||||
unsigned getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
||||
unsigned getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
||||
unsigned getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx) {
|
||||
return new SIMCCodeEmitter(MCII, MRI, Ctx);
|
||||
}
|
||||
|
||||
// Returns the encoding value to use if the given integer is an integer inline
|
||||
// immediate value, or 0 if it is not.
|
||||
template <typename IntTy>
|
||||
static uint32_t getIntInlineImmEncoding(IntTy Imm) {
|
||||
if (Imm >= 0 && Imm <= 64)
|
||||
return 128 + Imm;
|
||||
|
||||
if (Imm >= -16 && Imm <= -1)
|
||||
return 192 + std::abs(Imm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t getLit16Encoding(uint16_t Val, const MCSubtargetInfo &STI) {
|
||||
uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
|
||||
if (IntImm != 0)
|
||||
return IntImm;
|
||||
|
||||
if (Val == 0x3800) // 0.5
|
||||
return 240;
|
||||
|
||||
if (Val == 0xB800) // -0.5
|
||||
return 241;
|
||||
|
||||
if (Val == 0x3C00) // 1.0
|
||||
return 242;
|
||||
|
||||
if (Val == 0xBC00) // -1.0
|
||||
return 243;
|
||||
|
||||
if (Val == 0x4000) // 2.0
|
||||
return 244;
|
||||
|
||||
if (Val == 0xC000) // -2.0
|
||||
return 245;
|
||||
|
||||
if (Val == 0x4400) // 4.0
|
||||
return 246;
|
||||
|
||||
if (Val == 0xC400) // -4.0
|
||||
return 247;
|
||||
|
||||
if (Val == 0x3118 && // 1.0 / (2.0 * pi)
|
||||
STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
|
||||
return 248;
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
static uint32_t getLit32Encoding(uint32_t Val, const MCSubtargetInfo &STI) {
|
||||
uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
|
||||
if (IntImm != 0)
|
||||
return IntImm;
|
||||
|
||||
if (Val == FloatToBits(0.5f))
|
||||
return 240;
|
||||
|
||||
if (Val == FloatToBits(-0.5f))
|
||||
return 241;
|
||||
|
||||
if (Val == FloatToBits(1.0f))
|
||||
return 242;
|
||||
|
||||
if (Val == FloatToBits(-1.0f))
|
||||
return 243;
|
||||
|
||||
if (Val == FloatToBits(2.0f))
|
||||
return 244;
|
||||
|
||||
if (Val == FloatToBits(-2.0f))
|
||||
return 245;
|
||||
|
||||
if (Val == FloatToBits(4.0f))
|
||||
return 246;
|
||||
|
||||
if (Val == FloatToBits(-4.0f))
|
||||
return 247;
|
||||
|
||||
if (Val == 0x3e22f983 && // 1.0 / (2.0 * pi)
|
||||
STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
|
||||
return 248;
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI) {
|
||||
uint32_t IntImm = getIntInlineImmEncoding(static_cast<int64_t>(Val));
|
||||
if (IntImm != 0)
|
||||
return IntImm;
|
||||
|
||||
if (Val == DoubleToBits(0.5))
|
||||
return 240;
|
||||
|
||||
if (Val == DoubleToBits(-0.5))
|
||||
return 241;
|
||||
|
||||
if (Val == DoubleToBits(1.0))
|
||||
return 242;
|
||||
|
||||
if (Val == DoubleToBits(-1.0))
|
||||
return 243;
|
||||
|
||||
if (Val == DoubleToBits(2.0))
|
||||
return 244;
|
||||
|
||||
if (Val == DoubleToBits(-2.0))
|
||||
return 245;
|
||||
|
||||
if (Val == DoubleToBits(4.0))
|
||||
return 246;
|
||||
|
||||
if (Val == DoubleToBits(-4.0))
|
||||
return 247;
|
||||
|
||||
if (Val == 0x3fc45f306dc9c882 && // 1.0 / (2.0 * pi)
|
||||
STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
|
||||
return 248;
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO,
|
||||
const MCOperandInfo &OpInfo,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
int64_t Imm;
|
||||
if (MO.isExpr()) {
|
||||
const auto *C = dyn_cast<MCConstantExpr>(MO.getExpr());
|
||||
if (!C)
|
||||
return 255;
|
||||
|
||||
Imm = C->getValue();
|
||||
} else {
|
||||
|
||||
assert(!MO.isFPImm());
|
||||
|
||||
if (!MO.isImm())
|
||||
return ~0;
|
||||
|
||||
Imm = MO.getImm();
|
||||
}
|
||||
|
||||
switch (OpInfo.OperandType) {
|
||||
case AMDGPU::OPERAND_REG_IMM_INT32:
|
||||
case AMDGPU::OPERAND_REG_IMM_FP32:
|
||||
case AMDGPU::OPERAND_REG_INLINE_C_INT32:
|
||||
case AMDGPU::OPERAND_REG_INLINE_C_FP32:
|
||||
return getLit32Encoding(static_cast<uint32_t>(Imm), STI);
|
||||
|
||||
case AMDGPU::OPERAND_REG_IMM_INT64:
|
||||
case AMDGPU::OPERAND_REG_IMM_FP64:
|
||||
case AMDGPU::OPERAND_REG_INLINE_C_INT64:
|
||||
case AMDGPU::OPERAND_REG_INLINE_C_FP64:
|
||||
return getLit64Encoding(static_cast<uint64_t>(Imm), STI);
|
||||
|
||||
case AMDGPU::OPERAND_REG_IMM_INT16:
|
||||
case AMDGPU::OPERAND_REG_IMM_FP16:
|
||||
case AMDGPU::OPERAND_REG_INLINE_C_INT16:
|
||||
case AMDGPU::OPERAND_REG_INLINE_C_FP16:
|
||||
// FIXME Is this correct? What do inline immediates do on SI for f16 src
|
||||
// which does not have f16 support?
|
||||
return getLit16Encoding(static_cast<uint16_t>(Imm), STI);
|
||||
|
||||
case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
|
||||
case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
|
||||
uint16_t Lo16 = static_cast<uint16_t>(Imm);
|
||||
uint32_t Encoding = getLit16Encoding(Lo16, STI);
|
||||
return Encoding;
|
||||
}
|
||||
default:
|
||||
llvm_unreachable("invalid operand size");
|
||||
}
|
||||
}
|
||||
|
||||
void SIMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
verifyInstructionPredicates(MI,
|
||||
computeAvailableFeatures(STI.getFeatureBits()));
|
||||
|
||||
uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI);
|
||||
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
|
||||
unsigned bytes = Desc.getSize();
|
||||
|
||||
for (unsigned i = 0; i < bytes; i++) {
|
||||
OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
|
||||
}
|
||||
|
||||
if (bytes > 4)
|
||||
return;
|
||||
|
||||
// Check for additional literals in SRC0/1/2 (Op 1/2/3)
|
||||
for (unsigned i = 0, e = Desc.getNumOperands(); i < e; ++i) {
|
||||
|
||||
// Check if this operand should be encoded as [SV]Src
|
||||
if (!AMDGPU::isSISrcOperand(Desc, i))
|
||||
continue;
|
||||
|
||||
// Is this operand a literal immediate?
|
||||
const MCOperand &Op = MI.getOperand(i);
|
||||
if (getLitEncoding(Op, Desc.OpInfo[i], STI) != 255)
|
||||
continue;
|
||||
|
||||
// Yes! Encode it
|
||||
int64_t Imm = 0;
|
||||
|
||||
if (Op.isImm())
|
||||
Imm = Op.getImm();
|
||||
else if (Op.isExpr()) {
|
||||
if (const auto *C = dyn_cast<MCConstantExpr>(Op.getExpr()))
|
||||
Imm = C->getValue();
|
||||
|
||||
} else if (!Op.isExpr()) // Exprs will be replaced with a fixup value.
|
||||
llvm_unreachable("Must be immediate or expr");
|
||||
|
||||
for (unsigned j = 0; j < 4; j++) {
|
||||
OS.write((uint8_t) ((Imm >> (8 * j)) & 0xff));
|
||||
}
|
||||
|
||||
// Only one literal value allowed
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned SIMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
|
||||
if (MO.isExpr()) {
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
MCFixupKind Kind = (MCFixupKind)AMDGPU::fixup_si_sopp_br;
|
||||
Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getMachineOpValue(MI, MO, Fixups, STI);
|
||||
}
|
||||
|
||||
unsigned
|
||||
SIMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
using namespace AMDGPU::SDWA;
|
||||
|
||||
uint64_t RegEnc = 0;
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
|
||||
unsigned Reg = MO.getReg();
|
||||
RegEnc |= MRI.getEncodingValue(Reg);
|
||||
RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
|
||||
if (AMDGPU::isSGPR(AMDGPU::mc2PseudoReg(Reg), &MRI)) {
|
||||
RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
|
||||
}
|
||||
return RegEnc;
|
||||
}
|
||||
|
||||
unsigned
|
||||
SIMCCodeEmitter::getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
using namespace AMDGPU::SDWA;
|
||||
|
||||
uint64_t RegEnc = 0;
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
|
||||
unsigned Reg = MO.getReg();
|
||||
if (Reg != AMDGPU::VCC) {
|
||||
RegEnc |= MRI.getEncodingValue(Reg);
|
||||
RegEnc &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
|
||||
RegEnc |= SDWA9EncValues::VOPC_DST_VCC_MASK;
|
||||
}
|
||||
return RegEnc;
|
||||
}
|
||||
|
||||
static bool needsPCRel(const MCExpr *Expr) {
|
||||
switch (Expr->getKind()) {
|
||||
case MCExpr::SymbolRef:
|
||||
return true;
|
||||
case MCExpr::Binary: {
|
||||
auto *BE = cast<MCBinaryExpr>(Expr);
|
||||
if (BE->getOpcode() == MCBinaryExpr::Sub)
|
||||
return false;
|
||||
return needsPCRel(BE->getLHS()) || needsPCRel(BE->getRHS());
|
||||
}
|
||||
case MCExpr::Unary:
|
||||
return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
|
||||
case MCExpr::Target:
|
||||
case MCExpr::Constant:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("invalid kind");
|
||||
}
|
||||
|
||||
uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
|
||||
const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
if (MO.isReg())
|
||||
return MRI.getEncodingValue(MO.getReg());
|
||||
|
||||
if (MO.isExpr() && MO.getExpr()->getKind() != MCExpr::Constant) {
|
||||
// FIXME: If this is expression is PCRel or not should not depend on what
|
||||
// the expression looks like. Given that this is just a general expression,
|
||||
// it should probably be FK_Data_4 and whatever is producing
|
||||
//
|
||||
// s_add_u32 s2, s2, (extern_const_addrspace+16
|
||||
//
|
||||
// And expecting a PCRel should instead produce
|
||||
//
|
||||
// .Ltmp1:
|
||||
// s_add_u32 s2, s2, (extern_const_addrspace+16)-.Ltmp1
|
||||
MCFixupKind Kind;
|
||||
if (needsPCRel(MO.getExpr()))
|
||||
Kind = FK_PCRel_4;
|
||||
else
|
||||
Kind = FK_Data_4;
|
||||
Fixups.push_back(MCFixup::create(4, MO.getExpr(), Kind, MI.getLoc()));
|
||||
}
|
||||
|
||||
// Figure out the operand number, needed for isSrcOperand check
|
||||
unsigned OpNo = 0;
|
||||
for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) {
|
||||
if (&MO == &MI.getOperand(OpNo))
|
||||
break;
|
||||
}
|
||||
|
||||
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
|
||||
if (AMDGPU::isSISrcOperand(Desc, OpNo)) {
|
||||
uint32_t Enc = getLitEncoding(MO, Desc.OpInfo[OpNo], STI);
|
||||
if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4))
|
||||
return Enc;
|
||||
|
||||
} else if (MO.isImm())
|
||||
return MO.getImm();
|
||||
|
||||
llvm_unreachable("Encoding of this operand type is not supported yet.");
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user