Skip to content

Commit 18b08af

Browse files
spirv-val: Print OpFunctionCall with ShaderDebugInfo (KhronosGroup#6686)
Next part of KhronosGroup#6617 - Creates a common util for function lines - Have way to print two sections - Add `OpFunctionCall` ``` error: 54: OpFunctionCall Argument <id> '41[%41]'s type does not match Function <id> '28[%_ptr_Function_int]'s parameter type. %47 = OpFunctionCall %int %48 %41 --> file_b.comp:4:0 | 4 | int y = foo( 5 | x 6 | ); | --> file_a.comp:2:0 | 2 | int foo(int z) { | ```
1 parent 4548962 commit 18b08af

3 files changed

Lines changed: 457 additions & 52 deletions

File tree

source/val/validation_state.cpp

Lines changed: 150 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,7 +2191,10 @@ std::string ValidationState_t::InspectShaderDebugInfo(const Instruction& inst) {
21912191
if (func != nullptr) {
21922192
if (inst.opcode() == spv::Op::OpVariable) {
21932193
InspectDebugLocalVariable(ss, *func, inst);
2194+
} else if (inst.opcode() == spv::Op::OpFunctionCall) {
2195+
InspectDebugFunctionDefinition(ss, inst);
21942196
} else {
2197+
// Currently a fall back for anything in a function
21952198
InspectDebugLine(ss, inst);
21962199
}
21972200
} else if (inst.opcode() == spv::Op::OpVariable) {
@@ -2203,6 +2206,88 @@ std::string ValidationState_t::InspectShaderDebugInfo(const Instruction& inst) {
22032206
return ss.str();
22042207
}
22052208

2209+
ValidationState_t::DebugSourceInfo ValidationState_t::GetDebugSourceInfo(
2210+
const Instruction& inst) {
2211+
assert(inst.opcode() == spv::Op::OpExtInst);
2212+
assert(inst.word(3) == ShaderDebugInfoSet());
2213+
2214+
uint32_t line_start_id = 0, line_end_id = 0, column_start_id = 0,
2215+
column_end_id = 0;
2216+
2217+
switch (inst.word(4)) {
2218+
case NonSemanticShaderDebugInfoDebugLine:
2219+
line_start_id = 6;
2220+
line_end_id = 7;
2221+
column_start_id = 8;
2222+
column_end_id = 9;
2223+
break;
2224+
case NonSemanticShaderDebugInfoDebugTypeTemplateParameterPack:
2225+
line_start_id = 7;
2226+
column_start_id = 8;
2227+
break;
2228+
case NonSemanticShaderDebugInfoDebugLexicalBlock:
2229+
line_start_id = 6;
2230+
column_start_id = 7;
2231+
break;
2232+
case NonSemanticShaderDebugInfoDebugLocalVariable:
2233+
case NonSemanticShaderDebugInfoDebugGlobalVariable:
2234+
case NonSemanticShaderDebugInfoDebugTypedef:
2235+
case NonSemanticShaderDebugInfoDebugTypeEnum:
2236+
case NonSemanticShaderDebugInfoDebugTypeComposite:
2237+
case NonSemanticShaderDebugInfoDebugTypeMember:
2238+
case NonSemanticShaderDebugInfoDebugTypeTemplateTemplateParameter:
2239+
case NonSemanticShaderDebugInfoDebugFunctionDeclaration:
2240+
case NonSemanticShaderDebugInfoDebugFunction:
2241+
line_start_id = 8;
2242+
column_start_id = 9;
2243+
break;
2244+
case NonSemanticShaderDebugInfoDebugTypeTemplateParameter:
2245+
case NonSemanticShaderDebugInfoDebugImportedEntity:
2246+
line_start_id = 9;
2247+
column_start_id = 10;
2248+
break;
2249+
case NonSemanticShaderDebugInfoDebugMacroDef:
2250+
case NonSemanticShaderDebugInfoDebugMacroUndef:
2251+
line_start_id = 6;
2252+
break;
2253+
default:
2254+
return {0, 0, 0, 0};
2255+
}
2256+
2257+
// spirv-val enforces these are int32 constants
2258+
bool is_int32 = false, is_const_int32 = false;
2259+
uint32_t line_start = 0;
2260+
uint32_t line_end = 0;
2261+
uint32_t column_start = 0;
2262+
uint32_t column_end = 0;
2263+
2264+
std::tie(is_int32, is_const_int32, line_start) =
2265+
EvalInt32IfConst(inst.word(line_start_id));
2266+
2267+
// Some instructions only provide a line and column, so set the "end" to be
2268+
// same as "start"
2269+
if (line_end_id != 0) {
2270+
std::tie(is_int32, is_const_int32, line_end) =
2271+
EvalInt32IfConst(inst.word(line_end_id));
2272+
} else {
2273+
line_end = line_start;
2274+
}
2275+
2276+
if (column_start_id != 0) {
2277+
std::tie(is_int32, is_const_int32, column_start) =
2278+
EvalInt32IfConst(inst.word(column_start_id));
2279+
}
2280+
2281+
if (column_end_id != 0) {
2282+
std::tie(is_int32, is_const_int32, column_end) =
2283+
EvalInt32IfConst(inst.word(column_end_id));
2284+
} else {
2285+
column_end = column_start;
2286+
}
2287+
2288+
return {line_start, line_end, column_start, column_end};
2289+
}
2290+
22062291
void ValidationState_t::InspectDebugLine(std::ostringstream& ss,
22072292
const Instruction& inst) {
22082293
const uint32_t set_id = ShaderDebugInfoSet();
@@ -2233,22 +2318,8 @@ void ValidationState_t::InspectDebugLine(std::ostringstream& ss,
22332318
return;
22342319
}
22352320

2236-
bool is_int32 = false, is_const_int32 = false;
2237-
uint32_t line_start = 0;
2238-
uint32_t line_end = 0;
2239-
uint32_t column_start = 0;
2240-
uint32_t column_end = 0;
2241-
std::tie(is_int32, is_const_int32, line_start) =
2242-
EvalInt32IfConst(debug_line_inst->word(6));
2243-
std::tie(is_int32, is_const_int32, line_end) =
2244-
EvalInt32IfConst(debug_line_inst->word(7));
2245-
std::tie(is_int32, is_const_int32, column_start) =
2246-
EvalInt32IfConst(debug_line_inst->word(8));
2247-
std::tie(is_int32, is_const_int32, column_end) =
2248-
EvalInt32IfConst(debug_line_inst->word(9));
2249-
2250-
PrintShaderDebugInfoSource(ss, *debug_source, line_start, line_end,
2251-
column_start);
2321+
auto source_info = GetDebugSourceInfo(*debug_line_inst);
2322+
PrintShaderDebugInfoSource(ss, *debug_source, source_info);
22522323
}
22532324

22542325
void ValidationState_t::InspectDebugGlobalVariable(
@@ -2279,16 +2350,8 @@ void ValidationState_t::InspectDebugGlobalVariable(
22792350
return;
22802351
}
22812352

2282-
bool is_int32 = false, is_const_int32 = false;
2283-
uint32_t line_start = 0;
2284-
uint32_t column_start = 0;
2285-
std::tie(is_int32, is_const_int32, line_start) =
2286-
EvalInt32IfConst(debug_gloabl_var_inst->word(8));
2287-
std::tie(is_int32, is_const_int32, column_start) =
2288-
EvalInt32IfConst(debug_gloabl_var_inst->word(9));
2289-
2290-
PrintShaderDebugInfoSource(ss, *debug_source, line_start, line_start,
2291-
column_start);
2353+
auto source_info = GetDebugSourceInfo(*debug_gloabl_var_inst);
2354+
PrintShaderDebugInfoSource(ss, *debug_source, source_info);
22922355
}
22932356

22942357
void ValidationState_t::InspectDebugLocalVariable(
@@ -2333,24 +2396,68 @@ void ValidationState_t::InspectDebugLocalVariable(
23332396
return;
23342397
}
23352398

2336-
bool is_int32 = false, is_const_int32 = false;
2337-
uint32_t line_start = 0;
2338-
uint32_t column_start = 0;
2339-
std::tie(is_int32, is_const_int32, line_start) =
2340-
EvalInt32IfConst(debug_local_variable->word(8));
2341-
std::tie(is_int32, is_const_int32, column_start) =
2342-
EvalInt32IfConst(debug_local_variable->word(9));
2399+
auto source_info = GetDebugSourceInfo(*debug_local_variable);
2400+
PrintShaderDebugInfoSource(ss, *debug_source, source_info);
2401+
}
2402+
2403+
void ValidationState_t::InspectDebugFunctionDefinition(
2404+
std::ostringstream& ss, const Instruction& function_call_inst) {
2405+
// First print the caller, then print the callee if also found
2406+
InspectDebugLine(ss, function_call_inst);
2407+
2408+
const uint32_t set_id = ShaderDebugInfoSet();
2409+
const Instruction* debug_func_def = nullptr;
2410+
2411+
const uint32_t callee_function_id =
2412+
function_call_inst.GetOperandAs<uint32_t>(2);
2413+
const Instruction* function_inst = FindDef(callee_function_id);
2414+
if (!function_inst) return;
2415+
2416+
// Loop through the Function block as the DebugFunctionDefinition needs to be
2417+
// inside it
2418+
size_t first_inst_id = (function_inst - &ordered_instructions()[0]) + 1;
2419+
for (size_t i = first_inst_id + 1; i < ordered_instructions().size(); ++i) {
2420+
const Instruction& current_inst = ordered_instructions()[i];
2421+
if (current_inst.opcode() == spv::Op::OpFunctionEnd) {
2422+
break; // we hit the next Funciton block
2423+
}
2424+
2425+
if (current_inst.opcode() == spv::Op::OpExtInst &&
2426+
current_inst.GetOperandAs<uint32_t>(2) == set_id &&
2427+
current_inst.GetOperandAs<uint32_t>(3) ==
2428+
NonSemanticShaderDebugInfoDebugFunctionDefinition &&
2429+
current_inst.GetOperandAs<uint32_t>(5) == callee_function_id) {
2430+
debug_func_def = &current_inst;
2431+
break;
2432+
}
2433+
}
2434+
if (!debug_func_def) return;
2435+
2436+
const Instruction* debug_function =
2437+
FindDef(debug_func_def->GetOperandAs<uint32_t>(4));
2438+
if (!debug_function || debug_function->GetOperandAs<uint32_t>(3) !=
2439+
NonSemanticShaderDebugInfoDebugFunction) {
2440+
return;
2441+
}
2442+
2443+
const Instruction* debug_source =
2444+
FindDef(debug_function->GetOperandAs<uint32_t>(6));
2445+
if (!debug_source || debug_source->GetOperandAs<uint32_t>(3) !=
2446+
NonSemanticShaderDebugInfoDebugSource) {
2447+
return;
2448+
}
23432449

2344-
PrintShaderDebugInfoSource(ss, *debug_source, line_start, line_start,
2345-
column_start);
2450+
auto source_info = GetDebugSourceInfo(*debug_function);
2451+
PrintShaderDebugInfoSource(ss, *debug_source, source_info);
23462452
}
23472453

23482454
void ValidationState_t::PrintShaderDebugInfoSource(
23492455
std::ostringstream& ss, const Instruction& debug_source,
2350-
uint32_t line_start, uint32_t line_end, uint32_t column_start) {
2456+
const DebugSourceInfo& source_info) {
23512457
// The left hand side line number, need to make sure if going from line number
23522458
// 99 to 100 that all lines have the same padding
2353-
const size_t vertical_line_padding = std::to_string(line_end).length();
2459+
const size_t vertical_line_padding =
2460+
std::to_string(source_info.line_end).length();
23542461
auto add_vertical_line = [&](uint32_t line_number) {
23552462
size_t padding = 1;
23562463
if (line_number != 0) {
@@ -2373,9 +2480,10 @@ void ValidationState_t::PrintShaderDebugInfoSource(
23732480
auto stream_text = [&](const Instruction* op_string) {
23742481
const std::string text = op_string->GetOperandAs<std::string>(1);
23752482
for (const char c : text) {
2376-
if (current_line_num >= line_start && current_line_num <= line_end) {
2483+
if (current_line_num >= source_info.line_start &&
2484+
current_line_num <= source_info.line_end) {
23772485
ss << c;
2378-
if (c == '\n' && current_line_num < line_end) {
2486+
if (c == '\n' && current_line_num < source_info.line_end) {
23792487
add_vertical_line(current_line_num + 1);
23802488
}
23812489
}
@@ -2389,14 +2497,14 @@ void ValidationState_t::PrintShaderDebugInfoSource(
23892497
const Instruction* file_string =
23902498
FindDef(debug_source.GetOperandAs<uint32_t>(4));
23912499
ss << "\n --> " << file_string->GetOperandAs<std::string>(1) << ":"
2392-
<< line_start << ":" << column_start << '\n';
2500+
<< source_info.line_start << ":" << source_info.column_start << '\n';
23932501

23942502
add_vertical_line(0);
23952503
ss << '\n';
23962504

23972505
const Instruction* source_string =
23982506
FindDef(debug_source.GetOperandAs<uint32_t>(5));
2399-
add_vertical_line(line_start);
2507+
add_vertical_line(source_info.line_start);
24002508
stream_text(source_string);
24012509

24022510
const uint32_t set_id = ShaderDebugInfoSet();
@@ -2418,10 +2526,9 @@ void ValidationState_t::PrintShaderDebugInfoSource(
24182526
}
24192527

24202528
// This happens if the error is the last line of source
2421-
if (current_line_num == line_end) ss << "\n";
2529+
if (current_line_num == source_info.line_end) ss << "\n";
24222530

24232531
add_vertical_line(0);
2424-
ss << "\n";
24252532
}
24262533

24272534
bool ValidationState_t::IsValidStorageClass(

source/val/validation_state.h

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,15 +1007,6 @@ class ValidationState_t {
10071007
void RegisterShaderDebugInfo(uint32_t id) { shader_debug_info_set_id = id; }
10081008
uint32_t ShaderDebugInfoSet() const { return shader_debug_info_set_id; }
10091009
std::string InspectShaderDebugInfo(const Instruction& inst);
1010-
void InspectDebugLine(std::ostringstream& ss, const Instruction& inst);
1011-
void InspectDebugGlobalVariable(std::ostringstream& ss,
1012-
const Instruction& inst);
1013-
void InspectDebugLocalVariable(std::ostringstream& ss, const Function& func,
1014-
const Instruction& inst);
1015-
void PrintShaderDebugInfoSource(std::ostringstream& ss,
1016-
const Instruction& debug_source,
1017-
uint32_t line_start, uint32_t line_end,
1018-
uint32_t column_start);
10191010

10201011
private:
10211012
ValidationState_t(const ValidationState_t&);
@@ -1210,6 +1201,24 @@ class ValidationState_t {
12101201
/// Variables used to reduce the number of diagnostic messages.
12111202
uint32_t num_of_warnings_;
12121203
uint32_t max_num_of_warnings_;
1204+
1205+
struct DebugSourceInfo {
1206+
uint32_t line_start;
1207+
uint32_t line_end;
1208+
uint32_t column_start;
1209+
uint32_t column_end;
1210+
};
1211+
DebugSourceInfo GetDebugSourceInfo(const Instruction& inst);
1212+
void InspectDebugLine(std::ostringstream& ss, const Instruction& inst);
1213+
void InspectDebugGlobalVariable(std::ostringstream& ss,
1214+
const Instruction& inst);
1215+
void InspectDebugLocalVariable(std::ostringstream& ss, const Function& func,
1216+
const Instruction& inst);
1217+
void InspectDebugFunctionDefinition(std::ostringstream& ss,
1218+
const Instruction& function_call_inst);
1219+
void PrintShaderDebugInfoSource(std::ostringstream& ss,
1220+
const Instruction& debug_source,
1221+
const DebugSourceInfo& source_info);
12131222
};
12141223

12151224
} // namespace val

0 commit comments

Comments
 (0)