Bring loader in sync with stg/sc
Change-Id: I684522c442de0872007a7e4da8919067fc7b42b3
[ROCm/ROCR-Runtime commit: c798c60343]
This commit is contained in:
@@ -158,7 +158,8 @@ set ( SRCS "core/util/lnx/os_linux.cpp"
|
||||
"libamdhsacode/amd_hsa_code_util.cpp"
|
||||
"libamdhsacode/amd_hsa_locks.cpp"
|
||||
"libamdhsacode/amd_options.cpp"
|
||||
"libamdhsacode/amd_hsa_code.cpp"
|
||||
"libamdhsacode/amd_hsa_code.cpp"
|
||||
"libamdhsacode/amdgpu_metadata.cpp"
|
||||
)
|
||||
|
||||
add_library( ${CORE_RUNTIME_TARGET} SHARED ${SRCS} )
|
||||
|
||||
@@ -183,6 +183,9 @@ namespace code {
|
||||
static Symbol* FromHandle(hsa_code_symbol_t handle);
|
||||
void setValue(uint64_t value) { elfsym->setValue(value); }
|
||||
void setSize(uint32_t size) { elfsym->setSize(size); }
|
||||
|
||||
std::string GetModuleName() const;
|
||||
std::string GetSymbolName() const;
|
||||
};
|
||||
|
||||
class KernelSymbol : public Symbol {
|
||||
@@ -209,6 +212,10 @@ namespace code {
|
||||
hsa_status_t GetInfo(hsa_code_symbol_info_t attribute, void *value) override;
|
||||
};
|
||||
|
||||
namespace Program {
|
||||
class Metadata;
|
||||
}
|
||||
|
||||
class AmdHsaCode {
|
||||
private:
|
||||
std::ostringstream out;
|
||||
@@ -227,10 +234,12 @@ namespace code {
|
||||
amd::elf::Section* debugInfo;
|
||||
amd::elf::Section* debugLine;
|
||||
amd::elf::Section* debugAbbrev;
|
||||
Program::Metadata* runtimeMetadata;
|
||||
|
||||
bool PullElf();
|
||||
bool PullElfV1();
|
||||
bool PullElfV2();
|
||||
bool PullOpenCLMetadata(const void* buffer, size_t size);
|
||||
|
||||
void AddAmdNote(uint32_t type, const void* desc, uint32_t desc_size);
|
||||
template <typename S>
|
||||
@@ -255,6 +264,7 @@ namespace code {
|
||||
void PrintRelocationData(std::ostream& out, RelocationSection* section);
|
||||
void PrintSymbol(std::ostream& out, Symbol* sym);
|
||||
void PrintDisassembly(std::ostream& out, const unsigned char *isa, size_t size, uint32_t isa_offset = 0);
|
||||
void PrintOpenCLMetadata(std::ostream& out);
|
||||
std::string MangleSymbolName(const std::string& module_name, const std::string symbol_name);
|
||||
bool ElfImageError();
|
||||
|
||||
@@ -390,6 +400,8 @@ namespace code {
|
||||
Section* DebugAbbrev();
|
||||
|
||||
Section* AddHsaHlDebug(const std::string& name, const void* data, size_t size);
|
||||
|
||||
Program::Metadata* GetRuntimeMetadata();
|
||||
};
|
||||
|
||||
class AmdHsaCodeManager {
|
||||
|
||||
@@ -408,6 +408,9 @@ public:
|
||||
/// invalid address, returns null pointer.
|
||||
virtual uint64_t FindHostAddress(uint64_t device_address) = 0;
|
||||
|
||||
/// @brief Print loader help.
|
||||
virtual void PrintHelp(std::ostream& out) = 0;
|
||||
|
||||
protected:
|
||||
/// @brief Default constructor.
|
||||
Loader() {}
|
||||
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
//===-- AMDGPURuntimeMetadata.h - AMDGPU Runtime Metadata -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
///
|
||||
/// Enums and structure types used by runtime metadata.
|
||||
///
|
||||
/// Runtime requests certain information (metadata) about kernels to be able
|
||||
/// to execute the kernels and answer the queries about the kernels.
|
||||
/// The metadata is represented as a byte stream in an ELF section of a
|
||||
/// binary (code object). The byte stream consists of key-value pairs.
|
||||
/// Each key is an 8 bit unsigned integer. Each value can be an integer,
|
||||
/// a string, or a stream of key-value pairs. There are 3 levels of key-value
|
||||
/// pair streams. At the beginning of the ELF section is the top level
|
||||
/// key-value pair stream. A kernel-level key-value pair stream starts after
|
||||
/// encountering KeyKernelBegin and ends immediately before encountering
|
||||
/// KeyKernelEnd. A kernel-argument-level key-value pair stream starts
|
||||
/// after encountering KeyArgBegin and ends immediately before encountering
|
||||
/// KeyArgEnd. A kernel-level key-value pair stream can only appear in a top
|
||||
/// level key-value pair stream. A kernel-argument-level key-value pair stream
|
||||
/// can only appear in a kernel-level key-value pair stream.
|
||||
///
|
||||
/// The format should be kept backward compatible. New enum values and bit
|
||||
/// fields should be appended at the end. It is suggested to bump up the
|
||||
/// revision number whenever the format changes and document the change
|
||||
/// in the revision in this header.
|
||||
///
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPURUNTIMEMETADATA_H
|
||||
#define LLVM_LIB_TARGET_AMDGPU_AMDGPURUNTIMEMETADATA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace AMDGPU {
|
||||
|
||||
namespace RuntimeMD {
|
||||
|
||||
// Version and revision of runtime metadata
|
||||
const unsigned char MDVersion = 1;
|
||||
const unsigned char MDRevision = 0;
|
||||
|
||||
// ELF section name containing runtime metadata
|
||||
const char SectionName[] = ".AMDGPU.runtime_metadata";
|
||||
|
||||
// Enumeration values of keys in runtime metadata.
|
||||
enum Key {
|
||||
KeyNull = 0, // Place holder. Ignored when encountered
|
||||
KeyMDVersion = 1, // Runtime metadata version
|
||||
KeyLanguage = 2, // Language
|
||||
KeyLanguageVersion = 3, // Language version
|
||||
KeyKernelBegin = 4, // Beginning of kernel-level stream
|
||||
KeyKernelEnd = 5, // End of kernel-level stream
|
||||
KeyKernelName = 6, // Kernel name
|
||||
KeyArgBegin = 7, // Beginning of kernel-arg-level stream
|
||||
KeyArgEnd = 8, // End of kernel-arg-level stream
|
||||
KeyArgSize = 9, // Kernel arg size
|
||||
KeyArgAlign = 10, // Kernel arg alignment
|
||||
KeyArgTypeName = 11, // Kernel type name
|
||||
KeyArgName = 12, // Kernel name
|
||||
KeyArgKind = 13, // Kernel argument kind
|
||||
KeyArgValueType = 14, // Kernel argument value type
|
||||
KeyArgAddrQual = 15, // Kernel argument address qualifier
|
||||
KeyArgAccQual = 16, // Kernel argument access qualifier
|
||||
KeyArgIsConst = 17, // Kernel argument is const qualified
|
||||
KeyArgIsRestrict = 18, // Kernel argument is restrict qualified
|
||||
KeyArgIsVolatile = 19, // Kernel argument is volatile qualified
|
||||
KeyArgIsPipe = 20, // Kernel argument is pipe qualified
|
||||
KeyReqdWorkGroupSize = 21, // Required work group size
|
||||
KeyWorkGroupSizeHint = 22, // Work group size hint
|
||||
KeyVecTypeHint = 23, // Vector type hint
|
||||
KeyKernelIndex = 24, // Kernel index for device enqueue
|
||||
KeyMinWavesPerSIMD = 25, // Minimum number of waves per SIMD
|
||||
KeyMaxWavesPerSIMD = 26, // Maximum number of waves per SIMD
|
||||
KeyFlatWorkGroupSizeLimits = 27, // Flat work group size limits
|
||||
KeyMaxWorkGroupSize = 28, // Maximum work group size
|
||||
KeyNoPartialWorkGroups = 29, // No partial work groups
|
||||
KeyPrintfInfo = 30, // Prinf function call information
|
||||
KeyArgActualAcc = 31, // The actual kernel argument access qualifier
|
||||
KeyArgPointeeAlign = 32, // Alignment of pointee type
|
||||
};
|
||||
|
||||
enum Language : uint8_t {
|
||||
OpenCL_C = 0,
|
||||
HCC = 1,
|
||||
OpenMP = 2,
|
||||
OpenCL_CPP = 3,
|
||||
};
|
||||
|
||||
enum LanguageVersion : uint16_t {
|
||||
V100 = 100,
|
||||
V110 = 110,
|
||||
V120 = 120,
|
||||
V200 = 200,
|
||||
V210 = 210,
|
||||
};
|
||||
|
||||
namespace KernelArg {
|
||||
enum Kind : uint8_t {
|
||||
ByValue = 0,
|
||||
GlobalBuffer = 1,
|
||||
DynamicSharedPointer = 2,
|
||||
Sampler = 3,
|
||||
Image = 4,
|
||||
Pipe = 5,
|
||||
Queue = 6,
|
||||
HiddenGlobalOffsetX = 7,
|
||||
HiddenGlobalOffsetY = 8,
|
||||
HiddenGlobalOffsetZ = 9,
|
||||
HiddenNone = 10,
|
||||
HiddenPrintfBuffer = 11,
|
||||
HiddenDefaultQueue = 12,
|
||||
HiddenCompletionAction = 13,
|
||||
};
|
||||
|
||||
enum ValueType : uint16_t {
|
||||
Struct = 0,
|
||||
I8 = 1,
|
||||
U8 = 2,
|
||||
I16 = 3,
|
||||
U16 = 4,
|
||||
F16 = 5,
|
||||
I32 = 6,
|
||||
U32 = 7,
|
||||
F32 = 8,
|
||||
I64 = 9,
|
||||
U64 = 10,
|
||||
F64 = 11,
|
||||
};
|
||||
|
||||
enum AccessQualifer : uint8_t {
|
||||
None = 0,
|
||||
ReadOnly = 1,
|
||||
WriteOnly = 2,
|
||||
ReadWrite = 3,
|
||||
};
|
||||
|
||||
enum AddressSpaceQualifer : uint8_t {
|
||||
Private = 0,
|
||||
Global = 1,
|
||||
Constant = 2,
|
||||
Local = 3,
|
||||
Generic = 4,
|
||||
Region = 5,
|
||||
};
|
||||
} // namespace KernelArg
|
||||
} // namespace RuntimeMD
|
||||
} // namespace AMDGPU
|
||||
|
||||
#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPURUNTIMEMETADATA_H
|
||||
@@ -41,6 +41,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "amd_elf_image.hpp"
|
||||
#include "amd_hsa_code_util.hpp"
|
||||
#include <gelf.h>
|
||||
#include <errno.h>
|
||||
#include <cstring>
|
||||
@@ -50,7 +51,6 @@
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include "amd_hsa_code_util.hpp"
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#define alignof __alignof
|
||||
@@ -60,17 +60,38 @@
|
||||
#ifndef _WIN32
|
||||
#define _open open
|
||||
#define _close close
|
||||
#define _tempnam tempnam
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_MEMFILE)
|
||||
|
||||
#include "memfile.h"
|
||||
#define OpenTemp(f) mem_open(NULL, 0, 0)
|
||||
#define CloseTemp(f) mem_close(f)
|
||||
#define _read(f, b, l) mem_read((f), (b), (l))
|
||||
#define _write(f, b, l) mem_write((f), (b), (l))
|
||||
#define _lseek(f, l, w) mem_lseek((f), (l), (w))
|
||||
#define _ftruncate(f, l) mem_ftruncate((f), (size_t)(l))
|
||||
#define sendfile(o, i, p, s) mem_sendfile((o), (i), (p), (s))
|
||||
|
||||
#else // USE_MEMFILE
|
||||
|
||||
#define OpenTemp(f) amd::hsa::OpenTempFile(f);
|
||||
#define CloseTemp(f) amd::hsa::CloseTempFile(f);
|
||||
|
||||
#ifndef _WIN32
|
||||
#define _read read
|
||||
#define _write write
|
||||
#define _lseek lseek
|
||||
#define _ftruncate ftruncate
|
||||
#define _tempnam tempnam
|
||||
#include <sys/sendfile.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#define _ftruncate _chsize
|
||||
#endif
|
||||
#endif // !_WIN32
|
||||
|
||||
#endif // !USE_MEMFILE
|
||||
|
||||
#if !defined(BSD_LIBELF)
|
||||
#define elf_setshstrndx elfx_update_shstrndx
|
||||
@@ -115,7 +136,7 @@ namespace amd {
|
||||
|
||||
FileImage::~FileImage()
|
||||
{
|
||||
if (d >= 0) { amd::hsa::CloseTempFile(d); }
|
||||
if (d != -1) { CloseTemp(d); }
|
||||
}
|
||||
|
||||
bool FileImage::error(const char* msg)
|
||||
@@ -153,8 +174,8 @@ namespace amd {
|
||||
|
||||
bool FileImage::create()
|
||||
{
|
||||
d = amd::hsa::OpenTempFile("amdelf");
|
||||
if (d < 0) { return error("Failed to open temporary file for elf image"); }
|
||||
d = OpenTemp("amdelf");
|
||||
if (d == -1) { return error("Failed to open temporary file for elf image"); }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#include <algorithm>
|
||||
#include "amd_hsa_code.hpp"
|
||||
#include "amd_hsa_code_util.hpp"
|
||||
#include "amdgpu_metadata.hpp"
|
||||
#include "AMDGPURuntimeMetadata.h"
|
||||
#include <libelf.h>
|
||||
#include "amd_hsa_elf.h"
|
||||
#include <fstream>
|
||||
@@ -122,60 +124,30 @@ namespace code {
|
||||
hsa_status_t Symbol::GetInfo(hsa_code_symbol_info_t attribute, void *value)
|
||||
{
|
||||
assert(value);
|
||||
std::string name = Name();
|
||||
|
||||
switch (attribute) {
|
||||
case HSA_CODE_SYMBOL_INFO_TYPE: {
|
||||
*((hsa_symbol_kind_t*)value) = Kind();
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_NAME_LENGTH:
|
||||
case HSA_CODE_SYMBOL_INFO_NAME: {
|
||||
std::string matter = "";
|
||||
switch (Linkage()) {
|
||||
case HSA_SYMBOL_LINKAGE_PROGRAM:
|
||||
assert(name.rfind(":") == std::string::npos);
|
||||
matter = name;
|
||||
break;
|
||||
case HSA_SYMBOL_LINKAGE_MODULE:
|
||||
assert(name.rfind(":") != std::string::npos);
|
||||
matter = name.substr(name.rfind(":") + 1);
|
||||
break;
|
||||
default:
|
||||
assert(!"Unsupported linkage in Symbol::GetInfo");
|
||||
return HSA_STATUS_ERROR;
|
||||
}
|
||||
if (attribute == HSA_CODE_SYMBOL_INFO_NAME_LENGTH) {
|
||||
*((uint32_t*) value) = matter.size() + 1;
|
||||
} else {
|
||||
memset(value, 0x0, matter.size() + 1);
|
||||
memcpy(value, matter.c_str(), matter.size());
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_NAME_LENGTH: {
|
||||
*((uint32_t*)value) = GetSymbolName().size();
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_NAME: {
|
||||
std::string SymbolName = GetSymbolName();
|
||||
memset(value, 0x0, SymbolName.size());
|
||||
memcpy(value, SymbolName.c_str(), SymbolName.size());
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_MODULE_NAME_LENGTH: {
|
||||
*((uint32_t*)value) = GetModuleName().size();
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_MODULE_NAME_LENGTH:
|
||||
case HSA_CODE_SYMBOL_INFO_MODULE_NAME: {
|
||||
switch (Linkage()) {
|
||||
case HSA_SYMBOL_LINKAGE_PROGRAM:
|
||||
if (attribute == HSA_CODE_SYMBOL_INFO_MODULE_NAME_LENGTH) {
|
||||
*((uint32_t*) value) = 0;
|
||||
}
|
||||
break;
|
||||
case HSA_SYMBOL_LINKAGE_MODULE: {
|
||||
assert(name.find(":") != std::string::npos);
|
||||
std::string matter = name.substr(0, name.find(":"));
|
||||
if (attribute == HSA_CODE_SYMBOL_INFO_MODULE_NAME_LENGTH) {
|
||||
*((uint32_t*) value) = matter.length() + 1;
|
||||
} else {
|
||||
memset(value, 0x0, matter.size() + 1);
|
||||
memcpy(value, matter.c_str(), matter.length());
|
||||
((char*)value)[matter.size() + 1] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(!"Unsupported linkage in Symbol::GetInfo");
|
||||
return HSA_STATUS_ERROR;
|
||||
}
|
||||
std::string ModuleName = GetModuleName();
|
||||
memset(value, 0x0, ModuleName.size());
|
||||
memcpy(value, ModuleName.c_str(), ModuleName.size());
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_LINKAGE: {
|
||||
@@ -193,6 +165,18 @@ namespace code {
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
std::string Symbol::GetModuleName() const {
|
||||
std::string FullName = Name();
|
||||
return FullName.rfind(":") != std::string::npos ?
|
||||
FullName.substr(0, FullName.find(":")) : "";
|
||||
}
|
||||
|
||||
std::string Symbol::GetSymbolName() const {
|
||||
std::string FullName = Name();
|
||||
return FullName.rfind(":") != std::string::npos ?
|
||||
FullName.substr(FullName.rfind(":") + 1) : FullName;
|
||||
}
|
||||
|
||||
hsa_code_symbol_t Symbol::ToHandle(Symbol* sym)
|
||||
{
|
||||
hsa_code_symbol_t s;
|
||||
@@ -289,7 +273,8 @@ namespace code {
|
||||
: img(nullptr),
|
||||
combineDataSegments(combineDataSegments_),
|
||||
hsatext(0), imageInit(0), samplerInit(0),
|
||||
debugInfo(0), debugLine(0), debugAbbrev(0)
|
||||
debugInfo(0), debugLine(0), debugAbbrev(0),
|
||||
runtimeMetadata(0)
|
||||
{
|
||||
for (unsigned i = 0; i < AMDGPU_HSA_SEGMENT_LAST; ++i) {
|
||||
for (unsigned j = 0; j < 2; ++j) {
|
||||
@@ -378,6 +363,17 @@ namespace code {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AmdHsaCode::PullOpenCLMetadata(const void* buffer, size_t size)
|
||||
{
|
||||
assert(!runtimeMetadata);
|
||||
runtimeMetadata = new Program::Metadata();
|
||||
if (!runtimeMetadata->ReadFrom(buffer, size)) {
|
||||
out << "Failed to read OpenCL metadata" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AmdHsaCode::LoadFromFile(const std::string& filename)
|
||||
{
|
||||
if (!img) { img.reset(amd::elf::NewElf64Image()); }
|
||||
@@ -994,6 +990,9 @@ namespace code {
|
||||
PrintSymbols(out);
|
||||
out << std::endl;
|
||||
PrintMachineCode(out);
|
||||
out << std::endl;
|
||||
PrintOpenCLMetadata(out);
|
||||
out << std::endl;
|
||||
out << "AMD HSA Code Object End" << std::endl;
|
||||
}
|
||||
|
||||
@@ -1100,6 +1099,19 @@ namespace code {
|
||||
}
|
||||
}
|
||||
|
||||
Program::Metadata* AmdHsaCode::GetRuntimeMetadata()
|
||||
{
|
||||
return runtimeMetadata;
|
||||
}
|
||||
|
||||
void AmdHsaCode::PrintOpenCLMetadata(std::ostream& out)
|
||||
{
|
||||
Program::Metadata* md = GetRuntimeMetadata();
|
||||
if (!md) { return; }
|
||||
md->Print(out);
|
||||
}
|
||||
|
||||
|
||||
void AmdHsaCode::PrintSegment(std::ostream& out, Segment* segment)
|
||||
{
|
||||
out << " Segment (" << segment->getSegmentIndex() << ")" << std::endl;
|
||||
@@ -1250,7 +1262,7 @@ namespace code {
|
||||
} else if (major_version == 8) {
|
||||
asic = "VI";
|
||||
} else if (major_version == 9) {
|
||||
asic = "GREENLAND";
|
||||
asic = "GFX9";
|
||||
} else {
|
||||
assert(!"unknown compute capability");
|
||||
}
|
||||
@@ -1522,11 +1534,15 @@ namespace code {
|
||||
|
||||
bool AmdHsaCode::PullElfV2()
|
||||
{
|
||||
Segment* note = NULL;
|
||||
for (size_t i = 0; i < img->segmentCount(); ++i) {
|
||||
Segment* s = img->segment(i);
|
||||
if (s->type() == PT_LOAD) {
|
||||
dataSegments.push_back(s);
|
||||
}
|
||||
else if (s->type() == PT_NOTE && s->align() >= 4) {
|
||||
note = s;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < img->sectionCount(); ++i) {
|
||||
Section* sec = img->section(i);
|
||||
@@ -1573,6 +1589,32 @@ namespace code {
|
||||
if (sym) { symbols.push_back(sym); }
|
||||
}
|
||||
|
||||
if (note) {
|
||||
// Iterate over the notes in this segment
|
||||
const char* ptr = note->data();
|
||||
const char* end = ptr + note->imageSize();
|
||||
|
||||
while (ptr < end) {
|
||||
struct Elf_Note {
|
||||
uint32_t n_namesz; // Length of note's name
|
||||
uint32_t n_descsz; // Length of note's value
|
||||
uint32_t n_type; // Type of note
|
||||
}* note = (struct Elf_Note*) ptr;
|
||||
const char* name = (const char*) ¬e[1];
|
||||
const char* desc = name + ((note->n_namesz + 3) & -4);
|
||||
|
||||
if (note->n_type == 7 /*NT_AMDGPU_HSA_RUNTIME_METADATA_1_0*/
|
||||
&& note->n_namesz == sizeof "AMD"
|
||||
&& !memcmp(name, "AMD", note->n_namesz)) {
|
||||
if (!PullOpenCLMetadata(desc,note->n_descsz)) { return false; }
|
||||
break;
|
||||
}
|
||||
ptr += sizeof(*note)
|
||||
+ ((note->n_namesz + 3) & -4)
|
||||
+ ((note->n_descsz + 3) & -4);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -222,6 +222,47 @@ void ChoiceOption::PrintHelp(HelpPrinter& printer) const {
|
||||
printer.PrintUsage(usage).PrintDescription(help_);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PrefixOption. //
|
||||
//===----------------------------------------------------------------------===//
|
||||
bool PrefixOption::IsValid() const {
|
||||
return (0 < name_.size()) && (name_.find(':') == std::string::npos);
|
||||
}
|
||||
|
||||
std::string::size_type PrefixOption::FindPrefix(const std::string& token) const {
|
||||
auto prefix = name_ + ':';
|
||||
return token.find(prefix);
|
||||
}
|
||||
|
||||
bool PrefixOption::Accept(const std::string& token) const {
|
||||
return
|
||||
(token.compare(0, name_.length(), name_) == 0) &&
|
||||
token.length() > name_.length() &&
|
||||
token[name_.length()] == ':';
|
||||
}
|
||||
|
||||
bool PrefixOption::ProcessTokens(std::list<std::string> &tokens) {
|
||||
assert(1 <= tokens.size());
|
||||
assert(Accept(tokens.front()) && "option name is mismatched");
|
||||
|
||||
std::string value = tokens.front(); tokens.pop_front();
|
||||
value = value.substr(name_.length() + 1);
|
||||
|
||||
for (const auto& token: tokens) {
|
||||
value += '=';
|
||||
value += token;
|
||||
}
|
||||
tokens.clear();
|
||||
|
||||
values_.push_back(value);
|
||||
is_set_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrefixOption::PrintHelp(HelpPrinter& printer) const {
|
||||
printer.PrintUsage("-" + name_ + ":[value]").PrintDescription(help_);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OptionParser. //
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -230,7 +271,7 @@ OptionParser::FindOption(const std::string& name) {
|
||||
std::vector<OptionBase*>::iterator it = options_.begin();
|
||||
std::vector<OptionBase*>::iterator end = options_.end();
|
||||
for (; it != end; ++it) {
|
||||
if ((*it)->name() == name) {
|
||||
if ((*it)->Accept(name)) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
return is_set_;
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
virtual bool IsValid() const {
|
||||
return 0 < name_.size();
|
||||
}
|
||||
|
||||
@@ -166,6 +166,7 @@ protected:
|
||||
error_(&error) {}
|
||||
|
||||
virtual void PrintHelp(HelpPrinter& printer) const = 0;
|
||||
virtual bool Accept(const std::string& name) const { return name_ == name; }
|
||||
|
||||
const std::string name_;
|
||||
const std::string help_;
|
||||
@@ -393,6 +394,41 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PrefixOption. //
|
||||
//===----------------------------------------------------------------------===//
|
||||
class PrefixOption final: public OptionBase {
|
||||
public:
|
||||
PrefixOption(const std::string& prefix,
|
||||
const std::string& help = "",
|
||||
std::ostream& error = std::cerr)
|
||||
: OptionBase(prefix, help, error) {}
|
||||
|
||||
~PrefixOption() {}
|
||||
|
||||
const std::vector<std::string>& values() const {
|
||||
return values_;
|
||||
}
|
||||
|
||||
bool IsValid() const override;
|
||||
|
||||
protected:
|
||||
void PrintHelp(HelpPrinter& printer) const override;
|
||||
bool Accept(const std::string& token) const override;
|
||||
|
||||
private:
|
||||
/// @brief Not copy-constructible.
|
||||
PrefixOption(const PrefixOption&);
|
||||
/// @brief Not copy-assignable.
|
||||
PrefixOption& operator =(const PrefixOption&);
|
||||
|
||||
bool ProcessTokens(std::list<std::string> &tokens);
|
||||
|
||||
std::string::size_type FindPrefix(const std::string& token) const;
|
||||
|
||||
std::vector<std::string> values_;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OptionParser. //
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The University of Illinois/NCSA
|
||||
// Open Source License (NCSA)
|
||||
//
|
||||
// Copyright (c) 2014-2016, Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Developed by:
|
||||
//
|
||||
// AMD Research and AMD HSA Software Development
|
||||
//
|
||||
// Advanced Micro Devices, Inc.
|
||||
//
|
||||
// www.amd.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal with the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimers.
|
||||
// - Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimers in
|
||||
// the documentation and/or other materials provided with the distribution.
|
||||
// - Neither the names of Advanced Micro Devices, Inc,
|
||||
// nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this Software without specific prior written
|
||||
// permission.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS WITH THE SOFTWARE.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "amdgpu_metadata.hpp"
|
||||
|
||||
namespace amd {
|
||||
namespace hsa {
|
||||
namespace code {
|
||||
|
||||
template <typename T>
|
||||
bool Read(std::istream& in, T& v);
|
||||
|
||||
template<>
|
||||
bool Read<uint32_t>(std::istream& in, uint32_t& v) {
|
||||
in.read((char *)&v, sizeof(v));
|
||||
return (in.tellg() != (std::streampos) -1 ) && !in.eof() && !in.fail() && !in.bad();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Read<uint16_t>(std::istream& in, uint16_t& v) {
|
||||
in.read((char *)&v, sizeof(v));
|
||||
return !in.eof() && !in.fail() && !in.bad();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Read<uint8_t>(std::istream& in, uint8_t& v) {
|
||||
in.read((char *)&v, sizeof(v));
|
||||
return !in.eof() && !in.fail() && !in.bad();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Read<std::string>(std::istream& in, std::string& v) {
|
||||
uint32_t len;
|
||||
if (!Read(in, len)) { return false; }
|
||||
v.resize(len);
|
||||
if (!in.read(&v[0], len)) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Read3(std::istream& in, T* v) {
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
if (!Read(in, v[i])) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T1, typename T>
|
||||
bool ReadConvert(std::istream& in, T& v) {
|
||||
T1 v1;
|
||||
if (!Read<T1>(in, v1)) { return false; }
|
||||
v = static_cast<T>(v1);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Read<AMDGPU::RuntimeMD::Key>(std::istream& in, AMDGPU::RuntimeMD::Key& v) {
|
||||
return ReadConvert<uint8_t>(in, v);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Read<AMDGPU::RuntimeMD::KernelArg::Kind>(std::istream& in, AMDGPU::RuntimeMD::KernelArg::Kind& v) {
|
||||
return ReadConvert<uint8_t>(in, v);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Read<AMDGPU::RuntimeMD::KernelArg::ValueType>(std::istream& in, AMDGPU::RuntimeMD::KernelArg::ValueType& v) {
|
||||
return ReadConvert<uint16_t>(in, v);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Read<AMDGPU::RuntimeMD::KernelArg::AccessQualifer>(std::istream& in, AMDGPU::RuntimeMD::KernelArg::AccessQualifer& v) {
|
||||
return ReadConvert<uint8_t>(in, v);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Read<AMDGPU::RuntimeMD::Language>(std::istream& in, AMDGPU::RuntimeMD::Language& v) {
|
||||
return ReadConvert<uint8_t>(in, v);
|
||||
}
|
||||
|
||||
namespace KernelArg {
|
||||
using namespace AMDGPU::RuntimeMD::KernelArg;
|
||||
Metadata::Metadata()
|
||||
: size(0), align(0), pointeeAlign(0), accQual(None),
|
||||
isConst(false), isRestrict(false), isVolatile(false), isPipe(false)
|
||||
{}
|
||||
|
||||
static const char* KindToString(Kind kind) {
|
||||
switch (kind) {
|
||||
case ByValue: return "ByValue";
|
||||
case GlobalBuffer: return "GlobalBuffer";
|
||||
case DynamicSharedPointer: return "DynamicSharedPointer";
|
||||
case Image: return "Image";
|
||||
case Sampler: return "Sampler";
|
||||
case Pipe: return "Pipe";
|
||||
case Queue: return "Queue";
|
||||
case HiddenGlobalOffsetX: return "HiddenGlobalOffsetX";
|
||||
case HiddenGlobalOffsetY: return "HiddenGlobalOffsetY";
|
||||
case HiddenGlobalOffsetZ: return "HiddenGlobalOffsetZ";
|
||||
case HiddenPrintfBuffer: return "HiddenPrintfBuffer";
|
||||
case HiddenDefaultQueue: return "HiddenDefaultQueue";
|
||||
case HiddenCompletionAction: return "HiddenCompletionAction";
|
||||
case HiddenNone: return "HiddenNone";
|
||||
default: return "<UnknownType>";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* ValueTypeToString(ValueType valueType) {
|
||||
switch (valueType) {
|
||||
case Struct: return "Struct";
|
||||
case I8: return "I8";
|
||||
case U8: return "U8";
|
||||
case I16: return "I16";
|
||||
case U16: return "U16";
|
||||
case F16: return "F16";
|
||||
case I32: return "I32";
|
||||
case U32: return "U32";
|
||||
case F32: return "F32";
|
||||
case I64: return "I64";
|
||||
case U64: return "U64";
|
||||
case F64: return "F64";
|
||||
default: return "<UnknownValueType>";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* AccessQualToString(AccessQualifer accessQual) {
|
||||
switch (accessQual) {
|
||||
case None: return "None";
|
||||
case ReadOnly: return "ReadOnly";
|
||||
case WriteOnly: return "WriteOnly";
|
||||
case ReadWrite: return "ReadWrite";
|
||||
default: return "<UnknownTypeQual>";
|
||||
}
|
||||
}
|
||||
|
||||
bool Metadata::ReadValue(std::istream& in, AMDGPU::RuntimeMD::Key key) {
|
||||
using namespace AMDGPU::RuntimeMD;
|
||||
|
||||
switch (key) {
|
||||
case KeyArgSize: return Read(in, size);
|
||||
case KeyArgAlign: return Read(in, align);
|
||||
case KeyArgTypeName: return Read(in, typeName);
|
||||
case KeyArgName: return Read(in, name);
|
||||
case KeyArgKind: return Read(in, kind);
|
||||
case KeyArgValueType: return Read(in, valueType);
|
||||
case KeyArgPointeeAlign: return Read(in, pointeeAlign);
|
||||
case KeyArgAddrQual: return Read(in, addrQual);
|
||||
case KeyArgAccQual: return Read(in, accQual);
|
||||
case KeyArgIsConst: isConst = true; return true;
|
||||
case KeyArgIsRestrict: isRestrict = true; return true;
|
||||
case KeyArgIsVolatile: isVolatile = true; return true;
|
||||
case KeyArgIsPipe: isPipe = true; return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Metadata::Print(std::ostream& out) {
|
||||
out
|
||||
<< "Kind: " << KindToString(kind);
|
||||
if (kind == ByValue) {
|
||||
out << " ValueType:" << ValueTypeToString(valueType);
|
||||
}
|
||||
if (isConst) { out << " Const"; }
|
||||
if (isRestrict) { out << " Restrict"; }
|
||||
if (isVolatile) { out << " Volatile"; }
|
||||
if (isPipe) { out << " Pipe"; }
|
||||
if (kind == Image || kind == Pipe) {
|
||||
out << " Access: " << AccessQualToString(accQual);
|
||||
}
|
||||
if (kind == GlobalBuffer || kind == DynamicSharedPointer) {
|
||||
out
|
||||
<< " Address: " << (unsigned) addrQual;
|
||||
}
|
||||
out
|
||||
<< " Size: " << size
|
||||
<< " Align: " << align;
|
||||
if (kind == DynamicSharedPointer) {
|
||||
out << " Pointee Align: " << pointeeAlign;
|
||||
}
|
||||
if (!typeName.empty()) {
|
||||
out << " Type Name: \"" << typeName << "\"";
|
||||
}
|
||||
if (!name.empty()) {
|
||||
out << " Name: \"" << name << "\"";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
Metadata::Metadata()
|
||||
: mdVersion(UINT8_MAX), mdRevision(UINT8_MAX),
|
||||
language((AMDGPU::RuntimeMD::Language) UINT8_MAX), languageVersion(UINT16_MAX),
|
||||
hasRequiredWorkgroupSize(false),
|
||||
hasWorkgroupSizeHint(false),
|
||||
hasVectorTypeHint(false),
|
||||
hasKernelIndex(false),
|
||||
hasMinWavesPerSIMD(false), hasMaxWavesPerSIMD(false),
|
||||
hasFlatWorkgroupSizeLimits(false),
|
||||
hasMaxWorkgroupSize(false),
|
||||
isNoPartialWorkgroups(false)
|
||||
{}
|
||||
|
||||
void Metadata::SetCommon(uint8_t mdVersion, uint8_t mdRevision,
|
||||
AMDGPU::RuntimeMD::Language language, uint16_t languageVersion) {
|
||||
this->mdVersion = mdVersion;
|
||||
this->mdRevision = mdRevision;
|
||||
this->language = language;
|
||||
this->languageVersion = languageVersion;
|
||||
}
|
||||
|
||||
const KernelArg::Metadata& Metadata::GetKernelArgMetadata(size_t index) const {
|
||||
assert((index < args.size()) && "kernel argument index too big");
|
||||
return args[index];
|
||||
}
|
||||
|
||||
bool Metadata::ReadValue(std::istream& in, AMDGPU::RuntimeMD::Key key) {
|
||||
using namespace AMDGPU::RuntimeMD;
|
||||
|
||||
KernelArg::Metadata* arg = args.empty() ? nullptr : &args.back();
|
||||
|
||||
switch (key) {
|
||||
case KeyKernelName:
|
||||
hasName = true;
|
||||
return Read(in, name);
|
||||
case KeyArgBegin:
|
||||
args.resize(args.size() + 1);
|
||||
break;
|
||||
case KeyArgEnd:
|
||||
// Verified in Program::Metadata::Read.
|
||||
break;
|
||||
case KeyArgSize:
|
||||
case KeyArgAlign:
|
||||
case KeyArgTypeName:
|
||||
case KeyArgName:
|
||||
case KeyArgKind:
|
||||
case KeyArgValueType:
|
||||
case KeyArgPointeeAlign:
|
||||
case KeyArgAddrQual:
|
||||
case KeyArgAccQual:
|
||||
case KeyArgIsConst:
|
||||
case KeyArgIsRestrict:
|
||||
case KeyArgIsVolatile:
|
||||
case KeyArgIsPipe:
|
||||
if (!arg) { return false; }
|
||||
if (!arg->ReadValue(in, key)) { return false; }
|
||||
break;
|
||||
case KeyReqdWorkGroupSize:
|
||||
hasRequiredWorkgroupSize = true;
|
||||
return Read3(in, requiredWorkgroupSize);
|
||||
case KeyWorkGroupSizeHint:
|
||||
hasWorkgroupSizeHint = true;
|
||||
return Read3(in, workgroupSizeHint);
|
||||
case KeyVecTypeHint:
|
||||
hasVectorTypeHint = true;
|
||||
return Read(in, vectorTypeHint);
|
||||
case KeyKernelIndex:
|
||||
hasKernelIndex = true;
|
||||
return Read(in, kernelIndex);
|
||||
case KeyMinWavesPerSIMD:
|
||||
hasMinWavesPerSIMD = true;
|
||||
return Read(in, minWavesPerSimd);
|
||||
case KeyMaxWavesPerSIMD:
|
||||
hasMaxWavesPerSIMD = true;
|
||||
return Read(in, maxWavesPerSimd);
|
||||
case KeyFlatWorkGroupSizeLimits:
|
||||
hasFlatWorkgroupSizeLimits = true;
|
||||
return
|
||||
Read(in, minFlatWorkgroupSize) &&
|
||||
Read(in, maxFlatWorkgroupSize);
|
||||
case KeyMaxWorkGroupSize:
|
||||
hasMaxWorkgroupSize = true;
|
||||
return Read3(in, maxWorkgroupSize);
|
||||
case KeyNoPartialWorkGroups:
|
||||
isNoPartialWorkgroups = true;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char* LanguageToString(AMDGPU::RuntimeMD::Language language) {
|
||||
using namespace AMDGPU::RuntimeMD;
|
||||
switch (language) {
|
||||
case OpenCL_C: return "OpenCL C";
|
||||
case HCC: return "HCC";
|
||||
case OpenMP: return "OpenMP";
|
||||
case OpenCL_CPP: return "OpenCL C++";
|
||||
default: return "<Unknown language>";
|
||||
}
|
||||
}
|
||||
|
||||
void Metadata::Print(std::ostream& out) {
|
||||
using namespace metadata_output;
|
||||
|
||||
out << " Kernel";
|
||||
if (HasName()) {
|
||||
out << " " << name;
|
||||
}
|
||||
out <<
|
||||
" (" << LanguageToString(language) << ' ' << (int) languageVersion <<
|
||||
"), metadata " << (int) mdVersion << '.' << (int) mdRevision << std::endl;
|
||||
if (hasRequiredWorkgroupSize) {
|
||||
out << " Required workgroup size: " << dim3(requiredWorkgroupSize) << std::endl;
|
||||
}
|
||||
if (hasWorkgroupSizeHint) {
|
||||
out << " Workgroup size hint: " << dim3(workgroupSizeHint) << std::endl;
|
||||
}
|
||||
if (hasVectorTypeHint) {
|
||||
out << " Vector type hint: " << vectorTypeHint << std::endl;
|
||||
}
|
||||
if (hasKernelIndex) {
|
||||
out << " Kernel iIndex: " << kernelIndex << std::endl;
|
||||
}
|
||||
if (hasMinWavesPerSIMD) {
|
||||
out << " Min waves per SIMD: " << minWavesPerSimd << std::endl;
|
||||
}
|
||||
if (hasMaxWavesPerSIMD) {
|
||||
out << " Max waves per SIMD: " << maxWavesPerSimd << std::endl;
|
||||
}
|
||||
if (hasFlatWorkgroupSizeLimits) {
|
||||
out << " Min flat workgroup size: " << minFlatWorkgroupSize << std::endl;
|
||||
out << " Max flat workgroup size: " << maxFlatWorkgroupSize << std::endl;
|
||||
}
|
||||
if (isNoPartialWorkgroups) {
|
||||
out << " No partial workgroups" << std::endl;
|
||||
}
|
||||
out << " Arguments" << std::endl;
|
||||
for (uint32_t i = 0; i < args.size(); ++i) {
|
||||
out << " " << i << ": ";
|
||||
args[i].Print(out);
|
||||
out << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Program {
|
||||
bool Metadata::ReadFrom(std::istream& in) {
|
||||
using namespace AMDGPU::RuntimeMD;
|
||||
Kernel::Metadata* kernel = nullptr;
|
||||
bool arg = false;
|
||||
uint8_t mdVersion = UINT8_MAX, mdRevision = UINT8_MAX;
|
||||
Language language = (Language) UINT8_MAX; uint16_t languageVersion = UINT16_MAX;
|
||||
while (in.tellg() != (std::streampos) -1 && !in.eof()) {
|
||||
Key key;
|
||||
if (!Read(in, key)) {
|
||||
if (in.eof()) { break; }
|
||||
return false;
|
||||
}
|
||||
switch (key) {
|
||||
case KeyNull: break; // Ignore
|
||||
case KeyMDVersion:
|
||||
if (!Read(in, mdRevision) ||
|
||||
!Read(in, mdVersion)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case KeyLanguage:
|
||||
if (!Read(in, language)) { return false; }
|
||||
break;
|
||||
case KeyLanguageVersion:
|
||||
if (!Read(in, languageVersion)) { return false; }
|
||||
break;
|
||||
case KeyKernelBegin:
|
||||
if (kernel) { return false; }
|
||||
kernels.resize(kernels.size() + 1);
|
||||
kernel = &kernels.back();
|
||||
kernel->SetCommon(mdVersion, mdRevision, language, languageVersion);
|
||||
break;
|
||||
case KeyKernelEnd:
|
||||
if (!kernel) { return false; }
|
||||
kernel = nullptr;
|
||||
break;
|
||||
case KeyArgBegin:
|
||||
if (!kernel || arg) { return false; }
|
||||
arg = true;
|
||||
if (!kernel->ReadValue(in, key)) { return false; }
|
||||
break;
|
||||
case KeyArgEnd:
|
||||
if (!kernel || !arg) { return false; }
|
||||
arg = false;
|
||||
break;
|
||||
case KeyPrintfInfo: {
|
||||
std::string formatString;
|
||||
if (!Read(in, formatString)) { return false; }
|
||||
printfInfo.push_back(formatString);
|
||||
break;
|
||||
}
|
||||
case KeyKernelName:
|
||||
case KeyArgSize:
|
||||
case KeyArgAlign:
|
||||
case KeyArgTypeName:
|
||||
case KeyArgName:
|
||||
case KeyArgKind:
|
||||
case KeyArgValueType:
|
||||
case KeyArgPointeeAlign:
|
||||
case KeyArgAddrQual:
|
||||
case KeyArgAccQual:
|
||||
case KeyArgIsConst:
|
||||
case KeyArgIsRestrict:
|
||||
case KeyArgIsVolatile:
|
||||
case KeyArgIsPipe:
|
||||
case KeyReqdWorkGroupSize:
|
||||
case KeyWorkGroupSizeHint:
|
||||
case KeyVecTypeHint:
|
||||
case KeyKernelIndex:
|
||||
case KeyMinWavesPerSIMD:
|
||||
case KeyMaxWavesPerSIMD:
|
||||
case KeyFlatWorkGroupSizeLimits:
|
||||
case KeyMaxWorkGroupSize:
|
||||
case KeyNoPartialWorkGroups:
|
||||
if (!kernel) { return false; }
|
||||
if (!kernel->ReadValue(in, key)) { return false; }
|
||||
break;
|
||||
default:
|
||||
//out << "Unsupported metadata key: " << key << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const Kernel::Metadata& Metadata::GetKernelMetadata(size_t index) const {
|
||||
assert(kernels.size() && "kernel metadata not found");
|
||||
assert((index < kernels.size()) && "kernel index too big");
|
||||
|
||||
return kernels[index];
|
||||
}
|
||||
|
||||
size_t Metadata::KernelIndexByName(const std::string& name) const {
|
||||
assert(kernels.size() && "kernel metadata not found");
|
||||
|
||||
size_t idx = 0;
|
||||
for (auto kernel : kernels) {
|
||||
if (kernel.Name().compare(name) == 0) { return idx; }
|
||||
idx++;
|
||||
}
|
||||
return kernels.max_size();
|
||||
}
|
||||
|
||||
bool Metadata::ReadFrom(const void* buffer, size_t size) {
|
||||
std::istringstream is(std::string(static_cast<const char*>(buffer), size));
|
||||
if (!ReadFrom(is)) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
void Metadata::Print(std::ostream& out) {
|
||||
out << "AMDGPU runtime metadata (" << kernels.size() << " kernel";
|
||||
if (kernels.size() > 1) out << "s";
|
||||
if (printfInfo.size() > 0) {
|
||||
out << ", " << printfInfo.size() << " printf info string";
|
||||
if (printfInfo.size() > 1) out << "s";
|
||||
}
|
||||
out << "):" << std::endl;
|
||||
for (Kernel::Metadata& kernel : kernels) {
|
||||
kernel.Print(out);
|
||||
}
|
||||
for (auto str : printfInfo) {
|
||||
out << " PrintfInfo \"" << str << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace metadata_output {
|
||||
std::ostream& operator<<(std::ostream& out, const dim3& d) {
|
||||
out << "(" << d.data[0] << ", " << d.data[1] << ", " << d.data[2] << ")";
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The University of Illinois/NCSA
|
||||
// Open Source License (NCSA)
|
||||
//
|
||||
// Copyright (c) 2014-2016, Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Developed by:
|
||||
//
|
||||
// AMD Research and AMD HSA Software Development
|
||||
//
|
||||
// Advanced Micro Devices, Inc.
|
||||
//
|
||||
// www.amd.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal with the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimers.
|
||||
// - Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimers in
|
||||
// the documentation and/or other materials provided with the distribution.
|
||||
// - Neither the names of Advanced Micro Devices, Inc,
|
||||
// nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this Software without specific prior written
|
||||
// permission.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS WITH THE SOFTWARE.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef AMDGPU_METADATA_HPP_
|
||||
#define AMDGPU_METADATA_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
#undef None
|
||||
#include "AMDGPURuntimeMetadata.h"
|
||||
|
||||
namespace amd {
|
||||
namespace hsa {
|
||||
namespace code {
|
||||
|
||||
namespace KernelArg {
|
||||
class Metadata {
|
||||
private:
|
||||
uint32_t size;
|
||||
uint32_t align;
|
||||
uint32_t pointeeAlign;
|
||||
std::string typeName;
|
||||
std::string name;
|
||||
AMDGPU::RuntimeMD::KernelArg::Kind kind;
|
||||
AMDGPU::RuntimeMD::KernelArg::ValueType valueType;
|
||||
uint8_t addrQual;
|
||||
AMDGPU::RuntimeMD::KernelArg::AccessQualifer accQual;
|
||||
bool isConst, isRestrict, isVolatile, isPipe;
|
||||
|
||||
public:
|
||||
Metadata();
|
||||
uint32_t Size() const { return size; }
|
||||
uint32_t Align() const { return align; }
|
||||
uint32_t PointeeAlign() const { return pointeeAlign; }
|
||||
const std::string& TypeName() const { return typeName; }
|
||||
const std::string& Name() const { return name; }
|
||||
AMDGPU::RuntimeMD::KernelArg::Kind Kind() const { return kind; }
|
||||
AMDGPU::RuntimeMD::KernelArg::ValueType ValueType() const { return valueType; }
|
||||
uint8_t AddrQual() const { return addrQual; }
|
||||
AMDGPU::RuntimeMD::KernelArg::AccessQualifer AccQual() const { return accQual; }
|
||||
bool IsConst() const { return isConst; }
|
||||
bool IsRestrict() const { return isRestrict; }
|
||||
bool IsVolatile() const { return isVolatile; }
|
||||
bool IsPipe() const { return isPipe; }
|
||||
|
||||
bool ReadValue(std::istream& in, AMDGPU::RuntimeMD::Key key);
|
||||
void Print(std::ostream& out);
|
||||
};
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
class Metadata {
|
||||
private:
|
||||
uint8_t mdVersion, mdRevision;
|
||||
AMDGPU::RuntimeMD::Language language;
|
||||
uint16_t languageVersion;
|
||||
std::vector<KernelArg::Metadata> args;
|
||||
|
||||
unsigned hasName : 1;
|
||||
unsigned hasRequiredWorkgroupSize : 1;
|
||||
unsigned hasWorkgroupSizeHint : 1;
|
||||
unsigned hasVectorTypeHint : 1;
|
||||
unsigned hasKernelIndex : 1;
|
||||
unsigned hasMinWavesPerSIMD : 1, hasMaxWavesPerSIMD : 1;
|
||||
unsigned hasFlatWorkgroupSizeLimits : 1;
|
||||
unsigned hasMaxWorkgroupSize : 1;
|
||||
unsigned isNoPartialWorkgroups : 1;
|
||||
|
||||
std::string name;
|
||||
uint32_t requiredWorkgroupSize[3];
|
||||
uint32_t workgroupSizeHint[3];
|
||||
std::string vectorTypeHint;
|
||||
|
||||
uint32_t kernelIndex;
|
||||
uint32_t numSgprs, numVgprs;
|
||||
uint32_t minWavesPerSimd, maxWavesPerSimd;
|
||||
uint32_t minFlatWorkgroupSize, maxFlatWorkgroupSize;
|
||||
uint32_t maxWorkgroupSize[3];
|
||||
|
||||
public:
|
||||
Metadata();
|
||||
|
||||
bool HasName() const { return hasName; }
|
||||
bool HasRequiredWorkgroupSize() const { return hasRequiredWorkgroupSize; }
|
||||
bool HasWorkgroupSizeHint() const { return hasWorkgroupSizeHint; }
|
||||
bool HasVecTypeHint() const { return hasVectorTypeHint; }
|
||||
bool HasKernelIndex() const { return hasKernelIndex; }
|
||||
bool HasMinWavesPerSIMD() const { return hasMinWavesPerSIMD; }
|
||||
bool HasMaxWavesPerSIMD() const { return hasMaxWavesPerSIMD; }
|
||||
bool HasFlatWorkgroupSizeLimits() const { return hasFlatWorkgroupSizeLimits; }
|
||||
bool HasMaxWorkgroupSize() const { return hasMaxWorkgroupSize; }
|
||||
|
||||
size_t KernelArgCount() const { return args.size(); }
|
||||
const KernelArg::Metadata& GetKernelArgMetadata(size_t index) const;
|
||||
|
||||
const std::string& Name() const { return name; }
|
||||
const uint32_t* RequiredWorkgroupSize() const { return hasRequiredWorkgroupSize ? requiredWorkgroupSize : nullptr; }
|
||||
const uint32_t* WorkgroupSizeHint() const { return hasWorkgroupSizeHint ? workgroupSizeHint : nullptr; }
|
||||
const std::string& VecTypeHint() const { return vectorTypeHint; }
|
||||
uint32_t KernelIndex() const { return hasKernelIndex ? kernelIndex : UINT32_MAX; }
|
||||
uint32_t MinWavesPerSIMD() const { return hasMinWavesPerSIMD ? minWavesPerSimd : UINT32_MAX; }
|
||||
uint32_t MaxWavesPerSIMD() const { return hasMaxWavesPerSIMD ? maxWavesPerSimd : UINT32_MAX; }
|
||||
uint32_t MinFlatWorkgroupSize() const { return hasFlatWorkgroupSizeLimits ? minFlatWorkgroupSize : UINT32_MAX; }
|
||||
uint32_t MaxFlatWorkgroupSize() const { return hasFlatWorkgroupSizeLimits ? maxFlatWorkgroupSize : UINT32_MAX; }
|
||||
const uint32_t* MaxWorkgroupSize() const { return hasMaxWorkgroupSize ? maxWorkgroupSize : 0; }
|
||||
bool IsNoPartialWorkgroups() const { return isNoPartialWorkgroups; }
|
||||
|
||||
void SetCommon(uint8_t mdVersion, uint8_t mdRevision, AMDGPU::RuntimeMD::Language language, uint16_t languageVersion);
|
||||
bool ReadValue(std::istream& in, AMDGPU::RuntimeMD::Key key);
|
||||
void Print(std::ostream& out);
|
||||
};
|
||||
}
|
||||
|
||||
namespace Program {
|
||||
class Metadata {
|
||||
private:
|
||||
uint16_t version;
|
||||
std::vector<Kernel::Metadata> kernels;
|
||||
std::vector<std::string> printfInfo;
|
||||
|
||||
public:
|
||||
size_t KernelCount() const { return kernels.size(); }
|
||||
const Kernel::Metadata& GetKernelMetadata(size_t index) const;
|
||||
size_t KernelIndexByName(const std::string& name) const;
|
||||
const std::vector<std::string>& PrintfInfo() const { return printfInfo; }
|
||||
|
||||
bool ReadFrom(std::istream& in);
|
||||
bool ReadFrom(const void* buffer, size_t size);
|
||||
void Print(std::ostream& out);
|
||||
};
|
||||
}
|
||||
|
||||
namespace metadata_output {
|
||||
|
||||
struct dim3 {
|
||||
uint32_t* data;
|
||||
|
||||
dim3(uint32_t* data_)
|
||||
: data(data_) {}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const dim3& d);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AMDGPU_METADATA_HPP_
|
||||
@@ -72,6 +72,7 @@ public:
|
||||
const amd::options::NoArgOption* DumpExec() const { return &dump_exec; }
|
||||
const amd::options::NoArgOption* DumpAll() const { return &dump_all; }
|
||||
const amd::options::ValueOption<std::string>* DumpDir() const { return &dump_dir; }
|
||||
const amd::options::PrefixOption* Substitute() const { return &substitute; }
|
||||
|
||||
bool ParseOptions(const std::string& options);
|
||||
void Reset();
|
||||
@@ -90,6 +91,7 @@ private:
|
||||
amd::options::NoArgOption dump_exec;
|
||||
amd::options::NoArgOption dump_all;
|
||||
amd::options::ValueOption<std::string> dump_dir;
|
||||
amd::options::PrefixOption substitute;
|
||||
amd::options::OptionParser option_parser;
|
||||
};
|
||||
|
||||
@@ -100,6 +102,7 @@ LoaderOptions::LoaderOptions(std::ostream& error) :
|
||||
dump_exec("dump-exec", "Dump executable to text file"),
|
||||
dump_all("dump-all", "Dump all finalizer input and output (as above)"),
|
||||
dump_dir("dump-dir", "Dump directory"),
|
||||
substitute("substitute", "Substitute code object with given index or index range on loading from file"),
|
||||
option_parser(false, error)
|
||||
{
|
||||
option_parser.AddOption(&help);
|
||||
@@ -108,17 +111,21 @@ LoaderOptions::LoaderOptions(std::ostream& error) :
|
||||
option_parser.AddOption(&dump_exec);
|
||||
option_parser.AddOption(&dump_all);
|
||||
option_parser.AddOption(&dump_dir);
|
||||
option_parser.AddOption(&substitute);
|
||||
}
|
||||
|
||||
bool LoaderOptions::ParseOptions(const std::string& options) {
|
||||
bool LoaderOptions::ParseOptions(const std::string& options)
|
||||
{
|
||||
return option_parser.ParseOptions(options.c_str());
|
||||
}
|
||||
|
||||
void LoaderOptions::Reset() {
|
||||
void LoaderOptions::Reset()
|
||||
{
|
||||
option_parser.Reset();
|
||||
}
|
||||
|
||||
void LoaderOptions::PrintHelp(std::ostream& out) const {
|
||||
void LoaderOptions::PrintHelp(std::ostream& out) const
|
||||
{
|
||||
option_parser.PrintHelp(out);
|
||||
}
|
||||
|
||||
@@ -232,6 +239,11 @@ uint64_t AmdHsaCodeLoader::FindHostAddress(uint64_t device_address)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AmdHsaCodeLoader::PrintHelp(std::ostream& out)
|
||||
{
|
||||
LoaderOptions().PrintHelp(out);
|
||||
}
|
||||
|
||||
void AmdHsaCodeLoader::EnableReadOnlyMode()
|
||||
{
|
||||
rw_lock_.ReaderLock();
|
||||
@@ -306,62 +318,21 @@ bool SymbolImpl::GetInfo(hsa_symbol_info32_t symbol_info, void *value) {
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_NAME_LENGTH: {
|
||||
std::string matter = "";
|
||||
|
||||
if (linkage == HSA_SYMBOL_LINKAGE_PROGRAM) {
|
||||
assert(name.rfind(":") == std::string::npos);
|
||||
matter = name;
|
||||
} else {
|
||||
assert(name.rfind(":") != std::string::npos);
|
||||
matter = name.substr(name.rfind(":") + 1);
|
||||
}
|
||||
|
||||
*((uint32_t*)value) = matter.size() + 1;
|
||||
*((uint32_t*)value) = symbol_name.size();
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_NAME: {
|
||||
std::string matter = "";
|
||||
|
||||
if (linkage == HSA_SYMBOL_LINKAGE_PROGRAM) {
|
||||
assert(name.rfind(":") == std::string::npos);
|
||||
matter = name;
|
||||
} else {
|
||||
assert(name.rfind(":") != std::string::npos);
|
||||
matter = name.substr(name.rfind(":") + 1);
|
||||
}
|
||||
|
||||
memset(value, 0x0, matter.size() + 1);
|
||||
memcpy(value, matter.c_str(), matter.size());
|
||||
memset(value, 0x0, symbol_name.size());
|
||||
memcpy(value, symbol_name.c_str(), symbol_name.size());
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_MODULE_NAME_LENGTH: {
|
||||
std::string matter = "";
|
||||
|
||||
if (linkage == HSA_SYMBOL_LINKAGE_PROGRAM) {
|
||||
assert(name.find(":") == std::string::npos);
|
||||
*((uint32_t*)value) = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(name.find(":") != std::string::npos);
|
||||
matter = name.substr(0, name.find(":"));
|
||||
|
||||
*((uint32_t*)value) = matter.size() + 1;
|
||||
*((uint32_t*)value) = module_name.size();
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_MODULE_NAME: {
|
||||
std::string matter = "";
|
||||
|
||||
if (linkage == HSA_SYMBOL_LINKAGE_PROGRAM) {
|
||||
assert(name.find(":") == std::string::npos);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(name.find(":") != std::string::npos);
|
||||
matter = name.substr(0, name.find(":"));
|
||||
|
||||
memset(value, 0x0, matter.size() + 1);
|
||||
memcpy(value, matter.c_str(), matter.size());
|
||||
memset(value, 0x0, module_name.size());
|
||||
memcpy(value, module_name.c_str(), module_name.size());
|
||||
break;
|
||||
}
|
||||
case HSA_CODE_SYMBOL_INFO_LINKAGE: {
|
||||
@@ -698,6 +669,8 @@ hsa_status_t ExecutableImpl::DefineProgramExternalVariable(
|
||||
program_symbols_.insert(
|
||||
std::make_pair(std::string(name),
|
||||
new VariableSymbol(true,
|
||||
"", // Only program linkage symbols can be
|
||||
// defined.
|
||||
std::string(name),
|
||||
HSA_SYMBOL_LINKAGE_PROGRAM,
|
||||
true,
|
||||
@@ -732,6 +705,8 @@ hsa_status_t ExecutableImpl::DefineAgentExternalVariable(
|
||||
auto insert_status = agent_symbols_.insert(
|
||||
std::make_pair(std::make_pair(std::string(name), agent),
|
||||
new VariableSymbol(true,
|
||||
"", // Only program linkage symbols can be
|
||||
// defined.
|
||||
std::string(name),
|
||||
HSA_SYMBOL_LINKAGE_PROGRAM,
|
||||
true,
|
||||
@@ -997,7 +972,7 @@ hsa_status_t ExecutableImpl::GetInfo(
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint32_t NextLoaderDumpNum()
|
||||
static uint32_t NextCodeObjectNum()
|
||||
{
|
||||
static std::atomic_uint_fast32_t dumpN(1);
|
||||
return dumpN++;
|
||||
@@ -1034,27 +1009,62 @@ hsa_status_t ExecutableImpl::LoadCodeObject(
|
||||
return HSA_STATUS_ERROR;
|
||||
}
|
||||
|
||||
code.reset(new code::AmdHsaCode());
|
||||
typedef std::tuple<uint32_t, uint32_t, std::string> Substitute;
|
||||
std::vector<Substitute> substitutes;
|
||||
|
||||
if (!code->InitAsHandle(code_object)) {
|
||||
return HSA_STATUS_ERROR_INVALID_CODE_OBJECT;
|
||||
for (const std::string& s : loaderOptions.Substitute()->values()) {
|
||||
std::string::size_type vi = s.find('=');
|
||||
if (vi == std::string::npos) { return HSA_STATUS_ERROR; }
|
||||
std::string value = s.substr(vi + 1);
|
||||
std::string range = s.substr(0, vi);
|
||||
std::string::size_type mi = range.find('-');
|
||||
uint32_t n1 = UINT32_MAX, n2 = UINT32_MAX;
|
||||
if (mi != std::string::npos) {
|
||||
std::string s1, s2;
|
||||
s1 = range.substr(0, mi - 1);
|
||||
s2 = range.substr(mi + 1);
|
||||
std::istringstream is1(s1); is1 >> n1;
|
||||
std::istringstream is2(s2); is2 >> n2;
|
||||
}
|
||||
else {
|
||||
std::istringstream is(range); is >> n1;
|
||||
n2 = n1;
|
||||
}
|
||||
substitutes.push_back(std::make_tuple(n1, n2, value));
|
||||
}
|
||||
|
||||
uint32_t dumpNum = 0;
|
||||
if (loaderOptions.DumpAll()->is_set() ||
|
||||
loaderOptions.DumpExec()->is_set() ||
|
||||
loaderOptions.DumpCode()->is_set() ||
|
||||
loaderOptions.DumpIsa()->is_set()) {
|
||||
dumpNum = NextLoaderDumpNum();
|
||||
uint32_t codeNum = NextCodeObjectNum();
|
||||
|
||||
code.reset(new code::AmdHsaCode());
|
||||
|
||||
std::string substituteFileName;
|
||||
for (const Substitute& ss : substitutes) {
|
||||
if (codeNum >= std::get<0>(ss) && codeNum <= std::get<1>(ss)) {
|
||||
substituteFileName = std::get<2>(ss);
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::vector<char> buffer;
|
||||
if (substituteFileName.empty()) {
|
||||
if (!code->InitAsHandle(code_object)) {
|
||||
return HSA_STATUS_ERROR_INVALID_CODE_OBJECT;
|
||||
}
|
||||
} else {
|
||||
if (!ReadFileIntoBuffer(substituteFileName, buffer)) {
|
||||
return HSA_STATUS_ERROR_INVALID_CODE_OBJECT;
|
||||
}
|
||||
if (!code->InitAsBuffer(&buffer[0], buffer.size())) {
|
||||
return HSA_STATUS_ERROR_INVALID_CODE_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
if (loaderOptions.DumpAll()->is_set() || loaderOptions.DumpCode()->is_set()) {
|
||||
if (!code->SaveToFile(amd::hsa::DumpFileName(loaderOptions.DumpDir()->value(), LOADER_DUMP_PREFIX, "hsaco", dumpNum))) {
|
||||
if (!code->SaveToFile(amd::hsa::DumpFileName(loaderOptions.DumpDir()->value(), LOADER_DUMP_PREFIX, "hsaco", codeNum))) {
|
||||
// Ignore error.
|
||||
}
|
||||
}
|
||||
if (loaderOptions.DumpAll()->is_set() || loaderOptions.DumpIsa()->is_set()) {
|
||||
if (!code->PrintToFile(amd::hsa::DumpFileName(loaderOptions.DumpDir()->value(), LOADER_DUMP_PREFIX, "isa", dumpNum))) {
|
||||
if (!code->PrintToFile(amd::hsa::DumpFileName(loaderOptions.DumpDir()->value(), LOADER_DUMP_PREFIX, "isa", codeNum))) {
|
||||
// Ignore error.
|
||||
}
|
||||
}
|
||||
@@ -1105,7 +1115,7 @@ hsa_status_t ExecutableImpl::LoadCodeObject(
|
||||
code.reset();
|
||||
|
||||
if (loaderOptions.DumpAll()->is_set() || loaderOptions.DumpExec()->is_set()) {
|
||||
if (!PrintToFile(amd::hsa::DumpFileName(loaderOptions.DumpDir()->value(), LOADER_DUMP_PREFIX, "exec", dumpNum))) {
|
||||
if (!PrintToFile(amd::hsa::DumpFileName(loaderOptions.DumpDir()->value(), LOADER_DUMP_PREFIX, "exec", codeNum))) {
|
||||
// Ignore error.
|
||||
}
|
||||
}
|
||||
@@ -1240,7 +1250,8 @@ hsa_status_t ExecutableImpl::LoadDefinitionSymbol(hsa_agent_t agent,
|
||||
SymbolImpl *symbol = nullptr;
|
||||
if (sym->IsVariableSymbol()) {
|
||||
symbol = new VariableSymbol(true,
|
||||
sym->Name(),
|
||||
sym->GetModuleName(),
|
||||
sym->GetSymbolName(),
|
||||
sym->Linkage(),
|
||||
true, // sym->IsDefinition()
|
||||
sym->Allocation(),
|
||||
@@ -1273,7 +1284,8 @@ hsa_status_t ExecutableImpl::LoadDefinitionSymbol(hsa_agent_t agent,
|
||||
size = sym->GetSection()->size() - sym->SectionOffset();
|
||||
}
|
||||
KernelSymbol *kernel_symbol = new KernelSymbol(true,
|
||||
sym->Name(),
|
||||
sym->GetModuleName(),
|
||||
sym->GetSymbolName(),
|
||||
sym->Linkage(),
|
||||
true, // sym->IsDefinition()
|
||||
kernarg_segment_size,
|
||||
@@ -1286,7 +1298,7 @@ hsa_status_t ExecutableImpl::LoadDefinitionSymbol(hsa_agent_t agent,
|
||||
address);
|
||||
kernel_symbol->debug_info.elf_raw = code->ElfData();
|
||||
kernel_symbol->debug_info.elf_size = code->ElfSize();
|
||||
kernel_symbol->debug_info.kernel_name = kernel_symbol->name.c_str();
|
||||
kernel_symbol->debug_info.kernel_name = kernel_symbol->full_name.c_str();
|
||||
kernel_symbol->debug_info.owning_segment = (void*)SymbolSegment(agent, sym)->Address(sym->GetSection()->addr());
|
||||
symbol = kernel_symbol;
|
||||
|
||||
|
||||
@@ -88,7 +88,8 @@ public:
|
||||
|
||||
bool is_loaded;
|
||||
hsa_symbol_kind_t kind;
|
||||
std::string name;
|
||||
std::string module_name;
|
||||
std::string symbol_name;
|
||||
hsa_symbol_linkage_t linkage;
|
||||
bool is_definition;
|
||||
uint64_t address;
|
||||
@@ -101,18 +102,20 @@ public:
|
||||
protected:
|
||||
SymbolImpl(const bool &_is_loaded,
|
||||
const hsa_symbol_kind_t &_kind,
|
||||
const std::string &_name,
|
||||
const std::string &_module_name,
|
||||
const std::string &_symbol_name,
|
||||
const hsa_symbol_linkage_t &_linkage,
|
||||
const bool &_is_definition,
|
||||
const uint64_t &_address = 0)
|
||||
: is_loaded(_is_loaded)
|
||||
, kind(_kind)
|
||||
, name(_name)
|
||||
, module_name(_module_name)
|
||||
, symbol_name(_symbol_name)
|
||||
, linkage(_linkage)
|
||||
, is_definition(_is_definition)
|
||||
, address(_address) {}
|
||||
|
||||
virtual bool GetInfo(hsa_symbol_info32_t symbol_info, void *value) override;
|
||||
virtual bool GetInfo(hsa_symbol_info32_t symbol_info, void *value);
|
||||
|
||||
private:
|
||||
SymbolImpl(const SymbolImpl &s);
|
||||
@@ -126,7 +129,8 @@ private:
|
||||
class KernelSymbol final: public SymbolImpl {
|
||||
public:
|
||||
KernelSymbol(const bool &_is_loaded,
|
||||
const std::string &_name,
|
||||
const std::string &_module_name,
|
||||
const std::string &_symbol_name,
|
||||
const hsa_symbol_linkage_t &_linkage,
|
||||
const bool &_is_definition,
|
||||
const uint32_t &_kernarg_segment_size,
|
||||
@@ -139,10 +143,12 @@ public:
|
||||
const uint64_t &_address = 0)
|
||||
: SymbolImpl(_is_loaded,
|
||||
HSA_SYMBOL_KIND_KERNEL,
|
||||
_name,
|
||||
_module_name,
|
||||
_symbol_name,
|
||||
_linkage,
|
||||
_is_definition,
|
||||
_address)
|
||||
, full_name(_module_name.empty() ? _symbol_name : _module_name + "::" + _symbol_name)
|
||||
, kernarg_segment_size(_kernarg_segment_size)
|
||||
, kernarg_segment_alignment(_kernarg_segment_alignment)
|
||||
, group_segment_size(_group_segment_size)
|
||||
@@ -155,6 +161,7 @@ public:
|
||||
|
||||
bool GetInfo(hsa_symbol_info32_t symbol_info, void *value);
|
||||
|
||||
std::string full_name;
|
||||
uint32_t kernarg_segment_size;
|
||||
uint32_t kernarg_segment_alignment;
|
||||
uint32_t group_segment_size;
|
||||
@@ -176,7 +183,8 @@ private:
|
||||
class VariableSymbol final: public SymbolImpl {
|
||||
public:
|
||||
VariableSymbol(const bool &_is_loaded,
|
||||
const std::string &_name,
|
||||
const std::string &_module_name,
|
||||
const std::string &_symbol_name,
|
||||
const hsa_symbol_linkage_t &_linkage,
|
||||
const bool &_is_definition,
|
||||
const hsa_variable_allocation_t &_allocation,
|
||||
@@ -188,7 +196,8 @@ public:
|
||||
const uint64_t &_address = 0)
|
||||
: SymbolImpl(_is_loaded,
|
||||
HSA_SYMBOL_KIND_VARIABLE,
|
||||
_name,
|
||||
_module_name,
|
||||
_symbol_name,
|
||||
_linkage,
|
||||
_is_definition,
|
||||
_address)
|
||||
@@ -526,6 +535,8 @@ public:
|
||||
|
||||
uint64_t FindHostAddress(uint64_t device_address) override;
|
||||
|
||||
void PrintHelp(std::ostream& out) override;
|
||||
|
||||
void EnableReadOnlyMode();
|
||||
void DisableReadOnlyMode();
|
||||
};
|
||||
|
||||
Verwijs in nieuw issue
Block a user