Skip to content

Commit b0c2bb1

Browse files
authored
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.
1 parent a326355 commit b0c2bb1

File tree

5 files changed

+94
-35
lines changed

5 files changed

+94
-35
lines changed

include/LLVMSPIRVLib.h

Lines changed: 5 additions & 1 deletion
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

lib/SPIRV/SPIRVReader.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4574,7 +4574,42 @@ bool llvm::getSpecConstInfo(std::istream &IS,
45744574
if (C->hasDecorate(DecorationSpecId, 0, &SpecConstIdLiteral)) {
45754575
SPIRVType *Ty = C->getType();
45764576
uint32_t SpecConstSize = Ty->isTypeBool() ? 1 : Ty->getBitWidth() / 8;
4577-
SpecConstInfo.emplace_back(SpecConstIdLiteral, SpecConstSize);
4577+
std::string TypeString = "";
4578+
if (Ty->isTypeBool()) {
4579+
TypeString = "i1";
4580+
} else if (Ty->isTypeInt()) {
4581+
switch (SpecConstSize) {
4582+
case 1:
4583+
TypeString = "i8";
4584+
break;
4585+
case 2:
4586+
TypeString = "i16";
4587+
break;
4588+
case 4:
4589+
TypeString = "i32";
4590+
break;
4591+
case 8:
4592+
TypeString = "i64";
4593+
break;
4594+
}
4595+
} else if (Ty->isTypeFloat()) {
4596+
switch (SpecConstSize) {
4597+
case 2:
4598+
TypeString = "f16";
4599+
break;
4600+
case 4:
4601+
TypeString = "f32";
4602+
break;
4603+
case 8:
4604+
TypeString = "f64";
4605+
break;
4606+
}
4607+
}
4608+
if (TypeString == "")
4609+
return false;
4610+
4611+
SpecConstInfo.emplace_back(
4612+
SpecConstInfoTy({SpecConstIdLiteral, SpecConstSize, TypeString}));
45784613
}
45794614
break;
45804615
}

test/SpecConstants/OpSpecConstant.spvasm

Lines changed: 19 additions & 11 deletions
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

test/lit.cfg.py

Lines changed: 1 addition & 1 deletion
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:

tools/llvm-spirv/llvm-spirv.cpp

Lines changed: 33 additions & 21 deletions
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"
@@ -183,6 +184,8 @@ static cl::opt<std::string> SpecConst(
183184
"SPIR-V module.\n"
184185
"The list of valid ids is available via -spec-const-info option.\n"
185186
"For duplicate ids the later one takes precedence.\n"
187+
"Float values may be represented in decimal or hexadecimal, hex "
188+
"values must be preceded by 0x.\n"
186189
"Supported types are: i1, i8, i16, i32, i64, f16, f32, f64.\n"),
187190
cl::value_desc("id1:type1:value1 id2:type2:value2 ..."));
188191

@@ -552,9 +555,9 @@ bool parseSpecConstOpt(llvm::StringRef SpecConstStr,
552555
<< "\" must be a 32-bit unsigned integer\n";
553556
return true;
554557
}
555-
auto It = std::find_if(
556-
SpecConstInfo.begin(), SpecConstInfo.end(),
557-
[=](SpecConstInfoTy Info) { return Info.first == SpecId; });
558+
auto It =
559+
std::find_if(SpecConstInfo.begin(), SpecConstInfo.end(),
560+
[=](SpecConstInfoTy Info) { return Info.ID == SpecId; });
558561
if (It == SpecConstInfo.end()) {
559562
errs() << "Error: CL_INVALID_SPEC_ID. \"" << Option << "\": There is no "
560563
<< "specialization constant with id = " << SpecId
@@ -572,11 +575,11 @@ bool parseSpecConstOpt(llvm::StringRef SpecConstStr,
572575
return true;
573576
}
574577
size_t Size = Width < 8 ? 1 : Width / 8;
575-
if (Size != It->second) {
578+
if (Size != It->Size) {
576579
errs() << "Error: CL_INVALID_VALUE. In \"" << Option << "\": Size of "
577580
<< "type i" << Width << " (" << Size << " bytes) "
578581
<< "does not match the size of the specialization constant "
579-
<< "in the module (" << It->second << " bytes)\n";
582+
<< "in the module (" << It->Size << " bytes)\n";
580583
return true;
581584
}
582585
APInt Value;
@@ -611,21 +614,29 @@ bool parseSpecConstOpt(llvm::StringRef SpecConstStr,
611614
return true;
612615
}
613616
APFloat Value(*FS);
614-
Expected<APFloat::opStatus> StatusOrErr =
615-
Value.convertFromString(Params[2], APFloat::rmNearestTiesToEven);
616-
if (!StatusOrErr) {
617-
return true;
618-
}
619-
// It's ok to have inexact conversion from decimal representation.
620-
APFloat::opStatus Status = *StatusOrErr;
621-
if (Status & ~APFloat::opInexact) {
622-
errs() << "Error: Invalid value for '-" << SpecConst.ArgStr
623-
<< "' option! In \"" << Option << "\": can't convert \""
624-
<< Params[2] << "\" to " << Width
625-
<< "-bit floating point number\n";
626-
return true;
617+
if (Params[2].find("0x") != StringRef::npos) {
618+
std::stringstream paramStream;
619+
paramStream << std::hex << Params[2].data();
620+
uint64_t specVal = 0;
621+
paramStream >> specVal;
622+
Opts.setSpecConst(SpecId, specVal);
623+
} else {
624+
Expected<APFloat::opStatus> StatusOrErr =
625+
Value.convertFromString(Params[2], APFloat::rmNearestTiesToEven);
626+
if (!StatusOrErr) {
627+
return true;
628+
}
629+
// It's ok to have inexact conversion from decimal representation.
630+
APFloat::opStatus Status = *StatusOrErr;
631+
if (Status & ~APFloat::opInexact) {
632+
errs() << "Error: Invalid value for '-" << SpecConst.ArgStr
633+
<< "' option! In \"" << Option << "\": can't convert \""
634+
<< Params[2] << "\" to " << Width
635+
<< "-bit floating point number\n";
636+
return true;
637+
}
638+
Opts.setSpecConst(SpecId, Value.bitcastToAPInt().getZExtValue());
627639
}
628-
Opts.setSpecConst(SpecId, Value.bitcastToAPInt().getZExtValue());
629640
} else {
630641
errs() << "Error: Invalid type for '-" << SpecConst.ArgStr
631642
<< "' option! In \"" << Option << "\": \"" << Params[1]
@@ -759,8 +770,9 @@ int main(int Ac, char **Av) {
759770
std::cout << "Number of scalar specialization constants in the module = "
760771
<< SpecConstInfo.size() << "\n";
761772
for (auto &SpecConst : SpecConstInfo)
762-
std::cout << "Spec const id = " << SpecConst.first
763-
<< ", size in bytes = " << SpecConst.second << "\n";
773+
std::cout << "Spec const id = " << SpecConst.ID
774+
<< ", size in bytes = " << SpecConst.Size
775+
<< ", type = " << SpecConst.Type << "\n";
764776
}
765777
return 0;
766778
}

0 commit comments

Comments
 (0)