Skip to content

Commit 2acb87f

Browse files
spirv-val: Add DebugInfo to ReturnValue/FunctionParameter (KhronosGroup#6698)
Part of KhronosGroup#6617 For things like `OpReturnValue` and `OpFunctionParameter` it is valuable to print both the line it occured and the function definition as its related ``` --> a.comp:4:0 | 4 | return 4; | --> a.comp:3:0 | 3 | uint foo() { | ```
1 parent 3c042c5 commit 2acb87f

3 files changed

Lines changed: 320 additions & 0 deletions

File tree

source/val/validation_state.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,9 @@ std::string ValidationState_t::InspectShaderDebugInfo(const Instruction& inst) {
21952195
InspectDebugLocalVariable(ss, *func, inst);
21962196
} else if (opcode == spv::Op::OpFunctionCall) {
21972197
InspectFunctionCall(ss, inst);
2198+
} else if (opcode == spv::Op::OpReturnValue ||
2199+
opcode == spv::Op::OpFunctionParameter) {
2200+
InspectLineAndFunctionDefinition(ss, *func, inst);
21982201
} else {
21992202
// Currently a fall back for anything in a function
22002203
InspectDebugLine(ss, inst);
@@ -2423,6 +2426,19 @@ void ValidationState_t::InspectFunctionCall(
24232426
}
24242427
}
24252428

2429+
// For instruction in the function that it would be value to both get the line
2430+
// of the invalid instruction, but also the FunctionDefinition
2431+
void ValidationState_t::InspectLineAndFunctionDefinition(
2432+
std::ostringstream& ss, const Function& func, const Instruction& inst) {
2433+
// First print the return line (if one) than find the function def
2434+
InspectDebugLine(ss, inst);
2435+
2436+
const Instruction* function_inst = FindDef(func.id());
2437+
if (function_inst) {
2438+
InspectDebugFunctionDefinition(ss, *function_inst);
2439+
}
2440+
}
2441+
24262442
void ValidationState_t::InspectEntryPoint(std::ostringstream& ss,
24272443
const Instruction& inst) {
24282444
const Instruction* function_inst = nullptr;

source/val/validation_state.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,9 @@ class ValidationState_t {
12161216
const Instruction& inst);
12171217
void InspectFunctionCall(std::ostringstream& ss,
12181218
const Instruction& function_call_inst);
1219+
void InspectLineAndFunctionDefinition(std::ostringstream& ss,
1220+
const Function& func,
1221+
const Instruction& inst);
12191222
void InspectEntryPoint(std::ostringstream& ss, const Instruction& inst);
12201223
void InspectDebugFunctionDefinition(std::ostringstream& ss,
12211224
const Instruction& function_inst);

test/val/val_shader_debug_info_test.cpp

Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,307 @@ void main() {
940940
|)"));
941941
}
942942

943+
TEST_F(ValidateShaderDebugInfo, ReturnValue) {
944+
const std::string str = R"(
945+
OpCapability Shader
946+
OpExtension "SPV_KHR_non_semantic_info"
947+
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
948+
OpMemoryModel Logical GLSL450
949+
OpEntryPoint GLCompute %main "main"
950+
OpExecutionMode %main LocalSize 1 1 1
951+
%2 = OpString "a.comp"
952+
%8 = OpString "uint"
953+
%20 = OpString "foo"
954+
%23 = OpString "#version 450
955+
956+
uint foo() {
957+
return 4;
958+
}
959+
960+
void main() {
961+
int a = 0;
962+
uint b = foo();
963+
}"
964+
%28 = OpString "main"
965+
%44 = OpString "int"
966+
%50 = OpString "a"
967+
%60 = OpString "b"
968+
%void = OpTypeVoid
969+
%5 = OpTypeFunction %void
970+
%uint = OpTypeInt 32 0
971+
%int = OpTypeInt 32 1
972+
%uint_32 = OpConstant %uint 32
973+
%uint_6 = OpConstant %uint 6
974+
%uint_0 = OpConstant %uint 0
975+
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
976+
%uint_3 = OpConstant %uint 3
977+
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
978+
%16 = OpTypeFunction %uint
979+
%17 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9
980+
%22 = OpExtInst %void %1 DebugSource %2 %23
981+
%uint_1 = OpConstant %uint 1
982+
%uint_4 = OpConstant %uint 4
983+
%int_4 = OpConstant %int 4
984+
%uint_2 = OpConstant %uint 2
985+
%24 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %22 %uint_2
986+
%21 = OpExtInst %void %1 DebugFunction %20 %17 %22 %uint_3 %uint_0 %24 %20 %uint_3 %uint_3
987+
%uint_7 = OpConstant %uint 7
988+
%29 = OpExtInst %void %1 DebugFunction %28 %6 %22 %uint_7 %uint_0 %24 %28 %uint_3 %uint_7
989+
%uint_5 = OpConstant %uint 5
990+
%45 = OpExtInst %void %1 DebugTypeBasic %44 %uint_32 %uint_4 %uint_0
991+
%_ptr_Function_int = OpTypePointer Function %int
992+
%47 = OpExtInst %void %1 DebugTypePointer %45 %uint_7 %uint_0
993+
%uint_8 = OpConstant %uint 8
994+
%49 = OpExtInst %void %1 DebugLocalVariable %50 %45 %22 %uint_8 %uint_0 %29 %uint_4
995+
%53 = OpExtInst %void %1 DebugExpression
996+
%int_0 = OpConstant %int 0
997+
%_ptr_Function_uint = OpTypePointer Function %uint
998+
%57 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
999+
%uint_9 = OpConstant %uint 9
1000+
%59 = OpExtInst %void %1 DebugLocalVariable %60 %9 %22 %uint_9 %uint_0 %29 %uint_4
1001+
%uint_10 = OpConstant %uint 10
1002+
%main = OpFunction %void None %5
1003+
%15 = OpLabel
1004+
%a = OpVariable %_ptr_Function_int Function
1005+
%b = OpVariable %_ptr_Function_uint Function
1006+
%41 = OpExtInst %void %1 DebugScope %29
1007+
%42 = OpExtInst %void %1 DebugLine %22 %uint_7 %uint_7 %uint_0 %uint_0
1008+
%40 = OpExtInst %void %1 DebugFunctionDefinition %29 %main
1009+
%54 = OpExtInst %void %1 DebugLine %22 %uint_8 %uint_8 %uint_0 %uint_0
1010+
%52 = OpExtInst %void %1 DebugDeclare %49 %a %53
1011+
OpStore %a %int_0
1012+
%63 = OpExtInst %void %1 DebugLine %22 %uint_9 %uint_9 %uint_0 %uint_0
1013+
%62 = OpExtInst %void %1 DebugDeclare %59 %b %53
1014+
%64 = OpFunctionCall %uint %foo_
1015+
OpStore %b %64
1016+
%65 = OpExtInst %void %1 DebugLine %22 %uint_10 %uint_10 %uint_0 %uint_0
1017+
OpReturn
1018+
OpFunctionEnd
1019+
%foo_ = OpFunction %uint None %16
1020+
%19 = OpLabel
1021+
%32 = OpExtInst %void %1 DebugScope %21
1022+
%33 = OpExtInst %void %1 DebugLine %22 %uint_3 %uint_3 %uint_0 %uint_0
1023+
%31 = OpExtInst %void %1 DebugFunctionDefinition %21 %foo_
1024+
%34 = OpExtInst %void %1 DebugLine %22 %uint_4 %uint_4 %uint_0 %uint_0
1025+
OpReturnValue %int_4
1026+
OpFunctionEnd
1027+
)";
1028+
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
1029+
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
1030+
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"(--> a.comp:4:0
1031+
|
1032+
4 | return 4;
1033+
|
1034+
--> a.comp:3:0
1035+
|
1036+
3 | uint foo() {
1037+
|)"));
1038+
}
1039+
1040+
TEST_F(ValidateShaderDebugInfo, ReturnValueVoid) {
1041+
const std::string str = R"(
1042+
OpCapability Shader
1043+
OpExtension "SPV_KHR_non_semantic_info"
1044+
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
1045+
OpMemoryModel Logical GLSL450
1046+
OpEntryPoint GLCompute %main "main"
1047+
OpExecutionMode %main LocalSize 1 1 1
1048+
%2 = OpString "a.comp"
1049+
%8 = OpString "uint"
1050+
%20 = OpString "foo"
1051+
%23 = OpString "#version 450
1052+
1053+
uint foo() {
1054+
return 4;
1055+
}
1056+
1057+
void main() {
1058+
int a = 0;
1059+
uint b = foo();
1060+
}"
1061+
%28 = OpString "main"
1062+
%44 = OpString "int"
1063+
%50 = OpString "a"
1064+
%60 = OpString "b"
1065+
%void = OpTypeVoid
1066+
%5 = OpTypeFunction %void
1067+
%uint = OpTypeInt 32 0
1068+
%int = OpTypeInt 32 1
1069+
%uint_32 = OpConstant %uint 32
1070+
%uint_6 = OpConstant %uint 6
1071+
%uint_0 = OpConstant %uint 0
1072+
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
1073+
%uint_3 = OpConstant %uint 3
1074+
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
1075+
%16 = OpTypeFunction %uint
1076+
%17 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9
1077+
%22 = OpExtInst %void %1 DebugSource %2 %23
1078+
%uint_1 = OpConstant %uint 1
1079+
%uint_4 = OpConstant %uint 4
1080+
%int_4 = OpConstant %int 4
1081+
%uint_2 = OpConstant %uint 2
1082+
%24 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %22 %uint_2
1083+
%21 = OpExtInst %void %1 DebugFunction %20 %17 %22 %uint_3 %uint_0 %24 %20 %uint_3 %uint_3
1084+
%uint_7 = OpConstant %uint 7
1085+
%29 = OpExtInst %void %1 DebugFunction %28 %6 %22 %uint_7 %uint_0 %24 %28 %uint_3 %uint_7
1086+
%uint_5 = OpConstant %uint 5
1087+
%45 = OpExtInst %void %1 DebugTypeBasic %44 %uint_32 %uint_4 %uint_0
1088+
%_ptr_Function_int = OpTypePointer Function %int
1089+
%47 = OpExtInst %void %1 DebugTypePointer %45 %uint_7 %uint_0
1090+
%uint_8 = OpConstant %uint 8
1091+
%49 = OpExtInst %void %1 DebugLocalVariable %50 %45 %22 %uint_8 %uint_0 %29 %uint_4
1092+
%53 = OpExtInst %void %1 DebugExpression
1093+
%int_0 = OpConstant %int 0
1094+
%_ptr_Function_uint = OpTypePointer Function %uint
1095+
%57 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
1096+
%uint_9 = OpConstant %uint 9
1097+
%59 = OpExtInst %void %1 DebugLocalVariable %60 %9 %22 %uint_9 %uint_0 %29 %uint_4
1098+
%uint_10 = OpConstant %uint 10
1099+
%main = OpFunction %void None %5
1100+
%15 = OpLabel
1101+
%a = OpVariable %_ptr_Function_int Function
1102+
%b = OpVariable %_ptr_Function_uint Function
1103+
%41 = OpExtInst %void %1 DebugScope %29
1104+
%42 = OpExtInst %void %1 DebugLine %22 %uint_7 %uint_7 %uint_0 %uint_0
1105+
%40 = OpExtInst %void %1 DebugFunctionDefinition %29 %main
1106+
%54 = OpExtInst %void %1 DebugLine %22 %uint_8 %uint_8 %uint_0 %uint_0
1107+
%52 = OpExtInst %void %1 DebugDeclare %49 %a %53
1108+
OpStore %a %int_0
1109+
%63 = OpExtInst %void %1 DebugLine %22 %uint_9 %uint_9 %uint_0 %uint_0
1110+
%62 = OpExtInst %void %1 DebugDeclare %59 %b %53
1111+
%64 = OpFunctionCall %uint %foo_
1112+
OpStore %b %64
1113+
%65 = OpExtInst %void %1 DebugLine %22 %uint_10 %uint_10 %uint_0 %uint_0
1114+
OpReturnValue %int_0
1115+
OpFunctionEnd
1116+
%foo_ = OpFunction %uint None %16
1117+
%19 = OpLabel
1118+
%32 = OpExtInst %void %1 DebugScope %21
1119+
%33 = OpExtInst %void %1 DebugLine %22 %uint_3 %uint_3 %uint_0 %uint_0
1120+
%31 = OpExtInst %void %1 DebugFunctionDefinition %21 %foo_
1121+
%34 = OpExtInst %void %1 DebugLine %22 %uint_4 %uint_4 %uint_0 %uint_0
1122+
OpReturnValue %int_4
1123+
OpFunctionEnd
1124+
)";
1125+
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
1126+
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
1127+
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"(--> a.comp:10:0
1128+
|
1129+
10 | }
1130+
|
1131+
--> a.comp:7:0
1132+
|
1133+
7 | void main() {
1134+
|)"));
1135+
}
1136+
1137+
TEST_F(ValidateShaderDebugInfo, FunctionParameter) {
1138+
const std::string str = R"(
1139+
; SPIR-V
1140+
; Version: 1.5
1141+
; Generator: Khronos Glslang Reference Front End; 11
1142+
; Bound: 75
1143+
; Schema: 0
1144+
OpCapability Shader
1145+
OpExtension "SPV_KHR_non_semantic_info"
1146+
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
1147+
%3 = OpExtInstImport "GLSL.std.450"
1148+
OpMemoryModel Logical GLSL450
1149+
OpEntryPoint GLCompute %main "main"
1150+
OpExecutionMode %main LocalSize 1 1 1
1151+
%2 = OpString "a.comp"
1152+
%8 = OpString "uint"
1153+
%24 = OpString "foo"
1154+
%27 = OpString "#version 450
1155+
1156+
uint foo(uint a) {
1157+
return a * 4;
1158+
}
1159+
1160+
void main() {
1161+
int a = 0;
1162+
uint b = foo(a);
1163+
}"
1164+
%33 = OpString "a"
1165+
%38 = OpString "main"
1166+
%53 = OpString "int"
1167+
%65 = OpString "b"
1168+
%void = OpTypeVoid
1169+
%5 = OpTypeFunction %void
1170+
%uint = OpTypeInt 32 0
1171+
%uint_32 = OpConstant %uint 32
1172+
%uint_6 = OpConstant %uint 6
1173+
%uint_0 = OpConstant %uint 0
1174+
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
1175+
%uint_3 = OpConstant %uint 3
1176+
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
1177+
%_ptr_Function_uint = OpTypePointer Function %uint
1178+
%uint_7 = OpConstant %uint 7
1179+
%18 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
1180+
%19 = OpTypeFunction %uint %_ptr_Function_uint
1181+
%20 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9 %9
1182+
%26 = OpExtInst %void %1 DebugSource %2 %27
1183+
%uint_1 = OpConstant %uint 1
1184+
%uint_4 = OpConstant %uint 4
1185+
%uint_2 = OpConstant %uint 2
1186+
%28 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %26 %uint_2
1187+
%25 = OpExtInst %void %1 DebugFunction %24 %20 %26 %uint_3 %uint_0 %28 %24 %uint_3 %uint_3
1188+
%32 = OpExtInst %void %1 DebugLocalVariable %33 %9 %26 %uint_3 %uint_0 %25 %uint_4 %uint_1
1189+
%35 = OpExtInst %void %1 DebugExpression
1190+
%39 = OpExtInst %void %1 DebugFunction %38 %6 %26 %uint_7 %uint_0 %28 %38 %uint_3 %uint_7
1191+
%uint_5 = OpConstant %uint 5
1192+
%int = OpTypeInt 32 1
1193+
%54 = OpExtInst %void %1 DebugTypeBasic %53 %uint_32 %uint_4 %uint_0
1194+
%_ptr_Function_int = OpTypePointer Function %int
1195+
%56 = OpExtInst %void %1 DebugTypePointer %54 %uint_7 %uint_0
1196+
%uint_8 = OpConstant %uint 8
1197+
%58 = OpExtInst %void %1 DebugLocalVariable %33 %54 %26 %uint_8 %uint_0 %39 %uint_4
1198+
%int_0 = OpConstant %int 0
1199+
%uint_9 = OpConstant %uint 9
1200+
%64 = OpExtInst %void %1 DebugLocalVariable %65 %9 %26 %uint_9 %uint_0 %39 %uint_4
1201+
%uint_10 = OpConstant %uint 10
1202+
%main = OpFunction %void None %5
1203+
%15 = OpLabel
1204+
%a_0 = OpVariable %_ptr_Function_int Function
1205+
%b = OpVariable %_ptr_Function_uint Function
1206+
%param = OpVariable %_ptr_Function_uint Function
1207+
%50 = OpExtInst %void %1 DebugScope %39
1208+
%51 = OpExtInst %void %1 DebugLine %26 %uint_7 %uint_7 %uint_0 %uint_0
1209+
%49 = OpExtInst %void %1 DebugFunctionDefinition %39 %main
1210+
%61 = OpExtInst %void %1 DebugLine %26 %uint_8 %uint_8 %uint_0 %uint_0
1211+
%60 = OpExtInst %void %1 DebugDeclare %58 %a_0 %35
1212+
OpStore %a_0 %int_0
1213+
%68 = OpExtInst %void %1 DebugLine %26 %uint_9 %uint_9 %uint_0 %uint_0
1214+
%67 = OpExtInst %void %1 DebugDeclare %64 %b %35
1215+
%69 = OpLoad %int %a_0
1216+
%70 = OpBitcast %uint %69
1217+
OpStore %param %70
1218+
%72 = OpFunctionCall %uint %foo_u1_ %param
1219+
OpStore %b %72
1220+
%73 = OpExtInst %void %1 DebugLine %26 %uint_10 %uint_10 %uint_0 %uint_0
1221+
OpReturn
1222+
OpFunctionEnd
1223+
%foo_u1_ = OpFunction %uint None %19
1224+
%a = OpFunctionParameter %_ptr_Function_int
1225+
%23 = OpLabel
1226+
%36 = OpExtInst %void %1 DebugScope %25
1227+
%37 = OpExtInst %void %1 DebugLine %26 %uint_3 %uint_3 %uint_0 %uint_0
1228+
%34 = OpExtInst %void %1 DebugDeclare %32 %a %35
1229+
%40 = OpExtInst %void %1 DebugFunctionDefinition %25 %foo_u1_
1230+
%42 = OpExtInst %void %1 DebugLine %26 %uint_4 %uint_4 %uint_0 %uint_0
1231+
%41 = OpLoad %uint %a
1232+
%43 = OpIMul %uint %41 %uint_4
1233+
OpReturnValue %43
1234+
OpFunctionEnd
1235+
)";
1236+
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
1237+
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
1238+
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"(--> a.comp:3:0
1239+
|
1240+
3 | uint foo(uint a) {
1241+
|)"));
1242+
}
1243+
9431244
} // namespace
9441245
} // namespace val
9451246
} // namespace spvtools

0 commit comments

Comments
 (0)