Skip to content

Commit a83c28b

Browse files
aarongreigKornevNikita
authored andcommitted
Report spec constant types when they are queried with --spec-const-info (#1758)
Also allow binary float spec constant input by passing a hex value with 0x prefix. Original commit: KhronosGroup/SPIRV-LLVM-Translator@b0c2bb1
1 parent 84a6b41 commit a83c28b

File tree

5 files changed

+94
-35
lines changed

5 files changed

+94
-35
lines changed

llvm-spirv/include/LLVMSPIRVLib.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,11 @@ bool readSpirv(LLVMContext &C, const SPIRV::TranslatorOpts &Opts,
132132
/// \brief Partially load SPIR-V from the stream and decode only instructions
133133
/// needed to get information about specialization constants.
134134
/// \returns true if succeeds.
135-
using SpecConstInfoTy = std::pair<uint32_t, uint32_t>;
135+
struct SpecConstInfoTy {
136+
uint32_t ID;
137+
uint32_t Size;
138+
std::string Type;
139+
};
136140
bool getSpecConstInfo(std::istream &IS,
137141
std::vector<SpecConstInfoTy> &SpecConstInfo);
138142

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

+36-1
Original file line numberDiff line numberDiff line change
@@ -4565,7 +4565,42 @@ bool llvm::getSpecConstInfo(std::istream &IS,
45654565
if (C->hasDecorate(DecorationSpecId, 0, &SpecConstIdLiteral)) {
45664566
SPIRVType *Ty = C->getType();
45674567
uint32_t SpecConstSize = Ty->isTypeBool() ? 1 : Ty->getBitWidth() / 8;
4568-
SpecConstInfo.emplace_back(SpecConstIdLiteral, SpecConstSize);
4568+
std::string TypeString = "";
4569+
if (Ty->isTypeBool()) {
4570+
TypeString = "i1";
4571+
} else if (Ty->isTypeInt()) {
4572+
switch (SpecConstSize) {
4573+
case 1:
4574+
TypeString = "i8";
4575+
break;
4576+
case 2:
4577+
TypeString = "i16";
4578+
break;
4579+
case 4:
4580+
TypeString = "i32";
4581+
break;
4582+
case 8:
4583+
TypeString = "i64";
4584+
break;
4585+
}
4586+
} else if (Ty->isTypeFloat()) {
4587+
switch (SpecConstSize) {
4588+
case 2:
4589+
TypeString = "f16";
4590+
break;
4591+
case 4:
4592+
TypeString = "f32";
4593+
break;
4594+
case 8:
4595+
TypeString = "f64";
4596+
break;
4597+
}
4598+
}
4599+
if (TypeString == "")
4600+
return false;
4601+
4602+
SpecConstInfo.emplace_back(
4603+
SpecConstInfoTy({SpecConstIdLiteral, SpecConstSize, TypeString}));
45694604
}
45704605
break;
45714606
}

llvm-spirv/test/SpecConstants/OpSpecConstant.spvasm

+19-11
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33

44
; RUN: llvm-spirv -spec-const-info %t.spv | FileCheck %s --check-prefix=CHECK-INFO
55
; CHECK-INFO: Number of scalar specialization constants in the module = 11
6-
; CHECK-INFO: Spec const id = 101, size in bytes = 1
7-
; CHECK-INFO: Spec const id = 102, size in bytes = 2
8-
; CHECK-INFO: Spec const id = 103, size in bytes = 4
9-
; CHECK-INFO: Spec const id = 104, size in bytes = 8
10-
; CHECK-INFO: Spec const id = 105, size in bytes = 1
11-
; CHECK-INFO: Spec const id = 106, size in bytes = 1
12-
; CHECK-INFO: Spec const id = 107, size in bytes = 1
13-
; CHECK-INFO: Spec const id = 108, size in bytes = 2
14-
; CHECK-INFO: Spec const id = 109, size in bytes = 4
15-
; CHECK-INFO: Spec const id = 110, size in bytes = 8
16-
; CHECK-INFO: Spec const id = 111, size in bytes = 8
6+
; CHECK-INFO: Spec const id = 101, size in bytes = 1, type = i8
7+
; CHECK-INFO: Spec const id = 102, size in bytes = 2, type = i16
8+
; CHECK-INFO: Spec const id = 103, size in bytes = 4, type = i32
9+
; CHECK-INFO: Spec const id = 104, size in bytes = 8, type = i64
10+
; CHECK-INFO: Spec const id = 105, size in bytes = 1, type = i8
11+
; CHECK-INFO: Spec const id = 106, size in bytes = 1, type = i1
12+
; CHECK-INFO: Spec const id = 107, size in bytes = 1, type = i1
13+
; CHECK-INFO: Spec const id = 108, size in bytes = 2, type = f16
14+
; CHECK-INFO: Spec const id = 109, size in bytes = 4, type = f32
15+
; CHECK-INFO: Spec const id = 110, size in bytes = 8, type = f64
16+
; CHECK-INFO: Spec const id = 111, size in bytes = 8, type = f64
1717

1818
; Negative tests for the command line option.
1919
; RUN: not llvm-spirv -r -emit-opaque-pointers %t.spv -spec-const "1234" 2>&1 | FileCheck %s --check-prefix=CHECK-FORMAT
@@ -46,6 +46,9 @@
4646
; RUN: llvm-spirv -r -emit-opaque-pointers -o - %t.spv | llvm-dis | FileCheck %s --check-prefix=CHECK-DEFAULT
4747
; RUN: llvm-spirv -r -emit-opaque-pointers -spec-const "101:i8:42 102:i16:22 103:i32:33 104:i64:44 105:i8:0 106:i1:0 107:i1:1 108:f16:5.5 109:f32:6.6 110:f64:7.7 111:f64:8.8 101:i8:11" -o - %t.spv | llvm-dis | FileCheck %s --check-prefix=CHECK-SPEC
4848

49+
; RUN: llvm-spirv -r -emit-opaque-pointers -o - %t.spv | llvm-dis | FileCheck %s --check-prefix=CHECK-DEFAULT
50+
; RUN: llvm-spirv -r -emit-opaque-pointers -spec-const "108:f16:0x1234 109:f32:0x12345678 110:f64:0x12345678ABCDEF00" -o - %t.spv | llvm-dis | FileCheck %s --check-prefix=CHECK-HEX
51+
4952
; CHECK-DEFAULT: @bt = addrspace(2) constant i1 true, align 1
5053
; CHECK-DEFAULT: @bf = addrspace(2) constant i1 false, align 1
5154
; CHECK-DEFAULT: @c = addrspace(2) constant i8 97, align 1
@@ -68,6 +71,11 @@
6871
; CHECK-SPEC: @d = addrspace(2) constant double 7.700000e+00, align 8
6972
; CHECK-SPEC: @ss = addrspace(1) global %struct.S { i8 0, double 8.800000e+00 }, align 8
7073

74+
; CHECK-HEX: @h = addrspace(2) constant half 0xH1234, align 2
75+
; Float literals are represented as doubles, so 0x12345678 becomes the value below.
76+
; CHECK-HEX: @f = addrspace(2) constant float 0x3A468ACF00000000, align 4
77+
; CHECK-HEX: @d = addrspace(2) constant double 0x12345678ABCDEF00, align 8
78+
7179
; SPIR-V
7280
; Version: 1.0
7381
; Generator: Khronos LLVM/SPIR-V Translator; 14

llvm-spirv/test/lit.cfg.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050

5151
config.substitutions.append(('%PATH%', config.environment['PATH']))
5252

53-
tool_dirs = [config.llvm_tools_dir, config.llvm_spirv_dir]
53+
tool_dirs = [config.llvm_spirv_dir, config.llvm_tools_dir]
5454

5555
tools = ['llvm-as', 'llvm-dis', 'llvm-spirv', 'not']
5656
if not config.spirv_skip_debug_info_tests:

llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp

+33-21
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#include <map>
7676
#include <memory>
7777
#include <set>
78+
#include <sstream>
7879
#include <string>
7980

8081
#define DEBUG_TYPE "spirv"
@@ -190,6 +191,8 @@ static cl::opt<std::string> SpecConst(
190191
"SPIR-V module.\n"
191192
"The list of valid ids is available via -spec-const-info option.\n"
192193
"For duplicate ids the later one takes precedence.\n"
194+
"Float values may be represented in decimal or hexadecimal, hex "
195+
"values must be preceded by 0x.\n"
193196
"Supported types are: i1, i8, i16, i32, i64, f16, f32, f64.\n"),
194197
cl::value_desc("id1:type1:value1 id2:type2:value2 ..."));
195198

@@ -559,9 +562,9 @@ bool parseSpecConstOpt(llvm::StringRef SpecConstStr,
559562
<< "\" must be a 32-bit unsigned integer\n";
560563
return true;
561564
}
562-
auto It = std::find_if(
563-
SpecConstInfo.begin(), SpecConstInfo.end(),
564-
[=](SpecConstInfoTy Info) { return Info.first == SpecId; });
565+
auto It =
566+
std::find_if(SpecConstInfo.begin(), SpecConstInfo.end(),
567+
[=](SpecConstInfoTy Info) { return Info.ID == SpecId; });
565568
if (It == SpecConstInfo.end()) {
566569
errs() << "Error: CL_INVALID_SPEC_ID. \"" << Option << "\": There is no "
567570
<< "specialization constant with id = " << SpecId
@@ -579,11 +582,11 @@ bool parseSpecConstOpt(llvm::StringRef SpecConstStr,
579582
return true;
580583
}
581584
size_t Size = Width < 8 ? 1 : Width / 8;
582-
if (Size != It->second) {
585+
if (Size != It->Size) {
583586
errs() << "Error: CL_INVALID_VALUE. In \"" << Option << "\": Size of "
584587
<< "type i" << Width << " (" << Size << " bytes) "
585588
<< "does not match the size of the specialization constant "
586-
<< "in the module (" << It->second << " bytes)\n";
589+
<< "in the module (" << It->Size << " bytes)\n";
587590
return true;
588591
}
589592
APInt Value;
@@ -618,21 +621,29 @@ bool parseSpecConstOpt(llvm::StringRef SpecConstStr,
618621
return true;
619622
}
620623
APFloat Value(*FS);
621-
Expected<APFloat::opStatus> StatusOrErr =
622-
Value.convertFromString(Params[2], APFloat::rmNearestTiesToEven);
623-
if (!StatusOrErr) {
624-
return true;
625-
}
626-
// It's ok to have inexact conversion from decimal representation.
627-
APFloat::opStatus Status = *StatusOrErr;
628-
if (Status & ~APFloat::opInexact) {
629-
errs() << "Error: Invalid value for '-" << SpecConst.ArgStr
630-
<< "' option! In \"" << Option << "\": can't convert \""
631-
<< Params[2] << "\" to " << Width
632-
<< "-bit floating point number\n";
633-
return true;
624+
if (Params[2].find("0x") != StringRef::npos) {
625+
std::stringstream paramStream;
626+
paramStream << std::hex << Params[2].data();
627+
uint64_t specVal = 0;
628+
paramStream >> specVal;
629+
Opts.setSpecConst(SpecId, specVal);
630+
} else {
631+
Expected<APFloat::opStatus> StatusOrErr =
632+
Value.convertFromString(Params[2], APFloat::rmNearestTiesToEven);
633+
if (!StatusOrErr) {
634+
return true;
635+
}
636+
// It's ok to have inexact conversion from decimal representation.
637+
APFloat::opStatus Status = *StatusOrErr;
638+
if (Status & ~APFloat::opInexact) {
639+
errs() << "Error: Invalid value for '-" << SpecConst.ArgStr
640+
<< "' option! In \"" << Option << "\": can't convert \""
641+
<< Params[2] << "\" to " << Width
642+
<< "-bit floating point number\n";
643+
return true;
644+
}
645+
Opts.setSpecConst(SpecId, Value.bitcastToAPInt().getZExtValue());
634646
}
635-
Opts.setSpecConst(SpecId, Value.bitcastToAPInt().getZExtValue());
636647
} else {
637648
errs() << "Error: Invalid type for '-" << SpecConst.ArgStr
638649
<< "' option! In \"" << Option << "\": \"" << Params[1]
@@ -766,8 +777,9 @@ int main(int Ac, char **Av) {
766777
std::cout << "Number of scalar specialization constants in the module = "
767778
<< SpecConstInfo.size() << "\n";
768779
for (auto &SpecConst : SpecConstInfo)
769-
std::cout << "Spec const id = " << SpecConst.first
770-
<< ", size in bytes = " << SpecConst.second << "\n";
780+
std::cout << "Spec const id = " << SpecConst.ID
781+
<< ", size in bytes = " << SpecConst.Size
782+
<< ", type = " << SpecConst.Type << "\n";
771783
}
772784
return 0;
773785
}

0 commit comments

Comments
 (0)