From 7ec6c7ed301f9985ef507553ae6b23da3b252146 Mon Sep 17 00:00:00 2001 From: gob Date: Wed, 17 Jan 2024 14:20:41 +0100 Subject: [PATCH 001/693] portability.h: deal with popen/pclose on win32 --- src/common/portability.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/portability.h b/src/common/portability.h index 722413a4c..33187f234 100644 --- a/src/common/portability.h +++ b/src/common/portability.h @@ -15,6 +15,8 @@ static_assert(__STDC_VERSION__ >= 201112L, "C11 support is required to build sha #define SHADY_UNUSED #define LARRAY(T, name, size) T* name = alloca(sizeof(T) * (size)) #define alloca _alloca + #define popen _popen + #define pclose _pclose #define SHADY_FALLTHROUGH // It's mid 2022, and this typedef is missing from // MSVC is not a real C11 compiler. From 7f300cf67859cfa7e9799b01862ef29a84429a3c Mon Sep 17 00:00:00 2001 From: gob Date: Wed, 17 Jan 2024 14:20:53 +0100 Subject: [PATCH 002/693] frontends/llvm: use LLVM-C target --- src/frontends/llvm/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/frontends/llvm/CMakeLists.txt b/src/frontends/llvm/CMakeLists.txt index 0e46cabd2..a349b3348 100644 --- a/src/frontends/llvm/CMakeLists.txt +++ b/src/frontends/llvm/CMakeLists.txt @@ -8,11 +8,11 @@ separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) add_definitions(${LLVM_DEFINITIONS_LIST}) target_compile_definitions(shady_fe_llvm PRIVATE "LLVM_VERSION_MAJOR=${LLVM_VERSION_MAJOR}") -if (TARGET LLVM) - message("LLVM shared library target exists, major version = ${LLVM_VERSION_MAJOR}") - target_link_libraries(shady_fe_llvm PRIVATE LLVM) +if (TARGET LLVM-C) + message("LLVM-C shared library target exists, major version = ${LLVM_VERSION_MAJOR}") + target_link_libraries(shady_fe_llvm PRIVATE LLVM-C) else () - message(FATAL_ERROR "Failed to find LLVM target, but found LLVM module earlier") + message(FATAL_ERROR "Failed to find LLVM-C target, but found LLVM module earlier") endif() target_link_libraries(shady_fe_llvm PRIVATE api common shady) From 06822e46538f2f5f8aa1a808f92fb1d063bd6572 Mon Sep 17 00:00:00 2001 From: gob Date: Wed, 17 Jan 2024 14:34:14 +0100 Subject: [PATCH 003/693] fix vcc include paths when testing on multi-config targets like MSVC --- src/driver/vcc.c | 13 ++++++++++++- test/vcc/CMakeLists.txt | 20 +++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/driver/vcc.c b/src/driver/vcc.c index 9fe8522ee..881d6341b 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -13,6 +13,7 @@ typedef struct { char* tmp_filename; bool delete_tmp_file; + char* include_path; } VccOptions; static void cli_parse_vcc_args(VccOptions* options, int* pargc, char** argv) { @@ -26,6 +27,13 @@ static void cli_parse_vcc_args(VccOptions* options, int* pargc, char** argv) { options->delete_tmp_file = false; options->tmp_filename = "vcc_tmp.ll"; continue; + } else if (strcmp(argv[i], "--vcc-include-path") == 0) { + argv[i] = NULL; + i++; + if (i == argc) + error("Missing subgroup size name"); + options->include_path = argv[i]; + continue; } } @@ -81,7 +89,10 @@ int main(int argc, char** argv) { growy_append_string(g, "clang"); char* self_path = get_executable_location(); char* working_dir = strip_path(self_path); - growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s/../share/vcc/include/\" -D__SHADY__=1", working_dir); + if (!vcc_options.include_path) { + vcc_options.include_path = format_string_interned(arena, "%s/../share/vcc/include/", working_dir); + } + growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options.include_path); free(working_dir); free(self_path); growy_append_formatted(g, " -o %s", vcc_options.tmp_filename); diff --git a/test/vcc/CMakeLists.txt b/test/vcc/CMakeLists.txt index a0af7c595..335dfdf3d 100644 --- a/test/vcc/CMakeLists.txt +++ b/test/vcc/CMakeLists.txt @@ -1,18 +1,20 @@ list(APPEND VCC_SIMPLE_TESTS empty.c) list(APPEND VCC_SIMPLE_TESTS address_spaces.c) +set(VCC_TEST_ARGS --vcc-include-path "${PROJECT_BINARY_DIR}/share/vcc/include/") + foreach(T IN LISTS VCC_SIMPLE_TESTS) - add_test(NAME "test/vcc/${T}" COMMAND vcc ${PROJECT_SOURCE_DIR}/test/vcc/${T}) + add_test(NAME "test/vcc/${T}" COMMAND vcc ${PROJECT_SOURCE_DIR}/test/vcc/${T} ${VCC_TEST_ARGS}) endforeach() -spv_outputting_test(NAME test/vcc/branch.c COMPILER vcc EXTRA_ARGS) -spv_outputting_test(NAME test/vcc/loop.c COMPILER vcc EXTRA_ARGS) -spv_outputting_test(NAME test/vcc/goto.c COMPILER vcc EXTRA_ARGS) +spv_outputting_test(NAME test/vcc/branch.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) +spv_outputting_test(NAME test/vcc/loop.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) +spv_outputting_test(NAME test/vcc/goto.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) -spv_outputting_test(NAME test/vcc/vec_swizzle.c COMPILER vcc EXTRA_ARGS --entry-point test --no-dynamic-scheduling --execution-model Fragment) +spv_outputting_test(NAME test/vcc/vec_swizzle.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point test --no-dynamic-scheduling --execution-model Fragment) -spv_outputting_test(NAME test/vcc/empty.comp.c COMPILER vcc EXTRA_ARGS --entry-point main) +spv_outputting_test(NAME test/vcc/empty.comp.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main) -spv_outputting_test(NAME test/vcc/simple.frag.c COMPILER vcc EXTRA_ARGS --entry-point main --no-dynamic-scheduling --execution-model Fragment) -spv_outputting_test(NAME test/vcc/checkerboard.frag.c COMPILER vcc EXTRA_ARGS --entry-point main --no-dynamic-scheduling --execution-model Fragment) -spv_outputting_test(NAME test/vcc/textured.frag.c COMPILER vcc EXTRA_ARGS --entry-point main --no-dynamic-scheduling --execution-model Fragment) +spv_outputting_test(NAME test/vcc/simple.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --no-dynamic-scheduling --execution-model Fragment) +spv_outputting_test(NAME test/vcc/checkerboard.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --no-dynamic-scheduling --execution-model Fragment) +spv_outputting_test(NAME test/vcc/textured.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --no-dynamic-scheduling --execution-model Fragment) From 46fa972ef77d68f298c9235f8a9f5330dab599eb Mon Sep 17 00:00:00 2001 From: gob Date: Wed, 17 Jan 2024 14:42:39 +0100 Subject: [PATCH 004/693] win32: dirty fix for DLL hell --- src/driver/CMakeLists.txt | 5 +++++ src/shady/generator/CMakeLists.txt | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index 8539478f8..ef9f53817 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -18,4 +18,9 @@ if (TARGET shady_fe_llvm) add_executable(vcc vcc.c) target_link_libraries(vcc PRIVATE driver api common) install(TARGETS vcc EXPORT shady_export_set) + + add_custom_command(TARGET vcc POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS + ) endif () diff --git a/src/shady/generator/CMakeLists.txt b/src/shady/generator/CMakeLists.txt index d5837075d..e2e1ede1c 100644 --- a/src/shady/generator/CMakeLists.txt +++ b/src/shady/generator/CMakeLists.txt @@ -16,4 +16,11 @@ function(add_generated_file) set(F_TARGET_NAME generate_${F_FILE_NAME}) endif () add_custom_target(${F_TARGET_NAME} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME}) + + # This hacky job is required for being able to run built targets in-place when generating the code + # This is also required for the various drivers but since they're built in the same directory it will work for now + add_custom_command(TARGET ${GENERATOR_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS + ) endfunction() From aa92c82d33269be0726d63d2d2dc7dd36869169d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 17 Jan 2024 16:38:29 +0100 Subject: [PATCH 005/693] gate dll hell behind WIN32 --- src/driver/CMakeLists.txt | 10 ++++++---- src/shady/generator/CMakeLists.txt | 11 +++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index ef9f53817..50a495a9e 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -19,8 +19,10 @@ if (TARGET shady_fe_llvm) target_link_libraries(vcc PRIVATE driver api common) install(TARGETS vcc EXPORT shady_export_set) - add_custom_command(TARGET vcc POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy -t $ $ - COMMAND_EXPAND_LISTS - ) + if (WIN32) + add_custom_command(TARGET vcc POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS + ) + endif () endif () diff --git a/src/shady/generator/CMakeLists.txt b/src/shady/generator/CMakeLists.txt index e2e1ede1c..8d3a61f07 100644 --- a/src/shady/generator/CMakeLists.txt +++ b/src/shady/generator/CMakeLists.txt @@ -19,8 +19,11 @@ function(add_generated_file) # This hacky job is required for being able to run built targets in-place when generating the code # This is also required for the various drivers but since they're built in the same directory it will work for now - add_custom_command(TARGET ${GENERATOR_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy -t $ $ - COMMAND_EXPAND_LISTS - ) + if (WIN32) + message("copying DLLs: ${TARGET_DLLS}") + add_custom_command(TARGET ${GENERATOR_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS + ) + endif () endfunction() From 50aae657f07dc1b407f185d2e17d3c6bd32aca56 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 17 Jan 2024 16:38:42 +0100 Subject: [PATCH 006/693] fall back to 'LLVM' target if LLVM-C is unavailable --- src/frontends/llvm/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontends/llvm/CMakeLists.txt b/src/frontends/llvm/CMakeLists.txt index a349b3348..868b22e02 100644 --- a/src/frontends/llvm/CMakeLists.txt +++ b/src/frontends/llvm/CMakeLists.txt @@ -11,8 +11,11 @@ target_compile_definitions(shady_fe_llvm PRIVATE "LLVM_VERSION_MAJOR=${LLVM_VERS if (TARGET LLVM-C) message("LLVM-C shared library target exists, major version = ${LLVM_VERSION_MAJOR}") target_link_libraries(shady_fe_llvm PRIVATE LLVM-C) +elseif (TARGET LLVM) + message("LLVM shared library target exists, major version = ${LLVM_VERSION_MAJOR}") + target_link_libraries(shady_fe_llvm PRIVATE LLVM) else () - message(FATAL_ERROR "Failed to find LLVM-C target, but found LLVM module earlier") +message(FATAL_ERROR "Failed to find LLVM-C target, but found LLVM module earlier") endif() target_link_libraries(shady_fe_llvm PRIVATE api common shady) From e47a02aa8bb3ac9bf381b9c1f14c871452cf4a73 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 17:36:00 +0100 Subject: [PATCH 007/693] add some more use2def code --- include/shady/ir.h | 2 ++ src/shady/analysis/leak.c | 21 ++++++++++++++++++++- src/shady/analysis/leak.h | 5 ++++- src/shady/node.c | 23 +++++++++++++++-------- src/shady/passes/lcssa.c | 2 +- 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index d8c616627..7e728d6d1 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -156,6 +156,8 @@ typedef struct { NodeResolveConfig default_node_resolve_config(); const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config); +/// Resolves a variable to the instruction that produces its value (if any) +const Node* get_var_def(Variable var); const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config); //////////////////////////////// Constructors //////////////////////////////// diff --git a/src/shady/analysis/leak.c b/src/shady/analysis/leak.c index 2c8dea13a..c62f249ad 100644 --- a/src/shady/analysis/leak.c +++ b/src/shady/analysis/leak.c @@ -20,7 +20,7 @@ void visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, Visit } } -const Node* get_binding_abstraction(const UsesMap* map, const Node* var) { +const Node* get_var_binding_abstraction(const UsesMap* map, const Node* var) { assert(var->tag == Variable_TAG); const Use* use = get_first_use(map, var); assert(use); @@ -35,6 +35,25 @@ const Node* get_binding_abstraction(const UsesMap* map, const Node* var) { return binding_use->user; } +const Node* get_case_user(const UsesMap* map, const Node* cas) { + const Use* use = get_first_use(map, cas); + if (!use) + return NULL; + assert(!use->next_use); + assert(use->operand_class == NcCase); + return use->user; +} + +const Node* get_var_instruction(const UsesMap* map, const Node* var) { + const Node* abs = get_var_binding_abstraction(map, var); + if (!abs || abs->tag != Case_TAG) + return NULL; // variable is not bound by a case + const Node* case_user = get_case_user(map, abs); + if (!case_user || case_user->tag != Let_TAG) + return NULL; + return case_user->payload.let.instruction; +} + bool is_control_static(const UsesMap* map, const Node* control) { assert(control->tag == Control_TAG); const Node* inside = control->payload.control.inside; diff --git a/src/shady/analysis/leak.h b/src/shady/analysis/leak.h index 21ffe7656..c232c7a42 100644 --- a/src/shady/analysis/leak.h +++ b/src/shady/analysis/leak.h @@ -9,7 +9,10 @@ typedef void (VisitEnclosingAbsCallback)(void*, const Use*); void visit_enclosing_abstractions(UsesMap*, const Node*, void* uptr, VisitEnclosingAbsCallback fn); -const Node* get_binding_abstraction(const UsesMap*, const Node* var); +const Node* get_var_binding_abstraction(const UsesMap*, const Node* var); +const Node* get_case_user(const UsesMap*, const Node* cas); + +const Node* get_var_instruction(const UsesMap*, const Node* var); bool is_control_static(const UsesMap*, const Node* control); diff --git a/src/shady/node.c b/src/shady/node.c index 2ac77cf77..41d06c94b 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -119,6 +119,18 @@ NodeResolveConfig default_node_resolve_config() { }; } +const Node* get_var_def(Variable var) { + if (var.pindex != 0) + return NULL; + const Node* abs = var.abs; + if (!abs || abs->tag != Case_TAG) + return NULL; + const Node* user = abs->payload.case_.structured_construct; + if (user->tag != Let_TAG) + return NULL; + return user->payload.let.instruction; +} + const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config) { while (node) { switch (node->tag) { @@ -129,15 +141,10 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi node = node->payload.ref_decl.decl; continue; case Variable_TAG: { - if (node->payload.var.pindex != 0) - break; - const Node* abs = node->payload.var.abs; - if (!abs || abs->tag != Case_TAG) - break; - const Node* user = abs->payload.case_.structured_construct; - if (user->tag != Let_TAG) + const Node* def = get_var_def(node->payload.var); + if (!def) break; - node = user->payload.let.instruction; + node = def; continue; } case PrimOp_TAG: { diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 4a5b7f968..9d3492b2f 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -58,7 +58,7 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No struct List* fvs = compute_free_variables(ctx->scope, old); for (size_t i = 0; i < entries_count_list(fvs); i++) { const Node* fv = read_list(const Node*, fvs)[i]; - const Node* defining_abs = get_binding_abstraction(ctx->scope_uses, fv); + const Node* defining_abs = get_var_binding_abstraction(ctx->scope_uses, fv); const CFNode* defining_cf_node = scope_lookup(ctx->scope, defining_abs); assert(defining_cf_node); const LTNode* defining_loop = get_loop(looptree_lookup(ctx->loop_tree, defining_cf_node->node)); From fd3df2ee00ed3e69580dd7ac09ff61c0fcb5bff7 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 17:36:18 +0100 Subject: [PATCH 008/693] fix concat_nodes --- src/shady/ir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/ir.c b/src/shady/ir.c index f49260c40..de11f036e 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -146,7 +146,7 @@ Nodes concat_nodes(IrArena* arena, Nodes a, Nodes b) { Nodes change_node_at_index(IrArena* arena, Nodes old, size_t i, const Node* n) { LARRAY(const Node*, tmp, old.count); for (size_t j = 0; j < old.count; j++) - tmp[j] = old.nodes[i]; + tmp[j] = old.nodes[j]; tmp[i] = n; return nodes(arena, old.count, tmp); } From 3f763642a119d08968c5c81d0cb907855b51b5e6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 18:20:21 +0100 Subject: [PATCH 009/693] get_pointee_type will decay unsized array types now --- src/shady/type_helpers.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index a4fb84720..78270883e 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -43,6 +43,9 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { assert(type->tag == PtrType_TAG); uniform &= is_addr_space_uniform(arena, type->payload.ptr_type.address_space); type = type->payload.ptr_type.pointed_type; + while (type->tag == ArrType_TAG && !type->payload.arr_type.size) + type = type->payload.arr_type.element_type; + if (qualified) type = qualified_type(arena, (QualifiedType) { .type = type, From 4bd80f7cce2bca17a9adb8d55e738076d38164a1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 18:20:57 +0100 Subject: [PATCH 010/693] fix mem2reg regression --- src/shady/passes/opt_mem2reg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 8ba377177..869f7938e 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -368,12 +368,12 @@ static const Node* process(Context* ctx, const Node* old) { const Type* known_value_t = known_value->type; bool kv_u = deconstruct_qualified_type(&known_value_t); - const Type* load_result_t = ptr->type; + const Type* load_result_t = rewrite_node(&ctx->rewriter, ptr->type); bool lrt_u = deconstruct_qualified_type(&load_result_t); deconstruct_pointer_type(&load_result_t); assert(!lrt_u || kv_u); if (is_reinterpret_cast_legal(load_result_t, known_value_t)) - return prim_op_helper(a, reinterpret_op, singleton(rewrite_node(&ctx->rewriter, load_result_t)), singleton(known_value)); + return prim_op_helper(a, reinterpret_op, singleton(load_result_t), singleton(known_value)); } const Node* other_ptr = get_known_address(&ctx->rewriter, k); if (other_ptr && ptr != other_ptr) { @@ -530,7 +530,7 @@ Module* opt_mem2reg(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = src; - for (size_t round = 0; round < 2; round++) { + for (size_t round = 0; round < 5; round++) { dst = new_module(a, get_module_name(src)); Context ctx = { From 66860831312d0c1ee73db0aaf06ae5e49bb564a2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 18:24:49 +0100 Subject: [PATCH 011/693] mem2reg: enable following conversions --- src/shady/passes/opt_mem2reg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 869f7938e..f16146aab 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -137,6 +137,7 @@ static void visit_ptr_uses(const Node* ptr_value, PtrSourceKnowledge* k, const U k->leaks = true; continue; } + case convert_op: case reinterpret_op: { debugv_print("mem2reg leak analysis: following reinterpret instr: "); log_node(DEBUGV, use->user); @@ -144,8 +145,7 @@ static void visit_ptr_uses(const Node* ptr_value, PtrSourceKnowledge* k, const U visit_ptr_uses(use->user, k, map); continue; } - case lea_op: - case convert_op: { + case lea_op: { //TODO: follow where those derived pointers are used and establish whether they leak themselves k->leaks = true; continue; From 7a67680662b1140ea5022d382a3056e178280fd6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 18:33:59 +0100 Subject: [PATCH 012/693] be more specific about where conversion is OK when following mem2reg --- src/shady/passes/opt_mem2reg.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index f16146aab..81a89b3e2 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -137,7 +137,6 @@ static void visit_ptr_uses(const Node* ptr_value, PtrSourceKnowledge* k, const U k->leaks = true; continue; } - case convert_op: case reinterpret_op: { debugv_print("mem2reg leak analysis: following reinterpret instr: "); log_node(DEBUGV, use->user); @@ -145,6 +144,19 @@ static void visit_ptr_uses(const Node* ptr_value, PtrSourceKnowledge* k, const U visit_ptr_uses(use->user, k, map); continue; } + case convert_op: { + if (first(payload.type_arguments)->tag == PtrType_TAG) { + // this is a ptr-ptr conversion, which means it's a Generic-non generic conversion + // these are fine, just track them + debugv_print("mem2reg leak analysis: following conversion instr: "); + log_node(DEBUGV, use->user); + debugv_print(".\n"); + visit_ptr_uses(use->user, k, map); + continue; + } + k->leaks = true; + continue; + } case lea_op: { //TODO: follow where those derived pointers are used and establish whether they leak themselves k->leaks = true; From 0fa506cef74b25491129e803274a4abb24c06b35 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 21:57:58 +0100 Subject: [PATCH 013/693] vcc: add a special flag to just dump LLVM IR and bail out --- src/driver/vcc.c | 59 +++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/src/driver/vcc.c b/src/driver/vcc.c index 881d6341b..1b78cf173 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -14,6 +14,7 @@ typedef struct { char* tmp_filename; bool delete_tmp_file; char* include_path; + bool only_run_clang; } VccOptions; static void cli_parse_vcc_args(VccOptions* options, int* pargc, char** argv) { @@ -34,6 +35,10 @@ static void cli_parse_vcc_args(VccOptions* options, int* pargc, char** argv) { error("Missing subgroup size name"); options->include_path = argv[i]; continue; + } else if (strcmp(argv[i], "--only-run-clang") == 0) { + argv[i] = NULL; + options->only_run_clang = true; + continue; } } @@ -71,19 +76,6 @@ int main(int argc, char** argv) { error("clang not present in path or otherwise broken (retval=%d)", clang_retval); size_t num_source_files = entries_count_list(args.input_filenames); - if (!vcc_options.tmp_filename) { - vcc_options.tmp_filename = alloca(33); - vcc_options.tmp_filename[32] = '\0'; - uint32_t hash = 0; - for (size_t i = 0; i < num_source_files; i++) { - String filename = read_list(const char*, args.input_filenames)[i]; - hash ^= hash_murmur(filename, strlen(filename)); - } - srand(hash); - for (size_t i = 0; i < 32; i++) { - vcc_options.tmp_filename[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % (10 + 26 * 2)]; - } - } Growy* g = new_growy(); growy_append_string(g, "clang"); @@ -95,7 +87,25 @@ int main(int argc, char** argv) { growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options.include_path); free(working_dir); free(self_path); - growy_append_formatted(g, " -o %s", vcc_options.tmp_filename); + + if (vcc_options.only_run_clang) + growy_append_formatted(g, " -o %s", args.output_filename); + else { + if (!vcc_options.tmp_filename) { + vcc_options.tmp_filename = alloca(33); + vcc_options.tmp_filename[32] = '\0'; + uint32_t hash = 0; + for (size_t i = 0; i < num_source_files; i++) { + String filename = read_list(const char*, args.input_filenames)[i]; + hash ^= hash_murmur(filename, strlen(filename)); + } + srand(hash); + for (size_t i = 0; i < 32; i++) { + vcc_options.tmp_filename[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % (10 + 26 * 2)]; + } + } + growy_append_formatted(g, " -o %s", vcc_options.tmp_filename); + } for (size_t i = 0; i < num_source_files; i++) { String filename = read_list(const char*, args.input_filenames)[i]; @@ -129,17 +139,20 @@ int main(int argc, char** argv) { if (clang_returned) exit(ClangInvocationFailed); - size_t len; - char* llvm_ir; - if (!read_file(vcc_options.tmp_filename, &len, &llvm_ir)) - exit(InputFileIOError); - driver_load_source_file(SrcLLVM, len, llvm_ir, mod); - free(llvm_ir); + if (!vcc_options.only_run_clang) { + size_t len; + char* llvm_ir; + if (!read_file(vcc_options.tmp_filename, &len, &llvm_ir)) + exit(InputFileIOError); + driver_load_source_file(SrcLLVM, len, llvm_ir, mod); + free(llvm_ir); - if (vcc_options.delete_tmp_file) - remove(vcc_options.tmp_filename); + if (vcc_options.delete_tmp_file) + remove(vcc_options.tmp_filename); + + driver_compile(&args, mod); + } - driver_compile(&args, mod); info_print("Done\n"); destroy_ir_arena(arena); From c2c4720076fb700f0b8f941e17cad0e2415d2552 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 21:58:24 +0100 Subject: [PATCH 014/693] l2s: force entry point args to be uniform --- src/frontends/llvm/l2s_postprocess.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 241448b8e..9987cc24e 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -75,12 +75,13 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, fn_ctx.old_fn_or_bb = node; Controls controls; initialize_controls(ctx, &controls, node); - Node* decl = (Node*) recreate_node_identity(&fn_ctx.rewriter, node); - Nodes annotations = decl->payload.fun.annotations; + Nodes new_params = recreate_variables(&fn_ctx.rewriter, node->payload.fun.params); + Nodes old_annotations = node->payload.fun.annotations; ParsedAnnotation* an = find_annotation(ctx->p, node); + Op primop_intrinsic = PRIMOPS_COUNT; while (an) { if (strcmp(get_annotation_name(an->payload), "PrimOpIntrinsic") == 0) { - assert(!decl->payload.fun.body); + assert(!node->payload.fun.body); Op op; size_t i; for (i = 0; i < PRIMOPS_COUNT; i++) { @@ -90,15 +91,24 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } } assert(i != PRIMOPS_COUNT); - decl->payload.fun.body = fn_ret(a, (Return) { - .args = singleton(prim_op_helper(a, op, empty(a), get_abstraction_params(decl))) - }); + primop_intrinsic = op; + } else if (strcmp(get_annotation_name(an->payload), "EntryPoint") == 0) { + for (size_t i = 0; i < new_params.count; i++) + new_params = change_node_at_index(a, new_params, i, var(a, qualified_type_helper(get_unqualified_type(new_params.nodes[i]->payload.var.type), true), new_params.nodes[i]->payload.var.name)); } - annotations = append_nodes(a, annotations, an->payload); + old_annotations = append_nodes(a, old_annotations, an->payload); an = an->next; } - decl->payload.fun.annotations = annotations; - // decl->payload.fun.body = wrap_in_controls(ctx, &controls, decl->payload.fun.body); + register_processed_list(&fn_ctx.rewriter, node->payload.fun.params, new_params); + Nodes new_annotations = rewrite_nodes(&fn_ctx.rewriter, old_annotations); + Node* decl = function(ctx->rewriter.dst_module, new_params, get_abstraction_name(node), new_annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); + register_processed(&ctx->rewriter, node, decl); + if (primop_intrinsic != PRIMOPS_COUNT) { + decl->payload.fun.body = fn_ret(a, (Return) { + .args = singleton(prim_op_helper(a, primop_intrinsic, empty(a), get_abstraction_params(decl))) + }); + } else + decl->payload.fun.body = rewrite_node(&fn_ctx.rewriter, node->payload.fun.body); destroy_scope(fn_ctx.curr_scope); return decl; } From 55d206de516706a7be106931f70e288e25084bf4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jan 2024 21:58:36 +0100 Subject: [PATCH 015/693] shady.h: added global addrspace and globalinvocationid builtin --- vcc-std/include/shady.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index 0e81f9788..d938d9be3 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -22,6 +22,7 @@ namespace vcc { #define output __attribute__((address_space(390))) #define uniform __attribute__((annotate("shady::uniform"))) #define push_constant __attribute__((address_space(392))) +#define global __attribute__((address_space(1))) #define private __attribute__((address_space(5))) #define private_logical __attribute__((address_space(385))) @@ -60,6 +61,10 @@ __attribute__((annotate("shady::builtin::WorkgroupSize"))) __attribute__((address_space(389))) uvec3 gl_WorkGroupSize; +__attribute__((annotate("shady::builtin::GlobalInvocationId"))) +__attribute__((address_space(389))) +uvec3 gl_GlobalInvocationID; + #if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) } #endif From ee540c4ca261da7f757488767c20fa6729652985 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 19 Jan 2024 13:35:04 +0100 Subject: [PATCH 016/693] added vec wrapper classes --- vcc-std/include/shady.h | 24 ++---- vcc-std/include/shady_vec.h | 141 ++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 17 deletions(-) create mode 100644 vcc-std/include/shady_vec.h diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index d938d9be3..a5a7c20ec 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -26,32 +26,22 @@ namespace vcc { #define private __attribute__((address_space(5))) #define private_logical __attribute__((address_space(385))) -typedef float vec4 __attribute__((ext_vector_type(4))); -typedef float vec3 __attribute__((ext_vector_type(3))); -typedef float vec2 __attribute__((ext_vector_type(2))); - -typedef int ivec4 __attribute__((ext_vector_type(4))); -typedef int ivec3 __attribute__((ext_vector_type(3))); -typedef int ivec2 __attribute__((ext_vector_type(2))); - -typedef unsigned uvec4 __attribute__((ext_vector_type(4))); -typedef unsigned uvec3 __attribute__((ext_vector_type(3))); -typedef unsigned uvec2 __attribute__((ext_vector_type(2))); +#include "shady_vec.h" typedef struct __shady_builtin_sampler2D {} sampler2D; -vec4 texture2D(const sampler2D, vec2) __asm__("shady::prim_op::sample_texture"); +vec4 texture2D(const sampler2D, native_vec2) __asm__("shady::prim_op::sample_texture"); // builtins __attribute__((annotate("shady::builtin::FragCoord"))) -input vec4 gl_FragCoord; +input native_vec4 gl_FragCoord; __attribute__((annotate("shady::builtin::Position"))) -output vec4 gl_Position; +output native_vec4 gl_Position; __attribute__((annotate("shady::builtin::WorkgroupId"))) __attribute__((address_space(389))) -uvec3 gl_WorkGroupID; +native_uvec3 gl_WorkGroupID; __attribute__((annotate("shady::builtin::VertexIndex"))) __attribute__((address_space(389))) @@ -59,11 +49,11 @@ input int gl_VertexIndex; __attribute__((annotate("shady::builtin::WorkgroupSize"))) __attribute__((address_space(389))) -uvec3 gl_WorkGroupSize; +native_uvec3 gl_WorkGroupSize; __attribute__((annotate("shady::builtin::GlobalInvocationId"))) __attribute__((address_space(389))) -uvec3 gl_GlobalInvocationID; +native_uvec3 gl_GlobalInvocationID; #if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) } diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h new file mode 100644 index 000000000..fed12e018 --- /dev/null +++ b/vcc-std/include/shady_vec.h @@ -0,0 +1,141 @@ +#if defined(__cplusplus) & !defined(SHADY_CPP_NO_WRAPPER_CLASSES) +#define SHADY_ENABLE_WRAPPER_CLASSES +#endif + +typedef float native_vec4 __attribute__((ext_vector_type(4))); +typedef float native_vec3 __attribute__((ext_vector_type(3))); +typedef float native_vec2 __attribute__((ext_vector_type(2))); + +typedef int native_ivec4 __attribute__((ext_vector_type(4))); +typedef int native_ivec3 __attribute__((ext_vector_type(3))); +typedef int native_ivec2 __attribute__((ext_vector_type(2))); + +typedef unsigned native_uvec4 __attribute__((ext_vector_type(4))); +typedef unsigned native_uvec3 __attribute__((ext_vector_type(3))); +typedef unsigned native_uvec2 __attribute__((ext_vector_type(2))); + +#ifdef SHADY_ENABLE_WRAPPER_CLASSES +template +struct vec4_impl { + using This = vec4_impl; + float x, y, z, w; + + vec4_impl() {} + vec4_impl(T scalar) : x(scalar), y(scalar), z(scalar), w(scalar) {} + vec4_impl(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} + vec4_impl(Native n) : x(n.x), y(n.y), z(n.z), w(n.w) {} + + operator Native() { + return (Native) { x, y, z, w }; + } + + This operator +(This other) { + return This(x + other.x, y + other.y, z + other.z, w + other.w); + } + This operator -(This other) { + return This(x - other.x, y - other.y, z - other.z, w - other.w); + } + This operator *(This other) { + return This(x * other.x, y * other.y, z * other.z, w * other.w); + } + This operator /(This other) { + return This(x / other.x, y / other.y, z / other.z, w / other.w); + } + This operator *(T s) { + return This(x * s, y * s, z * s, w * s); + } + This operator /(T s) { + return This(x / s, y / s, z / s, z / s); + } +}; + +template +struct vec3_impl { + using This = vec3_impl; + float x, y, z; + + vec3_impl() {} + vec3_impl(T scalar) : x(scalar), y(scalar), z(scalar) {} + vec3_impl(T x, T y, T z) : x(x), y(y), z(z) {} + vec3_impl(Native n) : x(n.x), y(n.y), z(n.z) {} + + operator Native() { + return (Native) { x, y, z }; + } + + This operator +(This other) { + return This(x + other.x, y + other.y, z + other.z); + } + This operator -(This other) { + return This(x - other.x, y - other.y, z - other.z); + } + This operator *(This other) { + return This(x * other.x, y * other.y, z * other.z); + } + This operator /(This other) { + return This(x / other.x, y / other.y, z / other.z); + } + This operator *(T s) { + return This(x * s, y * s, z * s); + } + This operator /(T s) { + return This(x / s, y / s, z / s); + } +}; + +template +struct vec2_impl { + using This = vec2_impl; + float x, y; + + vec2_impl() {} + vec2_impl(T scalar) : x(scalar), y(scalar) {} + vec2_impl(T x, T y) : x(x), y(y) {} + vec2_impl(Native n) : x(n.x), y(n.y) {} + + operator Native() { + return (Native) { x, y }; + } + + This operator +(This other) { + return This(x + other.x, y + other.y); + } + This operator -(This other) { + return This(x - other.x, y - other.y); + } + This operator *(This other) { + return This(x * other.x, y * other.y); + } + This operator /(This other) { + return This(x / other.x, y / other.y); + } + This operator *(T s) { + return This(x * s, y * s); + } + This operator /(T s) { + return This(x / s, y / s); + } +}; + +typedef vec4_impl vec4; +typedef vec4_impl uvec4; +typedef vec4_impl ivec4; + +typedef vec3_impl vec3; +typedef vec3_impl uvec3; +typedef vec3_impl ivec3; + +typedef vec2_impl vec2; +typedef vec2_impl uvec2; +typedef vec2_impl ivec2; +#else +typedef native_vec4 vec4; +typedef native_vec3 vec3; +typedef native_vec2 vec2; +typedef native_ivec4 ivec4; +typedef native_ivec3 ivec3; +typedef native_ivec2 ivec2; +typedef native_uvec4 uvec4; +typedef native_uvec3 uvec3; +typedef native_uvec2 uvec2; +#endif \ No newline at end of file From d3e6cc07dd7b27eaaf3c5326057123906cbf476e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 11:36:32 +0100 Subject: [PATCH 017/693] added more tests for mem2reg with conversions --- test/opt/mem2reg3.slim | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/opt/mem2reg3.slim b/test/opt/mem2reg3.slim index 2ace39f60..c0b0aaf6d 100644 --- a/test/opt/mem2reg3.slim +++ b/test/opt/mem2reg3.slim @@ -2,3 +2,16 @@ fn f varying f32(varying i32 x) { var i32 i = 0; return (*(reinterpret[ptr private f32](&i))); } + +fn g varying i32(varying i32 x) { + var i32 i = 0; + return (*(convert[ptr generic i32](&i))); +} + +fn h varying f32(varying i32 x) { + var i32 i = 0; + val p = &i; + val p1 = (reinterpret[ptr private f32](&i)); + val p2 = convert[ptr generic f32](p1); + return (*p2); +} From 411945ac6c4c6c4c59f6882ba95c8e5fc0a95f70 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 17:44:00 +0100 Subject: [PATCH 018/693] let cleanup do eta-reduction for bbs --- src/shady/passes/cleanup.c | 36 ++++++++++++++++++++++++++++ src/shady/passes/lower_alloca.c | 0 src/shady/passes/opt_demote_alloca.c | 0 src/shady/rewrite.c | 6 +++++ src/shady/rewrite.h | 1 + 5 files changed, 43 insertions(+) create mode 100644 src/shady/passes/lower_alloca.c create mode 100644 src/shady/passes/opt_demote_alloca.c diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 03e1bbc79..1102aa2c4 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -12,7 +12,24 @@ typedef struct { bool* todo; } Context; +static size_t count_calls(const UsesMap* map, const Node* bb) { + size_t count = 0; + const Use* use = get_first_use(map, bb); + for (;use; use = use->next_use) { + if (use->user->tag == Jump_TAG) { + const Use* jump_use = get_first_use(map, use->user); + for (; jump_use; jump_use = jump_use->next_use) { + if (jump_use->operand_class == NcJump) + return SIZE_MAX; // you can never inline conditional jumps + count++; + } + } + } + return count; +} + const Node* process(Context* ctx, const Node* old) { + Rewriter* r = &ctx->rewriter; if (old->tag == Function_TAG || old->tag == Constant_TAG) { Context c = *ctx; c.map = create_uses_map(old, NcType | NcDeclaration); @@ -51,6 +68,25 @@ const Node* process(Context* ctx, const Node* old) { } break; } + case BasicBlock_TAG: { + size_t uses = count_calls(ctx->map, old); + if (uses <= 1) { + log_string(DEBUGV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name(old), uses); + return NULL; + } + break; + } + case Jump_TAG: { + const Node* otarget = old->payload.jump.target; + const Node* ntarget = rewrite_node(r, otarget); + if (!ntarget) { + // it's been inlined away! just steal the body + Nodes nargs = rewrite_nodes(r, old->payload.jump.args); + register_processed_list(r, get_abstraction_params(otarget), nargs); + return rewrite_node(r, get_abstraction_body(otarget)); + } + break; + } default: break; } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c new file mode 100644 index 000000000..e69de29bb diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c new file mode 100644 index 000000000..e69de29bb diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index c11c7024e..e99c06286 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -214,6 +214,12 @@ Nodes recreate_variables(Rewriter* rewriter, Nodes old) { return nodes(rewriter->dst_arena, old.count, nvars); } +Node* clone_bb_head(Rewriter* r, const Node* bb) { + assert(bb && bb->tag == BasicBlock_TAG); + Nodes nparams = recreate_variables(r, get_abstraction_params(bb)); + return basic_block(r->dst_arena, (Node*) bb->payload.basic_block.fn, nparams, get_abstraction_name(bb)); +} + Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { Node* new = NULL; switch (is_declaration(old)) { diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index 2ba43e86e..a98a3a69b 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -59,6 +59,7 @@ void recreate_decl_body_identity(Rewriter*, const Node*, Node*); /// Rewrites a variable under a new identity const Node* recreate_variable(Rewriter* rewriter, const Node* old); Nodes recreate_variables(Rewriter* rewriter, Nodes old); +Node* clone_bb_head(Rewriter*, const Node* bb); /// Looks up if the node was already processed const Node* search_processed(const Rewriter*, const Node*); From 9d9967b32756c8a41066014564f3c13af7f67ecc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 18:14:19 +0100 Subject: [PATCH 019/693] split setup_stack_frame and lower_alloca --- src/shady/CMakeLists.txt | 1 + src/shady/compile.c | 1 + src/shady/passes/lower_alloca.c | 173 ++++++++++++++++++++++++++ src/shady/passes/passes.h | 4 +- src/shady/passes/setup_stack_frames.c | 67 ---------- 5 files changed, 178 insertions(+), 68 deletions(-) diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 40fbfb908..6217640d5 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -58,6 +58,7 @@ set(SHADY_SOURCES passes/lift_indirect_targets.c passes/lcssa.c passes/lower_callf.c + passes/lower_alloca.c passes/lower_stack.c passes/lower_lea.c passes/lower_physical_ptrs.c diff --git a/src/shady/compile.c b/src/shady/compile.c index 2713aded2..ad3ae817e 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -113,6 +113,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_subgroup_ops) RUN_PASS(lower_stack) + RUN_PASS(lower_alloca) RUN_PASS(lower_lea) RUN_PASS(lower_generic_globals) RUN_PASS(lower_generic_ptrs) diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index e69de29bb..2f7a87dbc 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -0,0 +1,173 @@ +#include "passes.h" + +#include "log.h" +#include "portability.h" +#include "list.h" +#include "dict.h" +#include "util.h" + +#include "../rewrite.h" +#include "../visit.h" +#include "../type.h" +#include "../ir_private.h" +#include "../transform/ir_gen_helpers.h" + +#include + +typedef struct Context_ { + Rewriter rewriter; + bool disable_lowering; + + const CompilerConfig* config; + struct Dict* prepared_offsets; + const Node* entry_base_stack_ptr; + const Node* entry_stack_offset; + size_t num_slots; + const Node* frame_size; +} Context; + +typedef struct { + Visitor visitor; + Context* context; + BodyBuilder* bb; + Node* nom_t; + size_t num_slots; + struct List* members; + struct Dict* prepared_offsets; +} VContext; + +typedef struct { + size_t i; + const Node* offset; + const Type* type; + AddressSpace as; +} StackSlot; + +static void search_operand_for_alloca(VContext* vctx, const Node* node) { + IrArena* a = vctx->context->rewriter.dst_arena; + AddressSpace as; + + if (node->tag == PrimOp_TAG) { + switch (node->payload.prim_op.op) { + case alloca_op: as = AsPrivatePhysical; break; + case alloca_subgroup_op: as = AsSubgroupPhysical; break; + default: goto not_alloca; + } + + const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.prim_op.type_arguments.nodes[0]); + assert(is_data_type(element_type)); + const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, singleton(type_decl_ref_helper(a, vctx->nom_t)), singleton(int32_literal(a, entries_count_list(vctx->members)))); + append_list(const Type*, vctx->members, element_type); + + StackSlot slot = { vctx->num_slots, slot_offset, element_type, as }; + insert_dict(const Node*, StackSlot, vctx->prepared_offsets, node, slot); + + vctx->num_slots++; + + return; + } + + not_alloca: + visit_node_operands(&vctx->visitor, IGNORE_ABSTRACTIONS_MASK, node); +} + +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + +static const Node* process(Context* ctx, const Node* node) { + const Node* found = search_processed(&ctx->rewriter, node); + if (found) return found; + + IrArena* a = ctx->rewriter.dst_arena; + Module* m = ctx->rewriter.dst_module; + switch (node->tag) { + case Function_TAG: { + Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); + Context ctx2 = *ctx; + ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames"); + ctx2.prepared_offsets = new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); + + BodyBuilder* bb = begin_body(a); + if (!ctx2.disable_lowering) { + String tmp_name = format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun)); + ctx2.entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_pointer_op } ), (String []) { tmp_name })); + ctx2.entry_base_stack_ptr = gen_primop_ce(bb, get_stack_base_op, 0, NULL); + + Node* nom_t = nominal_type(m, empty(a), format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); + VContext vctx = { + .visitor = { + .visit_node_fn = (VisitNodeFn) search_operand_for_alloca, + }, + .context = &ctx2, + .bb = bb, + .nom_t = nom_t, + .num_slots = 0, + .members = new_list(const Node*), + .prepared_offsets = ctx2.prepared_offsets, + }; + if (node->payload.fun.body) { + search_operand_for_alloca(&vctx, node->payload.fun.body); + visit_function_rpo(&vctx.visitor, node); + } + vctx.nom_t->payload.nom_type.body = record_type(a, (RecordType) { + .members = nodes(a, vctx.num_slots, read_list(const Node*, vctx.members)), + .names = strings(a, 0, NULL), + .special = 0 + }); + destroy_list(vctx.members); + ctx2.num_slots = vctx.num_slots; + ctx2.frame_size = gen_primop_e(bb, size_of_op, singleton(type_decl_ref_helper(a, vctx.nom_t)), empty(a)); + ctx2.frame_size = convert_int_extend_according_to_src_t(bb, get_unqualified_type(ctx2.entry_stack_offset->type), ctx2.frame_size); + } + if (node->payload.fun.body) + fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); + else + cancel_body(bb); + + destroy_dict(ctx2.prepared_offsets); + return fun; + } + case PrimOp_TAG: { + if (!ctx->disable_lowering && node->payload.prim_op.op == alloca_op) { + StackSlot* found_slot = find_value_dict(const Node*, StackSlot, ctx->prepared_offsets, node); + if (!found_slot) { + error_print("lower_alloca: failed to find a stack offset for "); + log_node(ERROR, node); + error_print(", most likely this means this alloca was not found in the first block of a function.\n"); + log_module(DEBUG, ctx->config, ctx->rewriter.src_module); + error_die(); + } + + BodyBuilder* bb = begin_body(a); + //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); + const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, ctx->entry_base_stack_ptr, found_slot->offset)); + const Node* slot = first(bind_instruction_named(bb, lea_instr, (String []) { format_string_arena(a->arena, "stack_slot_%d", found_slot->i) })); + const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); + slot = gen_reinterpret_cast(bb, ptr_t, slot); + bool last = found_slot->i == ctx->num_slots - 1; + if (last) { + const Node* updated_stack_ptr = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->entry_stack_offset, ctx->frame_size)); + gen_primop(bb, set_stack_pointer_op, empty(a), singleton(updated_stack_ptr)); + } + + return yield_values_and_wrap_in_block(bb, singleton(slot)); + } + break; + } + default: break; + } + return recreate_node_identity(&ctx->rewriter, node); +} + +Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(aconfig); + Module* dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .config = config, + }; + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + return dst; +} diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index e1aaf0c34..9da5047a2 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -56,8 +56,10 @@ RewritePass simt2d; /// @name Physical memory emulation /// @{ -/// Implements stack frames, saves the stack size on function entry and restores it upon exit +/// Implements stack frames: saves the stack size on function entry and restores it upon exit RewritePass setup_stack_frames; +/// Implements stack frames: collects allocas into a struct placed on the stack upon function entry +RewritePass lower_alloca; /// Turns stack pushes and pops into accesses into pointer load and stores RewritePass lower_stack; /// Eliminates lea_op on all physical address spaces diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index a8363f92f..8d084737a 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -18,55 +18,14 @@ typedef struct Context_ { bool disable_lowering; const CompilerConfig* config; - const Node* entry_base_stack_ptr; const Node* entry_stack_offset; } Context; -typedef struct { - Visitor visitor; - Context* context; - BodyBuilder* bb; - Node* nom_t; - struct List* members; -} VContext; - -static void search_operand_for_alloca(VContext* vctx, const Node* node) { - IrArena* a = vctx->context->rewriter.dst_arena; - AddressSpace as; - - if (node->tag == PrimOp_TAG) { - switch (node->payload.prim_op.op) { - case alloca_op: as = AsPrivatePhysical; break; - case alloca_subgroup_op: as = AsSubgroupPhysical; break; - default: goto not_alloca; - } - - const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.prim_op.type_arguments.nodes[0]); - assert(is_data_type(element_type)); - const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, singleton(type_decl_ref_helper(a, vctx->nom_t)), singleton(int32_literal(a, entries_count_list(vctx->members)))); - append_list(const Type*, vctx->members, element_type); - - const Node* slot = first(bind_instruction_named(vctx->bb, prim_op(a, (PrimOp) { - .op = lea_op, - .operands = mk_nodes(a, vctx->context->entry_base_stack_ptr, slot_offset) }), (String []) {format_string_arena(a->arena, "stack_slot_%d", entries_count_list(vctx->members)) })); - - const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = element_type, .address_space = as }); - slot = gen_reinterpret_cast(vctx->bb, ptr_t, slot); - - register_processed(&vctx->context->rewriter, node, quote_helper(a, singleton(slot))); - return; - } - - not_alloca: - visit_node_operands(&vctx->visitor, IGNORE_ABSTRACTIONS_MASK, node); -} - static const Node* process(Context* ctx, const Node* node) { const Node* found = search_processed(&ctx->rewriter, node); if (found) return found; IrArena* a = ctx->rewriter.dst_arena; - Module* m = ctx->rewriter.dst_module; switch (node->tag) { case Function_TAG: { Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); @@ -75,33 +34,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); if (!ctx2.disable_lowering) { - Node* nom_t = nominal_type(m, empty(a), format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); ctx2.entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_pointer_op } ), (String []) {format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun)) })); - ctx2.entry_base_stack_ptr = gen_primop_ce(bb, get_stack_base_op, 0, NULL); - VContext vctx = { - .visitor = { - .visit_node_fn = (VisitNodeFn) search_operand_for_alloca, - }, - .context = &ctx2, - .bb = bb, - .nom_t = nom_t, - .members = new_list(const Node*), - }; - if (node->payload.fun.body) { - search_operand_for_alloca(&vctx, node->payload.fun.body); - visit_function_rpo(&vctx.visitor, node); - } - vctx.nom_t->payload.nom_type.body = record_type(a, (RecordType) { - .members = nodes(a, entries_count_list(vctx.members), read_list(const Node*, vctx.members)), - .names = strings(a, 0, NULL), - .special = 0 - }); - destroy_list(vctx.members); - - const Node* frame_size = gen_primop_e(bb, size_of_op, singleton(type_decl_ref_helper(a, nom_t)), empty(a)); - frame_size = convert_int_extend_according_to_src_t(bb, get_unqualified_type(ctx2.entry_stack_offset->type), frame_size); - const Node* updated_stack_ptr = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx2.entry_stack_offset, frame_size)); - gen_primop(bb, set_stack_pointer_op, empty(a), singleton(updated_stack_ptr)); } if (node->payload.fun.body) fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); From ee351f7f28c5d3733505807954435d76df864e3d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 18:14:54 +0100 Subject: [PATCH 020/693] added opt to weaken/demote allocas --- include/shady/ir.h | 1 + src/shady/CMakeLists.txt | 1 + src/shady/compile.c | 2 + src/shady/fold.c | 6 + src/shady/passes/lift_indirect_targets.c | 2 + src/shady/passes/opt_demote_alloca.c | 161 +++++++++++++++++++++++ src/shady/passes/passes.h | 1 + 7 files changed, 174 insertions(+) diff --git a/include/shady/ir.h b/include/shady/ir.h index 7e728d6d1..8623b774d 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -98,6 +98,7 @@ typedef struct { /// 'folding' optimisations - happen in the constructors directly struct { bool delete_unreachable_structured_cases; + bool weaken_non_leaking_allocas; } optimisations; } ArenaConfig; diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 6217640d5..312bc527a 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -84,6 +84,7 @@ set(SHADY_SOURCES passes/opt_stack.c passes/opt_restructure.c passes/opt_mem2reg.c + passes/opt_demote_alloca.c passes/reconvergence_heuristics.c passes/simt2d.c passes/specialize_entry_point.c diff --git a/src/shady/compile.c b/src/shady/compile.c index ad3ae817e..f2f3bfaca 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -97,6 +97,8 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(opt_inline) RUN_PASS(lift_indirect_targets) + RUN_PASS(opt_demote_alloca) + RUN_PASS(opt_mem2reg) // run mem2reg because we can now weaken non-leaking allocas if (config->specialization.execution_model != EmNone) RUN_PASS(specialize_execution_model) diff --git a/src/shady/fold.c b/src/shady/fold.c index 02b9d2b7f..19a4030b7 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -243,6 +243,12 @@ break; return quote_single(arena, value); break; } + case store_op: { + if (first(payload.operands)->tag == Undef_TAG) { + return quote_helper(arena, empty(arena)); + } + break; + } case reinterpret_op: case convert_op: // get rid of identity casts diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 138d9c0be..e98847467 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -201,6 +201,8 @@ static const Node* process_node(Context* ctx, const Node* node) { Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + // this will be safe now since we won't lift any more code after this pass + aconfig.optimisations.weaken_non_leaking_allocas = true; IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index e69de29bb..db4033ff0 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -0,0 +1,161 @@ +#include "passes.h" + +#include "log.h" +#include "portability.h" +#include "list.h" +#include "util.h" + +#include "../rewrite.h" +#include "../visit.h" +#include "../type.h" +#include "../ir_private.h" +#include "../transform/ir_gen_helpers.h" +#include "../analysis/uses.h" + +#include + +typedef struct Context_ { + Rewriter rewriter; + bool disable_lowering; + + const UsesMap* scope_uses; + const CompilerConfig* config; +} Context; + +typedef struct { + bool leaks; + bool read_from; + bool reinterpreted; +} PtrUsageKnowledge; + +static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, PtrUsageKnowledge* k, const UsesMap* map) { + const Type* ptr_type = ptr_value->type; + bool ptr_u = deconstruct_qualified_type(&ptr_type); + assert(ptr_type->tag == PtrType_TAG); + + const Use* use = get_first_use(map, ptr_value); + for (;use; use = use->next_use) { + if (is_abstraction(use->user) && use->operand_class == NcVariable) + continue; + else if (use->user->tag == Let_TAG && use->operand_class == NcInstruction) { + Nodes vars = get_abstraction_params(get_let_tail(use->user)); + for (size_t i = 0; i < vars.count; i++) { + debugv_print("mem2reg leak analysis: following let-bound variable: "); + log_node(DEBUGV, vars.nodes[i]); + debugv_print(".\n"); + visit_ptr_uses(vars.nodes[i], slice_type, k, map); + } + } else if (use->user->tag == PrimOp_TAG) { + PrimOp payload = use->user->payload.prim_op; + switch (payload.op) { + case load_op: { + if (get_pointer_type_element(ptr_type) != slice_type) + k->reinterpreted = true; + k->read_from = true; + continue; // loads don't leak the address. + } + case store_op: { + if (get_pointer_type_element(ptr_type) != slice_type) + k->reinterpreted = true; + // stores leak the value if it's stored + if (ptr_value == payload.operands.nodes[1]) + k->leaks = true; + continue; + } + case reinterpret_op: { + debugvv_print("demote_alloca leak analysis: following reinterpret instr: "); + log_node(DEBUGVV, use->user); + debugvv_print(".\n"); + visit_ptr_uses(use->user, slice_type, k, map); + continue; + } + case convert_op: { + if (first(payload.type_arguments)->tag == PtrType_TAG) { + // this is a ptr-ptr conversion, which means it's a Generic-non generic conversion + // these are fine, just track them + debugvv_print("demote_alloca leak analysis: following conversion instr: "); + log_node(DEBUGVV, use->user); + debugvv_print(".\n"); + visit_ptr_uses(use->user, slice_type, k, map); + continue; + } + k->leaks = true; + continue; + } + case lea_op: { + // TODO: follow where those derived pointers are used and establish whether they leak themselves + // use slice_type to keep track of the expected type for the relevant sub-object + k->leaks = true; + continue; + } default: break; + } + if (has_primop_got_side_effects(payload.op)) + k->leaks = true; + } else if (use->user->tag == Composite_TAG) { + // todo... + // note: if a composite literal containing our POI (pointer-of-interest) is extracted from, folding ops simplify this to the original POI + // so we don't need to be so clever here I think + k->leaks = true; + } else { + k->leaks = true; + } + } +} + +static const Node* process(Context* ctx, const Node* old) { + const Node* found = search_processed(&ctx->rewriter, old); + if (found) return found; + + IrArena* a = ctx->rewriter.dst_arena; + switch (old->tag) { + case Function_TAG: { + Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); + Context fun_ctx = *ctx; + fun_ctx.scope_uses = create_uses_map(old, (NcDeclaration | NcType)); + fun_ctx.disable_lowering = lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); + if (old->payload.fun.body) + fun->payload.fun.body = rewrite_node(&fun_ctx.rewriter, old->payload.fun.body); + destroy_uses_map(fun_ctx.scope_uses); + return fun; + } + case PrimOp_TAG: { + PrimOp payload = old->payload.prim_op; + switch (payload.op) { + case alloca_op: + case alloca_logical_op: { + PtrUsageKnowledge k = { 0 }; + assert(ctx->scope_uses); + visit_ptr_uses(old, first(payload.type_arguments), &k, ctx->scope_uses); + debugv_print("demote_alloca: uses analysis results for "); + log_node(DEBUGV, old); + debugv_print(": leaks=%d read_from=%d reinterpreted=%d\n", k.leaks, k.read_from, k.reinterpreted); + if (!k.leaks) { + if (!k.read_from /* this should include killing dead stores! */) + return quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(&ctx->rewriter, old->type))}))); + if (!k.reinterpreted && get_arena_config(a).optimisations.weaken_non_leaking_allocas) + return prim_op_helper(a, alloca_logical_op, rewrite_nodes(&ctx->rewriter, payload.type_arguments), rewrite_nodes(&ctx->rewriter, payload.operands)); + } + } + default: + break; + } + break; + } + default: break; + } + return recreate_node_identity(&ctx->rewriter, old); +} + +Module* opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(aconfig); + Module* dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .config = config, + }; + ctx.rewriter.config.rebind_let = true; + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + return dst; +} diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 9da5047a2..e11d2d408 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -112,6 +112,7 @@ RewritePass opt_inline_jumps; /// In addition, also inlines function calls according to heuristics RewritePass opt_inline; RewritePass opt_mem2reg; +RewritePass opt_demote_alloca; /// Try to identify reconvergence points throughout the program for unstructured control flow programs RewritePass reconvergence_heuristics; From cc02b64dc2053bf0b5d55ad51694df5626ae3a0f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 21:33:29 +0100 Subject: [PATCH 021/693] upgraded opt_demote_alloca to be strength-reducing for casts too --- src/shady/passes/opt_demote_alloca.c | 142 ++++++++++++++++++++++++--- src/shady/rewrite.c | 4 +- src/shady/rewrite.h | 1 + 3 files changed, 129 insertions(+), 18 deletions(-) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index db4033ff0..219dca534 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -3,6 +3,7 @@ #include "log.h" #include "portability.h" #include "list.h" +#include "dict.h" #include "util.h" #include "../rewrite.h" @@ -11,6 +12,7 @@ #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" #include "../analysis/uses.h" +#include "../analysis/leak.h" #include @@ -20,15 +22,23 @@ typedef struct Context_ { const UsesMap* scope_uses; const CompilerConfig* config; + Arena* arena; + struct Dict* alloca_info; } Context; typedef struct { + const Type* type; bool leaks; bool read_from; - bool reinterpreted; -} PtrUsageKnowledge; + bool non_logical_use; + const Node* bound; +} AllocaInfo; -static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, PtrUsageKnowledge* k, const UsesMap* map) { +typedef struct { + AllocaInfo* src_alloca; +} PtrSourceKnowledge; + +static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, AllocaInfo* k, const UsesMap* map) { const Type* ptr_type = ptr_value->type; bool ptr_u = deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); @@ -49,20 +59,32 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, PtrUsa PrimOp payload = use->user->payload.prim_op; switch (payload.op) { case load_op: { - if (get_pointer_type_element(ptr_type) != slice_type) - k->reinterpreted = true; + //if (get_pointer_type_element(ptr_type) != slice_type) + // k->reinterpreted = true; k->read_from = true; continue; // loads don't leak the address. } case store_op: { - if (get_pointer_type_element(ptr_type) != slice_type) - k->reinterpreted = true; + //if (get_pointer_type_element(ptr_type) != slice_type) + // k->reinterpreted = true; // stores leak the value if it's stored if (ptr_value == payload.operands.nodes[1]) k->leaks = true; continue; } case reinterpret_op: { + k->non_logical_use = true; + continue; + } + case convert_op: { + if (first(payload.type_arguments)->tag == PtrType_TAG) { + k->non_logical_use = true; + } else { + k->leaks = true; + } + continue; + } + /*case reinterpret_op: { debugvv_print("demote_alloca leak analysis: following reinterpret instr: "); log_node(DEBUGVV, use->user); debugvv_print(".\n"); @@ -81,7 +103,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, PtrUsa } k->leaks = true; continue; - } + }*/ case lea_op: { // TODO: follow where those derived pointers are used and establish whether they leak themselves // use slice_type to keep track of the expected type for the relevant sub-object @@ -102,11 +124,40 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, PtrUsa } } +PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { + PtrSourceKnowledge k = { 0 }; + while (ptr) { + assert(is_value(ptr)); + if (ptr->tag == Variable_TAG) { + const Node* instr = get_var_instruction(ctx->scope_uses, ptr); + PrimOp payload = instr->payload.prim_op; + switch (payload.op) { + case alloca_logical_op: + case alloca_op: { + k.src_alloca = *find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, instr); + return k; + } + case convert_op: + case reinterpret_op: { + ptr = first(payload.operands); + continue; + } + // TODO: lea and co + default: break; + } + } + + ptr = NULL; + } + return k; +} + static const Node* process(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; switch (old->tag) { case Function_TAG: { Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); @@ -118,23 +169,75 @@ static const Node* process(Context* ctx, const Node* old) { destroy_uses_map(fun_ctx.scope_uses); return fun; } + case Let_TAG: { + const Node* oinstruction = get_let_instruction(old); + const Node* otail = get_let_tail(old); + const Node* ninstruction = rewrite_node(r, oinstruction); + AllocaInfo** found_info = find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, oinstruction); + if (found_info) { + const Node* ovar = first(get_abstraction_params(otail)); + insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, ovar, found_info); + } + Nodes oparams = otail->payload.case_.params; + Nodes ntypes = unwrap_multiple_yield_types(r->dst_arena, ninstruction->type); + assert(ntypes.count == oparams.count); + LARRAY(const Node*, new_params, oparams.count); + for (size_t i = 0; i < oparams.count; i++) { + new_params[i] = var(r->dst_arena, ntypes.nodes[i], oparams.nodes[i]->payload.var.name); + register_processed(r, oparams.nodes[i], new_params[i]); + } + if (found_info) + (*found_info)->bound = new_params[0]; + const Node* nbody = rewrite_node(r, otail->payload.case_.body); + const Node* tail = case_(r->dst_arena, nodes(r->dst_arena, oparams.count, new_params), nbody); + return let(a, ninstruction, tail); + } case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; switch (payload.op) { case alloca_op: case alloca_logical_op: { - PtrUsageKnowledge k = { 0 }; + AllocaInfo* k = arena_alloc(ctx->arena, sizeof(AllocaInfo)); + *k = (AllocaInfo) { .type = rewrite_node(r, first(payload.type_arguments)) }; assert(ctx->scope_uses); - visit_ptr_uses(old, first(payload.type_arguments), &k, ctx->scope_uses); + visit_ptr_uses(old, first(payload.type_arguments), k, ctx->scope_uses); + insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, old, k); debugv_print("demote_alloca: uses analysis results for "); log_node(DEBUGV, old); - debugv_print(": leaks=%d read_from=%d reinterpreted=%d\n", k.leaks, k.read_from, k.reinterpreted); - if (!k.leaks) { - if (!k.read_from /* this should include killing dead stores! */) - return quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(&ctx->rewriter, old->type))}))); - if (!k.reinterpreted && get_arena_config(a).optimisations.weaken_non_leaking_allocas) - return prim_op_helper(a, alloca_logical_op, rewrite_nodes(&ctx->rewriter, payload.type_arguments), rewrite_nodes(&ctx->rewriter, payload.operands)); + debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); + if (!k->leaks) { + if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) + return quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}))); + if (!k->non_logical_use && get_arena_config(a).optimisations.weaken_non_leaking_allocas) + return prim_op_helper(a, alloca_logical_op, rewrite_nodes(&ctx->rewriter, payload.type_arguments), rewrite_nodes(r, payload.operands)); } + break; + } + case load_op: { + PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, first(payload.operands)); + if (k.src_alloca) { + const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.operands.nodes[0]->type))); + if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { + BodyBuilder* bb = begin_body(a); + const Node* data = gen_load(bb, k.src_alloca->bound); + data = gen_reinterpret_cast(bb, access_type, data); + return yield_values_and_wrap_in_block(bb, singleton(data)); + } + } + break; + } + case store_op: { + PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, first(payload.operands)); + if (k.src_alloca) { + const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.operands.nodes[0]->type))); + if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { + BodyBuilder* bb = begin_body(a); + const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.operands.nodes[1])); + gen_store(bb, k.src_alloca->bound, data); + return yield_values_and_wrap_in_block(bb, empty(a)); + } + } + break; } default: break; @@ -146,6 +249,9 @@ static const Node* process(Context* ctx, const Node* old) { return recreate_node_identity(&ctx->rewriter, old); } +KeyHash hash_node(const Node**); +bool compare_node(const Node**, const Node**); + Module* opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); IrArena* a = new_ir_arena(aconfig); @@ -153,9 +259,13 @@ Module* opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .config = config, + .arena = new_arena(), + .alloca_info = new_dict(const Node, AllocaInfo, (HashFn) hash_node, (CmpFn) compare_node) }; ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); + destroy_dict(ctx.alloca_info); + destroy_arena(ctx.arena); return dst; } diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index e99c06286..d067cf898 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -288,7 +288,7 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) } } -static const Node* rebind_results(Rewriter* rewriter, const Node* ninstruction, const Node* olam) { +const Node* rebind_let(Rewriter* rewriter, const Node* ninstruction, const Node* olam) { assert(olam->tag == Case_TAG); Nodes oparams = olam->payload.case_.params; Nodes ntypes = unwrap_multiple_yield_types(rewriter->dst_arena, ninstruction->type); @@ -342,7 +342,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { } const Node* tail; if (rewriter->config.rebind_let) - tail = rebind_results(rewriter, instruction, node->payload.let.tail); + tail = rebind_let(rewriter, instruction, node->payload.let.tail); else tail = rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail); return let(arena, instruction, tail); diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index a98a3a69b..d97bea438 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -60,6 +60,7 @@ void recreate_decl_body_identity(Rewriter*, const Node*, Node*); const Node* recreate_variable(Rewriter* rewriter, const Node* old); Nodes recreate_variables(Rewriter* rewriter, Nodes old); Node* clone_bb_head(Rewriter*, const Node* bb); +const Node* rebind_let(Rewriter*, const Node* ninstruction, const Node* ocase); /// Looks up if the node was already processed const Node* search_processed(const Rewriter*, const Node*); From 79e11d59fb42bbb59fc198a09b07f5f400ed5443 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 21:34:19 +0100 Subject: [PATCH 022/693] rewrote mem2reg --- src/shady/passes/opt_mem2reg.c | 790 +++++++++++++++++++-------------- 1 file changed, 451 insertions(+), 339 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 81a89b3e2..cb6fa8d3d 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -18,14 +18,22 @@ typedef struct { AddressSpace as; - bool leaks; - bool read_from; const Type* type; } PtrSourceKnowledge; typedef struct { - const Node* ptr_address; - const Node* ptr_value; + enum { + PSUnknown, + PSKnownValue, + PSKnownAlias, + PSKnownSubElement, + } state; + union { + const Node* ptr_value; + // for PSKnownAlias: old node to lookup + const Node* alias_old_address; + struct { const Node* old_base; Nodes indices; } sub_element; + }; bool ptr_has_leaked; PtrSourceKnowledge* source; } PtrKnowledge; @@ -42,15 +50,21 @@ struct KB { Arena* a; }; +typedef struct { + const Node* old_jump; + Node* wrapper_bb; + KnowledgeBase* kb; +} TodoJump; + typedef struct { Rewriter rewriter; Scope* scope; - const UsesMap* scope_uses; struct Dict* abs_to_kb; - const Node* abs; + const Node* oabs; Arena* a; struct Dict* bb_new_args; + struct List* todo_jumps; } Context; static PtrKnowledge* get_last_valid_ptr_knowledge(const KnowledgeBase* kb, const Node* n) { @@ -63,10 +77,10 @@ static PtrKnowledge* get_last_valid_ptr_knowledge(const KnowledgeBase* kb, const return k; } -static PtrKnowledge* create_ptr_knowledge(KnowledgeBase* kb, const Node* instruction, const Node* address_value) { +static PtrKnowledge* create_ptr_knowledge(KnowledgeBase* kb, const Node* instruction) { PtrKnowledge* k = arena_alloc(kb->a, sizeof(PtrKnowledge)); PtrSourceKnowledge* sk = arena_alloc(kb->a, sizeof(PtrSourceKnowledge)); - *k = (PtrKnowledge) { .source = sk, .ptr_address = address_value }; + *k = (PtrKnowledge) { .source = sk, .state = PSUnknown/*, .ptr_address = address_value*/ }; *sk = (PtrSourceKnowledge) { 0 }; bool fresh = insert_dict(const Node*, PtrKnowledge*, kb->map, instruction, k); assert(fresh); @@ -87,128 +101,171 @@ static void insert_ptr_knowledge(KnowledgeBase* kb, const Node* n, PtrKnowledge* insert_dict(const Node*, PtrKnowledge*, kb->map, n, k); } -static const Node* get_known_value(Rewriter* r, const PtrKnowledge* k) { +static const Node* get_known_value(KnowledgeBase* kb, const PtrKnowledge* k) { const Node* v = NULL; - if (k && !k->ptr_has_leaked && !k->source->leaks) { - if (k->ptr_value) { + while (k) { + if (k->state == PSKnownValue) { v = k->ptr_value; - } + k = NULL; + } else if (k->state == PSKnownAlias) { + k = get_last_valid_ptr_knowledge(kb, k->alias_old_address); + } else + k = NULL; } - if (r && v && v->arena != r->dst_arena) - return rewrite_node(r, v); return v; } -static const Node* get_known_address(Rewriter* r, const PtrKnowledge* k) { +/*static const Node* get_known_address(Rewriter* r, const PtrKnowledge* k) { const Node* v = NULL; if (k) { if (k->ptr_address) { v = k->ptr_address; } } - if (r && v && v->arena != r->dst_arena) - return rewrite_node(r, v); + if (v) + assert(v->arena == r->dst_arena); + // if (r && v && v->arena != r->dst_arena) + // return rewrite_node(r, v); return v; +}*/ + +KeyHash hash_node(const Node**); +bool compare_node(const Node**, const Node**); + +static void destroy_kb(KnowledgeBase* kb) { + destroy_dict(kb->map); + destroy_dict(kb->potential_additional_params); } -static void visit_ptr_uses(const Node* ptr_value, PtrSourceKnowledge* k, const UsesMap* map) { - const Use* use = get_first_use(map, ptr_value); - for (;use; use = use->next_use) { - if (is_abstraction(use->user) && use->operand_class == NcVariable) - continue; - else if (use->user->tag == Let_TAG && use->operand_class == NcInstruction) { - Nodes vars = get_abstraction_params(get_let_tail(use->user)); - for (size_t i = 0; i < vars.count; i++) { - debugv_print("mem2reg leak analysis: following let-bound variable: "); - log_node(DEBUGV, vars.nodes[i]); - debugv_print(".\n"); - visit_ptr_uses(vars.nodes[i], k, map); - } - } else if (use->user->tag == PrimOp_TAG) { - PrimOp payload = use->user->payload.prim_op; - switch (payload.op) { - case load_op: { - k->read_from = true; - continue; // loads don't leak the address. - } - case store_op: { - // stores leak the value if it's stored - if (ptr_value == payload.operands.nodes[1]) - k->leaks = true; - continue; - } - case reinterpret_op: { - debugv_print("mem2reg leak analysis: following reinterpret instr: "); - log_node(DEBUGV, use->user); - debugv_print(".\n"); - visit_ptr_uses(use->user, k, map); - continue; - } - case convert_op: { - if (first(payload.type_arguments)->tag == PtrType_TAG) { - // this is a ptr-ptr conversion, which means it's a Generic-non generic conversion - // these are fine, just track them - debugv_print("mem2reg leak analysis: following conversion instr: "); - log_node(DEBUGV, use->user); - debugv_print(".\n"); - visit_ptr_uses(use->user, k, map); - continue; - } - k->leaks = true; - continue; - } - case lea_op: { - //TODO: follow where those derived pointers are used and establish whether they leak themselves - k->leaks = true; - continue; - } default: break; - } - if (has_primop_got_side_effects(payload.op)) - k->leaks = true; - } else if (use->user->tag == Composite_TAG) { - // todo... - k->leaks = true; - } else { - k->leaks = true; +static KnowledgeBase* get_kb(Context* ctx, const Node* abs) { + KnowledgeBase** found = find_value_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, abs); + assert(found); + return *found; +} + +static KnowledgeBase* create_kb(Context* ctx, const Node* old) { + arena_alloc(ctx->a, sizeof(KnowledgeBase)); + CFNode* cf_node = scope_lookup(ctx->scope, old); + KnowledgeBase* kb = arena_alloc(ctx->a, sizeof(KnowledgeBase)); + *kb = (KnowledgeBase) { + .cfnode = cf_node, + .a = ctx->a, + .map = new_dict(const Node*, PtrKnowledge*, (HashFn) hash_node, (CmpFn) compare_node), + .potential_additional_params = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .dominator_kb = NULL, + }; + // log_string(DEBUGVV, "Creating KB for "); + // log_node(DEBUGVV, old); + // log_string(DEBUGVV, "\n."); + if (entries_count_list(cf_node->pred_edges) == 1) { + CFEdge edge = read_list(CFEdge, cf_node->pred_edges)[0]; + assert(edge.dst == cf_node); + CFNode* dominator = edge.src; + const KnowledgeBase* parent_kb = get_kb(ctx, dominator->node); + assert(parent_kb->map); + kb->dominator_kb = parent_kb; + } + assert(kb->map); + insert_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, old, kb); + return kb; +} + +static void wipe_all_leaked_pointers(KnowledgeBase* kb) { + size_t i = 0; + const Node* ptr; + PtrKnowledge* k; + while (dict_iter(kb->map, &i, &ptr, &k)) { + if (k->ptr_has_leaked) { + k->ptr_value = NULL; } } } -static void visit_instruction(Context* ctx, KnowledgeBase* kb, const Node* instruction, Nodes results) { - IrArena* a = instruction->arena; - switch (is_instruction(instruction)) { - case NotAnInstruction: assert(is_instruction(instruction)); +static void mark_values_as_escaping(KnowledgeBase* kb, Nodes values); +static void mark_value_as_escaping(KnowledgeBase* kb, const Node* value) { + PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, value); + if (k) + k->ptr_has_leaked = true; + switch (is_value(value)) { + case NotAValue: assert(false); + case Value_Variable_TAG: + break; + case Value_ConstrainedValue_TAG: + break; + case Value_UntypedNumber_TAG: + break; + case Value_IntLiteral_TAG: + break; + case Value_FloatLiteral_TAG: + break; + case Value_StringLiteral_TAG: + break; + case Value_True_TAG: + break; + case Value_False_TAG: + break; + case Value_NullPtr_TAG: + break; + case Value_Composite_TAG: + mark_values_as_escaping(kb, value->payload.composite.contents); + break; + case Value_Fill_TAG: + mark_value_as_escaping(kb, value->payload.fill.value); + break; + case Value_Undef_TAG: + break; + case Value_RefDecl_TAG: + break; + case Value_FnAddr_TAG: + break; + } +} + +static void mark_values_as_escaping(KnowledgeBase* kb, Nodes values) { + for (size_t i = 0; i < values.count; i++) + mark_value_as_escaping(kb, values.nodes[i]); +} + +static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const Node* oinstruction) { + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + switch (is_instruction(oinstruction)) { + case NotAnInstruction: assert(is_instruction(oinstruction)); case Instruction_Call_TAG: break; case Instruction_PrimOp_TAG: { - PrimOp payload = instruction->payload.prim_op; + PrimOp payload = oinstruction->payload.prim_op; switch (payload.op) { case alloca_logical_op: case alloca_op: { - const Node* optr = first(results); - PtrKnowledge* k = create_ptr_knowledge(kb, instruction, optr); - visit_ptr_uses(optr, k->source, ctx->scope_uses); - debugv_print("mem2reg: "); - log_node(DEBUGV, optr); - if (k->source->leaks) - debugv_print(" is leaking so it will not be eliminated.\n"); - else - debugv_print(" was found to not leak.\n"); - const Type* t = instruction->type; - bool u = deconstruct_qualified_type(&t); + PtrKnowledge* k = create_ptr_knowledge(kb, oinstruction); + const Type* t = oinstruction->type; + deconstruct_qualified_type(&t); assert(t->tag == PtrType_TAG); k->source->as = t->payload.ptr_type.address_space; - deconstruct_pointer_type(&t); - k->source->type = qualified_type_helper(t, u); + //k->source->type = qualified_type_helper(t, u); + k->source->type = rewrite_node(r, first(payload.type_arguments)); - insert_ptr_knowledge(kb, optr, k); - k->ptr_value = undef(a, (Undef) { .type = first(payload.type_arguments) }); - break; + // TODO: we can only enable this safely once we properly deal with control-flow + k->state = PSKnownValue; + k->ptr_value = undef(a, (Undef) { .type = rewrite_node(r, first(payload.type_arguments)) }); + return recreate_node_identity(r, oinstruction); } case load_op: { - const Node* ptr = first(payload.operands); - const PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, ptr); - if (!k || !k->ptr_value) { + const Node* optr = first(payload.operands); + PtrKnowledge* ok = get_last_valid_ptr_knowledge(kb, optr); + const Node* known_value = get_known_value(kb, ok); + if (known_value) { + const Type* known_value_t = known_value->type; + bool kv_u = deconstruct_qualified_type(&known_value_t); + + const Type* load_result_t = rewrite_node(&ctx->rewriter, optr->type); + bool lrt_u = deconstruct_qualified_type(&load_result_t); + deconstruct_pointer_type(&load_result_t); + assert(!lrt_u || kv_u); + if (is_reinterpret_cast_legal(load_result_t, known_value_t)) + return prim_op_helper(a, reinterpret_op, singleton(load_result_t), singleton(known_value)); + } else { const KnowledgeBase* phi_kb = kb; while (phi_kb->dominator_kb) { phi_kb = phi_kb->dominator_kb; @@ -217,47 +274,96 @@ static void visit_instruction(Context* ctx, KnowledgeBase* kb, const Node* instr log_node(DEBUG, first(payload.operands)); debug_print(" at phi-like node %s.\n", get_abstraction_name(phi_kb->cfnode->node)); // log_node(DEBUG, phi_location->node); - insert_set_get_key(const Node*, phi_kb->potential_additional_params, ptr); + insert_set_get_key(const Node*, phi_kb->potential_additional_params, optr); } - break; + // const Node* other_ptr = get_known_address(&ctx->rewriter, ok); + // if (other_ptr && optr != other_ptr) { + // return prim_op_helper(a, load_op, empty(a), singleton(other_ptr)); + // } + return prim_op_helper(a, load_op, empty(a), singleton(rewrite_node(r, optr))); } case store_op: { - const Node* ptr = first(payload.operands); - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, ptr); + const Node* optr = first(payload.operands); + PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, optr); + if (k) { + k = update_ptr_knowledge(kb, optr, k); + } else { + PtrSourceKnowledge* sk = NULL; + CFNode* node = scope_lookup(ctx->scope, ctx->oabs); + while (node) { + KnowledgeBase* kb2 = get_kb(ctx, node->node); + assert(kb2); + PtrKnowledge* k2 = get_last_valid_ptr_knowledge(kb2, optr); + if (k2) { + sk = k2->source; + break; + } + node = node->idom; + } + if (sk) { + k = arena_alloc(ctx->a, sizeof(PtrKnowledge)); + *k = (PtrKnowledge) { + .source = sk, + .ptr_has_leaked = true // TODO: this is wrong in the "too conservative" way + // fixing this requires accounting for the dominance relation properly + // to visit all predecessors first, then merging the knowledge + }; + insert_ptr_knowledge(kb, optr, k); + } else { + // just make up a new source and assume it leaks/aliases + k = create_ptr_knowledge(kb, optr); + const Type* t = optr->type; + deconstruct_qualified_type(&t); + assert(t->tag == PtrType_TAG); + k->source->as = t->payload.ptr_type.address_space; + k->source->type = rewrite_node(r, get_pointer_type_element(t)); + k->ptr_has_leaked = true; + } + } if (k) { - k = update_ptr_knowledge(kb, ptr, k); - k->ptr_value = payload.operands.nodes[1]; + k->state = PSKnownValue; + k->ptr_value = rewrite_node(r, payload.operands.nodes[1]); } - break; // let's take care of dead stores another time + // let's take care of dead stores another time + return recreate_node_identity(r, oinstruction); } case reinterpret_op: { + const Node* rewritten = recreate_node_identity(r, oinstruction); // if we have knowledge on a particular ptr, the same knowledge propagates if we bitcast it! PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, first(payload.operands)); if (k) { - k = update_ptr_knowledge(kb, instruction, k); - k->ptr_address = first(results); - insert_ptr_knowledge(kb, first(results), k); + k = update_ptr_knowledge(kb, oinstruction, k); + k->state = PSKnownAlias; + k->alias_old_address = first(payload.operands); } - break; + return rewritten; } case convert_op: { + const Node* rewritten = recreate_node_identity(r, oinstruction); // if we convert a pointer to generic AS, we'd like to use the old address instead where possible - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, first(payload.operands)); - if (k) { - debug_print("mem2reg: the converted ptr "); - log_node(DEBUG, first(results)); - debug_print(" is the same as "); - log_node(DEBUG, first(payload.operands)); - debug_print(".\n"); - k = update_ptr_knowledge(kb, instruction, k); - k->ptr_address = first(payload.operands); - insert_ptr_knowledge(kb, first(results), k); + if (first(payload.type_arguments)->tag == PtrType_TAG) { + PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, first(payload.operands)); + if (k) { + debug_print("mem2reg: the converted ptr "); + log_node(DEBUG, oinstruction); + debug_print(" is the same as "); + log_node(DEBUG, first(payload.operands)); + debug_print(".\n"); + k = update_ptr_knowledge(kb, oinstruction, k); + k->state = PSKnownAlias; + k->alias_old_address = first(payload.operands); + } } break; } default: break; } - break; + + mark_values_as_escaping(kb, payload.operands); + if (has_primop_got_side_effects(payload.op)) + wipe_all_leaked_pointers(kb); + + return recreate_node_identity(r, oinstruction); } case Instruction_Control_TAG: break; @@ -266,273 +372,275 @@ static void visit_instruction(Context* ctx, KnowledgeBase* kb, const Node* instr case Instruction_Comment_TAG: break; case Instruction_If_TAG: + break; case Instruction_Match_TAG: + break; case Instruction_Loop_TAG: assert(false && "unsupported"); break; } + + // wipe_all_leaked_pointers(kb); + return recreate_node_identity(r, oinstruction); } -static void visit_terminator(Context* ctx, KnowledgeBase* kb, const Node* old) { - if (!old) - return; +static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Node* old) { + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; switch (is_terminator(old)) { case Terminator_LetMut_TAG: case NotATerminator: assert(false); - case Terminator_Let_TAG: { - const Node* otail = get_let_tail(old); - visit_instruction(ctx, kb, get_let_instruction(old), get_abstraction_params(otail)); - break; + case Let_TAG: { + const Node* oinstruction = get_let_instruction(old); + const Node* ninstruction = rewrite_node(r, oinstruction); + PtrKnowledge** found = find_value_dict(const Node*, PtrKnowledge*, kb->map, oinstruction); + if (found) { // copy any knownledge about an instruction to the bound variable + const Node* old_case = get_let_tail(old); + Nodes old_params = get_abstraction_params(old_case); + assert(old_params.count == 1); + PtrKnowledge* k = *found; + const Node* first_param = first(old_params); + insert_dict(const Node*, PtrKnowledge*, kb->map, first_param, k); + } + + return let(a, ninstruction, rewrite_node(r, get_let_tail(old))); } - default: + case Jump_TAG: { + const Node* old_target = old->payload.jump.target; + // rewrite_node(&ctx->rewriter, old_target); + Nodes args = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); + + //String s = format_string_interned(a, "%s_", get_abstraction_name(old_target)); + String s = get_abstraction_name(old_target); + Node* wrapper = basic_block(a, (Node*) rewrite_node(r, old_target->payload.basic_block.fn), recreate_variables(r, get_abstraction_params(old_target)), s); + TodoJump todo = { + .old_jump = old, + .wrapper_bb = wrapper, + .kb = kb, + }; + append_list(TodoJump, ctx->todo_jumps, todo); + + return jump_helper(a, wrapper, args); + } + case Terminator_TailCall_TAG: + mark_values_as_escaping(kb, old->payload.tail_call.args); + break; + case Terminator_Branch_TAG: + break; + case Terminator_Switch_TAG: + break; + case Terminator_Join_TAG: + // TODO: local joins are fine + mark_values_as_escaping(kb, old->payload.join.args); + break; + case Terminator_MergeContinue_TAG: + break; + case Terminator_MergeBreak_TAG: + break; + case Terminator_Yield_TAG: + break; + case Terminator_Return_TAG: + mark_values_as_escaping(kb, old->payload.fn_ret.args); + break; + case Terminator_Unreachable_TAG: break; } + return recreate_node_identity(r, old); } -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); +static void handle_bb(Context* ctx, const Node* old) { + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; -static void destroy_kb(KnowledgeBase* kb) { - destroy_dict(kb->map); - destroy_dict(kb->potential_additional_params); -} + log_string(DEBUGV, "mem2reg: handling bb %s\n", get_abstraction_name(old)); -static KnowledgeBase* get_kb(Context* ctx, const Node* abs) { - KnowledgeBase** found = find_value_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, abs); - assert(found); - return *found; -} + KnowledgeBase* kb = create_kb(ctx, old); + Context fn_ctx = *ctx; + fn_ctx.oabs = old; + ctx = &fn_ctx; + + Nodes params = recreate_variables(&ctx->rewriter, get_abstraction_params(old)); + Nodes let_params = recreate_variables(&ctx->rewriter, get_abstraction_params(old)); + register_processed_list(&ctx->rewriter, get_abstraction_params(old), let_params); + const Node* nbody = rewrite_node(&ctx->rewriter, get_abstraction_body(old)); + nbody = let(a, quote_helper(a, params), case_(a, let_params, nbody)); + + CFNode* cfnode = scope_lookup(ctx->scope, old); + BodyBuilder* bb = begin_body(a); + size_t i = 0; + const Node* ptr; + Nodes ptrs = empty(ctx->rewriter.src_arena); + while (dict_iter(kb->potential_additional_params, &i, &ptr, NULL)) { + PtrSourceKnowledge* source = NULL; + PtrKnowledge uk = { 0 }; + // check if all the edges have a value for this! + for (size_t j = 0; j < entries_count_list(cfnode->pred_edges); j++) { + CFEdge edge = read_list(CFEdge, cfnode->pred_edges)[j]; + if (edge.type == StructuredPseudoExitEdge) + continue; // these are not real edges... + KnowledgeBase* kb_at_src = get_kb(ctx, edge.src->node); + + const Node* kv = get_known_value(kb_at_src, get_last_valid_ptr_knowledge(kb_at_src, ptr)); + if (kv) { + log_node(DEBUG, ptr); + debug_print(" has a known value ("); + log_node(DEBUG, kv); + debug_print(") in %s ...\n", get_abstraction_name(edge.src->node)); + } else + goto next_potential_param; + + PtrKnowledge* k = get_last_valid_ptr_knowledge(kb_at_src, ptr); + if (!source) + source = k->source; + else + assert(source == k->source); + + const Type* kv_type = get_known_value(kb_at_src, get_last_valid_ptr_knowledge(kb_at_src, ptr))->type; + deconstruct_qualified_type(&kv_type); + const Type* alloca_type_t = source->type; + //deconstruct_qualified_type(&alloca_type_t); + if (kv_type != source->type && !is_reinterpret_cast_legal(kv_type, alloca_type_t)) { + log_node(DEBUG, ptr); + debug_print(" has a known value in %s, but it's type ", get_abstraction_name(edge.src->node)); + log_node(DEBUG, kv_type); + debug_print(" cannot be reinterpreted into the alloca type "); + log_node(DEBUG, source->type); + debug_print("\n."); + goto next_potential_param; + } -static void visit_cfnode(Context* ctx, CFNode* node, CFNode* dominator) { - const Node* oabs = node->node; - KnowledgeBase* kb = arena_alloc(ctx->a, sizeof(KnowledgeBase)); - *kb = (KnowledgeBase) { - .cfnode = node, - .a = ctx->a, - .map = new_dict(const Node*, PtrKnowledge*, (HashFn) hash_node, (CmpFn) compare_node), - .potential_additional_params = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .dominator_kb = NULL, - }; - if (entries_count_list(node->pred_edges) == 1) { - assert(dominator); - CFEdge edge = read_list(CFEdge, node->pred_edges)[0]; - assert(edge.dst == node); - assert(edge.src == dominator); - const KnowledgeBase* parent_kb = get_kb(ctx, dominator->node); - assert(parent_kb->map); - kb->dominator_kb = parent_kb; + uk.ptr_has_leaked |= k->ptr_has_leaked; + } + + log_node(DEBUG, ptr); + debug_print(" has a known value in all predecessors! Turning it into a new parameter.\n"); + + const Node* param = var(a, qualified_type_helper(source->type, false), unique_name(a, "ssa_phi")); + params = append_nodes(a, params, param); + ptrs = append_nodes(ctx->rewriter.src_arena, ptrs, ptr); + gen_store(bb, rewrite_node(r, ptr), param); + + PtrKnowledge* k = arena_alloc(ctx->a, sizeof(PtrKnowledge)); + *k = (PtrKnowledge) { + .ptr_value = param, + .source = source, + .ptr_has_leaked = uk.ptr_has_leaked + }; + insert_ptr_knowledge(kb, ptr, k); + + next_potential_param: continue; } - assert(kb->map); - insert_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, node->node, kb); - assert(is_abstraction(oabs)); - visit_terminator(ctx, kb, get_abstraction_body(oabs)); - for (size_t i = 0; i < entries_count_list(node->dominates); i++) { - CFNode* dominated = read_list(CFNode*, node->dominates)[i]; - visit_cfnode(ctx, dominated, node); + Node* fn = (Node*) rewrite_node(&ctx->rewriter, ctx->scope->entry->node); + String s = format_string_interned(a, "%s_", get_abstraction_name(old)); + //String s = get_abstraction_name(old); + Node* new_bb = basic_block(a, fn, params, s); + register_processed(&ctx->rewriter, old, new_bb); + new_bb->payload.basic_block.body = finish_body(bb, nbody); + + // new_bb->type = bb_type(a, (BBType) { + // .param_types = get_variables_types(a, get_abstraction_params(new_bb)), + // }); + + if (ptrs.count > 0) { + insert_dict(const Node*, Nodes, ctx->bb_new_args, old, ptrs); + } +} + +static void handle_jump_wrappers(Context* ctx) { + IrArena* a = ctx->rewriter.dst_arena; + for (size_t j = 0; j < entries_count_list(ctx->todo_jumps); j++) { + TodoJump todo = read_list(TodoJump, ctx->todo_jumps)[j]; + const Node* old = todo.old_jump; + const Node* old_target = old->payload.jump.target; + const Node* new_target = rewrite_node(&ctx->rewriter, old_target); + Nodes args = get_abstraction_params(todo.wrapper_bb); + + BodyBuilder* bb = begin_body(a); + Nodes* additional_ssa_params = find_value_dict(const Node*, Nodes, ctx->bb_new_args, old_target); + if (additional_ssa_params) { + assert(additional_ssa_params->count > 0); + + for (size_t i = 0; i < additional_ssa_params->count; i++) { + const Node* ptr = additional_ssa_params->nodes[i]; + PtrKnowledge* k = get_last_valid_ptr_knowledge(todo.kb, ptr); + const Node* value = get_known_value(todo.kb, k); + + const Type* known_value_t = value->type; + deconstruct_qualified_type(&known_value_t); + + const Type* alloca_type_t = k->source->type; + + if (alloca_type_t != known_value_t && is_reinterpret_cast_legal(alloca_type_t, known_value_t)) + value = first(gen_primop(bb, reinterpret_op, singleton(rewrite_node(&ctx->rewriter, alloca_type_t)), singleton(value))); + + assert(value); + args = append_nodes(a, args, value); + } + + } + todo.wrapper_bb->payload.basic_block.body = finish_body(bb, jump_helper(a, new_target, args)); } } static const Node* process(Context* ctx, const Node* old) { assert(old); Context fn_ctx = *ctx; - if (old->tag == Function_TAG && !lookup_annotation(old, "Internal")) { + if (is_abstraction(old)) { + fn_ctx.oabs = old; ctx = &fn_ctx; + } + + KnowledgeBase* kb = NULL; + if (old->tag == Function_TAG && !lookup_annotation(old, "Internal")) { fn_ctx.scope = new_scope(old); - fn_ctx.scope_uses = create_uses_map(old, (NcDeclaration | NcType)); fn_ctx.abs_to_kb = new_dict(const Node*, KnowledgeBase**, (HashFn) hash_node, (CmpFn) compare_node); - visit_cfnode(&fn_ctx, fn_ctx.scope->entry, NULL); - fn_ctx.abs = old; + fn_ctx.todo_jumps = new_list(TodoJump), + kb = create_kb(ctx, old); const Node* new_fn = recreate_node_identity(&fn_ctx.rewriter, old); + + for (size_t i = 1; i < ctx->scope->size; i++) { + CFNode* cf_node = ctx->scope->rpo[i]; + if (cf_node->node->tag == BasicBlock_TAG) + handle_bb(ctx, cf_node->node); + } + + //handle_bb_wrappers(ctx); + //clear_list(ctx->todo_bbs); + handle_jump_wrappers(ctx); + destroy_list(fn_ctx.todo_jumps); + destroy_scope(fn_ctx.scope); - destroy_uses_map(fn_ctx.scope_uses); size_t i = 0; - KnowledgeBase* kb; while (dict_iter(fn_ctx.abs_to_kb, &i, NULL, &kb)) { destroy_kb(kb); } destroy_dict(fn_ctx.abs_to_kb); return new_fn; - } else if (is_abstraction(old)) { - fn_ctx.abs = old; - ctx = &fn_ctx; } - KnowledgeBase* kb = NULL; - if (ctx->abs && ctx->abs_to_kb) { - kb = get_kb(ctx, ctx->abs); + // setup a new KB if this is a fresh abstraction + if (is_abstraction(old) && ctx->scope) { + kb = create_kb(ctx, old); + } else if (ctx->oabs && ctx->abs_to_kb) { + // otherwise look up the enclosing one, if any + kb = get_kb(ctx, ctx->oabs); assert(kb); } if (!kb) return recreate_node_identity(&ctx->rewriter, old); - IrArena* a = ctx->rewriter.dst_arena; + if (is_instruction(old)) + return process_instruction(ctx, kb, old); + if (is_terminator(old)) + return process_terminator(ctx, kb, old); switch (old->tag) { - case PrimOp_TAG: { - PrimOp payload = old->payload.prim_op; - switch (payload.op) { - case load_op: { - const Node* ptr = first(payload.operands); - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, ptr); - const Node* known_value = get_known_value(&ctx->rewriter, k); - if (known_value) { - const Type* known_value_t = known_value->type; - bool kv_u = deconstruct_qualified_type(&known_value_t); - - const Type* load_result_t = rewrite_node(&ctx->rewriter, ptr->type); - bool lrt_u = deconstruct_qualified_type(&load_result_t); - deconstruct_pointer_type(&load_result_t); - assert(!lrt_u || kv_u); - if (is_reinterpret_cast_legal(load_result_t, known_value_t)) - return prim_op_helper(a, reinterpret_op, singleton(load_result_t), singleton(known_value)); - } - const Node* other_ptr = get_known_address(&ctx->rewriter, k); - if (other_ptr && ptr != other_ptr) { - return prim_op_helper(a, load_op, empty(a), singleton(other_ptr)); - } - break; - } - case store_op: { - const Node* ptr = first(payload.operands); - const PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, ptr); - if (k && !k->source->leaks && !k->source->read_from) - return quote_helper(a, empty(a)); - const Node* other_ptr = get_known_address(&ctx->rewriter, k); - if (other_ptr && ptr != other_ptr) { - return prim_op_helper(a, store_op, empty(a), mk_nodes(a, other_ptr, rewrite_node(&ctx->rewriter, payload.operands.nodes[1]))); - } - break; - } - case alloca_op: { - const PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, old); - if (k && !k->source->leaks && !k->source->read_from) - return quote_helper(a, singleton(undef(a, (Undef) { .type = get_unqualified_type(rewrite_node(&ctx->rewriter, old->type)) }))); - break; - } - default: break; - } - break; - } case BasicBlock_TAG: { - CFNode* cfnode = scope_lookup(ctx->scope, old); - size_t i = 0; - const Node* ptr; - Nodes params = recreate_variables(&ctx->rewriter, get_abstraction_params(old)); - register_processed_list(&ctx->rewriter, get_abstraction_params(old), params); - Nodes ptrs = empty(ctx->rewriter.src_arena); - while (dict_iter(kb->potential_additional_params, &i, &ptr, NULL)) { - PtrSourceKnowledge* source = NULL; - PtrKnowledge uk = { 0 }; - // check if all the edges have a value for this! - for (size_t j = 0; j < entries_count_list(cfnode->pred_edges); j++) { - CFEdge edge = read_list(CFEdge, cfnode->pred_edges)[j]; - if (edge.type == StructuredPseudoExitEdge) - continue; // these are not real edges... - KnowledgeBase* kb_at_src = get_kb(ctx, edge.src->node); - - if (get_known_value(NULL, get_last_valid_ptr_knowledge(kb_at_src, ptr))) { - log_node(DEBUG, ptr); - debug_print(" has a known value in %s ...\n", get_abstraction_name(edge.src->node)); - } else - goto next_potential_param; - - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb_at_src, ptr); - if (!source) - source = k->source; - else - assert(source == k->source); - - const Type* kv_type = get_known_value(NULL, get_last_valid_ptr_knowledge(kb_at_src, ptr))->type; - deconstruct_qualified_type(&kv_type); - const Type* alloca_type_t = source->type; - deconstruct_qualified_type(&alloca_type_t); - if (kv_type != source->type && !is_reinterpret_cast_legal(kv_type, alloca_type_t)) { - log_node(DEBUG, ptr); - debug_print(" has a known value in %s, but it's type ", get_abstraction_name(edge.src->node)); - log_node(DEBUG, kv_type); - debug_print(" cannot be reinterpreted into the alloca type "); - log_node(DEBUG, source->type); - debug_print("\n."); - goto next_potential_param; - } - - uk.ptr_has_leaked |= k->ptr_has_leaked; - } - - log_node(DEBUG, ptr); - debug_print(" has a known value in all predecessors! Turning it into a new parameter.\n"); - - const Node* param = var(a, rewrite_node(&ctx->rewriter, source->type), unique_name(a, "ssa_phi")); - params = append_nodes(a, params, param); - ptrs = append_nodes(ctx->rewriter.src_arena, ptrs, ptr); - - PtrKnowledge* k = arena_alloc(ctx->a, sizeof(PtrKnowledge)); - *k = (PtrKnowledge) { - .ptr_value = param, - .source = source, - .ptr_has_leaked = uk.ptr_has_leaked - }; - insert_ptr_knowledge(kb, ptr, k); - - next_potential_param: continue; - } - - if (ptrs.count > 0) { - insert_dict(const Node*, Nodes, ctx->bb_new_args, old, ptrs); - } - - Node* fn = (Node*) rewrite_node(&ctx->rewriter, ctx->scope->entry->node); - Node* bb = basic_block(a, fn, params, get_abstraction_name(old)); - register_processed(&ctx->rewriter, old, bb); - bb->payload.basic_block.body = rewrite_node(&ctx->rewriter, get_abstraction_body(old)); - return bb; - } - case Jump_TAG: { - const Node* new_bb = rewrite_node(&ctx->rewriter, old->payload.jump.target); - Nodes args = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); - - Nodes* additional_ssa_params = find_value_dict(const Node*, Nodes, ctx->bb_new_args, old->payload.jump.target); - if (additional_ssa_params) { - assert(additional_ssa_params->count > 0); - - LARRAY(const Type*, tr_params_arr, args.count); - for (size_t i = 0; i < args.count; i++) - tr_params_arr[i] = var(a, args.nodes[i]->type, args.nodes[i]->payload.var.name); - Nodes tr_params = nodes(a, args.count, tr_params_arr); - Node* fn = (Node*) rewrite_node(&ctx->rewriter, ctx->scope->entry->node); - Node* trampoline = basic_block(a, fn, tr_params, format_string_interned(a, "%s_trampoline", get_abstraction_name(new_bb))); - Nodes tr_args = args; - BodyBuilder* bb = begin_body(a); - - for (size_t i = 0; i < additional_ssa_params->count; i++) { - const Node* ptr = additional_ssa_params->nodes[i]; - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, ptr); - const Node* value = get_known_value(&ctx->rewriter, k); - - const Type* known_value_t = value->type; - deconstruct_qualified_type(&known_value_t); - - const Type* alloca_type_t = k->source->type; - deconstruct_qualified_type(&alloca_type_t); - - if (alloca_type_t != known_value_t && is_reinterpret_cast_legal(alloca_type_t, known_value_t)) - value = first(gen_primop(bb, reinterpret_op, singleton(rewrite_node(&ctx->rewriter, alloca_type_t)), singleton(value))); - - assert(value); - args = append_nodes(a, args, value); - } - - trampoline->payload.basic_block.body = finish_body(bb, jump_helper(a, new_bb, args)); - - return jump_helper(a, trampoline, tr_args); - } - - return jump_helper(a, new_bb, args); + assert(false); } default: break; } - return recreate_node_identity(&ctx->rewriter, old); } @@ -549,11 +657,15 @@ Module* opt_mem2reg(const CompilerConfig* config, Module* src) { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .bb_new_args = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), .a = new_arena(), + + .todo_jumps = NULL, }; ctx.rewriter.config.fold_quote = false; + // ctx.rewriter.config.rebind_let = false; rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); destroy_dict(ctx.bb_new_args); destroy_arena(ctx.a); From 9c4750323ca3b76e397fb99fb6ee437be5df04d0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 21:41:23 +0100 Subject: [PATCH 023/693] demote_alloca: fix broken behavior when ptr params are involved --- src/shady/passes/opt_demote_alloca.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 219dca534..1eb4b99e1 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -130,20 +130,23 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { assert(is_value(ptr)); if (ptr->tag == Variable_TAG) { const Node* instr = get_var_instruction(ctx->scope_uses, ptr); - PrimOp payload = instr->payload.prim_op; - switch (payload.op) { - case alloca_logical_op: - case alloca_op: { - k.src_alloca = *find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, instr); - return k; - } - case convert_op: - case reinterpret_op: { - ptr = first(payload.operands); - continue; + if (instr) { + PrimOp payload = instr->payload.prim_op; + switch (payload.op) { + case alloca_logical_op: + case alloca_op: { + k.src_alloca = *find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, instr); + return k; + } + case convert_op: + case reinterpret_op: { + ptr = first(payload.operands); + continue; + } + // TODO: lea and co + default: + break; } - // TODO: lea and co - default: break; } } From 65d3260b3840827c5b247a8fd4ec1c2b8da16a8b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 21:42:04 +0100 Subject: [PATCH 024/693] removed BB inlining code from opt_inline since cleanup does it now --- src/shady/compile.c | 4 +-- src/shady/passes/opt_inline.c | 55 ++--------------------------------- src/shady/passes/passes.h | 2 -- 3 files changed, 4 insertions(+), 57 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index f2f3bfaca..6eb6267a4 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -82,8 +82,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(normalize_builtins); RUN_PASS(infer_program) - RUN_PASS(opt_inline_jumps) - RUN_PASS(lcssa) RUN_PASS(reconvergence_heuristics) @@ -108,7 +106,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_tailcalls) RUN_PASS(lower_switch_btree) RUN_PASS(opt_restructurize) - RUN_PASS(opt_inline_jumps) + //RUN_PASS(opt_mem2reg) RUN_PASS(lower_mask) RUN_PASS(lower_memcpy) diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 26fda811b..15075c73b 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -19,7 +19,6 @@ typedef struct { CallGraph* graph; const Node* old_fun; Node* fun; - bool allow_fn_inlining; struct Dict* inlined_return_sites; } Context; @@ -138,37 +137,6 @@ static const Node* process(Context* ctx, const Node* node) { destroy_scope(scope); return new; } - case Jump_TAG: { - const Node* otarget = node->payload.jump.target; - assert(otarget && otarget->tag == BasicBlock_TAG); - assert(otarget->payload.basic_block.fn == ctx->scope->entry->node); - CFNode* cfnode = scope_lookup(ctx->scope, otarget); - assert(cfnode); - size_t preds_count = entries_count_list(cfnode->pred_edges); - assert(preds_count > 0 && "this CFG looks broken"); - if (preds_count == 1) { - debugv_print("Inlining jump to %s inside function %s\n", get_abstraction_name(otarget), get_abstraction_name(ctx->old_fun)); - Nodes nargs = rewrite_nodes(&ctx->rewriter, node->payload.jump.args); - return inline_call(ctx, otarget, nargs, false); - } - break; - } - // do not inline jumps in branches - case Branch_TAG: { - return branch(a, (Branch) { - .branch_condition = rewrite_node(&ctx->rewriter, node->payload.branch.branch_condition), - .true_jump = recreate_node_identity(&ctx->rewriter, node->payload.branch.true_jump), - .false_jump = recreate_node_identity(&ctx->rewriter, node->payload.branch.false_jump), - }); - } - case Switch_TAG: { - return br_switch(a, (Switch) { - .switch_value = rewrite_node(&ctx->rewriter, node->payload.br_switch.switch_value), - .case_values = rewrite_nodes(&ctx->rewriter, node->payload.br_switch.case_values), - .case_jumps = rewrite_nodes_with_fn(&ctx->rewriter, node->payload.br_switch.case_jumps, recreate_node_identity), - .default_jump = recreate_node_identity(&ctx->rewriter, node->payload.br_switch.default_jump), - }); - } case Call_TAG: { if (!ctx->graph) break; @@ -222,14 +190,6 @@ static const Node* process(Context* ctx, const Node* node) { } break; } - case BasicBlock_TAG: { - Nodes params = recreate_variables(&ctx->rewriter, node->payload.basic_block.params); - register_processed_list(&ctx->rewriter, node->payload.basic_block.params, params); - Node* bb = basic_block(a, (Node*) ctx->fun, params, node->payload.basic_block.name); - register_processed(&ctx->rewriter, node, bb); - bb->payload.basic_block.body = process(ctx, node->payload.basic_block.body); - return bb; - } default: break; } @@ -242,7 +202,7 @@ static const Node* process(Context* ctx, const Node* node) { KeyHash hash_node(const Node**); bool compare_node(const Node**, const Node**); -void opt_simplify_cf(SHADY_UNUSED const CompilerConfig* config, Module* src, Module* dst, bool allow_fn_inlining) { +void opt_simplify_cf(SHADY_UNUSED const CompilerConfig* config, Module* src, Module* dst) { Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .graph = NULL, @@ -250,8 +210,7 @@ void opt_simplify_cf(SHADY_UNUSED const CompilerConfig* config, Module* src, Mod .fun = NULL, .inlined_return_sites = new_dict(const Node*, CGNode*, (HashFn) hash_node, (CmpFn) compare_node), }; - if (allow_fn_inlining) - ctx.graph = new_callgraph(src); + ctx.graph = new_callgraph(src); rewrite_module(&ctx.rewriter); if (ctx.graph) @@ -261,18 +220,10 @@ void opt_simplify_cf(SHADY_UNUSED const CompilerConfig* config, Module* src, Mod destroy_dict(ctx.inlined_return_sites); } -Module* opt_inline_jumps(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); - Module* dst = new_module(a, get_module_name(src)); - opt_simplify_cf(config, src, dst, false); - return dst; -} - Module* opt_inline(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); - opt_simplify_cf(config, src, dst, true); + opt_simplify_cf(config, src, dst); return dst; } diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index e11d2d408..7e2dfc75d 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -107,8 +107,6 @@ RewritePass lower_fill; RewritePass eliminate_constants; /// Tags all functions that don't need special handling RewritePass mark_leaf_functions; -/// Inlines basic blocks used exactly once, necessary after opt_restructure -RewritePass opt_inline_jumps; /// In addition, also inlines function calls according to heuristics RewritePass opt_inline; RewritePass opt_mem2reg; From 377b953679c60b24e04247dc41e93e951fbc1d96 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 21:42:27 +0100 Subject: [PATCH 025/693] fix lower_alloca and lower_stack ordering --- src/shady/compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 6eb6267a4..612f5e06b 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -111,9 +111,9 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_mask) RUN_PASS(lower_memcpy) RUN_PASS(lower_subgroup_ops) - RUN_PASS(lower_stack) RUN_PASS(lower_alloca) + RUN_PASS(lower_stack) RUN_PASS(lower_lea) RUN_PASS(lower_generic_globals) RUN_PASS(lower_generic_ptrs) From 10bc82497768986fc3e4b904e13091a28c9f5f81 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 22:06:42 +0100 Subject: [PATCH 026/693] treat scheduler code mostly normally --- src/shady/compile.c | 5 ++--- src/shady/internal/scheduler.slim | 30 +++++++++++++++--------------- src/shady/passes/opt_mem2reg.c | 23 +++++++++++++++-------- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 612f5e06b..7b43b7bc3 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -86,7 +86,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(reconvergence_heuristics) RUN_PASS(lower_cf_instrs) - RUN_PASS(opt_mem2reg) + RUN_PASS(opt_mem2reg) // run mem2reg because control-flow is now normalized RUN_PASS(setup_stack_frames) if (!config->hacks.force_join_point_lifting) RUN_PASS(mark_leaf_functions) @@ -95,7 +95,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(opt_inline) RUN_PASS(lift_indirect_targets) - RUN_PASS(opt_demote_alloca) RUN_PASS(opt_mem2reg) // run mem2reg because we can now weaken non-leaking allocas if (config->specialization.execution_model != EmNone) @@ -106,7 +105,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_tailcalls) RUN_PASS(lower_switch_btree) RUN_PASS(opt_restructurize) - //RUN_PASS(opt_mem2reg) + RUN_PASS(opt_mem2reg) RUN_PASS(lower_mask) RUN_PASS(lower_memcpy) diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index afc9112cb..003310704 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -21,7 +21,7 @@ @Internal @Builtin("SubgroupLocalInvocationId") input u32 subgroup_local_id; -@Internal @Structured @DisablePass("setup_stack_frames") @Leaf +@Internal @Leaf fn builtin_init_scheduler() { val init_mask = subgroup_active_mask(); @@ -32,7 +32,7 @@ fn builtin_init_scheduler() { actual_subgroup_size = subgroup_reduce_sum(u32 1); } -@Internal @Structured @DisablePass("setup_stack_frames") @Leaf +@Internal @Leaf fn builtin_entry_join_point uniform JoinPoint() { val init_mask = subgroup_active_mask(); @@ -41,7 +41,7 @@ fn builtin_entry_join_point uniform JoinPoint() { return (jp); } -@Internal @Structured @Leaf +@Internal @Leaf fn builtin_create_control_point varying JoinPoint(uniform u32 join_destination, varying u32 payload) { val curr_mask = subgroup_active_mask(); val depth = subgroup_broadcast_first(scheduler_vector#(subgroup_local_id)#1); @@ -54,7 +54,7 @@ fn builtin_create_control_point varying JoinPoint(uniform u32 join_destination, return (jp); } -@Internal @Structured @Leaf +@Internal @Leaf fn builtin_fork(varying u32 branch_destination) { val first_branch = subgroup_broadcast_first(branch_destination); @@ -89,7 +89,7 @@ fn builtin_fork(varying u32 branch_destination) { } } -@Internal @Structured @Leaf +@Internal @Leaf fn builtin_yield(uniform u32 resume_target) { resume_at#(subgroup_local_id) = resume_target; // resume_with#(subgroup_local_id) = subgroup_active_mask(); @@ -103,7 +103,7 @@ fn builtin_yield(uniform u32 resume_target) { } } -@Internal @Structured @Leaf +@Internal @Leaf fn builtin_join(varying u32 join_at, varying TreeNode token) { resume_at#(subgroup_local_id) = join_at; scheduler_vector#(subgroup_local_id) = token; @@ -114,7 +114,7 @@ fn builtin_join(varying u32 join_at, varying TreeNode token) { } } -@Internal @Structured @Leaf +@Internal @Leaf fn is_parent bool(varying TreeNode child, varying TreeNode maybe_parent) { val child_mask = child#0; val parent_mask = maybe_parent#0; @@ -124,32 +124,32 @@ fn is_parent bool(varying TreeNode child, varying TreeNode maybe_parent) { return (child_depth >= parent_depth); } -@Internal @Structured @Leaf +@Internal @Leaf fn forward_distance u32(varying u32 x, varying u32 dst, varying u32 max_mod) { var u32 t = dst - x; t = t % max_mod; return (t); } -@Internal @Structured @Leaf +@Internal @Leaf fn reduce2 u32(varying u32 a_index, varying u32 b_index) { val a = scheduler_vector#a_index; val b = scheduler_vector#b_index; - + if (is_parent(a, b)) { return (a_index); } if (is_parent(b, a)) { return (b_index); } - + val a_dist = forward_distance(a_index, scheduler_cursor, actual_subgroup_size); val b_dist = forward_distance(b_index, scheduler_cursor, actual_subgroup_size); - + if (a_dist < b_dist) { return (a_index); } return (b_index); } -@Internal @Structured @Leaf +@Internal @Leaf fn builtin_find_schedulable_leaf() { var u32 reduced = u32 0; - loop (uniform u32 i = u32 1) { + loop (varying u32 i = u32 1) { if (i >= actual_subgroup_size) { break; } reduced = reduce2(reduced, i); continue(i + u32 1); @@ -160,7 +160,7 @@ fn builtin_find_schedulable_leaf() { return (); } -@Internal @Structured @Leaf +@Internal @Leaf fn builtin_get_active_branch mask_t() { val this_thread_branch = scheduler_vector#(subgroup_local_id); val same_dest = resume_at#(subgroup_local_id) == next_fn; diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index cb6fa8d3d..8d31b1029 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -138,21 +138,23 @@ static void destroy_kb(KnowledgeBase* kb) { } static KnowledgeBase* get_kb(Context* ctx, const Node* abs) { + assert(ctx->scope); KnowledgeBase** found = find_value_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, abs); assert(found); return *found; } static KnowledgeBase* create_kb(Context* ctx, const Node* old) { + assert(ctx->scope); arena_alloc(ctx->a, sizeof(KnowledgeBase)); CFNode* cf_node = scope_lookup(ctx->scope, old); KnowledgeBase* kb = arena_alloc(ctx->a, sizeof(KnowledgeBase)); *kb = (KnowledgeBase) { - .cfnode = cf_node, - .a = ctx->a, - .map = new_dict(const Node*, PtrKnowledge*, (HashFn) hash_node, (CmpFn) compare_node), - .potential_additional_params = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .dominator_kb = NULL, + .cfnode = cf_node, + .a = ctx->a, + .map = new_dict(const Node*, PtrKnowledge*, (HashFn) hash_node, (CmpFn) compare_node), + .potential_additional_params = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .dominator_kb = NULL, }; // log_string(DEBUGVV, "Creating KB for "); // log_node(DEBUGVV, old); @@ -232,6 +234,7 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No switch (is_instruction(oinstruction)) { case NotAnInstruction: assert(is_instruction(oinstruction)); case Instruction_Call_TAG: + wipe_all_leaked_pointers(kb); break; case Instruction_PrimOp_TAG: { PrimOp payload = oinstruction->payload.prim_op; @@ -376,11 +379,11 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No case Instruction_Match_TAG: break; case Instruction_Loop_TAG: - assert(false && "unsupported"); + mark_values_as_escaping(kb, oinstruction->payload.loop_instr.initial_args); + // assert(false && "unsupported"); break; } - // wipe_all_leaked_pointers(kb); return recreate_node_identity(r, oinstruction); } @@ -592,7 +595,11 @@ static const Node* process(Context* ctx, const Node* old) { } KnowledgeBase* kb = NULL; - if (old->tag == Function_TAG && !lookup_annotation(old, "Internal")) { + if (old->tag == Function_TAG) { + // if (lookup_annotation(old, "Internal")) { + // fn_ctx.scope = NULL; + // return recreate_node_identity(&fn_ctx.rewriter, old);; + // } fn_ctx.scope = new_scope(old); fn_ctx.abs_to_kb = new_dict(const Node*, KnowledgeBase**, (HashFn) hash_node, (CmpFn) compare_node); fn_ctx.todo_jumps = new_list(TodoJump), From a7329c328c027bb2687e8e044757e64582137822 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 22:06:54 +0100 Subject: [PATCH 027/693] fold undef conversions into undef --- src/shady/fold.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shady/fold.c b/src/shady/fold.c index 19a4030b7..83a0c1c17 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -251,6 +251,9 @@ break; } case reinterpret_op: case convert_op: + if (first(payload.operands)->tag == Undef_TAG) { + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + } // get rid of identity casts if (payload.type_arguments.nodes[0] == get_unqualified_type(payload.operands.nodes[0]->type)) return quote_single(arena, payload.operands.nodes[0]); From b513103ab4c2627c5e13c58089a76989a0211c87 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 21 Jan 2024 22:07:18 +0100 Subject: [PATCH 028/693] cleanup: do a fixed-point demote_alloca --- src/shady/passes/cleanup.c | 31 ++++++++++++++++++---------- src/shady/passes/opt_demote_alloca.c | 24 ++++++++++++++++----- src/shady/passes/passes.h | 3 ++- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 1102aa2c4..c51d3f253 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -9,7 +9,7 @@ typedef struct { Rewriter rewriter; const UsesMap* map; - bool* todo; + bool todo; } Context; static size_t count_calls(const UsesMap* map, const Node* bb) { @@ -63,7 +63,7 @@ const Node* process(Context* ctx, const Node* old) { debug_print("Cleanup: found an unused instruction: "); log_node(DEBUG, payload.instruction); debug_print("\n"); - *ctx->todo = true; + ctx->todo = true; return rewrite_node(&ctx->rewriter, get_abstraction_body(tail_case)); } break; @@ -93,23 +93,32 @@ const Node* process(Context* ctx, const Node* old) { return recreate_node_identity(&ctx->rewriter, old);; } -Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* src) { +OptPass simplify; + +bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { + Module* src = *m; + + IrArena* a = new_ir_arena(get_arena_config(get_module_arena(*m))); + *m = new_module(a, get_module_name(*m)); + Context ctx = { .todo = false }; + ctx.rewriter = create_rewriter(src, *m, (RewriteNodeFn) process), + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + return ctx.todo; +} + +Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); if (!aconfig.check_types) return src; - IrArena* a = new_ir_arena(aconfig); bool todo; - Context ctx = { .todo = &todo }; size_t r = 0; - Module* m; + Module* m = src; do { debug_print("Cleanup round %d\n", r); todo = false; - m = new_module(a, get_module_name(src)); - ctx.rewriter = create_rewriter(src, m, (RewriteNodeFn) process), - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); - src = m; + todo |= simplify(config, &m); + todo |= opt_demote_alloca(config, &m); r++; } while (todo); return m; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 1eb4b99e1..337e14ea0 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -24,6 +24,7 @@ typedef struct Context_ { const CompilerConfig* config; Arena* arena; struct Dict* alloca_info; + bool todo; } Context; typedef struct { @@ -209,10 +210,14 @@ static const Node* process(Context* ctx, const Node* old) { log_node(DEBUGV, old); debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); if (!k->leaks) { - if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) + if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { + ctx->todo |= true; return quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}))); - if (!k->non_logical_use && get_arena_config(a).optimisations.weaken_non_leaking_allocas) + } + if (!k->non_logical_use && get_arena_config(a).optimisations.weaken_non_leaking_allocas) { + ctx->todo |= true; return prim_op_helper(a, alloca_logical_op, rewrite_nodes(&ctx->rewriter, payload.type_arguments), rewrite_nodes(r, payload.operands)); + } } break; } @@ -221,6 +226,9 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca) { const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.operands.nodes[0]->type))); if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { + if (k.src_alloca->bound != rewrite_node(r, first(payload.operands))) + break; + ctx->todo |= true; BodyBuilder* bb = begin_body(a); const Node* data = gen_load(bb, k.src_alloca->bound); data = gen_reinterpret_cast(bb, access_type, data); @@ -234,6 +242,9 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca) { const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.operands.nodes[0]->type))); if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { + if (k.src_alloca->bound != rewrite_node(r, first(payload.operands))) + break; + ctx->todo |= true; BodyBuilder* bb = begin_body(a); const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.operands.nodes[1])); gen_store(bb, k.src_alloca->bound, data); @@ -255,7 +266,8 @@ static const Node* process(Context* ctx, const Node* old) { KeyHash hash_node(const Node**); bool compare_node(const Node**, const Node**); -Module* opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { +bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { + Module* src = *m; ArenaConfig aconfig = get_arena_config(get_module_arena(src)); IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); @@ -263,12 +275,14 @@ Module* opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .arena = new_arena(), - .alloca_info = new_dict(const Node, AllocaInfo, (HashFn) hash_node, (CmpFn) compare_node) + .alloca_info = new_dict(const Node, AllocaInfo, (HashFn) hash_node, (CmpFn) compare_node), + .todo = false }; ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); destroy_dict(ctx.alloca_info); destroy_arena(ctx.arena); - return dst; + *m = dst; + return ctx.todo; } diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 7e2dfc75d..fee940885 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -3,6 +3,7 @@ #include "shady/ir.h" typedef Module* (RewritePass)(const CompilerConfig* config, Module* src); +typedef bool (OptPass)(const CompilerConfig* config, Module** m); /// @name Boring, regular compiler stuff /// @{ @@ -110,7 +111,7 @@ RewritePass mark_leaf_functions; /// In addition, also inlines function calls according to heuristics RewritePass opt_inline; RewritePass opt_mem2reg; -RewritePass opt_demote_alloca; +OptPass opt_demote_alloca; /// Try to identify reconvergence points throughout the program for unstructured control flow programs RewritePass reconvergence_heuristics; From bbdc15a4154fe677da581d39b306615f1db6418f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 11:15:12 +0100 Subject: [PATCH 029/693] opt_inline: simplified and fixed bugs --- src/shady/passes/opt_inline.c | 103 +++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 15075c73b..0990775c5 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -10,16 +10,19 @@ #include "../type.h" #include "../ir_private.h" -#include "../analysis/scope.h" #include "../analysis/callgraph.h" +typedef struct { + const Node* host_fn; + const Node* return_jp; +} InlinedCall; + typedef struct { Rewriter rewriter; - Scope* scope; CallGraph* graph; const Node* old_fun; Node* fun; - struct Dict* inlined_return_sites; + InlinedCall* inlined_call; } Context; static const Node* ignore_immediate_fn_addr(const Node* node) { @@ -30,13 +33,21 @@ static const Node* ignore_immediate_fn_addr(const Node* node) { } static bool is_call_potentially_inlineable(const Node* src_fn, const Node* dst_fn) { - if (lookup_annotation(src_fn, "Leaf")) + if (lookup_annotation(src_fn, "Internal")) return false; if (lookup_annotation(dst_fn, "NoInline")) return false; return true; } +static bool is_call_safely_removable(const Node* fn) { + if (lookup_annotation(fn, "Internal")) + return false; + if (lookup_annotation(fn, "EntryPoint")) + return false; + return true; +} + typedef struct { size_t num_calls; size_t num_inlineable_calls; @@ -58,7 +69,7 @@ static FnInliningCriteria get_inlining_heuristic(CGNode* fn_node) { debugv_print("%s has %d callers\n", get_abstraction_name(fn_node->fn), crit.num_calls); // a function can be inlined if it has exactly one inlineable call... - if (crit.num_inlineable_calls == 1) + if (crit.num_inlineable_calls <= 1) crit.can_be_inlined = true; // avoid inlining recursive things for now @@ -73,43 +84,50 @@ static FnInliningCriteria get_inlining_heuristic(CGNode* fn_node) { if (fn_node->is_address_captured) crit.can_be_eliminated = false; + if (!is_call_safely_removable(fn_node->fn)) + crit.can_be_eliminated = false; + return crit; } /// inlines the abstraction with supplied arguments -static const Node* inline_call(Context* ctx, const Node* oabs, Nodes nargs, bool separate_scope) { - assert(is_abstraction(oabs)); +static const Node* inline_call(Context* ctx, const Node* ocallee, Nodes nargs, const Node* return_to) { + assert(is_abstraction(ocallee)); + log_string(DEBUG, "Inlining '%s' inside '%s'\n", get_abstraction_name(ctx->fun), get_abstraction_name(ocallee)); Context inline_context = *ctx; - if (separate_scope) - inline_context.rewriter.map = clone_dict(inline_context.rewriter.map); - Nodes oparams = get_abstraction_params(oabs); - register_processed_list(&inline_context.rewriter, oparams, nargs); + inline_context.rewriter.map = clone_dict(inline_context.rewriter.map); - if (oabs->tag == Function_TAG) - inline_context.scope = new_scope(oabs); + ctx = &inline_context; + InlinedCall inlined_call = { + .host_fn = ctx->fun, + .return_jp = return_to, + }; + inline_context.inlined_call = &inlined_call; - const Node* nbody = rewrite_node(&inline_context.rewriter, get_abstraction_body(oabs)); + Nodes oparams = get_abstraction_params(ocallee); + register_processed_list(&inline_context.rewriter, oparams, nargs); - if (oabs->tag == Function_TAG) - destroy_scope(inline_context.scope); + const Node* nbody = rewrite_node(&inline_context.rewriter, get_abstraction_body(ocallee)); - if (separate_scope) - destroy_dict(inline_context.rewriter.map); + destroy_dict(inline_context.rewriter.map); assert(is_terminator(nbody)); return nbody; } static const Node* process(Context* ctx, const Node* node) { + if (!node) + return NULL; + const Node* found = search_processed(&ctx->rewriter, node); + if (found) + return found; + IrArena* a = ctx->rewriter.dst_arena; - if (!node) return NULL; + Rewriter* r = &ctx->rewriter; assert(a != node->arena); assert(node->arena == ctx->rewriter.src_arena); - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - switch (node->tag) { case Function_TAG: { if (ctx->graph) { @@ -122,19 +140,17 @@ static const Node* process(Context* ctx, const Node* node) { Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); Node* new = function(ctx->rewriter.dst_module, recreate_variables(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); - for (size_t i = 0; i < new->payload.fun.params.count; i++) - register_processed(&ctx->rewriter, node->payload.fun.params.nodes[i], new->payload.fun.params.nodes[i]); - register_processed(&ctx->rewriter, node, new); + register_processed(r, node, new); Context fn_ctx = *ctx; - Scope* scope = new_scope(node); fn_ctx.rewriter.map = clone_dict(fn_ctx.rewriter.map); - fn_ctx.scope = scope; fn_ctx.old_fun = node; fn_ctx.fun = new; + fn_ctx.inlined_call = NULL; + for (size_t i = 0; i < new->payload.fun.params.count; i++) + register_processed(&fn_ctx.rewriter, node->payload.fun.params.nodes[i], new->payload.fun.params.nodes[i]); recreate_decl_body_identity(&fn_ctx.rewriter, node, new); destroy_dict(fn_ctx.rewriter.map); - destroy_scope(scope); return new; } case Call_TAG: { @@ -154,11 +170,8 @@ static const Node* process(Context* ctx, const Node* node) { Nodes nyield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); const Node* join_point = var(a, qualified_type_helper(jp_type, true), format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); - insert_dict_and_get_result(const Node*, const Node*, ctx->inlined_return_sites, ocallee, join_point); - - const Node* nbody = inline_call(ctx, ocallee, nargs, true); - remove_dict(const Node*, ctx->inlined_return_sites, ocallee); + const Node* nbody = inline_call(ctx, ocallee, nargs, join_point); return control(a, (Control) { .yield_types = nyield_types, @@ -168,10 +181,23 @@ static const Node* process(Context* ctx, const Node* node) { } break; } + case BasicBlock_TAG: { + const Node* ofn = node->payload.basic_block.fn; + const Node* nfn; + if (ctx->inlined_call) + nfn = ctx->inlined_call->host_fn; + else + nfn = rewrite_node(r, ofn); + Nodes nparams = recreate_variables(r, get_abstraction_params(node)); + register_processed_list(r, get_abstraction_params(node), nparams); + Node* bb = basic_block(a, (Node*) nfn, nparams, get_abstraction_name(node)); + register_processed(r, node, bb); + bb->payload.basic_block.body = rewrite_node(r, get_abstraction_body(node)); + return bb; + } case Return_TAG: { - const Node** p_ret_jp = find_value_dict(const Node*, const Node*, ctx->inlined_return_sites, node); - if (p_ret_jp) - return join(a, (Join) { .join_point = *p_ret_jp, .args = rewrite_nodes(&ctx->rewriter, node->payload.fn_ret.args )}); + if (ctx->inlined_call) + return join(a, (Join) { .join_point = ctx->inlined_call->return_jp, .args = rewrite_nodes(r, node->payload.fn_ret.args )}); break; } case TailCall_TAG: { @@ -184,8 +210,7 @@ static const Node* process(Context* ctx, const Node* node) { if (get_inlining_heuristic(fn_node).can_be_inlined) { debugv_print("Inlining tail call to %s\n", get_abstraction_name(ocallee)); Nodes nargs = rewrite_nodes(&ctx->rewriter, node->payload.tail_call.args); - - return inline_call(ctx, ocallee, nargs, true); + return inline_call(ctx, ocallee, nargs, NULL); } } break; @@ -206,9 +231,8 @@ void opt_simplify_cf(SHADY_UNUSED const CompilerConfig* config, Module* src, Mod Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .graph = NULL, - .scope = NULL, .fun = NULL, - .inlined_return_sites = new_dict(const Node*, CGNode*, (HashFn) hash_node, (CmpFn) compare_node), + .inlined_call = NULL, }; ctx.graph = new_callgraph(src); @@ -217,7 +241,6 @@ void opt_simplify_cf(SHADY_UNUSED const CompilerConfig* config, Module* src, Mod destroy_callgraph(ctx.graph); destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.inlined_return_sites); } Module* opt_inline(const CompilerConfig* config, Module* src) { From ea843d0c1b8ac7992ebbf585752de11960da23c8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 11:16:36 +0100 Subject: [PATCH 030/693] more alloca fixes --- src/shady/passes/lower_alloca.c | 23 ++++++++++++++++------- src/shady/passes/setup_stack_frames.c | 8 +++++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 2f7a87dbc..f8df498a2 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -24,6 +24,8 @@ typedef struct Context_ { const Node* entry_stack_offset; size_t num_slots; const Node* frame_size; + + const Type* stack_ptr_t; } Context; typedef struct { @@ -89,8 +91,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); if (!ctx2.disable_lowering) { - String tmp_name = format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun)); - ctx2.entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_pointer_op } ), (String []) { tmp_name })); + ctx2.entry_stack_offset = NULL; ctx2.entry_base_stack_ptr = gen_primop_ce(bb, get_stack_base_op, 0, NULL); Node* nom_t = nominal_type(m, empty(a), format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); @@ -117,7 +118,7 @@ static const Node* process(Context* ctx, const Node* node) { destroy_list(vctx.members); ctx2.num_slots = vctx.num_slots; ctx2.frame_size = gen_primop_e(bb, size_of_op, singleton(type_decl_ref_helper(a, vctx.nom_t)), empty(a)); - ctx2.frame_size = convert_int_extend_according_to_src_t(bb, get_unqualified_type(ctx2.entry_stack_offset->type), ctx2.frame_size); + ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); } if (node->payload.fun.body) fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); @@ -139,16 +140,23 @@ static const Node* process(Context* ctx, const Node* node) { } BodyBuilder* bb = begin_body(a); + if (!ctx->entry_stack_offset) { + //String tmp_name = format_string_arena(a->arena, "stack_ptr_before_alloca_%s", get_abstraction_name(fun)); + String tmp_name = "stack_ptr_before_alloca"; + ctx->entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_pointer_op } ), (String []) { tmp_name })); + } + //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); - const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, ctx->entry_base_stack_ptr, found_slot->offset)); + const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); + const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, ctx->entry_base_stack_ptr, gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->entry_stack_offset, converted_offset)))); const Node* slot = first(bind_instruction_named(bb, lea_instr, (String []) { format_string_arena(a->arena, "stack_slot_%d", found_slot->i) })); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = gen_reinterpret_cast(bb, ptr_t, slot); - bool last = found_slot->i == ctx->num_slots - 1; - if (last) { + //bool last = found_slot->i == ctx->num_slots - 1; + //if (last) { const Node* updated_stack_ptr = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->entry_stack_offset, ctx->frame_size)); gen_primop(bb, set_stack_pointer_op, empty(a), singleton(updated_stack_ptr)); - } + //} return yield_values_and_wrap_in_block(bb, singleton(slot)); } @@ -166,6 +174,7 @@ Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .config = config, + .stack_ptr_t = int_type(a, (Int) { .is_signed = false, .width = IntTy32 }), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 8d084737a..06adeef97 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -26,9 +26,10 @@ static const Node* process(Context* ctx, const Node* node) { if (found) return found; IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; switch (node->tag) { case Function_TAG: { - Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); + Node* fun = recreate_decl_header_identity(r, node); Context ctx2 = *ctx; ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames"); @@ -52,10 +53,11 @@ static const Node* process(Context* ctx, const Node* node) { .operands = nodes(a, 1, (const Node* []) {ctx->entry_stack_offset }) })); } - return finish_body(bb, recreate_node_identity(&ctx->rewriter, node)); + return finish_body(bb, recreate_node_identity(r, node)); } - default: return recreate_node_identity(&ctx->rewriter, node); + default: break; } + return recreate_node_identity(r, node); } Module* setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* src) { From 518494033cbad4440a5f075407682b85feeea992 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 15:56:34 +0100 Subject: [PATCH 031/693] debug: print post-passes IR after cleanup --- src/shady/compile.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shady/compile.h b/src/shady/compile.h index b6e147b21..809935002 100644 --- a/src/shady/compile.h +++ b/src/shady/compile.h @@ -16,8 +16,6 @@ old_mod = *pmod; \ *pmod = pass_name(config, *pmod); \ (*pmod)->sealed = true; \ -debugvv_print("After "#pass_name" pass: \n"); \ -log_module(DEBUGVV, config, *pmod); \ if (SHADY_RUN_VERIFY) \ verify_module(*pmod); \ if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) \ @@ -25,6 +23,8 @@ if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old old_mod = *pmod; \ if (config->optimisations.cleanup.after_every_pass) \ *pmod = cleanup(config, *pmod); \ +debugvv_print("After "#pass_name" pass: \n"); \ +log_module(DEBUGVV, config, *pmod); \ if (SHADY_RUN_VERIFY) \ verify_module(*pmod); \ if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) \ From 377cf1c6b554a89ff23f60353aef0e90f502120e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 15:56:59 +0100 Subject: [PATCH 032/693] change cleanup passes order to have zero dangling quotes --- src/shady/passes/cleanup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index c51d3f253..396dffa62 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -117,8 +117,8 @@ Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { do { debug_print("Cleanup round %d\n", r); todo = false; - todo |= simplify(config, &m); todo |= opt_demote_alloca(config, &m); + todo |= simplify(config, &m); r++; } while (todo); return m; From d18d1c84422d0860d59da1ede5f5ed8eae1e039c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 15:57:26 +0100 Subject: [PATCH 033/693] fix demote_alloca --- src/shady/passes/opt_demote_alloca.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 337e14ea0..4d1396bb2 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -51,7 +51,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca else if (use->user->tag == Let_TAG && use->operand_class == NcInstruction) { Nodes vars = get_abstraction_params(get_let_tail(use->user)); for (size_t i = 0; i < vars.count; i++) { - debugv_print("mem2reg leak analysis: following let-bound variable: "); + debugv_print("demote_alloca leak analysis: following let-bound variable: "); log_node(DEBUGV, vars.nodes[i]); debugv_print(".\n"); visit_ptr_uses(vars.nodes[i], slice_type, k, map); @@ -226,7 +226,7 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca) { const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.operands.nodes[0]->type))); if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { - if (k.src_alloca->bound != rewrite_node(r, first(payload.operands))) + if (k.src_alloca->bound == rewrite_node(r, first(payload.operands))) break; ctx->todo |= true; BodyBuilder* bb = begin_body(a); @@ -242,7 +242,7 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca) { const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.operands.nodes[0]->type))); if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { - if (k.src_alloca->bound != rewrite_node(r, first(payload.operands))) + if (k.src_alloca->bound == rewrite_node(r, first(payload.operands))) break; ctx->todo |= true; BodyBuilder* bb = begin_body(a); From 7cad0310bba4ec8a1fc7eec5fadfec72d54bb523 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 16:01:05 +0100 Subject: [PATCH 034/693] prevent the tests from being optimized into mush by opt_inline --- src/shady/passes/opt_inline.c | 2 ++ test/arrays.slim | 1 - test/comments.slim | 1 - test/constant_in_use.slim | 1 - test/control_flow1.slim | 1 + test/control_flow2.slim | 1 + test/functions1.slim | 2 ++ test/generic_ptrs1.slim | 4 ++++ test/generic_ptrs2.slim | 1 + test/identity.slim | 1 + test/math.slim | 1 + test/memory1.slim | 2 ++ test/memory2.slim | 1 + test/opt/mem2reg1.slim | 1 + test/opt/mem2reg2.slim | 17 +++++++++++++++++ test/opt/mem2reg3.slim | 15 +++++++++------ test/rec_pow.slim | 1 + test/rec_pow2.slim | 2 ++ test/restructure1.slim | 2 ++ test/restructure2.slim | 2 ++ test/subgroup_var.slim | 1 + 21 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 0990775c5..d5f95dbf7 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -45,6 +45,8 @@ static bool is_call_safely_removable(const Node* fn) { return false; if (lookup_annotation(fn, "EntryPoint")) return false; + if (lookup_annotation(fn, "Exported")) + return false; return true; } diff --git a/test/arrays.slim b/test/arrays.slim index 5c5cc054a..368cf6a47 100644 --- a/test/arrays.slim +++ b/test/arrays.slim @@ -1,4 +1,3 @@ - type T = struct { f32 x; f32 y; diff --git a/test/comments.slim b/test/comments.slim index 2c7ac5435..3a1587957 100644 --- a/test/comments.slim +++ b/test/comments.slim @@ -1,4 +1,3 @@ - // trivial function that does nothing @EntryPoint("Compute") @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn main() { diff --git a/test/constant_in_use.slim b/test/constant_in_use.slim index ae800e585..f8495cc58 100644 --- a/test/constant_in_use.slim +++ b/test/constant_in_use.slim @@ -1,4 +1,3 @@ - const i32 NINE = 9; const i32 TEN = 10; diff --git a/test/control_flow1.slim b/test/control_flow1.slim index 55f70e77e..24003e571 100644 --- a/test/control_flow1.slim +++ b/test/control_flow1.slim @@ -1,3 +1,4 @@ +@Exported fn extend varying i32(varying bool b) { val extended = if i32 (b) { yield(1); diff --git a/test/control_flow2.slim b/test/control_flow2.slim index 4c833b3a9..52d6be049 100644 --- a/test/control_flow2.slim +++ b/test/control_flow2.slim @@ -1,3 +1,4 @@ +@Exported fn fac varying i32(varying i32 count) { val x = loop i32 (varying i32 i = 1, varying i32 a = 1) { val r = lt(i, count); // if i < count diff --git a/test/functions1.slim b/test/functions1.slim index 36241b2f1..01ea3d5e0 100644 --- a/test/functions1.slim +++ b/test/functions1.slim @@ -1,7 +1,9 @@ +@Exported fn identity varying i32(varying i32 i) { return(i); } +@Exported fn f varying i32 (varying i32 i) { val j = identity(i); val k = add(j, 1); diff --git a/test/generic_ptrs1.slim b/test/generic_ptrs1.slim index 26db2aafe..bd627ffd5 100644 --- a/test/generic_ptrs1.slim +++ b/test/generic_ptrs1.slim @@ -1,15 +1,19 @@ +@Exported fn foo1 ptr generic i32(varying ptr global i32 x) { return (convert[ptr generic i32](x)); } +@Exported fn foo2 ptr generic i32(varying ptr shared i32 x) { return (convert[ptr generic i32](x)); } +@Exported fn foo3 ptr generic i32(varying ptr subgroup i32 x) { return (convert[ptr generic i32](x)); } +@Exported fn foo4 ptr generic i32(varying ptr private i32 x) { return (convert[ptr generic i32](x)); } diff --git a/test/generic_ptrs2.slim b/test/generic_ptrs2.slim index f1745a6f7..0b2a1c62c 100644 --- a/test/generic_ptrs2.slim +++ b/test/generic_ptrs2.slim @@ -1,3 +1,4 @@ +@Exported fn foo i32(varying ptr generic i32 x) { return (load(x)); } \ No newline at end of file diff --git a/test/identity.slim b/test/identity.slim index df8ac2f39..b152635b8 100644 --- a/test/identity.slim +++ b/test/identity.slim @@ -1,4 +1,5 @@ // trivial function that returns its argument +@Exported fn identity i32(varying i32 i) { return (i); } diff --git a/test/math.slim b/test/math.slim index d2a6a946f..e55854f89 100644 --- a/test/math.slim +++ b/test/math.slim @@ -1,3 +1,4 @@ +@Exported fn foo f32(varying f32 x) { return (sqrt(x)); } diff --git a/test/memory1.slim b/test/memory1.slim index 23c6d6479..5c9f187c8 100644 --- a/test/memory1.slim +++ b/test/memory1.slim @@ -2,10 +2,12 @@ @DescriptorBinding(0) global i32 extern_int; +@Exported fn read_from_extern i32() { return (extern_int); } +@Exported fn read_from_global_ptr i32(uniform ptr global i32 global_ptr) { val loaded = load(global_ptr); return(loaded); diff --git a/test/memory2.slim b/test/memory2.slim index ccb8dfcf8..814b4a008 100644 --- a/test/memory2.slim +++ b/test/memory2.slim @@ -1,3 +1,4 @@ +@Exported fn alloca_load_store i32() { val a = alloca[i32](); store(a, 9); diff --git a/test/opt/mem2reg1.slim b/test/opt/mem2reg1.slim index 992833fa8..d0dcd1d87 100644 --- a/test/opt/mem2reg1.slim +++ b/test/opt/mem2reg1.slim @@ -1,3 +1,4 @@ +@Exported fn f varying i32() { var i32 i = 0; i = 1; diff --git a/test/opt/mem2reg2.slim b/test/opt/mem2reg2.slim index f87f56fc0..098475494 100644 --- a/test/opt/mem2reg2.slim +++ b/test/opt/mem2reg2.slim @@ -1,3 +1,4 @@ +@Exported fn f varying i32(varying i32 x) { var i32 i = 0; branch ((x > 0), t, j); @@ -7,6 +8,22 @@ fn f varying i32(varying i32 x) { jump j(); } + cont j() { + i = 1; + return (i); + } +} + +@Exported +fn g varying i32(varying i32 x) { + var i32 i = 0; + branch ((x > 0), t, j); + + cont t() { + i = x; + jump j(); + } + cont j() { return (i); } diff --git a/test/opt/mem2reg3.slim b/test/opt/mem2reg3.slim index c0b0aaf6d..2bf5addbd 100644 --- a/test/opt/mem2reg3.slim +++ b/test/opt/mem2reg3.slim @@ -1,15 +1,18 @@ -fn f varying f32(varying i32 x) { - var i32 i = 0; +@Exported +fn f varying f32() { + var i32 i = 1116340224; // 69.0f return (*(reinterpret[ptr private f32](&i))); } -fn g varying i32(varying i32 x) { - var i32 i = 0; +@Exported +fn g varying i32() { + var i32 i = 420; return (*(convert[ptr generic i32](&i))); } -fn h varying f32(varying i32 x) { - var i32 i = 0; +@Exported +fn h varying f32() { + var i32 i = 1116340224; // 69.0f val p = &i; val p1 = (reinterpret[ptr private f32](&i)); val p2 = convert[ptr generic f32](p1); diff --git a/test/rec_pow.slim b/test/rec_pow.slim index a1f72803e..42ed9ff0d 100644 --- a/test/rec_pow.slim +++ b/test/rec_pow.slim @@ -1,3 +1,4 @@ +@Exported fn rec_pow i32(varying i32 x, varying i32 y) { if (y > 1) { return (x * rec_pow(x, y - 1)); diff --git a/test/rec_pow2.slim b/test/rec_pow2.slim index 91af62059..101505bc1 100644 --- a/test/rec_pow2.slim +++ b/test/rec_pow2.slim @@ -1,7 +1,9 @@ +@Exported fn rec_pow_chain_helper i32(varying i32 x, varying i32 y) { return (rec_pow_chain(x, y)); } +@Exported fn rec_pow_chain i32(varying i32 x, varying i32 y) { if (y > 1) { return (x * rec_pow_chain_helper(x, y - 1)); diff --git a/test/restructure1.slim b/test/restructure1.slim index b51eba4e0..ca028114b 100644 --- a/test/restructure1.slim +++ b/test/restructure1.slim @@ -4,6 +4,7 @@ // /!\ there is no reconvergence happening in this function (except for the return itself) // to reconverge, one needs to use the control() construct, such as demonstrated in restructure3 // to be absolutely clear: two distinct sets of threads will execute two different dynamic instances bb3 +@Exported fn f i32(varying bool b) { branch (b, bb1(), bb2()); @@ -23,6 +24,7 @@ fn f i32(varying bool b) { // f is equivalent (and should be turned back into) this function: // (modulo some dataflow jank that opt passes may or may not cleanup) +@Exported fn g i32(varying bool b) { val r = if i32(b) { // blah diff --git a/test/restructure2.slim b/test/restructure2.slim index aa89e2e03..9bf6238ce 100644 --- a/test/restructure2.slim +++ b/test/restructure2.slim @@ -2,6 +2,7 @@ // such loops are only allowed if there is only one path through them that involves a back-edge // in other words: no implicit synchronisation at the loop header +@Exported fn f i32(varying bool b) { jump bb1(); @@ -15,6 +16,7 @@ fn f i32(varying bool b) { } // the behaviour should be equivalent to this structured code: +@Exported fn g i32(varying bool b) { loop() { if (b) { diff --git a/test/subgroup_var.slim b/test/subgroup_var.slim index 594ab32ee..72dd2e308 100644 --- a/test/subgroup_var.slim +++ b/test/subgroup_var.slim @@ -1,5 +1,6 @@ subgroup i32 x; +@Exported fn foo uniform i32() { return (x); } From 0d444d5021c78aa445a1507f3fa99f899cc4d944 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 16:03:23 +0100 Subject: [PATCH 035/693] mem2reg: fix broken dominance assumption wrt special edge types --- src/shady/compile.c | 4 ++-- src/shady/passes/opt_mem2reg.c | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 7b43b7bc3..e9ef74eff 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -86,7 +86,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(reconvergence_heuristics) RUN_PASS(lower_cf_instrs) - RUN_PASS(opt_mem2reg) // run mem2reg because control-flow is now normalized + RUN_PASS(opt_mem2reg) // run because control-flow is now normalized RUN_PASS(setup_stack_frames) if (!config->hacks.force_join_point_lifting) RUN_PASS(mark_leaf_functions) @@ -95,7 +95,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(opt_inline) RUN_PASS(lift_indirect_targets) - RUN_PASS(opt_mem2reg) // run mem2reg because we can now weaken non-leaking allocas + RUN_PASS(opt_mem2reg) // run because we can now weaken non-leaking allocas if (config->specialization.execution_model != EmNone) RUN_PASS(specialize_execution_model) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 8d31b1029..f4e63d040 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -162,10 +162,12 @@ static KnowledgeBase* create_kb(Context* ctx, const Node* old) { if (entries_count_list(cf_node->pred_edges) == 1) { CFEdge edge = read_list(CFEdge, cf_node->pred_edges)[0]; assert(edge.dst == cf_node); - CFNode* dominator = edge.src; - const KnowledgeBase* parent_kb = get_kb(ctx, dominator->node); - assert(parent_kb->map); - kb->dominator_kb = parent_kb; + if (edge.type == LetTailEdge || edge.type == JumpEdge) { + CFNode* dominator = edge.src; + const KnowledgeBase* parent_kb = get_kb(ctx, dominator->node); + assert(parent_kb->map); + kb->dominator_kb = parent_kb; + } } assert(kb->map); insert_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, old, kb); From c3e1bac75dfd98192a1380d1b5046bf8384f94fe Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 17:46:36 +0100 Subject: [PATCH 036/693] vcc: added ternary.c test --- test/vcc/CMakeLists.txt | 1 + test/vcc/ternary.c | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 test/vcc/ternary.c diff --git a/test/vcc/CMakeLists.txt b/test/vcc/CMakeLists.txt index 335dfdf3d..359f11c55 100644 --- a/test/vcc/CMakeLists.txt +++ b/test/vcc/CMakeLists.txt @@ -10,6 +10,7 @@ endforeach() spv_outputting_test(NAME test/vcc/branch.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/loop.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/goto.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) +spv_outputting_test(NAME test/vcc/ternary.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/vec_swizzle.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point test --no-dynamic-scheduling --execution-model Fragment) diff --git a/test/vcc/ternary.c b/test/vcc/ternary.c new file mode 100644 index 000000000..ce927cc7d --- /dev/null +++ b/test/vcc/ternary.c @@ -0,0 +1,5 @@ +#include + +int pick(int a, int b, bool c) { + return c ? a : b; +} \ No newline at end of file From 913a387b6bde341b4708592ee8e9bfc90734a846 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 18:16:39 +0100 Subject: [PATCH 037/693] l2s: handle trunc to i1 --- src/frontends/llvm/l2s_instr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index b806776e6..bb861340b 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -234,6 +234,11 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM const Node* zero = int_literal(a, (IntLiteral) { .value = 0, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); const Node* one = int_literal(a, (IntLiteral) { .value = 1, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); r = prim_op_helper(a, select_op, empty(a), mk_nodes(a, first(ops), one, zero)); + } else if (t->tag == Bool_TAG) { + assert(src_t->tag == Int_TAG); + const Node* one = int_literal(a, (IntLiteral) { .value = 1, .width = src_t->payload.int_type.width, .is_signed = false }); + r = prim_op_helper(a, and_op, empty(a), mk_nodes(a, first(ops), one)); + r = prim_op_helper(a, eq_op, empty(a), mk_nodes(a, first(BIND_PREV_R(int_type(a, (Int) { .width = src_t->payload.int_type.width, .is_signed = false }))), one)); } else { // reinterpret as unsigned, convert to change size, reinterpret back to target T const Type* unsigned_src_t = change_int_t_sign(src_t, false); From e20946cdfe41007b1d72474f03e53930a48b2f8c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 18:16:53 +0100 Subject: [PATCH 038/693] l2s: slap "Exported" on all fns for now --- src/frontends/llvm/l2s.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 0597654da..e2a77210c 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -110,7 +110,9 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { const Type* fn_type = convert_type(p, LLVMGlobalGetValueType(fn)); assert(fn_type->tag == FnType_TAG); assert(fn_type->payload.fn_type.param_types.count == params.count); - Node* f = function(p->dst, params, LLVMGetValueName(fn), empty(a), fn_type->payload.fn_type.return_types); + Nodes annotations = empty(a); + annotations = append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Exported" })); + Node* f = function(p->dst, params, LLVMGetValueName(fn), annotations, fn_type->payload.fn_type.return_types); const Node* r = fn_addr_helper(a, f); insert_dict(LLVMValueRef, const Node*, p->map, fn, r); From 7b0c707cdb526b96d9acb8505a118a2ad9c349a6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 18:17:13 +0100 Subject: [PATCH 039/693] l2s: deal with phis --- src/frontends/llvm/l2s.c | 17 ++++++++++++++++- src/frontends/llvm/l2s_instr.c | 32 +++++++++++++++++++++++++++----- src/frontends/llvm/l2s_private.h | 5 +++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index e2a77210c..92e776bd9 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -2,6 +2,7 @@ #include "log.h" #include "dict.h" +#include "list.h" #include "util.h" #include "llvm-c/IRReader.h" @@ -59,12 +60,16 @@ const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb) { if (found) return *found; IrArena* a = get_module_arena(p->dst); + struct List* phis = new_list(LLVMValueRef); Nodes params = empty(a); LLVMValueRef instr = LLVMGetFirstInstruction(bb); while (instr) { switch (LLVMGetInstructionOpcode(instr)) { case LLVMPHI: { - assert(false); + const Node* nparam = var(a, convert_type(p, LLVMTypeOf(instr)), "phi"); + insert_dict(LLVMValueRef, const Node*, p->map, instr, nparam); + append_list(LLVMValueRef, phis, instr); + params = append_nodes(a, params, nparam); break; } default: goto after_phis; @@ -78,6 +83,7 @@ const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb) { name = unique_name(a, "bb"); Node* nbb = basic_block(a, fn, params, name); insert_dict(LLVMValueRef, const Node*, p->map, bb, nbb); + insert_dict(const Node*, struct List*, p->phis, nbb, phis); BodyBuilder* b = begin_body(a); nbb->payload.basic_block.body = write_bb_tail(p, nbb, b, bb, instr); return nbb; @@ -186,6 +192,7 @@ bool parse_llvm_into_shady(Module* dst, size_t len, const char* data) { .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .scopes = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), + .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), .annotations_arena = new_arena(), .src = src, .dst = dirty, @@ -208,6 +215,14 @@ bool parse_llvm_into_shady(Module* dst, size_t len, const char* data) { destroy_dict(p.map); destroy_dict(p.annotations); destroy_dict(p.scopes); + { + size_t i = 0; + struct List* phis_list; + while (dict_iter(p.phis, &i, NULL, &phis_list)) { + destroy_list(phis_list); + } + } + destroy_dict(p.phis); destroy_arena(p.annotations_arena); LLVMContextDispose(context); diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index bb861340b..23459cf0a 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -3,6 +3,7 @@ #include "portability.h" #include "log.h" #include "dict.h" +#include "list.h" #include "../shady/type.h" @@ -54,6 +55,27 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { return v; } +static const Node* convert_jump(Parser* p, Node* fn, Node* fn_or_bb, LLVMBasicBlockRef dst) { + IrArena* a = fn->arena; + const Node* dst_bb = convert_basic_block(p, fn, dst); + BBPhis* phis = find_value_dict(const Node*, BBPhis, p->phis, dst_bb); + assert(phis); + size_t params_count = entries_count_list(phis->list); + LARRAY(const Node*, params, params_count); + for (size_t i = 0; i < params_count; i++) { + LLVMValueRef phi = read_list(LLVMValueRef, phis->list)[i]; + for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { + if (convert_basic_block(p, fn, LLVMGetIncomingBlock(phi, j)) == fn_or_bb) { + params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); + goto next; + } + } + assert(false && "failed to find the appropriate source"); + next: continue; + } + return jump_helper(a, dst_bb, nodes(a, params_count, params)); +} + /// instr may be an instruction or a constantexpr EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { Node* fn = fn_or_bb; @@ -110,23 +132,23 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM }; case LLVMBr: { unsigned n_successors = LLVMGetNumSuccessors(instr); - LARRAY(const Node*, targets, n_successors); + LARRAY(LLVMBasicBlockRef , targets, n_successors); for (size_t i = 0; i < n_successors; i++) - targets[i] = convert_basic_block(p, fn, LLVMGetSuccessor(instr, i)); + targets[i] = LLVMGetSuccessor(instr, i); if (LLVMIsConditional(instr)) { assert(n_successors == 2); const Node* condition = convert_value(p, LLVMGetCondition(instr)); return (EmittedInstr) { .terminator = branch(a, (Branch) { .branch_condition = condition, - .true_jump = jump_helper(a, targets[0], empty(a)), - .false_jump = jump_helper(a, targets[1], empty(a)), + .true_jump = convert_jump(p, fn, fn_or_bb, targets[0]), + .false_jump = convert_jump(p, fn, fn_or_bb, targets[1]), }) }; } else { assert(n_successors == 1); return (EmittedInstr) { - .terminator = jump_helper(a, targets[0], empty(a)) + .terminator = convert_jump(p, fn, fn_or_bb, targets[0]) }; } } diff --git a/src/frontends/llvm/l2s_private.h b/src/frontends/llvm/l2s_private.h index b2e7b2283..91d28d06a 100644 --- a/src/frontends/llvm/l2s_private.h +++ b/src/frontends/llvm/l2s_private.h @@ -15,6 +15,7 @@ typedef struct { struct Dict* map; struct Dict* annotations; struct Dict* scopes; + struct Dict* phis; Arena* annotations_arena; LLVMModuleRef src; Module* dst; @@ -52,6 +53,10 @@ typedef struct { Nodes result_types; } EmittedInstr; +typedef struct { + struct List* list; +} BBPhis; + EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc); From c3cdbd0bdd6bb812bfdf6b777c60bebe23fa6890 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 18:18:52 +0100 Subject: [PATCH 040/693] opt_inline: do not inline fns without a body! --- src/shady/passes/opt_inline.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index d5f95dbf7..12e59045a 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -37,6 +37,8 @@ static bool is_call_potentially_inlineable(const Node* src_fn, const Node* dst_f return false; if (lookup_annotation(dst_fn, "NoInline")) return false; + if (!dst_fn->payload.fun.body) + return false; return true; } From 20df51eade9abf83f8495dd26a2985771fad7a9a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 19:35:33 +0100 Subject: [PATCH 041/693] lower_generic_ptrs: enable uniform loads to behave as expected --- src/shady/passes/lower_generic_ptrs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 27aab375a..5230a21bf 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -76,7 +76,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo IrArena* a = ctx->rewriter.dst_arena; String name; switch (which) { - case LoadFn: name = format_string_interned(a, "generated_load_Generic_%s", name_type_safe(a, t)); break; + case LoadFn: name = format_string_interned(a, "generated_load_Generic_%s%s", name_type_safe(a, t), uniform_ptr ? "_uniform" : ""); break; case StoreFn: name = format_string_interned(a, "generated_store_Generic_%s", name_type_safe(a, t)); break; } @@ -84,13 +84,13 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo if (found) return *found; - const Node* ptr_param = var(a, qualified_type_helper(ctx->generic_ptr_type, false), "ptr"); + const Node* ptr_param = var(a, qualified_type_helper(ctx->generic_ptr_type, uniform_ptr), "ptr"); const Node* value_param; Nodes params = singleton(ptr_param); Nodes return_ts = empty(a); switch (which) { case LoadFn: - return_ts = singleton(qualified_type_helper(t, false)); + return_ts = singleton(qualified_type_helper(t, uniform_ptr)); break; case StoreFn: value_param = var(a, qualified_type_helper(t, false), "value"); @@ -221,10 +221,11 @@ static const Node* process(Context* ctx, const Node* old) { } case load_op: { const Type* old_ptr_t = first(old->payload.prim_op.operands)->type; - deconstruct_qualified_type(&old_ptr_t); + bool u = deconstruct_qualified_type(&old_ptr_t); + u &= is_addr_space_uniform(a, old_ptr_t->payload.ptr_type.address_space); if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { return call(a, (Call) { - .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, false, rewrite_node(&ctx->rewriter, old_ptr_t->payload.ptr_type.pointed_type))), + .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, u, rewrite_node(&ctx->rewriter, old_ptr_t->payload.ptr_type.pointed_type))), .args = singleton(rewrite_node(&ctx->rewriter, first(old->payload.prim_op.operands))), }); } From 628a81a7a169db32feb4af9f8114a9cd6202fe2c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jan 2024 19:35:47 +0100 Subject: [PATCH 042/693] shady.h: added uniform_constant and uniform_block --- vcc-std/include/shady.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index a5a7c20ec..cc3b31aed 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -20,7 +20,10 @@ namespace vcc { #define input __attribute__((address_space(389))) #define output __attribute__((address_space(390))) +// maybe deprecate it ? #define uniform __attribute__((annotate("shady::uniform"))) +#define uniform_constant __attribute__((address_space(398))) +#define uniform_block __attribute__((address_space(395))) #define push_constant __attribute__((address_space(392))) #define global __attribute__((address_space(1))) #define private __attribute__((address_space(5))) From be900e4db6d632700777285f5a764930f2d592dc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 23 Jan 2024 11:23:04 +0100 Subject: [PATCH 043/693] fix some memory leaks --- src/shady/passes/cleanup.c | 4 ++-- src/shady/passes/opt_demote_alloca.c | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 396dffa62..d8fc3f6f2 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -98,7 +98,7 @@ OptPass simplify; bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { Module* src = *m; - IrArena* a = new_ir_arena(get_arena_config(get_module_arena(*m))); + IrArena* a = get_module_arena(src); *m = new_module(a, get_module_name(*m)); Context ctx = { .todo = false }; ctx.rewriter = create_rewriter(src, *m, (RewriteNodeFn) process), @@ -121,5 +121,5 @@ Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { todo |= simplify(config, &m); r++; } while (todo); - return m; + return import(config, m); } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 4d1396bb2..cde917e19 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -178,9 +178,11 @@ static const Node* process(Context* ctx, const Node* old) { const Node* otail = get_let_tail(old); const Node* ninstruction = rewrite_node(r, oinstruction); AllocaInfo** found_info = find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, oinstruction); + AllocaInfo* info = NULL; if (found_info) { const Node* ovar = first(get_abstraction_params(otail)); - insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, ovar, found_info); + info = *found_info; + insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, ovar, info); } Nodes oparams = otail->payload.case_.params; Nodes ntypes = unwrap_multiple_yield_types(r->dst_arena, ninstruction->type); @@ -190,8 +192,8 @@ static const Node* process(Context* ctx, const Node* old) { new_params[i] = var(r->dst_arena, ntypes.nodes[i], oparams.nodes[i]->payload.var.name); register_processed(r, oparams.nodes[i], new_params[i]); } - if (found_info) - (*found_info)->bound = new_params[0]; + if (info) + info->bound = new_params[0]; const Node* nbody = rewrite_node(r, otail->payload.case_.body); const Node* tail = case_(r->dst_arena, nodes(r->dst_arena, oparams.count, new_params), nbody); return let(a, ninstruction, tail); @@ -268,14 +270,13 @@ bool compare_node(const Node**, const Node**); bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { Module* src = *m; - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + IrArena* a = get_module_arena(src); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .arena = new_arena(), - .alloca_info = new_dict(const Node, AllocaInfo, (HashFn) hash_node, (CmpFn) compare_node), + .alloca_info = new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), .todo = false }; ctx.rewriter.config.rebind_let = true; From fb8604de90ad3ce2c3eb7528678916c8468aa139 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 10:36:26 +0100 Subject: [PATCH 044/693] fix rpath issues with LLVM on macOS --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e4b98c444..65b05fafa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # required for MSVC set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1) From 27573936eed9069cda920caf3fa5104e3b709c08 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 11:08:51 +0100 Subject: [PATCH 045/693] split off split_composite from enter_composite --- src/shady/type.c | 2 +- src/shady/type.h | 1 + src/shady/type_helpers.c | 91 ++++++++++++++++++++-------------------- 3 files changed, 48 insertions(+), 46 deletions(-) diff --git a/src/shady/type.c b/src/shady/type.c index e7f2c9580..47eeaf8cb 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -774,13 +774,13 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* base_ptr_type = get_unqualified_type(base->type); assert(base_ptr_type->tag == PtrType_TAG && "lea expects a pointer as a base"); + const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; const Node* offset = prim_op.operands.nodes[1]; assert(offset); const Type* offset_type = offset->type; bool offset_uniform = deconstruct_qualified_type(&offset_type); assert(offset_type->tag == Int_TAG && "lea expects an integer offset"); - const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; const IntLiteral* lit = resolve_to_int_literal(offset); bool offset_is_zero = lit && lit->value == 0; diff --git a/src/shady/type.h b/src/shady/type.h index 14ad8350d..39152e3e6 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -35,6 +35,7 @@ Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); /// Returns the (possibly qualified) pointee type from a (possibly qualified) ptr type const Type* get_pointee_type(IrArena*, const Type*); +void step_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); void enter_composite(const Type** datatype, bool* u, Nodes indices, bool allow_entering_pack); /// Collects the annotated types in the list of variables diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 78270883e..435205745 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -54,59 +54,60 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { return type; } -void enter_composite(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack) { +void step_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack) { const Type* current_type = *datatype; + const Type* selector_type = selector->type; + bool selector_uniform = deconstruct_qualified_type(&selector_type); - for(size_t i = 0; i < indices.count; i++) { - const Node* selector = indices.nodes[i]; - const Type* selector_type = selector->type; - bool selector_uniform = deconstruct_qualified_type(&selector_type); - - assert(selector_type->tag == Int_TAG && "selectors must be integers"); - *uniform &= selector_uniform; - - try_again: - switch (current_type->tag) { - case RecordType_TAG: { - size_t selector_value = get_int_literal_value(*resolve_to_int_literal(selector), false); - assert(selector_value < current_type->payload.record_type.members.count); - current_type = current_type->payload.record_type.members.nodes[selector_value]; - continue; - } - case ArrType_TAG: { - current_type = current_type->payload.arr_type.element_type; - continue; - } - case TypeDeclRef_TAG: { - const Node* nom_decl = current_type->payload.type_decl_ref.decl; - assert(nom_decl->tag == NominalType_TAG); - current_type = nom_decl->payload.nom_type.body; - goto try_again; - } - case PackType_TAG: { - assert(allow_entering_pack); - assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a pack type need to be constant"); - size_t selector_value = get_int_literal_value(*resolve_to_int_literal(selector), false); - assert(selector_value < current_type->payload.pack_type.width); - current_type = current_type->payload.pack_type.element_type; - continue; - } + assert(selector_type->tag == Int_TAG && "selectors must be integers"); + *uniform &= selector_uniform; + + try_again: + switch (current_type->tag) { + case RecordType_TAG: { + size_t selector_value = get_int_literal_value(*resolve_to_int_literal(selector), false); + assert(selector_value < current_type->payload.record_type.members.count); + current_type = current_type->payload.record_type.members.nodes[selector_value]; + break; + } + case ArrType_TAG: { + current_type = current_type->payload.arr_type.element_type; + break; + } + case TypeDeclRef_TAG: { + const Node* nom_decl = current_type->payload.type_decl_ref.decl; + assert(nom_decl->tag == NominalType_TAG); + current_type = nom_decl->payload.nom_type.body; + goto try_again; + } + case PackType_TAG: { + assert(allow_entering_pack); + assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a pack type need to be constant"); + size_t selector_value = get_int_literal_value(*resolve_to_int_literal(selector), false); + assert(selector_value < current_type->payload.pack_type.width); + current_type = current_type->payload.pack_type.element_type; + break; + } // also remember to assert literals for the selectors ! - default: { - log_string(ERROR, "Trying to enter non-composite type '"); - log_node(ERROR, current_type); - log_string(ERROR, "' with selector '"); - log_node(ERROR, selector); - log_string(ERROR, "'."); - error(""); - } + default: { + log_string(ERROR, "Trying to enter non-composite type '"); + log_node(ERROR, current_type); + log_string(ERROR, "' with selector '"); + log_node(ERROR, selector); + log_string(ERROR, "'."); + error(""); } - i++; } - *datatype = current_type; } +void enter_composite(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack) { + for(size_t i = 0; i < indices.count; i++) { + const Node* selector = indices.nodes[i]; + step_composite(datatype, uniform, selector, allow_entering_pack); + } +} + Nodes get_variables_types(IrArena* arena, Nodes variables) { LARRAY(const Type*, arr, variables.count); for (size_t i = 0; i < variables.count; i++) { From 515ee206f7b772a5250e8aba264377615dff0c53 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 11:54:15 +0100 Subject: [PATCH 046/693] use vendored SPIRV-Headers from now on --- .gitmodules | 3 +++ CMakeLists.txt | 2 +- SPIRV-Headers | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) create mode 160000 SPIRV-Headers diff --git a/.gitmodules b/.gitmodules index 075ae1c91..0c1f5d5f4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "murmur3"] path = murmur3 url = https://github.com/PeterScott/murmur3 +[submodule "SPIRV-Headers"] + path = SPIRV-Headers + url = https://github.com/shady-gang/SPIRV-Headers.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 65b05fafa..13bc5f743 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ if (MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() -find_package(SPIRV-Headers REQUIRED) +add_subdirectory(SPIRV-Headers) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) diff --git a/SPIRV-Headers b/SPIRV-Headers new file mode 160000 index 000000000..82f7a40bb --- /dev/null +++ b/SPIRV-Headers @@ -0,0 +1 @@ +Subproject commit 82f7a40bbc35a85407e971c17e8666356d861064 From fd7ac4748a5cc47925cdbadcf1c8490342185cf1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 12:22:31 +0100 Subject: [PATCH 047/693] add default cases where switch (is_instruction(...)) is used --- src/shady/emit/c/emit_c_instructions.c | 1 + src/shady/emit/spirv/emit_spv_instructions.c | 1 + src/shady/passes/infer.c | 1 + src/shady/passes/opt_restructure.c | 7 +++---- src/shady/print.c | 1 + 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 21d7cb9f0..9b2e06621 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -765,5 +765,6 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_Control_TAG: error("TODO") case Instruction_Block_TAG: error("Should be eliminated by the compiler") case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; + default: error("TODO"); } } diff --git a/src/shady/emit/spirv/emit_spv_instructions.c b/src/shady/emit/spirv/emit_spv_instructions.c index dd09c5ed1..c620f857e 100644 --- a/src/shady/emit/spirv/emit_spv_instructions.c +++ b/src/shady/emit/spirv/emit_spv_instructions.c @@ -634,5 +634,6 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Match_TAG: emit_match(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.match_instr, results_count, results); break; case Loop_TAG: emit_loop(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.loop_instr, results_count, results); break; case Comment_TAG: break; + default: error("TODO: unhandled instruction"); } } diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index b9a952f89..c8c42cdfc 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -702,6 +702,7 @@ static const Node* _infer_instruction(Context* ctx, const Node* node, const Type case Control_TAG: return _infer_control(ctx, node, expected_type); case Block_TAG: return _infer_block (ctx, node, expected_type); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); + default: error("TODO") case NotAnInstruction: error("not an instruction"); } SHADY_UNREACHABLE; diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index a1f41fb54..7c3522562 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -180,10 +180,6 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case Instruction_Loop_TAG: case Instruction_Match_TAG: error("not supposed to exist in IR at this stage"); case Instruction_Block_TAG: error("Should be eliminated by the compiler"); - case Instruction_Comment_TAG: - case Instruction_PrimOp_TAG: { - break; - } case Instruction_Call_TAG: { const Node* callee = old_instr->payload.call.callee; if (callee->tag == FnAddr_TAG) { @@ -252,6 +248,9 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad const Node* tail_lambda = case_(a, empty(a), finish_body(bb2, exit_ladder)); return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), tail_lambda))); } + default: { + break; + } } return rebuild_let(ctx, body, recreate_node_identity(&ctx->rewriter, old_instr), exit_ladder); } diff --git a/src/shady/print.c b/src/shady/print.c index 3b9a8566b..5e103f9e8 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -530,6 +530,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { static void print_instruction(PrinterCtx* ctx, const Node* node) { switch (is_instruction(node)) { case NotAnInstruction: assert(false); break; + default: assert(false); case Instruction_Comment_TAG: { printf(GREY); printf("/* %s */", node->payload.comment.string); From ca3838cab2a0f4e9c1a6b32edb19bd2b1b3b83e2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 12:36:51 +0100 Subject: [PATCH 048/693] added print.h header for dealing with node printing --- include/shady/ir.h | 3 --- src/driver/driver.c | 3 ++- src/shady/print.c | 40 +++++++++++++++++++--------------------- src/shady/print.h | 26 ++++++++++++++++++++++++++ test/opt/opt_oracle.c | 5 +++-- 5 files changed, 50 insertions(+), 27 deletions(-) create mode 100644 src/shady/print.h diff --git a/include/shady/ir.h b/include/shady/ir.h index 8623b774d..6760644a0 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -341,8 +341,5 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig emitter_config, Modul void dump_cfg(FILE* file, Module*); void dump_loop_trees(FILE* output, Module* mod); -void dump_module(Module*); -void print_module_into_str(Module*, char** str_ptr, size_t*); -void dump_node(const Node* node); #endif diff --git a/src/driver/driver.c b/src/driver/driver.c index 7b09567c6..02cf7f8fd 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -1,11 +1,12 @@ #include "shady/ir.h" #include "shady/driver.h" +#include "shady/print.h" + #include "frontends/slim/parser.h" #include "list.h" #include "util.h" - #include "log.h" #include diff --git a/src/shady/print.c b/src/shady/print.c index 5e103f9e8..a2f5a4f1d 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1,3 +1,4 @@ +#include "print.h" #include "ir_private.h" #include "analysis/scope.h" #include "analysis/uses.h" @@ -16,16 +17,6 @@ #include typedef struct PrinterCtx_ PrinterCtx; -typedef void (*PrintFn)(PrinterCtx* ctx, char* format, ...); - -typedef struct { - bool skip_builtin; - bool skip_internal; - bool skip_generated; - bool print_ptrs; - bool color; - bool reparseable; -} PrintConfig; struct PrinterCtx_ { Printer* printer; @@ -942,46 +933,53 @@ static void print_mod_impl(PrinterCtx* ctx, Module* mod) { #undef print_node #undef printf -static void print_helper(Printer* printer, const Node* node, Module* mod, PrintConfig config) { +void print_module(Printer* printer, Module* mod, PrintConfig config) { + PrinterCtx ctx = { + .printer = printer, + .config = config, + }; + print_mod_impl(&ctx, mod); + flush(ctx.printer); + destroy_printer(ctx.printer); +} + +void print_node(Printer* printer, const Node* node, PrintConfig config) { PrinterCtx ctx = { .printer = printer, .config = config, }; - if (node) - print_node_impl(&ctx, node); - if (mod) - print_mod_impl(&ctx, mod); + print_node_impl(&ctx, node); flush(ctx.printer); destroy_printer(ctx.printer); } void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { Growy* g = new_growy(); - print_helper(open_growy_as_printer(g), node, NULL, (PrintConfig) { .reparseable = true }); + print_node(open_growy_as_printer(g), node, (PrintConfig) { .reparseable = true }); *size = growy_size(g); *str_ptr = growy_deconstruct(g); } void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { Growy* g = new_growy(); - print_helper(open_growy_as_printer(g), NULL, mod, (PrintConfig) { .reparseable = true, }); + print_module(open_growy_as_printer(g), mod, (PrintConfig) { .reparseable = true, }); *size = growy_size(g); *str_ptr = growy_deconstruct(g); } void dump_node(const Node* node) { - print_helper(open_file_as_printer(stdout), node, NULL, (PrintConfig) { .color = true }); + print_node(open_file_as_printer(stdout), node, (PrintConfig) { .color = true }); printf("\n"); } void dump_module(Module* mod) { - print_helper(open_file_as_printer(stdout), NULL, mod, (PrintConfig) { .color = true }); + print_module(open_file_as_printer(stdout), mod, (PrintConfig) { .color = true }); printf("\n"); } void log_node(LogLevel level, const Node* node) { if (level >= get_log_level()) - print_helper(open_file_as_printer(stderr), node, NULL, (PrintConfig) { .color = true }); + print_node(open_file_as_printer(stderr), node, (PrintConfig) { .color = true }); } void log_module(LogLevel level, CompilerConfig* compiler_cfg, Module* mod) { @@ -992,5 +990,5 @@ void log_module(LogLevel level, CompilerConfig* compiler_cfg, Module* mod) { config.skip_internal = compiler_cfg->logging.skip_internal; } if (level >= get_log_level()) - print_helper(open_file_as_printer(stderr), NULL, mod, config); + print_module(open_file_as_printer(stderr), mod, config); } diff --git a/src/shady/print.h b/src/shady/print.h new file mode 100644 index 000000000..852e9b4b9 --- /dev/null +++ b/src/shady/print.h @@ -0,0 +1,26 @@ +#ifndef SHADY_PRINT +#define SHADY_PRINT + +#include "shady/ir.h" +#include "printer.h" +#include + +typedef struct { + bool skip_builtin; + bool skip_internal; + bool skip_generated; + bool print_ptrs; + bool color; + bool reparseable; +} PrintConfig; + +void print_module(Printer* printer, Module* mod, PrintConfig config); +void print_node(Printer* printer, const Node* node, PrintConfig config); + +void print_module_into_str(Module* mod, char** str_ptr, size_t* size); +void print_node_into_str(const Node* node, char** str_ptr, size_t* size); + +void dump_module(Module*); +void dump_node(const Node* node); + +#endif \ No newline at end of file diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index b66aad4a0..04964c3da 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -1,9 +1,10 @@ #include "shady/ir.h" #include "shady/driver.h" -#include "log.h" +#include "shady/visit.h" +#include "shady/print.h" -#include "../src/shady/visit.h" +#include "log.h" #include #include From 308fa119a71dc75d68a25131d4efdcf8c7a75005 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 13:28:26 +0100 Subject: [PATCH 049/693] update spirv-headers --- SPIRV-Headers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPIRV-Headers b/SPIRV-Headers index 82f7a40bb..1c9115b56 160000 --- a/SPIRV-Headers +++ b/SPIRV-Headers @@ -1 +1 @@ -Subproject commit 82f7a40bbc35a85407e971c17e8666356d861064 +Subproject commit 1c9115b562bab79ee2160fbd845f41b815b9f21f From 4befd598f9ee8356dbc1feb4c38265cdc85cfef0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 13:29:21 +0100 Subject: [PATCH 050/693] produce an intermediate 'imported.json' file from the spirv.core file --- src/frontends/llvm/generator_l2s.c | 6 +- src/shady/api/generator_grammar.c | 28 ++++---- src/shady/api/generator_primops.c | 8 +-- src/shady/generator/CMakeLists.txt | 35 ++++++---- src/shady/generator/generator.c | 94 ++------------------------- src/shady/generator/generator.h | 8 +-- src/shady/generator/generator_main.c | 65 ++++++++++++++++++ src/shady/generator/import_spv_defs.c | 81 +++++++++++++++++++++++ src/shady/generator_constructors.c | 12 ++-- src/shady/generator_node.c | 18 ++--- src/shady/generator_primops.c | 6 +- src/shady/generator_rewrite.c | 6 +- src/shady/generator_type.c | 6 +- src/shady/generator_visit.c | 6 +- 14 files changed, 222 insertions(+), 157 deletions(-) create mode 100644 src/shady/generator/generator_main.c create mode 100644 src/shady/generator/import_spv_defs.c diff --git a/src/frontends/llvm/generator_l2s.c b/src/frontends/llvm/generator_l2s.c index 7fc35b42f..c205e5cb5 100644 --- a/src/frontends/llvm/generator_l2s.c +++ b/src/frontends/llvm/generator_l2s.c @@ -21,11 +21,11 @@ void generate_llvm_shady_address_space_conversion(Growy* g, json_object* address growy_append_formatted(g, "}\n"); } -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* src) { + generate_header(g, src); growy_append_formatted(g, "#include \"l2s_private.h\"\n"); growy_append_formatted(g, "#include \"log.h\"\n"); growy_append_formatted(g, "#include \n"); - generate_llvm_shady_address_space_conversion(g, json_object_object_get(data.shd, "address-spaces")); + generate_llvm_shady_address_space_conversion(g, json_object_object_get(src, "address-spaces")); } diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index e2783a4df..9e7018b29 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -1,7 +1,7 @@ #include "generator.h" -static json_object* lookup_node_class(Data data, String name) { - json_object* node_classes = json_object_object_get(data.shd, "node-classes"); +static json_object* lookup_node_class(json_object* src, String name) { + json_object* node_classes = json_object_object_get(src, "node-classes"); for (size_t i = 0; i < json_object_array_length(node_classes); i++) { json_object* class = json_object_array_get_idx(node_classes, i); String class_name = json_object_get_string(json_object_object_get(class, "name")); @@ -12,7 +12,7 @@ static json_object* lookup_node_class(Data data, String name) { return NULL; } -static String class_to_type(Data data, String class, bool list) { +static String class_to_type(json_object* src, String class, bool list) { assert(class); if (strcmp(class, "string") == 0) { if (list) @@ -21,20 +21,20 @@ static String class_to_type(Data data, String class, bool list) { return "String"; } // check the class is valid - if (!lookup_node_class(data, class)) { + if (!lookup_node_class(src, class)) { error_print("invalid node class '%s'\n", class); error_die(); } return list ? "Nodes" : "const Node*"; } -static String get_type_for_operand(Data data, json_object* op) { +static String get_type_for_operand(json_object* src, json_object* op) { String op_type = json_object_get_string(json_object_object_get(op, "type")); bool list = json_object_get_boolean(json_object_object_get(op, "list")); String op_class = NULL; if (!op_type) { op_class = json_object_get_string(json_object_object_get(op, "class")); - op_type = class_to_type(data, op_class, list); + op_type = class_to_type(src, op_class, list); } assert(op_type); return op_type; @@ -82,7 +82,7 @@ static void generate_node_tags(Growy* g, json_object* nodes) { growy_append_formatted(g, "} NodeTag;\n\n"); } -static void generate_node_payloads(Growy* g, Data data, json_object* nodes) { +static void generate_node_payloads(Growy* g, json_object* src, json_object* nodes) { for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -97,7 +97,7 @@ static void generate_node_payloads(Growy* g, Data data, json_object* nodes) { for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); - growy_append_formatted(g, "\t%s %s;\n", get_type_for_operand(data, op), op_name); + growy_append_formatted(g, "\t%s %s;\n", get_type_for_operand(src, op), op_name); } growy_append_formatted(g, "} %s;\n\n", name); } @@ -175,18 +175,18 @@ static void generate_node_tags_for_class(Growy* g, json_object* nodes, String cl growy_append_formatted(g, "} %sTag;\n\n", capitalized_class); } -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* src) { + generate_header(g, src); - generate_address_spaces(g, json_object_object_get(data.shd, "address-spaces")); + generate_address_spaces(g, json_object_object_get(src, "address-spaces")); - json_object* node_classes = json_object_object_get(data.shd, "node-classes"); + json_object* node_classes = json_object_object_get(src, "node-classes"); generate_bit_enum(g, "NodeClass", "Nc", node_classes); - json_object* nodes = json_object_object_get(data.shd, "nodes"); + json_object* nodes = json_object_object_get(src, "nodes"); generate_node_tags(g, nodes); growy_append_formatted(g, "NodeClass get_node_class_from_tag(NodeTag tag);\n\n"); - generate_node_payloads(g, data, nodes); + generate_node_payloads(g, src, nodes); generate_node_type(g, nodes); generate_node_ctor(g, nodes, false); diff --git a/src/shady/api/generator_primops.c b/src/shady/api/generator_primops.c index a2910f1d3..e4f6813a5 100644 --- a/src/shady/api/generator_primops.c +++ b/src/shady/api/generator_primops.c @@ -1,9 +1,9 @@ #include "generator.h" -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* src) { + generate_header(g, src); - json_object* nodes = json_object_object_get(data.shd, "prim-ops"); + json_object* nodes = json_object_object_get(src, "prim-ops"); growy_append_formatted(g, "typedef enum Op_ {\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { @@ -18,7 +18,7 @@ void generate(Growy* g, Data data) { growy_append_formatted(g, "\tPRIMOPS_COUNT,\n"); growy_append_formatted(g, "} Op;\n"); - json_object* op_classes = json_object_object_get(data.shd, "prim-ops-classes"); + json_object* op_classes = json_object_object_get(src, "prim-ops-classes"); generate_bit_enum(g, "OpClass", "Oc", op_classes); growy_append_formatted(g, "OpClass get_primop_class(Op);\n\n"); } diff --git a/src/shady/generator/CMakeLists.txt b/src/shady/generator/CMakeLists.txt index 8d3a61f07..b3a446b26 100644 --- a/src/shady/generator/CMakeLists.txt +++ b/src/shady/generator/CMakeLists.txt @@ -4,26 +4,35 @@ add_library(generator_common generator.c generator_common.c json_apply.c) target_link_libraries(generator_common PUBLIC common json-c::json-c) target_include_directories(generator_common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +add_executable(import_spv_defs import_spv_defs.c) +target_link_libraries(import_spv_defs PUBLIC common generator_common) + +# This hacky job is required for being able to run built targets in-place when generating the code +# This is also required for the various drivers but since they're built in the same directory it will work for now +if (WIN32) + message("copying DLLs for generator targets") + add_custom_command(TARGET import_spv_defs POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS + ) +endif () + +get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/imported.json COMMAND import_spv_defs ${CMAKE_CURRENT_BINARY_DIR}/imported.json ${SPIRV_HEADERS_INCLUDE_DIRS} DEPENDS ${GENERATOR_NAME} SPIRV-Headers::SPIRV-Headers VERBATIM) +add_custom_target(do_import_spv_defs DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/imported.json) + +set(SHADY_IMPORTED_JSON_PATH ${CMAKE_CURRENT_BINARY_DIR}/imported.json CACHE INTERNAL "path to imported.json") + function(add_generated_file) cmake_parse_arguments(PARSE_ARGV 0 F "" "FILE_NAME;TARGET_NAME" "SOURCES" ) set(GENERATOR_NAME generator_${F_FILE_NAME}) - add_executable(${GENERATOR_NAME} ${F_SOURCES}) + add_executable(${GENERATOR_NAME} ${F_SOURCES} ${CMAKE_SOURCE_DIR}/src/shady/generator/generator_main.c) target_link_libraries(${GENERATOR_NAME} generator_common) - get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} COMMAND ${GENERATOR_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} ${CMAKE_SOURCE_DIR}/include/shady/grammar.json ${CMAKE_SOURCE_DIR}/include/shady/primops.json ${SPIRV_HEADERS_INCLUDE_DIRS} DEPENDS ${GENERATOR_NAME} ${CMAKE_SOURCE_DIR}/include/shady/grammar.json ${CMAKE_SOURCE_DIR}/include/shady/primops.json VERBATIM) if ("${F_TARGET_NAME}" STREQUAL "") set(F_TARGET_NAME generate_${F_FILE_NAME}) endif () - add_custom_target(${F_TARGET_NAME} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME}) - # This hacky job is required for being able to run built targets in-place when generating the code - # This is also required for the various drivers but since they're built in the same directory it will work for now - if (WIN32) - message("copying DLLs: ${TARGET_DLLS}") - add_custom_command(TARGET ${GENERATOR_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy -t $ $ - COMMAND_EXPAND_LISTS - ) - endif () + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} COMMAND ${GENERATOR_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} "${SHADY_IMPORTED_JSON_PATH}" ${CMAKE_SOURCE_DIR}/include/shady/grammar.json ${CMAKE_SOURCE_DIR}/include/shady/primops.json DEPENDS do_import_spv_defs ${GENERATOR_NAME} ${CMAKE_SOURCE_DIR}/include/shady/grammar.json ${CMAKE_SOURCE_DIR}/include/shady/primops.json VERBATIM) + add_custom_target(${F_TARGET_NAME} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME}) endfunction() diff --git a/src/shady/generator/generator.c b/src/shady/generator/generator.c index 3930b8db1..75e542b42 100644 --- a/src/shady/generator/generator.c +++ b/src/shady/generator/generator.c @@ -62,10 +62,11 @@ String capitalize(String str) { return dst; } -void generate_header(Growy* g, Data data) { - int32_t major = json_object_get_int(json_object_object_get(data.spv, "major_version")); - int32_t minor = json_object_get_int(json_object_object_get(data.spv, "minor_version")); - int32_t revision = json_object_get_int(json_object_object_get(data.spv, "revision")); +void generate_header(Growy* g, json_object* root) { + json_object* spv = json_object_object_get(root, "spv"); + int32_t major = json_object_get_int(json_object_object_get(spv, "major_version")); + int32_t minor = json_object_get_int(json_object_object_get(spv, "minor_version")); + int32_t revision = json_object_get_int(json_object_object_get(spv, "revision")); growy_append_formatted(g, "/* Generated from SPIR-V %d.%d revision %d */\n", major, minor, revision); growy_append_formatted(g, "/* Do not edit this file manually ! */\n"); growy_append_formatted(g, "/* It is generated by the 'generator' target using Json grammar files. */\n\n"); @@ -80,88 +81,3 @@ bool starts_with_vowel(String str) { } return false; } - -enum { - ArgSelf = 0, - ArgDstFile, - ArgShadyGrammarJson, - ArgShadyPrimopsJson, - ArgSpirvGrammarSearchPathBegins -}; - -int main(int argc, char** argv) { - assert(argc > ArgSpirvGrammarSearchPathBegins); - - //char* mode = argv[ArgGeneratorFn]; - char* dst_file = argv[ArgDstFile]; - char* shd_grammar_json_path = argv[ArgShadyGrammarJson]; - char* shd_primops_json_path = argv[ArgShadyPrimopsJson]; - // search the include path for spirv.core.grammar.json - char* spv_core_json_path = NULL; - for (size_t i = ArgSpirvGrammarSearchPathBegins; i < argc; i++) { - char* path = format_string_new("%s/spirv/unified1/spirv.core.grammar.json", argv[i]); - info_print("trying path %s\n", path); - FILE* f = fopen(path, "rb"); - if (f) { - spv_core_json_path = path; - fclose(f); - break; - } - free(path); - } - - if (!spv_core_json_path) - abort(); - - json_tokener* tokener = json_tokener_new_ex(32); - enum json_tokener_error json_err; - - typedef struct { - size_t size; - char* contents; - json_object* root; - } JsonFile; - - String json_paths[3] = { shd_grammar_json_path, shd_primops_json_path, spv_core_json_path }; - JsonFile json_files[3]; - for (size_t i = 0; i < sizeof(json_files) / sizeof(json_files[0]); i++) { - String path = json_paths[i]; - read_file(path, &json_files[i].size, &json_files[i].contents); - json_files[i].root = json_tokener_parse_ex(tokener, json_files[i].contents, json_files[i].size); - json_err = json_tokener_get_error(tokener); - if (json_err != json_tokener_success) { - error("Json tokener error while parsing %s:\n %s\n", path, json_tokener_error_desc(json_err)); - } - - info_print("Correctly opened json file: %s\n", path); - } - Growy* g = new_growy(); - - Data data = { - .shd = json_object_new_object(), - .spv = json_files[2].root, - }; - - for (size_t i = 0; i < 2; i++) { - json_apply_object(data.shd, json_files[i].root); - } - - generate(g, data); - - size_t final_size = growy_size(g); - growy_append_bytes(g, 1, (char[]) { 0 }); - char* generated = growy_deconstruct(g); - debug_print("debug: %s\n", generated); - if (!write_file(dst_file, final_size, generated)) { - error_print("Failed to write file '%s'\n", dst_file); - error_die(); - } - free(generated); - for (size_t i = 0; i < sizeof(json_files) / sizeof(json_files[0]); i++) { - free(json_files[i].contents); - json_object_put(json_files[i].root); - } - json_object_put(data.shd); - json_tokener_free(tokener); - free(spv_core_json_path); -} diff --git a/src/shady/generator/generator.h b/src/shady/generator/generator.h index ad4b87931..8536cdcdf 100644 --- a/src/shady/generator/generator.h +++ b/src/shady/generator/generator.h @@ -14,14 +14,8 @@ #include typedef const char* String; -typedef struct { - json_object* shd; - json_object* spv; -} Data; -void generate(Growy* g, Data); - -void generate_header(Growy* g, Data data); +void generate_header(Growy* g, json_object* root); void add_comments(Growy* g, String indent, json_object* comments); String to_snake_case(String camel); String capitalize(String str); diff --git a/src/shady/generator/generator_main.c b/src/shady/generator/generator_main.c new file mode 100644 index 000000000..826f17b5d --- /dev/null +++ b/src/shady/generator/generator_main.c @@ -0,0 +1,65 @@ +#include "generator.h" + +#include "util.h" +#include "portability.h" + +void generate(Growy* g, json_object* root); + +enum { + ArgSelf = 0, + ArgDstFile, + ArgFirstInput, +}; + +int main(int argc, char** argv) { + assert(argc > ArgFirstInput); + int inputs_count = argc - ArgFirstInput; + char* dst_file = argv[ArgDstFile]; + + json_tokener* tokener = json_tokener_new_ex(32); + enum json_tokener_error json_err; + + typedef struct { + size_t size; + char* contents; + json_object* root; + } JsonFile; + + LARRAY(JsonFile, json_files, inputs_count); + for (size_t i = 0; i < inputs_count; i++) { + String path = argv[ArgFirstInput + i]; + read_file(path, &json_files[i].size, &json_files[i].contents); + json_files[i].root = json_tokener_parse_ex(tokener, json_files[i].contents, json_files[i].size); + json_err = json_tokener_get_error(tokener); + if (json_err != json_tokener_success) { + error("Json tokener error while parsing %s:\n %s\n", path, json_tokener_error_desc(json_err)); + } + + info_print("Correctly opened json file: %s\n", path); + } + Growy* g = new_growy(); + + json_object* src = json_object_new_object(); + + for (size_t i = 0; i < inputs_count; i++) { + json_apply_object(src, json_files[i].root); + } + + generate(g, src); + + size_t final_size = growy_size(g); + growy_append_bytes(g, 1, (char[]) { 0 }); + char* generated = growy_deconstruct(g); + debug_print("debug: %s\n", generated); + if (!write_file(dst_file, final_size, generated)) { + error_print("Failed to write file '%s'\n", dst_file); + error_die(); + } + free(generated); + for (size_t i = 0; i < sizeof(json_files) / sizeof(json_files[0]); i++) { + free(json_files[i].contents); + json_object_put(json_files[i].root); + } + json_object_put(src); + json_tokener_free(tokener); +} diff --git a/src/shady/generator/import_spv_defs.c b/src/shady/generator/import_spv_defs.c new file mode 100644 index 000000000..bb9992a2c --- /dev/null +++ b/src/shady/generator/import_spv_defs.c @@ -0,0 +1,81 @@ +#include "generator.h" + +#include "util.h" + +enum { + ArgSelf = 0, + ArgDstFile, + ArgSpirvGrammarSearchPathBegins +}; + +void import_spirv_defs(json_object* src, json_object* dst) { + json_object* spv = json_object_new_object(); + json_object_object_add(spv, "major_version", json_object_object_get(src, "major_version")); + json_object_object_add(spv, "minor_version", json_object_object_get(src, "minor_version")); + json_object_object_add(spv, "revision", json_object_object_get(src, "revision")); + json_object_object_add(dst, "spv", spv); +} + +int main(int argc, char** argv) { + assert(argc > ArgSpirvGrammarSearchPathBegins); + + //char* mode = argv[ArgGeneratorFn]; + char* dst_file = argv[ArgDstFile]; + // search the include path for spirv.core.grammar.json + char* spv_core_json_path = NULL; + for (size_t i = ArgSpirvGrammarSearchPathBegins; i < argc; i++) { + char* path = format_string_new("%s/spirv/unified1/spirv.core.grammar.json", argv[i]); + info_print("trying path %s\n", path); + FILE* f = fopen(path, "rb"); + if (f) { + spv_core_json_path = path; + fclose(f); + break; + } + free(path); + } + + if (!spv_core_json_path) + abort(); + + json_tokener* tokener = json_tokener_new_ex(32); + enum json_tokener_error json_err; + + typedef struct { + size_t size; + char* contents; + json_object* root; + } JsonFile; + + JsonFile json_file; + read_file(spv_core_json_path, &json_file.size, &json_file.contents); + json_file.root = json_tokener_parse_ex(tokener, json_file.contents, json_file.size); + json_err = json_tokener_get_error(tokener); + if (json_err != json_tokener_success) { + error("Json tokener error while parsing %s:\n %s\n", spv_core_json_path, json_tokener_error_desc(json_err)); + } + + info_print("Correctly opened json file: %s\n", spv_core_json_path); + + json_object* output = json_object_new_object(); + + import_spirv_defs(json_file.root, output); + + Growy* g = new_growy(); + growy_append_string(g, json_object_to_json_string(output)); + json_object_put(output); + + size_t final_size = growy_size(g); + growy_append_bytes(g, 1, (char[]) { 0 }); + char* generated = growy_deconstruct(g); + debug_print("debug: %s\n", generated); + if (!write_file(dst_file, final_size, generated)) { + error_print("Failed to write file '%s'\n", dst_file); + error_die(); + } + free(generated); + free(json_file.contents); + json_object_put(json_file.root); + json_tokener_free(tokener); + free(spv_core_json_path); +} diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 66d08a0e2..6b74f7b07 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -1,7 +1,7 @@ #include "generator.h" -static void generate_pre_construction_validation(Growy* g, Data data) { - json_object* nodes = json_object_object_get(data.shd, "nodes"); +static void generate_pre_construction_validation(Growy* g, json_object* src) { + json_object* nodes = json_object_object_get(src, "nodes"); growy_append_formatted(g, "void pre_construction_validation(IrArena* arena, Node* node) {\n"); growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); @@ -62,10 +62,10 @@ static void generate_pre_construction_validation(Growy* g, Data data) { growy_append_formatted(g, "}\n\n"); } -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* src) { + generate_header(g, src); - json_object* nodes = json_object_object_get(data.shd, "nodes"); + json_object* nodes = json_object_object_get(src, "nodes"); generate_node_ctor(g, nodes, true); - generate_pre_construction_validation(g, data); + generate_pre_construction_validation(g, src); } diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index f6aa94655..3148dc68e 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -32,7 +32,7 @@ static void generate_node_has_payload_array(Growy* g, json_object* nodes) { growy_append_formatted(g, "};\n\n"); } -static void generate_node_payload_hash_fn(Growy* g, Data data, json_object* nodes) { +static void generate_node_payload_hash_fn(Growy* g, json_object* src, json_object* nodes) { growy_append_formatted(g, "KeyHash hash_node_payload(const Node* node) {\n"); growy_append_formatted(g, "\tKeyHash hash = 0;\n"); growy_append_formatted(g, "\tswitch (node->tag) { \n"); @@ -70,7 +70,7 @@ static void generate_node_payload_hash_fn(Growy* g, Data data, json_object* node growy_append_formatted(g, "}\n"); } -static void generate_node_payload_cmp_fn(Growy* g, Data data, json_object* nodes) { +static void generate_node_payload_cmp_fn(Growy* g, json_object* src, json_object* nodes) { growy_append_formatted(g, "bool compare_node_payload(const Node* a, const Node* b) {\n"); growy_append_formatted(g, "\tbool eq = true;\n"); growy_append_formatted(g, "\tswitch (a->tag) { \n"); @@ -138,18 +138,18 @@ void generate_address_space_name_fn(Growy* g, json_object* address_spaces) { growy_append_formatted(g, "}\n"); } -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* src) { + generate_header(g, src); - json_object* nodes = json_object_object_get(data.shd, "nodes"); - generate_address_space_name_fn(g, json_object_object_get(data.shd, "address-spaces")); + json_object* nodes = json_object_object_get(src, "nodes"); + generate_address_space_name_fn(g, json_object_object_get(src, "address-spaces")); generate_node_names_string_array(g, nodes); generate_node_has_payload_array(g, nodes); - generate_node_payload_hash_fn(g, data, nodes); - generate_node_payload_cmp_fn(g, data, nodes); + generate_node_payload_hash_fn(g, src, nodes); + generate_node_payload_cmp_fn(g, src, nodes); generate_bit_enum_classifier(g, "get_node_class_from_tag", "NodeClass", "Nc", "NodeTag", "", "_TAG", nodes); - json_object* node_classes = json_object_object_get(data.shd, "node-classes"); + json_object* node_classes = json_object_object_get(src, "node-classes"); for (size_t i = 0; i < json_object_array_length(node_classes); i++) { json_object* node_class = json_object_array_get_idx(node_classes, i); String name = json_object_get_string(json_object_object_get(node_class, "name")); diff --git a/src/shady/generator_primops.c b/src/shady/generator_primops.c index 551065a50..bb57bf258 100644 --- a/src/shady/generator_primops.c +++ b/src/shady/generator_primops.c @@ -34,10 +34,10 @@ static void generate_primops_side_effects_array(Growy* g, json_object* primops) growy_append_string(g, "\n};\n"); } -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* shd) { + generate_header(g, shd); - json_object* primops = json_object_object_get(data.shd, "prim-ops"); + json_object* primops = json_object_object_get(shd, "prim-ops"); generate_primops_names_array(g, primops); generate_primops_side_effects_array(g, primops); diff --git a/src/shady/generator_rewrite.c b/src/shady/generator_rewrite.c index 65d948393..a163d6044 100644 --- a/src/shady/generator_rewrite.c +++ b/src/shady/generator_rewrite.c @@ -78,10 +78,10 @@ static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { growy_append_formatted(g, "}\n\n"); } -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* src) { + generate_header(g, src); - json_object* nodes = json_object_object_get(data.shd, "nodes"); + json_object* nodes = json_object_object_get(src, "nodes"); generate_can_be_default_rewritten_fn(g, nodes); generate_rewriter_default_fns(g, nodes); } diff --git a/src/shady/generator_type.c b/src/shady/generator_type.c index 0f279a3bd..d4aaddf3a 100644 --- a/src/shady/generator_type.c +++ b/src/shady/generator_type.c @@ -1,9 +1,9 @@ #include "generator.h" -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* src) { + generate_header(g, src); - json_object* nodes = json_object_object_get(data.shd, "nodes"); + json_object* nodes = json_object_object_get(src, "nodes"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); diff --git a/src/shady/generator_visit.c b/src/shady/generator_visit.c index ff43113fe..64d030af8 100644 --- a/src/shady/generator_visit.c +++ b/src/shady/generator_visit.c @@ -1,9 +1,9 @@ #include "generator.h" -void generate(Growy* g, Data data) { - generate_header(g, data); +void generate(Growy* g, json_object* src) { + generate_header(g, src); - json_object* nodes = json_object_object_get(data.shd, "nodes"); + json_object* nodes = json_object_object_get(src, "nodes"); growy_append_formatted(g, "void visit_node_operands(Visitor* visitor, NodeClass exclude, const Node* node) {\n"); growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); From 8facf72654fcfce2c0d623fc975022b93d1ed16a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 17:57:02 +0100 Subject: [PATCH 051/693] fix bug in remove_list --- src/common/list.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/list.h b/src/common/list.h index 3196ae000..2ddca75bd 100644 --- a/src/common/list.h +++ b/src/common/list.h @@ -32,7 +32,7 @@ void add_list_impl(struct List* list, size_t index, void* element); #define delete_list(T, list, i) delete_list_impl(list, index) void delete_list_impl(struct List* list, size_t index); -#define remove_list(T, list, i) *(T*) remove_list_impl(list, index) +#define remove_list(T, list, i) *((T*) remove_list_impl(list, i)) void* remove_list_impl(struct List* list, size_t index); #define read_list(T, list) ((T*) (list)->alloc) From 961ef53dd71621c32ac99ba78bb746c38afbad57 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 17:57:21 +0100 Subject: [PATCH 052/693] json_apply: behaviour change for arrays --- src/shady/generator/json_apply.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/shady/generator/json_apply.c b/src/shady/generator/json_apply.c index 88077d4ed..6fc6d010a 100644 --- a/src/shady/generator/json_apply.c +++ b/src/shady/generator/json_apply.c @@ -17,12 +17,22 @@ void json_apply_object(json_object* target, json_object* src) { json_object* existing = json_object_object_get(target, name); if (existing && json_object_get_type(existing) == json_type_object) { json_apply_object(existing, value); - } else if (existing && json_object_get_type(existing) == json_type_array && json_object_get_type(value) == json_type_array && json_object_array_length(value) <= json_object_array_length(existing)) { - for (size_t j = 0; j < json_object_array_length(value); j++) - json_object_array_put_idx(existing, j, json_object_array_get_idx(value, j)); + } else if (existing && json_object_get_type(existing) == json_type_array && json_object_get_type(value) == json_type_array/* && json_object_array_length(value) <= json_object_array_length(existing)*/) { + for (size_t j = 0; j < json_object_array_length(value); j++) { + json_object* elem = json_object_array_get_idx(value, j); + // json_object* copy = NULL; + // json_object_deep_copy(elem, ©, NULL); + // json_object_array_put_idx(existing, j, copy); + // json_object_array_put_idx(existing, j, elem); + json_object_array_add(existing, elem); + json_object_get(elem); + } } else { if (existing) warn_print("json-apply: overwriting key '%s'\n", name); + // json_object* copy = NULL; + // json_object_deep_copy(value, ©, NULL); + // json_object_object_add(target, name, copy); json_object_object_add(target, name, value); json_object_get(value); } From f5f70b3c9c888f8f0049a5401d3dacf607d22471 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Jan 2024 17:58:09 +0100 Subject: [PATCH 053/693] started work on logic for importing spirv ops --- include/shady/spv_imports.json | 47 +++++ src/shady/generator/CMakeLists.txt | 4 +- src/shady/generator/import_spv_defs.c | 257 ++++++++++++++++++++++++-- 3 files changed, 295 insertions(+), 13 deletions(-) create mode 100644 include/shady/spv_imports.json diff --git a/include/shady/spv_imports.json b/include/shady/spv_imports.json new file mode 100644 index 000000000..0c4a105ed --- /dev/null +++ b/include/shady/spv_imports.json @@ -0,0 +1,47 @@ +{ + "instruction-filters": [ + { + "operand-filters": [ + { + "import": "yes" + }, + { + "filter-kind": { "IdResult": {}}, + "import": "no" + }, + { + "filter-kind": { "IdRef": {} }, + "overlay": { + "class": "value" + } + }, + { + "filter-kind": { "Dim": {}, "LiteralInteger": {}, "ImageFormat": {} }, + "overlay": { + "type": "uint32_t" + } + } + ] + }, + { + "filter-name": { "OpTypeSampler": {}, "OpTypeImage": {}, "OpTypeSampledImage": {} }, + "import": "yes", + "operand-filters": [ + { + "filter-kind": { "AccessQualifier": {}}, + "import": "no" + }, + { + "filter-kind": { "IdRef": {}}, + "overlay": { + "class": "type" + } + } + ], + "overlay": { + "class": "type", + "type": false + } + } + ] +} \ No newline at end of file diff --git a/src/shady/generator/CMakeLists.txt b/src/shady/generator/CMakeLists.txt index b3a446b26..3db487381 100644 --- a/src/shady/generator/CMakeLists.txt +++ b/src/shady/generator/CMakeLists.txt @@ -18,8 +18,8 @@ if (WIN32) endif () get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/imported.json COMMAND import_spv_defs ${CMAKE_CURRENT_BINARY_DIR}/imported.json ${SPIRV_HEADERS_INCLUDE_DIRS} DEPENDS ${GENERATOR_NAME} SPIRV-Headers::SPIRV-Headers VERBATIM) -add_custom_target(do_import_spv_defs DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/imported.json) +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/imported.json COMMAND import_spv_defs ${CMAKE_CURRENT_BINARY_DIR}/imported.json ${CMAKE_SOURCE_DIR}/include/shady/spv_imports.json ${SPIRV_HEADERS_INCLUDE_DIRS} DEPENDS import_spv_defs SPIRV-Headers::SPIRV-Headers ${CMAKE_SOURCE_DIR}/include/shady/spv_imports.json VERBATIM) +add_custom_target(do_import_spv_defs DEPENDS import_spv_defs ${CMAKE_CURRENT_BINARY_DIR}/imported.json) set(SHADY_IMPORTED_JSON_PATH ${CMAKE_CURRENT_BINARY_DIR}/imported.json CACHE INTERNAL "path to imported.json") diff --git a/src/shady/generator/import_spv_defs.c b/src/shady/generator/import_spv_defs.c index bb9992a2c..43f9a921d 100644 --- a/src/shady/generator/import_spv_defs.c +++ b/src/shady/generator/import_spv_defs.c @@ -1,25 +1,250 @@ #include "generator.h" #include "util.h" +#include "list.h" enum { ArgSelf = 0, ArgDstFile, + ArgImportsFile, ArgSpirvGrammarSearchPathBegins }; -void import_spirv_defs(json_object* src, json_object* dst) { +void apply_instruction_filter(json_object* filter, json_object* instruction, json_object* instantiated_filter, struct List* pending) { + switch (json_object_get_type(filter)) { + case json_type_array: { + for (size_t i = 0; i < json_object_array_length(filter); i++) { + apply_instruction_filter(json_object_array_get_idx(filter, i), instruction, instantiated_filter, pending); + } + break; + } + case json_type_object: { + json_object* filter_name = json_object_object_get(filter, "filter-name"); + if (filter_name) { + assert(json_object_get_type(filter_name) == json_type_object); + String name = json_object_get_string(json_object_object_get(instruction, "opname")); + bool found = false; + json_object_object_foreach(filter_name, match_name, subfilter) { + if (strcmp(name, match_name) == 0) { + found = true; + append_list(json_object*, pending, subfilter); + } + } + if (!found) + return; + } + + json_apply_object(instantiated_filter, filter); + /*json_object_object_foreach(filter, proprerty, value) { + json_object_get(value); + json_object_object_add(instantiated_filter, proprerty, value); + }*/ + break; + } + default: error("Filters need to be arrays or objects"); + } +} + +json_object* apply_instruction_filters(json_object* filter, json_object* instruction) { + json_object* instantiated_filter = json_object_new_object(); + struct List* pending = new_list(json_object*); + apply_instruction_filter(filter, instruction, instantiated_filter, pending); + while(entries_count_list(pending) > 0) { + json_object* pending_filter = read_list(json_object*, pending)[0]; + remove_list(json_object*, pending, 0); + apply_instruction_filter(pending_filter, instruction, instantiated_filter, pending); + continue; + } + destroy_list(pending); + return instantiated_filter; +} + +void apply_operand_filter(json_object* filter, json_object* operand, json_object* instantiated_filter, struct List* pending) { + //fprintf(stderr, "applying %s\n", json_object_to_json_string(filter)); + switch (json_object_get_type(filter)) { + case json_type_array: { + for (size_t i = 0; i < json_object_array_length(filter); i++) { + apply_operand_filter(json_object_array_get_idx(filter, i), operand, instantiated_filter, pending); + } + break; + } + case json_type_object: { + json_object* filter_name = json_object_object_get(filter, "filter-name"); + if (filter_name) { + assert(json_object_get_type(filter_name) == json_type_object); + String name = json_object_get_string(json_object_object_get(operand, "name")); + if (!name) + name = ""; + bool found = false; + json_object_object_foreach(filter_name, match_name, subfilter) { + if (strcmp(name, match_name) == 0) { + found = true; + append_list(json_object*, pending, subfilter); + } + } + if (!found) + return; + } + json_object* filter_kind = json_object_object_get(filter, "filter-kind"); + if (filter_kind) { + assert(json_object_get_type(filter_kind) == json_type_object); + String kind = json_object_get_string(json_object_object_get(operand, "kind")); + if (!kind) + kind = ""; + bool found = false; + json_object_object_foreach(filter_kind, match_name, subfilter) { + if (strcmp(kind, match_name) == 0) { + found = true; + append_list(json_object*, pending, subfilter); + } + } + if (!found) + return; + } + + json_apply_object(instantiated_filter, filter); + break; + } + default: error("Filters need to be arrays or objects"); + } +} + +json_object* apply_operand_filters(json_object* filter, json_object* operand) { + //fprintf(stderr, "building filter for %s\n", json_object_to_json_string(operand)); + json_object* instantiated_filter = json_object_new_object(); + struct List* pending = new_list(json_object*); + apply_operand_filter(filter, operand, instantiated_filter, pending); + while(entries_count_list(pending) > 0) { + json_object* pending_filter = read_list(json_object*, pending)[0]; + remove_list(json_object*, pending, 0); + apply_operand_filter(pending_filter, operand, instantiated_filter, pending); + continue; + } + destroy_list(pending); + //fprintf(stderr, "done: %s\n", json_object_to_json_string(instantiated_filter)); + return instantiated_filter; +} + +json_object* import_operand(json_object* operand, json_object* instruction_filter) { + String kind = json_object_get_string(json_object_object_get(operand, "kind")); + assert(kind); + String name = json_object_get_string(json_object_object_get(operand, "name")); + if (!name) + name = kind; + + json_object* operand_filters = json_object_object_get(instruction_filter, "operand-filters"); + assert(operand_filters); + json_object* filter = apply_operand_filters(operand_filters, operand); + + String import_property = json_object_get_string(json_object_object_get(filter, "import")); + if (!import_property || (strcmp(import_property, "no") == 0)) { + json_object_put(filter); + return NULL; + } else if (strcmp(import_property, "yes") != 0) { + error("a filter's 'import' property needs to be 'yes' or 'no'") + } + + json_object* field = json_object_new_object(); + + char* tmpname = NULL; + tmpname = calloc(strlen(name) + 1, 1); + if (name[0] == '\'') { + memcpy(tmpname, name + 1, strlen(name) - 2); + name = tmpname; + } else { + memcpy(tmpname, name, strlen(name)); + } + for (size_t i = 0; i < strlen(tmpname); i++) { + if (tmpname[i] == ' ') + tmpname[i] = '_'; + else + tmpname[i] = tolower(tmpname[i]); + } + json_object_object_add(field, "name", json_object_new_string(name)); + free(tmpname); + + json_object* insert = json_object_object_get(filter, "overlay"); + if (insert) { + json_apply_object(field, insert); + } + json_object_put(filter); + + return field; +} + +static void copy_object(json_object* dst, json_object* src, String name, String copied_name) { + json_object* o = json_object_object_get(src, name); + json_object_get(o); + json_object_object_add(dst, copied_name ? copied_name : name, o); +} + +json_object* import_filtered_instruction(json_object* instruction, json_object* filter) { + String name = json_object_get_string(json_object_object_get(instruction, "opname")); + assert(name && strlen(name) > 2); + name = name + 2; // strip 'Op' prefix + + String import_property = json_object_get_string(json_object_object_get(filter, "import")); + if (!import_property || (strcmp(import_property, "no") == 0)) { + return NULL; + } else if (strcmp(import_property, "yes") != 0) { + error("a filter's 'import' property needs to be 'yes' or 'no'") + } + + json_object* node = json_object_new_object(); + json_object_object_add(node, "name", json_object_new_string(name)); + copy_object(node, instruction, "opcode", "spirv-opcode"); + + json_object* insert = json_object_object_get(filter, "overlay"); + if (insert) { + json_apply_object(node, insert); + } + + json_object* operands = json_object_object_get(instruction, "operands"); + assert(operands); + json_object* ops = json_object_new_array(); + for (size_t i = 0; i < json_object_array_length(operands); i++) { + json_object* operand = json_object_array_get_idx(operands, i); + json_object* field = import_operand(operand, filter); + if (field) + json_object_array_add(ops, field); + } + + if (json_object_array_length(ops) > 0) + json_object_object_add(node, "ops", ops); + else + json_object_put(ops); + + return node; +} + +void import_spirv_defs(json_object* imports, json_object* src, json_object* dst) { json_object* spv = json_object_new_object(); - json_object_object_add(spv, "major_version", json_object_object_get(src, "major_version")); - json_object_object_add(spv, "minor_version", json_object_object_get(src, "minor_version")); - json_object_object_add(spv, "revision", json_object_object_get(src, "revision")); json_object_object_add(dst, "spv", spv); + copy_object(spv, src, "major_version", NULL); + copy_object(spv, src, "minor_version", NULL); + copy_object(spv, src, "revision", NULL); + + // import instructions + json_object* filters = json_object_object_get(imports, "instruction-filters"); + json_object* nodes = json_object_new_array(); + json_object_object_add(dst, "nodes", nodes); + json_object* instructions = json_object_object_get(src, "instructions"); + //assert(false); + for (size_t i = 0; i < json_object_array_length(instructions); i++) { + json_object* instruction = json_object_array_get_idx(instructions, i); + + json_object* filter = apply_instruction_filters(filters, instruction); + json_object* result = import_filtered_instruction(instruction, filter); + if (result) { + json_object_array_add(nodes, result); + } + json_object_put(filter); + } } int main(int argc, char** argv) { assert(argc > ArgSpirvGrammarSearchPathBegins); - //char* mode = argv[ArgGeneratorFn]; char* dst_file = argv[ArgDstFile]; // search the include path for spirv.core.grammar.json char* spv_core_json_path = NULL; @@ -47,9 +272,17 @@ int main(int argc, char** argv) { json_object* root; } JsonFile; - JsonFile json_file; - read_file(spv_core_json_path, &json_file.size, &json_file.contents); - json_file.root = json_tokener_parse_ex(tokener, json_file.contents, json_file.size); + JsonFile imports; + read_file(argv[ArgImportsFile], &imports.size, &imports.contents); + imports.root = json_tokener_parse_ex(tokener, imports.contents, imports.size); + json_err = json_tokener_get_error(tokener); + if (json_err != json_tokener_success) { + error("Json tokener error while parsing %s:\n %s\n", argv[ArgImportsFile], json_tokener_error_desc(json_err)); + } + + JsonFile spirv; + read_file(spv_core_json_path, &spirv.size, &spirv.contents); + spirv.root = json_tokener_parse_ex(tokener, spirv.contents, spirv.size); json_err = json_tokener_get_error(tokener); if (json_err != json_tokener_success) { error("Json tokener error while parsing %s:\n %s\n", spv_core_json_path, json_tokener_error_desc(json_err)); @@ -59,7 +292,7 @@ int main(int argc, char** argv) { json_object* output = json_object_new_object(); - import_spirv_defs(json_file.root, output); + import_spirv_defs(imports.root, spirv.root, output); Growy* g = new_growy(); growy_append_string(g, json_object_to_json_string(output)); @@ -74,8 +307,10 @@ int main(int argc, char** argv) { error_die(); } free(generated); - free(json_file.contents); - json_object_put(json_file.root); + free(spirv.contents); + json_object_put(spirv.root); + free(imports.contents); + json_object_put(imports.root); json_tokener_free(tokener); free(spv_core_json_path); } From 0085f64570b7bf12a3cd13d8193f49d88efec5b2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 28 Jan 2024 10:11:05 +0100 Subject: [PATCH 054/693] use OpTypeImage, OpTypeSampler and OpTypeSampledImage directly --- include/shady/grammar.json | 26 ---------- src/frontends/llvm/l2s_type.c | 7 +-- src/shady/emit/c/emit_c_signatures.c | 2 +- src/shady/emit/spirv/emit_spv_type.c | 4 +- src/shady/generator/import_spv_defs.c | 74 ++++++++++++++++++--------- src/shady/print.c | 6 +-- src/shady/type.c | 18 ++++--- 7 files changed, 69 insertions(+), 68 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index ff131a9e5..3c10d3a0a 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -253,32 +253,6 @@ { "name": "decl", "class": "declaration" } ] }, - { - "name": "ImageType", - "class": "type", - "type": false, - "ops": [ - { "name": "sampled_type", "class": "type" }, - { "name": "dim", "type": "uint32_t" }, - { "name": "depth", "type": "uint32_t" }, - { "name": "onion", "type": "bool" }, - { "name": "multisample", "type": "bool" }, - { "name": "sampled", "type": "uint32_t" } - ] - }, - { - "name": "SamplerType", - "class": "type", - "type": false - }, - { - "name": "CombinedImageSamplerType", - "class": "type", - "type": false, - "ops": [ - { "name": "image_type", "class": "type" } - ] - }, { "name": "Variable", "snake_name": "var", diff --git a/src/frontends/llvm/l2s_type.c b/src/frontends/llvm/l2s_type.c index 4da900def..30b1df86e 100644 --- a/src/frontends/llvm/l2s_type.c +++ b/src/frontends/llvm/l2s_type.c @@ -50,14 +50,15 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { const Node* result = NULL; if (name) { if (strcmp(name, "struct.__shady_builtin_sampler2D") == 0) - return combined_image_sampler_type(a, (CombinedImageSamplerType) { .image_type = image_type(a, (ImageType) { + return sampled_image_type(a, (SampledImageType) { .image_type = image_type(a, (ImageType) { //.sampled_type = pack_type(a, (PackType) { .element_type = float_type(a, (Float) { .width = FloatTy32 }), .width = 4 }), .sampled_type = float_type(a, (Float) { .width = FloatTy32 }), .dim = 1, .depth = 0, - .onion = 0, - .multisample = 0, + .arrayed = 0, + .ms = 0, .sampled = 1, + .imageformat = 0 } ) }); decl = nominal_type(p->dst, empty(a), name); diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index 306dffd90..0e8cb5503 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -123,7 +123,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { case LamType_TAG: case BBType_TAG: error("these types do not exist in C"); case MaskType_TAG: error("should be lowered away"); - case Type_CombinedImageSamplerType_TAG: + case Type_SampledImageType_TAG: case Type_SamplerType_TAG: case Type_ImageType_TAG: case JoinPointType_TAG: error("TODO") diff --git a/src/shady/emit/spirv/emit_spv_type.c b/src/shady/emit/spirv/emit_spv_type.c index c782cb2d7..98f0cad0e 100644 --- a/src/shady/emit/spirv/emit_spv_type.c +++ b/src/shady/emit/spirv/emit_spv_type.c @@ -200,11 +200,11 @@ SpvId emit_type(Emitter* emitter, const Type* type) { new = emit_decl(emitter, type->payload.type_decl_ref.decl); break; } - case Type_CombinedImageSamplerType_TAG: new = spvb_sampled_image_type(emitter->file_builder, emit_type(emitter, type->payload.combined_image_sampler_type.image_type)); break; + case Type_SampledImageType_TAG: new = spvb_sampled_image_type(emitter->file_builder, emit_type(emitter, type->payload.sampled_image_type.image_type)); break; case Type_SamplerType_TAG: new = spvb_sampler_type(emitter->file_builder); break; case Type_ImageType_TAG: { ImageType p = type->payload.image_type; - new = spvb_image_type(emitter->file_builder, emit_type(emitter, p.sampled_type), p.dim, p.depth, p.onion, p.multisample, p.sampled, SpvImageFormatUnknown); + new = spvb_image_type(emitter->file_builder, emit_type(emitter, p.sampled_type), p.dim, p.depth, p.arrayed, p.ms, p.sampled, p.imageformat); break; } case Type_MaskType_TAG: diff --git a/src/shady/generator/import_spv_defs.c b/src/shady/generator/import_spv_defs.c index 43f9a921d..14b71c8fb 100644 --- a/src/shady/generator/import_spv_defs.c +++ b/src/shady/generator/import_spv_defs.c @@ -10,6 +10,48 @@ enum { ArgSpirvGrammarSearchPathBegins }; +static String sanitize_node_name(String name) { + char* tmpname = NULL; + tmpname = calloc(strlen(name) + 1, 1); + bool is_type = false; + if (string_starts_with(name, "OpType")) { + memcpy(tmpname, name + 6, strlen(name) - 6); + is_type = true; + } else if (string_starts_with(name, "Op")) + memcpy(tmpname, name + 2, strlen(name) - 2); + else + memcpy(tmpname, name, strlen(name)); + + if (is_type) + memcpy(tmpname + strlen(tmpname), "Type", 4); + + return tmpname; +} + +static String sanitize_field_name(String name) { + char* tmpname = NULL; + tmpname = calloc(strlen(name) + 1, 1); + if (name[0] == '\'') { + memcpy(tmpname, name + 1, strlen(name) - 2); + name = tmpname; + } else { + memcpy(tmpname, name, strlen(name)); + } + for (size_t i = 0; i < strlen(tmpname); i++) { + if (tmpname[i] == ' ') + tmpname[i] = '_'; + else + tmpname[i] = tolower(tmpname[i]); + } + return tmpname; +} + +static void copy_object(json_object* dst, json_object* src, String name, String copied_name) { + json_object* o = json_object_object_get(src, name); + json_object_get(o); + json_object_object_add(dst, copied_name ? copied_name : name, o); +} + void apply_instruction_filter(json_object* filter, json_object* instruction, json_object* instantiated_filter, struct List* pending) { switch (json_object_get_type(filter)) { case json_type_array: { @@ -146,22 +188,9 @@ json_object* import_operand(json_object* operand, json_object* instruction_filte json_object* field = json_object_new_object(); - char* tmpname = NULL; - tmpname = calloc(strlen(name) + 1, 1); - if (name[0] == '\'') { - memcpy(tmpname, name + 1, strlen(name) - 2); - name = tmpname; - } else { - memcpy(tmpname, name, strlen(name)); - } - for (size_t i = 0; i < strlen(tmpname); i++) { - if (tmpname[i] == ' ') - tmpname[i] = '_'; - else - tmpname[i] = tolower(tmpname[i]); - } - json_object_object_add(field, "name", json_object_new_string(name)); - free(tmpname); + char* field_name = sanitize_field_name(name); + json_object_object_add(field, "name", json_object_new_string(field_name)); + free(field_name); json_object* insert = json_object_object_get(filter, "overlay"); if (insert) { @@ -172,16 +201,10 @@ json_object* import_operand(json_object* operand, json_object* instruction_filte return field; } -static void copy_object(json_object* dst, json_object* src, String name, String copied_name) { - json_object* o = json_object_object_get(src, name); - json_object_get(o); - json_object_object_add(dst, copied_name ? copied_name : name, o); -} - json_object* import_filtered_instruction(json_object* instruction, json_object* filter) { String name = json_object_get_string(json_object_object_get(instruction, "opname")); assert(name && strlen(name) > 2); - name = name + 2; // strip 'Op' prefix + String node_name = sanitize_node_name(name); String import_property = json_object_get_string(json_object_object_get(filter, "import")); if (!import_property || (strcmp(import_property, "no") == 0)) { @@ -191,7 +214,7 @@ json_object* import_filtered_instruction(json_object* instruction, json_object* } json_object* node = json_object_new_object(); - json_object_object_add(node, "name", json_object_new_string(name)); + json_object_object_add(node, "name", json_object_new_string(node_name)); copy_object(node, instruction, "opcode", "spirv-opcode"); json_object* insert = json_object_object_get(filter, "overlay"); @@ -214,6 +237,7 @@ json_object* import_filtered_instruction(json_object* instruction, json_object* else json_object_put(ops); + free(node_name); return node; } @@ -295,7 +319,7 @@ int main(int argc, char** argv) { import_spirv_defs(imports.root, spirv.root, output); Growy* g = new_growy(); - growy_append_string(g, json_object_to_json_string(output)); + growy_append_string(g, json_object_to_json_string_ext(output, JSON_C_TO_STRING_PRETTY)); json_object_put(output); size_t final_size = growy_size(g); diff --git a/src/shady/print.c b/src/shady/print.c index a2f5a4f1d..93e40088c 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -337,18 +337,18 @@ static void print_type(PrinterCtx* ctx, const Node* node) { printf("["); print_node(node->payload.image_type.sampled_type); printf(RESET); - printf(", %d, %d, %d, %d]", node->payload.image_type.dim, node->payload.image_type.depth, node->payload.image_type.onion, node->payload.image_type.multisample); + printf(", %d, %d, %d, %d]", node->payload.image_type.dim, node->payload.image_type.depth, node->payload.image_type.arrayed, node->payload.image_type.ms); break; } case Type_SamplerType_TAG: { printf("sampler_type"); break; } - case Type_CombinedImageSamplerType_TAG: { + case Type_SampledImageType_TAG: { printf("sampled"); printf(RESET); printf("["); - print_node(node->payload.combined_image_sampler_type.image_type); + print_node(node->payload.sampled_image_type.image_type); printf(RESET); printf("]"); break; diff --git a/src/shady/type.c b/src/shady/type.c index 47eeaf8cb..46e3a128d 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -123,16 +123,18 @@ bool is_subtype(const Type* supertype, const Type* type) { return false; if (supertype->payload.image_type.dim != type->payload.image_type.dim) return false; - if (supertype->payload.image_type.onion != type->payload.image_type.onion) + if (supertype->payload.image_type.arrayed != type->payload.image_type.arrayed) return false; - if (supertype->payload.image_type.multisample != type->payload.image_type.multisample) + if (supertype->payload.image_type.ms != type->payload.image_type.ms) return false; if (supertype->payload.image_type.sampled != type->payload.image_type.sampled) return false; + if (supertype->payload.image_type.imageformat != type->payload.image_type.imageformat) + return false; return true; } - case Type_CombinedImageSamplerType_TAG: - return is_subtype(supertype->payload.combined_image_sampler_type.image_type, type->payload.combined_image_sampler_type.image_type); + case Type_SampledImageType_TAG: + return is_subtype(supertype->payload.sampled_image_type.image_type, type->payload.sampled_image_type.image_type); case SamplerType_TAG: case NoRet_TAG: case Bool_TAG: @@ -212,7 +214,7 @@ String name_type_safe(IrArena* arena, const Type* t) { case Type_PackType_TAG: case Type_ImageType_TAG: case Type_SamplerType_TAG: - case Type_CombinedImageSamplerType_TAG: + case Type_SampledImageType_TAG: break; case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; } @@ -268,7 +270,7 @@ bool is_data_type(const Type* type) { case NotAType: return false; // Image stuff is data (albeit opaque) - case Type_CombinedImageSamplerType_TAG: + case Type_SampledImageType_TAG: case Type_SamplerType_TAG: case Type_ImageType_TAG: return true; @@ -1057,8 +1059,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { bool uniform_src = deconstruct_qualified_type(&sampled_image_t); const Type* coords_t = prim_op.operands.nodes[1]->type; deconstruct_qualified_type(&coords_t); - assert(sampled_image_t->tag == CombinedImageSamplerType_TAG); - const Type* image_t = sampled_image_t->payload.combined_image_sampler_type.image_type; + assert(sampled_image_t->tag == SampledImageType_TAG); + const Type* image_t = sampled_image_t->payload.sampled_image_type.image_type; assert(image_t->tag == ImageType_TAG); size_t coords_dim = deconstruct_packed_type(&coords_t); return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = maybe_packed_type_helper(image_t->payload.image_type.sampled_type, 4) }); From ca985566ac7f19ded16c5cdf13f63944c2aecdf4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jan 2024 18:25:11 +0100 Subject: [PATCH 055/693] rearrange passes, do specialization earlier --- src/shady/compile.c | 6 +++--- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/specialize_entry_point.c | 7 +++++++ src/shady/transform/internal_constants.c | 6 +++--- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index e9ef74eff..285d303f6 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -107,6 +107,9 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(opt_restructurize) RUN_PASS(opt_mem2reg) + if (config->specialization.entry_point) + RUN_PASS(specialize_entry_point) + RUN_PASS(lower_mask) RUN_PASS(lower_memcpy) RUN_PASS(lower_subgroup_ops) @@ -127,9 +130,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { if (config->lower.simt_to_explicit_simd) RUN_PASS(simt2d) - - if (config->specialization.entry_point) - RUN_PASS(specialize_entry_point) RUN_PASS(lower_fill) return CompilationNoError; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index cde917e19..e1d060af3 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -129,7 +129,7 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { PtrSourceKnowledge k = { 0 }; while (ptr) { assert(is_value(ptr)); - if (ptr->tag == Variable_TAG) { + if (ptr->tag == Variable_TAG && ctx->scope_uses) { const Node* instr = get_var_instruction(ctx->scope_uses, ptr); if (instr) { PrimOp payload = instr->payload.prim_op; diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index eabe889b6..e29bdb33a 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -129,6 +129,13 @@ Module* specialize_entry_point(const CompilerConfig* config, Module* src) { const Node* old_entry_point_decl = find_entry_point(src, config); rewrite_node(&ctx.rewriter, old_entry_point_decl); + Nodes old_decls = get_module_declarations(src); + for (size_t i = 0; i < old_decls.count; i++) { + const Node* old_decl = old_decls.nodes[i]; + if (lookup_annotation(old_decl, "RetainAfterSpecialization")) + rewrite_node(&ctx.rewriter, old_decl); + } + destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/transform/internal_constants.c b/src/shady/transform/internal_constants.c index 0c61bcc39..83257c113 100644 --- a/src/shady/transform/internal_constants.c +++ b/src/shady/transform/internal_constants.c @@ -6,9 +6,9 @@ void generate_dummy_constants(SHADY_UNUSED CompilerConfig* config, Module* mod) { IrArena* arena = get_module_arena(mod); -#define X(name, T, placeholder) \ - Node* name##_var = constant(mod, nodes(arena, 0, NULL), T, #name); \ - name##_var->payload.constant.instruction = quote_helper(arena, singleton(placeholder)); +#define X(constant_name, T, placeholder) \ + Node* constant_name##_var = constant(mod, singleton(annotation(arena, (Annotation) { .name = "RetainAfterSpecialization" })), T, #constant_name); \ + constant_name##_var->payload.constant.instruction = quote_helper(arena, singleton(placeholder)); INTERNAL_CONSTANTS(X) #undef X } From 14e62871de63fa874bccdcb214ad314d67ff718e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jan 2024 18:26:23 +0100 Subject: [PATCH 056/693] aggressively delete LEAs and loads using undef --- src/shady/fold.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/shady/fold.c b/src/shady/fold.c index 83a0c1c17..699ecc3ab 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -249,6 +249,12 @@ break; } break; } + case load_op: { + if (first(payload.operands)->tag == Undef_TAG) { + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + } + break; + } case reinterpret_op: case convert_op: if (first(payload.operands)->tag == Undef_TAG) { @@ -258,6 +264,11 @@ break; if (payload.type_arguments.nodes[0] == get_unqualified_type(payload.operands.nodes[0]->type)) return quote_single(arena, payload.operands.nodes[0]); break; + case lea_op: + if (first(payload.operands)->tag == Undef_TAG) { + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + } + break; default: break; } return node; From 90d889e3425a3d34eddbcde16e0475f896ab04f9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jan 2024 18:27:11 +0100 Subject: [PATCH 057/693] remove unecessary flags from vcc tests --- test/vcc/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/vcc/CMakeLists.txt b/test/vcc/CMakeLists.txt index 359f11c55..48b895e7e 100644 --- a/test/vcc/CMakeLists.txt +++ b/test/vcc/CMakeLists.txt @@ -12,10 +12,10 @@ spv_outputting_test(NAME test/vcc/loop.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS spv_outputting_test(NAME test/vcc/goto.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/ternary.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) -spv_outputting_test(NAME test/vcc/vec_swizzle.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point test --no-dynamic-scheduling --execution-model Fragment) +spv_outputting_test(NAME test/vcc/vec_swizzle.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point test --execution-model Fragment) spv_outputting_test(NAME test/vcc/empty.comp.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main) -spv_outputting_test(NAME test/vcc/simple.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --no-dynamic-scheduling --execution-model Fragment) -spv_outputting_test(NAME test/vcc/checkerboard.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --no-dynamic-scheduling --execution-model Fragment) -spv_outputting_test(NAME test/vcc/textured.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --no-dynamic-scheduling --execution-model Fragment) +spv_outputting_test(NAME test/vcc/simple.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --execution-model Fragment) +spv_outputting_test(NAME test/vcc/checkerboard.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --execution-model Fragment) +spv_outputting_test(NAME test/vcc/textured.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --execution-model Fragment) From 739f2affcdb0b5ab45a02aafa2d0945fb37817fb Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Feb 2024 11:47:43 +0100 Subject: [PATCH 058/693] disable scheduler in frag and vtx for now --- src/driver/cli.c | 7 +++++++ src/shady/internal/scheduler.slim | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/driver/cli.c b/src/driver/cli.c index 9ad332cd7..237c57491 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -115,6 +115,13 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a #undef EM if (em == EmNone) error("Unknown execution model: %s", argv[i]); + switch (em) { + case EmFragment: + case EmVertex: + config->dynamic_scheduling = false; + break; + default: break; + } config->specialization.execution_model = em; } else if (strcmp(argv[i], "--simt2d") == 0) { config->lower.simt_to_explicit_simd = true; diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index 003310704..e83215828 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -9,7 +9,7 @@ u32 payload; }; -@Internal subgroup u32 actual_subgroup_size; +@Internal private u32 actual_subgroup_size; @Internal subgroup u32 scheduler_cursor = 0; @Internal subgroup [TreeNode; SUBGROUP_SIZE] scheduler_vector; @@ -76,7 +76,7 @@ fn builtin_fork(varying u32 branch_destination) { } } - // We must pick one branch as our 'favourite child' to schedule for immediate execution# + // We must pick one branch as our 'favourite child' to schedule for immediate execution // we could do fancy intrinsics, but for now we'll just pick the first one if (subgroup_elect_first()) { next_fn = subgroup_broadcast_first(branch_destination); From fd8acfd0b734ffdfd7e8ffeab59ce1d91069f0c2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Feb 2024 18:51:26 +0100 Subject: [PATCH 059/693] improve untyped pointer heuristic --- src/shady/passes/infer.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index c8c42cdfc..c2c3a24d1 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -353,6 +353,11 @@ static const Node* reinterpret_cast_helper(BodyBuilder* bb, const Node* ptr, con return ptr; } +// Turns untyped pointers back into typed pointers +// For physical pointers, we can just reinterpret them +// For logical pointers, we need to do some stupid best-effort tricks and pray it works out +// the sort of casts we can allow are casting a pointer to a composite to a pointer to one of it's first elements +// we just attempt to do LEAs until we hit the right type, or some unrecoverable error static void fix_source_pointer(BodyBuilder* bb, const Node** operand, const Type* element_type) { IrArena* a = element_type->arena; const Type* original_operand_t = get_unqualified_type((*operand)->type); @@ -365,7 +370,8 @@ static void fix_source_pointer(BodyBuilder* bb, const Node** operand, const Type } else { // we can't insert a cast but maybe we can make this work do { - const Type* pointee = get_pointer_type_element(get_unqualified_type((*operand)->type)); + const Node* ptr_t = get_unqualified_type((*operand)->type); + const Type* pointee = get_pointer_type_element(ptr_t); if (pointee == element_type) return; pointee = get_maybe_nominal_type_body(pointee); @@ -373,8 +379,13 @@ static void fix_source_pointer(BodyBuilder* bb, const Node** operand, const Type *operand = gen_lea(bb, *operand, int32_literal(a, 0), singleton(int32_literal(a, 0))); continue; } - // TODO arrays - assert(false); + if (pointee->tag == ArrType_TAG) { + *operand = gen_lea(bb, *operand, int32_literal(a, 0), singleton(int32_literal(a, 0))); + continue; + } + // TODO: better diagnostics + error_print("Fatal: Trying to type-pun a pointer in logical memory (%s)\n", get_address_space_name(get_pointer_type_address_space(ptr_t))); + error_die(); } while(true); } } From a23bd07f9b5f5711618a49f4f71145748f9a1ffa Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Feb 2024 11:48:07 +0100 Subject: [PATCH 060/693] hack: set untyped_ptr arena config flag in l2s --- src/driver/vcc.c | 1 - src/frontends/llvm/l2s.c | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/driver/vcc.c b/src/driver/vcc.c index 1b78cf173..bd829d990 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -67,7 +67,6 @@ int main(int argc, char** argv) { } ArenaConfig aconfig = default_arena_config(); - aconfig.untyped_ptrs = true; // tolerate untyped ptrs... IrArena* arena = new_ir_arena(aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 92e776bd9..23d7974b8 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -1,4 +1,5 @@ #include "l2s_private.h" +#include "shady/ir_private.h" #include "log.h" #include "dict.h" @@ -185,6 +186,9 @@ bool parse_llvm_into_shady(Module* dst, size_t len, const char* data) { error_die(); } info_print("LLVM IR parsed successfully\n"); +#if UNTYPED_POINTERS + get_module_arena(dst)->config.untyped_ptrs = true; // tolerate untyped ptrs... +#endif Module* dirty = new_module(get_module_arena(dst), "dirty"); Parser p = { From b14dfe4dd71cdc551b0fcb79356cd92411cce46e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Feb 2024 11:48:28 +0100 Subject: [PATCH 061/693] fix untyped ptr inference interaction with globals --- src/shady/passes/infer.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index c2c3a24d1..afa5f8578 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -164,6 +164,7 @@ static const Node* _infer_value(Context* ctx, const Node* node, const Type* expe } IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; switch (is_value(node)) { case NotAValue: error(""); case Variable_TAG: return find_processed(&ctx->rewriter, node); @@ -232,9 +233,25 @@ static const Node* _infer_value(Context* ctx, const Node* node, const Type* expe case True_TAG: return true_lit(a); case False_TAG: return false_lit(a); case StringLiteral_TAG: return string_lit(a, (StringLiteral) { .string = string(a, node->payload.string_lit.string )}); - case RefDecl_TAG: - case FnAddr_TAG: return recreate_node_identity(&ctx->rewriter, node); - case Value_Undef_TAG: return recreate_node_identity(&ctx->rewriter, node); + case RefDecl_TAG: { + if (get_arena_config(ctx->rewriter.src_arena).untyped_ptrs) { + const Node* ref_decl = recreate_node_identity(&ctx->rewriter, node); + assert(ref_decl->tag == RefDecl_TAG); + const Node* decl = ref_decl->payload.ref_decl.decl; + if (decl->tag == GlobalVariable_TAG) { + AddressSpace as = decl->payload.global_variable.address_space; + if (is_physical_as(as)) { + const Node* untyped_ptr = ptr_type(a, (PtrType) {.address_space = as, .pointed_type = unit_type(a)}); + Node* cast_constant = constant(ctx->rewriter.dst_module, empty(a), untyped_ptr, format_string_interned(a, "%s_cast", get_decl_name(decl))); + cast_constant->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr), singleton(ref_decl)); + return ref_decl_helper(a, cast_constant); + } + } + } + break; + } + case FnAddr_TAG: break; + case Value_Undef_TAG: break; case Value_Composite_TAG: { const Node* elem_type = infer(ctx, node->payload.composite.type, NULL); bool uniform = false; @@ -278,9 +295,9 @@ static const Node* _infer_value(Context* ctx, const Node* node, const Type* expe const Node* value = infer(ctx, node->payload.fill.value, qualified_type(a, (QualifiedType) { .is_uniform = uniform, .type = element_t })); return fill(a, (Fill) { .type = composite_t, .value = value }); } - case Value_NullPtr_TAG: return recreate_node_identity(&ctx->rewriter, node); + case Value_NullPtr_TAG: break; } - SHADY_UNREACHABLE; + return recreate_node_identity(&ctx->rewriter, node); } static const Node* _infer_case(Context* ctx, const Node* node, const Node* expected) { @@ -467,16 +484,6 @@ static const Node* _infer_primop(Context* ctx, const Node* node, const Type* exp if (is_generic_ptr_type(src_pointer_type) != is_generic_ptr_type(dst_pointer_type)) op = convert_op; - if (old_dst_pointer_type->tag == PtrType_TAG && !old_dst_pointer_type->payload.ptr_type.pointed_type) { - const Type* element_type = uint8_type(a); - if (src_pointer_type->tag == PtrType_TAG && src_pointer_type->payload.ptr_type.pointed_type) { - // element_type = infer(ctx, old_src_pointer_type->payload.ptr_type.pointed_type, NULL); - element_type = src_pointer_type->payload.ptr_type.pointed_type; - } - dst_pointer_type = type_untyped_ptr(dst_pointer_type, element_type); - type_args = change_node_at_index(a, type_args, 0, dst_pointer_type); - } - goto rebuild; } case lea_op: { From 7f13050f98ae794553975c547298d1dc9deb4f69 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Feb 2024 11:48:49 +0100 Subject: [PATCH 062/693] added string.c test --- test/vcc/CMakeLists.txt | 1 + test/vcc/string.c | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 test/vcc/string.c diff --git a/test/vcc/CMakeLists.txt b/test/vcc/CMakeLists.txt index 48b895e7e..daabec251 100644 --- a/test/vcc/CMakeLists.txt +++ b/test/vcc/CMakeLists.txt @@ -11,6 +11,7 @@ spv_outputting_test(NAME test/vcc/branch.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_AR spv_outputting_test(NAME test/vcc/loop.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/goto.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/ternary.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) +spv_outputting_test(NAME test/vcc/string.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/vec_swizzle.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point test --execution-model Fragment) diff --git a/test/vcc/string.c b/test/vcc/string.c new file mode 100644 index 000000000..c2ed032f3 --- /dev/null +++ b/test/vcc/string.c @@ -0,0 +1,3 @@ +void f(void) { + const char* s = "hi"; +} From 40e45cb219efce8e6edd6fee485515d45595f486 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Feb 2024 12:16:35 +0100 Subject: [PATCH 063/693] demote_alloca: fix crashes with free-standing blocks --- src/shady/passes/opt_demote_alloca.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index e1d060af3..1a40cef0e 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -173,6 +173,11 @@ static const Node* process(Context* ctx, const Node* old) { destroy_uses_map(fun_ctx.scope_uses); return fun; } + case Constant_TAG: { + Context fun_ctx = *ctx; + fun_ctx.scope_uses = NULL; + return recreate_node_identity(&fun_ctx.rewriter, old); + } case Let_TAG: { const Node* oinstruction = get_let_instruction(old); const Node* otail = get_let_tail(old); From 4eea7b302f1a2f1a5ae2211c57e0c0265e0d4e38 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Feb 2024 12:18:53 +0100 Subject: [PATCH 064/693] spirv: run a last round of eliminate_constants before codegen --- src/shady/emit/spirv/emit_spv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 5e6cb45a2..989741bdf 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -528,6 +528,7 @@ static Module* run_backend_specific_passes(CompilerConfig* config, Module* initi RUN_PASS(lower_entrypoint_args) RUN_PASS(spirv_map_entrypoint_args) RUN_PASS(spirv_lift_globals_ssbo) + RUN_PASS(eliminate_constants) RUN_PASS(import) return *pmod; From f6cb3c4991bf4d497a21ce1b0c15428a22f72767 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Feb 2024 12:33:23 +0100 Subject: [PATCH 065/693] l2s: fix parsing composites of typedef'd types --- src/frontends/llvm/l2s_value.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/frontends/llvm/l2s_value.c b/src/frontends/llvm/l2s_value.c index 5fa779f47..659a6b6ef 100644 --- a/src/frontends/llvm/l2s_value.c +++ b/src/frontends/llvm/l2s_value.c @@ -102,8 +102,9 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { return data_composite(t, width, v); } case LLVMConstantStructValueKind: { - assert(t->tag == RecordType_TAG); - size_t size = t->payload.record_type.members.count; + const Node* actual_t = get_maybe_nominal_type_body(t); + assert(actual_t->tag == RecordType_TAG); + size_t size = actual_t->payload.record_type.members.count; LARRAY(const Node*, elements, size); for (size_t i = 0; i < size; i++) { LLVMValueRef value = LLVMGetOperand(v, i); From 3b1011cf0491f3bfa2ee5aa08db241496473ff94 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Feb 2024 12:33:48 +0100 Subject: [PATCH 066/693] spirv: fix globals lifting when recursion is involved --- src/shady/passes/spirv_lift_globals_ssbo.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index 485b5e7b9..7538de78d 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -83,12 +83,6 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul member_tys[lifted_globals_count] = rewrite_node(&ctx.rewriter, odecl->type); member_names[lifted_globals_count] = get_decl_name(odecl); - if (odecl->payload.global_variable.init) - annotations = append_nodes(a, annotations, annotation_values(a, (AnnotationValues) { - .name = "InitialValue", - .values = mk_nodes(a, int32_literal(a, lifted_globals_count), rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) - })); - register_processed(&ctx.rewriter, odecl, int32_literal(a, lifted_globals_count)); lifted_globals_count++; } @@ -103,6 +97,21 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul } rewrite_module(&ctx.rewriter); + + lifted_globals_count = 0; + for (size_t i = 0; i < old_decls.count; i++) { + const Node* odecl = old_decls.nodes[i]; + if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobalPhysical) + continue; + if (odecl->payload.global_variable.init) + annotations = append_nodes(a, annotations, annotation_values(a, (AnnotationValues) { + .name = "InitialValue", + .values = mk_nodes(a, int32_literal(a, lifted_globals_count), rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) + })); + + lifted_globals_count++; + } + destroy_rewriter(&ctx.rewriter); return dst; } From ad4fb82a7666e9d523f7d26068cb1c400d2fc9b0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Feb 2024 12:40:36 +0100 Subject: [PATCH 067/693] handle constant instrs better --- src/shady/passes/lower_cf_instrs.c | 8 +++++++- src/shady/passes/opt_mem2reg.c | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 4326627ca..a190c4202 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -146,6 +146,11 @@ static const Node* process_node(Context* ctx, const Node* node) { fun->payload.fun.body = rewrite_node(&sub_ctx.rewriter, node->payload.fun.body); destroy_scope(sub_ctx.scope); return fun; + } else if (node->tag == Constant_TAG) { + sub_ctx.scope = NULL; + sub_ctx.abs = NULL; + sub_ctx.current_fn = NULL; + ctx = &sub_ctx; } if (is_abstraction(node)) { @@ -256,8 +261,9 @@ static const Node* process_node(Context* ctx, const Node* node) { .args = rewrite_nodes(&ctx->rewriter, node->payload.merge_break.args), }); } - default: return recreate_node_identity(&ctx->rewriter, node); + default: break; } + return recreate_node_identity(&ctx->rewriter, node); } KeyHash hash_node(const Node**); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index f4e63d040..8b4686d05 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -626,6 +626,11 @@ static const Node* process(Context* ctx, const Node* old) { } destroy_dict(fn_ctx.abs_to_kb); return new_fn; + } else if (old->tag == Constant_TAG) { + fn_ctx.scope = NULL; + fn_ctx.abs_to_kb = NULL; + fn_ctx.todo_jumps = NULL; + ctx = &fn_ctx; } // setup a new KB if this is a fresh abstraction From 6ef1bd8d614afdce30385d98ed5fea4319473ae0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 5 Feb 2024 11:29:45 -0800 Subject: [PATCH 068/693] fix duplicate untyped constant helper --- src/shady/passes/infer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index afa5f8578..256d2d46f 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -244,7 +244,9 @@ static const Node* _infer_value(Context* ctx, const Node* node, const Type* expe const Node* untyped_ptr = ptr_type(a, (PtrType) {.address_space = as, .pointed_type = unit_type(a)}); Node* cast_constant = constant(ctx->rewriter.dst_module, empty(a), untyped_ptr, format_string_interned(a, "%s_cast", get_decl_name(decl))); cast_constant->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr), singleton(ref_decl)); - return ref_decl_helper(a, cast_constant); + const Node* cast_ref_decl = ref_decl_helper(a, cast_constant); + register_processed(r, node, cast_ref_decl); + return cast_ref_decl; } } } From a6b72aa45b85a66aea8fb29fc1a385a776222634 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 5 Feb 2024 11:36:03 -0800 Subject: [PATCH 069/693] fix: eliminate_constants will now deal properly with multiple usages --- src/shady/passes/eliminate_constants.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 2d20a79c4..c33ab40a3 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -3,6 +3,7 @@ #include "../rewrite.h" #include "portability.h" #include "log.h" +#include "dict.h" typedef struct { Rewriter rewriter; @@ -30,9 +31,12 @@ static const Node* process(Context* ctx, const Node* node) { const Node* value = get_quoted_value(decl->payload.constant.instruction); if (value) return rewrite_node(&ctx->rewriter, value); + c.rewriter.map = clone_dict(c.rewriter.map); assert(ctx->bb); // TODO: actually _copy_ the instruction so we can duplicate the code safely! - return first(bind_instruction(ctx->bb, rewrite_node(&ctx->rewriter, decl->payload.constant.instruction))); + const Node* rewritten = first(bind_instruction(ctx->bb, rewrite_node(&ctx->rewriter, decl->payload.constant.instruction))); + destroy_dict(c.rewriter.map); + return rewritten; } break; } From 3cd6267251454996053948af43d9ab7ef1586fc8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 07:21:19 -0800 Subject: [PATCH 070/693] added Vcc hello_world.c sample --- samples/vcc/hello_world.c | 8 ++++++++ src/frontends/llvm/l2s_instr.c | 17 +++++++++-------- src/shady/node.c | 14 ++++++++++++++ src/shady/print.c | 12 +++++++++++- 4 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 samples/vcc/hello_world.c diff --git a/samples/vcc/hello_world.c b/samples/vcc/hello_world.c new file mode 100644 index 000000000..a834343c6 --- /dev/null +++ b/samples/vcc/hello_world.c @@ -0,0 +1,8 @@ +#include + +void debug_printf(const char*) __asm__("shady::prim_op::debug_printf"); + +compute_shader local_size(1, 1, 1) +void main() { + debug_printf("Hello World from Vcc!\n"); +} diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index 23459cf0a..b9ba8e5ab 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -512,7 +512,7 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM } r = prim_op_helper(a, op, empty(a), nodes(a, num_args, processed_ops)); free(str); - break; + goto finish; } else { error_print("Unrecognised shady intrinsic '%s'\n", keyword); error_die(); @@ -522,14 +522,15 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM error_print("Unhandled intrinsic '%s'\n", intrinsic); error_die(); } - if (r) - break; + finish: - Nodes ops = convert_operands(p, num_ops, instr); - r = call(a, (Call) { - .callee = ops.nodes[num_args], - .args = nodes(a, num_args, ops.nodes), - }); + if (!r) { + Nodes ops = convert_operands(p, num_ops, instr); + r = call(a, (Call) { + .callee = ops.nodes[num_args], + .args = nodes(a, num_args, ops.nodes), + }); + } if (t == unit_type(a)) num_results = 0; break; diff --git a/src/shady/node.c b/src/shady/node.c index 41d06c94b..e943889a8 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -209,6 +209,20 @@ const char* get_string_literal(IrArena* arena, const Node* node) { if (!node) return NULL; switch (node->tag) { + case RefDecl_TAG: { + const Node* decl = node->payload.ref_decl.decl; + switch (is_declaration(decl)) { + case Declaration_GlobalVariable_TAG: { + const Node* init = decl->payload.global_variable.init; + if (init) + return get_string_literal(arena, init); + break; + } + default: + break; + } + return NULL; + } case PrimOp_TAG: { switch (node->payload.prim_op.op) { case lea_op: { diff --git a/src/shady/print.c b/src/shady/print.c index 93e40088c..bf09d5f9b 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -261,7 +261,17 @@ static void print_type(PrinterCtx* ctx, const Node* node) { } break; case RecordType_TAG: - printf("struct"); + if (node->payload.record_type.special & MultipleReturn) { + if (node->payload.record_type.members.count == 0) { + printf("unit_t"); + break; + } + printf("multiple_return"); + } else if (node->payload.record_type.special & DecorateBlock) { + printf("block"); + } else { + printf("struct"); + } printf(RESET); printf(" {"); const Nodes* members = &node->payload.record_type.members; From 28d51ba50d8ce1e9e16a6344f82924aaa243c2a2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 07:21:35 -0800 Subject: [PATCH 071/693] vcc: added 'shared' address space qualifier --- vcc-std/include/shady.h | 1 + 1 file changed, 1 insertion(+) diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index cc3b31aed..3c1b4be75 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -26,6 +26,7 @@ namespace vcc { #define uniform_block __attribute__((address_space(395))) #define push_constant __attribute__((address_space(392))) #define global __attribute__((address_space(1))) +#define shared __attribute__((address_space(3))) #define private __attribute__((address_space(5))) #define private_logical __attribute__((address_space(385))) From 7d4bad84014be2710a0875594c2348f2907f0c27 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 07:34:06 -0800 Subject: [PATCH 072/693] vcc: improved hello_world example with formatted printing` --- samples/vcc/hello_world.c | 2 ++ src/frontends/llvm/l2s_instr.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/vcc/hello_world.c b/samples/vcc/hello_world.c index a834343c6..54ec3fd7f 100644 --- a/samples/vcc/hello_world.c +++ b/samples/vcc/hello_world.c @@ -1,8 +1,10 @@ #include void debug_printf(const char*) __asm__("shady::prim_op::debug_printf"); +void debug_printfi(const char*, int) __asm__("shady::prim_op::debug_printf::i"); compute_shader local_size(1, 1, 1) void main() { debug_printf("Hello World from Vcc!\n"); + debug_printfi("I can print numbers too: %d!\n", 42); } diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index b9ba8e5ab..fe56c8a9a 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -493,7 +493,8 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM if (strcmp(strtok(str, "::"), "shady") == 0) { char* keyword = strtok(NULL, "::"); if (strcmp(keyword, "prim_op") == 0) { - char* opname = strtok(NULL, "::");Op op; + char* opname = strtok(NULL, "::"); + Op op; size_t i; for (i = 0; i < PRIMOPS_COUNT; i++) { if (strcmp(get_primop_name(i), opname) == 0) { From 7031660e59b80ac120db392d5e4a4909a246135b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 09:21:53 -0800 Subject: [PATCH 073/693] eliminate duplicate builtins definitions --- src/shady/compile.c | 3 ++- src/shady/passes/normalize_builtins.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 285d303f6..9f5f5fd90 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -79,7 +79,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(bind_program) RUN_PASS(normalize) - RUN_PASS(normalize_builtins); + RUN_PASS(normalize_builtins) RUN_PASS(infer_program) RUN_PASS(lcssa) @@ -131,6 +131,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { if (config->lower.simt_to_explicit_simd) RUN_PASS(simt2d) RUN_PASS(lower_fill) + RUN_PASS(normalize_builtins) return CompilationNoError; } diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index cd8e3edc9..15937aa09 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -10,6 +10,7 @@ typedef struct { Rewriter rewriter; + Node** builtins; } Context; static const Type* get_req_cast(Context* ctx, const Node* src) { @@ -76,11 +77,14 @@ static const Node* process(Context* ctx, const Node* node) { if (ba) { Builtin b = get_builtin_by_name(get_annotation_string_payload(ba)); assert(b != BuiltinsCount); + if (ctx->builtins[b]) + return ctx->builtins[b]; const Type* t = get_builtin_type(a, b); Node* ndecl = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, global_variable.annotations), t, global_variable.name, global_variable.address_space); register_processed(&ctx->rewriter, node, ndecl); // no 'init' for builtins, right ? assert(!global_variable.init); + ctx->builtins[b] = ndecl; return ndecl; } } @@ -114,8 +118,10 @@ Module* normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* sr Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .builtins = calloc(sizeof(Node*), BuiltinsCount) }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); + free(ctx.builtins); return dst; } From c7a20ae7db2629263dd119723530d65c958b40c3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 11:26:53 -0800 Subject: [PATCH 074/693] normalize the address space of builtins as well --- src/shady/emit/c/emit_c_instructions.c | 1 + src/shady/passes/lower_workgroups.c | 2 -- src/shady/passes/normalize_builtins.c | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 9b2e06621..f5a11e6d7 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -556,6 +556,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct } break; } + case subgroup_assume_uniform_op: case subgroup_broadcast_first_op: { CValue value = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); switch (emitter->config.dialect) { diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 06cc7d982..4c18d6b91 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -36,8 +36,6 @@ static const Node* process(Context* ctx, const Node* node) { return global_var(m, filtered_as, rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsPrivateLogical); case BuiltinNumWorkgroups: return global_var(m, filtered_as, rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsExternal); - case BuiltinWorkgroupSize: - assert(false); default: break; } diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 15937aa09..1c56f554a 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -80,7 +80,7 @@ static const Node* process(Context* ctx, const Node* node) { if (ctx->builtins[b]) return ctx->builtins[b]; const Type* t = get_builtin_type(a, b); - Node* ndecl = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, global_variable.annotations), t, global_variable.name, global_variable.address_space); + Node* ndecl = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, global_variable.annotations), t, global_variable.name, get_builtin_as(b)); register_processed(&ctx->rewriter, node, ndecl); // no 'init' for builtins, right ? assert(!global_variable.init); From 39036f403518e6a11e4131b5be0998ab2d38f521 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 11:27:18 -0800 Subject: [PATCH 075/693] vcc: added subgroup id builtins --- vcc-std/include/shady.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index 3c1b4be75..6416b3ecd 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -49,7 +49,15 @@ native_uvec3 gl_WorkGroupID; __attribute__((annotate("shady::builtin::VertexIndex"))) __attribute__((address_space(389))) -input int gl_VertexIndex; +unsigned gl_VertexIndex; + +__attribute__((annotate("shady::builtin::SubgroupId"))) +__attribute__((address_space(389))) +unsigned subgroup_id; + +__attribute__((annotate("shady::builtin::SubgroupLocalInvocationId"))) +__attribute__((address_space(389))) +unsigned subgroup_local_id; __attribute__((annotate("shady::builtin::WorkgroupSize"))) __attribute__((address_space(389))) From ed94e375e27fd3f3b8b5437c9cefa06e9ee0c795 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 13:57:37 -0800 Subject: [PATCH 076/693] fix CMake on windows --- src/shady/generator/CMakeLists.txt | 2 +- src/shady/passes/lower_subgroup_ops.c | 123 ++++++++++++++++---------- src/shady/transform/ir_gen_helpers.c | 6 ++ src/shady/transform/ir_gen_helpers.h | 1 + 4 files changed, 84 insertions(+), 48 deletions(-) diff --git a/src/shady/generator/CMakeLists.txt b/src/shady/generator/CMakeLists.txt index 3db487381..b01e1e0d3 100644 --- a/src/shady/generator/CMakeLists.txt +++ b/src/shady/generator/CMakeLists.txt @@ -12,7 +12,7 @@ target_link_libraries(import_spv_defs PUBLIC common generator_common) if (WIN32) message("copying DLLs for generator targets") add_custom_command(TARGET import_spv_defs POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ COMMAND_EXPAND_LISTS ) endif () diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 61ca943fe..53a07ff3b 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -2,6 +2,7 @@ #include "portability.h" #include "log.h" +#include "dict.h" #include "../rewrite.h" #include "../type.h" @@ -11,6 +12,7 @@ typedef struct { Rewriter rewriter; const CompilerConfig* config; + struct Dict* fns; } Context; static bool is_extended_type(SHADY_UNUSED IrArena* a, const Type* t, bool allow_vectors) { @@ -26,59 +28,68 @@ static bool is_extended_type(SHADY_UNUSED IrArena* a, const Type* t, bool allow_ } } -static const Node* process_let(Context* ctx, const Node* old) { - assert(old->tag == Let_TAG); +static bool is_supported_natively(Context* ctx, const Type* element_type) { IrArena* a = ctx->rewriter.dst_arena; - const Node* tail = rewrite_node(&ctx->rewriter, old->payload.let.tail); - const Node* old_instruction = old->payload.let.instruction; - - if (old_instruction->tag == PrimOp_TAG) { - PrimOp payload = old_instruction->payload.prim_op; - switch (payload.op) { - case subgroup_broadcast_first_op: { - BodyBuilder* builder = begin_body(a); - const Node* varying_value = rewrite_node(&ctx->rewriter, payload.operands.nodes[0]); - const Type* element_type = get_unqualified_type(varying_value->type); - - if (element_type->tag == Int_TAG && element_type->payload.int_type.width == IntTy32) { - cancel_body(builder); - break; - } else if (is_extended_type(a, element_type, true) && !ctx->config->lower.emulate_subgroup_ops_extended_types) { - cancel_body(builder); - break; - } - - TypeMemLayout layout = get_mem_layout(a, element_type); - - const Type* local_arr_ty = arr_type(a, (ArrType) { .element_type = int32_type(a), .size = NULL }); - - const Node* varying_top_of_stack = gen_primop_e(builder, get_stack_base_op, empty(a), empty(a)); - const Type* varying_raw_ptr_t = ptr_type(a, (PtrType) { .address_space = AsPrivatePhysical, .pointed_type = local_arr_ty }); - const Node* varying_raw_ptr = gen_reinterpret_cast(builder, varying_raw_ptr_t, varying_top_of_stack); - const Type* varying_typed_ptr_t = ptr_type(a, (PtrType) { .address_space = AsPrivatePhysical, .pointed_type = element_type }); - const Node* varying_typed_ptr = gen_reinterpret_cast(builder, varying_typed_ptr_t, varying_top_of_stack); - - gen_store(builder, varying_typed_ptr, varying_value); - for (int32_t j = 0; j < bytes_to_words_static(a, layout.size_in_bytes); j++) { - const Node* varying_logical_addr = gen_lea(builder, varying_raw_ptr, int32_literal(a, 0), nodes(a, 1, (const Node* []) {int32_literal(a, j) })); - const Node* input = gen_load(builder, varying_logical_addr); + if (element_type->tag == Int_TAG && element_type->payload.int_type.width == IntTy32) { + return true; + } else if (!ctx->config->lower.emulate_subgroup_ops_extended_types && is_extended_type(a, element_type, true)) { + return true; + } - const Node* partial_result = gen_primop_ce(builder, subgroup_broadcast_first_op, 1, (const Node* []) { input }); + return false; +} - if (ctx->config->printf_trace.subgroup_ops) - gen_primop(builder, debug_printf_op, empty(a), mk_nodes(a, string_lit(a, (StringLiteral) { .string = "partial_result %d"}), partial_result)); +static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* src); - gen_store(builder, varying_logical_addr, partial_result); - } - const Node* result = gen_load(builder, varying_typed_ptr); - result = first(gen_primop(builder, subgroup_assume_uniform_op, empty(a), singleton(result))); - return finish_body(builder, let(a, quote_helper(a, singleton(result)), tail)); +static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Node* t) { + IrArena* a = ctx->rewriter.dst_arena; + BodyBuilder* bb = begin_body(a); + t = get_maybe_nominal_type_body(t); + switch (is_type(t)) { + case Type_ArrType_TAG: + case Type_RecordType_TAG: { + assert(t->payload.record_type.special == 0); + Nodes element_types = get_composite_type_element_types(t); + LARRAY(const Node*, elements, element_types.count); + for (size_t i = 0; i < element_types.count; i++) { + const Node* e = gen_extract(bb, param, singleton(uint32_literal(a, i))); + elements[i] = build_subgroup_first(ctx, bb, e); } - default: break; + fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { + .fn = fn, + .args = singleton(composite_helper(a, t, nodes(a, element_types.count, elements))) + })); + return; } + default: + log_string(ERROR, "subgroup_first is not supported on "); + log_node(ERROR, t); + log_string(ERROR, ".\n"); + error_die(); + } + SHADY_UNREACHABLE; +} + +static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* src) { + IrArena* a = ctx->rewriter.dst_arena; + Module* m = ctx->rewriter.dst_module; + const Node* t = get_unqualified_type(src->type); + if (is_supported_natively(ctx, t)) + return gen_primop_e(bb, subgroup_broadcast_first_op, empty(a), singleton(src)); + + Node* fn = NULL; + Node** found = find_value_dict(const Node*, Node*, ctx->fns, t); + if (found) + fn = *found; + else { + const Node* param = var(a, qualified_type_helper(t, false), "src"); + fn = function(m, singleton(param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), + singleton(annotation(a, (Annotation) { .name = "Generated"})), singleton(qualified_type_helper(t, true))); + insert_dict(const Node*, Node*, ctx->fns, t, fn); + build_fn_body(ctx, fn, param, t); } - return let(a, rewrite_node(&ctx->rewriter, old_instruction), tail); + return first(gen_call(bb, fn_addr_helper(a, fn), singleton(src))); } static const Node* process(Context* ctx, const Node* node) { @@ -86,12 +97,28 @@ static const Node* process(Context* ctx, const Node* node) { const Node* found = search_processed(&ctx->rewriter, node); if (found) return found; + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; switch (node->tag) { - case Let_TAG: return process_let(ctx, node); - default: return recreate_node_identity(&ctx->rewriter, node); + case PrimOp_TAG: { + PrimOp payload = node->payload.prim_op; + switch (payload.op) { + case subgroup_broadcast_first_op: { + BodyBuilder* bb = begin_body(a); + return yield_values_and_wrap_in_block(bb, singleton( + build_subgroup_first(ctx, bb, rewrite_node(r, first(payload.operands))))); + } + default: break; + } + } + default: break; } + return recreate_node_identity(&ctx->rewriter, node); } +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); IrArena* a = new_ir_arena(aconfig); @@ -100,8 +127,10 @@ Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .config = config, + .fns = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node) }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); + destroy_dict(ctx.fns); return dst; } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 0c6fcfda3..b98023994 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -12,6 +12,12 @@ #include #include +Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { + assert(bb->arena->config.check_types); + const Node* instruction = call(bb->arena, (Call) { .callee = callee, .args = args }); + return bind_instruction(bb, instruction); +} + Nodes gen_primop(BodyBuilder* bb, Op op, Nodes type_args, Nodes operands) { assert(bb->arena->config.check_types); const Node* instruction = prim_op(bb->arena, (PrimOp) { .op = op, .type_arguments = type_args, .operands = operands }); diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index d93803798..50c0942c8 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -8,6 +8,7 @@ void gen_push_value_stack(BodyBuilder* bb, const Node* value); void gen_push_values_stack(BodyBuilder* bb, Nodes values); const Node* gen_pop_value_stack(BodyBuilder*, const Type* type); +Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); Nodes gen_primop(BodyBuilder*, Op, Nodes, Nodes); Nodes gen_primop_c(BodyBuilder*, Op op, size_t operands_count, const Node* operands[]); const Node* gen_primop_ce(BodyBuilder*, Op op, size_t operands_count, const Node* operands[]); From eb7dd9be993c7b7015a02d78f235a748bcbafcf9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 13:58:15 -0800 Subject: [PATCH 077/693] github CI: don't install SPIRV-Headers no more --- .github/workflows/cmake-multi-platform.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 0c6098ea5..730ab5b20 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -56,13 +56,13 @@ jobs: run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - - name: Install SPIRV-Headers - run: | - git clone https://github.com/KhronosGroup/SPIRV-Headers - mkdir SPIRV-Headers/build - cmake -B SPIRV-Headers/build -S SPIRV-Headers - mkdir SPIRV-Headers/install - cmake --install SPIRV-Headers/build --prefix SPIRV-Headers/install + #- name: Install SPIRV-Headers + # run: | + # git clone https://github.com/KhronosGroup/SPIRV-Headers + # mkdir SPIRV-Headers/build + # cmake -B SPIRV-Headers/build -S SPIRV-Headers + # mkdir SPIRV-Headers/install + # cmake --install SPIRV-Headers/build --prefix SPIRV-Headers/install - name: Install Clang & LLVM (setup-clang) if: (!startsWith(matrix.os,'windows')) From 4bd8f1ef1961ab858c65c370c65ef4483d692ca9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 6 Feb 2024 16:53:24 -0800 Subject: [PATCH 078/693] fix leak in generator --- src/shady/generator/import_spv_defs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/generator/import_spv_defs.c b/src/shady/generator/import_spv_defs.c index 14b71c8fb..75908993d 100644 --- a/src/shady/generator/import_spv_defs.c +++ b/src/shady/generator/import_spv_defs.c @@ -204,7 +204,6 @@ json_object* import_operand(json_object* operand, json_object* instruction_filte json_object* import_filtered_instruction(json_object* instruction, json_object* filter) { String name = json_object_get_string(json_object_object_get(instruction, "opname")); assert(name && strlen(name) > 2); - String node_name = sanitize_node_name(name); String import_property = json_object_get_string(json_object_object_get(filter, "import")); if (!import_property || (strcmp(import_property, "no") == 0)) { @@ -212,6 +211,7 @@ json_object* import_filtered_instruction(json_object* instruction, json_object* } else if (strcmp(import_property, "yes") != 0) { error("a filter's 'import' property needs to be 'yes' or 'no'") } + String node_name = sanitize_node_name(name); json_object* node = json_object_new_object(); json_object_object_add(node, "name", json_object_new_string(node_name)); From 1a18a8ebe80b49b7794e87f1e67c9b466e8d88c3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 7 Feb 2024 04:27:02 -0800 Subject: [PATCH 079/693] revampled lower_subgroup_ops to not make use of scratch memory --- src/shady/passes/lower_subgroup_ops.c | 37 +++++++++++++++++++++------ src/shady/transform/ir_gen_helpers.c | 28 ++++++++++++++++++++ src/shady/transform/ir_gen_helpers.h | 2 ++ 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 53a07ff3b..98045e369 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -41,9 +41,10 @@ static bool is_supported_natively(Context* ctx, const Type* element_type) { static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* src); -static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Node* t) { +static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* t) { IrArena* a = ctx->rewriter.dst_arena; BodyBuilder* bb = begin_body(a); + const Type* original_t = t; t = get_maybe_nominal_type_body(t); switch (is_type(t)) { case Type_ArrType_TAG: @@ -57,17 +58,37 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Node* } fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .fn = fn, - .args = singleton(composite_helper(a, t, nodes(a, element_types.count, elements))) + .args = singleton(composite_helper(a, original_t, nodes(a, element_types.count, elements))) })); return; } - default: - log_string(ERROR, "subgroup_first is not supported on "); - log_node(ERROR, t); - log_string(ERROR, ".\n"); - error_die(); + case Type_Int_TAG: { + if (t->payload.int_type.width == IntTy64) { + const Node* hi = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, param, int32_literal(a, 32))); + hi = convert_int_zero_extend(bb, int32_type(a), hi); + const Node* lo = convert_int_zero_extend(bb, int32_type(a), param); + hi = build_subgroup_first(ctx, bb, hi); + lo = build_subgroup_first(ctx, bb, lo); + const Node* it = int_type(a, (Int) { .width = IntTy64, .is_signed = t->payload.int_type.is_signed }); + hi = convert_int_zero_extend(bb, it, hi); + lo = convert_int_zero_extend(bb, it, lo); + hi = gen_primop_e(bb, lshift_op, empty(a), mk_nodes(a, hi, int32_literal(a, 32))); + const Node* result = gen_primop_e(bb, or_op, empty(a), mk_nodes(a, lo, hi)); + fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { + .fn = fn, + .args = singleton(result) + })); + return; + } + break; + } + default: break; } - SHADY_UNREACHABLE; + + log_string(ERROR, "subgroup_first emulation is not supported for "); + log_node(ERROR, t); + log_string(ERROR, ".\n"); + error_die(); } static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* src) { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index b98023994..39d122e6b 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -203,6 +203,34 @@ const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* d return val; } +const Node* convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { + const Type* src_type = get_unqualified_type(src->type); + assert(src_type->tag == Int_TAG); + assert(dst_type->tag == Int_TAG); + + const Node* val = src; + val = gen_primop_e(bb, reinterpret_op, singleton( + int_type(bb->arena, (Int) {.width = src_type->payload.int_type.width, .is_signed = false })), singleton(val)); + val = gen_primop_e(bb, convert_op, singleton( + int_type(bb->arena, (Int) {.width = dst_type->payload.int_type.width, .is_signed = false })), singleton(val)); + val = gen_primop_e(bb, reinterpret_op, singleton(dst_type), singleton(val)); + return val; +} + +const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { + const Type* src_type = get_unqualified_type(src->type); + assert(src_type->tag == Int_TAG); + assert(dst_type->tag == Int_TAG); + + const Node* val = src; + val = gen_primop_e(bb, reinterpret_op, singleton( + int_type(bb->arena, (Int) {.width = src_type->payload.int_type.width, .is_signed = true })), singleton(val)); + val = gen_primop_e(bb, convert_op, singleton( + int_type(bb->arena, (Int) {.width = dst_type->payload.int_type.width, .is_signed = true })), singleton(val)); + val = gen_primop_e(bb, reinterpret_op, singleton(dst_type), singleton(val)); + return val; +} + const Node* get_default_zero_value(IrArena* a, const Type* t) { switch (is_type(t)) { case NotAType: error("") diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 50c0942c8..a6692a86a 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -33,6 +33,8 @@ const Node* access_decl(Rewriter*, const char* name); const Node* convert_int_extend_according_to_src_t(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_extend_according_to_dst_t(BodyBuilder*, const Type* dst_type, const Node* src); +const Node* convert_int_zero_extend(BodyBuilder*, const Type* dst_type, const Node* src); +const Node* convert_int_sign_extend(BodyBuilder*, const Type* dst_type, const Node* src); const Node* get_default_zero_value(IrArena*, const Type*); From b70825e8a8de3fdfb7f12e3cf298156114d2ef5e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Feb 2024 12:39:38 +0100 Subject: [PATCH 080/693] added operands to node classes --- include/shady/grammar.json | 5 +- src/shady/annotation.c | 14 ++---- src/shady/api/generator_grammar.c | 64 +++++++------------------- src/shady/generator/generator.h | 4 ++ src/shady/generator/generator_common.c | 55 ++++++++++++++++++++++ src/shady/generator/generator_main.c | 2 + src/shady/generator_node.c | 45 ++++++++++++++++++ 7 files changed, 130 insertions(+), 59 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 3c10d3a0a..9a6706903 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -116,7 +116,10 @@ "name": "terminator" }, { - "name": "declaration" + "name": "declaration", + "ops": [ + { "name": "annotations", "class": "annotation", "list": true } + ] }, { "name": "case" diff --git a/src/shady/annotation.c b/src/shady/annotation.c index abec2141e..dcefcc4b7 100644 --- a/src/shady/annotation.c +++ b/src/shady/annotation.c @@ -18,17 +18,9 @@ String get_annotation_name(const Node* node) { static const Node* search_annotations(const Node* decl, const char* name, size_t* i) { assert(decl); - const Nodes* annotations = NULL; - switch (decl->tag) { - case Function_TAG: annotations = &decl->payload.fun.annotations; break; - case GlobalVariable_TAG: annotations = &decl->payload.global_variable.annotations; break; - case Constant_TAG: annotations = &decl->payload.constant.annotations; break; - case NominalType_TAG: annotations = &decl->payload.nom_type.annotations; break; - default: error("Not a declaration") - } - - while (*i < annotations->count) { - const Node* annotation = annotations->nodes[*i]; + const Nodes annotations = get_declaration_annotations(decl); + while (*i < annotations.count) { + const Node* annotation = annotations.nodes[*i]; (*i)++; if (strcmp(get_annotation_name(annotation), name) == 0) { return annotation; diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 9e7018b29..9eb208f33 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -1,45 +1,5 @@ #include "generator.h" -static json_object* lookup_node_class(json_object* src, String name) { - json_object* node_classes = json_object_object_get(src, "node-classes"); - for (size_t i = 0; i < json_object_array_length(node_classes); i++) { - json_object* class = json_object_array_get_idx(node_classes, i); - String class_name = json_object_get_string(json_object_object_get(class, "name")); - assert(class_name); - if (strcmp(name, class_name) == 0) - return class; - } - return NULL; -} - -static String class_to_type(json_object* src, String class, bool list) { - assert(class); - if (strcmp(class, "string") == 0) { - if (list) - return "Strings"; - else - return "String"; - } - // check the class is valid - if (!lookup_node_class(src, class)) { - error_print("invalid node class '%s'\n", class); - error_die(); - } - return list ? "Nodes" : "const Node*"; -} - -static String get_type_for_operand(json_object* src, json_object* op) { - String op_type = json_object_get_string(json_object_object_get(op, "type")); - bool list = json_object_get_boolean(json_object_object_get(op, "list")); - String op_class = NULL; - if (!op_type) { - op_class = json_object_get_string(json_object_object_get(op, "class")); - op_type = class_to_type(src, op_class, list); - } - assert(op_type); - return op_type; -} - static void generate_address_spaces(Growy* g, json_object* address_spaces) { growy_append_formatted(g, "typedef enum AddressSpace_ {\n"); for (size_t i = 0; i < json_object_array_length(address_spaces); i++) { @@ -118,17 +78,11 @@ static void generate_node_type(Growy* g, json_object* nodes) { assert(name); String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); - void* alloc = NULL; - if (!snake_name) { - alloc = snake_name = to_snake_case(name); - } + assert(snake_name); json_object* ops = json_object_object_get(node, "ops"); if (ops) growy_append_formatted(g, "\t\t%s %s;\n", name, snake_name); - - if (alloc) - free(alloc); } growy_append_formatted(g, "\t} payload;\n"); @@ -175,6 +129,20 @@ static void generate_node_tags_for_class(Growy* g, json_object* nodes, String cl growy_append_formatted(g, "} %sTag;\n\n", capitalized_class); } +static void generate_header_getters_for_class(Growy* g, json_object* src, json_object* node_class) { + String class_name = json_object_get_string(json_object_object_get(node_class, "name")); + json_object* class_ops = json_object_object_get(node_class, "ops"); + if (!class_ops) + return; + assert(json_object_get_type(class_ops) == json_type_array); + for (size_t i = 0; i < json_object_array_length(class_ops); i++) { + json_object* operand = json_object_array_get_idx(class_ops, i); + String operand_name = json_object_get_string(json_object_object_get(operand, "name")); + assert(operand_name); + growy_append_formatted(g, "%s get_%s_%s(const Node* node);\n", get_type_for_operand(src, operand), class_name, operand_name); + } +} + void generate(Growy* g, json_object* src) { generate_header(g, src); @@ -203,5 +171,7 @@ void generate(Growy* g, json_object* src) { } else { growy_append_formatted(g, "bool is_%s(const Node*);\n", name); } + + generate_header_getters_for_class(g, src, node_class); } } diff --git a/src/shady/generator/generator.h b/src/shady/generator/generator.h index 8536cdcdf..c046431f7 100644 --- a/src/shady/generator/generator.h +++ b/src/shady/generator/generator.h @@ -24,6 +24,10 @@ bool starts_with_vowel(String str); bool has_custom_ctor(json_object* node); void generate_node_ctor(Growy* g, json_object* nodes, bool definition); +json_object* lookup_node_class(json_object* src, String name); +String class_to_type(json_object* src, String class, bool list); +String get_type_for_operand(json_object* src, json_object* op); + void generate_bit_enum(Growy* g, String enum_type_name, String enum_case_prefix, json_object* cases); void generate_bit_enum_classifier(Growy* g, String fn_name, String enum_type_name, String enum_case_prefix, String src_type_name, String src_case_prefix, String src_case_suffix, json_object* cases); diff --git a/src/shady/generator/generator_common.c b/src/shady/generator/generator_common.c index 5d20b2551..6f80789cb 100644 --- a/src/shady/generator/generator_common.c +++ b/src/shady/generator/generator_common.c @@ -63,6 +63,61 @@ void generate_node_ctor(Growy* g, json_object* nodes, bool definition) { growy_append_formatted(g, "\n"); } +json_object* lookup_node_class(json_object* src, String name) { + json_object* node_classes = json_object_object_get(src, "node-classes"); + for (size_t i = 0; i < json_object_array_length(node_classes); i++) { + json_object* class = json_object_array_get_idx(node_classes, i); + String class_name = json_object_get_string(json_object_object_get(class, "name")); + assert(class_name); + if (strcmp(name, class_name) == 0) + return class; + } + return NULL; +} + +String class_to_type(json_object* src, String class, bool list) { + assert(class); + if (strcmp(class, "string") == 0) { + if (list) + return "Strings"; + else + return "String"; + } + // check the class is valid + if (!lookup_node_class(src, class)) { + error_print("invalid node class '%s'\n", class); + error_die(); + } + return list ? "Nodes" : "const Node*"; +} + +String get_type_for_operand(json_object* src, json_object* op) { + String op_type = json_object_get_string(json_object_object_get(op, "type")); + bool list = json_object_get_boolean(json_object_object_get(op, "list")); + String op_class = NULL; + if (!op_type) { + op_class = json_object_get_string(json_object_object_get(op, "class")); + op_type = class_to_type(src, op_class, list); + } + assert(op_type); + return op_type; +} + +void preprocess(json_object* src) { + json_object* nodes = json_object_object_get(src, "nodes"); + for (size_t i = 0; i < json_object_array_length(nodes); i++) { + json_object* node = json_object_array_get_idx(nodes, i); + String name = json_object_get_string(json_object_object_get(node, "name")); + json_object* snake_name = json_object_object_get(node, "snake_name"); + if (!snake_name) { + String tmp = to_snake_case(name); + json_object* generated_snake_name = json_object_new_string(tmp); + json_object_object_add(node, "snake_name", generated_snake_name); + free((void*) tmp); + } + } +} + void generate_bit_enum(Growy* g, String enum_type_name, String enum_case_prefix, json_object* cases) { assert(json_object_get_type(cases) == json_type_array); growy_append_formatted(g, "typedef enum {\n"); diff --git a/src/shady/generator/generator_main.c b/src/shady/generator/generator_main.c index 826f17b5d..3c6dbd3b9 100644 --- a/src/shady/generator/generator_main.c +++ b/src/shady/generator/generator_main.c @@ -3,6 +3,7 @@ #include "util.h" #include "portability.h" +void preprocess(json_object* root); void generate(Growy* g, json_object* root); enum { @@ -45,6 +46,7 @@ int main(int argc, char** argv) { json_apply_object(src, json_files[i].root); } + preprocess(src); generate(g, src); size_t final_size = growy_size(g); diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 3148dc68e..9b424e6e6 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -126,6 +126,49 @@ static void generate_isa_for_class(Growy* g, json_object* nodes, String class, S growy_append_formatted(g, "}\n\n"); } +static bool is_of(json_object* node, String class_name) { + switch (json_object_get_type(node)) { + case json_type_array: { + for (size_t i = 0; i < json_object_array_length(node); i++) + if (is_of(json_object_array_get_idx(node, i), class_name)) + return true; + break; + } + case json_type_string: return strcmp(json_object_get_string(node), class_name) == 0; + default: break; + } + return false; +} + +static void generate_getters_for_class(Growy* g, json_object* src, json_object* nodes, json_object* node_class) { + String class_name = json_object_get_string(json_object_object_get(node_class, "name")); + json_object* class_ops = json_object_object_get(node_class, "ops"); + if (!class_ops) + return; + assert(json_object_get_type(class_ops) == json_type_array); + for (size_t i = 0; i < json_object_array_length(class_ops); i++) { + json_object* operand = json_object_array_get_idx(class_ops, i); + String operand_name = json_object_get_string(json_object_object_get(operand, "name")); + assert(operand_name); + growy_append_formatted(g, "%s get_%s_%s(const Node* node) {\n", get_type_for_operand(src, operand), class_name, operand_name); + growy_append_formatted(g, "\tswitch(node->tag) {\n"); + for (size_t j = 0; j < json_object_array_length(nodes); j++) { + json_object* node = json_object_array_get_idx(nodes, j); + if (is_of(json_object_object_get(node, "class"), class_name)) { + String node_name = json_object_get_string(json_object_object_get(node, "name")); + growy_append_formatted(g, "\t\tcase %s_TAG: ", node_name); + String node_snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); + assert(node_snake_name); + growy_append_formatted(g, "return node->payload.%s.%s;\n", node_snake_name, operand_name); + } + } + growy_append_formatted(g, "\t\tdefault: break;\n"); + growy_append_formatted(g, "\t}\n"); + growy_append_formatted(g, "\tassert(false);\n"); + growy_append_formatted(g, "}\n\n"); + } +} + void generate_address_space_name_fn(Growy* g, json_object* address_spaces) { growy_append_formatted(g, "String get_address_space_name(AddressSpace as) {\n"); growy_append_formatted(g, "\tswitch (as) {\n"); @@ -155,6 +198,8 @@ void generate(Growy* g, json_object* src) { String name = json_object_get_string(json_object_object_get(node_class, "name")); assert(name); + generate_getters_for_class(g, src, nodes, node_class); + json_object* generate_enum = json_object_object_get(node_class, "generate-enum"); String capitalized = capitalize(name); generate_isa_for_class(g, nodes, name, capitalized, !generate_enum || json_object_get_boolean(generate_enum)); From 52b433a1dada5304c3626ca2843d35ea26a62b1f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Feb 2024 12:42:30 +0100 Subject: [PATCH 081/693] autogenerate get_declaration_name --- include/shady/grammar.json | 3 ++- include/shady/ir.h | 1 - src/frontends/llvm/l2s_postprocess.c | 2 +- src/shady/emit/c/emit_c.c | 4 ++-- src/shady/emit/c/emit_c_instructions.c | 2 +- src/shady/module.c | 4 ++-- src/shady/node.c | 10 ---------- src/shady/passes/bind.c | 4 ++-- src/shady/passes/lift_indirect_targets.c | 4 ++-- src/shady/passes/lower_generic_globals.c | 2 +- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/opt_restructure.c | 4 ++-- src/shady/passes/specialize_entry_point.c | 6 +++--- src/shady/passes/spirv_lift_globals_ssbo.c | 2 +- src/shady/print.c | 8 ++++---- src/shady/transform/ir_gen_helpers.c | 2 +- 16 files changed, 25 insertions(+), 35 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 9a6706903..083f11f24 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -118,7 +118,8 @@ { "name": "declaration", "ops": [ - { "name": "annotations", "class": "annotation", "list": true } + { "name": "annotations", "class": "annotation", "list": true }, + { "name": "name", "class": "string" } ] }, { diff --git a/include/shady/ir.h b/include/shady/ir.h index 6760644a0..1bfca60e2 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -112,7 +112,6 @@ ArenaConfig get_arena_config(const IrArena*); //////////////////////////////// Getters //////////////////////////////// /// Get the name out of a global variable, function or constant -String get_decl_name(const Node*); String get_value_name(const Node*); String get_value_name_safe(const Node*); void set_variable_name(Node* var, String); diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 9987cc24e..93531b6cc 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -214,7 +214,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, as = AsUniformConstant; an = an->next; } - Node* decl = global_var(ctx->rewriter.dst_module, annotations, type, get_decl_name(node), as); + Node* decl = global_var(ctx->rewriter.dst_module, annotations, type, get_declaration_name(node), as); register_processed(&ctx->rewriter, node, decl); if (old_init) decl->payload.global_variable.init = rewrite_node(&ctx->rewriter, old_init); diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 03c0952ac..4a6ccfc40 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -288,7 +288,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { break; } case Value_FnAddr_TAG: { - emitted = legalize_c_identifier(emitter, get_decl_name(value->payload.fn_addr.fn)); + emitted = legalize_c_identifier(emitter, get_declaration_name(value->payload.fn_addr.fn)); emitted = format_string_arena(emitter->arena->arena, "(&%s)", emitted); break; } @@ -504,7 +504,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { CType* found2 = lookup_existing_type(emitter, decl); if (found2) return; - const char* name = legalize_c_identifier(emitter, get_decl_name(decl)); + const char* name = legalize_c_identifier(emitter, get_declaration_name(decl)); const Type* decl_type = decl->type; const char* decl_center = name; CTerm emit_as; diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index f5a11e6d7..da3e00e57 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -625,7 +625,7 @@ static void emit_call(Emitter* emitter, Printer* p, const Node* call, Instructio CValue e_callee; const Node* callee = call->payload.call.callee; if (callee->tag == FnAddr_TAG) - e_callee = get_decl_name(callee->payload.fn_addr.fn); + e_callee = get_declaration_name(callee->payload.fn_addr.fn); else e_callee = to_cvalue(emitter, emit_value(emitter, p, callee)); diff --git a/src/shady/module.c b/src/shady/module.c index f5f9d74ce..46396012f 100644 --- a/src/shady/module.c +++ b/src/shady/module.c @@ -32,14 +32,14 @@ Nodes get_module_declarations(const Module* m) { void register_decl_module(Module* m, Node* node) { assert(is_declaration(node)); - assert(!get_declaration(m, get_decl_name(node)) && "duplicate declaration"); + assert(!get_declaration(m, get_declaration_name(node)) && "duplicate declaration"); append_list(Node*, m->decls, node); } const Node* get_declaration(const Module* m, String name) { Nodes existing_decls = get_module_declarations(m); for (size_t i = 0; i < existing_decls.count; i++) { - if (strcmp(get_decl_name(existing_decls.nodes[i]), name) == 0) + if (strcmp(get_declaration_name(existing_decls.nodes[i]), name) == 0) return existing_decls.nodes[i]; } return NULL; diff --git a/src/shady/node.c b/src/shady/node.c index e943889a8..5f47505ca 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -8,16 +8,6 @@ #include #include -String get_decl_name(const Node* node) { - switch (node->tag) { - case Constant_TAG: return node->payload.constant.name; - case Function_TAG: return node->payload.fun.name; - case GlobalVariable_TAG: return node->payload.global_variable.name; - case NominalType_TAG: return node->payload.nom_type.name; - default: error("Not a decl !"); - } -} - String get_value_name(const Node* v) { assert(v && is_value(v)); if (v->tag == Variable_TAG) diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 04809176e..0747f0c72 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -43,7 +43,7 @@ static Resolved resolve_using_name(Context* ctx, const char* name) { Nodes new_decls = get_module_declarations(ctx->rewriter.dst_module); for (size_t i = 0; i < new_decls.count; i++) { const Node* decl = new_decls.nodes[i]; - if (strcmp(get_decl_name(decl), name) == 0) { + if (strcmp(get_declaration_name(decl), name) == 0) { return (Resolved) { .is_var = decl->tag == GlobalVariable_TAG, .node = decl @@ -54,7 +54,7 @@ static Resolved resolve_using_name(Context* ctx, const char* name) { Nodes old_decls = get_module_declarations(ctx->rewriter.src_module); for (size_t i = 0; i < old_decls.count; i++) { const Node* old_decl = old_decls.nodes[i]; - if (strcmp(get_decl_name(old_decl), name) == 0) { + if (strcmp(get_declaration_name(old_decl), name) == 0) { Context top_ctx = *ctx; top_ctx.current_function = NULL; top_ctx.local_variables = NULL; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index e98847467..bbc9bcae7 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -148,10 +148,10 @@ static const Node* process_node(Context* ctx, const Node* node) { // TODO: share this code if (is_declaration(node)) { - String name = get_decl_name(node); + String name = get_declaration_name(node); Nodes decls = get_module_declarations(ctx->rewriter.dst_module); for (size_t i = 0; i < decls.count; i++) { - if (strcmp(get_decl_name(decls.nodes[i]), name) == 0) + if (strcmp(get_declaration_name(decls.nodes[i]), name) == 0) return decls.nodes[i]; } } diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 9fdc0efff..0388ef866 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -24,7 +24,7 @@ static const Node* process(Context* ctx, const Node* node) { const Type* dst_t = ptr_type(a, (PtrType) { .pointed_type = t, .address_space = AsGeneric }); Nodes decl_annotations = singleton(annotation(a, (Annotation) { .name = "Generated" })); Node* constant_decl = constant(ctx->rewriter.dst_module, decl_annotations, dst_t, - format_string_interned(a, "%s_generic", get_decl_name(node))); + format_string_interned(a, "%s_generic", get_declaration_name(node))); const Node* result = constant_decl; constant_decl->payload.constant.instruction = prim_op_helper(a, convert_op, singleton(dst_t), singleton(ref_decl_helper(a, new_global))); register_processed(&ctx->rewriter, node, result); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 4c18d6b91..313995ab0 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -39,7 +39,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return get_builtin(ctx->rewriter.dst_module, b, get_decl_name(node)); + return get_builtin(ctx->rewriter.dst_module, b, get_declaration_name(node)); } break; } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 7c3522562..234ad79a7 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -340,10 +340,10 @@ static const Node* process(Context* ctx, const Node* node) { if (found) return found; if (is_declaration(node)) { - String name = get_decl_name(node); + String name = get_declaration_name(node); Nodes decls = get_module_declarations(ctx->rewriter.dst_module); for (size_t i = 0; i < decls.count; i++) { - if (strcmp(get_decl_name(decls.nodes[i]), name) == 0) + if (strcmp(get_declaration_name(decls.nodes[i]), name) == 0) return decls.nodes[i]; } } diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index e29bdb33a..9786727f7 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -51,9 +51,9 @@ static const Node* process(Context* ctx, const Node* node) { } case Constant_TAG: { Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); - if (strcmp(get_decl_name(ncnst), "SUBGROUP_SIZE") == 0) { + if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, a->config.specializations.subgroup_size))); - } else if (strcmp(get_decl_name(ncnst), "SUBGROUPS_PER_WG") == 0) { + } else if (strcmp(get_declaration_name(ncnst), "SUBGROUPS_PER_WG") == 0) { if (ctx->old_wg_size_annotation) { // SUBGROUPS_PER_WG = (NUMBER OF INVOCATIONS IN SUBGROUP / SUBGROUP SIZE) // Note: this computations assumes only full subgroups are launched, if subgroups can launch partially filled then this relationship does not hold. @@ -80,7 +80,7 @@ static const Node* find_entry_point(Module* m, const CompilerConfig* config) { const Node* found = NULL; Nodes old_decls = get_module_declarations(m); for (size_t i = 0; i < old_decls.count; i++) { - if (strcmp(get_decl_name(old_decls.nodes[i]), config->specialization.entry_point) == 0) { + if (strcmp(get_declaration_name(old_decls.nodes[i]), config->specialization.entry_point) == 0) { assert(!found); found = old_decls.nodes[i]; } diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index 7538de78d..23c237fe0 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -81,7 +81,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul continue; member_tys[lifted_globals_count] = rewrite_node(&ctx.rewriter, odecl->type); - member_names[lifted_globals_count] = get_decl_name(odecl); + member_names[lifted_globals_count] = get_declaration_name(odecl); register_processed(&ctx.rewriter, odecl, int32_literal(a, lifted_globals_count)); lifted_globals_count++; diff --git a/src/shady/print.c b/src/shady/print.c index bf09d5f9b..75528dbc0 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -364,7 +364,7 @@ static void print_type(PrinterCtx* ctx, const Node* node) { break; } case TypeDeclRef_TAG: { - printf("%s", get_decl_name(node->payload.type_decl_ref.decl)); + printf("%s", get_declaration_name(node->payload.type_decl_ref.decl)); break; } } @@ -516,13 +516,13 @@ static void print_value(PrinterCtx* ctx, const Node* node) { } case Value_RefDecl_TAG: { printf(BYELLOW); - printf((char*) get_decl_name(node->payload.ref_decl.decl)); + printf((char*) get_declaration_name(node->payload.ref_decl.decl)); printf(RESET); break; } case FnAddr_TAG: printf(BYELLOW); - printf((char*) get_decl_name(node->payload.fn_addr.fn)); + printf((char*) get_declaration_name(node->payload.fn_addr.fn)); printf(RESET); break; } @@ -878,7 +878,7 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { printf("\n}"); } else if (is_declaration(node)) { printf(BYELLOW); - printf("%s", get_decl_name(node)); + printf("%s", get_declaration_name(node)); printf(RESET); } else if (node->tag == Unbound_TAG) { printf(YELLOW); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 39d122e6b..b935873ec 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -162,7 +162,7 @@ const Node* find_or_process_decl(Rewriter* rewriter, const char* name) { Nodes old_decls = get_module_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { const Node* decl = old_decls.nodes[i]; - if (strcmp(get_decl_name(decl), name) == 0) { + if (strcmp(get_declaration_name(decl), name) == 0) { return rewrite_node(rewriter, decl); } } From 55644d3aa25527a2a90d2357eadb9a820be6e565 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Feb 2024 13:00:22 +0100 Subject: [PATCH 082/693] autogenerate get_annotation_name --- include/shady/grammar.json | 5 ++++- include/shady/ir.h | 1 - src/shady/annotation.c | 11 ----------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 083f11f24..4680dde85 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -129,7 +129,10 @@ "name": "basic_block" }, { - "name": "annotation" + "name": "annotation", + "ops": [ + { "name": "name", "class": "string" } + ] }, { "name": "jump", diff --git a/include/shady/ir.h b/include/shady/ir.h index 1bfca60e2..9f4a9ecd1 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -135,7 +135,6 @@ Nodes get_annotation_values(const Node* annotation); /// Gets the string literal attached to an annotation, if present. const char* get_annotation_string_payload(const Node* annotation); bool lookup_annotation_with_string_payload(const Node* decl, const char* annotation_name, const char* expected_payload); -String get_annotation_name(const Node* node); Nodes filter_out_annotation(IrArena*, Nodes, const char* name); bool is_abstraction (const Node*); diff --git a/src/shady/annotation.c b/src/shady/annotation.c index dcefcc4b7..ae2710b2f 100644 --- a/src/shady/annotation.c +++ b/src/shady/annotation.c @@ -5,17 +5,6 @@ #include #include -String get_annotation_name(const Node* node) { - assert(is_annotation(node)); - switch (node->tag) { - case Annotation_TAG: return node->payload.annotation.name; - case AnnotationValue_TAG: return node->payload.annotation_value.name; - case AnnotationValues_TAG: return node->payload.annotation_values.name; - case AnnotationCompound_TAG: return node->payload.annotation_compound.name; - default: return false; - } -} - static const Node* search_annotations(const Node* decl, const char* name, size_t* i) { assert(decl); const Nodes annotations = get_declaration_annotations(decl); From ddb8a629781dc6f660ad955699e1af89547edfa5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Feb 2024 13:02:25 +0100 Subject: [PATCH 083/693] removed alloca_subgroup --- include/shady/primops.json | 5 ----- src/shady/emit/c/emit_c_instructions.c | 1 - src/shady/passes/lower_alloca.c | 1 - src/shady/passes/lower_physical_ptrs.c | 1 - src/shady/type.c | 1 - 5 files changed, 9 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index 1caf963a2..53cb4342c 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -215,11 +215,6 @@ "class": "memory", "side-effects": true }, - { - "name": "alloca_subgroup", - "class": "memory", - "side-effects": true - }, { "name": "load", "class": "memory", diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index da3e00e57..0e5611b29 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -248,7 +248,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct term = term_from_cvalue(format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); break; } - case alloca_subgroup_op: error("Lower me"); case alloca_op: case alloca_logical_op: { assert(outputs.count == 1); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index f8df498a2..38096a4c0 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -52,7 +52,6 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { if (node->tag == PrimOp_TAG) { switch (node->payload.prim_op.op) { case alloca_op: as = AsPrivatePhysical; break; - case alloca_subgroup_op: as = AsSubgroupPhysical; break; default: goto not_alloca; } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 3c68e6254..3580c3e51 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -301,7 +301,6 @@ static const Node* process_node(Context* ctx, const Node* old) { case PrimOp_TAG: { const PrimOp* oprim_op = &old->payload.prim_op; switch (oprim_op->op) { - case alloca_subgroup_op: case alloca_op: error("This needs to be lowered (see setup_stack_frames.c)") // lowering for either kind of memory accesses is similar case load_op: diff --git a/src/shady/type.c b/src/shady/type.c index 46e3a128d..5cb01e0d7 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -752,7 +752,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { return empty_multiple_return_type(arena); } case alloca_logical_op: as = AsFunctionLogical; goto alloca_case; - case alloca_subgroup_op: as = AsSubgroupPhysical; goto alloca_case; case alloca_op: as = AsPrivatePhysical; goto alloca_case; alloca_case: { assert(prim_op.type_arguments.count == 1); From f93b34acbcc4acf33b407823aff83cb21a91ad05 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 18 Feb 2024 11:59:08 +0100 Subject: [PATCH 084/693] added autogenerated print functions --- include/shady/grammar.json | 4 +- include/shady/ir.h | 2 +- src/shady/CMakeLists.txt | 3 +- src/shady/generator_print.c | 79 ++++++++++++++++++++++++++++++ src/shady/passes/infer.c | 2 +- src/shady/print.c | 97 ++++++++++++++++++++++++++++++++++++- src/shady/print.h | 4 ++ 7 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 src/shady/generator_print.c diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 4680dde85..00dd3f296 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -249,7 +249,7 @@ "class": "type", "ops": [ { "name": "element_type", "class": "type" }, - { "name": "width", "type": "int" } + { "name": "width", "type": "uint32_t" } ] }, { @@ -267,7 +267,7 @@ "constructor": "custom", "ops": [ { "name": "type", "class": "type" }, - { "name": "id", "type": "VarId" }, + { "name": "id", "type": "uint32_t" }, { "name": "name", "class": "string" }, { "name": "abs", "type": "const Node*", "ignore": true }, { "name": "pindex", "type": "unsigned", "ignore": true } diff --git a/include/shady/ir.h b/include/shady/ir.h index 9f4a9ecd1..d03d07a27 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -9,7 +9,7 @@ typedef struct IrArena_ IrArena; typedef struct Node_ Node; typedef struct Node_ Type; -typedef unsigned int VarId; +typedef uint32_t VarId; typedef const char* String; //////////////////////////////// Lists & Strings //////////////////////////////// diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 312bc527a..def8e39de 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -14,9 +14,10 @@ add_generated_file(FILE_NAME primops_generated.c TARGET_NAME primops_genera add_generated_file(FILE_NAME constructors_generated.c TARGET_NAME constructors_generated SOURCES generator_constructors.c) add_generated_file(FILE_NAME visit_generated.c TARGET_NAME visit_generated SOURCES generator_visit.c) add_generated_file(FILE_NAME rewrite_generated.c TARGET_NAME rewrite_generated SOURCES generator_rewrite.c) +add_generated_file(FILE_NAME print_generated.c TARGET_NAME print_generated SOURCES generator_print.c) add_library(shady_generated INTERFACE) -add_dependencies(shady_generated node_generated primops_generated type_generated constructors_generated visit_generated rewrite_generated) +add_dependencies(shady_generated node_generated primops_generated type_generated constructors_generated visit_generated rewrite_generated print_generated) target_include_directories(shady_generated INTERFACE "$") target_link_libraries(api INTERFACE "$") diff --git a/src/shady/generator_print.c b/src/shady/generator_print.c new file mode 100644 index 000000000..59b9ed842 --- /dev/null +++ b/src/shady/generator_print.c @@ -0,0 +1,79 @@ +#include "generator.h" + +void generate_node_print_fns(Growy* g, json_object* src) { + json_object* nodes = json_object_object_get(src, "nodes"); + growy_append_formatted(g, "void print_node_generated(Printer* printer, const Node* node, PrintConfig config) {\n"); + growy_append_formatted(g, "\tswitch (node->tag) { \n"); + assert(json_object_get_type(nodes) == json_type_array); + for (size_t i = 0; i < json_object_array_length(nodes); i++) { + json_object* node = json_object_array_get_idx(nodes, i); + String name = json_object_get_string(json_object_object_get(node, "name")); + String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); + void* alloc = NULL; + if (!snake_name) { + alloc = snake_name = to_snake_case(name); + } + growy_append_formatted(g, "\tcase %s_TAG: {\n", name); + growy_append_formatted(g, "\t\tprint(printer, \"%s \");\n", name); + json_object* ops = json_object_object_get(node, "ops"); + if (ops) { + assert(json_object_get_type(ops) == json_type_array); + for (size_t j = 0; j < json_object_array_length(ops); j++) { + json_object* op = json_object_array_get_idx(ops, j); + bool ignore = json_object_get_boolean(json_object_object_get(op, "ignore")); + if (ignore) + continue; + + String op_name = json_object_get_string(json_object_object_get(op, "name")); + String op_class = json_object_get_string(json_object_object_get(op, "class")); + if (op_class && strcmp(op_class, "string") != 0) { + bool is_list = json_object_get_boolean(json_object_object_get(op, "list")); + String cap_class = capitalize(op_class); + if (is_list) { + growy_append_formatted(g, "\t\t{\n"); + growy_append_formatted(g, "\t\t\tprint_node_operand_list(printer, node, \"%s\", Nc%s, node->payload.%s.%s, config);\n", op_name, cap_class, snake_name, op_name); + // growy_append_formatted(g, "\t\t\tsize_t count = node->payload.%s.%s.count;\n", snake_name, op_name); + // growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < count; i++) {\n"); + // growy_append_formatted(g, "\t\t\t\tprint_node_operand(printer, node, \"%s\", Nc%s, i, node->payload.%s.%s.nodes[i], config);\n", op_name, cap_class, snake_name, op_name); + // growy_append_formatted(g, "\t\t\t}\n"); + growy_append_formatted(g, "\t\t}\n"); + } else { + growy_append_formatted(g, "\t\t{\n"); + growy_append_formatted(g, "\t\t\tprint_node_operand(printer, node, \"%s\", Nc%s, node->payload.%s.%s, config);\n", op_name, cap_class, snake_name, op_name); + growy_append_formatted(g, "\t\t}\n"); + } + free(cap_class); + } else { + String op_type = json_object_get_string(json_object_object_get(op, "type")); + if (!op_type) { + assert(op_class && strcmp(op_class, "string") == 0); + if (json_object_get_boolean(json_object_object_get(op, "list"))) + op_type = "Strings"; + else + op_type = "String"; + } + char* s = strdup(op_type); + for (size_t k = 0; k < strlen(op_type); k++) { + if (!isalnum(s[k])) + s[k] = '_'; + } + growy_append_formatted(g, "\t\tprint_node_operand_%s(printer, node, \"%s\", node->payload.%s.%s, config);\n", s, op_name, snake_name, op_name); + free(s); + } + } + } + growy_append_formatted(g, "\t\tbreak;\n"); + growy_append_formatted(g, "\t}\n", name); + if (alloc) + free(alloc); + } + growy_append_formatted(g, "\t\tdefault: assert(false);\n"); + growy_append_formatted(g, "\t}\n"); + growy_append_formatted(g, "}\n"); +} + +void generate(Growy* g, json_object* src) { + generate_header(g, src); + //growy_append_formatted(g, "#include \"print.h\"\n\n"); + generate_node_print_fns(g, src); +} diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 256d2d46f..70b2f642f 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -242,7 +242,7 @@ static const Node* _infer_value(Context* ctx, const Node* node, const Type* expe AddressSpace as = decl->payload.global_variable.address_space; if (is_physical_as(as)) { const Node* untyped_ptr = ptr_type(a, (PtrType) {.address_space = as, .pointed_type = unit_type(a)}); - Node* cast_constant = constant(ctx->rewriter.dst_module, empty(a), untyped_ptr, format_string_interned(a, "%s_cast", get_decl_name(decl))); + Node* cast_constant = constant(ctx->rewriter.dst_module, empty(a), untyped_ptr, format_string_interned(a, "%s_cast", get_declaration_name(decl))); cast_constant->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr), singleton(ref_decl)); const Node* cast_ref_decl = ref_decl_helper(a, cast_constant); register_processed(r, node, cast_ref_decl); diff --git a/src/shady/print.c b/src/shady/print.c index 75528dbc0..3b7d18514 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -367,6 +367,9 @@ static void print_type(PrinterCtx* ctx, const Node* node) { printf("%s", get_declaration_name(node->payload.type_decl_ref.decl)); break; } + default: + print_node_generated(ctx->printer, node, ctx->config); + break; } printf(RESET); } @@ -525,13 +528,15 @@ static void print_value(PrinterCtx* ctx, const Node* node) { printf((char*) get_declaration_name(node->payload.fn_addr.fn)); printf(RESET); break; + default: + print_node_generated(ctx->printer, node, ctx->config); + break; } } static void print_instruction(PrinterCtx* ctx, const Node* node) { switch (is_instruction(node)) { case NotAnInstruction: assert(false); break; - default: assert(false); case Instruction_Comment_TAG: { printf(GREY); printf("/* %s */", node->payload.comment.string); @@ -631,6 +636,7 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { print_case_body(ctx, node->payload.block.inside); break; } + default: print_node_generated(ctx->printer, node, ctx->config); } } @@ -928,7 +934,9 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { printf(RESET); break; } - default: error("dunno how to print %s", node_tags[node->tag]); + default: + print_node_generated(ctx->printer, node, ctx->config); + break; } } @@ -1002,3 +1010,88 @@ void log_module(LogLevel level, CompilerConfig* compiler_cfg, Module* mod) { if (level >= get_log_level()) print_module(open_file_as_printer(stderr), mod, config); } + +void print_node_operand(Printer* p, const Node* n, String name, NodeClass op_class, const Node* op, PrintConfig config) { + print(p, " '%s': %%zu", name, (size_t) op); +} + +void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass op_class, Nodes ops, PrintConfig config) { + print(p, " '%s': [", name); + for (size_t i = 0; i < ops.count; i++) { + print(p, "%%zu", (size_t) ops.nodes[i]); + if (i + 1 < ops.count) + print(p, ", "); + } + print(p, "]"); +} + +void print_node_operand_const_Node_(Printer* p, const Node* n, String name, const Node* op, PrintConfig config) { + print(p, " '%s': %%zu", name, (size_t) op); +} + +void print_node_operand_AddressSpace(Printer* p, const Node* n, String name, AddressSpace as, PrintConfig config) { + print(p, " '%s': %s", name, get_address_space_name(as)); +} + +void print_node_operand_Op(Printer* p, const Node* n, String name, Op op, PrintConfig config) { + print(p, " '%s': %s", name, get_primop_name(op)); +} + +void print_node_operand_RecordSpecialFlag(Printer* p, const Node* n, String name, RecordSpecialFlag flags, PrintConfig config) { + print(p, " '%s': ", name); + if (flags & MultipleReturn) + print(p, "MultipleReturn"); + if (flags & DecorateBlock) + print(p, "DecorateBlock"); +} + +void print_node_operand_uint32_t(Printer* p, const Node* n, String name, uint32_t i, PrintConfig config) { + print(p, " '%s': %u", name, i); +} + +void print_node_operand_uint64_t(Printer* p, const Node* n, String name, uint64_t i, PrintConfig config) { + print(p, " '%s': %zu", name, i); +} + +void print_node_operand_IntSizes(Printer* p, const Node* n, String name, IntSizes s, PrintConfig config) { + print(p, " '%s': ", name); + switch (s) { + case IntTy8: print(p, "8"); break; + case IntTy16: print(p, "16"); break; + case IntTy32: print(p, "32"); break; + case IntTy64: print(p, "64"); break; + } +} + +void print_node_operand_FloatSizes(Printer* p, const Node* n, String name, FloatSizes s, PrintConfig config) { + print(p, " '%s': ", name); + switch (s) { + case FloatTy16: print(p, "16"); break; + case FloatTy32: print(p, "32"); break; + case FloatTy64: print(p, "64"); break; + } +} + +void print_node_operand_String(Printer* p, const Node* n, String name, String s, PrintConfig config) { + print(p, " '%s': \"%s\"", name, s); +} + +void print_node_operand_Strings(Printer* p, const Node* n, String name, Strings ops, PrintConfig config) { + print(p, " '%s': [", name); + for (size_t i = 0; i < ops.count; i++) { + print(p, "\"%s\"", (size_t) ops.strings[i]); + if (i + 1 < ops.count) + print(p, ", "); + } + print(p, "]"); +} + +void print_node_operand_bool(Printer* p, const Node* n, String name, bool b, PrintConfig config) { + print(p, " '%s': ", name); + if (b) + print(p, "true"); + else + print(p, "false"); +} + +#include "print_generated.c" diff --git a/src/shady/print.h b/src/shady/print.h index 852e9b4b9..2d04a7d48 100644 --- a/src/shady/print.h +++ b/src/shady/print.h @@ -16,6 +16,10 @@ typedef struct { void print_module(Printer* printer, Module* mod, PrintConfig config); void print_node(Printer* printer, const Node* node, PrintConfig config); +void print_node_operand(Printer* printer, const Node* node, String op_name, NodeClass op_class, const Node* op, PrintConfig config); +void print_node_operand_list(Printer* printer, const Node* node, String op_name, NodeClass op_class, Nodes ops, PrintConfig config); + +void print_node_generated(Printer* printer, const Node* node, PrintConfig config); void print_module_into_str(Module* mod, char** str_ptr, size_t* size); void print_node_into_str(const Node* node, char** str_ptr, size_t* size); From 42530642125d98105cb95182a0d5c119c96b84c5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Feb 2024 10:24:02 +0100 Subject: [PATCH 085/693] give all nodes unique IDs, just like in SPIR-V --- include/shady/grammar.json | 1 - include/shady/ir.h | 3 ++- src/shady/api/generator_grammar.c | 1 + src/shady/constructors.c | 2 +- src/shady/emit/c/emit_c.c | 16 +++++++--------- src/shady/emit/c/emit_c_instructions.c | 3 +-- src/shady/emit/c/emit_c_signatures.c | 5 +---- src/shady/ir.c | 16 +++++++++++----- src/shady/ir_private.h | 6 ++++-- src/shady/node.c | 2 +- src/shady/passes/bind.c | 4 +++- src/shady/passes/lcssa.c | 4 +++- src/shady/print.c | 10 +++++----- 13 files changed, 40 insertions(+), 33 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 00dd3f296..c56f65ee2 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -267,7 +267,6 @@ "constructor": "custom", "ops": [ { "name": "type", "class": "type" }, - { "name": "id", "type": "uint32_t" }, { "name": "name", "class": "string" }, { "name": "abs", "type": "const Node*", "ignore": true }, { "name": "pindex", "type": "unsigned", "ignore": true } diff --git a/include/shady/ir.h b/include/shady/ir.h index d03d07a27..7687f6010 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -9,7 +9,7 @@ typedef struct IrArena_ IrArena; typedef struct Node_ Node; typedef struct Node_ Type; -typedef uint32_t VarId; +typedef uint32_t NodeId; typedef const char* String; //////////////////////////////// Lists & Strings //////////////////////////////// @@ -108,6 +108,7 @@ ArenaConfig default_arena_config(); IrArena* new_ir_arena(ArenaConfig); void destroy_ir_arena(IrArena*); ArenaConfig get_arena_config(const IrArena*); +const Node* get_node_by_id(const IrArena*, NodeId); //////////////////////////////// Getters //////////////////////////////// diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 9eb208f33..3ad3a6f26 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -67,6 +67,7 @@ static void generate_node_payloads(Growy* g, json_object* src, json_object* node static void generate_node_type(Growy* g, json_object* nodes) { growy_append_formatted(g, "struct Node_ {\n"); growy_append_formatted(g, "\tIrArena* arena;\n"); + growy_append_formatted(g, "\tNodeId id;\n"); growy_append_formatted(g, "\tconst Type* type;\n"); growy_append_formatted(g, "\tNodeTag tag;\n"); growy_append_formatted(g, "\tunion NodesUnion {\n"); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index af9466740..e63ccf029 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -65,6 +65,7 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { // place the node in the arena and return it Node* alloc = (Node*) arena_alloc(arena->arena, sizeof(Node)); *alloc = node; + alloc->id = allocate_node_id(arena, alloc); insert_set_get_result(const Node*, arena->node_set, alloc); post_construction_validation(arena, alloc); @@ -94,7 +95,6 @@ Node* var(IrArena* arena, const Type* type, const char* name) { Variable variable = { .type = type, .name = string(arena, name), - .id = fresh_id(arena) }; Node node; diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 4a6ccfc40..ceaba3409 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -50,6 +50,8 @@ static bool is_legal_c_identifier_char(char c) { } String legalize_c_identifier(Emitter* e, String src) { + if (!src) + return "unnamed"; size_t len = strlen(src); LARRAY(char, dst, len + 1); size_t i; @@ -388,11 +390,10 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node case LetBinding: { String variable_name = get_value_name(tail_params.nodes[i]); - String bind_to; - if (variable_name) - bind_to = format_string_arena(emitter->arena->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), fresh_id(emitter->arena)); - else - bind_to = format_string_arena(emitter->arena->arena, "v%d", fresh_id(emitter->arena)); + if (!variable_name) + variable_name = ""; + + String bind_to = unique_name(emitter->arena, variable_name); const Type* t = yield_types.nodes[i]; @@ -604,10 +605,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { for (size_t i = 0; i < decl->payload.fun.params.count; i++) { String param_name; String variable_name = get_value_name(decl->payload.fun.params.nodes[i]); - if (variable_name) - param_name = format_string_arena(emitter->arena->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->payload.var.id); - else - param_name = format_string_arena(emitter->arena->arena, "p%d", decl->payload.fun.params.nodes[i]->payload.var.id); + param_name = unique_name(emitter->arena, legalize_c_identifier(emitter, variable_name)); register_emitted(emitter, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 0e5611b29..abc2cec24 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -32,10 +32,9 @@ static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String g assert(init_values->count == types.count); LARRAY(String, names, types.count); for (size_t i = 0; i < types.count; i++) { - VarId id = fresh_id(emitter->arena); String name = given_names ? given_names->strings[i] : given_name; assert(name); - names[i] = format_string_arena(emitter->arena->arena, "%s_%d", name, id); + names[i] = unique_name(emitter->arena, name); if (init_values) { CTerm initializer = emit_value(emitter, p, init_values->nodes[i]); emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index 0e8cb5503..88274e738 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -59,10 +59,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const for (size_t i = 0; i < dom.count; i++) { String param_name; String variable_name = get_value_name(fn->payload.fun.params.nodes[i]); - if (variable_name) - param_name = format_string_arena(emitter->arena->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->payload.var.id); - else - param_name = format_string_arena(emitter->arena->arena, "p%d", fn->payload.fun.params.nodes[i]->payload.var.id); + param_name = unique_name(emitter->arena, legalize_c_identifier(emitter, variable_name)); print(paramp, emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { print(paramp, ", "); diff --git a/src/shady/ir.c b/src/shady/ir.c index de11f036e..1a2dc6287 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -28,8 +28,6 @@ IrArena* new_ir_arena(ArenaConfig config) { .arena = new_arena(), .config = config, - .next_free_id = 0, - .modules = new_list(Module*), .node_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), @@ -37,10 +35,16 @@ IrArena* new_ir_arena(ArenaConfig config) { .nodes_set = new_set(Nodes, (HashFn) hash_nodes, (CmpFn) compare_nodes), .strings_set = new_set(Strings, (HashFn) hash_strings, (CmpFn) compare_strings), + + .ids = new_growy(), }; return arena; } +const Node* get_node_by_id(const IrArena* a, NodeId id) { + return ((const Node**) growy_data(a->ids))[id]; +} + void destroy_ir_arena(IrArena* arena) { for (size_t i = 0; i < entries_count_list(arena->modules); i++) { destroy_module(read_list(Module*, arena->modules)[i]); @@ -52,6 +56,7 @@ void destroy_ir_arena(IrArena* arena) { destroy_dict(arena->nodes_set); destroy_dict(arena->node_set); destroy_arena(arena->arena); + destroy_growy(arena->ids); free(arena); } @@ -59,8 +64,9 @@ ArenaConfig get_arena_config(const IrArena* a) { return a->config; } -VarId fresh_id(IrArena* arena) { - return arena->next_free_id++; +NodeId allocate_node_id(IrArena* arena, const Node* n) { + growy_append_object(arena->ids, n); + return growy_size(arena->ids) / sizeof(const Node*); } Nodes nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { @@ -212,7 +218,7 @@ String format_string_interned(IrArena* arena, const char* str, ...) { } const char* unique_name(IrArena* arena, const char* str) { - return format_string_interned(arena, "%s_%d", str, fresh_id(arena)); + return format_string_interned(arena, "%s_%d", str, allocate_node_id(arena, NULL)); } KeyHash hash_nodes(Nodes* nodes) { diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index f2163f017..4e20799a4 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -5,6 +5,8 @@ #include "arena.h" +#include "growy.h" + #include "stdlib.h" #include "stdio.h" @@ -12,7 +14,7 @@ typedef struct IrArena_ { Arena* arena; ArenaConfig config; - VarId next_free_id; + Growy* ids; struct List* modules; struct Dict* node_set; @@ -37,7 +39,7 @@ struct BodyBuilder_ { struct List* stack; }; -VarId fresh_id(IrArena*); +NodeId allocate_node_id(IrArena*, const Node* n); struct List; Nodes list_to_nodes(IrArena*, struct List*); diff --git a/src/shady/node.c b/src/shady/node.c index 5f47505ca..18d2f7952 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -20,7 +20,7 @@ String get_value_name_safe(const Node* v) { if (name) return name; if (v->tag == Variable_TAG) - return format_string_interned(v->arena, "v%d", v->payload.var.id); + return format_string_interned(v->arena, "v%d", v->id); return node_tags[v->tag]; } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 0747f0c72..573989b6d 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -148,7 +148,9 @@ static const Node* desugar_let_mut(Context* ctx, const Node* node) { bind_instruction_outputs_count(bb, store, 0, NULL, false); add_binding(&body_infer_ctx, true, oparam->payload.var.name, ptr); - debugv_print("Lowered mutable variable %s\n", get_value_name_safe(oparam)); + log_string(DEBUGV, "Lowered mutable variable "); + log_node(DEBUGV, oparam); + log_string(DEBUGV, ".\n;"); } const Node* terminator = rewrite_node(&body_infer_ctx.rewriter, old_lam->payload.case_.body); diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 9d3492b2f..b7ccd9f63 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -64,7 +64,9 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No const LTNode* defining_loop = get_loop(looptree_lookup(ctx->loop_tree, defining_cf_node->node)); if (!is_child(defining_loop, bb_loop)) { // that's it, that variable is leaking ! - debug_print("lcssa: %s~%d is used outside of the loop that defines it %s %s\n", get_value_name_safe(fv), fv->payload.var.id, loop_name(defining_loop), loop_name(bb_loop)); + log_string(DEBUGV, "lcssa: "); + log_node(DEBUGV, fv); + log_string(DEBUGV, " (%%%d) is used outside of the loop that defines it %s %s\n", fv->id, loop_name(defining_loop), loop_name(bb_loop)); const Node* narg = rewrite_node(&ctx->rewriter, fv); const Node* nparam = var(a, narg->type, "lcssa_phi"); *nparams = append_nodes(a, *nparams, nparam); diff --git a/src/shady/print.c b/src/shady/print.c index 3b7d18514..bae07d6fa 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -414,9 +414,9 @@ static void print_value(PrinterCtx* ctx, const Node* node) { printf(YELLOW); String name = get_value_name(node); if (name) - printf("%s_%d", name, node->payload.var.id); + printf("%s", name); else - printf("v%d", node->payload.var.id); + printf("%%%d", node->id); printf(RESET); break; case UntypedNumber_TAG: @@ -1012,13 +1012,13 @@ void log_module(LogLevel level, CompilerConfig* compiler_cfg, Module* mod) { } void print_node_operand(Printer* p, const Node* n, String name, NodeClass op_class, const Node* op, PrintConfig config) { - print(p, " '%s': %%zu", name, (size_t) op); + print(p, " '%s': %%%zu", name, (size_t) op); } void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass op_class, Nodes ops, PrintConfig config) { print(p, " '%s': [", name); for (size_t i = 0; i < ops.count; i++) { - print(p, "%%zu", (size_t) ops.nodes[i]); + print(p, "%%%zu", (size_t) ops.nodes[i]); if (i + 1 < ops.count) print(p, ", "); } @@ -1026,7 +1026,7 @@ void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass o } void print_node_operand_const_Node_(Printer* p, const Node* n, String name, const Node* op, PrintConfig config) { - print(p, " '%s': %%zu", name, (size_t) op); + print(p, " '%s': %%%zu", name, (size_t) op); } void print_node_operand_AddressSpace(Printer* p, const Node* n, String name, AddressSpace as, PrintConfig config) { From 00fd41d25b31463043cc57a828d970d8ff7224a2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Feb 2024 12:53:38 +0100 Subject: [PATCH 086/693] remove 'mut' param from body_builder fns, add create_mutable_variables instead --- include/shady/ir.h | 5 +++-- src/frontends/llvm/l2s.c | 2 +- src/frontends/llvm/l2s_instr.c | 10 +++++----- src/frontends/slim/parser.c | 6 +++--- src/frontends/spirv/s2s.c | 32 ++++++++++++++++---------------- src/shady/body_builder.c | 12 ++++++++---- src/shady/passes/bind.c | 6 +++--- src/shady/passes/normalize.c | 2 +- 8 files changed, 40 insertions(+), 35 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 7687f6010..24c35b78a 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -241,8 +241,9 @@ Nodes bind_instruction_named(BodyBuilder*, const Node* instruction, String const /// Like append instruction, but you explicitly give it information about any yielded values /// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! -Nodes bind_instruction_explicit_result_types(BodyBuilder*, const Node* initial_value, Nodes provided_types, String const output_names[], bool mut); -Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count, String const output_names[], bool mut); +Nodes bind_instruction_explicit_result_types(BodyBuilder*, const Node* initial_value, Nodes provided_types, String const output_names[]); +Nodes create_mutable_variables(BodyBuilder*, const Node* initial_value, Nodes provided_types, String const output_names[]); +Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count, String const output_names[]); void bind_variables(BodyBuilder*, Nodes vars, Nodes values); diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 23d7974b8..02141af4c 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -47,7 +47,7 @@ static const Node* write_bb_tail(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM if (!emitted.instruction) continue; String names[] = { LLVMGetValueName(instr) }; - Nodes results = bind_instruction_explicit_result_types(b, emitted.instruction, emitted.result_types, names, false); + Nodes results = bind_instruction_explicit_result_types(b, emitted.instruction, emitted.result_types, names); if (emitted.result_types.count == 1) { const Node* result = first(results); insert_dict(LLVMValueRef, const Node*, p->map, instr, result); diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index fe56c8a9a..f9349b97c 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -37,7 +37,7 @@ static Nodes reinterpret_operands(BodyBuilder* b, Nodes ops, const Type* dst_t) IrArena* a = dst_t->arena; LARRAY(const Node*, nops, ops.count); for (size_t i = 0; i < ops.count; i++) - nops[i] = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(dst_t), singleton(ops.nodes[i])), singleton(dst_t), NULL, false)); + nops[i] = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(dst_t), singleton(ops.nodes[i])), singleton(dst_t), NULL)); return nodes(a, ops.count, nops); } @@ -101,7 +101,7 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM const Type* t = convert_type(p, LLVMTypeOf(instr)); -#define BIND_PREV_R(t) bind_instruction_explicit_result_types(b, r, singleton(t), NULL, false) +#define BIND_PREV_R(t) bind_instruction_explicit_result_types(b, r, singleton(t), NULL) //if (LLVMIsATerminatorInst(instr)) { if (LLVMIsAInstruction(instr)) { @@ -220,10 +220,10 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM assert(t->tag == PtrType_TAG); const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivatePhysical }); - r = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, alloca_op, singleton(allocated_t), empty(a)), singleton(allocated_ptr_t), NULL, false)); + r = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, alloca_op, singleton(allocated_t), empty(a)), singleton(allocated_ptr_t), NULL)); if (UNTYPED_POINTERS) { const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivatePhysical }); - r = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), 1, NULL, false)); + r = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), 1, NULL)); } r = prim_op_helper(a, convert_op, singleton(t), singleton(r)); break; @@ -507,7 +507,7 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM LARRAY(const Node*, processed_ops, ops.count); for (i = 0; i < num_args; i++) { if (decoded[i].is_byval) - processed_ops[i] = first(bind_instruction_outputs_count(b, prim_op_helper(a, load_op, empty(a), singleton(ops.nodes[i])), 1, NULL, false)); + processed_ops[i] = first(bind_instruction_outputs_count(b, prim_op_helper(a, load_op, empty(a), singleton(ops.nodes[i])), 1, NULL)); else processed_ops[i] = ops.nodes[i]; } diff --git a/src/frontends/slim/parser.c b/src/frontends/slim/parser.c index 87be4c718..c65ff6667 100644 --- a/src/frontends/slim/parser.c +++ b/src/frontends/slim/parser.c @@ -672,17 +672,17 @@ static bool accept_non_terminator_instr(ctxparams, BodyBuilder* bb, Node* fn) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok)); const Node* instruction = accept_instruction(ctx, fn, true); - bind_instruction_outputs_count(bb, instruction, ids.count, ids.strings, false); + bind_instruction_outputs_count(bb, instruction, ids.count, ids.strings); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok)); const Node* instruction = accept_instruction(ctx, fn, true); - bind_instruction_explicit_result_types(bb, instruction, types, ids.strings, true); + create_mutable_variables(bb, instruction, types, ids.strings); } else { const Node* instr = accept_instruction(ctx, fn, true); if (!instr) return false; - bind_instruction_outputs_count(bb, instr, 0, NULL, false); + bind_instruction_outputs_count(bb, instr, 0, NULL); } return true; } diff --git a/src/frontends/spirv/s2s.c b/src/frontends/spirv/s2s.c index 978e25f5d..94b8a216e 100644 --- a/src/frontends/spirv/s2s.c +++ b/src/frontends/spirv/s2s.c @@ -458,7 +458,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = shd_op.op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, num_ops, ops) - }), results_count, NULL, false); + }), results_count, NULL); if (has_result) { parser->defs[result].type = Value; parser->defs[result].node = first(results); @@ -742,7 +742,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = alloca_op, .type_arguments = singleton(contents_t), .operands = empty(parser->arena) - }), 1, NULL, false)); + }), 1, NULL)); parser->defs[result].type = Value; parser->defs[result].node = ptr; @@ -752,7 +752,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = store_op, .type_arguments = empty(parser->arena), .operands = mk_nodes(parser->arena, ptr, get_def_ssa_value(parser, instruction[4])) - }), 1, NULL, false); + }), 1, NULL); } else { Nodes annotations = empty(parser->arena); SpvDeco* builtin = find_decoration(parser, result, -1, SpvDecorationBuiltIn); @@ -971,7 +971,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = convert_op, .type_arguments = singleton(dst_t), .operands = singleton(src) - }), 1, NULL, false)); + }), 1, NULL)); break; } case SpvOpConvertPtrToU: @@ -984,7 +984,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = reinterpret_op, .type_arguments = singleton(dst_t), .operands = singleton(src) - }), 1, NULL, false)); + }), 1, NULL)); break; } case SpvOpInBoundsPtrAccessChain: @@ -1007,7 +1007,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = lea_op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, 2 + num_indices, ops) - }), 1, NULL, false)); + }), 1, NULL)); break; } case SpvOpCompositeExtract: { @@ -1021,7 +1021,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = extract_op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, 1 + num_indices, ops) - }), 1, NULL, false)); + }), 1, NULL)); break; } case SpvOpCompositeInsert: { @@ -1036,7 +1036,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = insert_op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, 2 + num_indices, ops) - }), 1, NULL, false)); + }), 1, NULL)); break; } case SpvOpVectorShuffle: { @@ -1061,7 +1061,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = extract_op, .type_arguments = empty(parser->arena), .operands = mk_nodes(parser->arena, src, int32_literal(parser->arena, index)) - }), 1, NULL, false)); + }), 1, NULL)); } parser->defs[result].type = Value; @@ -1078,7 +1078,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = load_op, .type_arguments = empty(parser->arena), .operands = singleton(src) - }), 1, NULL, false)); + }), 1, NULL)); break; } case SpvOpStore: { @@ -1088,7 +1088,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = store_op, .type_arguments = empty(parser->arena), .operands = mk_nodes(parser->arena, ptr, value) - }), 0, NULL, false); + }), 0, NULL); break; } case SpvOpCopyMemory: @@ -1104,7 +1104,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = size_of_op, .type_arguments = singleton(elem_t), .operands = empty(parser->arena) - }), 1, NULL, false)); + }), 1, NULL)); } else { cnt = get_def_ssa_value(parser, instruction[3]); } @@ -1112,7 +1112,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = memcpy_op, .type_arguments = empty(parser->arena), .operands = mk_nodes(parser->arena, dst, src, cnt) - }), 0, NULL, false); + }), 0, NULL); break; } case SpvOpSelectionMerge: @@ -1154,7 +1154,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, num_args, args) - }), rslts_count, NULL, false); + }), rslts_count, NULL); if (rslts_count == 1) parser->defs[result].node = first(rslts); @@ -1165,7 +1165,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { Nodes rslts = bind_instruction_outputs_count(parser->current_block.builder, call(parser->arena, (Call) { .callee = fn_addr_helper(parser->arena, callee), .args = nodes(parser->arena, num_args, args) - }), rslts_count, NULL, false); + }), rslts_count, NULL); if (rslts_count == 1) parser->defs[result].node = first(rslts); @@ -1285,7 +1285,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, instr, 1, NULL, false)); + parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, instr, 1, NULL)); break; } case SpvOpBranch: { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 890a4ce62..005de73fe 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -87,12 +87,16 @@ Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String co return bind_internal(bb, instruction, false, SIZE_MAX, NULL, output_names); } -Nodes bind_instruction_explicit_result_types(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[], bool mut) { - return bind_internal(bb, instruction, mut, provided_types.count, provided_types.nodes, output_names); +Nodes bind_instruction_explicit_result_types(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[]) { + return bind_internal(bb, instruction, false, provided_types.count, provided_types.nodes, output_names); } -Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count, String const output_names[], bool mut) { - return bind_internal(bb, instruction, mut, outputs_count, NULL, output_names); +Nodes create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[]) { + return bind_internal(bb, instruction, true, provided_types.count, provided_types.nodes, output_names); +} + +Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count, String const output_names[]) { + return bind_internal(bb, instruction, false, outputs_count, NULL, output_names); } void bind_variables(BodyBuilder* bb, Nodes vars, Nodes values) { diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 573989b6d..d517edd28 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -129,7 +129,7 @@ static const Node* desugar_let_mut(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); - Nodes initial_values = bind_instruction_outputs_count(bb, ninstruction, old_lam->payload.case_.params.count, NULL, false); + Nodes initial_values = bind_instruction_outputs_count(bb, ninstruction, old_lam->payload.case_.params.count, NULL); Nodes old_params = old_lam->payload.case_.params; for (size_t i = 0; i < old_params.count; i++) { const Node* oparam = old_params.nodes[i]; @@ -140,12 +140,12 @@ static const Node* desugar_let_mut(Context* ctx, const Node* node) { .type_arguments = nodes(a, 1, (const Node* []){rewrite_node(&ctx->rewriter, type_annotation) }), .operands = nodes(a, 0, NULL) }); - const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.var.name, false).nodes[0]; + const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.var.name).nodes[0]; const Node* store = prim_op(a, (PrimOp) { .op = store_op, .operands = nodes(a, 2, (const Node* []) {ptr, initial_values.nodes[0] }) }); - bind_instruction_outputs_count(bb, store, 0, NULL, false); + bind_instruction_outputs_count(bb, store, 0, NULL); add_binding(&body_infer_ctx, true, oparam->payload.var.name, ptr); log_string(DEBUGV, "Lowered mutable variable "); diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index c42d7a13d..9f21a4892 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -22,7 +22,7 @@ static const Node* force_to_be_value(Context* ctx, const Node* node) { if (is_instruction(node)) { const Node* let_bound; let_bound = process_node(ctx, node); - return first(bind_instruction_outputs_count(ctx->bb, let_bound, 1, NULL, false)); + return first(bind_instruction_outputs_count(ctx->bb, let_bound, 1, NULL)); } switch (node->tag) { From ac4be9e45603240e717b6ae2dc64e1b1117bf9dd Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Feb 2024 13:11:48 +0100 Subject: [PATCH 087/693] made LetMut into an instruction --- include/shady/grammar.json | 4 ++-- include/shady/ir.h | 2 +- src/shady/analysis/scope.c | 1 - src/shady/body_builder.c | 21 ++++++++++----------- src/shady/constructors.c | 4 ++-- src/shady/emit/c/emit_c.c | 1 - src/shady/emit/spirv/emit_spv.c | 1 - src/shady/node.c | 1 - src/shady/passes/bind.c | 16 ++++++---------- src/shady/passes/infer.c | 1 - src/shady/passes/opt_mem2reg.c | 1 - src/shady/passes/opt_restructure.c | 1 - src/shady/print.c | 16 +++++++++++----- 13 files changed, 32 insertions(+), 38 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index c56f65ee2..927ee980c 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -463,12 +463,12 @@ }, { "name": "LetMut", - "class": "terminator", + "class": "instruction", "constructor": "custom", "front-end-only": true, "ops": [ { "name": "instruction", "class": "instruction" }, - { "name": "tail", "class": "case" } + { "name": "variables", "class": "variable", "list": true } ] }, { diff --git a/include/shady/ir.h b/include/shady/ir.h index 24c35b78a..6aa58b640 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -217,7 +217,7 @@ const Node* prim_op_helper(IrArena*, Op, Nodes, Nodes); // terminators const Node* let(IrArena*, const Node* instruction, const Node* tail); -const Node* let_mut(IrArena*, const Node* instruction, const Node* tail); +const Node* let_mut(IrArena*, const Node* instruction, Nodes variables); const Node* jump_helper(IrArena* a, const Node* dst, Nodes args); // decl ctors diff --git a/src/shady/analysis/scope.c b/src/shady/analysis/scope.c index 3f1721f80..36f7ace6a 100644 --- a/src/shady/analysis/scope.c +++ b/src/shady/analysis/scope.c @@ -169,7 +169,6 @@ static void process_cf_node(ScopeBuildContext* ctx, CFNode* node) { if (!terminator) return; switch (is_terminator(terminator)) { - case LetMut_TAG: case Let_TAG: { const Node* target = get_let_tail(terminator); process_instruction(ctx, node, get_let_instruction(terminator), target); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 005de73fe..c57f40d18 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -12,7 +12,6 @@ typedef struct { const Node* instr; Nodes vars; - bool mut; } StackEntry; BodyBuilder* begin_body(IrArena* a) { @@ -62,7 +61,7 @@ static Nodes create_output_variables(IrArena* a, const Node* value, size_t outpu return nodes(a, outputs_count, (const Node**) vars); } -static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, bool mut, size_t outputs_count, const Node** provided_types, String const output_names[]) { +static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count, const Node** provided_types, String const output_names[]) { if (bb->arena->config.check_types) { assert(is_instruction(instruction)); } @@ -70,7 +69,6 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, bool mut, s StackEntry entry = { .instr = instruction, .vars = params, - .mut = mut, }; append_list(StackEntry, bb->stack, entry); return params; @@ -78,32 +76,33 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, bool mut, s Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { assert(bb->arena->config.check_types); - return bind_internal(bb, instruction, false, SIZE_MAX, NULL, NULL); + return bind_internal(bb, instruction, SIZE_MAX, NULL, NULL); } Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String const output_names[]) { assert(bb->arena->config.check_types); assert(output_names); - return bind_internal(bb, instruction, false, SIZE_MAX, NULL, output_names); + return bind_internal(bb, instruction, SIZE_MAX, NULL, output_names); } Nodes bind_instruction_explicit_result_types(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[]) { - return bind_internal(bb, instruction, false, provided_types.count, provided_types.nodes, output_names); + return bind_internal(bb, instruction, provided_types.count, provided_types.nodes, output_names); } Nodes create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[]) { - return bind_internal(bb, instruction, true, provided_types.count, provided_types.nodes, output_names); + Nodes mutable_vars = create_output_variables(bb->arena, instruction, provided_types.count, provided_types.nodes, output_names); + const Node* let_mut_instr = let_mut(bb->arena, instruction, mutable_vars); + return bind_internal(bb, let_mut_instr, 0, NULL, NULL); } Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count, String const output_names[]) { - return bind_internal(bb, instruction, false, outputs_count, NULL, output_names); + return bind_internal(bb, instruction, outputs_count, NULL, output_names); } void bind_variables(BodyBuilder* bb, Nodes vars, Nodes values) { StackEntry entry = { .instr = quote_helper(bb->arena, values), .vars = vars, - .mut = false, }; append_list(StackEntry, bb->stack, entry); } @@ -113,7 +112,7 @@ const Node* finish_body(BodyBuilder* bb, const Node* terminator) { for (size_t i = stack_size - 1; i < stack_size; i--) { StackEntry entry = read_list(StackEntry, bb->stack)[i]; const Node* lam = case_(bb->arena, entry.vars, terminator); - terminator = (entry.mut ? let_mut : let)(bb->arena, entry.instr, lam); + terminator = let(bb->arena, entry.instr, lam); } destroy_list(bb->stack); @@ -142,7 +141,7 @@ const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBu cancel_body(bb); return instruction; } - Nodes bound = bind_internal(bb, instruction, false, types ? types->count : SIZE_MAX, types ? types->nodes : NULL, NULL); + Nodes bound = bind_internal(bb, instruction, types ? types->count : SIZE_MAX, types ? types->nodes : NULL, NULL); return yield_values_and_wrap_in_block_explicit_return_types(bb, bound, types); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index e63ccf029..431b1192d 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -108,10 +108,10 @@ Node* var(IrArena* arena, const Type* type, const char* name) { return create_node_helper(arena, node, NULL); } -const Node* let_mut(IrArena* arena, const Node* instruction, const Node* tail) { +const Node* let_mut(IrArena* arena, const Node* instruction, Nodes variables) { LetMut payload = { .instruction = instruction, - .tail = tail, + .variables = variables, }; Node node; diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index ceaba3409..67b40aa33 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -353,7 +353,6 @@ void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const T static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { switch (is_terminator(terminator)) { case NotATerminator: assert(false); - case LetMut_TAG: case Join_TAG: error("this must be lowered away!"); case Jump_TAG: case Branch_TAG: diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 989741bdf..1dc7c53a3 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -223,7 +223,6 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); } - case LetMut_TAG: case TailCall_TAG: case Join_TAG: error("Lower me"); case Terminator_Yield_TAG: { diff --git a/src/shady/node.c b/src/shady/node.c index 18d2f7952..538fe1787 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -305,7 +305,6 @@ const Node* get_let_instruction(const Node* let) { const Node* get_let_tail(const Node* let) { switch (let->tag) { case Let_TAG: return let->payload.let.tail; - case LetMut_TAG: return let->payload.let_mut.tail; default: assert(false); } } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index d517edd28..61ea7be09 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -121,16 +121,12 @@ static const Node* get_node_address(Context* ctx, const Node* node) { static const Node* desugar_let_mut(Context* ctx, const Node* node) { assert(node->tag == LetMut_TAG); IrArena* a = ctx->rewriter.dst_arena; - Context body_infer_ctx = *ctx; - const Node* ninstruction = rewrite_node(&ctx->rewriter, node->payload.let.instruction); - - const Node* old_lam = node->payload.let.tail; - assert(old_lam && is_case(old_lam)); + const Node* ninstruction = rewrite_node(&ctx->rewriter, node->payload.let_mut.instruction); BodyBuilder* bb = begin_body(a); - Nodes initial_values = bind_instruction_outputs_count(bb, ninstruction, old_lam->payload.case_.params.count, NULL); - Nodes old_params = old_lam->payload.case_.params; + Nodes old_params = node->payload.let_mut.variables; + Nodes initial_values = bind_instruction_outputs_count(bb, ninstruction, old_params.count, NULL); for (size_t i = 0; i < old_params.count; i++) { const Node* oparam = old_params.nodes[i]; const Type* type_annotation = oparam->payload.var.type; @@ -147,14 +143,14 @@ static const Node* desugar_let_mut(Context* ctx, const Node* node) { }); bind_instruction_outputs_count(bb, store, 0, NULL); - add_binding(&body_infer_ctx, true, oparam->payload.var.name, ptr); + add_binding(ctx, true, oparam->payload.var.name, ptr); log_string(DEBUGV, "Lowered mutable variable "); log_node(DEBUGV, oparam); log_string(DEBUGV, ".\n;"); } - const Node* terminator = rewrite_node(&body_infer_ctx.rewriter, old_lam->payload.case_.body); - return finish_body(bb, terminator); + Nodes e = empty(a); + return yield_values_and_wrap_in_block_explicit_return_types(bb, empty(a), &e); } static const Node* rewrite_decl(Context* ctx, const Node* decl) { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 70b2f642f..02d88d277 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -731,7 +731,6 @@ static const Node* _infer_instruction(Context* ctx, const Node* node, const Type static const Node* _infer_terminator(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; switch (is_terminator(node)) { - case Terminator_LetMut_TAG: case NotATerminator: assert(false); case Let_TAG: { const Node* otail = node->payload.let.tail; diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 8b4686d05..8fd9e3203 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -393,7 +393,6 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (is_terminator(old)) { - case Terminator_LetMut_TAG: case NotATerminator: assert(false); case Let_TAG: { const Node* oinstruction = get_let_instruction(old); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 234ad79a7..2a35b65d4 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -168,7 +168,6 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad assert(body); switch (is_terminator(body)) { case NotATerminator: - case LetMut_TAG: assert(false); case Let_TAG: { const Node* old_tail = get_let_tail(body); Nodes otail_params = get_abstraction_params(old_tail); diff --git a/src/shady/print.c b/src/shady/print.c index bae07d6fa..fcf6beb0c 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -650,22 +650,28 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { TerminatorTag tag = is_terminator(node); switch (tag) { case NotATerminator: assert(false); - case Let_TAG: - case LetMut_TAG: { + case Let_TAG: { const Node* instruction = get_let_instruction(node); + bool mut = false; + if (instruction->tag == LetMut_TAG) + mut = true; const Node* tail = get_let_tail(node); if (!ctx->config.reparseable) { // if the let tail is a case, we apply some syntactic sugar - if (tail->payload.case_.params.count > 0) { + if (mut || tail->payload.case_.params.count > 0) { printf(GREEN); - if (tag == LetMut_TAG) + if (mut) printf("var"); else printf("val"); printf(RESET); Nodes params = tail->payload.case_.params; + if (mut) { + params = instruction->payload.let_mut.variables; + instruction = instruction->payload.let_mut.instruction; + } for (size_t i = 0; i < params.count; i++) { - if (tag == LetMut_TAG || !ctx->config.reparseable) { + if (mut || !ctx->config.reparseable) { printf(" "); print_node(params.nodes[i]->payload.var.type); } From 7793b6865c40cc94ec48cddd6ba79a0ff2a15c81 Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Sat, 27 Jan 2024 22:40:59 +0000 Subject: [PATCH 088/693] add .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..d16386367 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file From d1527f3cc18f8c8ff33e656fa947b4c426818fa7 Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Sat, 27 Jan 2024 22:41:24 +0000 Subject: [PATCH 089/693] various small cmake fixes --- src/frontends/slim/CMakeLists.txt | 4 ++-- src/shady/generator/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontends/slim/CMakeLists.txt b/src/frontends/slim/CMakeLists.txt index a9865e843..25dbad2c9 100644 --- a/src/frontends/slim/CMakeLists.txt +++ b/src/frontends/slim/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(slim_parser parser.c token.c) -target_link_libraries(slim_parser common api) +add_library(slim_parser STATIC parser.c token.c) +target_link_libraries(slim_parser PUBLIC common api) target_include_directories(slim_parser INTERFACE "$") set_property(TARGET slim_parser PROPERTY POSITION_INDEPENDENT_CODE ON) target_link_libraries(shady PUBLIC "$") diff --git a/src/shady/generator/CMakeLists.txt b/src/shady/generator/CMakeLists.txt index b01e1e0d3..f83df9bb7 100644 --- a/src/shady/generator/CMakeLists.txt +++ b/src/shady/generator/CMakeLists.txt @@ -1,6 +1,6 @@ find_package(json-c REQUIRED) -add_library(generator_common generator.c generator_common.c json_apply.c) +add_library(generator_common STATIC generator.c generator_common.c json_apply.c) target_link_libraries(generator_common PUBLIC common json-c::json-c) target_include_directories(generator_common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) From d8d8843c0d3cedf9265a3fbca3eec86e617669b2 Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Sat, 27 Jan 2024 22:42:05 +0000 Subject: [PATCH 090/693] FetchContent spirv-headers and json-c --- CMakeLists.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13bc5f743..77bd55652 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.13) project (shady C) +include(ExternalProject) +include(FetchContent) + set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) @@ -10,6 +13,18 @@ endif() add_subdirectory(SPIRV-Headers) +FetchContent_Declare( + json-c + GIT_REPOSITORY https://github.com/json-c/json-c + GIT_TAG master + OVERRIDE_FIND_PACKAGE +) + +FetchContent_MakeAvailable(json-c) +add_library(json-c::json-c ALIAS json-c) +configure_file(${json-c_SOURCE_DIR}/json.h.cmakein ${json-c_BINARY_DIR}/json-c/json.h @ONLY) +target_include_directories(json-c PUBLIC $) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) From 37d17891612d15906471b8d2ceb4584641afd93d Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Sat, 27 Jan 2024 22:42:51 +0000 Subject: [PATCH 091/693] discover installed LLVM on WIN32 --- CMakeLists.txt | 31 ++++++++++++++++++++++++++++++- src/frontends/CMakeLists.txt | 4 +--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 77bd55652..52e61b5c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.24) project (shady C) include(ExternalProject) @@ -25,6 +25,35 @@ add_library(json-c::json-c ALIAS json-c) configure_file(${json-c_SOURCE_DIR}/json.h.cmakein ${json-c_BINARY_DIR}/json-c/json.h @ONLY) target_include_directories(json-c PUBLIC $) +find_package(LLVM QUIET) +if(NOT ${LLVM_FOUND} AND WIN32) + find_program(clang_exe "clang.exe") + if(${clang_exe} STREQUAL "clang_exe-NOTFOUND") + message(STATUS "Win32: Installed LLVM not found") + else() + execute_process(COMMAND ${clang_exe} --version OUTPUT_VARIABLE clang_status) + string(REGEX MATCH "InstalledDir: (.*)[\r\n]" match ${clang_status}) + file(TO_CMAKE_PATH "${CMAKE_MATCH_1}/../" LLVM_DIR) + cmake_path(ABSOLUTE_PATH LLVM_DIR NORMALIZE) + string(REGEX MATCH "clang version ([0-9]+).([0-9]+).([0-9]+)" match2 ${clang_status}) + set(LLVM_VERSION_MAJOR ${CMAKE_MATCH_1}) + set(LLVM_VERSION_MINOR ${CMAKE_MATCH_2}) + set(LLVM_VERSION_PATCH ${CMAKE_MATCH_3}) + set(LLVM_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") + add_library(LLVM-C SHARED IMPORTED) + set_property(TARGET LLVM-C PROPERTY + IMPORTED_LOCATION "${LLVM_DIR}bin/LLVM-C.dll") + set_property(TARGET LLVM-C PROPERTY + IMPORTED_IMPLIB "${LLVM_DIR}lib/LLVM-C.lib") + target_include_directories(LLVM-C INTERFACE "vendor") + target_compile_definitions(LLVM-C INTERFACE -DLLVM_VERSION_MAJOR=${LLVM_VERSION_MAJOR} -DLLVM_VERSION_MINOR=${LLVM_VERSION_MINOR} -DLLVM_VERSION_PATCH=${LLVM_VERSION_PATCH}) + message(STATUS "Win32: Installed LLVM ${LLVM_VERSION} found at ${LLVM_DIR}") + set(LLVM_FOUND TRUE) + endif() +else() + message("LLVM ${LLVM_VERSION} found") +endif() + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) diff --git a/src/frontends/CMakeLists.txt b/src/frontends/CMakeLists.txt index 509f90bcd..21e8a6ffd 100644 --- a/src/frontends/CMakeLists.txt +++ b/src/frontends/CMakeLists.txt @@ -1,8 +1,6 @@ add_subdirectory(slim) add_subdirectory(spirv) -find_package(LLVM) if(LLVM_FOUND) - message("LLVM ${LLVM_VERSION} found") add_subdirectory(llvm) -endif () +endif() From 105c6fb95e9d32e01f0ad9128e7eb60f98f57df0 Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Sat, 27 Jan 2024 22:55:00 +0000 Subject: [PATCH 092/693] CI for Windows --- .github/workflows/cmake-multi-platform.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 730ab5b20..ac4127f4e 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -65,7 +65,6 @@ jobs: # cmake --install SPIRV-Headers/build --prefix SPIRV-Headers/install - name: Install Clang & LLVM (setup-clang) - if: (!startsWith(matrix.os,'windows')) uses: egor-tensin/setup-clang@v1.4 #- name: Install LLVM (winlibs) @@ -89,12 +88,6 @@ jobs: run: | echo "CMAKE_PLATFORM_SPECIFIC_ARGS=${{ env.CMAKE_PLATFORM_SPECIFIC_ARGS }} -DLLVM_DIR=/usr/lib/llvm-14/cmake" >> $GITHUB_ENV - - name: Install json-c (vcpkg) - if: startsWith(matrix.os,'windows') - run: | - vcpkg install json-c - echo "CMAKE_PLATFORM_SPECIFIC_ARGS=-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" >> "$env:GITHUB_ENV" - - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type From 2f61f781d0208ef8c362a194ccc9e073c57b46fb Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Tue, 30 Jan 2024 22:39:25 +0000 Subject: [PATCH 093/693] additional build changes needed to build as a lib --- src/frontends/slim/CMakeLists.txt | 1 + src/shady/CMakeLists.txt | 1 + src/shady/emit/c/CMakeLists.txt | 1 + src/shady/emit/spirv/CMakeLists.txt | 1 + src/shady/generator/CMakeLists.txt | 4 +++- 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/frontends/slim/CMakeLists.txt b/src/frontends/slim/CMakeLists.txt index 25dbad2c9..df7c30cb0 100644 --- a/src/frontends/slim/CMakeLists.txt +++ b/src/frontends/slim/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(slim_parser STATIC parser.c token.c) target_link_libraries(slim_parser PUBLIC common api) +target_include_directories(slim_parser PUBLIC $) target_include_directories(slim_parser INTERFACE "$") set_property(TARGET slim_parser PROPERTY POSITION_INDEPENDENT_CODE ON) target_link_libraries(shady PUBLIC "$") diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 312bc527a..25e60b7b9 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -96,6 +96,7 @@ set(SHADY_SOURCES ) add_library(shady STATIC ${SHADY_SOURCES}) +target_include_directories(shady PUBLIC $) set_property(TARGET shady PROPERTY POSITION_INDEPENDENT_CODE ON) if (WIN32) diff --git a/src/shady/emit/c/CMakeLists.txt b/src/shady/emit/c/CMakeLists.txt index 21dd62a62..b39d1a1c8 100644 --- a/src/shady/emit/c/CMakeLists.txt +++ b/src/shady/emit/c/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(shady_c OBJECT ) set_property(TARGET shady_c PROPERTY POSITION_INDEPENDENT_CODE ON) +target_include_directories(shady_c PUBLIC $) target_link_libraries(shady_c PUBLIC "api") target_link_libraries(shady_c PRIVATE "$") target_link_libraries(shady_c PUBLIC "$") diff --git a/src/shady/emit/spirv/CMakeLists.txt b/src/shady/emit/spirv/CMakeLists.txt index 97f6d1ace..7dd2894b6 100644 --- a/src/shady/emit/spirv/CMakeLists.txt +++ b/src/shady/emit/spirv/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(shady_spirv OBJECT ) set_property(TARGET shady_spirv PROPERTY POSITION_INDEPENDENT_CODE ON) +target_include_directories(shady_spirv PUBLIC $) target_link_libraries(shady_spirv PUBLIC "api") target_link_libraries(shady_spirv PRIVATE "$") target_link_libraries(shady_spirv PRIVATE "$") diff --git a/src/shady/generator/CMakeLists.txt b/src/shady/generator/CMakeLists.txt index f83df9bb7..f5c1c0259 100644 --- a/src/shady/generator/CMakeLists.txt +++ b/src/shady/generator/CMakeLists.txt @@ -29,10 +29,12 @@ function(add_generated_file) add_executable(${GENERATOR_NAME} ${F_SOURCES} ${CMAKE_SOURCE_DIR}/src/shady/generator/generator_main.c) target_link_libraries(${GENERATOR_NAME} generator_common) + get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} COMMAND ${GENERATOR_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} ${PROJECT_SOURCE_DIR}/include/shady/grammar.json ${PROJECT_SOURCE_DIR}/include/shady/primops.json ${SPIRV_HEADERS_INCLUDE_DIRS} DEPENDS ${GENERATOR_NAME} ${PROJECT_SOURCE_DIR}/include/shady/grammar.json ${PROJECT_SOURCE_DIR}/include/shady/primops.json VERBATIM) if ("${F_TARGET_NAME}" STREQUAL "") set(F_TARGET_NAME generate_${F_FILE_NAME}) endif () - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} COMMAND ${GENERATOR_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} "${SHADY_IMPORTED_JSON_PATH}" ${CMAKE_SOURCE_DIR}/include/shady/grammar.json ${CMAKE_SOURCE_DIR}/include/shady/primops.json DEPENDS do_import_spv_defs ${GENERATOR_NAME} ${CMAKE_SOURCE_DIR}/include/shady/grammar.json ${CMAKE_SOURCE_DIR}/include/shady/primops.json VERBATIM) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} COMMAND ${GENERATOR_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} "${SHADY_IMPORTED_JSON_PATH}" ${PROJECT_SOURCE_DIR}/include/shady/grammar.json ${PROJECT_SOURCE_DIR}/include/shady/primops.json DEPENDS do_import_spv_defs ${GENERATOR_NAME} ${PROJECT_SOURCE_DIR}/include/shady/grammar.json ${PROJECT_SOURCE_DIR}/include/shady/primops.json VERBATIM) add_custom_target(${F_TARGET_NAME} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME}) endfunction() From 766194599cdfb1a09036ceefe0d2246d569a05f7 Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Thu, 1 Feb 2024 21:42:32 +0000 Subject: [PATCH 094/693] fix merge --- src/shady/generator/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shady/generator/CMakeLists.txt b/src/shady/generator/CMakeLists.txt index f5c1c0259..d5f3f77c5 100644 --- a/src/shady/generator/CMakeLists.txt +++ b/src/shady/generator/CMakeLists.txt @@ -18,7 +18,7 @@ if (WIN32) endif () get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/imported.json COMMAND import_spv_defs ${CMAKE_CURRENT_BINARY_DIR}/imported.json ${CMAKE_SOURCE_DIR}/include/shady/spv_imports.json ${SPIRV_HEADERS_INCLUDE_DIRS} DEPENDS import_spv_defs SPIRV-Headers::SPIRV-Headers ${CMAKE_SOURCE_DIR}/include/shady/spv_imports.json VERBATIM) +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/imported.json COMMAND import_spv_defs ${CMAKE_CURRENT_BINARY_DIR}/imported.json ${PROJECT_SOURCE_DIR}/include/shady/spv_imports.json ${SPIRV_HEADERS_INCLUDE_DIRS} DEPENDS import_spv_defs SPIRV-Headers::SPIRV-Headers ${PROJECT_SOURCE_DIR}/include/shady/spv_imports.json VERBATIM) add_custom_target(do_import_spv_defs DEPENDS import_spv_defs ${CMAKE_CURRENT_BINARY_DIR}/imported.json) set(SHADY_IMPORTED_JSON_PATH ${CMAKE_CURRENT_BINARY_DIR}/imported.json CACHE INTERNAL "path to imported.json") @@ -26,11 +26,11 @@ set(SHADY_IMPORTED_JSON_PATH ${CMAKE_CURRENT_BINARY_DIR}/imported.json CACHE INT function(add_generated_file) cmake_parse_arguments(PARSE_ARGV 0 F "" "FILE_NAME;TARGET_NAME" "SOURCES" ) set(GENERATOR_NAME generator_${F_FILE_NAME}) - add_executable(${GENERATOR_NAME} ${F_SOURCES} ${CMAKE_SOURCE_DIR}/src/shady/generator/generator_main.c) + add_executable(${GENERATOR_NAME} ${F_SOURCES} ${PROJECT_SOURCE_DIR}/src/shady/generator/generator_main.c) target_link_libraries(${GENERATOR_NAME} generator_common) get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} COMMAND ${GENERATOR_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${F_FILE_NAME} ${PROJECT_SOURCE_DIR}/include/shady/grammar.json ${PROJECT_SOURCE_DIR}/include/shady/primops.json ${SPIRV_HEADERS_INCLUDE_DIRS} DEPENDS ${GENERATOR_NAME} ${PROJECT_SOURCE_DIR}/include/shady/grammar.json ${PROJECT_SOURCE_DIR}/include/shady/primops.json VERBATIM) + if ("${F_TARGET_NAME}" STREQUAL "") set(F_TARGET_NAME generate_${F_FILE_NAME}) endif () From abfd8faea778db48317b2f37284637167ac5bfcb Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Sat, 24 Feb 2024 21:29:28 +0000 Subject: [PATCH 095/693] get llvm-c headers via git --- CMakeLists.txt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52e61b5c3..2efc0126c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,8 @@ project (shady C) include(ExternalProject) include(FetchContent) +find_package(Git) + set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) @@ -45,7 +47,20 @@ if(NOT ${LLVM_FOUND} AND WIN32) IMPORTED_LOCATION "${LLVM_DIR}bin/LLVM-C.dll") set_property(TARGET LLVM-C PROPERTY IMPORTED_IMPLIB "${LLVM_DIR}lib/LLVM-C.lib") - target_include_directories(LLVM-C INTERFACE "vendor") + + execute_process( + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${GIT_EXECUTABLE} clone -n --depth 1 --filter=tree:0 https://github.com/llvm/llvm-project/ --branch "llvmorg-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}" + ) + execute_process( + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/llvm-project + COMMAND ${GIT_EXECUTABLE} sparse-checkout set --no-cone llvm/include/llvm-c + ) + execute_process( + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/llvm-project + COMMAND ${GIT_EXECUTABLE} checkout + ) + target_include_directories(LLVM-C INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/llvm-project/llvm/include) target_compile_definitions(LLVM-C INTERFACE -DLLVM_VERSION_MAJOR=${LLVM_VERSION_MAJOR} -DLLVM_VERSION_MINOR=${LLVM_VERSION_MINOR} -DLLVM_VERSION_PATCH=${LLVM_VERSION_PATCH}) message(STATUS "Win32: Installed LLVM ${LLVM_VERSION} found at ${LLVM_DIR}") set(LLVM_FOUND TRUE) From bdd90264579c6a3e3c54d72d424c9bb08622086a Mon Sep 17 00:00:00 2001 From: Marcell Kiss Date: Sun, 25 Feb 2024 00:13:46 +0000 Subject: [PATCH 096/693] support for building as shared lib --- include/shady/ir.h | 2 ++ src/driver/CMakeLists.txt | 4 ++-- src/shady/CMakeLists.txt | 2 +- src/shady/emit/CMakeLists.txt | 4 ++++ src/shady/emit/common.c | 5 +++++ 5 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 src/shady/emit/common.c diff --git a/include/shady/ir.h b/include/shady/ir.h index 6760644a0..9beaebc4c 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -342,4 +342,6 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig emitter_config, Modul void dump_cfg(FILE* file, Module*); void dump_loop_trees(FILE* output, Module* mod); +void free_output(char* output); + #endif diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index 50a495a9e..5691df311 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(driver STATIC driver.c cli.c) -target_link_libraries(driver PUBLIC "$") +add_library(driver driver.c cli.c) +target_link_libraries(driver PUBLIC "$" shady_spirv shady_c shady_emit_common) set_property(TARGET driver PROPERTY POSITION_INDEPENDENT_CODE ON) add_executable(slim slim.c) diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 25e60b7b9..e0e2da410 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -95,7 +95,7 @@ set(SHADY_SOURCES passes/spirv_lift_globals_ssbo.c ) -add_library(shady STATIC ${SHADY_SOURCES}) +add_library(shady OBJECT ${SHADY_SOURCES}) target_include_directories(shady PUBLIC $) set_property(TARGET shady PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/shady/emit/CMakeLists.txt b/src/shady/emit/CMakeLists.txt index 66d85f8e0..82efbf5d6 100644 --- a/src/shady/emit/CMakeLists.txt +++ b/src/shady/emit/CMakeLists.txt @@ -1,5 +1,9 @@ add_subdirectory(spirv) add_subdirectory(c) +add_library(shady_emit_common OBJECT + common.c +) + target_link_libraries(shady PRIVATE "$") target_link_libraries(shady PRIVATE "$") diff --git a/src/shady/emit/common.c b/src/shady/emit/common.c new file mode 100644 index 000000000..2970f51ac --- /dev/null +++ b/src/shady/emit/common.c @@ -0,0 +1,5 @@ +#include + +void free_output(char* output) { + free(output); +} \ No newline at end of file From c84d7439d4d6fc34e8806ce7e6876a7be9816120 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 13 Mar 2024 10:17:05 +0100 Subject: [PATCH 097/693] fix memory leak in generator_main.c --- src/shady/generator/generator_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/generator/generator_main.c b/src/shady/generator/generator_main.c index 3c6dbd3b9..de9dba0d3 100644 --- a/src/shady/generator/generator_main.c +++ b/src/shady/generator/generator_main.c @@ -58,7 +58,7 @@ int main(int argc, char** argv) { error_die(); } free(generated); - for (size_t i = 0; i < sizeof(json_files) / sizeof(json_files[0]); i++) { + for (size_t i = 0; i < inputs_count; i++) { free(json_files[i].contents); json_object_put(json_files[i].root); } From 1f2825d0dee6576f1f6aadaf141a1e10dfc7a7d3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 09:56:47 +0100 Subject: [PATCH 098/693] gate the fetchcontent code behind 3.24 version check --- CMakeLists.txt | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2efc0126c..5c26181e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.13) project (shady C) include(ExternalProject) @@ -15,17 +15,21 @@ endif() add_subdirectory(SPIRV-Headers) -FetchContent_Declare( - json-c - GIT_REPOSITORY https://github.com/json-c/json-c - GIT_TAG master - OVERRIDE_FIND_PACKAGE -) - -FetchContent_MakeAvailable(json-c) -add_library(json-c::json-c ALIAS json-c) -configure_file(${json-c_SOURCE_DIR}/json.h.cmakein ${json-c_BINARY_DIR}/json-c/json.h @ONLY) -target_include_directories(json-c PUBLIC $) +if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24") + FetchContent_Declare( + json-c + GIT_REPOSITORY https://github.com/json-c/json-c + GIT_TAG master + OVERRIDE_FIND_PACKAGE + ) + + FetchContent_MakeAvailable(json-c) + add_library(json-c::json-c ALIAS json-c) + configure_file(${json-c_SOURCE_DIR}/json.h.cmakein ${json-c_BINARY_DIR}/json-c/json.h @ONLY) + target_include_directories(json-c PUBLIC $) +else () + message("CMake 3.24 or later is required to use FetchContent") +endif () find_package(LLVM QUIET) if(NOT ${LLVM_FOUND} AND WIN32) From 40e5a21af899456beb203182274218701d3a6d02 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 13 Mar 2024 15:13:24 +0100 Subject: [PATCH 099/693] added CUDA backend stub --- src/runtime/CMakeLists.txt | 1 + src/runtime/cuda/CMakeLists.txt | 14 ++++++++++++++ src/runtime/cuda/cuda_runtime.c | 25 +++++++++++++++++++++++++ src/runtime/cuda/cuda_runtime_private.h | 12 ++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 src/runtime/cuda/CMakeLists.txt create mode 100644 src/runtime/cuda/cuda_runtime.c create mode 100644 src/runtime/cuda/cuda_runtime_private.h diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index c03ac06a9..0f1a4ab39 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -5,6 +5,7 @@ set_property(TARGET runtime PROPERTY POSITION_INDEPENDENT_CODE ON) set_target_properties(runtime PROPERTIES OUTPUT_NAME "shady_runtime") add_subdirectory(vulkan) +add_subdirectory(cuda) add_executable(runtime_test runtime_test.c) target_link_libraries(runtime_test runtime) diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt new file mode 100644 index 000000000..bf554122d --- /dev/null +++ b/src/runtime/cuda/CMakeLists.txt @@ -0,0 +1,14 @@ +find_package(CUDA) + +if (CUDA_FOUND) + message("Cuda found.") + add_library(cuda_runtime STATIC cuda_runtime.c) + target_link_libraries(cuda_runtime PUBLIC api) + target_link_libraries(cuda_runtime PUBLIC shady) + target_link_libraries(cuda_runtime PRIVATE "$") + target_link_libraries(cuda_runtime PRIVATE "$") + target_link_libraries(cuda_runtime PRIVATE CUDA_LIBRARIES) + set_property(TARGET cuda_runtime PROPERTY POSITION_INDEPENDENT_CODE ON) + target_link_libraries(runtime PRIVATE cuda_runtime) + target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) +endif () \ No newline at end of file diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c new file mode 100644 index 000000000..5b3d0ca87 --- /dev/null +++ b/src/runtime/cuda/cuda_runtime.c @@ -0,0 +1,25 @@ +#include "cuda_runtime_private.h" + +#include "log.h" +#include "portability.h" + +#include + +Backend* initialize_cuda_backend(Runtime* base) { + CudaBackend* backend = malloc(sizeof(CudaBackend)); + memset(backend, 0, sizeof(CudaBackend)); + backend->base = (Backend) { + .runtime = base, + // .cleanup = (void(*)()) shutdown_vulkan_runtime, + }; + + // CHECK(initialize_vk_instance(backend), goto init_fail_free) + // probe_vkr_devices(backend); + info_print("Shady CUDA backend successfully initialized !\n"); + return &backend->base; + + init_fail_free: + error_print("Failed to initialise the CUDA back-end.\n"); + free(backend); + return NULL; +} \ No newline at end of file diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h new file mode 100644 index 000000000..02daa9d33 --- /dev/null +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -0,0 +1,12 @@ +#ifndef SHADY_CUDA_RUNTIME_PRIVATE_H +#define SHADY_CUDA_RUNTIME_PRIVATE_H + +#include "../runtime_private.h" + +#include + +typedef struct CudaBackend_ { + Backend base; +} CudaBackend; + +#endif From 3bda065617ef789153a392a260195e2eb2bd2cfa Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 13:07:31 +0100 Subject: [PATCH 100/693] runtime/cuda: implement buffers --- include/shady/runtime.h | 2 +- src/runtime/cuda/CMakeLists.txt | 2 +- src/runtime/cuda/cuda_runtime.c | 51 +++++++++++++++++++-- src/runtime/cuda/cuda_runtime_buffer.c | 61 +++++++++++++++++++++++++ src/runtime/cuda/cuda_runtime_private.h | 25 +++++++++- src/runtime/runtime_private.h | 13 ++++-- src/runtime/vulkan/vk_runtime_buffer.c | 5 ++ 7 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 src/runtime/cuda/cuda_runtime_buffer.c diff --git a/include/shady/runtime.h b/include/shady/runtime.h index 0604dc39e..4064f5712 100644 --- a/include/shady/runtime.h +++ b/include/shady/runtime.h @@ -14,7 +14,7 @@ typedef struct { typedef struct Runtime_ Runtime; typedef struct Device_ Device; typedef struct Program_ Program; -typedef struct Command_ Command; +typedef struct Command_ Command; typedef struct Buffer_ Buffer; Runtime* initialize_runtime(RuntimeConfig config); diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index bf554122d..d50c1832c 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -2,7 +2,7 @@ find_package(CUDA) if (CUDA_FOUND) message("Cuda found.") - add_library(cuda_runtime STATIC cuda_runtime.c) + add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c) target_link_libraries(cuda_runtime PUBLIC api) target_link_libraries(cuda_runtime PUBLIC shady) target_link_libraries(cuda_runtime PRIVATE "$") diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 5b3d0ca87..7c4a6d4f8 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -2,19 +2,64 @@ #include "log.h" #include "portability.h" +#include "list.h" #include +static void shutdown_cuda_runtime(CudaBackend* b) { + +} + +static const char* cuda_device_get_name(CudaDevice* device) { return device->name; } + +static void cuda_device_cleanup(CudaDevice* device) { + +} + +static CudaDevice* create_cuda_device(CudaBackend* b, int ordinal) { + CUdevice handle; + CHECK_CUDA(cuDeviceGet(&handle, ordinal), return NULL); + CudaDevice* device = calloc(sizeof(CudaDevice), 1); + *device = (CudaDevice) { + .base = { + .get_name = (const char*(*)(Device*)) cuda_device_get_name, + .cleanup = (void(*)(Device*)) cuda_device_cleanup, + .allocate_buffer = (Buffer* (*)(Device*, size_t)) shd_cuda_allocate_buffer, + .can_import_host_memory = (bool (*)(Device*)) shd_cuda_can_import_host_memory, + .import_host_memory_as_buffer = (Buffer* (*)(Device*, void*, size_t)) shd_cuda_import_host_memory, + }, + .handle = handle, + }; + CHECK_CUDA(cuDeviceGetName(device->name, 255, handle), goto dealloc_and_return_null); + return device; + + dealloc_and_return_null: + free(device); + return NULL; +} + +static bool probe_cuda_devices(CudaBackend* b) { + int count; + CHECK_CUDA(cuDeviceGetCount(&count), return false); + for (size_t i = 0; i < count; i++) { + CudaDevice* device = create_cuda_device(b, i); + if (!device) + continue; + append_list(CudaDevice*, b->base.runtime->devices, device); + } + return true; +} + Backend* initialize_cuda_backend(Runtime* base) { CudaBackend* backend = malloc(sizeof(CudaBackend)); memset(backend, 0, sizeof(CudaBackend)); backend->base = (Backend) { .runtime = base, - // .cleanup = (void(*)()) shutdown_vulkan_runtime, + .cleanup = (void(*)()) shutdown_cuda_runtime, }; - // CHECK(initialize_vk_instance(backend), goto init_fail_free) - // probe_vkr_devices(backend); + CHECK_CUDA(cuInit(0), goto init_fail_free); + CHECK(probe_cuda_devices(backend), goto init_fail_free); info_print("Shady CUDA backend successfully initialized !\n"); return &backend->base; diff --git a/src/runtime/cuda/cuda_runtime_buffer.c b/src/runtime/cuda/cuda_runtime_buffer.c new file mode 100644 index 000000000..45e415ccd --- /dev/null +++ b/src/runtime/cuda/cuda_runtime_buffer.c @@ -0,0 +1,61 @@ +#include "cuda_runtime_private.h" + +#include "log.h" +#include "portability.h" + +static void cuda_destroy_buffer(CudaBuffer* buffer) { + if (buffer->is_allocated) + CHECK_CUDA(cuMemFree(buffer->device_ptr), {}); + if (buffer->is_imported) + CHECK_CUDA(cuMemHostUnregister(buffer->host_ptr), {}); + free(buffer); +} + +static uint64_t cuda_get_deviceptr(CudaBuffer* buffer) { + return (uint64_t) buffer->device_ptr; +} + +static void* cuda_get_host_ptr(CudaBuffer* buffer) { + return (void*) buffer->host_ptr; +} + +static CudaBuffer* new_buffer_common(size_t size) { + CudaBuffer* buffer = calloc(sizeof(CudaBuffer), 1); + *buffer = (CudaBuffer) { + .base = { + .backend_tag = CUDARuntimeBackend, + .get_host_ptr = (void*(*)(Buffer*)) cuda_get_host_ptr, + .get_device_ptr = (uint64_t(*)(Buffer*)) cuda_get_deviceptr, + .destroy = (void(*)(Buffer*)) cuda_destroy_buffer, + }, + .size = size, + }; + return buffer; +} + +CudaBuffer* shd_cuda_allocate_buffer(CudaDevice* device, size_t size) { + CUdeviceptr device_ptr; + CHECK_CUDA(cuMemAlloc(&device_ptr, size), return NULL); + CudaBuffer* buffer = new_buffer_common(size); + buffer->is_allocated = true; + buffer->device_ptr = device_ptr; + // TODO: check the assumptions of unified virtual addressing + buffer->host_ptr = (void*) device_ptr; + return buffer; +} + +CudaBuffer* shd_cuda_import_host_memory(CudaDevice* device, void* host_ptr, size_t size) { + CUdeviceptr device_ptr; + CHECK_CUDA(cuMemHostRegister(host_ptr, size, CU_MEMHOSTREGISTER_DEVICEMAP), return NULL); + CHECK_CUDA(cuMemHostGetDevicePointer(&device_ptr, host_ptr, 0), return NULL); + CudaBuffer* buffer = new_buffer_common(size); + buffer->is_imported = true; + buffer->device_ptr = device_ptr; + // TODO: check the assumptions of unified virtual addressing + buffer->host_ptr = (void*) host_ptr; + return buffer; +} + +bool shd_cuda_can_import_host_memory(CudaDevice* d) { + return true; +} diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index 02daa9d33..80f2f1030 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -3,10 +3,33 @@ #include "../runtime_private.h" -#include +#include +#include + +#define CHECK_NVRTC(x, failure_handler) { CUresult the_result_ = x; if (the_result_ != NVRTC_SUCCESS) { const char* msg; nvrtcGetErrorString(the_result_, &msg); error_print(#x " failed (%s)\n", msg); failure_handler; } } +#define CHECK_CUDA(x, failure_handler) { CUresult the_result_ = x; if (the_result_ != CUDA_SUCCESS) { const char* msg; cuGetErrorName(the_result_, &msg); error_print(#x " failed (%s)\n", msg); failure_handler; } } typedef struct CudaBackend_ { Backend base; } CudaBackend; +typedef struct { + Device base; + CUdevice handle; + char name[256]; +} CudaDevice; + +typedef struct { + Buffer base; + size_t size; + CUdeviceptr device_ptr; + void* host_ptr; + bool is_allocated; + bool is_imported; +} CudaBuffer; + +CudaBuffer* shd_cuda_allocate_buffer(CudaDevice*, size_t size); +CudaBuffer* shd_cuda_import_host_memory(CudaDevice*, void* host_ptr, size_t size); +bool shd_cuda_can_import_host_memory(CudaDevice*); + #endif diff --git a/src/runtime/runtime_private.h b/src/runtime/runtime_private.h index aef273ffe..b74efca95 100644 --- a/src/runtime/runtime_private.h +++ b/src/runtime/runtime_private.h @@ -15,6 +15,11 @@ struct Runtime_ { struct List* programs; }; +typedef enum { + VulkanRuntimeBackend, + CUDARuntimeBackend, +} ShdRuntimeBackend; + typedef struct Backend_ Backend; struct Backend_ { Runtime* runtime; @@ -44,12 +49,12 @@ struct Command_ { }; struct Buffer_ { - void (*destroy)(Buffer*); + ShdRuntimeBackend backend_tag; + void (*destroy)(Buffer*); void* (*get_host_ptr)(Buffer*); uint64_t (*get_device_ptr)(Buffer*); - - bool (*copy_into)(Buffer* dst, size_t buffer_offset, void* src, size_t bytes); - bool (*copy_from)(Buffer* src, size_t buffer_offset, void* dst, size_t bytes); + bool (*copy_into)(Buffer* dst, size_t buffer_offset, void* src, size_t bytes); + bool (*copy_from)(Buffer* src, size_t buffer_offset, void* dst, size_t bytes); }; void unload_program(Program*); diff --git a/src/runtime/vulkan/vk_runtime_buffer.c b/src/runtime/vulkan/vk_runtime_buffer.c index fd78b1f50..67f8ac644 100644 --- a/src/runtime/vulkan/vk_runtime_buffer.c +++ b/src/runtime/vulkan/vk_runtime_buffer.c @@ -253,6 +253,7 @@ static VkrCommand* submit_buffer_copy(VkrDevice* device, VkBuffer src, size_t sr } static bool vkr_copy_to_buffer_fallback(VkrBuffer* dst, size_t buffer_offset, void* src, size_t size) { + CHECK(dst->base.backend_tag == VulkanRuntimeBackend, return false); VkrDevice* device = dst->device; VkrBuffer* src_buf = vkr_allocate_buffer_device_(device, size, AllocHostVisible); @@ -276,6 +277,7 @@ static bool vkr_copy_to_buffer_fallback(VkrBuffer* dst, size_t buffer_offset, vo } static bool vkr_copy_from_buffer_fallback(VkrBuffer* src, size_t buffer_offset, void* dst, size_t size) { + CHECK(src->base.backend_tag == VulkanRuntimeBackend, return false); VkrDevice* device = src->device; VkrBuffer* dst_buf = vkr_allocate_buffer_device_(device, size, AllocHostVisible); @@ -299,6 +301,7 @@ static bool vkr_copy_from_buffer_fallback(VkrBuffer* src, size_t buffer_offset, } static bool vkr_copy_to_buffer_importing(VkrBuffer* dst, size_t buffer_offset, void* src, size_t size) { + CHECK(dst->base.backend_tag == VulkanRuntimeBackend, return false); VkrDevice* device = dst->device; VkrBuffer* src_buf = vkr_import_buffer_host(device, src, size); @@ -317,6 +320,7 @@ static bool vkr_copy_to_buffer_importing(VkrBuffer* dst, size_t buffer_offset, v } static bool vkr_copy_from_buffer_importing(VkrBuffer* src, size_t buffer_offset, void* dst, size_t size) { + CHECK(src->base.backend_tag == VulkanRuntimeBackend, return false); VkrDevice* device = src->device; VkrBuffer* dst_buf = vkr_import_buffer_host(device, dst, size); @@ -336,6 +340,7 @@ static bool vkr_copy_from_buffer_importing(VkrBuffer* src, size_t buffer_offset, static Buffer make_base_buffer(VkrDevice* device) { Buffer buffer = { + .backend_tag = VulkanRuntimeBackend, .destroy = (void(*)(Buffer*)) vkr_destroy_buffer, .get_device_ptr = (uint64_t(*)(Buffer*)) vkr_get_buffer_device_pointer, .get_host_ptr = (void*(*)(Buffer*)) vkr_get_buffer_host_pointer, From 441a18fd2ef0e8942f275f5c73bb7dca498b5af5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 13:51:08 +0100 Subject: [PATCH 101/693] runtime/cuda: draft out shady->cuda c->nvrtc->ptx pipeline --- src/runtime/cuda/CMakeLists.txt | 2 +- src/runtime/cuda/cuda_runtime.c | 20 ++++++ src/runtime/cuda/cuda_runtime_private.h | 31 ++++++++- src/runtime/cuda/cuda_runtime_program.c | 86 +++++++++++++++++++++++++ src/runtime/vulkan/vk_runtime_device.c | 4 +- src/runtime/vulkan/vk_runtime_program.c | 6 +- 6 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 src/runtime/cuda/cuda_runtime_program.c diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index d50c1832c..bd9a3169d 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -2,7 +2,7 @@ find_package(CUDA) if (CUDA_FOUND) message("Cuda found.") - add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c) + add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c cuda_runtime_program.c) target_link_libraries(cuda_runtime PUBLIC api) target_link_libraries(cuda_runtime PUBLIC shady) target_link_libraries(cuda_runtime PRIVATE "$") diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 7c4a6d4f8..0cfa1f19b 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -3,6 +3,7 @@ #include "log.h" #include "portability.h" #include "list.h" +#include "dict.h" #include @@ -13,7 +14,24 @@ static void shutdown_cuda_runtime(CudaBackend* b) { static const char* cuda_device_get_name(CudaDevice* device) { return device->name; } static void cuda_device_cleanup(CudaDevice* device) { + size_t i = 0; + CudaKernel* kernel; + while (dict_iter(device->specialized_programs, &i, NULL, &kernel)) { + shd_cuda_destroy_specialized_kernel(kernel); + } + destroy_dict(device->specialized_programs); +} + +CudaCommand shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args) { + CudaKernel* kernel = shd_cuda_get_specialized_program(device, p, entry_point); +} + +static KeyHash hash_spec_program_key(SpecProgramKey* ptr) { + return hash_murmur(ptr, sizeof(SpecProgramKey)); +} +static bool cmp_spec_program_keys(SpecProgramKey* a, SpecProgramKey* b) { + return memcmp(a, b, sizeof(SpecProgramKey)) == 0; } static CudaDevice* create_cuda_device(CudaBackend* b, int ordinal) { @@ -27,8 +45,10 @@ static CudaDevice* create_cuda_device(CudaBackend* b, int ordinal) { .allocate_buffer = (Buffer* (*)(Device*, size_t)) shd_cuda_allocate_buffer, .can_import_host_memory = (bool (*)(Device*)) shd_cuda_can_import_host_memory, .import_host_memory_as_buffer = (Buffer* (*)(Device*, void*, size_t)) shd_cuda_import_host_memory, + .launch_kernel = (Command*(*)(Device*, Program*, String, int, int, int, int, void**)) shd_cuda_launch_kernel, }, .handle = handle, + .specialized_programs = new_dict(SpecProgramKey, CudaKernel*, (HashFn) hash_spec_program_key, (CmpFn) cmp_spec_program_keys), }; CHECK_CUDA(cuDeviceGetName(device->name, 255, handle), goto dealloc_and_return_null); return device; diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index 80f2f1030..2a103609a 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -6,9 +6,14 @@ #include #include -#define CHECK_NVRTC(x, failure_handler) { CUresult the_result_ = x; if (the_result_ != NVRTC_SUCCESS) { const char* msg; nvrtcGetErrorString(the_result_, &msg); error_print(#x " failed (%s)\n", msg); failure_handler; } } +#define CHECK_NVRTC(x, failure_handler) { nvrtcResult the_result_ = x; if (the_result_ != NVRTC_SUCCESS) { const char* msg = nvrtcGetErrorString(the_result_); error_print(#x " failed (%s)\n", msg); failure_handler; } } #define CHECK_CUDA(x, failure_handler) { CUresult the_result_ = x; if (the_result_ != CUDA_SUCCESS) { const char* msg; cuGetErrorName(the_result_, &msg); error_print(#x " failed (%s)\n", msg); failure_handler; } } +typedef struct { + Program* base; + String entry_point; +} SpecProgramKey; + typedef struct CudaBackend_ { Backend base; } CudaBackend; @@ -17,6 +22,7 @@ typedef struct { Device base; CUdevice handle; char name[256]; + struct Dict* specialized_programs; } CudaDevice; typedef struct { @@ -28,8 +34,31 @@ typedef struct { bool is_imported; } CudaBuffer; +typedef struct { + Command base; +} CudaCommand; + +typedef struct { + SpecProgramKey key; + CudaDevice* device; + Module* final_module; + struct { + char* cuda_code; + size_t cuda_code_size; + }; + struct { + char* ptx; + size_t ptx_size; + }; + CUmodule cuda_module; + CUfunction entry_point_function; +} CudaKernel; + CudaBuffer* shd_cuda_allocate_buffer(CudaDevice*, size_t size); CudaBuffer* shd_cuda_import_host_memory(CudaDevice*, void* host_ptr, size_t size); bool shd_cuda_can_import_host_memory(CudaDevice*); +CudaKernel* shd_cuda_get_specialized_program(CudaDevice*, Program*, String ep); +bool shd_cuda_destroy_specialized_kernel(CudaKernel*); + #endif diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c new file mode 100644 index 000000000..119d0f707 --- /dev/null +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -0,0 +1,86 @@ +#include "cuda_runtime_private.h" + +#include "log.h" +#include "portability.h" +#include "dict.h" + +static CompilerConfig get_compiler_config_for_device(CudaDevice* device, const CompilerConfig* base_config) { + CompilerConfig config = *base_config; + config.specialization.subgroup_size = 32; + + return config; +} + +static bool emit_cuda_c_code(CudaKernel* spec) { + CompilerConfig config = get_compiler_config_for_device(spec->device, spec->key.base->base_config); + config.specialization.entry_point = spec->key.entry_point; + + Module* dst_mod; + CHECK(run_compiler_passes(&config, &dst_mod) == CompilationNoError, return false); + + CEmitterConfig emitter_config = { + .dialect = CUDA, + .explicitly_sized_types = true, + .allow_compound_literals = true, + }; + Module* final_mod; + emit_c(config, emitter_config, dst_mod, &spec->cuda_code_size, &spec->cuda_code, &final_mod); + spec->final_module = final_mod; + return true; +} + +static bool cuda_c_to_ptx(CudaKernel* kernel) { + nvrtcProgram program; + CHECK_NVRTC(nvrtcCreateProgram(&program, kernel->cuda_code, kernel->key.entry_point, 0, NULL, NULL), return false); + nvrtcResult compile_result = nvrtcCompileProgram(program, 0, false); + if (compile_result != NVRTC_SUCCESS) { + error_print("NVRTC compilation failed: %s\n", nvrtcGetErrorString(compile_result)); + } + + size_t log_size; + CHECK_NVRTC(nvrtcGetProgramLogSize(program, &log_size), return false); + char* log_buffer = calloc(log_size, 1); + CHECK_NVRTC(nvrtcGetProgramLog(program, log_buffer), return false); + log_string(compile_result == NVRTC_SUCCESS ? DEBUG : ERROR, "NVRTC compilation log: %s\n", log_buffer); + free(log_buffer); + + CHECK_NVRTC(nvrtcGetPTXSize(program, &kernel->ptx_size), return false); + kernel->ptx = calloc(kernel->ptx_size, 1); + CHECK_NVRTC(nvrtcGetPTX(program, kernel->ptx), return false); + CHECK_NVRTC(nvrtcDestroyProgram(&program), return false); + + return true; +} + +static bool load_ptx_into_cuda_program(CudaKernel* kernel) { + CHECK_CUDA(cuModuleLoadDataEx(&kernel->cuda_module, kernel->ptx, 0, NULL, NULL), return false); + CHECK_CUDA(cuModuleGetFunction(&kernel->entry_point_function, kernel->cuda_module, kernel->key.entry_point), return false); + return true; +} + +static CudaKernel* create_specialized_program(CudaDevice* device, SpecProgramKey key) { + CudaKernel* kernel = calloc(1, sizeof(CudaKernel)); + if (!kernel) + return NULL; + *kernel = (CudaKernel) { + .key = key, + .device = device, + }; + + CHECK(emit_cuda_c_code(kernel), return NULL); + CHECK(cuda_c_to_ptx(kernel), return NULL); + CHECK(load_ptx_into_cuda_program(kernel), return NULL); + + return kernel; +} + +CudaKernel* shd_cuda_get_specialized_program(CudaDevice* device, Program* program, String entry_point) { + SpecProgramKey key = { .base = program, .entry_point = entry_point }; + CudaKernel** found = find_value_dict(SpecProgramKey, CudaKernel*, device->specialized_programs, key); + if (found) + return *found; + CudaKernel* spec = create_specialized_program(device, key); + assert(spec); + insert_dict(SpecProgramKey, CudaKernel*, device->specialized_programs, key, spec); + return spec; +} diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index 6f8bca4c5..c96a883e7 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -208,11 +208,11 @@ static bool get_physical_device_caps(SHADY_UNUSED VkrBackend* runtime, VkPhysica return false; } -KeyHash hash_spec_program_key(SpecProgramKey* ptr) { +static KeyHash hash_spec_program_key(SpecProgramKey* ptr) { return hash_murmur(ptr, sizeof(SpecProgramKey)); } -bool cmp_spec_program_keys(SpecProgramKey* a, SpecProgramKey* b) { +static bool cmp_spec_program_keys(SpecProgramKey* a, SpecProgramKey* b) { return memcmp(a, b, sizeof(SpecProgramKey)) == 0; } diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index a529b8d4e..13d4a9afd 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -331,9 +331,9 @@ static bool compile_specialized_program(VkrSpecProgram* spec) { CHECK(run_compiler_passes(&config, &spec->specialized_module) == CompilationNoError, return false); - Module* new_mod; - emit_spirv(&config, spec->specialized_module, &spec->spirv_size, &spec->spirv_bytes, &new_mod); - spec->specialized_module = new_mod; + Module* final_mod; + emit_spirv(&config, spec->specialized_module, &spec->spirv_size, &spec->spirv_bytes, &final_mod); + spec->specialized_module = final_mod; if (spec->key.base->runtime->config.dump_spv) { String module_name = get_module_name(spec->specialized_module); From 874cf998e57ac77ff77e6b8f9e256b5e79fff268 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 14:02:43 +0100 Subject: [PATCH 102/693] runtime: moved extract_parameters_info to common code --- src/runtime/cuda/cuda_runtime_private.h | 1 + src/runtime/cuda/cuda_runtime_program.c | 1 + src/runtime/runtime_private.h | 9 ++ src/runtime/runtime_program.c | 106 +++++++++++++++++++++++ src/runtime/vulkan/vk_runtime_private.h | 7 -- src/runtime/vulkan/vk_runtime_program.c | 107 +----------------------- 6 files changed, 118 insertions(+), 113 deletions(-) diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index 2a103609a..11427ecc3 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -52,6 +52,7 @@ typedef struct { }; CUmodule cuda_module; CUfunction entry_point_function; + ProgramParamsInfo parameters; } CudaKernel; CudaBuffer* shd_cuda_allocate_buffer(CudaDevice*, size_t size); diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 119d0f707..3589745f3 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -70,6 +70,7 @@ static CudaKernel* create_specialized_program(CudaDevice* device, SpecProgramKey CHECK(emit_cuda_c_code(kernel), return NULL); CHECK(cuda_c_to_ptx(kernel), return NULL); CHECK(load_ptx_into_cuda_program(kernel), return NULL); + CHECK(shd_extract_parameters_info(&kernel->parameters, kernel->final_module), return false); return kernel; } diff --git a/src/runtime/runtime_private.h b/src/runtime/runtime_private.h index b74efca95..951348724 100644 --- a/src/runtime/runtime_private.h +++ b/src/runtime/runtime_private.h @@ -36,6 +36,13 @@ struct Device_ { bool (*can_import_host_memory)(Device*); }; +typedef struct { + size_t num_args; + const size_t* arg_offset; + const size_t* arg_size; + size_t args_size; +} ProgramParamsInfo; + struct Program_ { Runtime* runtime; const CompilerConfig* base_config; @@ -44,6 +51,8 @@ struct Program_ { Module* module; }; +bool shd_extract_parameters_info(ProgramParamsInfo* info, Module* mod); + struct Command_ { bool (*wait_for_completion)(Command*); }; diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index caf344e8d..076b4b274 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -4,11 +4,14 @@ #include "log.h" #include "list.h" #include "util.h" +#include "portability.h" #include #include #include +#include "../shady/transform/memory_layout.h" + Program* new_program_from_module(Runtime* runtime, const CompilerConfig* base_config, Module* mod) { Program* program = calloc(1, sizeof(Program)); program->runtime = runtime; @@ -55,3 +58,106 @@ void unload_program(Program* program) { destroy_ir_arena(program->arena); free(program); } + +bool shd_extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) { + Nodes decls = get_module_declarations(mod); + + const Node* args_struct_annotation; + const Node* args_struct_type = NULL; + const Node* entry_point_function = NULL; + + for (int i = 0; i < decls.count; ++i) { + const Node* node = decls.nodes[i]; + + switch (node->tag) { + case GlobalVariable_TAG: { + const Node* entry_point_args_annotation = lookup_annotation(node, "EntryPointArgs"); + if (entry_point_args_annotation) { + if (node->payload.global_variable.type->tag != RecordType_TAG) { + error_print("EntryPointArgs must be a struct\n"); + return false; + } + + if (args_struct_type) { + error_print("there cannot be more than one EntryPointArgs\n"); + return false; + } + + args_struct_annotation = entry_point_args_annotation; + args_struct_type = node->payload.global_variable.type; + } + break; + } + case Function_TAG: { + if (lookup_annotation(node, "EntryPoint")) { + if (node->payload.fun.params.count != 0) { + error_print("EntryPoint cannot have parameters\n"); + return false; + } + + if (entry_point_function) { + error_print("there cannot be more than one EntryPoint\n"); + return false; + } + + entry_point_function = node; + } + break; + } + default: break; + } + } + + if (!entry_point_function) { + error_print("could not find EntryPoint\n"); + return false; + } + + if (!args_struct_type) { + *parameters = (ProgramParamsInfo) { .num_args = 0 }; + return true; + } + + if (args_struct_annotation->tag != AnnotationValue_TAG) { + error_print("EntryPointArgs annotation must contain exactly one value\n"); + return false; + } + + const Node* annotation_fn = args_struct_annotation->payload.annotation_value.value; + assert(annotation_fn->tag == FnAddr_TAG); + if (annotation_fn->payload.fn_addr.fn != entry_point_function) { + error_print("EntryPointArgs annotation refers to different EntryPoint\n"); + return false; + } + + size_t num_args = args_struct_type->payload.record_type.members.count; + + if (num_args == 0) { + error_print("EntryPointArgs cannot be empty\n"); + return false; + } + + IrArena* a = get_module_arena(mod); + + LARRAY(FieldLayout, fields, num_args); + get_record_layout(a, args_struct_type, fields); + + size_t* offset_size_buffer = calloc(1, 2 * num_args * sizeof(size_t)); + if (!offset_size_buffer) { + error_print("failed to allocate EntryPointArgs offsets and sizes array\n"); + return false; + } + size_t* offsets = offset_size_buffer; + size_t* sizes = offset_size_buffer + num_args; + + for (int i = 0; i < num_args; ++i) { + offsets[i] = fields[i].offset_in_bytes; + sizes[i] = fields[i].mem_layout.size_in_bytes; + } + + parameters->num_args = num_args; + parameters->arg_offset = offsets; + parameters->arg_size = sizes; + parameters->args_size = offsets[num_args - 1] + sizes[num_args - 1]; + return true; +} diff --git a/src/runtime/vulkan/vk_runtime_private.h b/src/runtime/vulkan/vk_runtime_private.h index 5df5a1511..fe1a16361 100644 --- a/src/runtime/vulkan/vk_runtime_private.h +++ b/src/runtime/vulkan/vk_runtime_private.h @@ -190,13 +190,6 @@ bool vkr_wait_completion(VkrCommand* cmd); VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args); -typedef struct { - size_t num_args; - const size_t* arg_offset; - const size_t* arg_size; - size_t args_size; -} ProgramParamsInfo; - typedef struct ProgramResourceInfo_ ProgramResourceInfo; struct ProgramResourceInfo_ { bool is_bound; diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 13d4a9afd..95d023c5c 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -9,114 +9,9 @@ #include "arena.h" #include "util.h" -#include "../../shady/transform/memory_layout.h" - #include #include -static bool extract_parameters_info(VkrSpecProgram* program) { - Nodes decls = get_module_declarations(program->specialized_module); - - const Node* args_struct_annotation; - const Node* args_struct_type = NULL; - const Node* entry_point_function = NULL; - - for (int i = 0; i < decls.count; ++i) { - const Node* node = decls.nodes[i]; - - switch (node->tag) { - case GlobalVariable_TAG: { - const Node* entry_point_args_annotation = lookup_annotation(node, "EntryPointArgs"); - if (entry_point_args_annotation) { - if (node->payload.global_variable.type->tag != RecordType_TAG) { - error_print("EntryPointArgs must be a struct\n"); - return false; - } - - if (args_struct_type) { - error_print("there cannot be more than one EntryPointArgs\n"); - return false; - } - - args_struct_annotation = entry_point_args_annotation; - args_struct_type = node->payload.global_variable.type; - } - break; - } - case Function_TAG: { - if (lookup_annotation(node, "EntryPoint")) { - if (node->payload.fun.params.count != 0) { - error_print("EntryPoint cannot have parameters\n"); - return false; - } - - if (entry_point_function) { - error_print("there cannot be more than one EntryPoint\n"); - return false; - } - - entry_point_function = node; - } - break; - } - default: break; - } - } - - if (!entry_point_function) { - error_print("could not find EntryPoint\n"); - return false; - } - - if (!args_struct_type) { - program->parameters = (ProgramParamsInfo) { .num_args = 0 }; - return true; - } - - if (args_struct_annotation->tag != AnnotationValue_TAG) { - error_print("EntryPointArgs annotation must contain exactly one value\n"); - return false; - } - - const Node* annotation_fn = args_struct_annotation->payload.annotation_value.value; - assert(annotation_fn->tag == FnAddr_TAG); - if (annotation_fn->payload.fn_addr.fn != entry_point_function) { - error_print("EntryPointArgs annotation refers to different EntryPoint\n"); - return false; - } - - size_t num_args = args_struct_type->payload.record_type.members.count; - - if (num_args == 0) { - error_print("EntryPointArgs cannot be empty\n"); - return false; - } - - IrArena* a = get_module_arena(program->specialized_module); - - LARRAY(FieldLayout, fields, num_args); - get_record_layout(a, args_struct_type, fields); - - size_t* offset_size_buffer = calloc(1, 2 * num_args * sizeof(size_t)); - if (!offset_size_buffer) { - error_print("failed to allocate EntryPointArgs offsets and sizes array\n"); - return false; - } - size_t* offsets = offset_size_buffer; - size_t* sizes = offset_size_buffer + num_args; - - for (int i = 0; i < num_args; ++i) { - offsets[i] = fields[i].offset_in_bytes; - sizes[i] = fields[i].mem_layout.size_in_bytes; - } - - program->parameters.num_args = num_args; - program->parameters.arg_offset = offsets; - program->parameters.arg_size = sizes; - program->parameters.args_size = offsets[num_args - 1] + sizes[num_args - 1]; - return true; -} - static void register_required_descriptors(VkrSpecProgram* program, VkDescriptorSetLayoutBinding* binding) { assert(binding->descriptorCount > 0); size_t i = 0; @@ -232,7 +127,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay } static bool extract_layout(VkrSpecProgram* program) { - CHECK(extract_parameters_info(program), return false); + CHECK(shd_extract_parameters_info(&program->parameters, program->specialized_module), return false); if (program->parameters.args_size > program->device->caps.properties.base.properties.limits.maxPushConstantsSize) { error_print("EntryPointArgs exceed available push constant space\n"); return false; From e033d2e0e54c3e239e8c88d4d98899dbc4f34123 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 14:36:11 +0100 Subject: [PATCH 103/693] runtime/cuda: stub cudaLaunch --- src/runtime/cuda/CMakeLists.txt | 2 +- src/runtime/cuda/cuda_runtime.c | 20 +++++++++++++++++++- src/runtime/vulkan/vk_runtime_program.c | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index bd9a3169d..4532d5ebb 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -7,7 +7,7 @@ if (CUDA_FOUND) target_link_libraries(cuda_runtime PUBLIC shady) target_link_libraries(cuda_runtime PRIVATE "$") target_link_libraries(cuda_runtime PRIVATE "$") - target_link_libraries(cuda_runtime PRIVATE CUDA_LIBRARIES) + target_link_libraries(cuda_runtime PRIVATE ${CUDA_LIBRARIES}) set_property(TARGET cuda_runtime PROPERTY POSITION_INDEPENDENT_CODE ON) target_link_libraries(runtime PRIVATE cuda_runtime) target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 0cfa1f19b..4cfa3815c 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -22,8 +22,26 @@ static void cuda_device_cleanup(CudaDevice* device) { destroy_dict(device->specialized_programs); } -CudaCommand shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args) { +bool cuda_command_wait(CudaCommand* command) { + CHECK_CUDA(cuCtxSynchronize(), return false); + return true; +} + +CudaCommand* shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args) { CudaKernel* kernel = shd_cuda_get_specialized_program(device, p, entry_point); + + CudaCommand* cmd = calloc(sizeof(CudaCommand), 1); + *cmd = (CudaCommand) { + .base = { + .wait_for_completion = (bool(*)(Command*)) cuda_command_wait + } + }; + ArenaConfig final_config = get_arena_config(get_module_arena(kernel->final_module)); + unsigned int gx = final_config.specializations.workgroup_size[0]; + unsigned int gy = final_config.specializations.workgroup_size[1]; + unsigned int gz = final_config.specializations.workgroup_size[2]; + CHECK_CUDA(cuLaunchKernel(kernel->entry_point_function, dimx, dimy, dimz, gx, gy, gz, 0, 0, args, NULL), return NULL); + return cmd; } static KeyHash hash_spec_program_key(SpecProgramKey* ptr) { diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 95d023c5c..ab3533ad7 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -9,6 +9,8 @@ #include "arena.h" #include "util.h" +#include "../../shady/transform/memory_layout.h" + #include #include From effef01e4933815a97397b88bf4a6343ff0c4600 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 14:39:02 +0100 Subject: [PATCH 104/693] add prefix to CDialect enum members --- include/shady/ir.h | 6 +-- src/driver/driver.c | 6 +-- src/shady/emit/c/emit_c.c | 70 +++++++++++++------------- src/shady/emit/c/emit_c_builtins.c | 4 +- src/shady/emit/c/emit_c_instructions.c | 46 ++++++++--------- src/shady/emit/c/emit_c_signatures.c | 42 ++++++++-------- 6 files changed, 87 insertions(+), 87 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index f666bb89a..3698045da 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -326,9 +326,9 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** mod); void emit_spirv(CompilerConfig* config, Module*, size_t* output_size, char** output, Module** new_mod); typedef enum { - C, - GLSL, - ISPC + CDialect_C11, + CDialect_GLSL, + CDialect_ISPC } CDialect; typedef struct { diff --git a/src/driver/driver.c b/src/driver/driver.c index 02cf7f8fd..aedc2d9a5 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -156,15 +156,15 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { case TgtAuto: SHADY_UNREACHABLE; case TgtSPV: emit_spirv(&args->config, mod, &output_size, &output_buffer, NULL); break; case TgtC: - args->c_emitter_config.dialect = C; + args->c_emitter_config.dialect = CDialect_C11; emit_c(args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; case TgtGLSL: - args->c_emitter_config.dialect = GLSL; + args->c_emitter_config.dialect = CDialect_GLSL; emit_c(args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; case TgtISPC: - args->c_emitter_config.dialect = ISPC; + args->c_emitter_config.dialect = CDialect_ISPC; emit_c(args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; } diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 67b40aa33..341b8f7cf 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -105,9 +105,9 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e static bool has_forward_declarations(CDialect dialect) { switch (dialect) { - case C: return true; - case GLSL: // no global variable forward declarations in GLSL - case ISPC: // ISPC seems to share this quirk + case CDialect_C11: return true; + case CDialect_GLSL: // no global variable forward declarations in GLSL + case CDialect_ISPC: // ISPC seems to share this quirk return false; } } @@ -116,17 +116,17 @@ static void emit_global_variable_definition(Emitter* emitter, String prefix, Str // GLSL wants 'const' to go on the left to start the declaration, but in C const should go on the right (east const convention) switch (emitter->config.dialect) { // ISPC defaults to varying, even for constants... yuck - case ISPC: + case CDialect_ISPC: if (uniform) decl_center = format_string_arena(emitter->arena->arena, "uniform %s", decl_center); else decl_center = format_string_arena(emitter->arena->arena, "varying %s", decl_center); break; - case C: + case CDialect_C11: if (constant) decl_center = format_string_arena(emitter->arena->arena, "const %s", decl_center); break; - case GLSL: + case CDialect_GLSL: if (constant) prefix = format_string_arena(emitter->arena->arena, "%s %s", "const", prefix); break; @@ -163,7 +163,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { bool is_long = value->payload.int_literal.width == IntTy64; bool is_signed = value->payload.int_literal.is_signed; - if (emitter->config.dialect == GLSL) { + if (emitter->config.dialect == CDialect_GLSL) { if (!is_signed) emitted = format_string_arena(emitter->arena->arena, "%sU", emitted); if (is_long) @@ -194,7 +194,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { case Value_True_TAG: return term_from_cvalue("true"); case Value_False_TAG: return term_from_cvalue("false"); case Value_Undef_TAG: { - if (emitter->config.dialect == GLSL) + if (emitter->config.dialect == CDialect_GLSL) return emit_value(emitter, block_printer, get_default_zero_value(emitter->arena, value->payload.undef.type)); String name = unique_name(emitter->arena, "undef"); emit_global_variable_definition(emitter, "", name, value->payload.undef.type, true, true, NULL); @@ -233,7 +233,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { switch (emitter->config.dialect) { no_compound_literals: - case ISPC: { + case CDialect_ISPC: { // arrays need double the brackets if (type->tag == ArrType_TAG) emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); @@ -248,13 +248,13 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { } break; } - case C: + case CDialect_C11: // If we're C89 (ew) if (!emitter->config.allow_compound_literals) goto no_compound_literals; emitted = format_string_arena(emitter->arena->arena, "((%s) { %s })", emit_type(emitter, value->type, NULL), emitted); break; - case GLSL: + case CDialect_GLSL: if (type->tag != PackType_TAG) goto no_compound_literals; // GLSL doesn't have compound literals, but it does have constructor syntax for vectors @@ -298,7 +298,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { const Node* decl = value->payload.ref_decl.decl; emit_decl(emitter, decl); - if (emitter->config.dialect == ISPC && decl->tag == GlobalVariable_TAG) { + if (emitter->config.dialect == CDialect_ISPC && decl->tag == GlobalVariable_TAG) { if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !is_decl_builtin(decl)) { assert(block_printer && "ISPC backend cannot statically refer to a varying variable"); return ispc_varying_ptr_helper(emitter, block_printer, decl->type, *lookup_existing_term(emitter, decl)); @@ -331,14 +331,14 @@ void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const T // add extra qualifiers if immutable if (!mut) switch (emitter->config.dialect) { - case ISPC: + case CDialect_ISPC: center = format_string_arena(emitter->arena->arena, "const %s", center); break; - case C: + case CDialect_C11: prefix = "register "; center = format_string_arena(emitter->arena->arena, "const %s", center); break; - case GLSL: + case CDialect_GLSL: prefix = "const "; break; } @@ -456,13 +456,13 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node } case Terminator_Unreachable_TAG: { switch (emitter->config.dialect) { - case C: + case CDialect_C11: print(block_printer, "\n__builtin_unreachable();"); break; - case ISPC: + case CDialect_ISPC: print(block_printer, "\nassert(false);"); break; - case GLSL: + case CDialect_GLSL: print(block_printer, "\n//unreachable"); break; } @@ -479,7 +479,7 @@ void emit_lambda_body_at(Emitter* emitter, Printer* p, const Node* body, const N emit_terminator(emitter, p, body); if (bbs && bbs->count > 0) { - assert(emitter->config.dialect != GLSL); + assert(emitter->config.dialect != CDialect_GLSL); error("TODO"); } @@ -535,12 +535,12 @@ void emit_decl(Emitter* emitter, const Node* decl) { case AsSubgroupLogical: case AsSubgroupPhysical: switch (emitter->config.dialect) { - case C: - case GLSL: + case CDialect_C11: + case CDialect_GLSL: warn_print("C and GLSL do not have a 'subgroup' level addressing space, using shared instead"); address_space_prefix = "shared "; break; - case ISPC: + case CDialect_ISPC: address_space_prefix = ""; break; } @@ -555,12 +555,12 @@ void emit_decl(Emitter* emitter, const Node* decl) { case AsSharedPhysical: case AsSharedLogical: switch (emitter->config.dialect) { - case C: + case CDialect_C11: break; - case GLSL: + case CDialect_GLSL: address_space_prefix = "shared "; break; - case ISPC: + case CDialect_ISPC: // ISPC doesn't really know what "shared" is break; } @@ -610,7 +610,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { String fn_body = emit_lambda_body(emitter, body, NULL); String free_me = fn_body; - if (emitter->config.dialect == ISPC) { + if (emitter->config.dialect == CDialect_ISPC) { // ISPC hack: This compiler (like seemingly all LLVM-based compilers) has broken handling of the execution mask - it fails to generated masked stores for the entry BB of a function that may be called non-uniformingly // therefore we must tell ISPC to please, pretty please, mask everything by branching on what the mask should be fn_body = format_string_arena(emitter->arena->arena, "if ((lanemask() >> programIndex) & 1u) { %s}", fn_body); @@ -637,9 +637,9 @@ void emit_decl(Emitter* emitter, const Node* decl) { CType emitted = name; register_emitted_type(emitter, decl, emitted); switch (emitter->config.dialect) { - case ISPC: - case C: print(emitter->type_decls, "\ntypedef %s;", emit_type(emitter, decl->payload.nom_type.body, emitted)); break; - case GLSL: emit_nominal_type_body(emitter, format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; + case CDialect_ISPC: + case CDialect_C11: print(emitter->type_decls, "\ntypedef %s;", emit_type(emitter, decl->payload.nom_type.body, emitted)); break; + case CDialect_GLSL: emit_nominal_type_body(emitter, format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; } return; } @@ -674,10 +674,10 @@ static Module* run_backend_specific_passes(CompilerConfig* config, CEmitterConfi Module* old_mod = NULL; Module** pmod = &initial_mod; - if (econfig->dialect == ISPC) { + if (econfig->dialect == CDialect_ISPC) { RUN_PASS(lower_workgroups) } - if (econfig->dialect != GLSL) { + if (econfig->dialect != CDialect_GLSL) { RUN_PASS(lower_vec_arr) } if (config->lower.simt_to_explicit_simd) { @@ -718,23 +718,23 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, Growy* final = new_growy(); Printer* finalp = open_growy_as_printer(final); - if (emitter.config.dialect == GLSL) { + if (emitter.config.dialect == CDialect_GLSL) { print(finalp, "#version 420\n"); } print(finalp, "/* file generated by shady */\n"); switch (emitter.config.dialect) { - case ISPC: + case CDialect_ISPC: break; - case C: + case CDialect_C11: print(finalp, "\n#include "); print(finalp, "\n#include "); print(finalp, "\n#include "); print(finalp, "\n#include "); print(finalp, "\n#include "); break; - case GLSL: + case CDialect_GLSL: print(finalp, "#extension GL_ARB_gpu_shader_int64: require\n"); print(finalp, "#define ubyte uint\n"); print(finalp, "#define uchar uint\n"); diff --git a/src/shady/emit/c/emit_c_builtins.c b/src/shady/emit/c/emit_c_builtins.c index c94532c87..9e3568338 100644 --- a/src/shady/emit/c/emit_c_builtins.c +++ b/src/shady/emit/c/emit_c_builtins.c @@ -20,8 +20,8 @@ static String glsl_builtins[BuiltinsCount] = { CTerm emit_c_builtin(Emitter* emitter, Builtin b) { String name = NULL; switch(emitter->config.dialect) { - case ISPC: name = ispc_builtins[b]; break; - case GLSL: name = glsl_builtins[b]; break; + case CDialect_ISPC: name = ispc_builtins[b]; break; + case CDialect_GLSL: name = glsl_builtins[b]; break; default: break; } if (name) diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index abc2cec24..59decc3d0 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -185,9 +185,9 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, Printer* p, const ISe static const ISelTableEntry* lookup_entry(Emitter* emitter, Op op) { const ISelTableEntry* isel_entry = NULL; switch (emitter->config.dialect) { - case C: isel_entry = &isel_table_c[op]; break; - case GLSL: isel_entry = &isel_table_glsl[op]; break; - case ISPC: isel_entry = &isel_table_ispc[op]; break; + case CDialect_C11: isel_entry = &isel_table_c[op]; break; + case CDialect_GLSL: isel_entry = &isel_table_glsl[op]; break; + case CDialect_ISPC: isel_entry = &isel_table_ispc[op]; break; } if (isel_entry->isel_mechanism == IsNone) isel_entry = &isel_table[op]; @@ -254,7 +254,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; emit_variable_declaration(emitter, p, first(prim_op->type_arguments), variable_name, true, NULL); outputs.results[0] = variable; - if (emitter->config.dialect == ISPC) { + if (emitter->config.dialect == CDialect_ISPC) { outputs.results[0] = ispc_varying_ptr_helper(emitter, p, get_unqualified_type(node->type), variable); } outputs.binding[0] = NoBinding; @@ -276,7 +276,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, addr)); CValue cvalue = to_cvalue(emitter, emit_value(emitter, p, value)); // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this - if (emitter->config.dialect == ISPC && addr_uniform && is_addr_space_uniform(arena, addr_type->payload.ptr_type.address_space) && !value_uniform) + if (emitter->config.dialect == CDialect_ISPC && addr_uniform && is_addr_space_uniform(arena, addr_type->payload.ptr_type.address_space) && !value_uniform) cvalue = format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); print(p, "\n%s = %s;", dereferenced, cvalue); @@ -307,7 +307,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct switch (is_type(pointee_type)) { case ArrType_TAG: { CTerm index = emit_value(emitter, p, selector); - if (emitter->config.dialect == GLSL) + if (emitter->config.dialect == CDialect_GLSL) acc = term_from_cvar(format_string_arena(arena->arena, "(%s.arr[int(%s)])", deref_term(emitter, acc), to_cvalue(emitter, index))); else acc = term_from_cvar(format_string_arena(arena->arena, "(%s.arr[%s])", deref_term(emitter, acc), to_cvalue(emitter, index))); @@ -326,7 +326,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct // ISPC cannot deal with subscripting if you've done pointer arithmetic (!) inside the expression // so hum we just need to introduce a temporary variable to hold the pointer expression so far, and go again from there // See https://github.com/ispc/ispc/issues/2496 - if (emitter->config.dialect == ISPC) { + if (emitter->config.dialect == CDialect_ISPC) { String interm = unique_name(arena, "lea_intermediary_ptr_value"); print(p, "\n%s = %s;", emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); acc = term_from_cvalue(interm); @@ -347,7 +347,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct } assert(outputs.count == 1); outputs.results[0] = acc; - outputs.binding[0] = emitter->config.dialect == ISPC ? LetBinding : NoBinding; + outputs.binding[0] = emitter->config.dialect == CDialect_ISPC ? LetBinding : NoBinding; outputs.binding[0] = NoBinding; return; } @@ -384,7 +384,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct CTerm src = emit_value(emitter, p, first(prim_op->operands)); const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); - if (emitter->config.dialect == GLSL) { + if (emitter->config.dialect == CDialect_GLSL) { if (is_glsl_scalar_type(src_type) && is_glsl_scalar_type(dst_type)) { CType t = emit_type(emitter, dst_type, NULL); term = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", t, to_cvalue(emitter, src))); @@ -402,7 +402,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); switch (emitter->config.dialect) { - case C: { + case CDialect_C11: { String src = unique_name(arena, "bitcast_src"); String dst = unique_name(arena, "bitcast_result"); print(p, "\n%s = %s;", emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); @@ -412,7 +412,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct outputs.binding[0] = NoBinding; break; } - case GLSL: { + case CDialect_GLSL: { String n = NULL; if (dst_type->tag == Float_TAG) { assert(src_type->tag == Int_TAG); @@ -448,7 +448,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct error_print(".\n"); error_die(); } - case ISPC: { + case CDialect_ISPC: { if (dst_type->tag == Float_TAG) { assert(src_type->tag == Int_TAG); String n; @@ -520,7 +520,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct break; } case Type_ArrType_TAG: { - if (emitter->config.dialect == GLSL) + if (emitter->config.dialect == CDialect_GLSL) acc = format_string_arena(emitter->arena->arena, "(%s.arr[int(%s)])", acc, to_cvalue(emitter, emit_value(emitter, p, index))); else acc = format_string_arena(emitter->arena->arena, "(%s.arr[%s])", acc, to_cvalue(emitter, emit_value(emitter, p, index))); @@ -548,9 +548,9 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case create_joint_point_op: error("lowered in lower_tailcalls.c"); case subgroup_elect_first_op: { switch (emitter->config.dialect) { - case ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); break; - case C: - case GLSL: error("TODO") + case CDialect_ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); break; + case CDialect_C11: + case CDialect_GLSL: error("TODO") } break; } @@ -558,9 +558,9 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case subgroup_broadcast_first_op: { CValue value = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); switch (emitter->config.dialect) { - case ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; - case C: - case GLSL: error("TODO") + case CDialect_ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; + case CDialect_C11: + case CDialect_GLSL: error("TODO") } break; } @@ -571,7 +571,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct for (size_t i = 0; i < prim_op->operands.count; i++) { CValue str = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[i])); - if (emitter->config.dialect == ISPC && i > 0) + if (emitter->config.dialect == CDialect_ISPC && i > 0) str = format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); if (i > 0) @@ -580,13 +580,13 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct args_list = str; } switch (emitter->config.dialect) { - case ISPC: + case CDialect_ISPC: print(p, "\nforeach_active(printf_thread_index) { print(%s); }", args_list); break; - case C: + case CDialect_C11: print(p, "\nprintf(%s);", args_list); break; - case GLSL: warn_print("printf is not supported in GLSL"); + case CDialect_GLSL: warn_print("printf is not supported in GLSL"); break; } diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index 88274e738..7caef61d2 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -51,7 +51,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Growy* paramg = new_growy(); Printer* paramp = open_growy_as_printer(paramg); Nodes dom = fn_type->payload.fn_type.param_types; - if (dom.count == 0 && emitter->config.dialect == C) + if (dom.count == 0 && emitter->config.dialect == CDialect_C11) print(paramp, "void"); else if (fn) { Nodes params = fn->payload.fun.params; @@ -76,11 +76,11 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const growy_append_bytes(paramg, 1, (char[]) { 0 }); const char* parameters = printer_growy_unwrap(paramp); switch (emitter->config.dialect) { - case ISPC: - case C: + case CDialect_ISPC: + case CDialect_C11: center = format_string_arena(emitter->arena->arena, "(%s)(%s)", center, parameters); break; - case GLSL: + case CDialect_GLSL: // GLSL does not accept functions declared like void (foo)(int); // it also does not support higher-order functions and/or function pointers, so we drop the parentheses center = format_string_arena(emitter->arena->arena, "%s(%s)", center, parameters); @@ -92,11 +92,11 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const const Node* entry_point = fn ? lookup_annotation(fn, "EntryPoint") : NULL; if (entry_point) switch (emitter->config.dialect) { - case C: + case CDialect_C11: break; - case GLSL: + case CDialect_GLSL: break; - case ISPC: + case CDialect_ISPC: c_decl = format_string_arena(emitter->arena->arena, "export %s", c_decl); break; } @@ -128,7 +128,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { case Bool_TAG: emitted = "bool"; break; case Int_TAG: { switch (emitter->config.dialect) { - case ISPC: { + case CDialect_ISPC: { const char* ispc_int_types[4][2] = { { "uint8" , "int8" }, { "uint16", "int16" }, @@ -138,7 +138,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { emitted = ispc_int_types[type->payload.int_type.width][type->payload.int_type.is_signed]; break; } - case C: { + case CDialect_C11: { const char* c_classic_int_types[4][2] = { { "unsigned char" , "char" }, { "unsigned short", "short" }, @@ -154,7 +154,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { emitted = (emitter->config.explicitly_sized_types ? c_explicit_int_sizes : c_classic_int_types)[type->payload.int_type.width][type->payload.int_type.is_signed]; break; } - case GLSL: + case CDialect_GLSL: switch (type->payload.int_type.width) { case IntTy8: warn_print("vanilla GLSL does not support 8-bit integers\n"); emitted = "ubyte"; @@ -194,17 +194,17 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { String prefixed = format_string_arena(emitter->arena->arena, "struct %s", emitted); emit_nominal_type_body(emitter, prefixed, type); // C puts structs in their own namespace so we always need the prefix - if (emitter->config.dialect == C) + if (emitter->config.dialect == CDialect_C11) emitted = prefixed; break; } case Type_QualifiedType_TAG: switch (emitter->config.dialect) { - case C: - case GLSL: + case CDialect_C11: + case CDialect_GLSL: return emit_type(emitter, type->payload.qualified_type.type, center); - case ISPC: + case CDialect_ISPC: if (type->payload.qualified_type.is_uniform) return emit_type(emitter, type->payload.qualified_type.type, format_string_arena(emitter->arena->arena, "uniform %s", center)); else @@ -213,7 +213,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { case Type_PtrType_TAG: { CType t = emit_type(emitter, type->payload.ptr_type.pointed_type, format_string_arena(emitter->arena->arena, "* %s", center)); // we always emit pointers to _uniform_ data, no exceptions - if (emitter->config.dialect == ISPC) + if (emitter->config.dialect == CDialect_ISPC) t = format_string_arena(emitter->arena->arena, "uniform %s", t); return t; } @@ -245,11 +245,11 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { // ditto from RecordType switch (emitter->config.dialect) { - case C: - case ISPC: + case CDialect_C11: + case CDialect_ISPC: emitted = prefixed; break; - case GLSL: + case CDialect_GLSL: break; } break; @@ -258,7 +258,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { int width = type->payload.pack_type.width; const Type* element_type = type->payload.pack_type.element_type; switch (emitter->config.dialect) { - case GLSL: { + case CDialect_GLSL: { assert(is_glsl_scalar_type(element_type)); assert(width > 1); String base; @@ -271,8 +271,8 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { emitted = format_string_arena(emitter->arena->arena, "%s%d", base, width); break; } - case ISPC: error("Please lower to something else") - case C: { + case CDialect_ISPC: error("Please lower to something else") + case CDialect_C11: { emitted = emit_type(emitter, element_type, NULL); emitted = format_string_arena(emitter->arena->arena, "__attribute__ ((vector_size (%d * sizeof(%s) ))) %s", width, emitted, emitted); break; From 616062633448b7d921d2b23fe271afa58e11041b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 14:50:33 +0100 Subject: [PATCH 105/693] emit_c: preliminary CUDA C dialect support --- include/shady/ir.h | 3 ++- src/runtime/cuda/cuda_runtime_program.c | 2 +- src/shady/emit/c/emit_c.c | 21 +++++++++++++++------ src/shady/emit/c/emit_c_instructions.c | 5 +++++ src/shady/emit/c/emit_c_signatures.c | 13 +++++++------ 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 3698045da..5ba1f65a2 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -328,7 +328,8 @@ void emit_spirv(CompilerConfig* config, Module*, size_t* output_size, char** out typedef enum { CDialect_C11, CDialect_GLSL, - CDialect_ISPC + CDialect_ISPC, + CDialect_CUDA, } CDialect; typedef struct { diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 3589745f3..5acff1a1c 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -19,7 +19,7 @@ static bool emit_cuda_c_code(CudaKernel* spec) { CHECK(run_compiler_passes(&config, &dst_mod) == CompilationNoError, return false); CEmitterConfig emitter_config = { - .dialect = CUDA, + .dialect = CDialect_CUDA, .explicitly_sized_types = true, .allow_compound_literals = true, }; diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 341b8f7cf..e410f4a3f 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -106,6 +106,7 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e static bool has_forward_declarations(CDialect dialect) { switch (dialect) { case CDialect_C11: return true; + case CDialect_CUDA: return true; case CDialect_GLSL: // no global variable forward declarations in GLSL case CDialect_ISPC: // ISPC seems to share this quirk return false; @@ -123,6 +124,7 @@ static void emit_global_variable_definition(Emitter* emitter, String prefix, Str decl_center = format_string_arena(emitter->arena->arena, "varying %s", decl_center); break; case CDialect_C11: + case CDialect_CUDA: if (constant) decl_center = format_string_arena(emitter->arena->arena, "const %s", decl_center); break; @@ -248,6 +250,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { } break; } + case CDialect_CUDA: case CDialect_C11: // If we're C89 (ew) if (!emitter->config.allow_compound_literals) @@ -335,6 +338,7 @@ void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const T center = format_string_arena(emitter->arena->arena, "const %s", center); break; case CDialect_C11: + case CDialect_CUDA: prefix = "register "; center = format_string_arena(emitter->arena->arena, "const %s", center); break; @@ -456,6 +460,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node } case Terminator_Unreachable_TAG: { switch (emitter->config.dialect) { + case CDialect_CUDA: case CDialect_C11: print(block_printer, "\n__builtin_unreachable();"); break; @@ -535,11 +540,9 @@ void emit_decl(Emitter* emitter, const Node* decl) { case AsSubgroupLogical: case AsSubgroupPhysical: switch (emitter->config.dialect) { - case CDialect_C11: - case CDialect_GLSL: - warn_print("C and GLSL do not have a 'subgroup' level addressing space, using shared instead"); - address_space_prefix = "shared "; - break; + default: + warn_print("Non-ISPC dialects of C do not have a 'subgroup' level addressing space, using shared instead"); + goto case_shared; case CDialect_ISPC: address_space_prefix = ""; break; @@ -552,11 +555,15 @@ void emit_decl(Emitter* emitter, const Node* decl) { case AsGlobalPhysical: address_space_prefix = ""; break; + case_shared: case AsSharedPhysical: case AsSharedLogical: switch (emitter->config.dialect) { case CDialect_C11: break; + case CDialect_CUDA: + address_space_prefix = "__shared__ "; + break; case CDialect_GLSL: address_space_prefix = "shared "; break; @@ -565,6 +572,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { break; } break; + case AsExternal: address_space_prefix = "extern "; break; @@ -638,7 +646,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { register_emitted_type(emitter, decl, emitted); switch (emitter->config.dialect) { case CDialect_ISPC: - case CDialect_C11: print(emitter->type_decls, "\ntypedef %s;", emit_type(emitter, decl->payload.nom_type.body, emitted)); break; + default: print(emitter->type_decls, "\ntypedef %s;", emit_type(emitter, decl->payload.nom_type.body, emitted)); break; case CDialect_GLSL: emit_nominal_type_body(emitter, format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; } return; @@ -727,6 +735,7 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, switch (emitter.config.dialect) { case CDialect_ISPC: break; + case CDialect_CUDA: /* TODO: probably don't wanna do this */ case CDialect_C11: print(finalp, "\n#include "); print(finalp, "\n#include "); diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 59decc3d0..2c4fb03b4 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -185,6 +185,7 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, Printer* p, const ISe static const ISelTableEntry* lookup_entry(Emitter* emitter, Op op) { const ISelTableEntry* isel_entry = NULL; switch (emitter->config.dialect) { + case CDialect_CUDA: /* TODO: do better than that */ case CDialect_C11: isel_entry = &isel_table_c[op]; break; case CDialect_GLSL: isel_entry = &isel_table_glsl[op]; break; case CDialect_ISPC: isel_entry = &isel_table_ispc[op]; break; @@ -402,6 +403,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); switch (emitter->config.dialect) { + case CDialect_CUDA: case CDialect_C11: { String src = unique_name(arena, "bitcast_src"); String dst = unique_name(arena, "bitcast_result"); @@ -548,6 +550,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case create_joint_point_op: error("lowered in lower_tailcalls.c"); case subgroup_elect_first_op: { switch (emitter->config.dialect) { + case CDialect_CUDA: error("TODO") case CDialect_ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); break; case CDialect_C11: case CDialect_GLSL: error("TODO") @@ -558,6 +561,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case subgroup_broadcast_first_op: { CValue value = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); switch (emitter->config.dialect) { + case CDialect_CUDA: error("TODO") case CDialect_ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; case CDialect_C11: case CDialect_GLSL: error("TODO") @@ -583,6 +587,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case CDialect_ISPC: print(p, "\nforeach_active(printf_thread_index) { print(%s); }", args_list); break; + case CDialect_CUDA: case CDialect_C11: print(p, "\nprintf(%s);", args_list); break; diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index 7caef61d2..c133040d8 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -76,8 +76,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const growy_append_bytes(paramg, 1, (char[]) { 0 }); const char* parameters = printer_growy_unwrap(paramp); switch (emitter->config.dialect) { - case CDialect_ISPC: - case CDialect_C11: + default: center = format_string_arena(emitter->arena->arena, "(%s)(%s)", center, parameters); break; case CDialect_GLSL: @@ -98,6 +97,8 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const break; case CDialect_ISPC: c_decl = format_string_arena(emitter->arena->arena, "export %s", c_decl); + case CDialect_CUDA: + c_decl = format_string_arena(emitter->arena->arena, "__kernel__ %s", c_decl); break; } @@ -138,6 +139,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { emitted = ispc_int_types[type->payload.int_type.width][type->payload.int_type.is_signed]; break; } + case CDialect_CUDA: case CDialect_C11: { const char* c_classic_int_types[4][2] = { { "unsigned char" , "char" }, @@ -201,8 +203,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { } case Type_QualifiedType_TAG: switch (emitter->config.dialect) { - case CDialect_C11: - case CDialect_GLSL: + default: return emit_type(emitter, type->payload.qualified_type.type, center); case CDialect_ISPC: if (type->payload.qualified_type.is_uniform) @@ -245,8 +246,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { // ditto from RecordType switch (emitter->config.dialect) { - case CDialect_C11: - case CDialect_ISPC: + default: emitted = prefixed; break; case CDialect_GLSL: @@ -258,6 +258,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { int width = type->payload.pack_type.width; const Type* element_type = type->payload.pack_type.element_type; switch (emitter->config.dialect) { + case CDialect_CUDA: error("TODO") case CDialect_GLSL: { assert(is_glsl_scalar_type(element_type)); assert(width > 1); From fea357f3d9426bb2254f983b7e258e2289beac94 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 15:11:15 +0100 Subject: [PATCH 106/693] runtime/cuda: Use CUDAToolkit package instead of CUDA --- src/runtime/cuda/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index 4532d5ebb..767551fe5 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -1,13 +1,13 @@ -find_package(CUDA) +find_package(CUDAToolkit) -if (CUDA_FOUND) - message("Cuda found.") +if (CUDAToolkit_FOUND) + message("Cuda toolkit found.") add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c cuda_runtime_program.c) target_link_libraries(cuda_runtime PUBLIC api) target_link_libraries(cuda_runtime PUBLIC shady) target_link_libraries(cuda_runtime PRIVATE "$") target_link_libraries(cuda_runtime PRIVATE "$") - target_link_libraries(cuda_runtime PRIVATE ${CUDA_LIBRARIES}) + target_link_libraries(cuda_runtime PRIVATE CUDA::cudart CUDA::cuda_driver CUDA::nvrtc) set_property(TARGET cuda_runtime PROPERTY POSITION_INDEPENDENT_CODE ON) target_link_libraries(runtime PRIVATE cuda_runtime) target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) From cb856b6dde1743acf52202abfab282b91a8362e4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 15:11:47 +0100 Subject: [PATCH 107/693] runtime/cuda: hack for single-context --- src/runtime/cuda/cuda_runtime.c | 1 + src/runtime/cuda/cuda_runtime_private.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 4cfa3815c..7613cbefb 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -69,6 +69,7 @@ static CudaDevice* create_cuda_device(CudaBackend* b, int ordinal) { .specialized_programs = new_dict(SpecProgramKey, CudaKernel*, (HashFn) hash_spec_program_key, (CmpFn) cmp_spec_program_keys), }; CHECK_CUDA(cuDeviceGetName(device->name, 255, handle), goto dealloc_and_return_null); + CHECK_CUDA(cuCtxCreate(&device->context, 0, handle), goto dealloc_and_return_null); return device; dealloc_and_return_null: diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index 11427ecc3..475426d1e 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -21,6 +21,7 @@ typedef struct CudaBackend_ { typedef struct { Device base; CUdevice handle; + CUcontext context; char name[256]; struct Dict* specialized_programs; } CudaDevice; From 75584f1c18f00c9aa657703f10d7cc52343d5586 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 15:12:08 +0100 Subject: [PATCH 108/693] runtime/cuda: count devices --- src/runtime/cuda/cuda_runtime.c | 3 ++- src/runtime/cuda/cuda_runtime_private.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 7613cbefb..68bcebe15 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -84,6 +84,7 @@ static bool probe_cuda_devices(CudaBackend* b) { CudaDevice* device = create_cuda_device(b, i); if (!device) continue; + b->num_devices++; append_list(CudaDevice*, b->base.runtime->devices, device); } return true; @@ -99,7 +100,7 @@ Backend* initialize_cuda_backend(Runtime* base) { CHECK_CUDA(cuInit(0), goto init_fail_free); CHECK(probe_cuda_devices(backend), goto init_fail_free); - info_print("Shady CUDA backend successfully initialized !\n"); + info_print("Shady CUDA backend successfully initialized, found %d devices\n", backend->num_devices); return &backend->base; init_fail_free: diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index 475426d1e..95a312e50 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -16,6 +16,7 @@ typedef struct { typedef struct CudaBackend_ { Backend base; + size_t num_devices; } CudaBackend; typedef struct { From ad854622fe1893caea0ed969adc547b918e0e1bc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 15:12:20 +0100 Subject: [PATCH 109/693] runtime/cuda: add missing kernel deletion fn --- src/runtime/cuda/cuda_runtime_program.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 5acff1a1c..c100898e8 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -85,3 +85,12 @@ CudaKernel* shd_cuda_get_specialized_program(CudaDevice* device, Program* progra insert_dict(SpecProgramKey, CudaKernel*, device->specialized_programs, key, spec); return spec; } + +bool shd_cuda_destroy_specialized_kernel(CudaKernel* kernel) { + free(kernel->cuda_code); + free(kernel->ptx); + CHECK_CUDA(cuModuleUnload(kernel->cuda_module), return false); + + free(kernel); + return true; +} \ No newline at end of file From d8e02dce59082f55fdbac18f2a3c0405cc7deaca Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 25 Mar 2024 15:12:30 +0100 Subject: [PATCH 110/693] runtime: enable CUDA --- src/runtime/runtime.c | 6 ++++++ src/runtime/runtime_private.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index b2875c37f..1d1c20175 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -19,6 +19,12 @@ Runtime* initialize_runtime(RuntimeConfig config) { CHECK(vk_backend, goto init_fail_free); append_list(Backend*, runtime->backends, vk_backend); #endif +#if CUDA_BACKEND_PRESENT + Backend* cuda_backend = initialize_cuda_backend(runtime); + CHECK(cuda_backend, goto init_fail_free); + append_list(Backend*, runtime->backends, cuda_backend); +#endif + info_print("Shady runtime successfully initialized !\n"); return runtime; diff --git a/src/runtime/runtime_private.h b/src/runtime/runtime_private.h index 951348724..a3f626e3d 100644 --- a/src/runtime/runtime_private.h +++ b/src/runtime/runtime_private.h @@ -69,4 +69,5 @@ struct Buffer_ { void unload_program(Program*); Backend* initialize_vk_backend(Runtime*); +Backend* initialize_cuda_backend(Runtime*); #endif From 39c38ff3038c83b5b0883c0e10f148e15f9ab787 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 26 Mar 2024 13:51:09 +0100 Subject: [PATCH 111/693] runtime/cuda: implement missing copy fns --- src/runtime/cuda/cuda_runtime_buffer.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/runtime/cuda/cuda_runtime_buffer.c b/src/runtime/cuda/cuda_runtime_buffer.c index 45e415ccd..dd9991bac 100644 --- a/src/runtime/cuda/cuda_runtime_buffer.c +++ b/src/runtime/cuda/cuda_runtime_buffer.c @@ -19,16 +19,28 @@ static void* cuda_get_host_ptr(CudaBuffer* buffer) { return (void*) buffer->host_ptr; } +static bool cuda_copy_to_buffer_fallback(CudaBuffer* dst, size_t dst_offset, void* src, size_t size) { + CHECK_CUDA(cuMemcpyHtoD(dst->device_ptr + dst_offset, src, size), return false); + return true; +} + +static bool cuda_copy_from_buffer_fallback(CudaBuffer* src, size_t src_offset, void* dst, size_t size) { + CHECK_CUDA(cuMemcpyDtoH(dst, src->device_ptr + src_offset, size), return false); + return true; +} + static CudaBuffer* new_buffer_common(size_t size) { CudaBuffer* buffer = calloc(sizeof(CudaBuffer), 1); *buffer = (CudaBuffer) { - .base = { - .backend_tag = CUDARuntimeBackend, - .get_host_ptr = (void*(*)(Buffer*)) cuda_get_host_ptr, - .get_device_ptr = (uint64_t(*)(Buffer*)) cuda_get_deviceptr, - .destroy = (void(*)(Buffer*)) cuda_destroy_buffer, - }, - .size = size, + .base = { + .backend_tag = CUDARuntimeBackend, + .get_host_ptr = (void*(*)(Buffer*)) cuda_get_host_ptr, + .get_device_ptr = (uint64_t(*)(Buffer*)) cuda_get_deviceptr, + .destroy = (void(*)(Buffer*)) cuda_destroy_buffer, + .copy_into = (bool(*)(Buffer*, size_t, void*, size_t)) cuda_copy_to_buffer_fallback, + .copy_from = (bool(*)(Buffer*, size_t, void*, size_t)) cuda_copy_from_buffer_fallback, + }, + .size = size, }; return buffer; } From 2ba433f9b02f90dd249c901a5e873f1af7acbf38 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 26 Mar 2024 13:51:58 +0100 Subject: [PATCH 112/693] de-duplicate subgroup_size between Compiler and ArenaConfig --- include/shady/ir.h | 1 - src/shady/passes/lower_workgroups.c | 6 +++--- src/shady/passes/specialize_entry_point.c | 8 ++++---- src/shady/transform/internal_constants.c | 1 + src/shady/transform/internal_constants.h | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 5ba1f65a2..68e09c141 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -85,7 +85,6 @@ typedef struct { SubgroupMaskInt64 } subgroup_mask_representation; - uint32_t subgroup_size; uint32_t workgroup_size[3]; } specializations; diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 313995ab0..d84cd14a0 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -80,9 +80,9 @@ static const Node* process(Context* ctx, const Node* node) { const Node* subgroup_id[3]; uint32_t num_subgroups[3]; const Node* num_subgroups_literals[3]; - assert(a->config.specializations.subgroup_size); + assert(ctx->config->specialization.subgroup_size); assert(a->config.specializations.workgroup_size[0] && a->config.specializations.workgroup_size[1] && a->config.specializations.workgroup_size[2]); - num_subgroups[0] = a->config.specializations.workgroup_size[0] / a->config.specializations.subgroup_size; + num_subgroups[0] = a->config.specializations.workgroup_size[0] / ctx->config->specialization.subgroup_size; num_subgroups[1] = a->config.specializations.workgroup_size[1]; num_subgroups[2] = a->config.specializations.workgroup_size[2]; String names2[] = { "sgx", "sgy", "sgz" }; @@ -97,7 +97,7 @@ static const Node* process(Context* ctx, const Node* node) { // write the local ID const Node* local_id[3]; // local_id[0] = SUBGROUP_SIZE * subgroup_id[0] + subgroup_local_id - local_id[0] = gen_primop_e(bb2, add_op, empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, empty(a), mk_nodes(a, uint32_literal(a, a->config.specializations.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); + local_id[0] = gen_primop_e(bb2, add_op, empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, empty(a), mk_nodes(a, uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); local_id[1] = subgroup_id[1]; local_id[2] = subgroup_id[2]; gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 9786727f7..2cbe554cc 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -13,9 +13,9 @@ typedef struct { Rewriter rewriter; const Node* old_entry_point_decl; const Node* old_wg_size_annotation; + const CompilerConfig* config; } Context; - static const Node* process(Context* ctx, const Node* node) { if (!node) return NULL; const Node* found = search_processed(&ctx->rewriter, node); @@ -52,7 +52,7 @@ static const Node* process(Context* ctx, const Node* node) { case Constant_TAG: { Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { - ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, a->config.specializations.subgroup_size))); + ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, ctx->config->specialization.subgroup_size))); } else if (strcmp(get_declaration_name(ncnst), "SUBGROUPS_PER_WG") == 0) { if (ctx->old_wg_size_annotation) { // SUBGROUPS_PER_WG = (NUMBER OF INVOCATIONS IN SUBGROUP / SUBGROUP SIZE) @@ -61,7 +61,7 @@ static const Node* process(Context* ctx, const Node* node) { wg_size[0] = a->config.specializations.workgroup_size[0]; wg_size[1] = a->config.specializations.workgroup_size[1]; wg_size[2] = a->config.specializations.workgroup_size[2]; - uint32_t subgroups_per_wg = (wg_size[0] * wg_size[1] * wg_size[2]) / a->config.specializations.subgroup_size; + uint32_t subgroups_per_wg = (wg_size[0] * wg_size[1] * wg_size[2]) / ctx->config->specialization.subgroup_size; if (subgroups_per_wg == 0) subgroups_per_wg = 1; // uh-oh ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, subgroups_per_wg))); @@ -92,7 +92,6 @@ static const Node* find_entry_point(Module* m, const CompilerConfig* config) { static void specialize_arena_config(const CompilerConfig* config, Module* src, ArenaConfig* target) { size_t subgroup_size = config->specialization.subgroup_size; assert(subgroup_size); - target->specializations.subgroup_size = subgroup_size; const Node* old_entry_point_decl = find_entry_point(src, config); if (old_entry_point_decl->tag != Function_TAG) @@ -124,6 +123,7 @@ Module* specialize_entry_point(const CompilerConfig* config, Module* src) { Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .config = config, }; const Node* old_entry_point_decl = find_entry_point(src, config); diff --git a/src/shady/transform/internal_constants.c b/src/shady/transform/internal_constants.c index 83257c113..18eb15e95 100644 --- a/src/shady/transform/internal_constants.c +++ b/src/shady/transform/internal_constants.c @@ -1,6 +1,7 @@ #include "internal_constants.h" #include "portability.h" +#include "ir_private.h" #include diff --git a/src/shady/transform/internal_constants.h b/src/shady/transform/internal_constants.h index 1e4d3ebda..05a7d8875 100644 --- a/src/shady/transform/internal_constants.h +++ b/src/shady/transform/internal_constants.h @@ -4,7 +4,7 @@ #include "shady/ir.h" #define INTERNAL_CONSTANTS(X) \ -X(SUBGROUP_SIZE, int32_type(arena), uint32_literal(arena, 8)) \ +X(SUBGROUP_SIZE, int32_type(arena), uint32_literal(arena, config->specialization.subgroup_size)) \ X(SUBGROUPS_PER_WG, int32_type(arena), uint32_literal(arena, 1)) \ void generate_dummy_constants(CompilerConfig* config, Module*); From 7c417b39fe38735f614bc777a004d157285dfdd7 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 26 Mar 2024 13:52:21 +0100 Subject: [PATCH 113/693] runtime_test: rename entry point to avoid issues --- src/runtime/runtime_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 301f93e9d..7db28c5e4 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -13,7 +13,7 @@ #include static const char* default_shader = -"@EntryPoint(\"Compute\") @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn main(uniform i32 a, uniform ptr global i32 b) {\n" +"@EntryPoint(\"Compute\") @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn my_kernel(uniform i32 a, uniform ptr global i32 b) {\n" " val rb = reinterpret[u64](b);\n" " debug_printf(\"hi %d 0x%lx\\n\", a, rb);\n" " return ();\n" @@ -97,7 +97,7 @@ int main(int argc, char* argv[]) { int32_t a0 = 42; uint64_t a1 = get_buffer_device_pointer(buffer); - wait_completion(launch_kernel(program, device, "main", 1, 1, 1, 2, (void*[]) { &a0, &a1 })); + wait_completion(launch_kernel(program, device, "my_kernel", 1, 1, 1, 2, (void*[]) { &a0, &a1 })); destroy_buffer(buffer); From f91a6fda2428d88c5a35efbbb2fa43b2954deeb9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 26 Mar 2024 13:52:53 +0100 Subject: [PATCH 114/693] runtime/vk: fix parameter extraction --- src/runtime/cuda/cuda_runtime_private.h | 1 - src/runtime/cuda/cuda_runtime_program.c | 1 - src/runtime/vulkan/vk_runtime_program.c | 3 ++- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index 95a312e50..92eb54e32 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -54,7 +54,6 @@ typedef struct { }; CUmodule cuda_module; CUfunction entry_point_function; - ProgramParamsInfo parameters; } CudaKernel; CudaBuffer* shd_cuda_allocate_buffer(CudaDevice*, size_t size); diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index c100898e8..c6a95610a 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -70,7 +70,6 @@ static CudaKernel* create_specialized_program(CudaDevice* device, SpecProgramKey CHECK(emit_cuda_c_code(kernel), return NULL); CHECK(cuda_c_to_ptx(kernel), return NULL); CHECK(load_ptx_into_cuda_program(kernel), return NULL); - CHECK(shd_extract_parameters_info(&kernel->parameters, kernel->final_module), return false); return kernel; } diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index ab3533ad7..8d7999d4c 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -129,7 +129,6 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay } static bool extract_layout(VkrSpecProgram* program) { - CHECK(shd_extract_parameters_info(&program->parameters, program->specialized_module), return false); if (program->parameters.args_size > program->device->caps.properties.base.properties.limits.maxPushConstantsSize) { error_print("EntryPointArgs exceed available push constant space\n"); return false; @@ -228,6 +227,8 @@ static bool compile_specialized_program(VkrSpecProgram* spec) { CHECK(run_compiler_passes(&config, &spec->specialized_module) == CompilationNoError, return false); + CHECK(shd_extract_parameters_info(&spec->parameters, spec->specialized_module), return false); + Module* final_mod; emit_spirv(&config, spec->specialized_module, &spec->spirv_size, &spec->spirv_bytes, &final_mod); spec->specialized_module = final_mod; From 058a1aef5206e63bcef00709966fc8404453cafc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 26 Mar 2024 13:53:37 +0100 Subject: [PATCH 115/693] C: fix a bunch of syntax issues --- src/runtime/cuda/cuda_runtime_program.c | 5 +++-- src/shady/emit/c/emit_c.c | 29 ++++++++++++++++--------- src/shady/emit/c/emit_c_instructions.c | 2 +- src/shady/emit/c/emit_c_signatures.c | 10 ++++++--- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index c6a95610a..d90ab231e 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -15,12 +15,12 @@ static bool emit_cuda_c_code(CudaKernel* spec) { CompilerConfig config = get_compiler_config_for_device(spec->device, spec->key.base->base_config); config.specialization.entry_point = spec->key.entry_point; - Module* dst_mod; + Module* dst_mod = spec->key.base->module; CHECK(run_compiler_passes(&config, &dst_mod) == CompilationNoError, return false); CEmitterConfig emitter_config = { .dialect = CDialect_CUDA, - .explicitly_sized_types = true, + .explicitly_sized_types = false, .allow_compound_literals = true, }; Module* final_mod; @@ -35,6 +35,7 @@ static bool cuda_c_to_ptx(CudaKernel* kernel) { nvrtcResult compile_result = nvrtcCompileProgram(program, 0, false); if (compile_result != NVRTC_SUCCESS) { error_print("NVRTC compilation failed: %s\n", nvrtcGetErrorString(compile_result)); + debug_print("Dumping source:\n%s", kernel->cuda_code); } size_t log_size; diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index e410f4a3f..ca675d611 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -135,15 +135,15 @@ static void emit_global_variable_definition(Emitter* emitter, String prefix, Str } if (init) - print(emitter->fn_defs, "\n%s%s = %s;", prefix, emit_type(emitter, type, decl_center), init); + print(emitter->fn_decls, "\n%s%s = %s;", prefix, emit_type(emitter, type, decl_center), init); else - print(emitter->fn_defs, "\n%s%s;", prefix, emit_type(emitter, type, decl_center)); + print(emitter->fn_decls, "\n%s%s;", prefix, emit_type(emitter, type, decl_center)); - if (!has_forward_declarations(emitter->config.dialect) || !init) - return; - - String declaration = emit_type(emitter, type, decl_center); - print(emitter->fn_decls, "\n%s;", declaration); + //if (!has_forward_declarations(emitter->config.dialect) || !init) + // return; + // + //String declaration = emit_type(emitter, type, decl_center); + //print(emitter->fn_decls, "\n%s;", declaration); } CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { @@ -550,7 +550,15 @@ void emit_decl(Emitter* emitter, const Node* decl) { break; case AsPrivatePhysical: case AsPrivateLogical: - address_space_prefix = ""; + switch (emitter->config.dialect) { + case CDialect_CUDA: + address_space_prefix = "__device__ "; + break; + default: + address_space_prefix = ""; + break; + } + break; case AsGlobalLogical: case AsGlobalPhysical: address_space_prefix = ""; @@ -612,7 +620,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { for (size_t i = 0; i < decl->payload.fun.params.count; i++) { String param_name; String variable_name = get_value_name(decl->payload.fun.params.nodes[i]); - param_name = unique_name(emitter->arena, legalize_c_identifier(emitter, variable_name)); + param_name = format_string_interned(emitter->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); register_emitted(emitter, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } @@ -735,7 +743,8 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, switch (emitter.config.dialect) { case CDialect_ISPC: break; - case CDialect_CUDA: /* TODO: probably don't wanna do this */ + case CDialect_CUDA: + break; case CDialect_C11: print(finalp, "\n#include "); print(finalp, "\n#include "); diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 2c4fb03b4..e819481d3 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -409,7 +409,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct String dst = unique_name(arena, "bitcast_result"); print(p, "\n%s = %s;", emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); print(p, "\n%s;", emit_type(emitter, dst_type, dst)); - print(p, "\nmemcpy(&%s, &s, sizeof(%s));", dst, src, src); + print(p, "\nmemcpy(&%s, &%s, sizeof(%s));", dst, src, src); outputs.results[0] = term_from_cvalue(dst); outputs.binding[0] = NoBinding; break; diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index c133040d8..c09b058d4 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -59,7 +59,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const for (size_t i = 0; i < dom.count; i++) { String param_name; String variable_name = get_value_name(fn->payload.fun.params.nodes[i]); - param_name = unique_name(emitter->arena, legalize_c_identifier(emitter, variable_name)); + param_name = format_string_interned(emitter->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); print(paramp, emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { print(paramp, ", "); @@ -90,7 +90,8 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const String c_decl = emit_type(emitter, wrap_multiple_yield_types(emitter->arena, codom), center); const Node* entry_point = fn ? lookup_annotation(fn, "EntryPoint") : NULL; - if (entry_point) switch (emitter->config.dialect) { + if (entry_point) { + switch (emitter->config.dialect) { case CDialect_C11: break; case CDialect_GLSL: @@ -98,9 +99,12 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const case CDialect_ISPC: c_decl = format_string_arena(emitter->arena->arena, "export %s", c_decl); case CDialect_CUDA: - c_decl = format_string_arena(emitter->arena->arena, "__kernel__ %s", c_decl); + c_decl = format_string_arena(emitter->arena->arena, "extern \"C\" __global__ %s", c_decl); break; } + } else if (emitter->config.dialect == CDialect_CUDA) { + c_decl = format_string_arena(emitter->arena->arena, "__device__ %s", c_decl); + } return c_decl; } From a1821c008205a57cdd311a239a1d03f568334802 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 27 Mar 2024 11:40:00 +0100 Subject: [PATCH 116/693] runtime: revert 874cf998e57ac77ff77e6b8f9e256b5e79fff268 --- src/runtime/runtime_private.h | 2 - src/runtime/runtime_program.c | 103 ---------------------- src/runtime/vulkan/vk_runtime_program.c | 108 +++++++++++++++++++++++- 3 files changed, 106 insertions(+), 107 deletions(-) diff --git a/src/runtime/runtime_private.h b/src/runtime/runtime_private.h index a3f626e3d..a20803d0c 100644 --- a/src/runtime/runtime_private.h +++ b/src/runtime/runtime_private.h @@ -51,8 +51,6 @@ struct Program_ { Module* module; }; -bool shd_extract_parameters_info(ProgramParamsInfo* info, Module* mod); - struct Command_ { bool (*wait_for_completion)(Command*); }; diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index 076b4b274..5f811b236 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -58,106 +58,3 @@ void unload_program(Program* program) { destroy_ir_arena(program->arena); free(program); } - -bool shd_extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) { - Nodes decls = get_module_declarations(mod); - - const Node* args_struct_annotation; - const Node* args_struct_type = NULL; - const Node* entry_point_function = NULL; - - for (int i = 0; i < decls.count; ++i) { - const Node* node = decls.nodes[i]; - - switch (node->tag) { - case GlobalVariable_TAG: { - const Node* entry_point_args_annotation = lookup_annotation(node, "EntryPointArgs"); - if (entry_point_args_annotation) { - if (node->payload.global_variable.type->tag != RecordType_TAG) { - error_print("EntryPointArgs must be a struct\n"); - return false; - } - - if (args_struct_type) { - error_print("there cannot be more than one EntryPointArgs\n"); - return false; - } - - args_struct_annotation = entry_point_args_annotation; - args_struct_type = node->payload.global_variable.type; - } - break; - } - case Function_TAG: { - if (lookup_annotation(node, "EntryPoint")) { - if (node->payload.fun.params.count != 0) { - error_print("EntryPoint cannot have parameters\n"); - return false; - } - - if (entry_point_function) { - error_print("there cannot be more than one EntryPoint\n"); - return false; - } - - entry_point_function = node; - } - break; - } - default: break; - } - } - - if (!entry_point_function) { - error_print("could not find EntryPoint\n"); - return false; - } - - if (!args_struct_type) { - *parameters = (ProgramParamsInfo) { .num_args = 0 }; - return true; - } - - if (args_struct_annotation->tag != AnnotationValue_TAG) { - error_print("EntryPointArgs annotation must contain exactly one value\n"); - return false; - } - - const Node* annotation_fn = args_struct_annotation->payload.annotation_value.value; - assert(annotation_fn->tag == FnAddr_TAG); - if (annotation_fn->payload.fn_addr.fn != entry_point_function) { - error_print("EntryPointArgs annotation refers to different EntryPoint\n"); - return false; - } - - size_t num_args = args_struct_type->payload.record_type.members.count; - - if (num_args == 0) { - error_print("EntryPointArgs cannot be empty\n"); - return false; - } - - IrArena* a = get_module_arena(mod); - - LARRAY(FieldLayout, fields, num_args); - get_record_layout(a, args_struct_type, fields); - - size_t* offset_size_buffer = calloc(1, 2 * num_args * sizeof(size_t)); - if (!offset_size_buffer) { - error_print("failed to allocate EntryPointArgs offsets and sizes array\n"); - return false; - } - size_t* offsets = offset_size_buffer; - size_t* sizes = offset_size_buffer + num_args; - - for (int i = 0; i < num_args; ++i) { - offsets[i] = fields[i].offset_in_bytes; - sizes[i] = fields[i].mem_layout.size_in_bytes; - } - - parameters->num_args = num_args; - parameters->arg_offset = offsets; - parameters->arg_size = sizes; - parameters->args_size = offsets[num_args - 1] + sizes[num_args - 1]; - return true; -} diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 8d7999d4c..7dd44194e 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -221,16 +221,120 @@ static CompilerConfig get_compiler_config_for_device(VkrDevice* device, const Co return config; } +static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) { + Nodes decls = get_module_declarations(mod); + + const Node* args_struct_annotation; + const Node* args_struct_type = NULL; + const Node* entry_point_function = NULL; + + for (int i = 0; i < decls.count; ++i) { + const Node* node = decls.nodes[i]; + + switch (node->tag) { + case GlobalVariable_TAG: { + const Node* entry_point_args_annotation = lookup_annotation(node, "EntryPointArgs"); + if (entry_point_args_annotation) { + if (node->payload.global_variable.type->tag != RecordType_TAG) { + error_print("EntryPointArgs must be a struct\n"); + return false; + } + + if (args_struct_type) { + error_print("there cannot be more than one EntryPointArgs\n"); + return false; + } + + args_struct_annotation = entry_point_args_annotation; + args_struct_type = node->payload.global_variable.type; + } + break; + } + case Function_TAG: { + if (lookup_annotation(node, "EntryPoint")) { + if (node->payload.fun.params.count != 0) { + error_print("EntryPoint cannot have parameters\n"); + return false; + } + + if (entry_point_function) { + error_print("there cannot be more than one EntryPoint\n"); + return false; + } + + entry_point_function = node; + } + break; + } + default: break; + } + } + + if (!entry_point_function) { + error_print("could not find EntryPoint\n"); + return false; + } + + if (!args_struct_type) { + *parameters = (ProgramParamsInfo) { .num_args = 0 }; + return true; + } + + if (args_struct_annotation->tag != AnnotationValue_TAG) { + error_print("EntryPointArgs annotation must contain exactly one value\n"); + return false; + } + + const Node* annotation_fn = args_struct_annotation->payload.annotation_value.value; + assert(annotation_fn->tag == FnAddr_TAG); + if (annotation_fn->payload.fn_addr.fn != entry_point_function) { + error_print("EntryPointArgs annotation refers to different EntryPoint\n"); + return false; + } + + size_t num_args = args_struct_type->payload.record_type.members.count; + + if (num_args == 0) { + error_print("EntryPointArgs cannot be empty\n"); + return false; + } + + IrArena* a = get_module_arena(mod); + + LARRAY(FieldLayout, fields, num_args); + get_record_layout(a, args_struct_type, fields); + + size_t* offset_size_buffer = calloc(1, 2 * num_args * sizeof(size_t)); + if (!offset_size_buffer) { + error_print("failed to allocate EntryPointArgs offsets and sizes array\n"); + return false; + } + size_t* offsets = offset_size_buffer; + size_t* sizes = offset_size_buffer + num_args; + + for (int i = 0; i < num_args; ++i) { + offsets[i] = fields[i].offset_in_bytes; + sizes[i] = fields[i].mem_layout.size_in_bytes; + } + + parameters->num_args = num_args; + parameters->arg_offset = offsets; + parameters->arg_size = sizes; + parameters->args_size = offsets[num_args - 1] + sizes[num_args - 1]; + return true; +} + static bool compile_specialized_program(VkrSpecProgram* spec) { CompilerConfig config = get_compiler_config_for_device(spec->device, spec->key.base->base_config); config.specialization.entry_point = spec->key.entry_point; CHECK(run_compiler_passes(&config, &spec->specialized_module) == CompilationNoError, return false); - CHECK(shd_extract_parameters_info(&spec->parameters, spec->specialized_module), return false); - Module* final_mod; emit_spirv(&config, spec->specialized_module, &spec->spirv_size, &spec->spirv_bytes, &final_mod); + + CHECK(extract_parameters_info(&spec->parameters, final_mod), return false); + spec->specialized_module = final_mod; if (spec->key.base->runtime->config.dump_spv) { From 82c418edb3645fe460186597ce72b79a5752a0ec Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 27 Mar 2024 11:40:10 +0100 Subject: [PATCH 117/693] samples/aobench: do not force the log level --- samples/aobench/ao_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 82980a730..16ae8c28d 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -97,11 +97,9 @@ void render_device(const CompilerConfig* compiler_config, unsigned char *img, in } } - set_log_level(INFO); - RuntimeConfig runtime_config = (RuntimeConfig) { - .use_validation = true, - .dump_spv = true, + .use_validation = true, + .dump_spv = true, }; info_print("Shady checkerboard test starting...\n"); From 44122a4c3988fd7cd48d61fcd09d120346ac3cd6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 27 Mar 2024 14:05:01 +0100 Subject: [PATCH 118/693] emit_c: refactor how globals are emitted --- src/common/log.h | 7 ++ src/runtime/cuda/cuda_runtime_program.c | 2 +- src/shady/emit/c/emit_c.c | 153 ++++++++++-------------- src/shady/emit/c/emit_c.h | 3 + 4 files changed, 75 insertions(+), 90 deletions(-) diff --git a/src/common/log.h b/src/common/log.h index dc18de3d9..037f3223d 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -29,6 +29,13 @@ void log_module(LogLevel level, CompilerConfig*, Module*); #define warn_print(...) log_string(WARN, __VA_ARGS__) #define error_print(...) log_string(ERROR, __VA_ARGS__) +#define debugvv_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; debugvv_print(__VA_ARGS__ ); } } +#define debugv_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; debugv_print(__VA_ARGS__ ); } } +#define debug_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; debug_print(__VA_ARGS__ ); } } +#define info_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; info_print(__VA_ARGS__ ); } } +#define warn_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; warn_print(__VA_ARGS__ ); } } +#define error_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; error_print(__VA_ARGS__ ); } } + #ifdef _MSC_VER #define SHADY_UNREACHABLE __assume(0) #else diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index d90ab231e..0c8f58205 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -21,7 +21,7 @@ static bool emit_cuda_c_code(CudaKernel* spec) { CEmitterConfig emitter_config = { .dialect = CDialect_CUDA, .explicitly_sized_types = false, - .allow_compound_literals = true, + .allow_compound_literals = false, }; Module* final_mod; emit_c(config, emitter_config, dst_mod, &spec->cuda_code_size, &spec->cuda_code, &final_mod); diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index ca675d611..58456e413 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -113,27 +113,76 @@ static bool has_forward_declarations(CDialect dialect) { } } -static void emit_global_variable_definition(Emitter* emitter, String prefix, String decl_center, const Type* type, bool uniform, bool constant, String init) { +static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, String decl_center, const Type* type, bool constant, String init) { + String prefix = NULL; + // GLSL wants 'const' to go on the left to start the declaration, but in C const should go on the right (east const convention) switch (emitter->config.dialect) { - // ISPC defaults to varying, even for constants... yuck + case CDialect_C11: { + if (as != AsGeneric) warn_print_once(c11_non_generic_as, "warning: standard C does not have address spaces\n"); + prefix = ""; + if (constant) + decl_center = format_string_arena(emitter->arena->arena, "const %s", decl_center); + break; + } case CDialect_ISPC: - if (uniform) - decl_center = format_string_arena(emitter->arena->arena, "uniform %s", decl_center); - else - decl_center = format_string_arena(emitter->arena->arena, "varying %s", decl_center); + // ISPC doesn't really do address space qualifiers. + prefix = ""; break; - case CDialect_C11: case CDialect_CUDA: - if (constant) - decl_center = format_string_arena(emitter->arena->arena, "const %s", decl_center); + switch (as) { + case AsPrivateLogical: + case AsPrivatePhysical: prefix = "__device__ "; break; + case AsSharedPhysical: + case AsSharedLogical: prefix = "__shared__ "; break; + case AsGlobalLogical: + case AsGlobalPhysical: { + if (constant) + prefix = "__constant__ "; + else + prefix = "__device__ __managed__ "; + break; + } + default: { + prefix = format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); + warn_print("warning: address space %s not supported in CUDA for global variables\n", get_address_space_name(as)); + break; + } + } break; case CDialect_GLSL: - if (constant) - prefix = format_string_arena(emitter->arena->arena, "%s %s", "const", prefix); + switch (as) { + case AsSharedLogical: prefix = "shared "; break; + case AsInput: + case AsUInput: prefix = "in "; break; + case AsOutput: prefix = "out "; break; + case AsPrivateLogical: prefix = ""; break; + case AsUniformConstant: prefix = "uniform"; break; + case AsGlobalLogical: { + assert(constant && "Only constants are supported"); + prefix = "const "; + break; + } + default: { + prefix = format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); + warn_print("warning: address space %s not supported in GLSL for global variables\n", get_address_space_name(as)); + break; + } + } break; } + assert(prefix); + + // ISPC wants uniform/varying annotations + if (emitter->config.dialect == CDialect_ISPC) { + bool uniform = is_addr_space_uniform(emitter->arena, as); + if (uniform) + decl_center = format_string_arena(emitter->arena->arena, "uniform %s", decl_center); + else + decl_center = format_string_arena(emitter->arena->arena, "varying %s", decl_center); + } + if (init) print(emitter->fn_decls, "\n%s%s = %s;", prefix, emit_type(emitter, type, decl_center), init); else @@ -199,7 +248,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { if (emitter->config.dialect == CDialect_GLSL) return emit_value(emitter, block_printer, get_default_zero_value(emitter->arena, value->payload.undef.type)); String name = unique_name(emitter->arena, "undef"); - emit_global_variable_definition(emitter, "", name, value->payload.undef.type, true, true, NULL); + emit_global_variable_definition(emitter, AsGlobalLogical, name, value->payload.undef.type, true, NULL); emitted = name; break; } @@ -531,84 +580,10 @@ void emit_decl(Emitter* emitter, const Node* decl) { // we emit the global variable as a CVar, so we can refer to it's 'address' without explicit ptrs emit_as = term_from_cvar(name); - bool uniform = is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space); - - String address_space_prefix = NULL; - switch (decl->payload.global_variable.address_space) { - case AsGeneric: - break; - case AsSubgroupLogical: - case AsSubgroupPhysical: - switch (emitter->config.dialect) { - default: - warn_print("Non-ISPC dialects of C do not have a 'subgroup' level addressing space, using shared instead"); - goto case_shared; - case CDialect_ISPC: - address_space_prefix = ""; - break; - } - break; - case AsPrivatePhysical: - case AsPrivateLogical: - switch (emitter->config.dialect) { - case CDialect_CUDA: - address_space_prefix = "__device__ "; - break; - default: - address_space_prefix = ""; - break; - } - break; - case AsGlobalLogical: - case AsGlobalPhysical: - address_space_prefix = ""; - break; - case_shared: - case AsSharedPhysical: - case AsSharedLogical: - switch (emitter->config.dialect) { - case CDialect_C11: - break; - case CDialect_CUDA: - address_space_prefix = "__shared__ "; - break; - case CDialect_GLSL: - address_space_prefix = "shared "; - break; - case CDialect_ISPC: - // ISPC doesn't really know what "shared" is - break; - } - break; - - case AsExternal: - address_space_prefix = "extern "; - break; - case AsInput: - case AsUInput: - address_space_prefix = "in "; - break; - case AsOutput: - address_space_prefix = "out "; - break; - case AsUniform: - case AsImage: - case AsUniformConstant: - case AsShaderStorageBufferObject: - case AsFunctionLogical: - case AsPushConstant: - break; // error("These only make sense for SPIR-V !") - default: error("Unhandled address space"); - } - - if (!address_space_prefix) { - warn_print("No known address space prefix for as %d, this might produce broken code\n", decl->payload.global_variable.address_space); - address_space_prefix = ""; - } - register_emitted(emitter, decl, emit_as); - emit_global_variable_definition(emitter, address_space_prefix, decl_center, decl_type, uniform, false, init); + AddressSpace as = decl->payload.global_variable.address_space; + emit_global_variable_definition(emitter, as, decl_center, decl_type, false, init); return; } case Function_TAG: { @@ -646,7 +621,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { const Node* init_value = get_quoted_value(decl->payload.constant.instruction); assert(init_value && "TODO: support some measure of constant expressions"); String init = to_cvalue(emitter, emit_value(emitter, NULL, init_value)); - emit_global_variable_definition(emitter, "", decl_center, decl->type, true, true, init); + emit_global_variable_definition(emitter, AsGlobalLogical, decl_center, decl->type, true, init); return; } case NominalType_TAG: { diff --git a/src/shady/emit/c/emit_c.h b/src/shady/emit/c/emit_c.h index 48e37725c..0054f64dc 100644 --- a/src/shady/emit/c/emit_c.h +++ b/src/shady/emit/c/emit_c.h @@ -28,6 +28,8 @@ typedef struct { #define term_from_cvalue(t) (CTerm) { .value = t } #define term_from_cvar(t) (CTerm) { .var = t } +#define empty_term() (CTerm) { 0 } +#define is_term_empty(t) (!t.var && !t.value) typedef Strings Phis; @@ -56,6 +58,7 @@ void emit_decl(Emitter* emitter, const Node* decl); CType emit_type(Emitter* emitter, const Type*, const char* identifier); String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn); void emit_nominal_type_body(Emitter* emitter, String name, const Type* type); + void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer); CTerm emit_value(Emitter* emitter, Printer*, const Node* value); From 1077c8bdb6a1f99afcff8422df8ba7852b819f10 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 27 Mar 2024 14:06:10 +0100 Subject: [PATCH 119/693] split get_builtin and get_or_create_builtin --- src/shady/emit/spirv/emit_spv_instructions.c | 2 +- src/shady/passes/lower_workgroups.c | 12 ++++++------ src/shady/transform/ir_gen_helpers.c | 14 +++++++++++--- src/shady/transform/ir_gen_helpers.h | 3 ++- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/shady/emit/spirv/emit_spv_instructions.c b/src/shady/emit/spirv/emit_spv_instructions.c index c620f857e..1deedb0b4 100644 --- a/src/shady/emit/spirv/emit_spv_instructions.c +++ b/src/shady/emit/spirv/emit_spv_instructions.c @@ -237,7 +237,7 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { SpvId local_id; - const Node* b = ref_decl_helper(emitter->arena, get_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); + const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); emit_primop(emitter, fn_builder, bb_builder, prim_op(emitter->arena, (PrimOp) { .op = load_op, .operands = singleton(b) }), 1, &local_id); result = spvb_group_shuffle(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), scope_subgroup, emit_value(emitter, bb_builder, first(args)), local_id); spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index d84cd14a0..1de0e5db7 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -39,7 +39,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return get_builtin(ctx->rewriter.dst_module, b, get_declaration_name(node)); + return get_or_create_builtin(ctx->rewriter.dst_module, b, get_declaration_name(node)); } break; } @@ -64,7 +64,7 @@ static const Node* process(Context* ctx, const Node* node) { inner->payload.fun.body = recreate_node_identity(&ctx->rewriter, node->payload.fun.body); BodyBuilder* bb = begin_body(a); - const Node* num_workgroups_var = rewrite_node(&ctx->rewriter, get_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); + const Node* num_workgroups_var = rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); const Node* workgroup_num_vec3 = gen_load(bb, ref_decl_helper(a, num_workgroups_var)); // prepare variables for iterating over workgroups @@ -93,19 +93,19 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb2 = begin_body(a); // write the workgroup ID - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); + gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); // write the local ID const Node* local_id[3]; // local_id[0] = SUBGROUP_SIZE * subgroup_id[0] + subgroup_local_id local_id[0] = gen_primop_e(bb2, add_op, empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, empty(a), mk_nodes(a, uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); local_id[1] = subgroup_id[1]; local_id[2] = subgroup_id[2]; - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); + gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); // write the global ID const Node* global_id[3]; for (int dim = 0; dim < 3; dim++) global_id[dim] = gen_primop_e(bb2, add_op, empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, empty(a), mk_nodes(a, uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); + gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID bind_instruction(bb2, call(a, (Call) { .callee = fn_addr_helper(a, inner), .args = wparams })); @@ -153,7 +153,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* ptr = first(node->payload.prim_op.operands); if (ptr->tag == RefDecl_TAG) ptr = ptr->payload.ref_decl.decl; - if (ptr == get_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { + if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { BodyBuilder* bb = begin_body(a); const Node* loaded = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); const Node* uniformized = first(gen_primop(bb, subgroup_broadcast_first_op, empty(a), singleton(loaded))); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index b935873ec..1042b0149 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -111,7 +111,7 @@ void gen_comment(BodyBuilder* bb, String str) { bind_instruction(bb, comment(bb->arena, (Comment) { .string = str })); } -const Node* get_builtin(Module* m, Builtin b, String n) { +const Node* get_builtin(Module* m, Builtin b) { Nodes decls = get_module_declarations(m); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; @@ -126,14 +126,22 @@ const Node* get_builtin(Module* m, Builtin b, String n) { return decl; } + return NULL; +} + +const Node* get_or_create_builtin(Module* m, Builtin b, String n) { + const Node* decl = get_builtin(m, b); + if (decl) + return decl; + AddressSpace as = get_builtin_as(b); IrArena* a = get_module_arena(m); - Node* decl = global_var(m, singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, get_builtin_name(b)))), get_builtin_type(a, b), n ? n : format_string_arena(a->arena, "builtin_%s", get_builtin_name(b)), as); + decl = global_var(m, singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, get_builtin_name(b)))), get_builtin_type(a, b), n ? n : format_string_arena(a->arena, "builtin_%s", get_builtin_name(b)), as); return decl; } const Node* gen_builtin_load(Module* m, BodyBuilder* bb, Builtin b) { - return gen_load(bb, ref_decl_helper(bb->arena, get_builtin(m, b, NULL))); + return gen_load(bb, ref_decl_helper(bb->arena, get_or_create_builtin(m, b, NULL))); } bool is_builtin_load_op(const Node* n, Builtin* out) { diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index a6692a86a..daeffc1ee 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -23,7 +23,8 @@ void gen_store(BodyBuilder*, const Node* ptr, const Node* value); const Node* gen_lea(BodyBuilder*, const Node* base, const Node* offset, Nodes selectors); const Node* gen_extract(BodyBuilder*, const Node* base, Nodes selectors); void gen_comment(BodyBuilder*, String str); -const Node* get_builtin(Module* m, Builtin b, String n); +const Node* get_builtin(Module* m, Builtin b); +const Node* get_or_create_builtin(Module* m, Builtin b, String n); const Node* gen_builtin_load(Module*, BodyBuilder*, Builtin); typedef struct Rewriter_ Rewriter; From d4e7ada751f0813087652cbab20a99535d038fa0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 27 Mar 2024 16:09:45 +0100 Subject: [PATCH 120/693] emit_c: support decaying ptrs to zero-sized arrays --- include/shady/ir.h | 1 + src/runtime/cuda/cuda_runtime_program.c | 1 + src/shady/emit/c/emit_c_instructions.c | 23 ++++++++++++++--------- src/shady/emit/c/emit_c_signatures.c | 5 ++++- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 68e09c141..3344c14f2 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -335,6 +335,7 @@ typedef struct { CDialect dialect; bool explicitly_sized_types; bool allow_compound_literals; + bool decay_unsized_arrays; } CEmitterConfig; void emit_c(CompilerConfig compiler_config, CEmitterConfig emitter_config, Module*, size_t* output_size, char** output, Module** new_mod); diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 0c8f58205..da4622207 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -22,6 +22,7 @@ static bool emit_cuda_c_code(CudaKernel* spec) { .dialect = CDialect_CUDA, .explicitly_sized_types = false, .allow_compound_literals = false, + .decay_unsized_arrays = true, }; Module* final_mod; emit_c(config, emitter_config, dst_mod, &spec->cuda_code_size, &spec->cuda_code, &final_mod); diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index e819481d3..ee1b2158d 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -195,6 +195,16 @@ static const ISelTableEntry* lookup_entry(Emitter* emitter, Op op) { return isel_entry; } +static String index_into_array(Emitter* emitter, const Type* arr_type, CTerm expr, CTerm index) { + IrArena* arena = emitter->arena; + + String index2 = emitter->config.dialect == CDialect_GLSL ? format_string_arena(arena->arena, "int(%s)", to_cvalue(emitter, index)) : to_cvalue(emitter, index); + if (emitter->config.decay_unsized_arrays && !arr_type->payload.arr_type.size) + return format_string_arena(arena->arena, "((&%s)[%s])", deref_term(emitter, expr), index2); + else + return format_string_arena(arena->arena, "(%s.arr[%s])", deref_term(emitter, expr), index2); +} + static void emit_primop(Emitter* emitter, Printer* p, const Node* node, InstructionOutputs outputs) { assert(node->tag == PrimOp_TAG); IrArena* arena = emitter->arena; @@ -296,7 +306,8 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct // we sadly need to drop to the value level (aka explicit pointer arithmetic) to do this // this means such code is never going to be legal in GLSL // also the cast is to account for our arrays-in-structs hack - acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &(%s.arr[%s]))", emit_type(emitter, curr_ptr_type, NULL), deref_term(emitter, acc), to_cvalue(emitter, offset))); + const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); + acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &%s)", emit_type(emitter, curr_ptr_type, NULL), index_into_array(emitter, pointee_type, acc, offset))); uniform &= is_qualified_type_uniform(prim_op->operands.nodes[1]->type); } @@ -308,10 +319,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct switch (is_type(pointee_type)) { case ArrType_TAG: { CTerm index = emit_value(emitter, p, selector); - if (emitter->config.dialect == CDialect_GLSL) - acc = term_from_cvar(format_string_arena(arena->arena, "(%s.arr[int(%s)])", deref_term(emitter, acc), to_cvalue(emitter, index))); - else - acc = term_from_cvar(format_string_arena(arena->arena, "(%s.arr[%s])", deref_term(emitter, acc), to_cvalue(emitter, index))); + acc = term_from_cvar(index_into_array(emitter, pointee_type, acc, index)); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.arr_type.element_type, .address_space = curr_ptr_type->payload.ptr_type.address_space @@ -522,10 +530,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct break; } case Type_ArrType_TAG: { - if (emitter->config.dialect == CDialect_GLSL) - acc = format_string_arena(emitter->arena->arena, "(%s.arr[int(%s)])", acc, to_cvalue(emitter, emit_value(emitter, p, index))); - else - acc = format_string_arena(emitter->arena->arena, "(%s.arr[%s])", acc, to_cvalue(emitter, emit_value(emitter, p, index))); + acc = index_into_array(emitter, t, term_from_cvar(acc), emit_value(emitter, p, index)); break; } default: diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index c09b058d4..0895168a4 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -231,9 +231,12 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { Growy* g = new_growy(); Printer* p = open_growy_as_printer(g); + const Node* size = type->payload.arr_type.size; + if (!size && emitter->config.decay_unsized_arrays) + return emit_type(emitter, type->payload.arr_type.element_type, center); + print(p, "\n%s {", prefixed); indent(p); - const Node* size = type->payload.arr_type.size; String inner_decl_rhs; if (size) inner_decl_rhs = format_string_arena(emitter->arena->arena, "arr[%zu]", get_int_literal_value(*resolve_to_int_literal(size), false)); From c4988ff06b3fc2a18c6725072c0d593ffc79b261 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 27 Mar 2024 16:11:12 +0100 Subject: [PATCH 121/693] cuda: deploy rather severe hacks to make private memory work --- src/shady/emit/c/CMakeLists.txt | 5 ++++ src/shady/emit/c/cuda_builtins.cu | 14 +++++++++++ src/shady/emit/c/cuda_prelude.cu | 2 ++ src/shady/emit/c/emit_c.c | 42 ++++++++++++++++++++++++++++--- src/shady/emit/c/emit_c.h | 2 ++ 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 src/shady/emit/c/cuda_builtins.cu create mode 100644 src/shady/emit/c/cuda_prelude.cu diff --git a/src/shady/emit/c/CMakeLists.txt b/src/shady/emit/c/CMakeLists.txt index b39d1a1c8..5f904a7ad 100644 --- a/src/shady/emit/c/CMakeLists.txt +++ b/src/shady/emit/c/CMakeLists.txt @@ -10,3 +10,8 @@ target_include_directories(shady_c PUBLIC $") target_link_libraries(shady_c PUBLIC "$") + +embed_file(string shady_cuda_prelude_src cuda_prelude.cu) +embed_file(string shady_cuda_builtins_src cuda_builtins.cu) +target_link_libraries(shady_c PRIVATE "$") +target_link_libraries(shady_c PRIVATE "$") \ No newline at end of file diff --git a/src/shady/emit/c/cuda_builtins.cu b/src/shady/emit/c/cuda_builtins.cu new file mode 100644 index 000000000..38a7c2ec2 --- /dev/null +++ b/src/shady/emit/c/cuda_builtins.cu @@ -0,0 +1,14 @@ +__shared__ uvec3 __shady_make_thread_local(RealGlobalInvocationId); +__shared__ uvec3 __shady_make_thread_local(RealLocalInvocationId); + +#define GlobalInvocationId __shady_thread_local_access(RealGlobalInvocationId) +#define LocalInvocationId __shady_thread_local_access(RealLocalInvocationId) + +__device__ void __shady_prepare_builtins() { + LocalInvocationId.arr[0] = threadIdx.x; + LocalInvocationId.arr[1] = threadIdx.y; + LocalInvocationId.arr[2] = threadIdx.z; + GlobalInvocationId.arr[0] = threadIdx.x + blockDim.x * blockIdx.x; + GlobalInvocationId.arr[1] = threadIdx.y + blockDim.y * blockIdx.y; + GlobalInvocationId.arr[2] = threadIdx.z + blockDim.z * blockIdx.z; +} diff --git a/src/shady/emit/c/cuda_prelude.cu b/src/shady/emit/c/cuda_prelude.cu new file mode 100644 index 000000000..4f5279034 --- /dev/null +++ b/src/shady/emit/c/cuda_prelude.cu @@ -0,0 +1,2 @@ +#define __shady_make_thread_local(var) var[__shady_workgroup_size] +#define __shady_thread_local_access(var) (var[((threadIdx.x * blockDim.y + threadIdx.y) * blockDim.z + threadIdx.z)]) diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 58456e413..1794082ec 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -1,5 +1,8 @@ #include "emit_c.h" +#include "shady_cuda_prelude_src.h" +#include "shady_cuda_builtins_src.h" + #include "portability.h" #include "dict.h" #include "log.h" @@ -132,7 +135,11 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S case CDialect_CUDA: switch (as) { case AsPrivateLogical: - case AsPrivatePhysical: prefix = "__device__ "; break; + case AsPrivatePhysical: + // Note: this requires many hacks. + prefix = "__shared__ "; + decl_center = format_string_arena(emitter->arena->arena, "__shady_make_thread_local(%s)", decl_center); + break; case AsSharedPhysical: case AsSharedLogical: prefix = "__shared__ "; break; case AsGlobalLogical: @@ -572,14 +579,20 @@ void emit_decl(Emitter* emitter, const Node* decl) { const GlobalVariable* gvar = &decl->payload.global_variable; if (is_decl_builtin(decl)) { Builtin b = get_decl_builtin(decl); - register_emitted(emitter, decl, emit_c_builtin(emitter, b)); + CTerm t = emit_c_builtin(emitter, b); + register_emitted(emitter, decl, t); return; } decl_type = decl->payload.global_variable.type; // we emit the global variable as a CVar, so we can refer to it's 'address' without explicit ptrs emit_as = term_from_cvar(name); - + if ((decl->payload.global_variable.address_space == AsPrivatePhysical || decl->payload.global_variable.address_space == AsPrivateLogical) && emitter->config.dialect == CDialect_CUDA) { + // HACK + emit_as = term_from_cvar(format_string_interned(emitter->arena, "__shady_thread_local_access(%s)", name)); + if (init) + init = format_string_interned(emitter->arena, "__shady_replicate_thread_local(%s)", init); + } register_emitted(emitter, decl, emit_as); AddressSpace as = decl->payload.global_variable.address_space; @@ -606,6 +619,8 @@ void emit_decl(Emitter* emitter, const Node* decl) { // therefore we must tell ISPC to please, pretty please, mask everything by branching on what the mask should be fn_body = format_string_arena(emitter->arena->arena, "if ((lanemask() >> programIndex) & 1u) { %s}", fn_body); // I hate everything about this too. + } else if (emitter->config.dialect == CDialect_CUDA) { + fn_body = format_string_arena(emitter->arena->arena, "__shady_prepare_builtins();\n%s", fn_body); } print(emitter->fn_defs, "\n%s { %s }", head, fn_body); free_tmp_str(free_me); @@ -698,6 +713,18 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, .emitted_types = new_dict(Node*, String, (HashFn) hash_node, (CmpFn) compare_node), }; + // builtins magic (hack) for CUDA + if (emitter.config.dialect == CDialect_CUDA) { + emitter.total_workgroup_size = emitter.arena->config.specializations.workgroup_size[0]; + emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[1]; + emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[2]; + print(emitter.type_decls, "\ntypedef %s;\n", emit_type(&emitter, arr_type(arena, (ArrType) { + .size = int32_literal(arena, 3), + .element_type = uint32_type(arena) + }), "uvec3")); + print(emitter.fn_defs, shady_cuda_builtins_src); + } + Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) emit_decl(&emitter, decls.nodes[i]); @@ -718,8 +745,15 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, switch (emitter.config.dialect) { case CDialect_ISPC: break; - case CDialect_CUDA: + case CDialect_CUDA: { + print(finalp, "#define __shady_workgroup_size %d\n", emitter.total_workgroup_size); + print(finalp, "#define __shady_replicate_thread_local(v) { "); + for (size_t i = 0; i < emitter.total_workgroup_size; i++) + print(finalp, "v, "); + print(finalp, "}\n"); + print(finalp, shady_cuda_prelude_src); break; + } case CDialect_C11: print(finalp, "\n#include "); print(finalp, "\n#include "); diff --git a/src/shady/emit/c/emit_c.h b/src/shady/emit/c/emit_c.h index 0054f64dc..c285e999f 100644 --- a/src/shady/emit/c/emit_c.h +++ b/src/shady/emit/c/emit_c.h @@ -43,6 +43,8 @@ typedef struct { struct Dict* emitted_terms; struct Dict* emitted_types; + + int total_workgroup_size; } Emitter; void register_emitted(Emitter*, const Node*, CTerm); From e91f1fae9ee91030b1eab893d7f737304489e136 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 27 Mar 2024 19:32:43 +0100 Subject: [PATCH 122/693] cuda: ugly hack to pass arround a struct containing globals --- src/common/printer.c | 1 + src/shady/emit/c/emit_c.c | 55 ++++++++++++++++++++++++-- src/shady/emit/c/emit_c.h | 2 + src/shady/emit/c/emit_c_instructions.c | 5 +++ src/shady/emit/c/emit_c_signatures.c | 14 ++++++- 5 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/common/printer.c b/src/common/printer.c index a73bb57ff..ffafcfbd7 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -132,6 +132,7 @@ Printer* print(Printer* p, const char* f, ...) { const char* printer_growy_unwrap(Printer* p) { assert(p->output == PoGrowy); + growy_append_bytes(p->growy, 1, "\0"); const char* insides = growy_deconstruct(p->growy); free(p); return insides; diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 1794082ec..5fa77528a 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -136,9 +136,10 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S switch (as) { case AsPrivateLogical: case AsPrivatePhysical: + assert(false); // Note: this requires many hacks. - prefix = "__shared__ "; - decl_center = format_string_arena(emitter->arena->arena, "__shady_make_thread_local(%s)", decl_center); + prefix = "__device__ "; + decl_center = format_string_arena(emitter->arena->arena, "__shady_private_globals.%s", decl_center); break; case AsSharedPhysical: case AsSharedLogical: prefix = "__shared__ "; break; @@ -588,10 +589,15 @@ void emit_decl(Emitter* emitter, const Node* decl) { // we emit the global variable as a CVar, so we can refer to it's 'address' without explicit ptrs emit_as = term_from_cvar(name); if ((decl->payload.global_variable.address_space == AsPrivatePhysical || decl->payload.global_variable.address_space == AsPrivateLogical) && emitter->config.dialect == CDialect_CUDA) { - // HACK + if (emitter->use_private_globals) { + register_emitted(emitter, decl, term_from_cvar(format_string_arena(emitter->arena->arena, "__shady_private_globals->%s", name))); + // HACK + return; + } emit_as = term_from_cvar(format_string_interned(emitter->arena, "__shady_thread_local_access(%s)", name)); if (init) init = format_string_interned(emitter->arena, "__shady_replicate_thread_local(%s)", init); + register_emitted(emitter, decl, emit_as); } register_emitted(emitter, decl, emit_as); @@ -620,7 +626,13 @@ void emit_decl(Emitter* emitter, const Node* decl) { fn_body = format_string_arena(emitter->arena->arena, "if ((lanemask() >> programIndex) & 1u) { %s}", fn_body); // I hate everything about this too. } else if (emitter->config.dialect == CDialect_CUDA) { - fn_body = format_string_arena(emitter->arena->arena, "__shady_prepare_builtins();\n%s", fn_body); + if (lookup_annotation(decl, "EntryPoint")) { + // fn_body = format_string_arena(emitter->arena->arena, "\n__shady_entry_point_init();%s", fn_body); + if (emitter->use_private_globals) { + fn_body = format_string_arena(emitter->arena->arena, "\n__shady_PrivateGlobals __shady_private_globals_alloc;\n __shady_PrivateGlobals* __shady_private_globals = &__shady_private_globals_alloc;\n%s", fn_body); + } + fn_body = format_string_arena(emitter->arena->arena, "\n__shady_prepare_builtins();%s", fn_body); + } } print(emitter->fn_defs, "\n%s { %s }", head, fn_body); free_tmp_str(free_me); @@ -694,6 +706,33 @@ static Module* run_backend_specific_passes(CompilerConfig* config, CEmitterConfi return *pmod; } +static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { + Growy* g = new_growy(); + Printer* p = open_growy_as_printer(g); + + print(p, "typedef struct __shady_PrivateGlobals {\n"); + Nodes decls = get_module_declarations(m); + size_t count = 0; + for (size_t i = 0; i < decls.count; i++) { + const Node* decl = decls.nodes[i]; + if (decl->tag != GlobalVariable_TAG) + continue; + AddressSpace as = decl->payload.global_variable.address_space; + if (as != AsPrivatePhysical && as != AsPrivateLogical) + continue; + print(p, "%s;\n", c_emit_type(emitter, decl->payload.global_variable.type, decl->payload.global_variable.name)); + count++; + } + print(p, "} __shady_PrivateGlobals;\n"); + + if (count == 0) { + destroy_printer(p); + destroy_growy(g); + return NULL; + } + return printer_growy_unwrap(p); +} + void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod) { IrArena* initial_arena = get_module_arena(mod); mod = run_backend_specific_passes(&compiler_config, &config, mod); @@ -723,6 +762,13 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, .element_type = uint32_type(arena) }), "uvec3")); print(emitter.fn_defs, shady_cuda_builtins_src); + + String private_globals = collect_private_globals_in_struct(&emitter, mod); + if (private_globals) { + emitter.use_private_globals = true; + print(emitter.type_decls, private_globals); + free((void*)private_globals); + } } Nodes decls = get_module_declarations(mod); @@ -781,6 +827,7 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, print(finalp, "\n"); print(finalp, "\n"); print(finalp, "\n"); + growy_append_bytes(final, 1, "\0"); destroy_growy(type_decls_g); destroy_growy(fn_decls_g); diff --git a/src/shady/emit/c/emit_c.h b/src/shady/emit/c/emit_c.h index c285e999f..2f2d031f9 100644 --- a/src/shady/emit/c/emit_c.h +++ b/src/shady/emit/c/emit_c.h @@ -45,6 +45,8 @@ typedef struct { struct Dict* emitted_types; int total_workgroup_size; + bool use_private_globals; + Printer* entrypoint_prelude; } Emitter; void register_emitted(Emitter*, const Node*, CTerm); diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index ee1b2158d..c78937651 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -624,6 +624,11 @@ static void emit_call(Emitter* emitter, Printer* p, const Node* call, Instructio Growy* g = new_growy(); Printer* paramsp = open_growy_as_printer(g); + if (emitter->use_private_globals) { + print(paramsp, "__shady_private_globals"); + if (args.count > 0) + print(paramsp, ", "); + } for (size_t i = 0; i < args.count; i++) { print(paramsp, to_cvalue(emitter, emit_value(emitter, p, args.nodes[i]))); if (i + 1 < args.count) diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index 0895168a4..be8819020 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -48,6 +48,8 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const assert(!fn || fn->type == fn_type); Nodes codom = fn_type->payload.fn_type.return_types; + const Node* entry_point = fn ? lookup_annotation(fn, "EntryPoint") : NULL; + Growy* paramg = new_growy(); Printer* paramp = open_growy_as_printer(paramg); Nodes dom = fn_type->payload.fn_type.param_types; @@ -56,6 +58,11 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const else if (fn) { Nodes params = fn->payload.fun.params; assert(params.count == dom.count); + if (emitter->use_private_globals && !entry_point) { + print(paramp, "__shady_PrivateGlobals* __shady_private_globals"); + if (params.count > 0) + print(paramp, ", "); + } for (size_t i = 0; i < dom.count; i++) { String param_name; String variable_name = get_value_name(fn->payload.fun.params.nodes[i]); @@ -66,6 +73,11 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const } } } else { + if (emitter->use_private_globals) { + print(paramp, "__shady_PrivateGlobals*"); + if (dom.count > 0) + print(paramp, ", "); + } for (size_t i = 0; i < dom.count; i++) { print(paramp, emit_type(emitter, dom.nodes[i], "")); if (i + 1 < dom.count) { @@ -88,8 +100,6 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const free_tmp_str(parameters); String c_decl = emit_type(emitter, wrap_multiple_yield_types(emitter->arena, codom), center); - - const Node* entry_point = fn ? lookup_annotation(fn, "EntryPoint") : NULL; if (entry_point) { switch (emitter->config.dialect) { case CDialect_C11: From f1b2f1843775375667b23d09191a96fa89e57cdf Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 28 Mar 2024 10:15:21 +0100 Subject: [PATCH 123/693] share --device parsing between runtime_test and aobench --- samples/aobench/ao_main.c | 48 +++++++++++++++++------------ src/runtime/runtime_app_common.h | 53 ++++++++++++++++++++++++++++++++ src/runtime/runtime_private.h | 1 + src/runtime/runtime_test.c | 50 +++++++----------------------- 4 files changed, 93 insertions(+), 59 deletions(-) create mode 100644 src/runtime/runtime_app_common.h diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 16ae8c28d..4d1999c8e 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -1,18 +1,23 @@ #include "ao.h" +#include "../runtime/runtime_app_common.h" + +#include "shady/runtime.h" +#include "shady/driver.h" + +#include "log.h" +#include "util.h" #include #include #include #include -#include #include -#include "shady/runtime.h" -#include "shady/driver.h" - -#include "log.h" -#include "list.h" -#include "util.h" +typedef struct { + CompilerConfig compiler_config; + RuntimeConfig runtime_config; + CommonAppArgs common_app_args; +} Args; static uint64_t timespec_to_nano(struct timespec t) { return t.tv_sec * 1000000000 + t.tv_nsec; @@ -88,7 +93,7 @@ void render_ispc(unsigned char *img, int w, int h, int nsubsamples) { } #endif -void render_device(const CompilerConfig* compiler_config, unsigned char *img, int w, int h, int nsubsamples, String path) { +void render_device(Args* args, unsigned char *img, int w, int h, int nsubsamples, String path) { for (size_t i = 0; i < WIDTH; i++) { for (size_t j = 0; j < HEIGHT; j++) { img[j * WIDTH * 3 + i * 3 + 0] = 255; @@ -97,15 +102,10 @@ void render_device(const CompilerConfig* compiler_config, unsigned char *img, in } } - RuntimeConfig runtime_config = (RuntimeConfig) { - .use_validation = true, - .dump_spv = true, - }; - info_print("Shady checkerboard test starting...\n"); - Runtime* runtime = initialize_runtime(runtime_config); - Device* device = get_device(runtime, 0); + Runtime* runtime = initialize_runtime(args->runtime_config); + Device* device = get_device(runtime, args->common_app_args.device); assert(device); img[0] = 69; @@ -116,7 +116,7 @@ void render_device(const CompilerConfig* compiler_config, unsigned char *img, in info_print("Device-side address is: %zu\n", buf_addr); - Program* program = load_program_from_disk(runtime, compiler_config, path); + Program* program = load_program_from_disk(runtime, &args->compiler_config, path); // run it twice to compile everything and benefit from caches wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / 16, HEIGHT / 16, 1, 1, (void*[]) { &buf_addr })); @@ -138,20 +138,28 @@ void render_device(const CompilerConfig* compiler_config, unsigned char *img, in int main(int argc, char **argv) { set_log_level(INFO); + Args args = { + .compiler_config = default_compiler_config(), + .runtime_config = { + .use_validation = true, + .dump_spv = true, + } + }; CompilerConfig compiler_config = default_compiler_config(); cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&compiler_config, &argc, argv); + cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); bool do_host = false, do_ispc = false, do_device = false, do_all = true; for (size_t i = 0; i < argc; i++) { - if (strcmp(argv[i], "--device") == 0) { + if (strcmp(argv[i], "--only-device") == 0) { do_device = true; do_all = false; - } else if (strcmp(argv[i], "--host") == 0) { + } else if (strcmp(argv[i], "--only-host") == 0) { do_host = true; do_all = false; - } else if (strcmp(argv[i], "--ispc") == 0) { + } else if (strcmp(argv[i], "--only-ispc") == 0) { do_ispc = true; do_all = false; } @@ -172,7 +180,7 @@ int main(int argc, char **argv) { #endif if (do_device || do_all) { - render_device(&compiler_config, img, WIDTH, HEIGHT, NSUBSAMPLES, "./ao.cl.spv"); + render_device(&args, img, WIDTH, HEIGHT, NSUBSAMPLES, "./ao.cl.spv"); saveppm("device.ppm", WIDTH, HEIGHT, img); } diff --git a/src/runtime/runtime_app_common.h b/src/runtime/runtime_app_common.h new file mode 100644 index 000000000..526b82a08 --- /dev/null +++ b/src/runtime/runtime_app_common.h @@ -0,0 +1,53 @@ +#ifndef SHADY_RUNTIME_CLI +#define SHADY_RUNTIME_CLI + +#include "shady/driver.h" +#include "runtime_private.h" + +#include "log.h" + +#include +#include + +typedef struct { + size_t device; +} CommonAppArgs; + +static void cli_parse_common_app_arguments(CommonAppArgs* args, int* pargc, char** argv) { + int argc = *pargc; + + bool help = false; + for (int i = 1; i < argc; i++) { + if (argv[i] == NULL) + continue; + if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + help = true; + continue; + } else if (strcmp(argv[i], "--device") == 0 || strcmp(argv[i], "-d") == 0) { + argv[i] = NULL; + i++; + if (i >= argc) { + error_print("Missing device number for --device\n"); + exit(1); + } + args->device = strtol(argv[i], NULL, 10); + } else { + continue; + } + argv[i] = NULL; + } + + if (help) { + error_print("Usage: runtime_test [source.slim]\n"); + error_print("Available arguments: \n"); + error_print(" --log-level debug[v[v]], info, warn, error]\n"); + error_print(" --print-builtin\n"); + error_print(" --print-generated\n"); + error_print(" --device n\n"); + exit(0); + } + + cli_pack_remaining_args(pargc, argv); +} + +#endif diff --git a/src/runtime/runtime_private.h b/src/runtime/runtime_private.h index a20803d0c..d225bdf85 100644 --- a/src/runtime/runtime_private.h +++ b/src/runtime/runtime_private.h @@ -68,4 +68,5 @@ void unload_program(Program*); Backend* initialize_vk_backend(Runtime*); Backend* initialize_cuda_backend(Runtime*); + #endif diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 7db28c5e4..bd97c0be6 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -2,6 +2,8 @@ #include "shady/ir.h" #include "shady/driver.h" +#include "runtime_app_common.h" + #include "log.h" #include "portability.h" #include "util.h" @@ -11,6 +13,13 @@ #include #include #include +#include + +typedef struct { + DriverConfig driver_config; + RuntimeConfig runtime_config; + CommonAppArgs common_app_args; +} Args; static const char* default_shader = "@EntryPoint(\"Compute\") @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn my_kernel(uniform i32 a, uniform ptr global i32 b) {\n" @@ -19,43 +28,6 @@ static const char* default_shader = " return ();\n" "}"; -typedef struct { - DriverConfig driver_config; - RuntimeConfig runtime_config; - size_t device; -} Args; - -static void parse_runtime_arguments(int* pargc, char** argv, Args* args) { - int argc = *pargc; - - bool help = false; - for (int i = 1; i < argc; i++) { - if (argv[i] == NULL) - continue; - if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { - help = true; - continue; - } else if (strcmp(argv[i], "--device") == 0 || strcmp(argv[i], "-d") == 0) { - argv[i] = NULL; - i++; - args->device = strtol(argv[i], NULL, 10); - } else { - continue; - } - argv[i] = NULL; - } - - if (help) { - error_print("Usage: runtime_test [source.slim]\n"); - error_print("Available arguments: \n"); - error_print(" --log-level debug[v[v]], info, warn, error]\n"); - error_print(" --print-builtin\n"); - error_print(" --print-generated\n"); - error_print(" --device n\n"); - exit(0); - } -} - int main(int argc, char* argv[]) { set_log_level(INFO); Args args = { @@ -65,7 +37,7 @@ int main(int argc, char* argv[]) { .use_validation = true, .dump_spv = true, }; - parse_runtime_arguments(&argc, argv, &args); + cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.driver_config.config, &argc, argv); cli_parse_input_files(args.driver_config.input_filenames, &argc, argv); @@ -73,7 +45,7 @@ int main(int argc, char* argv[]) { info_print("Shady runtime test starting...\n"); Runtime* runtime = initialize_runtime(args.runtime_config); - Device* device = get_device(runtime, args.device); + Device* device = get_device(runtime, args.common_app_args.device); assert(device); Program* program; From 1e6de26e902dba3520debb5de276de1fbf0a1a29 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 28 Mar 2024 13:37:39 +0100 Subject: [PATCH 124/693] refactor CLI options a bit --- include/shady/ir.h | 7 ++++-- src/driver/cli.c | 34 +++++++++++++++++---------- src/shady/compile.c | 26 ++++++++++++++------ src/shady/passes/lower_generic_ptrs.c | 2 +- src/shady/print.c | 12 +++++----- src/shady/print.h | 6 ++--- 6 files changed, 55 insertions(+), 32 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 3344c14f2..9f8b5a35a 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -265,6 +265,9 @@ struct CompilerConfig_ { } target_spirv_version; struct { + bool emulate_generic_ptrs; + bool emulate_physical_memory; + bool emulate_subgroup_ops; bool emulate_subgroup_ops_extended_types; bool simt_to_explicit_simd; @@ -275,7 +278,7 @@ struct CompilerConfig_ { struct { bool spv_shuffle_instead_of_broadcast_first; bool force_join_point_lifting; - bool no_physical_global_ptrs; + bool assume_no_physical_global_ptrs; } hacks; struct { @@ -298,7 +301,7 @@ struct CompilerConfig_ { } shader_diagnostics; struct { - bool skip_generated, skip_builtin, skip_internal; + bool print_generated, print_builtin, print_internal; } logging; struct { diff --git a/src/driver/cli.c b/src/driver/cli.c index 237c57491..4e53b1217 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -81,6 +81,23 @@ void cli_parse_common_args(int* pargc, char** argv) { cli_pack_remaining_args(pargc, argv); } +#define PARSE_TOGGLE_OPTION(f, name) \ +if (strcmp(argv[i], "--no-"#name) == 0) { \ + config->f = false; argv[i] = NULL; continue; \ +} else if (strcmp(argv[i], "--"#name) == 0) { \ + config->f = true; argv[i] = NULL; continue; \ +} + +#define TOGGLE_OPTIONS(F) \ +F(lower.emulate_physical_memory, emulate-physical-memory) \ +F(dynamic_scheduling, dynamic-scheduling) \ +F(hacks.force_join_point_lifting, lift-join-points) \ +F(hacks.assume_no_physical_global_ptrs, assume-no-physical-global-ptrs) \ +F(logging.print_internal, print-internal) \ +F(logging.print_generated, print-builtin) \ +F(logging.print_generated, print-generated) \ +F(lower.simt_to_explicit_simd, lower-simt-to-simd) \ + void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { int argc = *pargc; @@ -88,11 +105,10 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a for (int i = 1; i < argc; i++) { if (argv[i] == NULL) continue; - if (strcmp(argv[i], "--no-dynamic-scheduling") == 0) { - config->dynamic_scheduling = false; - } else if (strcmp(argv[i], "--lift-join-points") == 0) { - config->hacks.force_join_point_lifting = true; - } else if (strcmp(argv[i], "--entry-point") == 0) { + + TOGGLE_OPTIONS(PARSE_TOGGLE_OPTION) + + if (strcmp(argv[i], "--entry-point") == 0) { argv[i] = NULL; i++; if (i == argc) @@ -123,14 +139,6 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a default: break; } config->specialization.execution_model = em; - } else if (strcmp(argv[i], "--simt2d") == 0) { - config->lower.simt_to_explicit_simd = true; - } else if (strcmp(argv[i], "--print-internal") == 0) { - config->logging.skip_internal = false; - } else if (strcmp(argv[i], "--print-generated") == 0) { - config->logging.skip_generated = false; - } else if (strcmp(argv[i], "--no-physical-global-ptrs") == 0) { - config->hacks.no_physical_global_ptrs = true; } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { help = true; continue; diff --git a/src/shady/compile.c b/src/shady/compile.c index 9f5f5fd90..86448a787 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -23,10 +23,15 @@ CompilerConfig default_compiler_config() { .minor = 4 }, + .lower = { + .emulate_physical_memory = true, + .emulate_generic_ptrs = true, + }, + .logging = { // most of the time, we are not interested in seeing generated & internal code in the debug output - .skip_internal = true, - .skip_generated = true, + .print_internal = true, + .print_generated = true, }, .optimisations = { @@ -113,13 +118,20 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_mask) RUN_PASS(lower_memcpy) RUN_PASS(lower_subgroup_ops) - - RUN_PASS(lower_alloca) + if (config->lower.emulate_physical_memory) { + RUN_PASS(lower_alloca) + } RUN_PASS(lower_stack) - RUN_PASS(lower_lea) + if (config->lower.emulate_physical_memory) { + RUN_PASS(lower_lea) + } RUN_PASS(lower_generic_globals) - RUN_PASS(lower_generic_ptrs) - RUN_PASS(lower_physical_ptrs) + if (config->lower.emulate_generic_ptrs) { + RUN_PASS(lower_generic_ptrs) + } + if (config->lower.emulate_physical_memory) { + RUN_PASS(lower_physical_ptrs) + } RUN_PASS(lower_subgroup_vars) RUN_PASS(lower_memory_layout) diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 5230a21bf..4011644f1 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -62,7 +62,7 @@ static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t } static bool allowed(Context* ctx, AddressSpace as) { - if (as == AsGlobalPhysical && ctx->config->hacks.no_physical_global_ptrs) + if (as == AsGlobalPhysical && ctx->config->hacks.assume_no_physical_global_ptrs) return false; if (as == AsSharedPhysical && !ctx->rewriter.dst_arena->config.allow_shared_memory) return false; diff --git a/src/shady/print.c b/src/shady/print.c index fcf6beb0c..282767aa0 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -782,11 +782,11 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { static void print_decl(PrinterCtx* ctx, const Node* node) { assert(is_declaration(node)); - if (ctx->config.skip_generated && lookup_annotation(node, "Generated")) + if (!ctx->config.print_generated && lookup_annotation(node, "Generated")) return; - if (ctx->config.skip_internal && lookup_annotation(node, "Internal")) + if (!ctx->config.print_internal && lookup_annotation(node, "Internal")) return; - if (ctx->config.skip_builtin && lookup_annotation(node, "Builtin")) + if (!ctx->config.print_builtin && lookup_annotation(node, "Builtin")) return; PrinterCtx sub_ctx = *ctx; @@ -1009,9 +1009,9 @@ void log_node(LogLevel level, const Node* node) { void log_module(LogLevel level, CompilerConfig* compiler_cfg, Module* mod) { PrintConfig config = { .color = true }; if (compiler_cfg) { - config.skip_generated = compiler_cfg->logging.skip_generated; - config.skip_builtin = compiler_cfg->logging.skip_builtin; - config.skip_internal = compiler_cfg->logging.skip_internal; + config.print_generated = compiler_cfg->logging.print_generated; + config.print_builtin = compiler_cfg->logging.print_builtin; + config.print_internal = compiler_cfg->logging.print_internal; } if (level >= get_log_level()) print_module(open_file_as_printer(stderr), mod, config); diff --git a/src/shady/print.h b/src/shady/print.h index 2d04a7d48..4ec5486b2 100644 --- a/src/shady/print.h +++ b/src/shady/print.h @@ -6,9 +6,9 @@ #include typedef struct { - bool skip_builtin; - bool skip_internal; - bool skip_generated; + bool print_builtin; + bool print_internal; + bool print_generated; bool print_ptrs; bool color; bool reparseable; From 1b3b33ef0a226f77c5cadafe24a0944ed2420f4b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 28 Mar 2024 13:38:05 +0100 Subject: [PATCH 125/693] fix ISPC --- samples/aobench/ao_main.c | 2 +- src/shady/emit/c/emit_c.c | 2 +- src/shady/emit/c/emit_c_signatures.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 4d1999c8e..7d39b7dd3 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -65,7 +65,7 @@ typedef struct { uint32_t x, y, z; } Vec3u; -Vec3u builtin_NumWorkgroups; +extern Vec3u builtin_NumWorkgroups; void render_ispc(unsigned char *img, int w, int h, int nsubsamples) { struct timespec ts; diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 5fa77528a..c08d5bdb4 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -836,7 +836,7 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, destroy_dict(emitter.emitted_types); destroy_dict(emitter.emitted_terms); - *output_size = growy_size(final); + *output_size = growy_size(final) - 1; *output = growy_deconstruct(final); destroy_printer(finalp); diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index be8819020..724328efd 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -108,6 +108,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const break; case CDialect_ISPC: c_decl = format_string_arena(emitter->arena->arena, "export %s", c_decl); + break; case CDialect_CUDA: c_decl = format_string_arena(emitter->arena->arena, "extern \"C\" __global__ %s", c_decl); break; From fe9e1d264b5c7312ca4b98f0fb7821295e792425 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 28 Mar 2024 13:38:21 +0100 Subject: [PATCH 126/693] runtime/cuda: dump source in debug mode --- src/runtime/cuda/cuda_runtime_program.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index da4622207..5475ab4e2 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -3,6 +3,7 @@ #include "log.h" #include "portability.h" #include "dict.h" +#include "util.h" static CompilerConfig get_compiler_config_for_device(CudaDevice* device, const CompilerConfig* base_config) { CompilerConfig config = *base_config; @@ -39,6 +40,9 @@ static bool cuda_c_to_ptx(CudaKernel* kernel) { debug_print("Dumping source:\n%s", kernel->cuda_code); } + if (get_log_level() <= DEBUG) + write_file("cuda_dump.cu", kernel->cuda_code_size - 1, kernel->cuda_code); + size_t log_size; CHECK_NVRTC(nvrtcGetProgramLogSize(program, &log_size), return false); char* log_buffer = calloc(log_size, 1); From 41ebfde4c6b33cc472d83f2e1d666690e4e5f425 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 28 Mar 2024 13:38:33 +0100 Subject: [PATCH 127/693] revert 3f763642a119d08968c5c81d0cb907855b51b5e6 --- src/shady/type_helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 435205745..94f9694a2 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -43,8 +43,8 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { assert(type->tag == PtrType_TAG); uniform &= is_addr_space_uniform(arena, type->payload.ptr_type.address_space); type = type->payload.ptr_type.pointed_type; - while (type->tag == ArrType_TAG && !type->payload.arr_type.size) - type = type->payload.arr_type.element_type; + // while (type->tag == ArrType_TAG && !type->payload.arr_type.size) + // type = type->payload.arr_type.element_type; if (qualified) type = qualified_type(arena, (QualifiedType) { From 97b4aa6021a25fe97f8861635d7990b3e22d88b7 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 28 Mar 2024 15:05:53 +0100 Subject: [PATCH 128/693] added native cuda variant of aobench --- samples/aobench/ao.c | 32 ++++++++++++++++++-------------- samples/aobench/ao.cu | 16 ++++++++++++++++ 2 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 samples/aobench/ao.cu diff --git a/samples/aobench/ao.c b/samples/aobench/ao.c index 1f9010dd8..0b5adf560 100644 --- a/samples/aobench/ao.c +++ b/samples/aobench/ao.c @@ -2,7 +2,11 @@ #include "ao.h" -unsigned int FNVHash(char* str, unsigned int length) { +#ifndef FUNCTION +#define FUNCTION +#endif + +FUNCTION unsigned int FNVHash(char* str, unsigned int length) { const unsigned int fnv_prime = 0x811C9DC5; unsigned int hash = 0; unsigned int i = 0; @@ -16,31 +20,31 @@ unsigned int FNVHash(char* str, unsigned int length) { return hash; } -unsigned int nrand(unsigned int* rng) { +FUNCTION unsigned int nrand(unsigned int* rng) { unsigned int orand = *rng; *rng = FNVHash((char*) &orand, 4); return *rng; } -Scalar drand48(Ctx* ctx) { +FUNCTION Scalar drand48(Ctx* ctx) { Scalar n = (nrand(&ctx->rng) / 65536.0f); n = n - floorf(n); return n; } -static Scalar vdot(vec v0, vec v1) +FUNCTION static Scalar vdot(vec v0, vec v1) { return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z; } -static void vcross(vec *c, vec v0, vec v1) +FUNCTION static void vcross(vec *c, vec v0, vec v1) { c->x = v0.y * v1.z - v0.z * v1.y; c->y = v0.z * v1.x - v0.x * v1.z; c->z = v0.x * v1.y - v0.y * v1.x; } -static void vnormalize(vec *c) +FUNCTION static void vnormalize(vec *c) { Scalar length = sqrtf(vdot((*c), (*c))); @@ -51,7 +55,7 @@ static void vnormalize(vec *c) } } -static void +FUNCTION static void ray_sphere_intersect(Isect *isect, const Ray *ray, const Sphere *sphere) { vec rs; @@ -84,7 +88,7 @@ ray_sphere_intersect(Isect *isect, const Ray *ray, const Sphere *sphere) } } -static void +FUNCTION static void ray_plane_intersect(Isect *isect, const Ray *ray, const Plane *plane) { Scalar d = -vdot(plane->p, plane->n); @@ -106,7 +110,7 @@ ray_plane_intersect(Isect *isect, const Ray *ray, const Plane *plane) } } -static void +FUNCTION static void orthoBasis(vec *basis, vec n) { basis[2] = n; @@ -129,7 +133,7 @@ orthoBasis(vec *basis, vec n) vnormalize(&basis[1]); } -static void ambient_occlusion(Ctx* ctx, vec *col, const Isect *isect) +FUNCTION static void ambient_occlusion(Ctx* ctx, vec *col, const Isect *isect) { int i, j; int ntheta = NAO_SAMPLES; @@ -189,7 +193,7 @@ static void ambient_occlusion(Ctx* ctx, vec *col, const Isect *isect) col->z = occlusion; } -unsigned char aobench_clamp(Scalar f) +FUNCTION unsigned char aobench_clamp(Scalar f) { Scalar s = (f * 255.5f); @@ -199,7 +203,7 @@ unsigned char aobench_clamp(Scalar f) return (unsigned char) s; } -void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamples, unsigned char* img) { +FUNCTION void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamples, unsigned char* img) { Scalar pixel[3] = { 0, 0, 0 }; ctx->rng = x * w + y; @@ -259,7 +263,7 @@ void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamples, unsigne img[3 * (y * w + x) + 2] = aobench_clamp(pixel[2]); } -void init_scene(Ctx* ctx) +FUNCTION void init_scene(Ctx* ctx) { ctx->spheres[0].center.x = -2.0f; ctx->spheres[0].center.y = 0.0f; @@ -286,7 +290,7 @@ void init_scene(Ctx* ctx) } -Ctx get_init_context() { +FUNCTION Ctx get_init_context() { return (Ctx) { .rng = 0xFEEFDEED, }; diff --git a/samples/aobench/ao.cu b/samples/aobench/ao.cu new file mode 100644 index 000000000..2cecf4c73 --- /dev/null +++ b/samples/aobench/ao.cu @@ -0,0 +1,16 @@ +#define FUNCTION __device__ +#include "ao.c" + +extern "C" { + +__global__ void aobench_kernel(unsigned char* out) { + int x = threadIdx.x + blockDim.x * blockIdx.x; + int y = threadIdx.y + blockDim.y * blockIdx.y; + + long int ptr = (long int) out; + Ctx ctx = get_init_context(); + init_scene(&ctx); + // render_pixel(&ctx, x, y, WIDTH, HEIGHT, NSUBSAMPLES, out); +} + +} \ No newline at end of file From 55a64bb5406a70e084a5392d5f88ecb42cb178c1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:40:48 +0200 Subject: [PATCH 129/693] frontend/llvm: hack: map unordered versions of fcmp to ordered --- src/frontends/llvm/l2s_instr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index f9349b97c..cb6877d39 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -375,21 +375,27 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM Op op; bool cast_to_signed = false; switch(LLVMGetFCmpPredicate(instr)) { + case LLVMRealUEQ: case LLVMRealOEQ: op = eq_op; break; + case LLVMRealUNE: case LLVMRealONE: op = neq_op; break; + case LLVMRealUGT: case LLVMRealOGT: op = gt_op; break; + case LLVMRealUGE: case LLVMRealOGE: op = gte_op; break; + case LLVMRealULT: case LLVMRealOLT: op = lt_op; break; + case LLVMRealULE: case LLVMRealOLE: op = lte_op; break; @@ -604,4 +610,4 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM LLVMDumpValue(instr); error_print(" (opcode=%d)\n", opcode); error_die(); -} \ No newline at end of file +} From 61accd35060adba441f15c5585027009525e18ff Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:43:15 +0200 Subject: [PATCH 130/693] fix some issues with Input/Output variables --- src/shady/emit/c/emit_c.c | 3 +++ src/shady/type.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index c08d5bdb4..606eae94b 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -576,6 +576,9 @@ void emit_decl(Emitter* emitter, const Node* decl) { String init = NULL; if (decl->payload.global_variable.init) init = to_cvalue(emitter, emit_value(emitter, NULL, decl->payload.global_variable.init)); + AddressSpace ass = decl->payload.global_variable.address_space; + if (ass == AsInput || ass == AsOutput) + init = NULL; const GlobalVariable* gvar = &decl->payload.global_variable; if (is_decl_builtin(decl)) { diff --git a/src/shady/type.c b/src/shady/type.c index 5cb01e0d7..5b0293322 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -172,10 +172,11 @@ size_t get_type_bitwidth(const Type* t) { bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { switch (as) { + case AsInput: + case AsOutput: case AsFunctionLogical: case AsPrivateLogical: case AsPrivatePhysical: - case AsInput: return !arena->config.is_simt; default: return true; From 7de5e254f89fa999de88ecc1abc5ddca16f80ca9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:44:09 +0200 Subject: [PATCH 131/693] c: implement hack for shifts because glsl is bad --- src/shady/emit/c/emit_c_instructions.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index c78937651..7ef73be4d 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -87,9 +87,9 @@ static const ISelTableEntry isel_table[PRIMOPS_COUNT] = { [or_op] = { IsMono, OsInfix, "|" }, [xor_op] = { IsMono, OsInfix, "^" }, [not_op] = { IsMono, OsPrefix, "!" }, - [rshift_arithm_op] = { IsMono, OsInfix, ">>" }, + /*[rshift_arithm_op] = { IsMono, OsInfix, ">>" }, [rshift_logical_op] = { IsMono, OsInfix, ">>" }, // TODO achieve desired right shift semantics through unsigned/signed casts - [lshift_op] = { IsMono, OsInfix, "<<" }, + [lshift_op] = { IsMono, OsInfix, "<<" },*/ }; static const ISelTableEntry isel_table_c[PRIMOPS_COUNT] = { @@ -258,6 +258,19 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct term = term_from_cvalue(format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); break; } + case lshift_op: + case rshift_arithm_op: + case rshift_logical_op: { + CValue src = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); + const Node* offset = prim_op->operands.nodes[1]; + CValue c_offset = to_cvalue(emitter, emit_value(emitter, p, offset)); + if (emitter->config.dialect == CDialect_GLSL) { + if (get_unqualified_type(offset->type)->payload.int_type.width == IntTy64) + c_offset = format_string_arena(arena->arena, "int(%s)", c_offset); + } + term = term_from_cvalue(format_string_arena(arena->arena, "(%s %s %s)", src, prim_op->op == lshift_op ? "<<" : ">>", c_offset)); + break; + } case alloca_op: case alloca_logical_op: { assert(outputs.count == 1); From 7ef61da67c74c509aab83efbba6d72f447514285 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:44:32 +0200 Subject: [PATCH 132/693] glsl: implement a bunch of math ops --- src/shady/emit/c/emit_c_instructions.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 7ef73be4d..18440323b 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -106,7 +106,19 @@ static const ISelTableEntry isel_table_c[PRIMOPS_COUNT] = { [pow_op] = { IsPoly, OsCall, .f_ops = {"powf", "powf", "pow"}}, }; -static const ISelTableEntry isel_table_glsl[PRIMOPS_COUNT] = { 0 }; +static const ISelTableEntry isel_table_glsl[PRIMOPS_COUNT] = { + [abs_op] = { IsMono, OsCall, "abs" }, + + [sin_op] = { IsMono, OsCall, "sin" }, + [cos_op] = { IsMono, OsCall, "cos" }, + [floor_op] = { IsMono, OsCall, "floor" }, + [ceil_op] = { IsMono, OsCall, "ceil" }, + [round_op] = { IsMono, OsCall, "round" }, + + [sqrt_op] = { IsMono, OsCall, "sqrt" }, + [exp_op] = { IsMono, OsCall, "exp" }, + [pow_op] = { IsMono, OsCall, "pow" }, +}; static const ISelTableEntry isel_table_ispc[PRIMOPS_COUNT] = { [abs_op] = { IsMono, OsCall, "abs" }, From a639e81bd08c0b994efb85023c73418051661291 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:44:54 +0200 Subject: [PATCH 133/693] c: implement shuffle and assume_uniform --- src/shady/emit/c/emit_c_instructions.c | 35 +++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 18440323b..bfa432e90 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -571,6 +571,33 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct term = term_from_cvalue(acc); break; } + case shuffle_op: { + String dst = unique_name(arena, "shuffled"); + const Node* lhs = prim_op->operands.nodes[0]; + const Node* rhs = prim_op->operands.nodes[1]; + String lhs_e = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[0])); + String rhs_e = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[1])); + const Type* lhs_t = lhs->type; + const Type* rhs_t = rhs->type; + bool lhs_u = deconstruct_qualified_type(&lhs_t); + bool rhs_u = deconstruct_qualified_type(&rhs_t); + size_t left_size = lhs_t->payload.pack_type.width; + // size_t total_size = lhs_t->payload.pack_type.width + rhs_t->payload.pack_type.width; + String suffixes = "xyzw"; + print(p, "\n%s = vec%d(", c_emit_type(emitter, node->type, dst), prim_op->operands.count - 2); + for (size_t i = 2; i < prim_op->operands.count; i++) { + const IntLiteral* selector = resolve_to_int_literal(prim_op->operands.nodes[i]); + if (selector->value < left_size) + print(p, "%s.%c\n", lhs_e, suffixes[selector->value]); + else + print(p, "%s.%c\n", rhs_e, suffixes[selector->value - left_size]); + if (i + 1 < prim_op->operands.count) + print(p, ", "); + } + print(p, ");\n"); + term = term_from_cvalue(dst); + break; + } case get_stack_base_op: case push_stack_op: case pop_stack_op: @@ -587,7 +614,13 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct } break; } - case subgroup_assume_uniform_op: + case subgroup_assume_uniform_op: { + if (emitter->config.dialect != CDialect_ISPC) { + outputs.results[0] = emit_value(emitter, p, prim_op->operands.nodes[0]); + outputs.binding[0] = NoBinding; + return; + } + } case subgroup_broadcast_first_op: { CValue value = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); switch (emitter->config.dialect) { From f0073f03eac1c3589770b27ab48ec9d9388eb65f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:45:21 +0200 Subject: [PATCH 134/693] mem2reg: add safety assume_uniform cast --- src/shady/passes/opt_mem2reg.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 8fd9e3203..73a813565 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -267,9 +267,13 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No const Type* load_result_t = rewrite_node(&ctx->rewriter, optr->type); bool lrt_u = deconstruct_qualified_type(&load_result_t); deconstruct_pointer_type(&load_result_t); - assert(!lrt_u || kv_u); - if (is_reinterpret_cast_legal(load_result_t, known_value_t)) - return prim_op_helper(a, reinterpret_op, singleton(load_result_t), singleton(known_value)); + // assert(!lrt_u || kv_u); + if (is_reinterpret_cast_legal(load_result_t, known_value_t)) { + const Node* n = prim_op_helper(a, reinterpret_op, singleton(load_result_t), singleton(known_value)); + if (lrt_u && !kv_u) + n = prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(known_value)); + return n; + } } else { const KnowledgeBase* phi_kb = kb; while (phi_kb->dominator_kb) { @@ -519,6 +523,7 @@ static void handle_bb(Context* ctx, const Node* old) { log_node(DEBUG, ptr); debug_print(" has a known value in all predecessors! Turning it into a new parameter.\n"); + assert(!is_qualified_type_uniform(source->type)); const Node* param = var(a, qualified_type_helper(source->type, false), unique_name(a, "ssa_phi")); params = append_nodes(a, params, param); ptrs = append_nodes(ctx->rewriter.src_arena, ptrs, ptr); From 0e654c38b904709c5b3d520b9514ccce52a38e50 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:45:46 +0200 Subject: [PATCH 135/693] print: do not use empty names --- src/shady/print.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/print.c b/src/shady/print.c index 282767aa0..e45b1b786 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -413,7 +413,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { } else printf(YELLOW); String name = get_value_name(node); - if (name) + if (name && strlen(name) > 0) printf("%s", name); else printf("%%%d", node->id); From 652169256aecf9b46b1c8da32e7ce8833f0081c8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:48:00 +0200 Subject: [PATCH 136/693] added option to toggle generic ptr emulation, made LEA smarter --- src/driver/cli.c | 1 + src/driver/driver.c | 2 +- src/shady/compile.c | 4 +--- src/shady/passes/lower_lea.c | 12 +++++++++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/driver/cli.c b/src/driver/cli.c index 4e53b1217..9ec6dc49e 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -90,6 +90,7 @@ if (strcmp(argv[i], "--no-"#name) == 0) { \ #define TOGGLE_OPTIONS(F) \ F(lower.emulate_physical_memory, emulate-physical-memory) \ +F(lower.emulate_generic_ptrs, emulate-generic-pointers) \ F(dynamic_scheduling, dynamic-scheduling) \ F(hacks.force_join_point_lifting, lift-join-points) \ F(hacks.assume_no_physical_global_ptrs, assume-no-physical-global-ptrs) \ diff --git a/src/driver/driver.c b/src/driver/driver.c index aedc2d9a5..576035cb3 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -33,7 +33,7 @@ SourceLanguage guess_source_language(const char* filename) { else if (string_ends_with(filename, ".slim")) return SrcShadyIR; - warn_print("unknown filename extension '%s', interpreting as Slim sourcecode by default."); + warn_print("unknown filename extension '%s', interpreting as Slim sourcecode by default.", filename); return SrcSlim; } diff --git a/src/shady/compile.c b/src/shady/compile.c index 86448a787..4ca30de75 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -122,9 +122,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_alloca) } RUN_PASS(lower_stack) - if (config->lower.emulate_physical_memory) { - RUN_PASS(lower_lea) - } + RUN_PASS(lower_lea) RUN_PASS(lower_generic_globals) if (config->lower.emulate_generic_ptrs) { RUN_PASS(lower_generic_ptrs) diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 49a3ad562..0fc2b8fe2 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -7,11 +7,13 @@ #include "log.h" #include "portability.h" +#include "shady/ir.h" #include typedef struct { Rewriter rewriter; + const CompilerConfig* config; } Context; static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* pointer_type, const Node* base, const Node* offset, size_t n_indices, const Node** indices) { @@ -105,8 +107,11 @@ static const Node* process(Context* ctx, const Node* old) { assert(old_base_ptr_t->tag == PtrType_TAG); const Node* old_result_t = old->type; deconstruct_qualified_type(&old_result_t); - // Leave logical ptrs alone - if (!is_physical_as(old_base_ptr_t->payload.ptr_type.address_space)) + bool must_lower = false; + // we have to lower generic pointers if we emulate them using ints + must_lower |= ctx->config->lower.emulate_generic_ptrs && old_base_ptr_t->payload.ptr_type.address_space == AsGeneric; + must_lower |= ctx->config->lower.emulate_physical_memory && is_physical_as(old_base_ptr_t->payload.ptr_type.address_space); + if (!must_lower) break; BodyBuilder* bb = begin_body(a); Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); @@ -132,7 +137,8 @@ Module* lower_lea(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process) + .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .config = config, }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); From 0839c18c1ec9b2301956830f54c3d131e612de0e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 10:48:36 +0200 Subject: [PATCH 137/693] aobench: define grid size in ao.h --- samples/aobench/ao.c | 2 +- samples/aobench/ao.cl | 2 +- samples/aobench/ao.cu | 2 +- samples/aobench/ao.h | 1 + samples/aobench/ao_main.c | 4 ++-- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/samples/aobench/ao.c b/samples/aobench/ao.c index 0b5adf560..da3c1742e 100644 --- a/samples/aobench/ao.c +++ b/samples/aobench/ao.c @@ -58,7 +58,7 @@ FUNCTION static void vnormalize(vec *c) FUNCTION static void ray_sphere_intersect(Isect *isect, const Ray *ray, const Sphere *sphere) { - vec rs; + vec rs = { 0 }; rs.x = ray->org.x - sphere->center.x; rs.y = ray->org.y - sphere->center.y; diff --git a/samples/aobench/ao.cl b/samples/aobench/ao.cl index a93631672..a61c825fc 100644 --- a/samples/aobench/ao.cl +++ b/samples/aobench/ao.cl @@ -17,7 +17,7 @@ void debug_printf_i32_i32(const __constant char*, int, int) __asm__("__shady::pr } -__attribute__((reqd_work_group_size(16, 16, 1))) +__attribute__((reqd_work_group_size(BLOCK_SIZE, BLOCK_SIZE, 1))) kernel void aobench_kernel(global unsigned char* out) { int x = get_global_id(0); int y = get_global_id(1); diff --git a/samples/aobench/ao.cu b/samples/aobench/ao.cu index 2cecf4c73..e51799134 100644 --- a/samples/aobench/ao.cu +++ b/samples/aobench/ao.cu @@ -10,7 +10,7 @@ __global__ void aobench_kernel(unsigned char* out) { long int ptr = (long int) out; Ctx ctx = get_init_context(); init_scene(&ctx); - // render_pixel(&ctx, x, y, WIDTH, HEIGHT, NSUBSAMPLES, out); + render_pixel(&ctx, x, y, WIDTH, HEIGHT, NSUBSAMPLES, out); } } \ No newline at end of file diff --git a/samples/aobench/ao.h b/samples/aobench/ao.h index dae5dda64..ee9f9130a 100644 --- a/samples/aobench/ao.h +++ b/samples/aobench/ao.h @@ -2,6 +2,7 @@ #define HEIGHT 2048 #define NSUBSAMPLES 1 #define NAO_SAMPLES 8 +#define BLOCK_SIZE 16 typedef float Scalar; diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 7d39b7dd3..38b1b7ee8 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -119,11 +119,11 @@ void render_device(Args* args, unsigned char *img, int w, int h, int nsubsamples Program* program = load_program_from_disk(runtime, &args->compiler_config, path); // run it twice to compile everything and benefit from caches - wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / 16, HEIGHT / 16, 1, 1, (void*[]) { &buf_addr })); + wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr })); struct timespec ts; timespec_get(&ts, TIME_UTC); uint64_t tsn = timespec_to_nano(ts); - wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / 16, HEIGHT / 16, 1, 1, (void*[]) { &buf_addr })); + wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr })); struct timespec tp; timespec_get(&tp, TIME_UTC); uint64_t tpn = timespec_to_nano(tp); From a63635aeb8610d63c319af01ae9fda572bff287e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 11:20:39 +0200 Subject: [PATCH 138/693] s2s: fix broken translation for LogicalNeq --- src/frontends/spirv/s2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontends/spirv/s2s.c b/src/frontends/spirv/s2s.c index 94b8a216e..c942375ec 100644 --- a/src/frontends/spirv/s2s.c +++ b/src/frontends/spirv/s2s.c @@ -298,7 +298,7 @@ static SpvShdOpMapping spv_shd_op_mapping[] = { [SpvOpOrdered] = { 0 }, [SpvOpUnordered] = { 0 }, [SpvOpLogicalEqual] = { 1, eq_op, 3 }, - [SpvOpLogicalNotEqual] = { 1, eq_op, 3 }, + [SpvOpLogicalNotEqual] = { 1, neq_op, 3 }, [SpvOpLogicalOr] = { 1, or_op, 3 }, [SpvOpLogicalAnd] = { 1, and_op, 3 }, [SpvOpLogicalNot] = { 1, not_op, 3 }, From 28453ef4ea0015f7bafd92f2c8c278dc31b06a1f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 11:20:57 +0200 Subject: [PATCH 139/693] mem2reg: remove broken assert --- src/shady/passes/opt_mem2reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 73a813565..44b70e624 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -523,7 +523,7 @@ static void handle_bb(Context* ctx, const Node* old) { log_node(DEBUG, ptr); debug_print(" has a known value in all predecessors! Turning it into a new parameter.\n"); - assert(!is_qualified_type_uniform(source->type)); + // assert(!is_qualified_type_uniform(source->type)); const Node* param = var(a, qualified_type_helper(source->type, false), unique_name(a, "ssa_phi")); params = append_nodes(a, params, param); ptrs = append_nodes(ctx->rewriter.src_arena, ptrs, ptr); From f783b3f730cd469b9fc1d47f7480d668127241a5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 12:06:25 +0200 Subject: [PATCH 140/693] l2s: fix generic-generic ptr ops --- src/frontends/llvm/l2s_instr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index cb6877d39..8f4b150ef 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -305,6 +305,8 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM case AsGlobalPhysical: op = convert_op; break; + case AsGeneric: // generic-to-generic isn't a conversion. + break; default: { warn_print("Cannot cast address space %s to Generic! Ignoring.\n", get_address_space_name(src_t->payload.ptr_type.address_space)); r = quote_helper(a, singleton(src)); From 16f422c62ce063ca4124b6dcc155f0dd142a2d26 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 12:10:46 +0200 Subject: [PATCH 141/693] aobench: port to vcc --- samples/aobench/CMakeLists.txt | 19 ++++------- samples/aobench/ao.cl | 43 ------------------------- samples/aobench/ao.comp.cpp | 58 ++++++++++++++++++++++++++++++++++ samples/aobench/ao_main.c | 2 +- 4 files changed, 66 insertions(+), 56 deletions(-) delete mode 100644 samples/aobench/ao.cl create mode 100644 samples/aobench/ao.comp.cpp diff --git a/samples/aobench/CMakeLists.txt b/samples/aobench/CMakeLists.txt index ef8e7503f..01379a90a 100644 --- a/samples/aobench/CMakeLists.txt +++ b/samples/aobench/CMakeLists.txt @@ -1,22 +1,17 @@ -find_program(CLANG_EXE "clang") -find_program(LLVM-SPIRV_EXE "llvm-spirv") - -if (CLANG_EXE AND LLVM-SPIRV_EXE) +if (TARGET vcc) add_executable(aobench_host ao_host.c ao_main.c) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMAND vcc ARGS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp --only-run-clang -o ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMENT ao.comp.c.ll DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp) - add_custom_command(OUTPUT ao.cl.ll COMMAND clang ARGS ${CMAKE_CURRENT_SOURCE_DIR}/ao.cl -std=clc++2021 -emit-llvm -o ${CMAKE_CURRENT_BINARY_DIR}/ao.cl.ll -c -target spir64-unknown-unknown -O2 DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ao.cl ${CMAKE_CURRENT_SOURCE_DIR}/ao.c) - add_custom_command(OUTPUT ao.cl.spv COMMAND llvm-spirv ARGS ${CMAKE_CURRENT_BINARY_DIR}/ao.cl.ll -o ${CMAKE_CURRENT_BINARY_DIR}/ao.cl.spv DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.cl.ll) - - set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/ao_main.c APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.cl.spv) + set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/ao_main.c APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll) add_custom_command(TARGET aobench_host POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/ao.cl.spv - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ao.cl.spv) + ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ao.comp.c.ll) find_program(ISPC_EXE "ispc") if (ISPC_EXE) target_compile_definitions(aobench_host PUBLIC ENABLE_ISPC=1) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc COMMAND slim ARGS ao.cl.spv --output ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc --entry-point aobench_kernel COMMENT generating aobench.ispc DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.cl.spv) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc COMMAND slim ARGS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll -o ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc --entry-point aobench_kernel COMMENT generating aobench.ispc DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc.o COMMAND ispc ARGS ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc -o ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc.o --pic -g -O2 -woff COMMENT generating aobench.ispc.o DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc) add_library(aobench_ispc OBJECT ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc.o) set_target_properties(aobench_ispc PROPERTIES LINKER_LANGUAGE C) @@ -25,5 +20,5 @@ if (CLANG_EXE AND LLVM-SPIRV_EXE) target_link_libraries(aobench_host PRIVATE m shady runtime common) else() - message("Clang and/or llvm-spirv not found. Skipping aobench.") + message("Vcc not enabled. Skipping aobench.") endif() diff --git a/samples/aobench/ao.cl b/samples/aobench/ao.cl deleted file mode 100644 index a61c825fc..000000000 --- a/samples/aobench/ao.cl +++ /dev/null @@ -1,43 +0,0 @@ -#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable - -#include "ao.c" - -Scalar sqrtf(Scalar s) { return sqrt(s); } -Scalar floorf(Scalar s) { return floor(s); } -Scalar fabsf(Scalar s) { return fabs(s); } -Scalar sinf(Scalar s) { return sin(s); } -Scalar cosf(Scalar s) { return cos(s); } - -global char zero; - -extern "C" { - -void debug_printf_i64(const __constant char*, long int) __asm__("__shady::prim_op::debug_printf::i64"); -void debug_printf_i32_i32(const __constant char*, int, int) __asm__("__shady::prim_op::debug_printf::i32_i32"); - -} - -__attribute__((reqd_work_group_size(BLOCK_SIZE, BLOCK_SIZE, 1))) -kernel void aobench_kernel(global unsigned char* out) { - int x = get_global_id(0); - int y = get_global_id(1); - - long int ptr = (long int) out; - //debug_printf_i64("ptr: %lu\n", ptr); - //debug_printf_i32_i32("ptr: %d %d\n", (int) (ptr << 32), (int) ptr); - - Ctx ctx = get_init_context(); - init_scene(&ctx); - - render_pixel(&ctx, x, y, WIDTH, HEIGHT, NSUBSAMPLES, out); - /*if (((x / 16) % 2) == ((y / 16) % 2)) { - out[((y * HEIGHT) + x) * 3 + 0] = x; - out[((y * HEIGHT) + x) * 3 + 1] = y; - out[((y * HEIGHT) + x) * 3 + 2] = 0; - } else { - out[((y * HEIGHT) + x) * 3 + 0] = 255; - out[((y * HEIGHT) + x) * 3 + 1] = zero; - out[((y * HEIGHT) + x) * 3 + 2] = zero; - }*/ - //out[index] = add(in1[index], in2[index]); -} \ No newline at end of file diff --git a/samples/aobench/ao.comp.cpp b/samples/aobench/ao.comp.cpp new file mode 100644 index 000000000..7774e457a --- /dev/null +++ b/samples/aobench/ao.comp.cpp @@ -0,0 +1,58 @@ +#include + +#define compute_shader __attribute__((annotate("shady::entry_point::Compute"))) + +#define location(i) __attribute__((annotate("shady::location::"#i))) + +#define input __attribute__((address_space(389))) +#define output __attribute__((address_space(390))) +#define global __attribute__((address_space(1))) + +typedef uint32_t uvec4 __attribute__((ext_vector_type(4))); +typedef float vec4 __attribute__((ext_vector_type(4))); + +typedef uint32_t uvec3 __attribute__((ext_vector_type(3))); +typedef float vec3 __attribute__((ext_vector_type(3))); + +/*__attribute__((annotate("shady::builtin::FragCoord"))) +input vec4 fragCoord; + +location(0) input vec3 fragColor; +location(0) output vec4 outColor;*/ + +__attribute__((annotate("shady::builtin::WorkgroupId"))) +input uvec3 workgroup_id; + +__attribute__((annotate("shady::builtin::GlobalInvocationId"))) +input uvec3 global_id; + +float sqrtf(float) __asm__("shady::prim_op::sqrt"); +float sinf(float) __asm__("shady::prim_op::sin"); +float cosf(float) __asm__("shady::prim_op::cos"); +float fmodf(float, float) __asm__("shady::prim_op::mod"); +float fabsf(float) __asm__("shady::prim_op::abs"); +float floorf(float) __asm__("shady::prim_op::floor"); +#include "ao.c" + +extern "C" __attribute__((annotate("shady::workgroup_size::16::16::1"))) +compute_shader void aobench_kernel(global unsigned char* out) { + //outColor = (vec4) { fragColor[0], fragColor[1], fragColor[2], 1.0f }; + //outColor = (vec4) { fragCoord[0] / 1024, fragCoord[1] / 1024, 1.0f, 1.0f }; + + Ctx ctx = get_init_context(); + init_scene(&ctx); + + int x = global_id.x; + int y = global_id.y; + //int x = (int) fragCoord.x % 1024; + //int y = (int) fragCoord.y % 1024; + + // unsigned int out[3]; // = { 55, 0, 0}; + out[0] = 255; + out[1] = 255; + render_pixel(&ctx, x + 3, y, WIDTH, HEIGHT, NSUBSAMPLES, (unsigned char*) out); + //out[2] = 155; + // out[0] = x / 4; + // out[1] = y / 4; + //outColor = (vec4) { ((int) out[0]) / 255.0f, ((int) out[1]) / 255.0f, ((int) out[2]) / 255.0f, 1.0f }; +} \ No newline at end of file diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 38b1b7ee8..1dcbda530 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -180,7 +180,7 @@ int main(int argc, char **argv) { #endif if (do_device || do_all) { - render_device(&args, img, WIDTH, HEIGHT, NSUBSAMPLES, "./ao.cl.spv"); + render_device(&args, img, WIDTH, HEIGHT, NSUBSAMPLES, "./ao.comp.c.ll"); saveppm("device.ppm", WIDTH, HEIGHT, img); } From f44692f802e13a0f1c652fb65026fe9d58c5aeb4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 14:02:27 +0200 Subject: [PATCH 142/693] aobench: hide internal fns using static --- samples/aobench/ao.c | 24 ++++++++++++------------ samples/aobench/ao.h | 10 +++++++--- samples/aobench/ao_host.c | 2 +- samples/aobench/ao_main.c | 1 + 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/samples/aobench/ao.c b/samples/aobench/ao.c index da3c1742e..94883dad3 100644 --- a/samples/aobench/ao.c +++ b/samples/aobench/ao.c @@ -6,7 +6,7 @@ #define FUNCTION #endif -FUNCTION unsigned int FNVHash(char* str, unsigned int length) { +FUNCTION static unsigned int FNVHash(char* str, unsigned int length) { const unsigned int fnv_prime = 0x811C9DC5; unsigned int hash = 0; unsigned int i = 0; @@ -20,13 +20,13 @@ FUNCTION unsigned int FNVHash(char* str, unsigned int length) { return hash; } -FUNCTION unsigned int nrand(unsigned int* rng) { +FUNCTION static unsigned int nrand(unsigned int* rng) { unsigned int orand = *rng; *rng = FNVHash((char*) &orand, 4); return *rng; } -FUNCTION Scalar drand48(Ctx* ctx) { +FUNCTION static Scalar drand48(Ctx* ctx) { Scalar n = (nrand(&ctx->rng) / 65536.0f); n = n - floorf(n); return n; @@ -193,7 +193,7 @@ FUNCTION static void ambient_occlusion(Ctx* ctx, vec *col, const Isect *isect) col->z = occlusion; } -FUNCTION unsigned char aobench_clamp(Scalar f) +FUNCTION static unsigned char aobench_clamp(Scalar f) { Scalar s = (f * 255.5f); @@ -203,7 +203,13 @@ FUNCTION unsigned char aobench_clamp(Scalar f) return (unsigned char) s; } -FUNCTION void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamples, unsigned char* img) { +FUNCTION EXTERNAL_FN Ctx get_init_context() { + return (Ctx) { + .rng = 0xFEEFDEED, + }; +} + +FUNCTION EXTERNAL_FN void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamples, unsigned char* img) { Scalar pixel[3] = { 0, 0, 0 }; ctx->rng = x * w + y; @@ -263,7 +269,7 @@ FUNCTION void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamples img[3 * (y * w + x) + 2] = aobench_clamp(pixel[2]); } -FUNCTION void init_scene(Ctx* ctx) +FUNCTION EXTERNAL_FN void init_scene(Ctx* ctx) { ctx->spheres[0].center.x = -2.0f; ctx->spheres[0].center.y = 0.0f; @@ -288,10 +294,4 @@ FUNCTION void init_scene(Ctx* ctx) ctx->plane.n.y = 1.0f; ctx->plane.n.z = 0.0f; -} - -FUNCTION Ctx get_init_context() { - return (Ctx) { - .rng = 0xFEEFDEED, - }; } \ No newline at end of file diff --git a/samples/aobench/ao.h b/samples/aobench/ao.h index ee9f9130a..f68446109 100644 --- a/samples/aobench/ao.h +++ b/samples/aobench/ao.h @@ -64,6 +64,10 @@ typedef struct { unsigned int rng; } Ctx; -Ctx get_init_context(); -void init_scene(Ctx*); -void render_pixel(Ctx*, int x, int y, int w, int h, int nsubsamples, unsigned char* img); +#ifndef EXTERNAL_FN +#define EXTERNAL_FN static +#endif + +EXTERNAL_FN Ctx get_init_context(); +EXTERNAL_FN void init_scene(Ctx*); +EXTERNAL_FN void render_pixel(Ctx*, int x, int y, int w, int h, int nsubsamples, unsigned char* img); diff --git a/samples/aobench/ao_host.c b/samples/aobench/ao_host.c index 086cf08d6..a39213c56 100644 --- a/samples/aobench/ao_host.c +++ b/samples/aobench/ao_host.c @@ -1,3 +1,3 @@ #define private - +#define EXTERNAL_FN /* not static */ #include "ao.c" \ No newline at end of file diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 1dcbda530..fc9c07617 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -1,3 +1,4 @@ +#define EXTERNAL_FN /* not static */ #include "ao.h" #include "../runtime/runtime_app_common.h" From 8a4881306fd8780e2dfdeb8bac828a1aa31d8d50 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 14:02:46 +0200 Subject: [PATCH 143/693] l2s: deal with linkage --- src/frontends/llvm/l2s.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 02141af4c..2609fa488 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -118,7 +118,15 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { assert(fn_type->tag == FnType_TAG); assert(fn_type->payload.fn_type.param_types.count == params.count); Nodes annotations = empty(a); - annotations = append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Exported" })); + switch (LLVMGetLinkage(fn)) { + case LLVMExternalLinkage: + case LLVMExternalWeakLinkage: { + annotations = append_nodes(a, annotations, annotation(a, (Annotation) {.name = "Exported"})); + break; + } + default: + break; + } Node* f = function(p->dst, params, LLVMGetValueName(fn), annotations, fn_type->payload.fn_type.return_types); const Node* r = fn_addr_helper(a, f); insert_dict(LLVMValueRef, const Node*, p->map, fn, r); From 3731057e093a9b6f3f73f7f8ea8c5c9a2c0bca97 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 14:03:04 +0200 Subject: [PATCH 144/693] aobench: parse compiler config correctly --- samples/aobench/ao_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index fc9c07617..5ac1f2b57 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -146,10 +146,9 @@ int main(int argc, char **argv) { .dump_spv = true, } }; - CompilerConfig compiler_config = default_compiler_config(); cli_parse_common_args(&argc, argv); - cli_parse_compiler_config_args(&compiler_config, &argc, argv); + cli_parse_compiler_config_args(&args.compiler_config, &argc, argv); cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); bool do_host = false, do_ispc = false, do_device = false, do_all = true; From 83aec2920639d7805bf05c1f30255c32ae4e5c7c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 14:03:20 +0200 Subject: [PATCH 145/693] arena: fix behavior when alloc_size > block_size --- src/common/arena.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/common/arena.c b/src/common/arena.c index 2c8a37990..0cc81f621 100644 --- a/src/common/arena.c +++ b/src/common/arena.c @@ -24,7 +24,7 @@ Arena* new_arena() { *arena = (Arena) { .nblocks = 0, .maxblocks = 256, - .blocks = malloc(256 * sizeof(size_t)), + .blocks = malloc(256 * sizeof(void*)), .available = 0, }; for (int i = 0; i < arena->maxblocks; i++) @@ -40,20 +40,39 @@ void destroy_arena(Arena* arena) { free(arena); } +static void* new_block(Arena* arena, size_t size) { + assert(arena->nblocks <= arena->maxblocks); + // we need more storage for the block pointers themselves ! + if (arena->nblocks == arena->maxblocks) { + arena->maxblocks *= 2; + arena->blocks = realloc(arena->blocks, arena->maxblocks * sizeof(void*)); + } + + void* allocated = malloc(size); + assert(allocated); + arena->blocks[arena->nblocks++] = allocated; + return allocated; +} + void* arena_alloc(Arena* arena, size_t size) { size = round_up(size, (size_t) sizeof(max_align_t)); if (size == 0) return NULL; - // arena is full - if (size > arena->available) { - assert(arena->nblocks <= arena->maxblocks); - // we need more storage for the block pointers themselves ! - if (arena->nblocks == arena->maxblocks) { - arena->maxblocks *= 2; - arena->blocks = realloc(arena->blocks, arena->maxblocks); + if (size > alloc_size) { + void* allocated = new_block(arena, size); + memset(allocated, 0, size); + // swap the last two blocks + if (arena->nblocks >= 2) { + void* swap = arena->blocks[arena->nblocks - 1]; + arena->blocks[arena->nblocks - 1] = arena->blocks[arena->nblocks - 2]; + arena->blocks[arena->nblocks - 2] = swap; } + return allocated; + } - arena->blocks[arena->nblocks++] = malloc(alloc_size); + // arena is full + if (size > arena->available) { + new_block(arena, alloc_size); arena->available = alloc_size; } From cf90520d6331db814ef2ff1c90840e3a585e24c7 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 3 Apr 2024 14:03:46 +0200 Subject: [PATCH 146/693] added inline-everything flag --- include/shady/ir.h | 1 + src/driver/cli.c | 1 + src/shady/passes/opt_inline.c | 28 +++++++++++++++++++--------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 9f8b5a35a..cdc762d1c 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -286,6 +286,7 @@ struct CompilerConfig_ { bool after_every_pass; bool delete_unused_instructions; } cleanup; + bool inline_everything; } optimisations; struct { diff --git a/src/driver/cli.c b/src/driver/cli.c index 9ec6dc49e..d4831e957 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -98,6 +98,7 @@ F(logging.print_internal, print-internal) \ F(logging.print_generated, print-builtin) \ F(logging.print_generated, print-generated) \ F(lower.simt_to_explicit_simd, lower-simt-to-simd) \ +F(optimisations.inline_everything, inline-everything) \ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { int argc = *pargc; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 12e59045a..c77952be4 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -19,6 +19,7 @@ typedef struct { typedef struct { Rewriter rewriter; + const CompilerConfig* config; CallGraph* graph; const Node* old_fun; Node* fun; @@ -59,7 +60,7 @@ typedef struct { bool can_be_eliminated; } FnInliningCriteria; -static FnInliningCriteria get_inlining_heuristic(CGNode* fn_node) { +static FnInliningCriteria get_inlining_heuristic(const CompilerConfig* config, CGNode* fn_node) { FnInliningCriteria crit = { 0 }; CGEdge e; @@ -70,10 +71,8 @@ static FnInliningCriteria get_inlining_heuristic(CGNode* fn_node) { crit.num_inlineable_calls++; } - debugv_print("%s has %d callers\n", get_abstraction_name(fn_node->fn), crit.num_calls); - // a function can be inlined if it has exactly one inlineable call... - if (crit.num_inlineable_calls <= 1) + if (crit.num_inlineable_calls <= 1 || config->optimisations.inline_everything) crit.can_be_inlined = true; // avoid inlining recursive things for now @@ -91,6 +90,16 @@ static FnInliningCriteria get_inlining_heuristic(CGNode* fn_node) { if (!is_call_safely_removable(fn_node->fn)) crit.can_be_eliminated = false; + debugv_print("inlining heuristic for '%s': num_calls=%d num_inlineable_calls=%d safely_removable=%d address_leaks=%d recursive=%d inlineable=%d can_be_eliminated=%d\n", + get_abstraction_name(fn_node->fn), + crit.num_calls, + crit.num_inlineable_calls, + is_call_safely_removable(fn_node->fn), + fn_node->is_address_captured, + fn_node->is_recursive, + crit.can_be_inlined, + crit.can_be_eliminated); + return crit; } @@ -98,7 +107,7 @@ static FnInliningCriteria get_inlining_heuristic(CGNode* fn_node) { static const Node* inline_call(Context* ctx, const Node* ocallee, Nodes nargs, const Node* return_to) { assert(is_abstraction(ocallee)); - log_string(DEBUG, "Inlining '%s' inside '%s'\n", get_abstraction_name(ctx->fun), get_abstraction_name(ocallee)); + log_string(DEBUG, "Inlining '%s' inside '%s'\n", get_abstraction_name(ocallee), get_abstraction_name(ctx->fun)); Context inline_context = *ctx; inline_context.rewriter.map = clone_dict(inline_context.rewriter.map); @@ -136,7 +145,7 @@ static const Node* process(Context* ctx, const Node* node) { case Function_TAG: { if (ctx->graph) { CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, node); - if (get_inlining_heuristic(fn_node).can_be_eliminated) { + if (get_inlining_heuristic(ctx->config, fn_node).can_be_eliminated) { debugv_print("Eliminating %s because it has exactly one caller\n", get_abstraction_name(fn_node->fn)); return NULL; } @@ -166,7 +175,7 @@ static const Node* process(Context* ctx, const Node* node) { ocallee = ignore_immediate_fn_addr(ocallee); if (ocallee->tag == Function_TAG) { CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); - if (get_inlining_heuristic(fn_node).can_be_inlined && is_call_potentially_inlineable(ctx->old_fun, ocallee)) { + if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined && is_call_potentially_inlineable(ctx->old_fun, ocallee)) { debugv_print("Inlining call to %s\n", get_abstraction_name(ocallee)); Nodes nargs = rewrite_nodes(&ctx->rewriter, oargs); @@ -211,7 +220,7 @@ static const Node* process(Context* ctx, const Node* node) { ocallee = ignore_immediate_fn_addr(ocallee); if (ocallee->tag == Function_TAG) { CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); - if (get_inlining_heuristic(fn_node).can_be_inlined) { + if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined) { debugv_print("Inlining tail call to %s\n", get_abstraction_name(ocallee)); Nodes nargs = rewrite_nodes(&ctx->rewriter, node->payload.tail_call.args); return inline_call(ctx, ocallee, nargs, NULL); @@ -231,9 +240,10 @@ static const Node* process(Context* ctx, const Node* node) { KeyHash hash_node(const Node**); bool compare_node(const Node**, const Node**); -void opt_simplify_cf(SHADY_UNUSED const CompilerConfig* config, Module* src, Module* dst) { +void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .config = config, .graph = NULL, .fun = NULL, .inlined_call = NULL, From 08d4c44cda0f05bc5ac82f01574d4dee32689ae4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 4 Apr 2024 15:51:46 +0200 Subject: [PATCH 147/693] l2s: process basic blocks more reliably even with phis --- src/frontends/llvm/l2s.c | 58 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 2609fa488..0c8ea58ba 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -56,10 +56,23 @@ static const Node* write_bb_tail(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM assert(false); } +typedef struct { + LLVMBasicBlockRef bb; + LLVMValueRef instr; + Node* nbb; +} TodoBB; + const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb) { const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); if (found) return *found; + assert(false); +} + +static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); + debug_print("l2s: converting BB %s %d\n", LLVMGetBasicBlockName(bb), bb); + if (get_log_level() <= DEBUG) + LLVMDumpValue(bb); struct List* phis = new_list(LLVMValueRef); Nodes params = empty(a); @@ -85,9 +98,14 @@ const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb) { Node* nbb = basic_block(a, fn, params, name); insert_dict(LLVMValueRef, const Node*, p->map, bb, nbb); insert_dict(const Node*, struct List*, p->phis, nbb, phis); - BodyBuilder* b = begin_body(a); - nbb->payload.basic_block.body = write_bb_tail(p, nbb, b, bb, instr); - return nbb; + TodoBB todo = { + .bb = bb, + .instr = instr, + .nbb = nbb, + }; + //append_list(TodoBB, p->todo_bbs, todo); + //return nbb; + return todo; } } @@ -107,12 +125,14 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { debug_print("Converting function: %s\n", LLVMGetValueName(fn)); Nodes params = empty(a); - for (LLVMValueRef oparam = LLVMGetFirstParam(fn); oparam && oparam <= LLVMGetLastParam(fn); oparam = LLVMGetNextParam(oparam)) { + for (LLVMValueRef oparam = LLVMGetFirstParam(fn); oparam; oparam = LLVMGetNextParam(oparam)) { LLVMTypeRef ot = LLVMTypeOf(oparam); const Type* t = convert_type(p, ot); const Node* param = var(a, t, LLVMGetValueName(oparam)); insert_dict(LLVMValueRef, const Node*, p->map, oparam, param); params = append_nodes(a, params, param); + if (oparam == LLVMGetLastParam(fn)) + break; } const Type* fn_type = convert_type(p, LLVMGlobalGetValueType(fn)); assert(fn_type->tag == FnType_TAG); @@ -131,11 +151,39 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { const Node* r = fn_addr_helper(a, f); insert_dict(LLVMValueRef, const Node*, p->map, fn, r); - if (LLVMCountBasicBlocks(fn) > 0) { + /*if (LLVMCountBasicBlocks(fn) > 0) { LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); BodyBuilder* b = begin_body(a); insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); f->payload.fun.body = write_bb_tail(p, f, b, first_bb, LLVMGetFirstInstruction(first_bb)); + }*/ + + if (LLVMCountBasicBlocks(fn) > 0) { + struct List* todo_bbs = new_list(TodoBB); + + for (LLVMBasicBlockRef bb = LLVMGetEntryBasicBlock(fn); bb; bb = LLVMGetNextBasicBlock(bb)) { + if (bb == LLVMGetEntryBasicBlock(fn)) { + LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); + insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); + } else { + TodoBB todo = prepare_bb(p, f, bb); + append_list(TodoBB, todo_bbs, todo); + } + if (bb == LLVMGetLastBasicBlock(fn)) + break; + } + + LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); + BodyBuilder* entry_bb = begin_body(a); + f->payload.fun.body = write_bb_tail(p, f, entry_bb, first_bb, LLVMGetFirstInstruction(first_bb)); + + for (size_t i = 0; i < entries_count_list(todo_bbs); i++) { + TodoBB todo = read_list(TodoBB, todo_bbs)[i]; + BodyBuilder* bb = begin_body(a); + todo.nbb->payload.basic_block.body = write_bb_tail(p, todo.nbb, bb, todo.bb, todo.instr); + } + + destroy_list(todo_bbs); } return r; From 971bc83fecfeb88bf7567c0ca74d3d3d6c8aaf0a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 4 Apr 2024 15:52:12 +0200 Subject: [PATCH 148/693] l2s: process annotations first --- src/frontends/llvm/l2s.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 0c8ea58ba..7820ef882 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -198,7 +198,6 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { String intrinsic = is_llvm_intrinsic(global); if (intrinsic) { if (strcmp(intrinsic, "llvm.global.annotations") == 0) { - process_llvm_annotations(p, global); return NULL; } warn_print("Skipping unknown LLVM intrinsic function: %s\n", name); @@ -258,6 +257,10 @@ bool parse_llvm_into_shady(Module* dst, size_t len, const char* data) { .dst = dirty, }; + LLVMValueRef global_annotations = LLVMGetNamedGlobal(src, "llvm.global.annotations"); + if (global_annotations) + process_llvm_annotations(&p, global_annotations); + for (LLVMValueRef fn = LLVMGetFirstFunction(src); fn && fn <= LLVMGetNextFunction(fn); fn = LLVMGetLastFunction(src)) { convert_function(&p, fn); } From 676cc1cc4014456a4c8f008f1345d7e273574787 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 4 Apr 2024 15:52:46 +0200 Subject: [PATCH 149/693] l2s: parsing improvements --- src/frontends/llvm/l2s_instr.c | 25 +++++++++++++++++++++---- src/frontends/llvm/l2s_postprocess.c | 22 ++++++++++++++++------ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index 8f4b150ef..9a2c9bdb4 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -272,10 +272,19 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM } case LLVMSExt: { // reinterpret as signed, convert to change size, reinterpret back to target T const Type* src_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); - const Type* signed_src_t = change_int_t_sign(src_t, true); - const Type* signed_dst_t = change_int_t_sign(t, true); - r = prim_op_helper(a, convert_op, singleton(signed_dst_t), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_src_t)); - r = prim_op_helper(a, reinterpret_op, singleton(t), BIND_PREV_R(signed_dst_t)); + Nodes ops = convert_operands(p, num_ops, instr); + if (src_t->tag == Bool_TAG) { + assert(t->tag == Int_TAG); + const Node* zero = int_literal(a, (IntLiteral) { .value = 0, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); + uint64_t i = UINT64_MAX >> (64 - int_size_in_bytes(t->payload.int_type.width) * 8); + const Node* ones = int_literal(a, (IntLiteral) { .value = i, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); + r = prim_op_helper(a, select_op, empty(a), mk_nodes(a, first(ops), ones, zero)); + } else { + const Type* signed_src_t = change_int_t_sign(src_t, true); + const Type* signed_dst_t = change_int_t_sign(t, true); + r = prim_op_helper(a, convert_op, singleton(signed_dst_t), reinterpret_operands(b, ops, signed_src_t)); + r = prim_op_helper(a, reinterpret_op, singleton(t), BIND_PREV_R(signed_dst_t)); + } break; } case LLVMFPToUI: case LLVMFPToSI: @@ -439,6 +448,14 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM // TODO return (EmittedInstr) { 0 }; } + if (strcmp(intrinsic, "llvm.dbg.value") == 0) { + // TODO + return (EmittedInstr) { 0 }; + } + if (string_starts_with(intrinsic, "llvm.lifetime")) { + // don't care + return (EmittedInstr) { 0 }; + } if (string_starts_with(intrinsic, "llvm.memcpy")) { Nodes ops = convert_operands(p, num_ops, instr); num_results = 0; diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 93531b6cc..64fcf28ed 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -65,6 +65,17 @@ bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { bool compare_nodes(Nodes* a, Nodes* b); +static Nodes remake_variables(Context* ctx, Nodes old) { + IrArena* a = ctx->rewriter.dst_arena; + LARRAY(const Node*, nvars, old.count); + for (size_t i = 0; i < old.count; i++) { + const Node* node = old.nodes[i]; + nvars[i] = var(a, node->payload.var.type ? qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.var.type), false) : NULL, node->payload.var.name); + assert(nvars[i]->tag == Variable_TAG); + } + return nodes(a, old.count, nvars); +} + static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { @@ -156,7 +167,6 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { debug_print("We need to introduce a control() block at %s, pointing at %s\n.", get_abstraction_name(dom->node), get_abstraction_name(dst)); Controls** found = find_value_dict(const Node, Controls*, ctx->controls, dom->node); - assert(found); if (found) { Controls* controls = *found; const Node* join_token = NULL; @@ -174,15 +184,15 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, controls->tokens = append_nodes(a, controls->tokens, join_token); controls->destinations = append_nodes(a, controls->destinations, dst); } - Nodes nargs = recreate_variables(&ctx->rewriter, get_abstraction_params(dst)); - + Nodes nparams = remake_variables(ctx, get_abstraction_params(dst)); + //register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); Node* fn = src; if (fn->tag == BasicBlock_TAG) fn = (Node*) fn->payload.basic_block.fn; assert(fn->tag == Function_TAG); - Node* wrapper = basic_block(a, fn, nargs, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name(dst))); + Node* wrapper = basic_block(a, fn, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name(dst))); wrapper->payload.basic_block.body = join(a, (Join) { - .args = nargs, + .args = nparams, .join_point = join_token }); return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args)); @@ -247,7 +257,7 @@ void postprocess(Parser* p, Module* src, Module* dst) { ctx.rewriter.rewrite_op_fn = (RewriteOpFn) process_op; ctx.rewriter.config.process_variables = true; - // ctx.rewriter.config.search_map = false; + ctx.rewriter.config.search_map = true; // ctx.rewriter.config.write_map = false; rewrite_module(&ctx.rewriter); From 0a3eca0dfc20510725d26d12a4bce9e3a7a1e321 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 4 Apr 2024 15:53:11 +0200 Subject: [PATCH 150/693] added --restructure-everything hack --- include/shady/ir.h | 1 + samples/aobench/ao_main.c | 2 ++ src/driver/cli.c | 1 + src/shady/passes/reconvergence_heuristics.c | 8 +++++--- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index cdc762d1c..da5ac640a 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -279,6 +279,7 @@ struct CompilerConfig_ { bool spv_shuffle_instead_of_broadcast_first; bool force_join_point_lifting; bool assume_no_physical_global_ptrs; + bool restructure_everything; } hacks; struct { diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 5ac1f2b57..27c0ada03 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -147,6 +147,8 @@ int main(int argc, char **argv) { } }; + args.compiler_config.hacks.restructure_everything = true; + cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.compiler_config, &argc, argv); cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); diff --git a/src/driver/cli.c b/src/driver/cli.c index d4831e957..ec3ad9377 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -99,6 +99,7 @@ F(logging.print_generated, print-builtin) \ F(logging.print_generated, print-generated) \ F(lower.simt_to_explicit_simd, lower-simt-to-simd) \ F(optimisations.inline_everything, inline-everything) \ +F(hacks.restructure_everything, restructure-everything) \ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { int argc = *pargc; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 9047fb27c..4c92a5038 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -18,6 +18,7 @@ typedef struct Context_ { Rewriter rewriter; + const CompilerConfig* config; const Node* current_fn; const Node* current_abstraction; Scope* fwd_scope; @@ -320,11 +321,11 @@ static const Node* process_node(Context* ctx, const Node* node) { } case Case_TAG: case BasicBlock_TAG: - if (!ctx->current_fn || !lookup_annotation(ctx->current_fn, "Restructure")) + if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) break; return process_abstraction(ctx, node); case Branch_TAG: { - if (!ctx->current_fn || !lookup_annotation(ctx->current_fn, "Restructure")) + if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) break; assert(ctx->fwd_scope); @@ -469,13 +470,14 @@ static const Node* process_node(Context* ctx, const Node* node) { return recreate_node_identity(rewriter, node); } -Module* reconvergence_heuristics(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .config = config, .current_fn = NULL, .fwd_scope = NULL, .back_scope = NULL, From 89fa34ae89b4639ba1ec832729b643090e009827 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 4 Apr 2024 16:22:33 +0200 Subject: [PATCH 151/693] cuda: added envvar override --- src/runtime/cuda/cuda_runtime_program.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 5475ab4e2..241f7d941 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -55,6 +55,11 @@ static bool cuda_c_to_ptx(CudaKernel* kernel) { CHECK_NVRTC(nvrtcGetPTX(program, kernel->ptx), return false); CHECK_NVRTC(nvrtcDestroyProgram(&program), return false); + String override_file = getenv("SHADY_OVERRIDE_PTX"); + if (override_file) { + read_file(override_file, &kernel->ptx_size, &kernel->ptx); + } + return true; } From 385460ee1813b0a259ba5755af79c1a429ed6232 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 4 Apr 2024 16:22:57 +0200 Subject: [PATCH 152/693] fix ispc --- src/shady/emit/c/emit_c.c | 4 ++-- src/shady/passes/lower_workgroups.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 606eae94b..d04a8155c 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -695,6 +695,8 @@ static Module* run_backend_specific_passes(CompilerConfig* config, CEmitterConfi Module* old_mod = NULL; Module** pmod = &initial_mod; + // C lacks a nice way to express constants that can be used in type definitions afterwards, so let's just inline them all. + RUN_PASS(eliminate_constants) if (econfig->dialect == CDialect_ISPC) { RUN_PASS(lower_workgroups) } @@ -704,8 +706,6 @@ static Module* run_backend_specific_passes(CompilerConfig* config, CEmitterConfi if (config->lower.simt_to_explicit_simd) { RUN_PASS(simt2d) } - // C lacks a nice way to express constants that can be used in type definitions afterwards, so let's just inline them all. - RUN_PASS(eliminate_constants) return *pmod; } diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 1de0e5db7..a3e57f13f 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -179,6 +179,7 @@ Module* lower_workgroups(const CompilerConfig* config, Module* src) { .config = config, .globals = calloc(sizeof(Node*), PRIMOPS_COUNT), }; + ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); free(ctx.globals); destroy_rewriter(&ctx.rewriter); From 13c0351ab745baf451743ccb273360994065d06b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 4 Apr 2024 16:23:11 +0200 Subject: [PATCH 153/693] misc. and cleanup --- src/shady/passes/infer.c | 2 +- src/shady/print.c | 5 ++--- src/shady/rewrite.c | 6 ------ 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 02d88d277..5b344c34c 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -686,7 +686,7 @@ static const Node* _infer_control(Context* ctx, const Node* node, const Type* ex }); jpt = qualified_type(a, (QualifiedType) { .is_uniform = true, .type = jpt }); const Node* jp = var(a, jpt, ojp->payload.var.name); - register_processed(&ctx->rewriter, ojp, jp); + register_processed(&joinable_ctx.rewriter, ojp, jp); const Node* nlam = case_(a, singleton(jp), infer(&joinable_ctx, get_abstraction_body(olam), NULL)); diff --git a/src/shady/print.c b/src/shady/print.c index e45b1b786..76f0bc7a7 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -414,9 +414,8 @@ static void print_value(PrinterCtx* ctx, const Node* node) { printf(YELLOW); String name = get_value_name(node); if (name && strlen(name) > 0) - printf("%s", name); - else - printf("%%%d", node->id); + printf("%s_", name); + printf("%%%d", node->id); printf(RESET); break; case UntypedNumber_TAG: diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index d067cf898..80e012c0e 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -214,12 +214,6 @@ Nodes recreate_variables(Rewriter* rewriter, Nodes old) { return nodes(rewriter->dst_arena, old.count, nvars); } -Node* clone_bb_head(Rewriter* r, const Node* bb) { - assert(bb && bb->tag == BasicBlock_TAG); - Nodes nparams = recreate_variables(r, get_abstraction_params(bb)); - return basic_block(r->dst_arena, (Node*) bb->payload.basic_block.fn, nparams, get_abstraction_name(bb)); -} - Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { Node* new = NULL; switch (is_declaration(old)) { From 1ee34e785eecd8fc4c6469a7cd7740fddb44375c Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 7 Apr 2024 14:20:20 +0200 Subject: [PATCH 154/693] fix cmake dependencies --- CMakeLists.txt | 1 + src/driver/CMakeLists.txt | 26 +++++++++++++++----------- src/frontends/llvm/CMakeLists.txt | 1 - src/frontends/slim/CMakeLists.txt | 1 - src/frontends/spirv/CMakeLists.txt | 3 +-- src/runtime/CMakeLists.txt | 6 ++---- src/runtime/cuda/CMakeLists.txt | 5 ++--- src/runtime/vulkan/CMakeLists.txt | 7 +++---- src/shady/CMakeLists.txt | 7 +++---- src/shady/emit/CMakeLists.txt | 3 --- src/shady/emit/c/CMakeLists.txt | 14 +++++++++----- src/shady/emit/spirv/CMakeLists.txt | 12 ++++++++---- 12 files changed, 44 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c26181e6..7b0e42bc4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ find_package(Git) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) if (MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index 5691df311..e58a9ee01 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -1,28 +1,32 @@ add_library(driver driver.c cli.c) -target_link_libraries(driver PUBLIC "$" shady_spirv shady_c shady_emit_common) -set_property(TARGET driver PROPERTY POSITION_INDEPENDENT_CODE ON) - -add_executable(slim slim.c) -target_link_libraries(slim PRIVATE driver) -install(TARGETS slim EXPORT shady_export_set) +target_link_libraries(driver PUBLIC "$") +target_link_libraries(driver PUBLIC "$") +set_target_properties(driver PROPERTIES OUTPUT_NAME "shady_driver") +install(TARGETS driver EXPORT shady_export_set) if (TARGET shady_s2s) target_compile_definitions(driver PUBLIC SPV_PARSER_PRESENT) - target_link_libraries(driver PRIVATE shady_s2s) + target_link_libraries(driver PUBLIC "$") endif() if (TARGET shady_fe_llvm) - target_link_libraries(driver PRIVATE shady_fe_llvm) target_compile_definitions(driver PUBLIC LLVM_PARSER_PRESENT) + target_link_libraries(driver PUBLIC "$") +endif () +add_executable(slim slim.c) +target_link_libraries(slim PRIVATE driver) +install(TARGETS slim EXPORT shady_export_set) + +if (TARGET shady_fe_llvm) add_executable(vcc vcc.c) - target_link_libraries(vcc PRIVATE driver api common) + target_link_libraries(vcc PRIVATE driver api) install(TARGETS vcc EXPORT shady_export_set) if (WIN32) add_custom_command(TARGET vcc POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy -t $ $ - COMMAND_EXPAND_LISTS + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS ) endif () endif () diff --git a/src/frontends/llvm/CMakeLists.txt b/src/frontends/llvm/CMakeLists.txt index 868b22e02..d3b7f103e 100644 --- a/src/frontends/llvm/CMakeLists.txt +++ b/src/frontends/llvm/CMakeLists.txt @@ -19,4 +19,3 @@ message(FATAL_ERROR "Failed to find LLVM-C target, but found LLVM module earlier endif() target_link_libraries(shady_fe_llvm PRIVATE api common shady) -set_property(TARGET shady_fe_llvm PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/frontends/slim/CMakeLists.txt b/src/frontends/slim/CMakeLists.txt index df7c30cb0..e52435573 100644 --- a/src/frontends/slim/CMakeLists.txt +++ b/src/frontends/slim/CMakeLists.txt @@ -2,5 +2,4 @@ add_library(slim_parser STATIC parser.c token.c) target_link_libraries(slim_parser PUBLIC common api) target_include_directories(slim_parser PUBLIC $) target_include_directories(slim_parser INTERFACE "$") -set_property(TARGET slim_parser PROPERTY POSITION_INDEPENDENT_CODE ON) target_link_libraries(shady PUBLIC "$") diff --git a/src/frontends/spirv/CMakeLists.txt b/src/frontends/spirv/CMakeLists.txt index ae1786be6..7956754dc 100644 --- a/src/frontends/spirv/CMakeLists.txt +++ b/src/frontends/spirv/CMakeLists.txt @@ -1,4 +1,3 @@ add_library(shady_s2s STATIC s2s.c) -target_link_libraries(shady_s2s PRIVATE api common shady) +target_link_libraries(shady_s2s PRIVATE api common) target_link_libraries(shady_s2s PRIVATE "$") -set_property(TARGET shady_s2s PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index 0f1a4ab39..e1f271fc3 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -1,7 +1,5 @@ -add_library(runtime SHARED runtime.c runtime_program.c) -target_link_libraries(runtime PUBLIC shady) -target_link_libraries(runtime PUBLIC "$") -set_property(TARGET runtime PROPERTY POSITION_INDEPENDENT_CODE ON) +add_library(runtime runtime.c runtime_program.c) +target_link_libraries(runtime PUBLIC driver) set_target_properties(runtime PROPERTIES OUTPUT_NAME "shady_runtime") add_subdirectory(vulkan) diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index 767551fe5..77ec98b04 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -3,12 +3,11 @@ find_package(CUDAToolkit) if (CUDAToolkit_FOUND) message("Cuda toolkit found.") add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c cuda_runtime_program.c) - target_link_libraries(cuda_runtime PUBLIC api) - target_link_libraries(cuda_runtime PUBLIC shady) + target_link_libraries(cuda_runtime PRIVATE api) target_link_libraries(cuda_runtime PRIVATE "$") target_link_libraries(cuda_runtime PRIVATE "$") target_link_libraries(cuda_runtime PRIVATE CUDA::cudart CUDA::cuda_driver CUDA::nvrtc) - set_property(TARGET cuda_runtime PROPERTY POSITION_INDEPENDENT_CODE ON) + target_link_libraries(runtime PRIVATE cuda_runtime) target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) endif () \ No newline at end of file diff --git a/src/runtime/vulkan/CMakeLists.txt b/src/runtime/vulkan/CMakeLists.txt index e7b2b6430..25935ea7b 100644 --- a/src/runtime/vulkan/CMakeLists.txt +++ b/src/runtime/vulkan/CMakeLists.txt @@ -3,14 +3,13 @@ find_package(Vulkan) if (Vulkan_FOUND) message("Vulkan found") add_library(vk_runtime STATIC vk_runtime.c vk_runtime_device.c vk_runtime_program.c vk_runtime_dispatch.c vk_runtime_buffer.c) - target_link_libraries(vk_runtime PUBLIC api) - target_link_libraries(vk_runtime PUBLIC shady) + target_link_libraries(vk_runtime PRIVATE api) target_link_libraries(vk_runtime PRIVATE "$") target_link_libraries(vk_runtime PRIVATE "$") target_link_libraries(vk_runtime PRIVATE Vulkan::Headers Vulkan::Vulkan) - set_property(TARGET vk_runtime PROPERTY POSITION_INDEPENDENT_CODE ON) - target_link_libraries(runtime PRIVATE vk_runtime) + target_compile_definitions(runtime PUBLIC VK_BACKEND_PRESENT=1) + target_link_libraries(runtime PRIVATE "$") else() message("Vulkan not found, runtime component will not be built.") endif() diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index cae92c0f5..f143bf281 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -96,9 +96,8 @@ set(SHADY_SOURCES passes/spirv_lift_globals_ssbo.c ) -add_library(shady OBJECT ${SHADY_SOURCES}) +add_library(shady ${SHADY_SOURCES}) target_include_directories(shady PUBLIC $) -set_property(TARGET shady PROPERTY POSITION_INDEPENDENT_CODE ON) if (WIN32) if (MSVC) @@ -111,7 +110,7 @@ endif() add_subdirectory(internal) add_subdirectory(emit) -target_link_libraries(shady PUBLIC "api") -target_link_libraries(shady PUBLIC "$") +target_link_libraries(shady PRIVATE "api") +target_link_libraries(shady INTERFACE "$") target_link_libraries(shady PRIVATE "$") target_link_libraries(shady PRIVATE "$") diff --git a/src/shady/emit/CMakeLists.txt b/src/shady/emit/CMakeLists.txt index 82efbf5d6..9be2855c0 100644 --- a/src/shady/emit/CMakeLists.txt +++ b/src/shady/emit/CMakeLists.txt @@ -4,6 +4,3 @@ add_subdirectory(c) add_library(shady_emit_common OBJECT common.c ) - -target_link_libraries(shady PRIVATE "$") -target_link_libraries(shady PRIVATE "$") diff --git a/src/shady/emit/c/CMakeLists.txt b/src/shady/emit/c/CMakeLists.txt index 5f904a7ad..4896b6d2f 100644 --- a/src/shady/emit/c/CMakeLists.txt +++ b/src/shady/emit/c/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(shady_c OBJECT +add_library(shady_c STATIC emit_c.c emit_c_instructions.c emit_c_signatures.c @@ -6,12 +6,16 @@ add_library(shady_c OBJECT ) set_property(TARGET shady_c PROPERTY POSITION_INDEPENDENT_CODE ON) -target_include_directories(shady_c PUBLIC $) -target_link_libraries(shady_c PUBLIC "api") +target_include_directories(shady_c PRIVATE $) + +target_link_libraries(shady_c PRIVATE "api") +target_link_libraries(shady_c INTERFACE "shady") target_link_libraries(shady_c PRIVATE "$") -target_link_libraries(shady_c PUBLIC "$") +target_link_libraries(shady_c PRIVATE "$") embed_file(string shady_cuda_prelude_src cuda_prelude.cu) embed_file(string shady_cuda_builtins_src cuda_builtins.cu) target_link_libraries(shady_c PRIVATE "$") -target_link_libraries(shady_c PRIVATE "$") \ No newline at end of file +target_link_libraries(shady_c PRIVATE "$") + +target_link_libraries(shady PUBLIC "$") diff --git a/src/shady/emit/spirv/CMakeLists.txt b/src/shady/emit/spirv/CMakeLists.txt index 7dd2894b6..d3de7ace3 100644 --- a/src/shady/emit/spirv/CMakeLists.txt +++ b/src/shady/emit/spirv/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(shady_spirv OBJECT +add_library(shady_spirv STATIC emit_spv.c emit_spv_type.c emit_spv_instructions.c @@ -6,8 +6,12 @@ add_library(shady_spirv OBJECT ) set_property(TARGET shady_spirv PROPERTY POSITION_INDEPENDENT_CODE ON) -target_include_directories(shady_spirv PUBLIC $) -target_link_libraries(shady_spirv PUBLIC "api") +target_include_directories(shady_spirv PRIVATE $) + +target_link_libraries(shady_spirv PRIVATE "api") +target_link_libraries(shady_spirv INTERFACE "shady") target_link_libraries(shady_spirv PRIVATE "$") target_link_libraries(shady_spirv PRIVATE "$") -target_link_libraries(shady_spirv PUBLIC "$") \ No newline at end of file +target_link_libraries(shady_spirv PRIVATE "$") + +target_link_libraries(shady PUBLIC "$") From 76602a2a0f629b2b174043503425c38e171555f5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 8 Apr 2024 15:47:17 +0200 Subject: [PATCH 155/693] fix cuda-runtime dep leaking --- src/runtime/cuda/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index 77ec98b04..31592995b 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -8,6 +8,6 @@ if (CUDAToolkit_FOUND) target_link_libraries(cuda_runtime PRIVATE "$") target_link_libraries(cuda_runtime PRIVATE CUDA::cudart CUDA::cuda_driver CUDA::nvrtc) - target_link_libraries(runtime PRIVATE cuda_runtime) + target_link_libraries(runtime PRIVATE "$") target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) endif () \ No newline at end of file From f296018faadf4e3d14701393aa29e45cfea3727b Mon Sep 17 00:00:00 2001 From: Michael Kenzel Date: Tue, 9 Apr 2024 12:22:38 +0200 Subject: [PATCH 156/693] fix windows build --- src/common/portability.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/portability.h b/src/common/portability.h index 33187f234..626d8203e 100644 --- a/src/common/portability.h +++ b/src/common/portability.h @@ -20,7 +20,7 @@ static_assert(__STDC_VERSION__ >= 201112L, "C11 support is required to build sha #define SHADY_FALLTHROUGH // It's mid 2022, and this typedef is missing from // MSVC is not a real C11 compiler. - typedef long long max_align_t; + typedef double max_align_t; #else #ifdef USE_VLAS #define LARRAY(T, name, size) T name[size] From d8c40fb9f138f2bdab023ab3751f5878e3b02709 Mon Sep 17 00:00:00 2001 From: Michael Kenzel Date: Tue, 9 Apr 2024 12:25:00 +0200 Subject: [PATCH 157/693] fix CUDA 12 build --- src/shady/emit/c/emit_c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index d04a8155c..0040c0bda 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -396,7 +396,6 @@ void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const T break; case CDialect_C11: case CDialect_CUDA: - prefix = "register "; center = format_string_arena(emitter->arena->arena, "const %s", center); break; case CDialect_GLSL: From 987968ea4c1ee812cb636b51b4a71576a950f164 Mon Sep 17 00:00:00 2001 From: Michael Kenzel Date: Tue, 9 Apr 2024 12:25:15 +0200 Subject: [PATCH 158/693] fix CUDA on windows --- src/shady/emit/c/emit_c_signatures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index 724328efd..a56ef2235 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -160,7 +160,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { { "unsigned char" , "char" }, { "unsigned short", "short" }, { "unsigned int" , "int" }, - { "unsigned long" , "long" }, + { "unsigned long long" , "long long" }, }; const char* c_explicit_int_sizes[4][2] = { { "uint8_t" , "int8_t" }, From 75f4a3e2e9630b67623b69b7906472a5558006d6 Mon Sep 17 00:00:00 2001 From: Michael Kenzel Date: Tue, 9 Apr 2024 12:37:00 +0200 Subject: [PATCH 159/693] fix double free upon read_file failure --- src/driver/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver/driver.c b/src/driver/driver.c index 576035cb3..ee7293aac 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -85,8 +85,8 @@ ShadyErrorCodes driver_load_source_file_from_filename(const char* filename, Modu goto exit; } err = driver_load_source_file(lang, len, contents, mod); - exit: free((void*) contents); + exit: return err; } From 0d763beddc6d202c992d7754b580b0094429a4b2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 9 Apr 2024 12:53:37 +0200 Subject: [PATCH 160/693] rework infer pass --- src/shady/passes/infer.c | 159 +++++++++++++++++++++------------------ src/shady/type_helpers.c | 4 +- 2 files changed, 88 insertions(+), 75 deletions(-) diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 5b344c34c..8ecaa24e2 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -36,6 +36,9 @@ typedef struct { const Nodes* continue_types; } Context; +static const Node* infer_value(Context* ctx, const Node* node, const Type* expected_type); +static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes* expected_types); + static const Node* infer(Context* ctx, const Node* node, const Type* expect) { Context ctx2 = *ctx; ctx2.expected_type = expect; @@ -51,7 +54,7 @@ static Nodes infer_nodes(Context* ctx, Nodes nodes) { #define rewrite_node error("don't use this directly, use the 'infer' and 'infer_node' helpers") #define rewrite_nodes rewrite_node -static const Node* _infer_annotation(Context* ctx, const Node* node) { +static const Node* infer_annotation(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; assert(is_annotation(node)); switch (node->tag) { @@ -63,7 +66,7 @@ static const Node* _infer_annotation(Context* ctx, const Node* node) { } } -static const Node* _infer_type(Context* ctx, const Type* type) { +static const Node* infer_type(Context* ctx, const Type* type) { IrArena* a = ctx->rewriter.dst_arena; switch (type->tag) { case ArrType_TAG: { @@ -83,7 +86,7 @@ static const Node* _infer_type(Context* ctx, const Type* type) { } } -static const Node* _infer_decl(Context* ctx, const Node* node) { +static const Node* infer_decl(Context* ctx, const Node* node) { assert(is_declaration(node)); const Node* already_done = search_processed(&ctx->rewriter, node); if (already_done) @@ -117,9 +120,10 @@ static const Node* _infer_decl(Context* ctx, const Node* node) { const Node* instruction; if (imported_hint) { assert(is_data_type(imported_hint)); - instruction = infer(ctx, oconstant->instruction, qualified_type_helper(imported_hint, true)); + Nodes s = singleton(qualified_type_helper(imported_hint, true)); + instruction = infer_instruction(ctx, oconstant->instruction, &s); } else { - instruction = infer(ctx, oconstant->instruction, NULL); + instruction = infer_instruction(ctx, oconstant->instruction, NULL); } imported_hint = get_unqualified_type(instruction->type); @@ -156,13 +160,9 @@ static const Type* remove_uniformity_qualifier(const Node* type) { return type; } -static const Node* _infer_value(Context* ctx, const Node* node, const Type* expected_type) { +static const Node* infer_value(Context* ctx, const Node* node, const Type* expected_type) { if (!node) return NULL; - if (expected_type) { - assert(is_value_type(expected_type)); - } - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (is_value(node)) { @@ -302,11 +302,9 @@ static const Node* _infer_value(Context* ctx, const Node* node, const Type* expe return recreate_node_identity(&ctx->rewriter, node); } -static const Node* _infer_case(Context* ctx, const Node* node, const Node* expected) { +static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg_type) { IrArena* a = ctx->rewriter.dst_arena; assert(is_case(node)); - assert(expected); - Nodes inferred_arg_type = unwrap_multiple_yield_types(a, expected); assert(inferred_arg_type.count == node->payload.case_.params.count || node->payload.case_.params.count == 0); Context body_context = *ctx; @@ -319,7 +317,7 @@ static const Node* _infer_case(Context* ctx, const Node* node, const Node* expec const Variable* old_param = &node->payload.case_.params.nodes[i]->payload.var; // for the param type: use the inferred one if none is already provided // if one is provided, check the inferred argument type is a subtype of the param type - const Type* param_type = infer(ctx, old_param->type, NULL); + const Type* param_type = old_param->type ? infer_type(ctx, old_param->type) : NULL; // and do not use the provided param type if it is an untyped ptr if (!param_type || param_type->tag != PtrType_TAG || param_type->payload.ptr_type.pointed_type) param_type = inferred_arg_type.nodes[i]; @@ -409,7 +407,7 @@ static void fix_source_pointer(BodyBuilder* bb, const Node** operand, const Type } } -static const Node* _infer_primop(Context* ctx, const Node* node, const Type* expected_type) { +static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* expected_types) { assert(node->tag == PrimOp_TAG); IrArena* a = ctx->rewriter.dst_arena; @@ -586,7 +584,7 @@ static const Node* _infer_primop(Context* ctx, const Node* node, const Type* exp } } -static const Node* _infer_indirect_call(Context* ctx, const Node* node, const Type* expected_type) { +static const Node* infer_indirect_call(Context* ctx, const Node* node, const Nodes* expected_types) { assert(node->tag == Call_TAG); IrArena* a = ctx->rewriter.dst_arena; @@ -616,21 +614,21 @@ static const Node* _infer_indirect_call(Context* ctx, const Node* node, const Ty }); } -static const Node* _infer_if(Context* ctx, const Node* node, const Type* expected_type) { +static const Node* infer_if(Context* ctx, const Node* node, const Nodes* expected_types) { assert(node->tag == If_TAG); IrArena* a = ctx->rewriter.dst_arena; - const Node* condition = infer(ctx, node->payload.if_instr.condition, bool_type(a)); + const Node* condition = infer(ctx, node->payload.if_instr.condition, qualified_type_helper(bool_type(a), false)); Nodes join_types = infer_nodes(ctx, node->payload.if_instr.yield_types); Context infer_if_body_ctx = *ctx; // When we infer the types of the arguments to a call to merge(), they are expected to be varying - Nodes expected_join_types = annotate_all_types(a, join_types, false); + Nodes expected_join_types = add_qualifiers(a, join_types, false); infer_if_body_ctx.merge_types = &expected_join_types; - const Node* true_body = infer(&infer_if_body_ctx, node->payload.if_instr.if_true, wrap_multiple_yield_types(a, nodes(a, 0, NULL))); + const Node* true_body = infer_case(&infer_if_body_ctx, node->payload.if_instr.if_true, nodes(a, 0, NULL)); // don't allow seeing the variables made available in the true branch infer_if_body_ctx.rewriter = ctx->rewriter; - const Node* false_body = node->payload.if_instr.if_false ? infer(&infer_if_body_ctx, node->payload.if_instr.if_false, wrap_multiple_yield_types(a, nodes(a, 0, NULL))) : NULL; + const Node* false_body = node->payload.if_instr.if_false ? infer_case(&infer_if_body_ctx, node->payload.if_instr.if_false, nodes(a, 0, NULL)) : NULL; return if_instr(a, (If) { .yield_types = join_types, @@ -640,7 +638,7 @@ static const Node* _infer_if(Context* ctx, const Node* node, const Type* expecte }); } -static const Node* _infer_loop(Context* ctx, const Node* node, const Type* expected_type) { +static const Node* infer_loop(Context* ctx, const Node* node, const Nodes* expected_types) { assert(node->tag == Loop_TAG); IrArena* a = ctx->rewriter.dst_arena; Context loop_body_ctx = *ctx; @@ -649,6 +647,7 @@ static const Node* _infer_loop(Context* ctx, const Node* node, const Type* expec Nodes old_params = get_abstraction_params(old_body); Nodes old_params_types = get_variables_types(a, old_params); Nodes new_params_types = infer_nodes(ctx, old_params_types); + new_params_types = annotate_all_types(a, new_params_types, false); Nodes old_initial_args = node->payload.loop_instr.initial_args; LARRAY(const Node*, new_initial_args, old_params.count); @@ -656,12 +655,13 @@ static const Node* _infer_loop(Context* ctx, const Node* node, const Type* expec new_initial_args[i] = infer(ctx, old_initial_args.nodes[i], new_params_types.nodes[i]); Nodes loop_yield_types = infer_nodes(ctx, node->payload.loop_instr.yield_types); + Nodes qual_yield_types = add_qualifiers(a, loop_yield_types, false); loop_body_ctx.merge_types = NULL; - loop_body_ctx.break_types = &loop_yield_types; + loop_body_ctx.break_types = &qual_yield_types; loop_body_ctx.continue_types = &new_params_types; - const Node* nbody = infer(&loop_body_ctx, old_body, wrap_multiple_yield_types(a, new_params_types)); + const Node* nbody = infer_case(&loop_body_ctx, old_body, new_params_types); // TODO check new body params match continue types return loop_instr(a, (Loop) { @@ -671,7 +671,7 @@ static const Node* _infer_loop(Context* ctx, const Node* node, const Type* expec }); } -static const Node* _infer_control(Context* ctx, const Node* node, const Type* expected_type) { +static const Node* infer_control(Context* ctx, const Node* node, const Nodes* expected_types) { assert(node->tag == Control_TAG); IrArena* a = ctx->rewriter.dst_arena; @@ -696,7 +696,7 @@ static const Node* _infer_control(Context* ctx, const Node* node, const Type* ex }); } -static const Node* _infer_block(Context* ctx, const Node* node, const Type* expected_type) { +static const Node* infer_block(Context* ctx, const Node* node, const Nodes* expected_types) { assert(node->tag == Block_TAG); IrArena* a = ctx->rewriter.dst_arena; @@ -712,15 +712,15 @@ static const Node* _infer_block(Context* ctx, const Node* node, const Type* expe }); } -static const Node* _infer_instruction(Context* ctx, const Node* node, const Type* expected_type) { +static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes* expected_types) { switch (is_instruction(node)) { - case PrimOp_TAG: return _infer_primop(ctx, node, expected_type); - case Call_TAG: return _infer_indirect_call(ctx, node, expected_type); - case If_TAG: return _infer_if (ctx, node, expected_type); - case Loop_TAG: return _infer_loop (ctx, node, expected_type); + case PrimOp_TAG: return infer_primop(ctx, node, expected_types); + case Call_TAG: return infer_indirect_call(ctx, node, expected_types); + case If_TAG: return infer_if (ctx, node, expected_types); + case Loop_TAG: return infer_loop (ctx, node, expected_types); case Match_TAG: error("TODO") - case Control_TAG: return _infer_control(ctx, node, expected_type); - case Block_TAG: return _infer_block (ctx, node, expected_type); + case Control_TAG: return infer_control(ctx, node, expected_types); + case Block_TAG: return infer_block (ctx, node, expected_types); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); default: error("TODO") case NotAnInstruction: error("not an instruction"); @@ -728,19 +728,19 @@ static const Node* _infer_instruction(Context* ctx, const Node* node, const Type SHADY_UNREACHABLE; } -static const Node* _infer_terminator(Context* ctx, const Node* node) { +static const Node* infer_terminator(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; switch (is_terminator(node)) { case NotATerminator: assert(false); case Let_TAG: { const Node* otail = node->payload.let.tail; Nodes annotated_types = get_variables_types(a, otail->payload.case_.params); - const Node* inferred_instruction = infer(ctx, node->payload.let.instruction, wrap_multiple_yield_types(a, annotated_types)); + const Node* inferred_instruction = infer_instruction(ctx, node->payload.let.instruction, &annotated_types); Nodes inferred_yield_types = unwrap_multiple_yield_types(a, inferred_instruction->type); for (size_t i = 0; i < inferred_yield_types.count; i++) { assert(is_value_type(inferred_yield_types.nodes[i])); } - const Node* inferred_tail = infer(ctx, otail, wrap_multiple_yield_types(a, inferred_yield_types)); + const Node* inferred_tail = infer_case(ctx, otail, inferred_yield_types); return let(a, inferred_instruction, inferred_tail); } case Return_TAG: { @@ -776,40 +776,49 @@ static const Node* _infer_terminator(Context* ctx, const Node* node) { case Terminator_Switch_TAG: break; case Terminator_TailCall_TAG: break; case Terminator_Yield_TAG: { - const Nodes* expected_types = ctx->merge_types; // TODO: block nodes should set merge types - assert(expected_types && "Merge terminator found but we're not within a suitable if instruction !"); - const Nodes* old_args = &node->payload.yield.args; - assert(expected_types->count == old_args->count); - LARRAY(const Node*, new_args, old_args->count); - for (size_t i = 0; i < old_args->count; i++) - new_args[i] = infer(ctx, old_args->nodes[i], (*expected_types).nodes[i]); + assert(ctx->merge_types && "Merge terminator found but we're not within a suitable if instruction !"); + Nodes expected_types = *ctx->merge_types; + Nodes old_args = node->payload.yield.args; + assert(expected_types.count == old_args.count); + LARRAY(const Node*, new_args, old_args.count); + for (size_t i = 0; i < old_args.count; i++) { + const Node* e = expected_types.nodes[i]; + assert(is_value_type(e)); + new_args[i] = infer(ctx, old_args.nodes[i], e); + } return yield(a, (Yield) { - .args = nodes(a, old_args->count, new_args) + .args = nodes(a, old_args.count, new_args) }); } case MergeContinue_TAG: { - const Nodes* expected_types = ctx->continue_types; - assert(expected_types && "Merge terminator found but we're not within a suitable loop instruction !"); - const Nodes* old_args = &node->payload.merge_continue.args; - assert(expected_types->count == old_args->count); - LARRAY(const Node*, new_args, old_args->count); - for (size_t i = 0; i < old_args->count; i++) - new_args[i] = infer(ctx, old_args->nodes[i], (*expected_types).nodes[i]); + assert(ctx->continue_types && "Merge terminator found but we're not within a suitable loop instruction !"); + Nodes expected_types = *ctx->continue_types; + Nodes old_args = node->payload.yield.args; + assert(expected_types.count == old_args.count); + LARRAY(const Node*, new_args, old_args.count); + for (size_t i = 0; i < old_args.count; i++) { + const Node* e = expected_types.nodes[i]; + assert(is_value_type(e)); + new_args[i] = infer(ctx, old_args.nodes[i], e); + } return merge_continue(a, (MergeContinue) { - .args = nodes(a, old_args->count, new_args) + .args = nodes(a, old_args.count, new_args) }); } case MergeBreak_TAG: { - const Nodes* expected_types = ctx->break_types; - assert(expected_types && "Merge terminator found but we're not within a suitable loop instruction !"); - const Nodes* old_args = &node->payload.merge_break.args; - assert(expected_types->count == old_args->count); - LARRAY(const Node*, new_args, old_args->count); - for (size_t i = 0; i < old_args->count; i++) - new_args[i] = infer(ctx, old_args->nodes[i], (*expected_types).nodes[i]); + assert(ctx->break_types && "Merge terminator found but we're not within a suitable loop instruction !"); + Nodes expected_types = *ctx->break_types; + Nodes old_args = node->payload.yield.args; + assert(expected_types.count == old_args.count); + LARRAY(const Node*, new_args, old_args.count); + for (size_t i = 0; i < old_args.count; i++) { + const Node* e = expected_types.nodes[i]; + assert(is_value_type(e)); + new_args[i] = infer(ctx, old_args.nodes[i], e); + } return merge_break(a, (MergeBreak) { - .args = nodes(a, old_args->count, new_args) + .args = nodes(a, old_args.count, new_args) }); } case Unreachable_TAG: return unreachable(a); @@ -822,7 +831,7 @@ static const Node* _infer_terminator(Context* ctx, const Node* node) { } static const Node* process(Context* src_ctx, const Node* node) { - const Type* expect = src_ctx->expected_type; + const Node* expected_type = src_ctx->expected_type; Context ctx = *src_ctx; ctx.expected_type = NULL; @@ -834,25 +843,27 @@ static const Node* process(Context* src_ctx, const Node* node) { } if (is_type(node)) { - assert(expect == NULL); - return _infer_type(&ctx, node); + assert(expected_type == NULL); + return infer_type(&ctx, node); } else if (is_value(node)) { - const Node* value = _infer_value(&ctx, node, expect); + const Node* value = infer_value(&ctx, node, expected_type); assert(is_value_type(value->type)); return value; - }else if (is_instruction(node)) - return _infer_instruction(&ctx, node, expect); - else if (is_terminator(node)) { - assert(expect == NULL); - return _infer_terminator(&ctx, node); + } else if (is_instruction(node)) { + assert(false); + //return infer_instruction(&ctx, node, expected_type); + } else if (is_terminator(node)) { + assert(expected_type == NULL); + return infer_terminator(&ctx, node); } else if (is_declaration(node)) { - return _infer_decl(&ctx, node); + return infer_decl(&ctx, node); } else if (is_annotation(node)) { - assert(expect == NULL); - return _infer_annotation(&ctx, node); + assert(expected_type == NULL); + return infer_annotation(&ctx, node); } else if (is_case(node)) { - assert(expect != NULL); - return _infer_case(&ctx, node, expect); + assert(false); + //assert(expected_types != NULL); + //return infer_case(&ctx, node, expected_types); } else if (is_basic_block(node)) { return _infer_basic_block(&ctx, node); } diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 94f9694a2..3fe05d656 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -24,7 +24,9 @@ Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type) { if (type->payload.record_type.special == MultipleReturn) return type->payload.record_type.members; // fallthrough - default: return nodes(arena, 1, (const Node* []) { type }); + default: + assert(is_value_type(type)); + return nodes(arena, 1, (const Node* []) { type }); } } From 791dcd2e85cfebcc5b21cf7222dfb62bd613266a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 9 Apr 2024 14:18:42 +0200 Subject: [PATCH 161/693] rewrote free variables analysis to do a whole scope at once --- include/shady/ir.h | 1 + src/common/dict.c | 8 ++ src/common/dict.h | 3 + src/shady/analysis/free_variables.c | 127 +++++++++++++++++------ src/shady/analysis/free_variables.h | 10 +- src/shady/analysis/scope.c | 7 +- src/shady/analysis/verify.c | 13 ++- src/shady/node.c | 10 ++ src/shady/passes/lcssa.c | 12 ++- src/shady/passes/lift_indirect_targets.c | 31 +++--- 10 files changed, 163 insertions(+), 59 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index da5ac640a..163361d62 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -139,6 +139,7 @@ Nodes filter_out_annotation(IrArena*, Nodes, const char* name); bool is_abstraction (const Node*); String get_abstraction_name (const Node* abs); +String get_abstraction_name_unsafe(const Node* abs); const Node* get_abstraction_body (const Node* abs); Nodes get_abstraction_params(const Node* abs); diff --git a/src/common/dict.c b/src/common/dict.c index 2fbaf1af0..2c83d686f 100644 --- a/src/common/dict.c +++ b/src/common/dict.c @@ -334,3 +334,11 @@ KeyHash hash_murmur(const void* data, size_t size) { final ^= out[3]; return final; } + +KeyHash hash_ptr(void** p) { + return hash_murmur(p, sizeof(void*)); +} + +bool compare_ptrs(void** a, void** b) { + return *a == *b; +} diff --git a/src/common/dict.h b/src/common/dict.h index 74fcdb5a4..009b3e043 100644 --- a/src/common/dict.h +++ b/src/common/dict.h @@ -46,4 +46,7 @@ bool insert_dict_and_get_result_impl(struct Dict*, void* key, void* value); KeyHash hash_murmur(const void* data, size_t size); +KeyHash hash_ptr(void**); +bool compare_ptrs(void**, void**); + #endif diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index c8412a6b4..bf94238da 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -8,6 +8,7 @@ #include "list.h" #include "dict.h" +#include #include KeyHash hash_node(Node**); @@ -15,20 +16,20 @@ bool compare_node(Node**, Node**); typedef struct { Visitor visitor; - struct Dict* bound_set; - struct Dict* set; - struct List* free_list; + struct Dict* map; + CFNodeVariables* current_scope; } Context; static void search_op_for_free_variables(Context* visitor, NodeClass class, String op_name, const Node* node) { assert(node); switch (node->tag) { case Variable_TAG: { - if (find_key_dict(const Node*, visitor->bound_set, node)) - return; - if (insert_set_get_result(const Node*, visitor->set, node)) { - append_list(const Node*, visitor->free_list, node); + Nodes params = get_abstraction_params(visitor->current_scope->node->node); + for (size_t i = 0; i < params.count; i++) { + if (params.nodes[i] == node) + return; } + insert_set_get_result(const Node*, visitor->current_scope->free_set, node); break; } case Function_TAG: @@ -38,26 +39,36 @@ static void search_op_for_free_variables(Context* visitor, NodeClass class, Stri } } -static void visit_domtree(Context* ctx, CFNode* cfnode, int depth) { - const Node* abs = cfnode->node; +static CFNodeVariables* create_node_variables(CFNode* cfnode) { + CFNodeVariables* v = calloc(sizeof(CFNodeVariables), 1); + *v = (CFNodeVariables) { + .node = cfnode, + .free_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node) + }; + return v; +} - bool is_named = abs->tag != Case_TAG; +static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, CFNodeVariables* parent) { + Context new_context = *ctx; + ctx = &new_context; - if (is_named) { - for (int i = 0; i < depth; i++) - debugvv_print(" "); - debugvv_print("%s\n", get_abstraction_name(abs)); + ctx->current_scope = create_node_variables(cfnode); + if (parent) { + ctx->current_scope->bound_set = clone_dict(parent->bound_set); + } else { + ctx->current_scope->bound_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); } + insert_dict(CFNode*, CFNodeVariables*, ctx->map, cfnode, ctx->current_scope); + const Node* abs = cfnode->node; + + bool is_named = abs->tag != Case_TAG; // Bind parameters Nodes params = get_abstraction_params(abs); for (size_t j = 0; j < params.count; j++) { const Node* param = params.nodes[j]; - bool r = insert_set_get_result(const Node*, ctx->bound_set, param); - // assert(r); - // this can happen if you visit the domtree of a CFG starting _inside_ a loop - // we will meet some unbound params but eventually we'll enter their definition after the fact - // those params should still be considered free in this case. + bool r = insert_set_get_result(const Node*, ctx->current_scope->bound_set, param); + assert(r); } const Node* body = get_abstraction_body(abs); @@ -66,35 +77,83 @@ static void visit_domtree(Context* ctx, CFNode* cfnode, int depth) { for (size_t i = 0; i < entries_count_list(cfnode->dominates); i++) { CFNode* child = read_list(CFNode*, cfnode->dominates)[i]; - visit_domtree(ctx, child, depth + (is_named ? 1 : 0)); + CFNodeVariables* child_variables = visit_domtree(ctx, child, depth + (is_named ? 1 : 1), ctx->current_scope); + size_t j = 0; + const Node* free_var; + while (dict_iter(child_variables->free_set, &j, &free_var, NULL)) { + for (size_t k = 0; k < params.count; k++) { + if (params.nodes[k] == free_var) + goto next; + } + insert_set_get_result(const Node*, ctx->current_scope->free_set, free_var); + next:; + } } + /*String abs_name = get_abstraction_name_unsafe(abs); + for (int i = 0; i < depth; i++) + debugvv_print(" "); + if (abs_name) + debugvv_print("%s: ", abs_name); + else + debugvv_print("%%%d: ", abs->id); + + if (true) { + bool prev = false; + size_t i = 0; + const Node* free_var; + while (dict_iter(ctx->current_scope->free_set, &i, &free_var, NULL)) { + if (prev) { + debugvv_print(", "); + } + log_node(DEBUGVV, free_var); + prev = true; + } + } + + if (true) { + debugvv_print(". Binds: "); + bool prev = false; + for (size_t i = 0; i < params.count; i++) { + if (prev) { + debugvv_print(", "); + } + log_node(DEBUGVV, params.nodes[i]); + prev = true; + } + } + + debugvv_print("\n");*/ + // Unbind parameters for (size_t j = 0; j < params.count; j++) { const Node* param = params.nodes[j]; - bool r = remove_dict(const Node*, ctx->bound_set, param); + bool r = remove_dict(const Node*, ctx->current_scope->bound_set, param); assert(r); } -} -struct List* compute_free_variables(const Scope* scope, const Node* at) { - struct Dict* bound_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - struct Dict* set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - struct List* free_list = new_list(const Node*); + return ctx->current_scope; +} +struct Dict* compute_scope_variables_map(const Scope* scope) { Context ctx = { .visitor = { .visit_op_fn = (VisitOpFn) search_op_for_free_variables, }, - .bound_set = bound_set, - .set = set, - .free_list = free_list, + .map = new_dict(CFNode*, CFNodeVariables*, (HashFn) hash_ptr, (CmpFn) compare_ptrs), }; - debugv_print("Computing free variables...\n"); - visit_domtree(&ctx, scope_lookup(scope, at), 0); + debugv_print("Computing free variables for function '%s' ...\n", get_abstraction_name(scope->entry->node)); + visit_domtree(&ctx, scope->entry, 0, NULL); + return ctx.map; +} - destroy_dict(bound_set); - destroy_dict(set); - return free_list; +void destroy_scope_variables_map(struct Dict* map) { + size_t i = 0; + CFNodeVariables* value; + while (dict_iter(map, &i, NULL, &value)) { + destroy_dict(value->bound_set); + destroy_dict(value->free_set); + free((void*) value); + } } diff --git a/src/shady/analysis/free_variables.h b/src/shady/analysis/free_variables.h index f6f92f4be..a0754dba2 100644 --- a/src/shady/analysis/free_variables.h +++ b/src/shady/analysis/free_variables.h @@ -4,7 +4,15 @@ #include "shady/ir.h" typedef struct Scope_ Scope; +typedef struct CFNode_ CFNode; -struct List* compute_free_variables(const Scope* scope, const Node*); +typedef struct { + CFNode* node; + struct Dict* bound_set; + struct Dict* free_set; +} CFNodeVariables; + +struct Dict* compute_scope_variables_map(const Scope* scope); +void destroy_scope_variables_map(struct Dict*); #endif diff --git a/src/shady/analysis/scope.c b/src/shady/analysis/scope.c index 36f7ace6a..d12cba366 100644 --- a/src/shady/analysis/scope.c +++ b/src/shady/analysis/scope.c @@ -550,9 +550,10 @@ static void dump_cf_node(FILE* output, const CFNode* n) { label = format_string_arena(bb->arena->arena, "%s%s", label, node_tags[body->tag]); - if (is_basic_block(bb)) { - label = format_string_arena(bb->arena->arena, "%s\n%s", get_abstraction_name(bb), label); - } + String abs_name = get_abstraction_name_unsafe(bb); + if (!abs_name) + abs_name = format_string_interned(bb->arena, "%%%d", bb->id); + label = format_string_arena(bb->arena->arena, "%s\n%s", abs_name, label); fprintf(output, "bb_%zu [label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index d4b085510..454857141 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -46,13 +46,16 @@ static void verify_scoping(Module* mod) { struct List* scopes = build_scopes(mod); for (size_t i = 0; i < entries_count_list(scopes); i++) { Scope* scope = read_list(Scope*, scopes)[i]; - struct List* leaking = compute_free_variables(scope, scope->entry->node); - for (size_t j = 0; j < entries_count_list(leaking); j++) { - log_node(ERROR, read_list(const Node*, leaking)[j]); + struct Dict* map = compute_scope_variables_map(scope); + CFNodeVariables* entry_vars = *find_value_dict(CFNode*, CFNodeVariables*, map, scope->entry); + size_t j = 0; + const Node* leaking; + while (dict_iter(entry_vars->free_set, &j, &leaking, NULL)) { + log_node(ERROR, leaking); error_print("\n"); } - assert(entries_count_list(leaking) == 0); - destroy_list(leaking); + assert(entries_count_dict(entry_vars->free_set) == 0); + destroy_scope_variables_map(map); destroy_scope(scope); } destroy_list(scopes); diff --git a/src/shady/node.c b/src/shady/node.c index 538fe1787..d5ab5aafe 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -263,6 +263,16 @@ String get_abstraction_name(const Node* abs) { } } +String get_abstraction_name_unsafe(const Node* abs) { + assert(is_abstraction(abs)); + switch (abs->tag) { + case Function_TAG: return abs->payload.fun.name; + case BasicBlock_TAG: return abs->payload.basic_block.name; + case Case_TAG: return NULL; + default: assert(false); + } +} + const Node* get_abstraction_body(const Node* abs) { assert(is_abstraction(abs)); switch (abs->tag) { diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index b7ccd9f63..af24e5851 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -17,6 +17,7 @@ typedef struct Context_ { const Node* current_fn; Scope* scope; const UsesMap* scope_uses; + struct Dict* scope_vars; LoopTree* loop_tree; struct Dict* lifted_arguments; } Context; @@ -55,9 +56,11 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No *lparams = empty(a); *nargs = empty(a); - struct List* fvs = compute_free_variables(ctx->scope, old); - for (size_t i = 0; i < entries_count_list(fvs); i++) { - const Node* fv = read_list(const Node*, fvs)[i]; + const Node* fv; + size_t i = 0; + CFNode* cf_node = scope_lookup(ctx->scope, old); + CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_node); + while (dict_iter(node_vars->free_set, &i, &fv, NULL)) { const Node* defining_abs = get_var_binding_abstraction(ctx->scope_uses, fv); const CFNode* defining_cf_node = scope_lookup(ctx->scope, defining_abs); assert(defining_cf_node); @@ -74,7 +77,6 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No *nargs = append_nodes(a, *nargs, narg); } } - destroy_list(fvs); if (nparams->count > 0) insert_dict(const Node*, Nodes, ctx->lifted_arguments, old, *nparams); @@ -152,6 +154,7 @@ const Node* process_node(Context* ctx, const Node* old) { ctx->current_fn = old; ctx->scope = new_scope(old); ctx->scope_uses = create_uses_map(old, (NcDeclaration | NcType)); + ctx->scope_vars = compute_scope_variables_map(ctx->scope); ctx->loop_tree = build_loop_tree(ctx->scope); Node* new = recreate_decl_header_identity(&ctx->rewriter, old); @@ -160,6 +163,7 @@ const Node* process_node(Context* ctx, const Node* old) { destroy_loop_tree(ctx->loop_tree); destroy_uses_map(ctx->scope_uses); destroy_scope(ctx->scope); + destroy_scope_variables_map(ctx->scope_vars); return new; } case Jump_TAG: { diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index bbc9bcae7..1a88e8f13 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -26,6 +26,7 @@ typedef struct Context_ { Rewriter rewriter; Scope* scope; const UsesMap* scope_uses; + struct Dict* scope_vars; struct Dict* lifted; bool disable_lowering; @@ -78,19 +79,23 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name String name = is_basic_block(cont) ? format_string_arena(a->arena, "%s_%s", get_abstraction_name(cont->payload.basic_block.fn), get_abstraction_name(cont)) : unique_name(a, given_name); // Compute the live stuff we'll need - Scope* scope = new_scope(cont); - struct List* recover_context = compute_free_variables(scope, cont); - size_t recover_context_size = entries_count_list(recover_context); - destroy_scope(scope); - - debugv_print("free (spilled) variables at '%s': ", name); - for (size_t i = 0; i < recover_context_size; i++) { - const Node* item = read_list(const Node*, recover_context)[i]; - debugv_print(get_value_name_safe(item)); - if (i + 1 < recover_context_size) - debugv_print(", "); + CFNode* cf_node = scope_lookup(ctx->scope, cont); + CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_node); + struct List* recover_context = new_list(const Node*); + size_t recover_context_size = entries_count_dict(node_vars->free_set); + + { + debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", name, entries_count_dict(node_vars->free_set)); + size_t i = 0; + const Node* item; + while (dict_iter(node_vars->free_set, &i, &item, NULL)) { + append_list(const Node*, recover_context, item ); + debugv_print(get_value_name_safe(item)); + if (i + 1 < recover_context_size) + debugv_print(", "); + } + debugv_print("\n"); } - debugv_print("\n"); // Create and register new parameters for the lifted continuation Nodes new_params = recreate_variables(&ctx->rewriter, oparams); @@ -166,12 +171,14 @@ static const Node* process_node(Context* ctx, const Node* node) { Context fn_ctx = *ctx; fn_ctx.scope = new_scope(node); fn_ctx.scope_uses = create_uses_map(node, (NcDeclaration | NcType)); + fn_ctx.scope_vars = compute_scope_variables_map(fn_ctx.scope); ctx = &fn_ctx; Node* new = recreate_decl_header_identity(&ctx->rewriter, node); recreate_decl_body_identity(&ctx->rewriter, node, new); destroy_uses_map(ctx->scope_uses); + destroy_scope_variables_map(ctx->scope_vars); destroy_scope(ctx->scope); return new; } From a92109d1598140ede5b9ed0720c1cc6aa48eb353 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 9 Apr 2024 14:19:14 +0200 Subject: [PATCH 162/693] get_string_literal: deal with constants --- src/shady/node.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shady/node.c b/src/shady/node.c index d5ab5aafe..c35fe7789 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -208,6 +208,9 @@ const char* get_string_literal(IrArena* arena, const Node* node) { return get_string_literal(arena, init); break; } + case Declaration_Constant_TAG: { + return get_string_literal(arena, decl->payload.constant.instruction); + } default: break; } From 9966658eef6a133af69ce091d3ac083d3ff17b01 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 9 Apr 2024 14:36:50 +0200 Subject: [PATCH 163/693] put scope dumping code in its own file --- src/shady/CMakeLists.txt | 1 + src/shady/analysis/scope.c | 129 ----------------------------- src/shady/analysis/scope_dump.c | 139 ++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 129 deletions(-) create mode 100644 src/shady/analysis/scope_dump.c diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index f143bf281..d542bf454 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -39,6 +39,7 @@ set(SHADY_SOURCES module.c analysis/scope.c + analysis/scope_dump.c analysis/free_variables.c analysis/verify.c analysis/callgraph.c diff --git a/src/shady/analysis/scope.c b/src/shady/analysis/scope.c index d12cba366..416578502 100644 --- a/src/shady/analysis/scope.c +++ b/src/shady/analysis/scope.c @@ -498,132 +498,3 @@ struct List* scope_get_dom_frontier(Scope* scope, const CFNode* node) { return dom_frontier; } - -static int extra_uniqueness = 0; - -static CFNode* get_let_pred(const CFNode* n) { - if (entries_count_list(n->pred_edges) == 1) { - CFEdge pred = read_list(CFEdge, n->pred_edges)[0]; - assert(pred.dst == n); - if (pred.type == LetTailEdge && entries_count_list(pred.src->succ_edges) == 1) { - assert(is_case(n->node)); - return pred.src; - } - } - return NULL; -} - -static void dump_cf_node(FILE* output, const CFNode* n) { - const Node* bb = n->node; - const Node* body = get_abstraction_body(bb); - if (!body) - return; - if (get_let_pred(n)) - return; - - String color = "black"; - if (is_case(bb)) - color = "green"; - else if (is_basic_block(bb)) - color = "blue"; - - String label = ""; - - const CFNode* let_chain_end = n; - while (body->tag == Let_TAG) { - const Node* instr = body->payload.let.instruction; - // label = ""; - if (instr->tag == PrimOp_TAG) - label = format_string_arena(bb->arena->arena, "%slet ... = %s (...)\n", label, get_primop_name(instr->payload.prim_op.op)); - else - label = format_string_arena(bb->arena->arena, "%slet ... = %s (...)\n", label, node_tags[instr->tag]); - - if (entries_count_list(let_chain_end->succ_edges) != 1 || read_list(CFEdge, let_chain_end->succ_edges)[0].type != LetTailEdge) - break; - - let_chain_end = read_list(CFEdge, let_chain_end->succ_edges)[0].dst; - const Node* abs = body->payload.let.tail; - assert(let_chain_end->node == abs); - assert(is_case(abs)); - body = get_abstraction_body(abs); - } - - label = format_string_arena(bb->arena->arena, "%s%s", label, node_tags[body->tag]); - - String abs_name = get_abstraction_name_unsafe(bb); - if (!abs_name) - abs_name = format_string_interned(bb->arena, "%%%d", bb->id); - label = format_string_arena(bb->arena->arena, "%s\n%s", abs_name, label); - - fprintf(output, "bb_%zu [label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); - - for (size_t i = 0; i < entries_count_list(n->dominates); i++) { - CFNode* d = read_list(CFNode*, n->dominates)[i]; - if (!find_key_dict(const Node*, n->structurally_dominates, d->node)) - dump_cf_node(output, d); - } -} - -static void dump_cfg_scope(FILE* output, Scope* scope) { - extra_uniqueness++; - - const Node* entry = scope->entry->node; - fprintf(output, "subgraph cluster_%s {\n", get_abstraction_name(entry)); - fprintf(output, "label = \"%s\";\n", get_abstraction_name(entry)); - for (size_t i = 0; i < entries_count_list(scope->contents); i++) { - const CFNode* n = read_list(const CFNode*, scope->contents)[i]; - dump_cf_node(output, n); - } - for (size_t i = 0; i < entries_count_list(scope->contents); i++) { - const CFNode* bb_node = read_list(const CFNode*, scope->contents)[i]; - const CFNode* src_node = bb_node; - while (true) { - const CFNode* let_parent = get_let_pred(src_node); - if (let_parent) - src_node = let_parent; - else - break; - } - - for (size_t j = 0; j < entries_count_list(bb_node->succ_edges); j++) { - CFEdge edge = read_list(CFEdge, bb_node->succ_edges)[j]; - const CFNode* target_node = edge.dst; - - if (edge.type == LetTailEdge && get_let_pred(target_node) == bb_node) - continue; - - String edge_color = "black"; - switch (edge.type) { - case LetTailEdge: edge_color = "green"; break; - case StructuredEnterBodyEdge: edge_color = "blue"; break; - case StructuredLeaveBodyEdge: edge_color = "red"; break; - case StructuredPseudoExitEdge: edge_color = "darkred"; break; - default: break; - } - - fprintf(output, "bb_%zu -> bb_%zu [color=\"%s\"];\n", (size_t) (src_node), (size_t) (target_node), edge_color); - } - } - fprintf(output, "}\n"); -} - -void dump_cfg(FILE* output, Module* mod) { - if (output == NULL) - output = stderr; - - fprintf(output, "digraph G {\n"); - struct List* scopes = build_scopes(mod); - for (size_t i = 0; i < entries_count_list(scopes); i++) { - Scope* scope = read_list(Scope*, scopes)[i]; - dump_cfg_scope(output, scope); - destroy_scope(scope); - } - destroy_list(scopes); - fprintf(output, "}\n"); -} - -void dump_cfg_auto(Module* mod) { - FILE* f = fopen("cfg.dot", "wb"); - dump_cfg(f, mod); - fclose(f); -} diff --git a/src/shady/analysis/scope_dump.c b/src/shady/analysis/scope_dump.c new file mode 100644 index 000000000..c86477c32 --- /dev/null +++ b/src/shady/analysis/scope_dump.c @@ -0,0 +1,139 @@ +#include "scope.h" +#include "../ir_private.h" + +#include "list.h" +#include "dict.h" +#include "util.h" + +#include + +static int extra_uniqueness = 0; + +static CFNode* get_let_pred(const CFNode* n) { + if (entries_count_list(n->pred_edges) == 1) { + CFEdge pred = read_list(CFEdge, n->pred_edges)[0]; + assert(pred.dst == n); + if (pred.type == LetTailEdge && entries_count_list(pred.src->succ_edges) == 1) { + assert(is_case(n->node)); + return pred.src; + } + } + return NULL; +} + +static void dump_cf_node(FILE* output, const CFNode* n) { + const Node* bb = n->node; + const Node* body = get_abstraction_body(bb); + if (!body) + return; + if (get_let_pred(n)) + return; + + String color = "black"; + if (is_case(bb)) + color = "green"; + else if (is_basic_block(bb)) + color = "blue"; + + String label = ""; + + String abs_name = get_abstraction_name_unsafe(bb); + if (!abs_name) + abs_name = format_string_interned(bb->arena, "%%%d", bb->id); + label = format_string_arena(bb->arena->arena, "%s: %s", abs_name, label); + + const CFNode* let_chain_end = n; + while (body->tag == Let_TAG) { + const Node* instr = body->payload.let.instruction; + // label = ""; + if (instr->tag == PrimOp_TAG) + label = format_string_arena(bb->arena->arena, "%slet ... = %s (...)\n", label, get_primop_name(instr->payload.prim_op.op)); + else + label = format_string_arena(bb->arena->arena, "%slet ... = %s (...)\n", label, node_tags[instr->tag]); + + const Node* abs = body->payload.let.tail; + label = format_string_arena(bb->arena->arena, "%s%%%d: ", label, abs->id); + + if (entries_count_list(let_chain_end->succ_edges) != 1 || read_list(CFEdge, let_chain_end->succ_edges)[0].type != LetTailEdge) + break; + + let_chain_end = read_list(CFEdge, let_chain_end->succ_edges)[0].dst; + assert(let_chain_end->node == abs); + assert(is_case(abs)); + body = get_abstraction_body(abs); + } + + label = format_string_arena(bb->arena->arena, "%s%s", label, node_tags[body->tag]); + + fprintf(output, "bb_%zu [label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); + + for (size_t i = 0; i < entries_count_list(n->dominates); i++) { + CFNode* d = read_list(CFNode*, n->dominates)[i]; + if (!find_key_dict(const Node*, n->structurally_dominates, d->node)) + dump_cf_node(output, d); + } +} + +static void dump_cfg_scope(FILE* output, Scope* scope) { + extra_uniqueness++; + + const Node* entry = scope->entry->node; + fprintf(output, "subgraph cluster_%s {\n", get_abstraction_name(entry)); + fprintf(output, "label = \"%s\";\n", get_abstraction_name(entry)); + for (size_t i = 0; i < entries_count_list(scope->contents); i++) { + const CFNode* n = read_list(const CFNode*, scope->contents)[i]; + dump_cf_node(output, n); + } + for (size_t i = 0; i < entries_count_list(scope->contents); i++) { + const CFNode* bb_node = read_list(const CFNode*, scope->contents)[i]; + const CFNode* src_node = bb_node; + while (true) { + const CFNode* let_parent = get_let_pred(src_node); + if (let_parent) + src_node = let_parent; + else + break; + } + + for (size_t j = 0; j < entries_count_list(bb_node->succ_edges); j++) { + CFEdge edge = read_list(CFEdge, bb_node->succ_edges)[j]; + const CFNode* target_node = edge.dst; + + if (edge.type == LetTailEdge && get_let_pred(target_node) == bb_node) + continue; + + String edge_color = "black"; + switch (edge.type) { + case LetTailEdge: edge_color = "green"; break; + case StructuredEnterBodyEdge: edge_color = "blue"; break; + case StructuredLeaveBodyEdge: edge_color = "red"; break; + case StructuredPseudoExitEdge: edge_color = "darkred"; break; + default: break; + } + + fprintf(output, "bb_%zu -> bb_%zu [color=\"%s\"];\n", (size_t) (src_node), (size_t) (target_node), edge_color); + } + } + fprintf(output, "}\n"); +} + +void dump_cfg(FILE* output, Module* mod) { + if (output == NULL) + output = stderr; + + fprintf(output, "digraph G {\n"); + struct List* scopes = build_scopes(mod); + for (size_t i = 0; i < entries_count_list(scopes); i++) { + Scope* scope = read_list(Scope*, scopes)[i]; + dump_cfg_scope(output, scope); + destroy_scope(scope); + } + destroy_list(scopes); + fprintf(output, "}\n"); +} + +void dump_cfg_auto(Module* mod) { + FILE* f = fopen("cfg.dot", "wb"); + dump_cfg(f, mod); + fclose(f); +} From a66815a3104116dc3d4bcd459b2c8952d7ef0994 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 9 Apr 2024 15:34:33 +0200 Subject: [PATCH 164/693] use actual instructions when dumping the CFG --- src/common/util.c | 19 ++++++++++++ src/common/util.h | 1 + src/shady/analysis/scope_dump.c | 55 ++++++++++++++++++++++++--------- src/shady/print.c | 37 ++++++++++++++++------ src/shady/print.h | 1 + 5 files changed, 89 insertions(+), 24 deletions(-) diff --git a/src/common/util.c b/src/common/util.c index 637834f8f..7cc562413 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -38,6 +38,25 @@ size_t apply_escape_codes(const char* src, size_t size, char* dst) { return j; } +size_t unapply_escape_codes(const char* src, size_t size, char* dst) { + char c = '\0'; + size_t j = 0; + for (size_t i = 0; i < size; i++) { + c = src[i]; + +#define ESCAPE_CASE(m, s) if (c == s) { \ + dst[j++] = '\\'; \ + dst[j++] = m; \ + continue; \ + } \ + + ESCAPE_SEQS(ESCAPE_CASE) + + dst[j++] = c; + } + return j; +} + static long get_file_size(FILE* f) { if (fseek(f, 0, SEEK_END) != 0) return -1; diff --git a/src/common/util.h b/src/common/util.h index d4d93accb..4842710c0 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -5,6 +5,7 @@ #include size_t apply_escape_codes(const char* src, size_t og_len, char* dst); +size_t unapply_escape_codes(const char* src, size_t og_len, char* dst); bool read_file(const char* filename, size_t* size, char** output); bool write_file(const char* filename, size_t size, const char* data); diff --git a/src/shady/analysis/scope_dump.c b/src/shady/analysis/scope_dump.c index c86477c32..dc981efb0 100644 --- a/src/shady/analysis/scope_dump.c +++ b/src/shady/analysis/scope_dump.c @@ -1,10 +1,14 @@ #include "scope.h" -#include "../ir_private.h" + +#include "shady/ir_private.h" +#include "shady/print.h" #include "list.h" #include "dict.h" #include "util.h" +#include "printer.h" +#include #include static int extra_uniqueness = 0; @@ -21,6 +25,26 @@ static CFNode* get_let_pred(const CFNode* n) { return NULL; } +static void print_node_helper(Printer* p, const Node* n) { + Growy* tmp_g = new_growy(); + Printer* tmp_p = open_growy_as_printer(tmp_g); + + PrintConfig config = { + .color = false, + .in_cfg = true, + }; + + print_node(tmp_p, n, config); + + String label = printer_growy_unwrap(tmp_p); + char* escaped_label = calloc(strlen(label) * 2, 1); + unapply_escape_codes(label, strlen(label), escaped_label); + + print(p, "%s", escaped_label); + free(escaped_label); + free((void*)label); +} + static void dump_cf_node(FILE* output, const CFNode* n) { const Node* bb = n->node; const Node* body = get_abstraction_body(bb); @@ -35,37 +59,38 @@ static void dump_cf_node(FILE* output, const CFNode* n) { else if (is_basic_block(bb)) color = "blue"; - String label = ""; + Growy* g = new_growy(); + Printer* p = open_growy_as_printer(g); String abs_name = get_abstraction_name_unsafe(bb); if (!abs_name) abs_name = format_string_interned(bb->arena, "%%%d", bb->id); - label = format_string_arena(bb->arena->arena, "%s: %s", abs_name, label); + + print(p, "%s: \n%s: ", abs_name, abs_name); const CFNode* let_chain_end = n; while (body->tag == Let_TAG) { - const Node* instr = body->payload.let.instruction; - // label = ""; - if (instr->tag == PrimOp_TAG) - label = format_string_arena(bb->arena->arena, "%slet ... = %s (...)\n", label, get_primop_name(instr->payload.prim_op.op)); - else - label = format_string_arena(bb->arena->arena, "%slet ... = %s (...)\n", label, node_tags[instr->tag]); - - const Node* abs = body->payload.let.tail; - label = format_string_arena(bb->arena->arena, "%s%%%d: ", label, abs->id); - if (entries_count_list(let_chain_end->succ_edges) != 1 || read_list(CFEdge, let_chain_end->succ_edges)[0].type != LetTailEdge) break; + print_node_helper(p, body); + print(p, "\\l"); + + const Node* abs = body->payload.let.tail; + print(p, "%%%d: ", abs->id); + let_chain_end = read_list(CFEdge, let_chain_end->succ_edges)[0].dst; assert(let_chain_end->node == abs); assert(is_case(abs)); body = get_abstraction_body(abs); } - label = format_string_arena(bb->arena->arena, "%s%s", label, node_tags[body->tag]); + print_node_helper(p, body); + print(p, "\\l"); - fprintf(output, "bb_%zu [label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); + String label = printer_growy_unwrap(p); + fprintf(output, "bb_%zu [nojustify=true, label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); + free((void*) label); for (size_t i = 0; i < entries_count_list(n->dominates); i++) { CFNode* d = read_list(CFNode*, n->dominates)[i]; diff --git a/src/shady/print.c b/src/shady/print.c index 76f0bc7a7..dc9375b49 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -567,6 +567,8 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf("("); print_node(node->payload.if_instr.condition); printf(") "); + if (ctx->config.in_cfg) + break; print_case_body(ctx, node->payload.if_instr.if_true); if (node->payload.if_instr.if_false) { printf(GREEN); @@ -580,6 +582,8 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf("loop"); printf(RESET); print_yield_types(ctx, node->payload.loop_instr.yield_types); + if (ctx->config.in_cfg) + break; const Node* body = node->payload.loop_instr.body; assert(is_case(body)); print_param_list(ctx, body->payload.case_.params, &node->payload.loop_instr.initial_args); @@ -593,6 +597,8 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf("("); print_node(node->payload.match_instr.inspect); printf(")"); + if (ctx->config.in_cfg) + break; printf(" {"); indent(ctx->printer); for (size_t i = 0; i < node->payload.match_instr.literals.count; i++) { @@ -625,6 +631,8 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf("control"); printf(RESET); print_yield_types(ctx, node->payload.control.yield_types); + if (ctx->config.in_cfg) + break; print_param_list(ctx, node->payload.control.inside->payload.case_.params, NULL); print_case_body(ctx, node->payload.control.inside); break; @@ -681,8 +689,10 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(" = "); } print_node(instruction); - printf(";\n"); - print_abs_body(ctx, tail); + if (!ctx->config.in_cfg) { + printf(";\n"); + print_abs_body(ctx, tail); + } } else { printf(GREEN); printf("let"); @@ -973,36 +983,45 @@ void print_node(Printer* printer, const Node* node, PrintConfig config) { }; print_node_impl(&ctx, node); flush(ctx.printer); - destroy_printer(ctx.printer); } void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { Growy* g = new_growy(); - print_node(open_growy_as_printer(g), node, (PrintConfig) { .reparseable = true }); + Printer* p = open_growy_as_printer(g); + print_node(p, node, (PrintConfig) { .reparseable = true }); + destroy_printer(p); *size = growy_size(g); *str_ptr = growy_deconstruct(g); } void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { Growy* g = new_growy(); - print_module(open_growy_as_printer(g), mod, (PrintConfig) { .reparseable = true, }); + Printer* p = open_growy_as_printer(g); + print_module(p, mod, (PrintConfig) { .reparseable = true, }); + destroy_printer(p); *size = growy_size(g); *str_ptr = growy_deconstruct(g); } void dump_node(const Node* node) { - print_node(open_file_as_printer(stdout), node, (PrintConfig) { .color = true }); + Printer* p = open_file_as_printer(stdout); + print_node(p, node, (PrintConfig) { .color = true }); printf("\n"); } void dump_module(Module* mod) { - print_module(open_file_as_printer(stdout), mod, (PrintConfig) { .color = true }); + Printer* p = open_file_as_printer(stdout); + print_module(p, mod, (PrintConfig) { .color = true }); + destroy_printer(p); printf("\n"); } void log_node(LogLevel level, const Node* node) { - if (level >= get_log_level()) - print_node(open_file_as_printer(stderr), node, (PrintConfig) { .color = true }); + if (level >= get_log_level()) { + Printer* p = open_file_as_printer(stderr); + print_node(p, node, (PrintConfig) { .color = true }); + destroy_printer(p); + } } void log_module(LogLevel level, CompilerConfig* compiler_cfg, Module* mod) { diff --git a/src/shady/print.h b/src/shady/print.h index 4ec5486b2..66e9d85d4 100644 --- a/src/shady/print.h +++ b/src/shady/print.h @@ -12,6 +12,7 @@ typedef struct { bool print_ptrs; bool color; bool reparseable; + bool in_cfg; } PrintConfig; void print_module(Printer* printer, Module* mod, PrintConfig config); From d3fa00981e0fa281979e21dcd1f8c513b47dd696 Mon Sep 17 00:00:00 2001 From: Michael Kenzel Date: Wed, 10 Apr 2024 00:46:33 +0200 Subject: [PATCH 165/693] improved CUDA module loading --- src/runtime/cuda/cuda_runtime.c | 2 + src/runtime/cuda/cuda_runtime_private.h | 2 + src/runtime/cuda/cuda_runtime_program.c | 70 ++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 68bcebe15..02d01cd62 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -69,6 +69,8 @@ static CudaDevice* create_cuda_device(CudaBackend* b, int ordinal) { .specialized_programs = new_dict(SpecProgramKey, CudaKernel*, (HashFn) hash_spec_program_key, (CmpFn) cmp_spec_program_keys), }; CHECK_CUDA(cuDeviceGetName(device->name, 255, handle), goto dealloc_and_return_null); + CHECK_CUDA(cuDeviceGetAttribute(&device->cc_major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, device->handle), goto dealloc_and_return_null); + CHECK_CUDA(cuDeviceGetAttribute(&device->cc_minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, device->handle), goto dealloc_and_return_null); CHECK_CUDA(cuCtxCreate(&device->context, 0, handle), goto dealloc_and_return_null); return device; diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index 92eb54e32..a5a6bd735 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -24,6 +24,8 @@ typedef struct { CUdevice handle; CUcontext context; char name[256]; + int cc_major; + int cc_minor; struct Dict* specialized_programs; } CudaDevice; diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 241f7d941..68036539f 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -28,21 +28,34 @@ static bool emit_cuda_c_code(CudaKernel* spec) { Module* final_mod; emit_c(config, emitter_config, dst_mod, &spec->cuda_code_size, &spec->cuda_code, &final_mod); spec->final_module = final_mod; + + if (get_log_level() <= DEBUG) + write_file("cuda_dump.cu", spec->cuda_code_size - 1, spec->cuda_code); + return true; } static bool cuda_c_to_ptx(CudaKernel* kernel) { nvrtcProgram program; CHECK_NVRTC(nvrtcCreateProgram(&program, kernel->cuda_code, kernel->key.entry_point, 0, NULL, NULL), return false); - nvrtcResult compile_result = nvrtcCompileProgram(program, 0, false); + + assert(kernel->device->cc_major < 10 && kernel->device->cc_minor < 10); + + char arch_flag[] = "-arch=compute_00"; + arch_flag[14] = '0' + kernel->device->cc_major; + arch_flag[15] = '0' + kernel->device->cc_minor; + + const char* options[] = { + arch_flag, + "--use_fast_math" + }; + + nvrtcResult compile_result = nvrtcCompileProgram(program, sizeof(options)/sizeof(*options), options); if (compile_result != NVRTC_SUCCESS) { error_print("NVRTC compilation failed: %s\n", nvrtcGetErrorString(compile_result)); debug_print("Dumping source:\n%s", kernel->cuda_code); } - if (get_log_level() <= DEBUG) - write_file("cuda_dump.cu", kernel->cuda_code_size - 1, kernel->cuda_code); - size_t log_size; CHECK_NVRTC(nvrtcGetProgramLogSize(program, &log_size), return false); char* log_buffer = calloc(log_size, 1); @@ -60,13 +73,58 @@ static bool cuda_c_to_ptx(CudaKernel* kernel) { read_file(override_file, &kernel->ptx_size, &kernel->ptx); } + if (get_log_level() <= DEBUG) + write_file("cuda_dump.ptx", kernel->ptx_size - 1, kernel->ptx); + return true; } static bool load_ptx_into_cuda_program(CudaKernel* kernel) { - CHECK_CUDA(cuModuleLoadDataEx(&kernel->cuda_module, kernel->ptx, 0, NULL, NULL), return false); - CHECK_CUDA(cuModuleGetFunction(&kernel->entry_point_function, kernel->cuda_module, kernel->key.entry_point), return false); + char info_log[10240] = {}; + char error_log[10240] = {}; + + CUjit_option options[] = { + CU_JIT_INFO_LOG_BUFFER, CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES, + CU_JIT_ERROR_LOG_BUFFER, CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES, + CU_JIT_TARGET + }; + + void* option_values[] = { + info_log, (void*)(uintptr_t)sizeof(info_log), + error_log, (void*)(uintptr_t)sizeof(error_log), + (void*)(uintptr_t)(kernel->device->cc_major * 10 + kernel->device->cc_minor) + }; + + CUlinkState linker; + CHECK_CUDA(cuLinkCreate(sizeof(options)/sizeof(options[0]), options, option_values, &linker), goto err_linker_create); + CHECK_CUDA(cuLinkAddData(linker, CU_JIT_INPUT_PTX, kernel->ptx, kernel->ptx_size, NULL, 0U, NULL, NULL), goto err_post_linker_create); + + void* binary; + size_t binary_size; + CHECK_CUDA(cuLinkComplete(linker, &binary, &binary_size), goto err_post_linker_create); + + if (*info_log) + info_print("CUDA JIT info: %s\n", info_log); + + if (get_log_level() <= DEBUG) + write_file("cuda_dump.cubin", binary_size, binary); + + CHECK_CUDA(cuModuleLoadData(&kernel->cuda_module, binary), goto err_post_linker_create); + CHECK_CUDA(cuModuleGetFunction(&kernel->entry_point_function, kernel->cuda_module, kernel->key.entry_point), goto err_post_module_load); + + cuLinkDestroy(linker); return true; + +err_post_module_load: + cuModuleUnload(kernel->cuda_module); +err_post_linker_create: + cuLinkDestroy(linker); + if (*info_log) + info_print("CUDA JIT info: %s\n", info_log); + if (*error_log) + error_print("CUDA JIT failed: %s\n", error_log); +err_linker_create: + return false; } static CudaKernel* create_specialized_program(CudaDevice* device, SpecProgramKey key) { From 91c317f64e7100af65cdef0ea3337e988c449359 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 10 Apr 2024 11:47:55 +0200 Subject: [PATCH 166/693] fix scoping issues with reconvergence heuristics --- samples/aobench/CMakeLists.txt | 2 +- src/shady/analysis/free_variables.c | 5 +- src/shady/passes/reconvergence_heuristics.c | 131 ++++++++++++++++---- 3 files changed, 108 insertions(+), 30 deletions(-) diff --git a/samples/aobench/CMakeLists.txt b/samples/aobench/CMakeLists.txt index 01379a90a..772e21864 100644 --- a/samples/aobench/CMakeLists.txt +++ b/samples/aobench/CMakeLists.txt @@ -1,6 +1,6 @@ if (TARGET vcc) add_executable(aobench_host ao_host.c ao_main.c) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMAND vcc ARGS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp --only-run-clang -o ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMENT ao.comp.c.ll DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMAND vcc ARGS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp --only-run-clang -O3 -o ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMENT ao.comp.c.ll DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ao.c) set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/ao_main.c APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll) add_custom_command(TARGET aobench_host POST_BUILD diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index bf94238da..a356a5453 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -128,8 +128,9 @@ static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, C // Unbind parameters for (size_t j = 0; j < params.count; j++) { const Node* param = params.nodes[j]; - bool r = remove_dict(const Node*, ctx->current_scope->bound_set, param); - assert(r); + assert(find_key_dict(const Node*, ctx->current_scope->bound_set, param)); + //bool r = remove_dict(const Node*, ctx->current_scope->bound_set, param); + //assert(r); } return ctx->current_scope; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 4c92a5038..be41d2b35 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -13,6 +13,7 @@ #include "../analysis/scope.h" #include "../analysis/looptree.h" +#include "../analysis/free_variables.h" #include @@ -24,6 +25,7 @@ typedef struct Context_ { Scope* fwd_scope; Scope* back_scope; LoopTree* current_looptree; + struct Dict* scope_vars; } Context; static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { @@ -58,6 +60,30 @@ static void gather_exiting_nodes(LoopTree* lt, const CFNode* entry, const CFNode } } +static void find_unbound_vars(const Node* node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { + const Node* free_post; + size_t i = 0; + while (dict_iter(free_set, &i, &free_post, NULL)) { + const Node* bound_pre; + size_t j = 0; + while (dict_iter(bound_set, &j, &bound_pre, NULL)) { + if (bound_pre == free_post) { + goto next; + } + } + + log_string(DEBUGVV, "Found variable used outside it's control scope: "); + log_node(DEBUGVV, free_post); + log_string(DEBUGVV, " (original:"); + log_node(DEBUGVV, node); + log_string(DEBUGVV, " )\n"); + + append_list(const Node*, leaking, free_post); + + next:; + } +} + static const Node* process_abstraction(Context* ctx, const Node* node) { assert(is_abstraction(node)); Context new_context = *ctx; @@ -101,14 +127,34 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Nodes nparams = recreate_variables(rewriter, get_abstraction_params(node)); Nodes inner_yield_types = strip_qualifiers(arena, get_variables_types(arena, nparams)); - LARRAY(Nodes, exit_allocas, exiting_nodes_count); + CFNode* cf_pre = scope_lookup(ctx->fwd_scope, node); + // assert(cf_pre->idom && "cfg entry nodes can't be loop headers anyhow"); + // cf_pre = cf_pre->idom; + CFNodeVariables* pre = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_pre); + + LARRAY(Nodes, exit_param_allocas, exiting_nodes_count); + LARRAY(struct List*, leaking, exiting_nodes_count); + LARRAY(Nodes, exit_fwd_allocas, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; Nodes exit_param_types = rewrite_nodes(rewriter, get_variables_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); - LARRAY(const Node*, allocas, exit_param_types.count); + LARRAY(const Node*, exit_param_allocas_tmp, exit_param_types.count); for (size_t j = 0; j < exit_param_types.count; j++) - allocas[j] = gen_primop_e(outer_bb, alloca_op, singleton(get_unqualified_type(exit_param_types.nodes[j])), empty(arena)); - exit_allocas[i] = nodes(arena, exit_param_types.count, allocas); + exit_param_allocas_tmp[j] = gen_primop_e(outer_bb, alloca_op, singleton(get_unqualified_type(exit_param_types.nodes[j])), empty(arena)); + exit_param_allocas[i] = nodes(arena, exit_param_types.count, exit_param_allocas_tmp); + + // Search for what's required after the exit but not in scope at the loop header + // this is similar to the LCSSA constraint, but here it's because controls have hard scopes + CFNode* cf_post = scope_lookup(ctx->fwd_scope, exiting_node->node); + CFNodeVariables* post = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_post); + leaking[i] = new_list(const Type*); + find_unbound_vars(exiting_node->node, pre->bound_set, post->free_set, leaking[i]); + + size_t leaking_count = entries_count_list(leaking[i]); + LARRAY(const Node*, exit_fwd_allocas_tmp, leaking_count); + for (size_t j = 0; j < leaking_count; j++) + exit_fwd_allocas_tmp[j] = gen_primop_e(outer_bb, alloca_op, singleton(rewrite_node(rewriter, get_unqualified_type(read_list(const Node*, leaking[i])[j]->type))), empty(arena)); + exit_fwd_allocas[i] = nodes(arena, leaking_count, exit_fwd_allocas_tmp); } const Node* exit_destination_alloca = NULL; @@ -125,31 +171,24 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .yield_types = inner_yield_types }), true), "jp_continue"); - LARRAY(const Node*, exit_wrappers, exiting_nodes_count); + LARRAY(Node*, exit_helpers, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { + exit_helpers[i] = basic_block(arena, fn, empty(arena), format_string_arena(arena->arena, "exit_helper_%d", i)); + CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = recreate_variables(&ctx->rewriter, get_abstraction_params(exiting_node->node)); - BodyBuilder* exit_wrapper_bb = begin_body(arena); - - for (size_t j = 0; j < exit_allocas[i].count; j++) - gen_store(exit_wrapper_bb, exit_allocas[i].nodes[j], exit_wrapper_params.nodes[j]); - - const Node* exit_wrapper_body = finish_body(exit_wrapper_bb, join(arena, (Join) { - .join_point = join_token_exit, - .args = empty(arena) - })); switch (exiting_node->node->tag) { case BasicBlock_TAG: { Node* pre_join_exit_bb = basic_block(arena, fn, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); - pre_join_exit_bb->payload.basic_block.body = exit_wrapper_body; + pre_join_exit_bb->payload.basic_block.body = jump_helper(arena, exit_helpers[i], empty(arena)); exit_wrappers[i] = pre_join_exit_bb; break; } case Case_TAG: - exit_wrappers[i] = case_(arena, exit_wrapper_params, exit_wrapper_body); + exit_wrappers[i] = case_(arena, exit_wrapper_params, jump_helper(arena, exit_helpers[i], empty(arena))); break; default: assert(false); @@ -196,10 +235,40 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { // assert(!search_processed(rewriter, old_params.nodes[i])); // } + struct Dict* old_map = rewriter->map; + rewriter->map = clone_dict(rewriter->map); Nodes inner_loop_params = recreate_variables(rewriter, get_abstraction_params(node)); register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); const Node* loop_body = recreate_node_identity(rewriter, get_abstraction_body(node)); + // save the context + for (size_t i = 0; i < exiting_nodes_count; i++) { + CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + assert(exiting_node->node && exiting_node->node->tag != Function_TAG); + Nodes exit_wrapper_params = get_abstraction_params(exit_helpers[i]); + BodyBuilder* exit_wrapper_bb = begin_body(arena); + + for (size_t j = 0; j < exit_param_allocas[i].count; j++) + gen_store(exit_wrapper_bb, exit_param_allocas[i].nodes[j], exit_wrapper_params.nodes[j]); + if (exiting_nodes_count > 1) + gen_store(exit_wrapper_bb, exit_destination_alloca, int32_literal(arena, i)); + + for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { + gen_store(exit_wrapper_bb, exit_fwd_allocas[i].nodes[j], rewrite_node(rewriter, read_list(const Node*, leaking[i])[j])); + } + + const Node* exit_wrapper_body = finish_body(exit_wrapper_bb, join(arena, (Join) { + .join_point = join_token_exit, + .args = empty(arena) + })); + + exit_helpers[i]->payload.basic_block.body = exit_wrapper_body; + } + + destroy_dict(rewriter->map); + rewriter->map = old_map; + register_processed_list(rewriter, get_abstraction_params(node), nparams); + // restore the old context for (size_t i = 0; i < exiting_nodes_count; i++) { remove_dict(const Node*, rewriter->map, read_list(CFNode*, exiting_nodes)[i]->node); @@ -211,7 +280,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { register_processed(rewriter, node, cached_entry); BodyBuilder* inner_bb = begin_body(arena); - const Node* inner_control = control (arena, (Control) { + const Node* inner_control = control(arena, (Control) { .inside = case_(arena, singleton(join_token_continue), loop_body), .yield_types = inner_yield_types }); @@ -223,7 +292,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .target = loop_outer, .args = inner_control_results })); - const Node* outer_control = control (arena, (Control) { + const Node* outer_control = control(arena, (Control) { .inside = case_(arena, singleton(join_token_exit), jump(arena, (Jump) { .target = loop_outer, .args = nparams @@ -233,34 +302,40 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { bind_instruction(outer_bb, outer_control); - const Node* outer_body; - LARRAY(const Node*, exit_numbers, exiting_nodes_count); LARRAY(const Node*, exit_jumps, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { BodyBuilder* exit_recover_bb = begin_body(arena); + // recover the context CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { + const Node* recovered = gen_load(exit_recover_bb, exit_fwd_allocas[i].nodes[j]); + register_processed(rewriter, read_list(const Node*, leaking[i])[j], recovered); + } + const Node* recreated_exit = rewrite_node(rewriter, exiting_node->node); - LARRAY(const Node*, recovered_args, exit_allocas[i].count); - for (size_t j = 0; j < exit_allocas[i].count; j++) - recovered_args[j] = gen_load(exit_recover_bb, exit_allocas[i].nodes[j]); + LARRAY(const Node*, recovered_args, exit_param_allocas[i].count); + for (size_t j = 0; j < exit_param_allocas[i].count; j++) + recovered_args[j] = gen_load(exit_recover_bb, exit_param_allocas[i].nodes[j]); exit_numbers[i] = int32_literal(arena, i); Node* exit_bb = basic_block(arena, fn, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name(exiting_node->node))); if (recreated_exit->tag == BasicBlock_TAG) { exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, jump(arena, (Jump) { - .target = recreated_exit, - .args = nodes(arena, exit_allocas[i].count, recovered_args), + .target = recreated_exit, + .args = nodes(arena, exit_param_allocas[i].count, recovered_args), })); } else { assert(recreated_exit->tag == Case_TAG); - exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, let(arena, quote_helper(arena, nodes(arena, exit_allocas[i].count, recovered_args)), recreated_exit)); + exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, let(arena, quote_helper(arena, nodes(arena, exit_param_allocas[i].count, recovered_args)), recreated_exit)); } exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena)); + destroy_list(leaking[i]); } + const Node* outer_body; if (exiting_nodes_count == 1) outer_body = finish_body(outer_bb, exit_jumps[0]->payload.jump.target->payload.basic_block.body); else { @@ -311,12 +386,14 @@ static const Node* process_node(Context* ctx, const Node* node) { ctx->fwd_scope = new_scope(ctx->current_fn); ctx->back_scope = new_scope_flipped(ctx->current_fn); ctx->current_looptree = build_loop_tree(ctx->fwd_scope); + ctx->scope_vars = compute_scope_variables_map(ctx->fwd_scope); const Node* new = process_abstraction(ctx, node);; destroy_scope(ctx->fwd_scope); destroy_scope(ctx->back_scope); destroy_loop_tree(ctx->current_looptree); + destroy_scope_variables_map(ctx->scope_vars); return new; } case Case_TAG: @@ -360,7 +437,7 @@ static const Node* process_node(Context* ctx, const Node* node) { idom = cfnode->idom->node; } - if(!idom) { + if (!idom) { break; } From 5dfa26bd9fb261b6eab1741e79e4d69d79f41e51 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 10 Apr 2024 11:48:12 +0200 Subject: [PATCH 167/693] aobench: notify on unrecognised args --- samples/aobench/ao_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 27c0ada03..0091af0e0 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -154,7 +154,7 @@ int main(int argc, char **argv) { cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); bool do_host = false, do_ispc = false, do_device = false, do_all = true; - for (size_t i = 0; i < argc; i++) { + for (size_t i = 1; i < argc; i++) { if (strcmp(argv[i], "--only-device") == 0) { do_device = true; do_all = false; @@ -164,6 +164,9 @@ int main(int argc, char **argv) { } else if (strcmp(argv[i], "--only-ispc") == 0) { do_ispc = true; do_all = false; + } else { + error_print("Unrecognised argument: %s\n", argv[i]); + error_die(); } } From dab0627087f413167515c41da9b0365b8da87bd4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 10 Apr 2024 11:48:48 +0200 Subject: [PATCH 168/693] more cfg graphviz dump helpers --- src/shady/analysis/looptree.c | 7 ++++++ src/shady/analysis/scope_dump.c | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index c29500602..ebe8d4bcc 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -295,3 +295,10 @@ void dump_loop_trees(FILE* output, Module* mod) { destroy_list(scopes); fprintf(output, "}\n"); } + + +void dump_loop_trees_auto(Module* mod) { + FILE* f = fopen("loop_trees.dot", "wb"); + dump_loop_trees(f, mod); + fclose(f); +} diff --git a/src/shady/analysis/scope_dump.c b/src/shady/analysis/scope_dump.c index dc981efb0..5f7235625 100644 --- a/src/shady/analysis/scope_dump.c +++ b/src/shady/analysis/scope_dump.c @@ -162,3 +162,43 @@ void dump_cfg_auto(Module* mod) { dump_cfg(f, mod); fclose(f); } + +static void dump_domtree_cfnode(Printer* p, CFNode* idom) { + String name = get_abstraction_name_unsafe(idom->node); + if (name) + print(p, "bb_%zu [label=\"%s\", shape=box];\n", (size_t) idom, name); + else + print(p, "bb_%zu [label=\"%%%d\", shape=box];\n", (size_t) idom, idom->node->id); + + for (size_t i = 0; i < entries_count_list(idom->dominates); i++) { + CFNode* child = read_list(CFNode*, idom->dominates)[i]; + dump_domtree_cfnode(p, child); + print(p, "bb_%zu -> bb_%zu;\n", (size_t) (idom), (size_t) (child)); + } +} + +void dump_domtree_scope(Printer* p, Scope* s) { + print(p, "subgraph cluster_%s {\n", get_abstraction_name(s->entry->node)); + dump_domtree_cfnode(p, s->entry); + print(p, "}\n"); +} + +void dump_domtree_module(Printer* p, Module* mod) { + print(p, "digraph G {\n"); + struct List* scopes = build_scopes(mod); + for (size_t i = 0; i < entries_count_list(scopes); i++) { + Scope* scope = read_list(Scope*, scopes)[i]; + dump_domtree_scope(p, scope); + destroy_scope(scope); + } + destroy_list(scopes); + print(p, "}\n"); +} + +void dump_domtree_auto(Module* mod) { + FILE* f = fopen("domtree.dot", "wb"); + Printer* p = open_file_as_printer(f); + dump_domtree_module(p, mod); + destroy_printer(p); + fclose(f); +} From 6ba42f1619eb427891028cf71dce9b67d5286834 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 10 Apr 2024 11:49:50 +0200 Subject: [PATCH 169/693] scope analysis: cleanup --- src/shady/analysis/scope.c | 102 +++++++++++++------------------------ src/shady/analysis/scope.h | 2 +- 2 files changed, 36 insertions(+), 68 deletions(-) diff --git a/src/shady/analysis/scope.c b/src/shady/analysis/scope.c index 416578502..26f8973c3 100644 --- a/src/shady/analysis/scope.c +++ b/src/shady/analysis/scope.c @@ -40,25 +40,21 @@ typedef struct { struct Dict* join_point_values; } ScopeBuildContext; -CFNode* scope_lookup(Scope* scope, const Node* block) { - CFNode** found = find_value_dict(const Node*, CFNode*, scope->map, block); +CFNode* scope_lookup(Scope* scope, const Node* abs) { + CFNode** found = find_value_dict(const Node*, CFNode*, scope->map, abs); if (found) { - assert((*found)->node); - return *found; + CFNode* cfnode = *found; + assert(cfnode->node); + assert(cfnode->node == abs); + return cfnode; } assert(false); return NULL; } -static CFNode* get_or_enqueue(ScopeBuildContext* ctx, const Node* abs) { - assert(is_abstraction(abs)); - assert(!is_function(abs) || abs == ctx->entry); - CFNode** found = find_value_dict(const Node*, CFNode*, ctx->nodes, abs); - if (found) return *found; - - CFNode* new = arena_alloc(ctx->arena, sizeof(CFNode)); +static CFNode* new_cfnode(Arena* a) { + CFNode* new = arena_alloc(a, sizeof(CFNode)); *new = (CFNode) { - .node = abs, .succ_edges = new_list(CFEdge), .pred_edges = new_list(CFEdge), .rpo_index = SIZE_MAX, @@ -66,6 +62,17 @@ static CFNode* get_or_enqueue(ScopeBuildContext* ctx, const Node* abs) { .dominates = NULL, .structurally_dominates = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), }; + return new; +} + +static CFNode* get_or_enqueue(ScopeBuildContext* ctx, const Node* abs) { + assert(is_abstraction(abs)); + assert(!is_function(abs) || abs == ctx->entry); + CFNode** found = find_value_dict(const Node*, CFNode*, ctx->nodes, abs); + if (found) return *found; + + CFNode* new = new_cfnode(ctx->arena); + new->node = abs; assert(abs && new->node); insert_dict(const Node*, CFNode*, ctx->nodes, abs, new); append_list(Node*, ctx->queue, new); @@ -101,8 +108,9 @@ static void add_edge(ScopeBuildContext* ctx, const Node* src, const Node* dst, C assert(is_structural_edge(type) == (bool) is_case(dst)); if (ctx->lt && !in_loop(ctx->lt, ctx->entry, dst)) return; - if (ctx->lt && dst == ctx->entry) + if (ctx->lt && dst == ctx->entry) { return; + } CFNode* src_node = get_or_enqueue(ctx, src); CFNode* dst_node = get_or_enqueue(ctx, dst); @@ -200,7 +208,9 @@ static void process_cf_node(ScopeBuildContext* ctx, CFNode* node) { case MergeBreak_TAG: { break; // TODO i guess } - case TailCall_TAG: + case TailCall_TAG: { + + } case Return_TAG: case Unreachable_TAG: break; case NotATerminator: if (terminator->arena->config.check_types) { error("Grammar problem"); } break; @@ -214,7 +224,7 @@ static void flip_scope(Scope* scope) { scope->entry = NULL; for (size_t i = 0; i < scope->size; i++) { - CFNode * cur = read_list(CFNode*, scope->contents)[i]; + CFNode* cur = read_list(CFNode*, scope->contents)[i]; struct List* tmp = cur->succ_edges; cur->succ_edges = cur->pred_edges; @@ -223,32 +233,23 @@ static void flip_scope(Scope* scope) { for (size_t j = 0; j < entries_count_list(cur->succ_edges); j++) { CFEdge* edge = &read_list(CFEdge, cur->succ_edges)[j]; - CFNode* tmp = edge->dst; + CFNode* tmp2 = edge->dst; edge->dst = edge->src; - edge->src = tmp; + edge->src = tmp2; } for (size_t j = 0; j < entries_count_list(cur->pred_edges); j++) { CFEdge* edge = &read_list(CFEdge, cur->pred_edges)[j]; - CFNode* tmp = edge->dst; + CFNode* tmp2 = edge->dst; edge->dst = edge->src; - edge->src = tmp; + edge->src = tmp2; } if (entries_count_list(cur->pred_edges) == 0) { if (scope->entry != NULL) { if (scope->entry->node) { - CFNode* new_entry = arena_alloc(scope->arena, sizeof(CFNode)); - *new_entry = (CFNode) { - .node = NULL, - .succ_edges = new_list(CFEdge), - .pred_edges = new_list(CFEdge), - .rpo_index = SIZE_MAX, - .idom = NULL, - .dominates = NULL, - }; - + CFNode* new_entry = new_cfnode(scope->arena); CFEdge prev_entry_edge = { .type = JumpEdge, .src = new_entry, @@ -272,6 +273,7 @@ static void flip_scope(Scope* scope) { } } + assert(scope->entry); if (!scope->entry->node) { scope->size += 1; append_list(Node*, scope->contents, scope->entry); @@ -396,7 +398,7 @@ static size_t post_order_visit(Scope* scope, CFNode* n, size_t i) { void compute_rpo(Scope* scope) { scope->rpo = malloc(sizeof(const CFNode*) * scope->size); - size_t index = post_order_visit(scope, scope->entry, scope->size); + size_t index = post_order_visit(scope, scope->entry, scope->size); assert(index == 0); // debug_print("RPO: "); @@ -422,9 +424,9 @@ void compute_domtree(Scope* scope) { continue; for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { CFEdge e = read_list(CFEdge, n->pred_edges)[j]; - CFNode* p = e.src; - if (p->rpo_index < n->rpo_index) { - n->idom = p; + CFNode* pred = e.src; + if (pred->rpo_index < n->rpo_index) { + n->idom = pred; goto outer_loop; } } @@ -464,37 +466,3 @@ void compute_domtree(Scope* scope) { append_list(CFNode*, n->idom->dominates, n); } } - -/** - * @param node: Start node. - * @param target: List to extend. @ref List of @ref CFNode* - */ -static void get_undominated_children(const CFNode* node, struct List* target) { - for (size_t i = 0; i < entries_count_list(node->succ_edges); i++) { - CFEdge edge = read_list(CFEdge, node->succ_edges)[i]; - - bool contained = false; - for (size_t j = 0; j < entries_count_list(node->dominates); j++) { - CFNode* dominated = read_list(CFNode*, node->dominates)[j]; - if (edge.dst == dominated) { - contained = true; - break; - } - } - if (!contained) - append_list(CFNode*, target, edge.dst); - } -} - -//TODO: this function can produce duplicates. -struct List* scope_get_dom_frontier(Scope* scope, const CFNode* node) { - struct List* dom_frontier = new_list(CFNode*); - - get_undominated_children(node, dom_frontier); - for (size_t i = 0; i < entries_count_list(node->dominates); i++) { - CFNode* dom = read_list(CFNode*, node->dominates)[i]; - get_undominated_children(dom, dom_frontier); - } - - return dom_frontier; -} diff --git a/src/shady/analysis/scope.h b/src/shady/analysis/scope.h index a4c87546d..c6b76402a 100644 --- a/src/shady/analysis/scope.h +++ b/src/shady/analysis/scope.h @@ -99,7 +99,7 @@ Scope* new_scope_lt_impl(const Node* entry, LoopTree* lt, bool flipped); */ #define new_scope_flipped(node) new_scope_impl(node, NULL, true); -CFNode* scope_lookup(Scope*, const Node* block); +CFNode* scope_lookup(Scope*, const Node* abs); void compute_rpo(Scope*); void compute_domtree(Scope*); From e6280df148702a90d101078d1a308f6efb95da3f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 10 Apr 2024 11:50:11 +0200 Subject: [PATCH 170/693] dump module when verify_scopes fails --- src/shady/analysis/verify.c | 11 +++++++---- src/shady/analysis/verify.h | 2 +- src/shady/compile.h | 4 ++-- src/shady/passes/opt_mem2reg.c | 2 +- src/shady/print.c | 1 - 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 454857141..807485708 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -42,7 +42,7 @@ static void verify_same_arena(Module* mod) { destroy_dict(visitor.once); } -static void verify_scoping(Module* mod) { +static void verify_scoping(const CompilerConfig* config, Module* mod) { struct List* scopes = build_scopes(mod); for (size_t i = 0; i < entries_count_list(scopes); i++) { Scope* scope = read_list(Scope*, scopes)[i]; @@ -54,7 +54,10 @@ static void verify_scoping(Module* mod) { log_node(ERROR, leaking); error_print("\n"); } - assert(entries_count_dict(entry_vars->free_set) == 0); + if (entries_count_dict(entry_vars->free_set) > 0) { + log_module(ERROR, config, mod); + error_die(); + } destroy_scope_variables_map(map); destroy_scope(scope); } @@ -118,12 +121,12 @@ static void verify_bodies(Module* mod) { } } -void verify_module(Module* mod) { +void verify_module(const CompilerConfig* config, Module* mod) { verify_same_arena(mod); // before we normalize the IR, scopes are broken because decls appear where they should not // TODO add a normalized flag to the IR and check grammar is adhered to strictly if (get_module_arena(mod)->config.check_types) { - verify_scoping(mod); + verify_scoping(config, mod); verify_bodies(mod); } } diff --git a/src/shady/analysis/verify.h b/src/shady/analysis/verify.h index aedd20142..2843ba802 100644 --- a/src/shady/analysis/verify.h +++ b/src/shady/analysis/verify.h @@ -3,6 +3,6 @@ #include "shady/ir.h" -void verify_module(Module*); +void verify_module(const CompilerConfig*, Module*); #endif diff --git a/src/shady/compile.h b/src/shady/compile.h index 809935002..2e9500007 100644 --- a/src/shady/compile.h +++ b/src/shady/compile.h @@ -17,7 +17,7 @@ old_mod = *pmod; \ *pmod = pass_name(config, *pmod); \ (*pmod)->sealed = true; \ if (SHADY_RUN_VERIFY) \ - verify_module(*pmod); \ + verify_module(config, *pmod); \ if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) \ destroy_ir_arena(get_module_arena(old_mod)); \ old_mod = *pmod; \ @@ -26,7 +26,7 @@ if (config->optimisations.cleanup.after_every_pass) \ debugvv_print("After "#pass_name" pass: \n"); \ log_module(DEBUGVV, config, *pmod); \ if (SHADY_RUN_VERIFY) \ - verify_module(*pmod); \ + verify_module(config, *pmod); \ if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) \ destroy_ir_arena(get_module_arena(old_mod)); \ if (config->hooks.after_pass.fn) \ diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 44b70e624..5010a94cd 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -688,7 +688,7 @@ Module* opt_mem2reg(const CompilerConfig* config, Module* src) { destroy_dict(ctx.bb_new_args); destroy_arena(ctx.a); - verify_module(dst); + verify_module(config, dst); if (get_module_arena(src) != initial_arena) destroy_ir_arena(get_module_arena(src)); diff --git a/src/shady/print.c b/src/shady/print.c index dc9375b49..ea4231226 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -973,7 +973,6 @@ void print_module(Printer* printer, Module* mod, PrintConfig config) { }; print_mod_impl(&ctx, mod); flush(ctx.printer); - destroy_printer(ctx.printer); } void print_node(Printer* printer, const Node* node, PrintConfig config) { From 1832a6423cca03a15cbe64327ea073d5212aa58b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 10 Apr 2024 12:06:53 +0200 Subject: [PATCH 171/693] add flag for structure parsing --- include/shady/driver.h | 4 ++-- include/shady/ir.h | 1 + samples/checkerboard/checkerboard.c | 2 +- src/driver/cli.c | 1 + src/driver/driver.c | 10 +++++----- src/driver/vcc.c | 4 +++- src/frontends/llvm/l2s.c | 3 ++- src/frontends/llvm/l2s.h | 2 +- src/frontends/llvm/l2s_postprocess.c | 4 ++++ src/frontends/llvm/l2s_private.h | 1 + src/runtime/runtime_program.c | 4 ++-- 11 files changed, 23 insertions(+), 13 deletions(-) diff --git a/include/shady/driver.h b/include/shady/driver.h index a0a5ace03..0e5f440f1 100644 --- a/include/shady/driver.h +++ b/include/shady/driver.h @@ -26,8 +26,8 @@ typedef enum { } SourceLanguage; SourceLanguage guess_source_language(const char* filename); -ShadyErrorCodes driver_load_source_file(SourceLanguage lang, size_t, const char* file_contents, Module* mod); -ShadyErrorCodes driver_load_source_file_from_filename(const char* filename, Module* mod); +ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t, const char* file_contents, Module* mod); +ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, Module* mod); typedef enum { TgtAuto, diff --git a/include/shady/ir.h b/include/shady/ir.h index 163361d62..3105e8cfc 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -281,6 +281,7 @@ struct CompilerConfig_ { bool force_join_point_lifting; bool assume_no_physical_global_ptrs; bool restructure_everything; + bool recover_structure; } hacks; struct { diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index fe4c7ac07..4d120e1f4 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -69,7 +69,7 @@ int main(int argc, char **argv) IrArena* a = new_ir_arena(default_arena_config()); Module* m = new_module(a, "checkerboard"); - driver_load_source_file(SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, m); + driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, m); Program* program = new_program_from_module(runtime, &compiler_config, m); wait_completion(launch_kernel(program, device, "main", 16, 16, 1, 1, (void*[]) { &buf_addr })); diff --git a/src/driver/cli.c b/src/driver/cli.c index ec3ad9377..bd5ceccfb 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -100,6 +100,7 @@ F(logging.print_generated, print-generated) \ F(lower.simt_to_explicit_simd, lower-simt-to-simd) \ F(optimisations.inline_everything, inline-everything) \ F(hacks.restructure_everything, restructure-everything) \ +F(hacks.recover_structure, recover-structure) \ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { int argc = *pargc; diff --git a/src/driver/driver.c b/src/driver/driver.c index 576035cb3..e55e4192e 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -37,11 +37,11 @@ SourceLanguage guess_source_language(const char* filename) { return SrcSlim; } -ShadyErrorCodes driver_load_source_file(SourceLanguage lang, size_t len, const char* file_contents, Module* mod) { +ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t len, const char* file_contents, Module* mod) { switch (lang) { case SrcLLVM: { #ifdef LLVM_PARSER_PRESENT - parse_llvm_into_shady(mod, len, file_contents); + parse_llvm_into_shady(config, mod, len, file_contents); #else assert(false && "LLVM front-end missing in this version"); #endif @@ -67,7 +67,7 @@ ShadyErrorCodes driver_load_source_file(SourceLanguage lang, size_t len, const c return NoError; } -ShadyErrorCodes driver_load_source_file_from_filename(const char* filename, Module* mod) { +ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, Module* mod) { ShadyErrorCodes err; SourceLanguage lang = guess_source_language(filename); size_t len; @@ -84,7 +84,7 @@ ShadyErrorCodes driver_load_source_file_from_filename(const char* filename, Modu err = InputFileDoesNotExist; goto exit; } - err = driver_load_source_file(lang, len, contents, mod); + err = driver_load_source_file(config, lang, len, contents, mod); exit: free((void*) contents); return err; @@ -98,7 +98,7 @@ ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { size_t num_source_files = entries_count_list(args->input_filenames); for (size_t i = 0; i < num_source_files; i++) { - int err = driver_load_source_file_from_filename(read_list(const char*, args->input_filenames)[i], mod); + int err = driver_load_source_file_from_filename(&args->config, read_list(const char*, args->input_filenames)[i], mod); if (err) return err; } diff --git a/src/driver/vcc.c b/src/driver/vcc.c index bd829d990..2f7e0223f 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -55,6 +55,8 @@ int main(int argc, char** argv) { .tmp_filename = NULL, .delete_tmp_file = true }; + args.config.hacks.recover_structure = true; + cli_parse_driver_arguments(&args, &argc, argv); cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.config, &argc, argv); @@ -143,7 +145,7 @@ int main(int argc, char** argv) { char* llvm_ir; if (!read_file(vcc_options.tmp_filename, &len, &llvm_ir)) exit(InputFileIOError); - driver_load_source_file(SrcLLVM, len, llvm_ir, mod); + driver_load_source_file(&args.config, SrcLLVM, len, llvm_ir, mod); free(llvm_ir); if (vcc_options.delete_tmp_file) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 7820ef882..f6b602a45 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -230,7 +230,7 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { return r; } -bool parse_llvm_into_shady(Module* dst, size_t len, const char* data) { +bool parse_llvm_into_shady(const CompilerConfig* config, Module* dst, size_t len, const char* data) { LLVMContextRef context = LLVMContextCreate(); LLVMModuleRef src; LLVMMemoryBufferRef mem = LLVMCreateMemoryBufferWithMemoryRange(data, len, "my_great_buffer", false); @@ -248,6 +248,7 @@ bool parse_llvm_into_shady(Module* dst, size_t len, const char* data) { Module* dirty = new_module(get_module_arena(dst), "dirty"); Parser p = { .ctx = context, + .config = config, .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .scopes = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), diff --git a/src/frontends/llvm/l2s.h b/src/frontends/llvm/l2s.h index 8ec275b98..62f9c464a 100644 --- a/src/frontends/llvm/l2s.h +++ b/src/frontends/llvm/l2s.h @@ -4,6 +4,6 @@ #include "shady/ir.h" #include -bool parse_llvm_into_shady(Module* dst, size_t len, const char* data); +bool parse_llvm_into_shady(const CompilerConfig*, Module* dst, size_t len, const char* data); #endif diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 64fcf28ed..5a0242c0a 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -11,6 +11,7 @@ typedef struct { Rewriter rewriter; + const CompilerConfig* config; Parser* p; Scope* curr_scope; const Node* old_fn_or_bb; @@ -138,6 +139,8 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, assert(src && dst); rewrite_node(&ctx->rewriter, dst); + if (!ctx->config->hacks.recover_structure) + break; Nodes* src_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, src); Nodes* dst_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, dst); if (!src_lexical_scope) { @@ -251,6 +254,7 @@ void postprocess(Parser* p, Module* src, Module* dst) { assert(src != dst); Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .config = p->config, .p = p, .controls = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), }; diff --git a/src/frontends/llvm/l2s_private.h b/src/frontends/llvm/l2s_private.h index 91d28d06a..e9fdb048a 100644 --- a/src/frontends/llvm/l2s_private.h +++ b/src/frontends/llvm/l2s_private.h @@ -11,6 +11,7 @@ #include typedef struct { + const CompilerConfig* config; LLVMContextRef ctx; struct Dict* map; struct Dict* annotations; diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index 5f811b236..a508bfb9a 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -28,7 +28,7 @@ Program* load_program(Runtime* runtime, const CompilerConfig* base_config, const IrArena* arena = new_ir_arena(default_arena_config()); Module* module = new_module(arena, "my_module"); - int err = driver_load_source_file(SrcShadyIR, strlen(program_src), program_src, module); + int err = driver_load_source_file(base_config, SrcShadyIR, strlen(program_src), program_src, module); if (err != NoError) { return NULL; } @@ -42,7 +42,7 @@ Program* load_program_from_disk(Runtime* runtime, const CompilerConfig* base_con IrArena* arena = new_ir_arena(default_arena_config()); Module* module = new_module(arena, "my_module"); - int err = driver_load_source_file_from_filename(path, module); + int err = driver_load_source_file_from_filename(base_config, path, module); if (err != NoError) { return NULL; } From f1c3a50a77f01bd284ae2aa6d84ff246cffa1841 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 10 Apr 2024 14:01:11 +0200 Subject: [PATCH 172/693] remove lcssa pass --- src/shady/CMakeLists.txt | 1 - src/shady/compile.c | 1 - src/shady/passes/lcssa.c | 217 --------------------------------------- 3 files changed, 219 deletions(-) delete mode 100644 src/shady/passes/lcssa.c diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index d542bf454..fb4ef271b 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -58,7 +58,6 @@ set(SHADY_SOURCES passes/infer.c passes/lower_cf_instrs.c passes/lift_indirect_targets.c - passes/lcssa.c passes/lower_callf.c passes/lower_alloca.c passes/lower_stack.c diff --git a/src/shady/compile.c b/src/shady/compile.c index 4ca30de75..8039d3f11 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -87,7 +87,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(normalize_builtins) RUN_PASS(infer_program) - RUN_PASS(lcssa) RUN_PASS(reconvergence_heuristics) RUN_PASS(lower_cf_instrs) diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c deleted file mode 100644 index af24e5851..000000000 --- a/src/shady/passes/lcssa.c +++ /dev/null @@ -1,217 +0,0 @@ -#include "shady/ir.h" - -#include "../rewrite.h" -#include "../analysis/scope.h" -#include "../analysis/looptree.h" -#include "../analysis/uses.h" -#include "../analysis/leak.h" -#include "../analysis/free_variables.h" - -#include "portability.h" -#include "log.h" -#include "dict.h" - -typedef struct Context_ { - Rewriter rewriter; - const CompilerConfig* config; - const Node* current_fn; - Scope* scope; - const UsesMap* scope_uses; - struct Dict* scope_vars; - LoopTree* loop_tree; - struct Dict* lifted_arguments; -} Context; - -static bool is_child(const LTNode* maybe_parent, const LTNode* child) { - const LTNode* n = child; - while (n) { - if (n == maybe_parent) - return true; - n = n->parent; - } - return NULL; -} - -static const LTNode* get_loop(const LTNode* n) { - const LTNode* p = n->parent; - if (p && p->type == LF_HEAD) - return p; - return NULL; -} - -static String loop_name(const LTNode* n) { - if (n && n->type == LF_HEAD && entries_count_list(n->cf_nodes) > 0) { - return get_abstraction_name(read_list(CFNode*, n->cf_nodes)[0]->node); - } - return ""; -} - -void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, Nodes* lparams, Nodes* nargs) { - IrArena* a = ctx->rewriter.dst_arena; - assert(old->tag == BasicBlock_TAG); - - const LTNode* bb_loop = get_loop(looptree_lookup(ctx->loop_tree, old)); - - *nparams = empty(a); - *lparams = empty(a); - *nargs = empty(a); - - const Node* fv; - size_t i = 0; - CFNode* cf_node = scope_lookup(ctx->scope, old); - CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_node); - while (dict_iter(node_vars->free_set, &i, &fv, NULL)) { - const Node* defining_abs = get_var_binding_abstraction(ctx->scope_uses, fv); - const CFNode* defining_cf_node = scope_lookup(ctx->scope, defining_abs); - assert(defining_cf_node); - const LTNode* defining_loop = get_loop(looptree_lookup(ctx->loop_tree, defining_cf_node->node)); - if (!is_child(defining_loop, bb_loop)) { - // that's it, that variable is leaking ! - log_string(DEBUGV, "lcssa: "); - log_node(DEBUGV, fv); - log_string(DEBUGV, " (%%%d) is used outside of the loop that defines it %s %s\n", fv->id, loop_name(defining_loop), loop_name(bb_loop)); - const Node* narg = rewrite_node(&ctx->rewriter, fv); - const Node* nparam = var(a, narg->type, "lcssa_phi"); - *nparams = append_nodes(a, *nparams, nparam); - *lparams = append_nodes(a, *lparams, fv); - *nargs = append_nodes(a, *nargs, narg); - } - } - - if (nparams->count > 0) - insert_dict(const Node*, Nodes, ctx->lifted_arguments, old, *nparams); -} - -const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* body) { - IrArena* a = ctx->rewriter.dst_arena; - Context ctx2 = *ctx; - ctx = &ctx2; - - Node* nfn = (Node*) rewrite_node(&ctx->rewriter, ctx->current_fn); - - if (!ctx->scope) { - error_print("LCSSA: Trying to process an abstraction that's not part of a function ('%s')!", get_abstraction_name(old)); - log_module(ERROR, ctx->config, ctx->rewriter.src_module); - error_die(); - } - const CFNode* n = scope_lookup(ctx->scope, old); - - size_t children_count = 0; - LARRAY(const Node*, old_children, entries_count_list(n->dominates)); - for (size_t i = 0; i < entries_count_list(n->dominates); i++) { - CFNode* c = read_list(CFNode*, n->dominates)[i]; - if (is_case(c->node)) - continue; - old_children[children_count++] = c->node; - } - - LARRAY(Node*, new_children, children_count); - LARRAY(Nodes, lifted_params, children_count); - LARRAY(Nodes, new_params, children_count); - for (size_t i = 0; i < children_count; i++) { - Nodes nargs; - find_liftable_loop_values(ctx, old_children[i], &new_params[i], &lifted_params[i], &nargs); - Nodes nparams = recreate_variables(&ctx->rewriter, get_abstraction_params(old_children[i])); - new_children[i] = basic_block(a, nfn, concat_nodes(a, nparams, new_params[i]), get_abstraction_name(old_children[i])); - register_processed(&ctx->rewriter, old_children[i], new_children[i]); - register_processed_list(&ctx->rewriter, get_abstraction_params(old_children[i]), nparams); - insert_dict(const Node*, Nodes, ctx->lifted_arguments, old_children[i], nargs); - } - - const Node* new = rewrite_node(&ctx->rewriter, body); - - ctx->rewriter.map = clone_dict(ctx->rewriter.map); - - for (size_t i = 0; i < children_count; i++) { - for (size_t j = 0; j < lifted_params[i].count; j++) { - remove_dict(const Node*, ctx->rewriter.map, lifted_params[i].nodes[j]); - } - register_processed_list(&ctx->rewriter, lifted_params[i], new_params[i]); - new_children[i]->payload.basic_block.body = process_abstraction_body(ctx, old_children[i], get_abstraction_body(old_children[i])); - } - - destroy_dict(ctx->rewriter.map); - - return new; -} - -const Node* process_node(Context* ctx, const Node* old) { - IrArena* a = ctx->rewriter.dst_arena; - - switch (old->tag) { - case NominalType_TAG: - case GlobalVariable_TAG: - case Constant_TAG: { - Context not_a_fn_ctx = *ctx; - ctx = ¬_a_fn_ctx; - ctx->scope = NULL; - return recreate_node_identity(&ctx->rewriter, old); - } - case Function_TAG: { - Context fn_ctx = *ctx; - ctx = &fn_ctx; - - ctx->current_fn = old; - ctx->scope = new_scope(old); - ctx->scope_uses = create_uses_map(old, (NcDeclaration | NcType)); - ctx->scope_vars = compute_scope_variables_map(ctx->scope); - ctx->loop_tree = build_loop_tree(ctx->scope); - - Node* new = recreate_decl_header_identity(&ctx->rewriter, old); - new->payload.fun.body = process_abstraction_body(ctx, old, get_abstraction_body(old)); - - destroy_loop_tree(ctx->loop_tree); - destroy_uses_map(ctx->scope_uses); - destroy_scope(ctx->scope); - destroy_scope_variables_map(ctx->scope_vars); - return new; - } - case Jump_TAG: { - Nodes nargs = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); - Nodes* lifted_args = find_value_dict(const Node*, Nodes, ctx->lifted_arguments, old->payload.jump.target); - if (lifted_args) { - nargs = concat_nodes(a, nargs, *lifted_args); - } - return jump(a, (Jump) { - .target = rewrite_node(&ctx->rewriter, old->payload.jump.target), - .args = nargs - }); - } - case BasicBlock_TAG: { - assert(false); - } - case Case_TAG: { - if (ctx->scope) { - Nodes nparams = recreate_variables(&ctx->rewriter, get_abstraction_params(old)); - register_processed_list(&ctx->rewriter, get_abstraction_params(old), nparams); - return case_(a, nparams, process_abstraction_body(ctx, old, get_abstraction_body(old))); - } - } - default: break; - } - - return recreate_node_identity(&ctx->rewriter, old); -} - -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); - -Module* lcssa(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); - Module* dst = new_module(a, get_module_name(src)); - - Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), - .config = config, - .current_fn = NULL, - .lifted_arguments = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node) - }; - - ctx.rewriter.config.fold_quote = false; - - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.lifted_arguments); - return dst; -} From a58516e7551e3bd680dbf32a49e0d76fd3b5b6b7 Mon Sep 17 00:00:00 2001 From: Michael Kenzel Date: Sat, 13 Apr 2024 01:37:27 +0200 Subject: [PATCH 173/693] make checkerboard sample work with CUDA --- samples/checkerboard/checkerboard.c | 4 ++-- samples/checkerboard/checkerboard_kernel.slim | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 4d120e1f4..bb038ab6e 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -72,7 +72,7 @@ int main(int argc, char **argv) driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, m); Program* program = new_program_from_module(runtime, &compiler_config, m); - wait_completion(launch_kernel(program, device, "main", 16, 16, 1, 1, (void*[]) { &buf_addr })); + wait_completion(launch_kernel(program, device, "checkerboard", 16, 16, 1, 1, (void*[]) { &buf_addr })); copy_from_buffer(buf, 0, img, buf_size); info_print("data %d\n", (int) img[0]); @@ -80,7 +80,7 @@ int main(int argc, char **argv) destroy_buffer(buf); shutdown_runtime(runtime); - saveppm("ao.ppm", WIDTH, HEIGHT, img); + saveppm("checkerboard.ppm", WIDTH, HEIGHT, img); destroy_ir_arena(a); free(img); } diff --git a/samples/checkerboard/checkerboard_kernel.slim b/samples/checkerboard/checkerboard_kernel.slim index 8f43575de..2412b5bfd 100644 --- a/samples/checkerboard/checkerboard_kernel.slim +++ b/samples/checkerboard/checkerboard_kernel.slim @@ -4,7 +4,7 @@ const i32 HEIGHT = 256; @Builtin("GlobalInvocationId") uniform input pack[u32; 3] global_id; -@EntryPoint("Compute") @WorkgroupSize(16, 16, 1) fn main(uniform ptr global [u8] p) { +@EntryPoint("Compute") @WorkgroupSize(16, 16, 1) fn checkerboard(uniform ptr global [u8] p) { val thread_id = global_id; val x = reinterpret[i32](thread_id#0); val y = reinterpret[i32](thread_id#1); From 032d7f822e4b50b9843c7b20e6acda4f8da66380 Mon Sep 17 00:00:00 2001 From: Michael Kenzel Date: Sat, 13 Apr 2024 01:42:37 +0200 Subject: [PATCH 174/693] turn off BUILD_SHARED_LIBS on windows --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c26181e6..20a2ecffa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,10 @@ if (MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() +if (WIN32) + set(BUILD_SHARED_LIBS OFF) +endif() + add_subdirectory(SPIRV-Headers) if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24") From 0c75231ad10f9fb2525d082b387fecf822ea62a3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Apr 2024 11:44:21 +0200 Subject: [PATCH 175/693] fix aobench ispc build --- include/shady/ir.h | 5 ++--- samples/aobench/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 3105e8cfc..6a1434c53 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -101,7 +101,6 @@ typedef struct { } optimisations; } ArenaConfig; -typedef struct CompilerConfig_ CompilerConfig; ArenaConfig default_arena_config(); IrArena* new_ir_arena(ArenaConfig); @@ -256,7 +255,7 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); //////////////////////////////// Compilation //////////////////////////////// -struct CompilerConfig_ { +typedef struct CompilerConfig_ { bool dynamic_scheduling; uint32_t per_thread_stack_size; @@ -317,7 +316,7 @@ struct CompilerConfig_ { struct { struct { void* uptr; void (*fn)(void*, String, Module*); } after_pass; } hooks; -}; +} CompilerConfig; CompilerConfig default_compiler_config(); diff --git a/samples/aobench/CMakeLists.txt b/samples/aobench/CMakeLists.txt index 772e21864..77bb7f506 100644 --- a/samples/aobench/CMakeLists.txt +++ b/samples/aobench/CMakeLists.txt @@ -11,7 +11,7 @@ if (TARGET vcc) find_program(ISPC_EXE "ispc") if (ISPC_EXE) target_compile_definitions(aobench_host PUBLIC ENABLE_ISPC=1) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc COMMAND slim ARGS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll -o ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc --entry-point aobench_kernel COMMENT generating aobench.ispc DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc COMMAND slim ARGS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll -o ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc --entry-point aobench_kernel --restructure-everything COMMENT generating aobench.ispc DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc.o COMMAND ispc ARGS ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc -o ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc.o --pic -g -O2 -woff COMMENT generating aobench.ispc.o DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc) add_library(aobench_ispc OBJECT ${CMAKE_CURRENT_BINARY_DIR}/aobench.ispc.o) set_target_properties(aobench_ispc PROPERTIES LINKER_LANGUAGE C) From 60724f3088e6910de56403fed14e2c2789c59129 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Apr 2024 15:26:17 +0200 Subject: [PATCH 176/693] fix segfault in reconvergence heuristics --- src/shady/passes/reconvergence_heuristics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index be41d2b35..e2a2604b2 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -245,7 +245,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); - Nodes exit_wrapper_params = get_abstraction_params(exit_helpers[i]); + Nodes exit_wrapper_params = get_abstraction_params(exit_wrappers[i]); BodyBuilder* exit_wrapper_bb = begin_body(arena); for (size_t j = 0; j < exit_param_allocas[i].count; j++) From 26efe854d8a793a22887323ccbcc98af7b08cc53 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Apr 2024 15:27:02 +0200 Subject: [PATCH 177/693] mem2reg: deal with leaking pointers more better --- src/shady/passes/opt_mem2reg.c | 129 +++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 53 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 5010a94cd..fe173370b 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -77,7 +77,7 @@ static PtrKnowledge* get_last_valid_ptr_knowledge(const KnowledgeBase* kb, const return k; } -static PtrKnowledge* create_ptr_knowledge(KnowledgeBase* kb, const Node* instruction) { +static PtrKnowledge* create_root_ptr_knowledge(KnowledgeBase* kb, const Node* instruction) { PtrKnowledge* k = arena_alloc(kb->a, sizeof(PtrKnowledge)); PtrSourceKnowledge* sk = arena_alloc(kb->a, sizeof(PtrSourceKnowledge)); *k = (PtrKnowledge) { .source = sk, .state = PSUnknown/*, .ptr_address = address_value*/ }; @@ -170,7 +170,8 @@ static KnowledgeBase* create_kb(Context* ctx, const Node* old) { } } assert(kb->map); - insert_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, old, kb); + bool ok = insert_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, old, kb); + assert(ok); return kb; } @@ -181,15 +182,67 @@ static void wipe_all_leaked_pointers(KnowledgeBase* kb) { while (dict_iter(kb->map, &i, &ptr, &k)) { if (k->ptr_has_leaked) { k->ptr_value = NULL; + debugvv_print("mem2reg: wiping the know ptr value for "); + log_node(DEBUGVV, ptr); + debug_print(".\n"); } } } -static void mark_values_as_escaping(KnowledgeBase* kb, Nodes values); -static void mark_value_as_escaping(KnowledgeBase* kb, const Node* value) { - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, value); - if (k) +static PtrKnowledge* find_or_create_ptr_knowledge_for_updating(Context* ctx, KnowledgeBase* kb, const Node* optr, bool create) { + Rewriter* r = &ctx->rewriter; + PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, optr); + if (k) { + k = update_ptr_knowledge(kb, optr, k); + } else { + PtrSourceKnowledge* sk = NULL; + CFNode* cf_node = scope_lookup(ctx->scope, ctx->oabs); + // we're creating a new chain of knowledge, but we want to use the same source if possible + while (cf_node) { + KnowledgeBase* kb2 = get_kb(ctx, cf_node->node); + assert(kb2); + PtrKnowledge* k2 = get_last_valid_ptr_knowledge(kb2, optr); + if (k2) { + sk = k2->source; + break; + } + cf_node = cf_node->idom; + } + if (sk) { + k = arena_alloc(ctx->a, sizeof(PtrKnowledge)); + *k = (PtrKnowledge) { + .source = sk, + .ptr_has_leaked = true // TODO: this is wrong in the "too conservative" way + // fixing this requires accounting for the dominance relation properly + // to visit all predecessors first, then merging the knowledge + }; + insert_ptr_knowledge(kb, optr, k); + } else if (create) { + // just make up a new source and assume it leaks/aliases + k = create_root_ptr_knowledge(kb, optr); + const Type* t = optr->type; + deconstruct_qualified_type(&t); + assert(t->tag == PtrType_TAG); + k->source->as = t->payload.ptr_type.address_space; + k->source->type = rewrite_node(r, get_pointer_type_element(t)); + k->ptr_has_leaked = true; + } + } + return k; +} + +static void mark_values_as_escaping(Context* ctx, KnowledgeBase* kb, Nodes values); + +static void mark_value_as_escaping(Context* ctx, KnowledgeBase* kb, const Node* value) { + PtrKnowledge* k = find_or_create_ptr_knowledge_for_updating(ctx, kb, value, false); + if (k) { + debugvv_print("mem2reg: marking "); + log_node(DEBUGVV, value); + debug_print(" as leaking.\n"); k->ptr_has_leaked = true; + if (k->alias_old_address) + mark_value_as_escaping(ctx, kb, k->alias_old_address); + } switch (is_value(value)) { case NotAValue: assert(false); case Value_Variable_TAG: @@ -211,10 +264,10 @@ static void mark_value_as_escaping(KnowledgeBase* kb, const Node* value) { case Value_NullPtr_TAG: break; case Value_Composite_TAG: - mark_values_as_escaping(kb, value->payload.composite.contents); + mark_values_as_escaping(ctx, kb, value->payload.composite.contents); break; case Value_Fill_TAG: - mark_value_as_escaping(kb, value->payload.fill.value); + mark_value_as_escaping(ctx, kb, value->payload.fill.value); break; case Value_Undef_TAG: break; @@ -225,9 +278,9 @@ static void mark_value_as_escaping(KnowledgeBase* kb, const Node* value) { } } -static void mark_values_as_escaping(KnowledgeBase* kb, Nodes values) { +static void mark_values_as_escaping(Context* ctx, KnowledgeBase* kb, Nodes values) { for (size_t i = 0; i < values.count; i++) - mark_value_as_escaping(kb, values.nodes[i]); + mark_value_as_escaping(ctx, kb, values.nodes[i]); } static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const Node* oinstruction) { @@ -243,7 +296,7 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No switch (payload.op) { case alloca_logical_op: case alloca_op: { - PtrKnowledge* k = create_ptr_knowledge(kb, oinstruction); + PtrKnowledge* k = create_root_ptr_knowledge(kb, oinstruction); const Type* t = oinstruction->type; deconstruct_qualified_type(&t); assert(t->tag == PtrType_TAG); @@ -293,42 +346,7 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No } case store_op: { const Node* optr = first(payload.operands); - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, optr); - if (k) { - k = update_ptr_knowledge(kb, optr, k); - } else { - PtrSourceKnowledge* sk = NULL; - CFNode* node = scope_lookup(ctx->scope, ctx->oabs); - while (node) { - KnowledgeBase* kb2 = get_kb(ctx, node->node); - assert(kb2); - PtrKnowledge* k2 = get_last_valid_ptr_knowledge(kb2, optr); - if (k2) { - sk = k2->source; - break; - } - node = node->idom; - } - if (sk) { - k = arena_alloc(ctx->a, sizeof(PtrKnowledge)); - *k = (PtrKnowledge) { - .source = sk, - .ptr_has_leaked = true // TODO: this is wrong in the "too conservative" way - // fixing this requires accounting for the dominance relation properly - // to visit all predecessors first, then merging the knowledge - }; - insert_ptr_knowledge(kb, optr, k); - } else { - // just make up a new source and assume it leaks/aliases - k = create_ptr_knowledge(kb, optr); - const Type* t = optr->type; - deconstruct_qualified_type(&t); - assert(t->tag == PtrType_TAG); - k->source->as = t->payload.ptr_type.address_space; - k->source->type = rewrite_node(r, get_pointer_type_element(t)); - k->ptr_has_leaked = true; - } - } + PtrKnowledge* k = find_or_create_ptr_knowledge_for_updating(ctx, kb, optr, true); if (k) { k->state = PSKnownValue; k->ptr_value = rewrite_node(r, payload.operands.nodes[1]); @@ -341,6 +359,11 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No // if we have knowledge on a particular ptr, the same knowledge propagates if we bitcast it! PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, first(payload.operands)); if (k) { + debug_print("mem2reg: the reinterpreted ptr "); + log_node(DEBUG, oinstruction); + debug_print(" is the same as "); + log_node(DEBUG, first(payload.operands)); + debug_print(".\n"); k = update_ptr_knowledge(kb, oinstruction, k); k->state = PSKnownAlias; k->alias_old_address = first(payload.operands); @@ -363,12 +386,12 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No k->alias_old_address = first(payload.operands); } } - break; + return rewritten; } default: break; } - mark_values_as_escaping(kb, payload.operands); + mark_values_as_escaping(ctx, kb, payload.operands); if (has_primop_got_side_effects(payload.op)) wipe_all_leaked_pointers(kb); @@ -385,7 +408,7 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No case Instruction_Match_TAG: break; case Instruction_Loop_TAG: - mark_values_as_escaping(kb, oinstruction->payload.loop_instr.initial_args); + mark_values_as_escaping(ctx, kb, oinstruction->payload.loop_instr.initial_args); // assert(false && "unsupported"); break; } @@ -431,7 +454,7 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod return jump_helper(a, wrapper, args); } case Terminator_TailCall_TAG: - mark_values_as_escaping(kb, old->payload.tail_call.args); + mark_values_as_escaping(ctx, kb, old->payload.tail_call.args); break; case Terminator_Branch_TAG: break; @@ -439,7 +462,7 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod break; case Terminator_Join_TAG: // TODO: local joins are fine - mark_values_as_escaping(kb, old->payload.join.args); + mark_values_as_escaping(ctx, kb, old->payload.join.args); break; case Terminator_MergeContinue_TAG: break; @@ -448,7 +471,7 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod case Terminator_Yield_TAG: break; case Terminator_Return_TAG: - mark_values_as_escaping(kb, old->payload.fn_ret.args); + mark_values_as_escaping(ctx, kb, old->payload.fn_ret.args); break; case Terminator_Unreachable_TAG: break; From e35eb46abe28ca636ffccd2a36e34c548bf2d9b3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Apr 2024 14:27:27 +0200 Subject: [PATCH 178/693] added reference types --- include/shady/grammar.json | 3 +- src/frontends/slim/parser.c | 35 ++++++++++++++++++------ src/frontends/slim/token.h | 1 + src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_lea.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 4 +-- src/shady/print.c | 5 ++-- src/shady/type.c | 24 +++++++++++----- 8 files changed, 54 insertions(+), 22 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 927ee980c..64db9ee37 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -225,7 +225,8 @@ "class": "type", "ops": [ { "name": "address_space", "type": "AddressSpace" }, - { "name": "pointed_type", "class": "type" } + { "name": "pointed_type", "class": "type" }, + { "name": "is_reference", "type": "bool" } ] }, { diff --git a/src/frontends/slim/parser.c b/src/frontends/slim/parser.c index c65ff6667..8ab8ad0da 100644 --- a/src/frontends/slim/parser.c +++ b/src/frontends/slim/parser.c @@ -215,16 +215,20 @@ static const Node* accept_value(ctxparams) { } } -static AddressSpace expect_ptr_address_space(ctxparams) { +static AddressSpace accept_address_space(ctxparams) { switch (curr_token(tokenizer).tag) { - case global_tok: next_token(tokenizer); return AsGlobalPhysical; - case private_tok: next_token(tokenizer); return AsPrivatePhysical; - case shared_tok: next_token(tokenizer); return AsSharedPhysical; - case subgroup_tok: next_token(tokenizer); return AsSubgroupPhysical; + case global_tok: next_token(tokenizer); return AsGlobal; + case private_tok: next_token(tokenizer); return AsPrivate; + case shared_tok: next_token(tokenizer); return AsShared; + case subgroup_tok: next_token(tokenizer); return AsSubgroup; case generic_tok: next_token(tokenizer); return AsGeneric; - default: error("expected address space qualifier"); + case input_tok: next_token(tokenizer); return AsInput; + case output_tok: next_token(tokenizer); return AsOutput; + case extern_tok: next_token(tokenizer); return AsExternal; + default: + break; } - SHADY_UNREACHABLE; + return NumAddressSpaces; } static const Type* accept_unqualified_type(ctxparams) { @@ -235,12 +239,27 @@ static const Type* accept_unqualified_type(ctxparams) { } else if (accept_token(ctx, mask_t_tok)) { return mask_type(arena); } else if (accept_token(ctx, ptr_tok)) { - AddressSpace as = expect_ptr_address_space(ctx); + AddressSpace as = accept_address_space(ctx); + if (as == NumAddressSpaces) { + error("expected address space qualifier"); + } + const Type* elem_type = accept_unqualified_type(ctx); + expect(elem_type); + return ptr_type(arena, (PtrType) { + .address_space = as, + .pointed_type = elem_type, + }); + } else if (accept_token(ctx, ref_tok)) { + AddressSpace as = accept_address_space(ctx); + if (as == NumAddressSpaces) { + error("expected address space qualifier"); + } const Type* elem_type = accept_unqualified_type(ctx); expect(elem_type); return ptr_type(arena, (PtrType) { .address_space = as, .pointed_type = elem_type, + .is_reference = true, }); } else if (config.front_end && accept_token(ctx, lsbracket_tok)) { const Type* elem_type = accept_unqualified_type(ctx); diff --git a/src/frontends/slim/token.h b/src/frontends/slim/token.h index 860ce03b7..138e1f21e 100644 --- a/src/frontends/slim/token.h +++ b/src/frontends/slim/token.h @@ -31,6 +31,7 @@ TEXT_TOKEN(val) \ TEXT_TOKEN(let) \ TEXT_TOKEN(in) \ TEXT_TOKEN(ptr) \ +TEXT_TOKEN(ref) \ TEXT_TOKEN(type) \ TEXT_TOKEN(fn) \ TEXT_TOKEN(cont) \ diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 1a88e8f13..0ca9c1442 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -52,7 +52,7 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, struct L const Node* nvar = rewrite_node(&ctx->rewriter, ovar); const Type* t = nvar->type; deconstruct_qualified_type(&t); - assert(t->tag != PtrType_TAG || is_physical_as(t->payload.ptr_type.address_space)); + assert(t->tag != PtrType_TAG || !t->payload.ptr_type.is_reference && "References cannot be spilled"); const Node* save_instruction = prim_op(a, (PrimOp) { .op = push_stack_op, .type_arguments = singleton(get_unqualified_type(nvar->type)), diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 0fc2b8fe2..b1b6f01a9 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -110,7 +110,7 @@ static const Node* process(Context* ctx, const Node* old) { bool must_lower = false; // we have to lower generic pointers if we emulate them using ints must_lower |= ctx->config->lower.emulate_generic_ptrs && old_base_ptr_t->payload.ptr_type.address_space == AsGeneric; - must_lower |= ctx->config->lower.emulate_physical_memory && is_physical_as(old_base_ptr_t->payload.ptr_type.address_space); + must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference; if (!must_lower) break; BodyBuilder* bb = begin_body(a); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 3580c3e51..6f5516e44 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -309,7 +309,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Type* ptr_type = old_ptr->type; bool uniform_ptr = deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); - if (!is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) + if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; BodyBuilder* bb = begin_body(a); @@ -331,7 +331,7 @@ static const Node* process_node(Context* ctx, const Node* old) { break; } case PtrType_TAG: { - if (is_as_emulated(ctx, old->payload.ptr_type.address_space)) + if (!old->payload.ptr_type.is_reference && is_as_emulated(ctx, old->payload.ptr_type.address_space)) return int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); break; } diff --git a/src/shady/print.c b/src/shady/print.c index ea4231226..5a5959b76 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -307,7 +307,7 @@ static void print_type(PrinterCtx* ctx, const Node* node) { break; } case PtrType_TAG: { - printf("ptr"); + printf(node->payload.ptr_type.is_reference ? "ref" : "ptr"); printf(RESET); printf("("); printf(BLUE); @@ -807,8 +807,9 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { const GlobalVariable* gvar = &node->payload.global_variable; print_annotations(ctx, gvar->annotations); printf(BLUE); + printf("var "); + printf(BLUE); printf(get_address_space_name(gvar->address_space)); - printf(RESET); printf(" "); print_node(gvar->type); printf(BYELLOW); diff --git a/src/shady/type.c b/src/shady/type.c index 5b0293322..db7de4c95 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -95,6 +95,8 @@ bool is_subtype(const Type* supertype, const Type* type) { // if either pointer type is untyped, both need to be if (supertype->arena->config.untyped_ptrs && (!supertype->payload.ptr_type.pointed_type || !type->payload.ptr_type.pointed_type)) return !supertype->payload.ptr_type.pointed_type && !type->payload.ptr_type.pointed_type; + if (!supertype->payload.ptr_type.is_reference && type->payload.ptr_type.is_reference) + return false; return is_subtype(supertype->payload.ptr_type.pointed_type, type->payload.ptr_type.pointed_type); } case Int_TAG: return supertype->payload.int_type.width == type->payload.int_type.width && supertype->payload.int_type.is_signed == type->payload.int_type.is_signed; @@ -301,8 +303,9 @@ bool is_ordered_type(const Type* t) { bool is_physical_ptr_type(const Type* t) { if (t->tag != PtrType_TAG) return false; - AddressSpace as = t->payload.ptr_type.address_space; - return is_physical_as(as); + return !t->payload.ptr_type.is_reference; + // AddressSpace as = t->payload.ptr_type.address_space; + // return t->arena->config.address_spaces[as].physical; } bool is_generic_ptr_type(const Type* t) { @@ -764,6 +767,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { .type = ptr_type(arena, (PtrType) { .pointed_type = elem_type, .address_space = as, + .is_reference = as == AsFunction }) }); } @@ -775,7 +779,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { bool uniform = is_qualified_type_uniform(base->type); const Type* base_ptr_type = get_unqualified_type(base->type); - assert(base_ptr_type->tag == PtrType_TAG && "lea expects a pointer as a base"); + assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; const Node* offset = prim_op.operands.nodes[1]; @@ -786,7 +790,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const IntLiteral* lit = resolve_to_int_literal(offset); bool offset_is_zero = lit && lit->value == 0; - assert(offset_is_zero || pointee_type->tag == ArrType_TAG && "if an offset is used, the base pointer must point to an array"); + assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); + assert(offset_is_zero || pointee_type->tag == ArrType_TAG && "if an offset is used, the base ptr must point to an array"); uniform &= offset_uniform; Nodes indices = nodes(arena, prim_op.operands.count - 2, &prim_op.operands.nodes[2]); @@ -794,7 +799,11 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { return qualified_type(arena, (QualifiedType) { .is_uniform = uniform, - .type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type, .address_space = base_ptr_type->payload.ptr_type.address_space }) + .type = ptr_type(arena, (PtrType) { + .pointed_type = pointee_type, + .address_space = base_ptr_type->payload.ptr_type.address_space, + .is_reference = base_ptr_type->payload.ptr_type.is_reference + }) }); } case memcpy_op: { @@ -1017,7 +1026,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case get_stack_base_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 0); - const Node* ptr = ptr_type(arena, (PtrType) { .pointed_type = arr_type(arena, (ArrType) { .element_type = uint8_type(arena), .size = NULL }), .address_space = prim_op.op == get_stack_base_op ? AsPrivatePhysical : AsSubgroupPhysical}); + const Node* ptr = ptr_type(arena, (PtrType) { .pointed_type = arr_type(arena, (ArrType) { .element_type = uint8_type(arena), .size = NULL }), .address_space = AsPrivate}); return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = ptr }); } case set_stack_pointer_op: { @@ -1322,7 +1331,8 @@ const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_var return ptr_type(arena, (PtrType) { .pointed_type = global_variable.type, - .address_space = global_variable.address_space + .address_space = global_variable.address_space, + .is_reference = lookup_annotation_list(global_variable.annotations, "Logical"), }); } From 60bd52135692a2794fe43f09315dc40b6f2c9ec9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Apr 2024 14:29:49 +0200 Subject: [PATCH 179/693] address spaces are no longer inherently logical or physical --- include/shady/grammar.json | 43 ++++--------- include/shady/ir.h | 7 ++- samples/fib.slim | 4 +- src/driver/cli.c | 1 - src/frontends/llvm/l2s_annotations.c | 29 ++++++--- src/frontends/llvm/l2s_instr.c | 19 ++---- src/frontends/slim/parser.c | 62 ++++++++++++------- src/frontends/slim/token.h | 1 + src/frontends/spirv/s2s.c | 25 ++++---- src/shady/api/generator_grammar.c | 12 ---- src/shady/compile.c | 12 +++- src/shady/emit/c/emit_c.c | 23 +++---- src/shady/emit/spirv/emit_spv.c | 3 +- src/shady/emit/spirv/emit_spv_instructions.c | 6 +- src/shady/emit/spirv/emit_spv_type.c | 9 ++- src/shady/internal/scheduler.slim | 14 ++--- src/shady/node.c | 1 + src/shady/passes/infer.c | 6 +- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_generic_globals.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 11 ++-- src/shady/passes/lower_physical_ptrs.c | 44 +++++++------ src/shady/passes/lower_stack.c | 4 +- src/shady/passes/lower_subgroup_vars.c | 11 ++-- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/simt2d.c | 2 +- src/shady/passes/specialize_execution_model.c | 4 +- src/shady/passes/spirv_lift_globals_ssbo.c | 8 +-- src/shady/transform/memory_layout.c | 12 ++-- src/shady/type.c | 23 +++---- test/memory1.slim | 2 +- test/subgroup_var.slim | 2 +- 32 files changed, 197 insertions(+), 209 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 64db9ee37..9cc76508a 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -2,53 +2,32 @@ "address-spaces": [ { "name": "Generic", - "llvm-id": 0, - "physical": true + "llvm-id": 0 }, { - "name": "GlobalPhysical", + "name": "Global", "description": "Global memory, all threads see the same data (not necessarily consistent!)", - "llvm-id": 1, - "physical": true + "llvm-id": 1 }, { - "name": "SharedPhysical", + "name": "Shared", "description": "Points into workgroup-private memory (aka shared memory)", - "llvm-id": 3, - "physical": true + "llvm-id": 3 }, { - "name": "SubgroupPhysical", + "name": "Subgroup", "description": [ "Points into subgroup-private memory", "All threads in a subgroup see the same contents for the same address, but threads in different subgroups see different data.", "Needs to be lowered to something else since targets do not understand this" ], - "llvm-id": 9, - "physical": true + "llvm-id": 9 }, { - "name": "PrivatePhysical", + "name": "Private", "description": [ "Points into thread-private memory (all threads see different contents for the same address)" ], - "llvm-id": 5, - "physical": true - }, - { - "name": "GlobalLogical", - "llvm-id": 388 - }, - { - "name": "SharedLogical", - "llvm-id": 387 - }, - { - "name": "SubgroupLogical", - "llvm-id": 386 - }, - { - "name": "PrivateLogical", - "llvm-id": 385 + "llvm-id": 5 }, { "name": "Input", @@ -74,8 +53,8 @@ "llvm-id": 392 }, { - "name": "FunctionLogical", - "description": "Weird SPIR-V nonsense: this is like PrivateLogical, but with non-static lifetimes (ie function lifetime)", + "name": "Function", + "description": "Weird SPIR-V nonsense: this is like Private, but with non-static lifetimes (ie function lifetime)", "llvm-id": 393 }, { diff --git a/include/shady/ir.h b/include/shady/ir.h index 6a1434c53..c573c51e1 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -73,8 +73,10 @@ typedef struct { bool validate_builtin_types; // do @Builtins variables need to match their type in builtins.h ? bool is_simt; - bool allow_subgroup_memory; - bool allow_shared_memory; + struct { + bool physical; + bool allowed; + } address_spaces[NumAddressSpaces]; struct { /// Selects which type the subgroup intrinsic primops use to manipulate masks @@ -278,7 +280,6 @@ typedef struct CompilerConfig_ { struct { bool spv_shuffle_instead_of_broadcast_first; bool force_join_point_lifting; - bool assume_no_physical_global_ptrs; bool restructure_everything; bool recover_structure; } hacks; diff --git a/samples/fib.slim b/samples/fib.slim index f8d6e4edd..5e6eb8563 100644 --- a/samples/fib.slim +++ b/samples/fib.slim @@ -5,10 +5,10 @@ fn fib varying u32(varying u32 n) { } @Builtin("SubgroupLocalInvocationId") -input u32 subgroup_local_id; +var input u32 subgroup_local_id; @Builtin("SubgroupId") -uniform input u32 subgroup_id; +var uniform input u32 subgroup_id; @EntryPoint("Compute") @WorkgroupSize(32, 1, 1) fn main() { val n = subgroup_local_id % u32 16; diff --git a/src/driver/cli.c b/src/driver/cli.c index bd5ceccfb..41f9463a8 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -93,7 +93,6 @@ F(lower.emulate_physical_memory, emulate-physical-memory) \ F(lower.emulate_generic_ptrs, emulate-generic-pointers) \ F(dynamic_scheduling, dynamic-scheduling) \ F(hacks.force_join_point_lifting, lift-join-points) \ -F(hacks.assume_no_physical_global_ptrs, assume-no-physical-global-ptrs) \ F(logging.print_internal, print-internal) \ F(logging.print_generated, print-builtin) \ F(logging.print_generated, print-generated) \ diff --git a/src/frontends/llvm/l2s_annotations.c b/src/frontends/llvm/l2s_annotations.c index 44e2b364c..b38debd06 100644 --- a/src/frontends/llvm/l2s_annotations.c +++ b/src/frontends/llvm/l2s_annotations.c @@ -29,6 +29,23 @@ static const Node* assert_and_strip_fn_addr(const Node* fn) { return fn; } +static const Node* look_past_stuff(const Node* thing) { + if (thing->tag == Constant_TAG) { + const Node* instr = thing->payload.constant.instruction; + assert(instr->tag == PrimOp_TAG); + thing = instr; + } + if (thing->tag == PrimOp_TAG) { + switch (thing->payload.prim_op.op) { + case reinterpret_op: + case convert_op: + case lea_op: thing = first(thing->payload.prim_op.operands); break; + default: assert(false); + } + } + return thing; +} + void process_llvm_annotations(Parser* p, LLVMValueRef global) { IrArena* a = get_module_arena(p->dst); const Type* t = convert_type(p, LLVMGlobalGetValueType(global)); @@ -39,19 +56,11 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { assert(value->tag == Composite_TAG && value->payload.composite.contents.count == arr_size); for (size_t i = 0; i < arr_size; i++) { const Node* entry = value->payload.composite.contents.nodes[i]; + entry = look_past_stuff(entry); assert(entry->tag == Composite_TAG); const Node* annotation_payload = entry->payload.composite.contents.nodes[1]; // eliminate dummy reinterpret cast - if (annotation_payload->tag == Constant_TAG) { - const Node* instr = annotation_payload->payload.constant.instruction; - assert(instr->tag == PrimOp_TAG); - switch (instr->payload.prim_op.op) { - case reinterpret_op: - case convert_op: - case lea_op: annotation_payload = first(instr->payload.prim_op.operands); break; - default: assert(false); - } - } + annotation_payload = look_past_stuff(annotation_payload); if (annotation_payload->tag == RefDecl_TAG) { annotation_payload = annotation_payload->payload.ref_decl.decl; } diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index 9a2c9bdb4..d8215e92e 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -219,10 +219,10 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM case LLVMAlloca: { assert(t->tag == PtrType_TAG); const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); - const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivatePhysical }); + const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivate }); r = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, alloca_op, singleton(allocated_t), empty(a)), singleton(allocated_ptr_t), NULL)); if (UNTYPED_POINTERS) { - const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivatePhysical }); + const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivate }); r = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), 1, NULL)); } r = prim_op_helper(a, convert_op, singleton(t), singleton(r)); @@ -308,24 +308,13 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM if (src_t->tag == PtrType_TAG && t->tag == PtrType_TAG) { if ((t->payload.ptr_type.address_space == AsGeneric)) { switch (src_t->payload.ptr_type.address_space) { - case AsPrivatePhysical: - case AsSubgroupPhysical: - case AsSharedPhysical: - case AsGlobalPhysical: - op = convert_op; - break; case AsGeneric: // generic-to-generic isn't a conversion. break; default: { - warn_print("Cannot cast address space %s to Generic! Ignoring.\n", get_address_space_name(src_t->payload.ptr_type.address_space)); - r = quote_helper(a, singleton(src)); - goto shortcut; + op = convert_op; + break; } } - } else if (!is_physical_as(t->payload.ptr_type.address_space)) { - warn_print("Cannot cast address space %s since it's non-physical. Ignoring.\n", get_address_space_name(src_t->payload.ptr_type.address_space)); - r = quote_helper(a, singleton(src)); - goto shortcut; } } else { assert(opcode != LLVMAddrSpaceCast); diff --git a/src/frontends/slim/parser.c b/src/frontends/slim/parser.c index 8ab8ad0da..a267ad270 100644 --- a/src/frontends/slim/parser.c +++ b/src/frontends/slim/parser.c @@ -996,30 +996,48 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { } static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { - AddressSpace as; - if (accept_token(ctx, private_tok)) - as = AsPrivateLogical; - else if (accept_token(ctx, shared_tok)) - as = AsSharedLogical; - else if (accept_token(ctx, subgroup_tok)) - as = AsSubgroupLogical; - else if (accept_token(ctx, global_tok)) - as = AsGlobalLogical; - else if (accept_token(ctx, extern_tok)) - as = AsExternal; - else if (accept_token(ctx, input_tok)) - as = AsInput; - else if (accept_token(ctx, output_tok)) - as = AsOutput; - else if (accept_token(ctx, uniform_tok)) { - if (accept_token(ctx, input_tok)) { + if (!accept_token(ctx, var_tok)) + return NULL; + + AddressSpace as = NumAddressSpaces; + bool uniform = false, logical = false; + while (true) { + AddressSpace nas = accept_address_space(ctx); + if (nas != NumAddressSpaces) { + if (as != NumAddressSpaces && as != nas) { + error("Conflicting address spaces for definition: %s and %s.\n", get_address_space_name(as), get_address_space_name(nas)); + } + as = nas; + continue; + } + if (accept_token(ctx, logical_tok)) { + logical = true; + continue; + } + if (accept_token(ctx, uniform_tok)) { + uniform = true; + continue; + } + break; + } + + if (as == NumAddressSpaces) { + error("Address space required for global variable declaration.\n"); + } + + if (uniform) { + if (as == AsInput) as = AsUInput; - } else { - expect(false && "expected 'input'"); - return NULL; + else { + error("'uniform' can only be used with 'input' currently.\n"); } - } else - return NULL; + } + + if (logical) { + annotations = append_nodes(arena, annotations, annotation(arena, (Annotation) { + .name = "Logical" + })); + } const Type* type = accept_unqualified_type(ctx); expect(type); diff --git a/src/frontends/slim/token.h b/src/frontends/slim/token.h index 138e1f21e..5536279aa 100644 --- a/src/frontends/slim/token.h +++ b/src/frontends/slim/token.h @@ -26,6 +26,7 @@ TEXT_TOKEN(input) \ TEXT_TOKEN(output) \ TOKEN(extern, "extern") \ TEXT_TOKEN(generic) \ +TEXT_TOKEN(logical) \ TEXT_TOKEN(var) \ TEXT_TOKEN(val) \ TEXT_TOKEN(let) \ diff --git a/src/frontends/spirv/s2s.c b/src/frontends/spirv/s2s.c index c942375ec..8ad151424 100644 --- a/src/frontends/spirv/s2s.c +++ b/src/frontends/spirv/s2s.c @@ -203,33 +203,36 @@ AddressSpace convert_storage_class(SpvStorageClass class) { switch (class) { case SpvStorageClassInput: return AsInput; case SpvStorageClassOutput: return AsOutput; - case SpvStorageClassWorkgroup: return AsSharedPhysical; - case SpvStorageClassCrossWorkgroup: return AsGlobalPhysical; - case SpvStorageClassPhysicalStorageBuffer: return AsGlobalPhysical; - case SpvStorageClassPrivate: return AsPrivatePhysical; - case SpvStorageClassFunction: return AsPrivatePhysical; + case SpvStorageClassWorkgroup: return AsShared; + case SpvStorageClassCrossWorkgroup: return AsGlobal; + case SpvStorageClassPhysicalStorageBuffer: return AsGlobal; + case SpvStorageClassPrivate: return AsPrivate; + case SpvStorageClassFunction: return AsPrivate; case SpvStorageClassGeneric: return AsGeneric; case SpvStorageClassPushConstant: return AsPushConstant; case SpvStorageClassAtomicCounter: - error("TODO"); + break; case SpvStorageClassImage: return AsImage; - error("TODO"); - case SpvStorageClassStorageBuffer: return AsGlobalLogical; + break; + case SpvStorageClassStorageBuffer: return AsShaderStorageBufferObject; case SpvStorageClassUniformConstant: - case SpvStorageClassUniform: return AsGlobalPhysical; // TODO: should probably depend on CL/VK flavours! + case SpvStorageClassUniform: return AsGlobal; // TODO: should probably depend on CL/VK flavours! case SpvStorageClassCallableDataKHR: case SpvStorageClassIncomingCallableDataKHR: case SpvStorageClassRayPayloadKHR: case SpvStorageClassHitAttributeKHR: case SpvStorageClassIncomingRayPayloadKHR: case SpvStorageClassShaderRecordBufferKHR: - error("Unsupported"); + break; case SpvStorageClassCodeSectionINTEL: case SpvStorageClassDeviceOnlyINTEL: case SpvStorageClassHostOnlyINTEL: case SpvStorageClassMax: - error("Unsupported"); + break; + default: + break; } + error("s2s: Unsupported storage class: %d\n", class); } typedef struct { diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 3ad3a6f26..0e8250696 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -10,18 +10,6 @@ static void generate_address_spaces(Growy* g, json_object* address_spaces) { } growy_append_formatted(g, "\tNumAddressSpaces,\n"); growy_append_formatted(g, "} AddressSpace;\n\n"); - - growy_append_formatted(g, "static inline bool is_physical_as(AddressSpace as) {\n"); - growy_append_formatted(g, "\tswitch(as) {\n"); - for (size_t i = 0; i < json_object_array_length(address_spaces); i++) { - json_object* as = json_object_array_get_idx(address_spaces, i); - String name = json_object_get_string(json_object_object_get(as, "name")); - if (json_object_get_boolean(json_object_object_get(as, "physical"))) - growy_append_formatted(g, "\t\tcase As%s: return true;\n", name); - } - growy_append_formatted(g, "\t\tdefault: return false;\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n\n"); } static void generate_node_tags(Growy* g, json_object* nodes) { diff --git a/src/shady/compile.c b/src/shady/compile.c index 8039d3f11..10684b025 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -49,11 +49,9 @@ CompilerConfig default_compiler_config() { } ArenaConfig default_arena_config() { - return (ArenaConfig) { + ArenaConfig config = { .is_simt = true, .validate_builtin_types = false, - .allow_subgroup_memory = true, - .allow_shared_memory = true, .memory = { .word_size = IntTy8, @@ -64,6 +62,14 @@ ArenaConfig default_arena_config() { .delete_unreachable_structured_cases = true, }, }; + + for (size_t i = 0; i < NumAddressSpaces; i++) { + // by default, all address spaces are physical ! + config.address_spaces[i].physical = true; + config.address_spaces[i].allowed = true; + } + + return config; } CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index d04a8155c..c1b2f822b 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -134,17 +134,14 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S break; case CDialect_CUDA: switch (as) { - case AsPrivateLogical: - case AsPrivatePhysical: + case AsPrivate: assert(false); // Note: this requires many hacks. prefix = "__device__ "; decl_center = format_string_arena(emitter->arena->arena, "__shady_private_globals.%s", decl_center); break; - case AsSharedPhysical: - case AsSharedLogical: prefix = "__shared__ "; break; - case AsGlobalLogical: - case AsGlobalPhysical: { + case AsShared: prefix = "__shared__ "; break; + case AsGlobal: { if (constant) prefix = "__constant__ "; else @@ -160,13 +157,13 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S break; case CDialect_GLSL: switch (as) { - case AsSharedLogical: prefix = "shared "; break; + case AsShared: prefix = "shared "; break; case AsInput: case AsUInput: prefix = "in "; break; case AsOutput: prefix = "out "; break; - case AsPrivateLogical: prefix = ""; break; + case AsPrivate: prefix = ""; break; case AsUniformConstant: prefix = "uniform"; break; - case AsGlobalLogical: { + case AsGlobal: { assert(constant && "Only constants are supported"); prefix = "const "; break; @@ -256,7 +253,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { if (emitter->config.dialect == CDialect_GLSL) return emit_value(emitter, block_printer, get_default_zero_value(emitter->arena, value->payload.undef.type)); String name = unique_name(emitter->arena, "undef"); - emit_global_variable_definition(emitter, AsGlobalLogical, name, value->payload.undef.type, true, NULL); + emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); emitted = name; break; } @@ -591,7 +588,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { decl_type = decl->payload.global_variable.type; // we emit the global variable as a CVar, so we can refer to it's 'address' without explicit ptrs emit_as = term_from_cvar(name); - if ((decl->payload.global_variable.address_space == AsPrivatePhysical || decl->payload.global_variable.address_space == AsPrivateLogical) && emitter->config.dialect == CDialect_CUDA) { + if ((decl->payload.global_variable.address_space == AsPrivate) && emitter->config.dialect == CDialect_CUDA) { if (emitter->use_private_globals) { register_emitted(emitter, decl, term_from_cvar(format_string_arena(emitter->arena->arena, "__shady_private_globals->%s", name))); // HACK @@ -651,7 +648,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { const Node* init_value = get_quoted_value(decl->payload.constant.instruction); assert(init_value && "TODO: support some measure of constant expressions"); String init = to_cvalue(emitter, emit_value(emitter, NULL, init_value)); - emit_global_variable_definition(emitter, AsGlobalLogical, decl_center, decl->type, true, init); + emit_global_variable_definition(emitter, AsGlobal, decl_center, decl->type, true, init); return; } case NominalType_TAG: { @@ -721,7 +718,7 @@ static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { if (decl->tag != GlobalVariable_TAG) continue; AddressSpace as = decl->payload.global_variable.address_space; - if (as != AsPrivatePhysical && as != AsPrivateLogical) + if (as != AsPrivate) continue; print(p, "%s;\n", c_emit_type(emitter, decl->payload.global_variable.type, decl->payload.global_variable.name)); count++; diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 1dc7c53a3..69d9ee087 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -291,7 +291,7 @@ static void emit_function(Emitter* emitter, const Node* node) { SpvId param_id = spvb_parameter(fn_builder, emit_type(emitter, param_type)); insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, params.nodes[i], param_id); deconstruct_qualified_type(¶m_type); - if (param_type->tag == PtrType_TAG && param_type->payload.ptr_type.address_space == AsGlobalPhysical) { + if (param_type->tag == PtrType_TAG && param_type->payload.ptr_type.address_space == AsGlobal) { spvb_decorate(emitter->file_builder, param_id, SpvDecorationAliased, 0, NULL); } } @@ -359,7 +359,6 @@ SpvId emit_decl(Emitter* emitter, const Node* decl) { SpvId init = 0; if (gvar->init) init = emit_value(emitter, NULL, gvar->init); - assert(!is_physical_as(gvar->address_space)); SpvStorageClass storage_class = emit_addr_space(emitter, gvar->address_space); spvb_global_variable(emitter->file_builder, given_id, emit_type(emitter, decl->type), storage_class, false, init); diff --git a/src/shady/emit/spirv/emit_spv_instructions.c b/src/shady/emit/spirv/emit_spv_instructions.c index 1deedb0b4..f3a7dd33f 100644 --- a/src/shady/emit/spirv/emit_spv_instructions.c +++ b/src/shady/emit/spirv/emit_spv_instructions.c @@ -325,7 +325,7 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui size_t operands_count = 0; uint32_t operands[2]; - if (ptr_type->payload.ptr_type.address_space == AsGlobalPhysical) { + if (ptr_type->payload.ptr_type.address_space == AsGlobal) { // TODO only do this in VK mode ? TypeMemLayout layout = get_mem_layout(emitter->arena, elem_type); operands[operands_count + 0] = SpvMemoryAccessAlignedMask; @@ -347,7 +347,7 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui size_t operands_count = 0; uint32_t operands[2]; - if (ptr_type->payload.ptr_type.address_space == AsGlobalPhysical) { + if (ptr_type->payload.ptr_type.address_space == AsGlobal) { // TODO only do this in VK mode ? TypeMemLayout layout = get_mem_layout(emitter->arena, elem_type); operands[operands_count + 0] = SpvMemoryAccessAlignedMask; @@ -364,7 +364,7 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui case alloca_logical_op: { const Type* elem_type = first(type_arguments); SpvId result = spvb_local_variable(fn_builder, emit_type(emitter, ptr_type(emitter->arena, (PtrType) { - .address_space = AsFunctionLogical, + .address_space = AsFunction, .pointed_type = elem_type })), SpvStorageClassFunction); assert(results_count == 1); diff --git a/src/shady/emit/spirv/emit_spv_type.c b/src/shady/emit/spirv/emit_spv_type.c index 98f0cad0e..a49d89c48 100644 --- a/src/shady/emit/spirv/emit_spv_type.c +++ b/src/shady/emit/spirv/emit_spv_type.c @@ -17,11 +17,10 @@ bool compare_node(Node**, Node**); SpvStorageClass emit_addr_space(Emitter* emitter, AddressSpace address_space) { switch(address_space) { - case AsGlobalLogical: return SpvStorageClassStorageBuffer; - case AsSharedLogical: return SpvStorageClassWorkgroup; - case AsPrivateLogical: return SpvStorageClassPrivate; - case AsFunctionLogical: return SpvStorageClassFunction; - case AsGlobalPhysical: + case AsShared: return SpvStorageClassWorkgroup; + case AsPrivate: return SpvStorageClassPrivate; + case AsFunction: return SpvStorageClassFunction; + case AsGlobal: spvb_set_addressing_model(emitter->file_builder, SpvAddressingModelPhysicalStorageBuffer64); spvb_extension(emitter->file_builder, "SPV_KHR_physical_storage_buffer"); spvb_capability(emitter->file_builder, SpvCapabilityPhysicalStorageBufferAddresses); diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index e83215828..0528f90de 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -9,17 +9,17 @@ u32 payload; }; -@Internal private u32 actual_subgroup_size; +@Internal var logical private u32 actual_subgroup_size; -@Internal subgroup u32 scheduler_cursor = 0; -@Internal subgroup [TreeNode; SUBGROUP_SIZE] scheduler_vector; -@Internal subgroup [u32; SUBGROUP_SIZE] resume_at; +@Internal var logical subgroup u32 scheduler_cursor = 0; +@Internal var logical subgroup [TreeNode; SUBGROUP_SIZE] scheduler_vector; +@Internal var logical subgroup [u32; SUBGROUP_SIZE] resume_at; -@Internal subgroup u32 next_fn; -@Internal subgroup TreeNode active_branch; +@Internal var logical subgroup u32 next_fn; +@Internal var logical subgroup TreeNode active_branch; @Internal @Builtin("SubgroupLocalInvocationId") -input u32 subgroup_local_id; +var logical input u32 subgroup_local_id; @Internal @Leaf fn builtin_init_scheduler() { diff --git a/src/shady/node.c b/src/shady/node.c index c35fe7789..a6ff0d9a4 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -153,6 +153,7 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi continue; } } + case convert_op: case reinterpret_op: { if (config.allow_incompatible_types) { node = first(node->payload.prim_op.operands); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 8ecaa24e2..920ab51dd 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -240,14 +240,14 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec const Node* decl = ref_decl->payload.ref_decl.decl; if (decl->tag == GlobalVariable_TAG) { AddressSpace as = decl->payload.global_variable.address_space; - if (is_physical_as(as)) { + /*if (is_physical_as(as)) { const Node* untyped_ptr = ptr_type(a, (PtrType) {.address_space = as, .pointed_type = unit_type(a)}); Node* cast_constant = constant(ctx->rewriter.dst_module, empty(a), untyped_ptr, format_string_interned(a, "%s_cast", get_declaration_name(decl))); cast_constant->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr), singleton(ref_decl)); const Node* cast_ref_decl = ref_decl_helper(a, cast_constant); register_processed(r, node, cast_ref_decl); return cast_ref_decl; - } + }*/ } } break; @@ -532,7 +532,7 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp .operands = new_ops }))); - if (was_untyped && is_physical_as(get_pointer_type_address_space(src_ptr))) { + if (was_untyped) { const Type* result_t = type_untyped_ptr(base_datatype, unit_type(a)); result = gen_reinterpret_cast(bb, result_t, result); } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 38096a4c0..278be673f 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -51,7 +51,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { if (node->tag == PrimOp_TAG) { switch (node->payload.prim_op.op) { - case alloca_op: as = AsPrivatePhysical; break; + case alloca_op: as = AsPrivate; break; default: goto not_alloca; } diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 0388ef866..fe325bd7d 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -17,7 +17,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case GlobalVariable_TAG: { if (node->payload.global_variable.address_space == AsGeneric) { - AddressSpace dst_as = AsGlobalPhysical; + AddressSpace dst_as = AsGlobal; const Type* t = rewrite_node(&ctx->rewriter, node->payload.global_variable.type); Node* new_global = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations), t, node->payload.global_variable.name, dst_as); diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 4011644f1..f2e03ad80 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -20,7 +20,7 @@ typedef struct { const CompilerConfig* config; } Context; -static AddressSpace generic_ptr_tags[4] = { AsGlobalPhysical, AsSharedPhysical, AsSubgroupPhysical, AsPrivatePhysical }; +static AddressSpace generic_ptr_tags[4] = { AsGlobal, AsShared, AsSubgroup, AsPrivate }; static size_t generic_ptr_tag_bitwidth = 2; @@ -36,7 +36,7 @@ static uint64_t get_tag_for_addr_space(AddressSpace as) { if (generic_ptr_tags[i] == as) return (uint64_t) i; } - error("this address space can't be converted to generic"); + error("address space '%s' can't be converted to generic", get_address_space_name(as)); } static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t tag, const Node* nptr, const Type* element_type) { @@ -62,11 +62,8 @@ static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t } static bool allowed(Context* ctx, AddressSpace as) { - if (as == AsGlobalPhysical && ctx->config->hacks.assume_no_physical_global_ptrs) - return false; - if (as == AsSharedPhysical && !ctx->rewriter.dst_arena->config.allow_shared_memory) - return false; - if (as == AsSubgroupPhysical && !ctx->rewriter.dst_arena->config.allow_subgroup_memory) + // if an address space is logical-only, or isn't allowed at all in the module, we can skip emitting a case for it. + if (!ctx->rewriter.dst_arena->config.address_spaces[as].physical || !ctx->rewriter.dst_arena->config.address_spaces[as].allowed) return false; return true; } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 6f5516e44..c5ded3ba0 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -39,19 +39,19 @@ static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, Body // TODO: make this configuration-dependant static bool is_as_emulated(SHADY_UNUSED Context* ctx, AddressSpace as) { switch (as) { - case AsPrivatePhysical: return true; // TODO have a config option to do this with swizzled global memory - case AsSubgroupPhysical: return true; - case AsSharedPhysical: return true; - case AsGlobalPhysical: return false; // TODO have a config option to do this with SSBOs + case AsPrivate: return true; // TODO have a config option to do this with swizzled global memory + case AsSubgroup: return true; + case AsShared: return true; + case AsGlobal: return false; // TODO have a config option to do this with SSBOs default: return false; } } static const Node** get_emulated_as_word_array(Context* ctx, AddressSpace as) { switch (as) { - case AsPrivatePhysical: return &ctx->fake_private_memory; - case AsSubgroupPhysical: return &ctx->fake_subgroup_memory; - case AsSharedPhysical: return &ctx->fake_shared_memory; + case AsPrivate: return &ctx->fake_private_memory; + case AsSubgroup: return &ctx->fake_subgroup_memory; + case AsShared: return &ctx->fake_shared_memory; default: error("Emulation of this AS is not supported"); } } @@ -67,7 +67,8 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type return gen_primop_ce(bb, neq_op, 2, (const Node*[]) {value, int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size })}); } case PtrType_TAG: switch (element_type->payload.ptr_type.address_space) { - case AsGlobalPhysical: { + case AsGlobal: { + // TODO: add a per-as size configuration const Type* ptr_int_t = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false }); const Node* unsigned_int = gen_deserialisation(ctx, bb, ptr_int_t, arr, base_offset); return gen_reinterpret_cast(bb, element_type, unsigned_int); @@ -158,7 +159,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element return; } case PtrType_TAG: switch (element_type->payload.ptr_type.address_space) { - case AsGlobalPhysical: { + case AsGlobal: { const Type* ptr_int_t = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false }); const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, singleton(ptr_int_t), singleton(value)); return gen_serialisation(ctx, bb, ptr_int_t, arr, base_offset, unsigned_value); @@ -343,7 +344,7 @@ static const Node* process_node(Context* ctx, const Node* old) { case GlobalVariable_TAG: { const GlobalVariable* old_gvar = &old->payload.global_variable; // Global variables into emulated address spaces become integer constants (to index into arrays used for emulation of said address space) - if (is_as_emulated(ctx, old_gvar->address_space)) { + if (!lookup_annotation(old, "Logical") && is_as_emulated(ctx, old_gvar->address_space)) { assert(false); } break; @@ -381,6 +382,7 @@ static Nodes collect_globals(Context* ctx, AddressSpace as) { const Node* decl = old_decls.nodes[i]; if (decl->tag != GlobalVariable_TAG) continue; if (decl->payload.global_variable.address_space != as) continue; + if (lookup_annotation(decl, "Logical")) continue; collected[members_count] = decl; members_count++; } @@ -445,7 +447,7 @@ static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, Body } } -static void construct_emulated_memory_array(Context* ctx, AddressSpace as, AddressSpace logical_as) { +static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { IrArena* a = ctx->rewriter.dst_arena; Module* m = ctx->rewriter.dst_module; String as_name = get_address_space_name(as); @@ -459,7 +461,7 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as, Addre .element_type = word_type, .size = NULL }); - *get_emulated_as_word_array(ctx, as) = undef(a, (Undef) { .type = ptr_type(a, (PtrType) { .address_space = logical_as, .pointed_type = words_array_type }) }); + *get_emulated_as_word_array(ctx, as) = undef(a, (Undef) { .type = ptr_type(a, (PtrType) { .address_space = as, .pointed_type = words_array_type }) }); return; } @@ -472,7 +474,7 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as, Addre const Node* size_of = gen_primop_e(bb, size_of_op, singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), empty(a)); const Node* size_in_words = bytes_to_words(bb, size_of); - Node* constant_decl = constant(m, annotations, ptr_size_type, format_string_interned(a, "globals_physical_%s_size", as_name)); + Node* constant_decl = constant(m, annotations, ptr_size_type, format_string_interned(a, "memory_%s_size", as_name)); constant_decl->payload.constant.instruction = yield_values_and_wrap_in_block(bb, singleton(size_in_words)); const Type* words_array_type = arr_type(a, (ArrType) { @@ -480,13 +482,17 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as, Addre .size = ref_decl_helper(a, constant_decl) }); - Node* words_array = global_var(m, annotations, words_array_type, format_string_arena(a->arena, "addressable_word_memory_%s", as_name), logical_as); + Node* words_array = global_var(m, append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical"})), words_array_type, format_string_arena(a->arena, "memory_%s", as_name), as); *get_emulated_as_word_array(ctx, as) = ref_decl_helper(a, words_array); } Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + aconfig.address_spaces[AsPrivate].physical = false; + aconfig.address_spaces[AsShared].physical = false; + aconfig.address_spaces[AsSubgroup].physical = false; + IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); @@ -495,11 +501,11 @@ Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { .config = config, }; - construct_emulated_memory_array(&ctx, AsPrivatePhysical, AsPrivateLogical); - if (dst->arena->config.allow_subgroup_memory) - construct_emulated_memory_array(&ctx, AsSubgroupPhysical, AsSubgroupLogical); - if (dst->arena->config.allow_shared_memory) - construct_emulated_memory_array(&ctx, AsSharedPhysical, AsSharedLogical); + construct_emulated_memory_array(&ctx, AsPrivate); + if (dst->arena->config.address_spaces[AsSubgroup].allowed) + construct_emulated_memory_array(&ctx, AsSubgroup); + if (dst->arena->config.address_spaces[AsShared].allowed) + construct_emulated_memory_array(&ctx, AsShared); for (size_t i = 0; i < NumAddressSpaces; i++) { if (is_as_emulated(&ctx, i)) { diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 13cec9a93..52e0dd0f5 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -191,10 +191,10 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { Nodes annotations = mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" })); // Arrays for the stacks - Node* stack_decl = global_var(dst, annotations, stack_arr_type, "stack", AsPrivatePhysical); + Node* stack_decl = global_var(dst, annotations, stack_arr_type, "stack", AsPrivate); // Pointers into those arrays - Node* stack_ptr_decl = global_var(dst, annotations, stack_counter_t, "stack_ptr", AsPrivateLogical); + Node* stack_ptr_decl = global_var(dst, append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical" })), stack_counter_t, "stack_ptr", AsPrivate); stack_ptr_decl->payload.global_variable.init = uint32_literal(a, 0); Context ctx = { diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 4c357aa3e..f47c52bbe 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -23,14 +23,14 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const switch (node->tag) { case PtrType_TAG: { AddressSpace as = node->payload.ptr_type.address_space; - if (as == AsSubgroupLogical) { - return ptr_type(a, (PtrType) { .pointed_type = rewrite_op(&ctx->rewriter, NcType, "pointed_type", node->payload.ptr_type.pointed_type), .address_space = AsSharedLogical }); + if (as == AsSubgroup) { + return ptr_type(a, (PtrType) { .pointed_type = rewrite_op(&ctx->rewriter, NcType, "pointed_type", node->payload.ptr_type.pointed_type), .address_space = AsShared, .is_reference = node->payload.ptr_type.is_reference }); } break; } case RefDecl_TAG: { const Node* odecl = node->payload.ref_decl.decl; - if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsSubgroupLogical) + if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsSubgroup) break; assert(ctx->b); const Node* ndecl = rewrite_op(&ctx->rewriter, NcDeclaration, "decl", odecl); @@ -40,14 +40,15 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const } case GlobalVariable_TAG: { AddressSpace as = node->payload.global_variable.address_space; - if (as == AsSubgroupLogical) { + if (as == AsSubgroup) { const Type* ntype = rewrite_op(&ctx->rewriter, NcType, "type", node->payload.global_variable.type); const Type* atype = arr_type(a, (ArrType) { .element_type = ntype, .size = ref_decl_helper(a, rewrite_op(&ctx->rewriter, NcDeclaration, "decl", get_declaration(ctx->rewriter.src_module, "SUBGROUPS_PER_WG"))) }); - Node* new = global_var(ctx->rewriter.dst_module, rewrite_ops(&ctx->rewriter, NcAnnotation, "annotations", node->payload.global_variable.annotations), atype, node->payload.global_variable.name, AsSharedLogical); + assert(lookup_annotation(node, "Logical") && "All subgroup variables should be logical by now!"); + Node* new = global_var(ctx->rewriter.dst_module, rewrite_ops(&ctx->rewriter, NcAnnotation, "annotations", node->payload.global_variable.annotations), atype, node->payload.global_variable.name, AsShared); register_processed(&ctx->rewriter, node, new); if (node->payload.global_variable.init) { diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index a3e57f13f..e70f12693 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -33,7 +33,7 @@ static const Node* process(Context* ctx, const Node* node) { case BuiltinWorkgroupId: case BuiltinGlobalInvocationId: case BuiltinLocalInvocationId: - return global_var(m, filtered_as, rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsPrivateLogical); + return global_var(m, filtered_as, rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsPrivate); case BuiltinNumWorkgroups: return global_var(m, filtered_as, rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsExternal); default: diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c index bad9e7197..ddb3052d4 100644 --- a/src/shady/passes/simt2d.c +++ b/src/shady/passes/simt2d.c @@ -52,7 +52,7 @@ static const Node* process(Context* ctx, const Node* node) { }), (String[]) {"allocated"})); } //return yield_values_and_wrap_in_control(bb, singleton(widen(ctx, allocated))); - const Node* result_type = maybe_packed_type_helper(ptr_type(a, (PtrType) { .address_space = AsFunctionLogical, .pointed_type = type }), ctx->width); + const Node* result_type = maybe_packed_type_helper(ptr_type(a, (PtrType) { .address_space = AsFunction, .pointed_type = type }), ctx->width); const Node* packed = composite_helper(a, result_type, nodes(a, ctx->width, allocated)); return yield_values_and_wrap_in_block(bb, singleton(packed)); } diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 416e9ef2e..0cb8b73d1 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -31,8 +31,8 @@ static void specialize_arena_config(const CompilerConfig* config, Module* m, Are switch (config->specialization.execution_model) { case EmVertex: case EmFragment: { - target->allow_subgroup_memory = false; - target->allow_shared_memory = false; + target->address_spaces[AsShared].allowed = false; + target->address_spaces[AsSubgroup].allowed = false; } default: break; } diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index 23c237fe0..9f9d79dec 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -28,7 +28,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case RefDecl_TAG: { const Node* odecl = node->payload.ref_decl.decl; - if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobalPhysical) + if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) break; assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), int32_literal(a, 0), singleton(rewrite_node(&ctx->rewriter, odecl))); @@ -36,7 +36,7 @@ static const Node* process(Context* ctx, const Node* node) { return ptr; } case GlobalVariable_TAG: - if (node->payload.global_variable.address_space != AsGlobalPhysical) + if (node->payload.global_variable.address_space != AsGlobal) break; assert(false); default: break; @@ -77,7 +77,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul size_t lifted_globals_count = 0; for (size_t i = 0; i < old_decls.count; i++) { const Node* odecl = old_decls.nodes[i]; - if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobalPhysical) + if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) continue; member_tys[lifted_globals_count] = rewrite_node(&ctx.rewriter, odecl->type); @@ -101,7 +101,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul lifted_globals_count = 0; for (size_t i = 0; i < old_decls.count; i++) { const Node* odecl = old_decls.nodes[i]; - if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobalPhysical) + if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) continue; if (odecl->payload.global_variable.init) annotations = append_nodes(a, annotations, annotation_values(a, (AnnotationValues) { diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 6e5341fab..44b20ade4 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -62,12 +62,12 @@ TypeMemLayout get_mem_layout(IrArena* a, const Type* type) { switch (type->tag) { case FnType_TAG: error("Functions have an opaque memory representation"); case PtrType_TAG: switch (type->payload.ptr_type.address_space) { - case AsPrivatePhysical: - case AsSubgroupPhysical: - case AsSharedPhysical: - case AsGlobalPhysical: - case AsGeneric: return get_mem_layout(a, int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false })); - default: error_print("as: %d", type->payload.ptr_type.address_space); error("unhandled address space") + case AsPrivate: + case AsSubgroup: + case AsShared: + case AsGlobal: + case AsGeneric: return get_mem_layout(a, int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false })); // TODO: use per-as layout + default: error("Pointers in address space '%s' does not have a defined memory layout", get_address_space_name(type->payload.ptr_type.address_space)); } case Int_TAG: return (TypeMemLayout) { .type = type, diff --git a/src/shady/type.c b/src/shady/type.c index db7de4c95..57ffcad46 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -163,7 +163,7 @@ size_t get_type_bitwidth(const Type* t) { case Int_TAG: return int_size_in_bytes(t->payload.int_type.width) * 8; case Float_TAG: return float_size_in_bytes(t->payload.float_type.width) * 8; case PtrType_TAG: { - if (is_physical_as(t->payload.ptr_type.address_space)) + if (t->arena->config.address_spaces[t->payload.ptr_type.address_space].physical) return int_size_in_bytes(t->arena->config.memory.ptr_size) * 8; break; } @@ -176,9 +176,8 @@ bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { switch (as) { case AsInput: case AsOutput: - case AsFunctionLogical: - case AsPrivateLogical: - case AsPrivatePhysical: + case AsFunction: + case AsPrivate: return !arena->config.is_simt; default: return true; @@ -397,15 +396,11 @@ const Type* check_type_pack_type(IrArena* arena, PackType pack_type) { } const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { - assert((arena->config.untyped_ptrs || ptr_type.pointed_type) && "Shady does not support untyped pointers, but can infer them, see infer.c"); - if (!arena->config.allow_subgroup_memory) { - assert(ptr_type.address_space != AsSubgroupPhysical); - assert(ptr_type.address_space != AsSubgroupLogical); - } - if (!arena->config.allow_shared_memory) { - assert(ptr_type.address_space != AsSharedPhysical); - assert(ptr_type.address_space != AsSharedLogical); + if (!arena->config.address_spaces[ptr_type.address_space].allowed) { + error_print("Address space %s is not allowed in this arena\n", get_address_space_name(ptr_type.address_space)); + error_die(); } + assert(ptr_type.pointed_type && "Shady does not support untyped pointers, but can infer them, see infer.c"); if (ptr_type.pointed_type) { if (ptr_type.pointed_type->tag == ArrType_TAG) { assert(is_data_type(ptr_type.pointed_type->payload.arr_type.element_type)); @@ -755,8 +750,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(is_subtype(val_expected_type, val->type)); return empty_multiple_return_type(arena); } - case alloca_logical_op: as = AsFunctionLogical; goto alloca_case; - case alloca_op: as = AsPrivatePhysical; goto alloca_case; + case alloca_logical_op: as = AsFunction; goto alloca_case; + case alloca_op: as = AsPrivate; goto alloca_case; alloca_case: { assert(prim_op.type_arguments.count == 1); assert(prim_op.operands.count == 0); diff --git a/test/memory1.slim b/test/memory1.slim index 5c9f187c8..b6f27ce4c 100644 --- a/test/memory1.slim +++ b/test/memory1.slim @@ -1,6 +1,6 @@ @DescriptorSet(0) @DescriptorBinding(0) -global i32 extern_int; +var global i32 extern_int; @Exported fn read_from_extern i32() { diff --git a/test/subgroup_var.slim b/test/subgroup_var.slim index 72dd2e308..e4a24eeba 100644 --- a/test/subgroup_var.slim +++ b/test/subgroup_var.slim @@ -1,4 +1,4 @@ -subgroup i32 x; +var subgroup i32 x; @Exported fn foo uniform i32() { From 18fd19e59ce1e1ff4920aa5ab49e6eccc931eef0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Apr 2024 15:57:24 +0200 Subject: [PATCH 180/693] mem2reg: lift "load" logic out --- src/shady/passes/opt_mem2reg.c | 62 +++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index fe173370b..223aa2dc3 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -189,6 +189,38 @@ static void wipe_all_leaked_pointers(KnowledgeBase* kb) { } } +static const Node* find_or_request_known_ptr_value(Context* ctx, KnowledgeBase* kb, const Node* optr) { + IrArena* a = ctx->rewriter.dst_arena; + PtrKnowledge* ok = get_last_valid_ptr_knowledge(kb, optr); + const Node* known_value = get_known_value(kb, ok); + if (known_value) { + const Type* known_value_t = known_value->type; + bool kv_u = deconstruct_qualified_type(&known_value_t); + + const Type* load_result_t = rewrite_node(&ctx->rewriter, optr->type); + bool lrt_u = deconstruct_qualified_type(&load_result_t); + deconstruct_pointer_type(&load_result_t); + // assert(!lrt_u || kv_u); + if (is_reinterpret_cast_legal(load_result_t, known_value_t)) { + const Node* n = prim_op_helper(a, reinterpret_op, singleton(load_result_t), singleton(known_value)); + if (lrt_u && !kv_u) + n = prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(known_value)); + return n; + } + } else { + const KnowledgeBase* phi_kb = kb; + while (phi_kb->dominator_kb) { + phi_kb = phi_kb->dominator_kb; + } + debug_print("mem2reg: It'd sure be nice to know the value of "); + log_node(DEBUG, optr); + debug_print(" at phi-like node %s.\n", get_abstraction_name(phi_kb->cfnode->node)); + // log_node(DEBUG, phi_location->node); + insert_set_get_key(const Node*, phi_kb->potential_additional_params, optr); + } + return NULL; +} + static PtrKnowledge* find_or_create_ptr_knowledge_for_updating(Context* ctx, KnowledgeBase* kb, const Node* optr, bool create) { Rewriter* r = &ctx->rewriter; PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, optr); @@ -311,33 +343,9 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No } case load_op: { const Node* optr = first(payload.operands); - PtrKnowledge* ok = get_last_valid_ptr_knowledge(kb, optr); - const Node* known_value = get_known_value(kb, ok); - if (known_value) { - const Type* known_value_t = known_value->type; - bool kv_u = deconstruct_qualified_type(&known_value_t); - - const Type* load_result_t = rewrite_node(&ctx->rewriter, optr->type); - bool lrt_u = deconstruct_qualified_type(&load_result_t); - deconstruct_pointer_type(&load_result_t); - // assert(!lrt_u || kv_u); - if (is_reinterpret_cast_legal(load_result_t, known_value_t)) { - const Node* n = prim_op_helper(a, reinterpret_op, singleton(load_result_t), singleton(known_value)); - if (lrt_u && !kv_u) - n = prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(known_value)); - return n; - } - } else { - const KnowledgeBase* phi_kb = kb; - while (phi_kb->dominator_kb) { - phi_kb = phi_kb->dominator_kb; - } - debug_print("mem2reg: It'd sure be nice to know the value of "); - log_node(DEBUG, first(payload.operands)); - debug_print(" at phi-like node %s.\n", get_abstraction_name(phi_kb->cfnode->node)); - // log_node(DEBUG, phi_location->node); - insert_set_get_key(const Node*, phi_kb->potential_additional_params, optr); - } + const Node* known_value = find_or_request_known_ptr_value(ctx, kb, optr); + if (known_value) + return known_value; // const Node* other_ptr = get_known_address(&ctx->rewriter, ok); // if (other_ptr && optr != other_ptr) { // return prim_op_helper(a, load_op, empty(a), singleton(other_ptr)); From 28f1b1ce868065accdd163523e21cc317f6ecb44 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Apr 2024 16:09:08 +0200 Subject: [PATCH 181/693] lower_lea: temporary hack --- src/shady/passes/lower_lea.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index b1b6f01a9..c19eb4d92 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -16,6 +16,17 @@ typedef struct { const CompilerConfig* config; } Context; +// TODO: make this configuration-dependant +static bool is_as_emulated(SHADY_UNUSED Context* ctx, AddressSpace as) { + switch (as) { + case AsPrivate: return true; // TODO have a config option to do this with swizzled global memory + case AsSubgroup: return true; + case AsShared: return true; + case AsGlobal: return true; // TODO have a config option to do this with SSBOs + default: return false; + } +} + static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* pointer_type, const Node* base, const Node* offset, size_t n_indices, const Node** indices) { IrArena* a = ctx->rewriter.dst_arena; const Type* emulated_ptr_t = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); @@ -110,7 +121,7 @@ static const Node* process(Context* ctx, const Node* old) { bool must_lower = false; // we have to lower generic pointers if we emulate them using ints must_lower |= ctx->config->lower.emulate_generic_ptrs && old_base_ptr_t->payload.ptr_type.address_space == AsGeneric; - must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference; + must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference && is_as_emulated(ctx, old_base_ptr_t->payload.ptr_type.address_space); if (!must_lower) break; BodyBuilder* bb = begin_body(a); From 767ad9807ac28878bdb224ba2fe2a0de265bdc2a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 14 Apr 2024 12:23:03 +0200 Subject: [PATCH 182/693] aobench: added more tunable parameters --- samples/aobench/ao.c | 8 ++++---- samples/aobench/ao.comp.cpp | 26 ++++++++++---------------- samples/aobench/ao.cu | 10 +++++++--- samples/aobench/ao.h | 7 ++----- samples/aobench/ao_host.c | 1 + samples/aobench/ao_main.c | 28 ++++++++++++++++++++-------- 6 files changed, 44 insertions(+), 36 deletions(-) diff --git a/samples/aobench/ao.c b/samples/aobench/ao.c index 94883dad3..5d6afa7cf 100644 --- a/samples/aobench/ao.c +++ b/samples/aobench/ao.c @@ -203,13 +203,13 @@ FUNCTION static unsigned char aobench_clamp(Scalar f) return (unsigned char) s; } -FUNCTION EXTERNAL_FN Ctx get_init_context() { +EXTERNAL_FN Ctx get_init_context() { return (Ctx) { .rng = 0xFEEFDEED, }; } -FUNCTION EXTERNAL_FN void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamples, unsigned char* img) { +EXTERNAL_FN void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamples, TEXEL_T* img) { Scalar pixel[3] = { 0, 0, 0 }; ctx->rng = x * w + y; @@ -269,7 +269,7 @@ FUNCTION EXTERNAL_FN void render_pixel(Ctx* ctx, int x, int y, int w, int h, int img[3 * (y * w + x) + 2] = aobench_clamp(pixel[2]); } -FUNCTION EXTERNAL_FN void init_scene(Ctx* ctx) +EXTERNAL_FN void init_scene(Ctx* ctx) { ctx->spheres[0].center.x = -2.0f; ctx->spheres[0].center.y = 0.0f; @@ -294,4 +294,4 @@ FUNCTION EXTERNAL_FN void init_scene(Ctx* ctx) ctx->plane.n.y = 1.0f; ctx->plane.n.z = 0.0f; -} \ No newline at end of file +} diff --git a/samples/aobench/ao.comp.cpp b/samples/aobench/ao.comp.cpp index 7774e457a..40bfc7fd6 100644 --- a/samples/aobench/ao.comp.cpp +++ b/samples/aobench/ao.comp.cpp @@ -32,27 +32,21 @@ float cosf(float) __asm__("shady::prim_op::cos"); float fmodf(float, float) __asm__("shady::prim_op::mod"); float fabsf(float) __asm__("shady::prim_op::abs"); float floorf(float) __asm__("shady::prim_op::floor"); + +#define EXTERNAL_FN static +#define FUNCTION static + #include "ao.c" -extern "C" __attribute__((annotate("shady::workgroup_size::16::16::1"))) -compute_shader void aobench_kernel(global unsigned char* out) { - //outColor = (vec4) { fragColor[0], fragColor[1], fragColor[2], 1.0f }; - //outColor = (vec4) { fragCoord[0] / 1024, fragCoord[1] / 1024, 1.0f, 1.0f }; +#define xstr(s) str(s) +#define str(s) #s +extern "C" __attribute__((annotate("shady::workgroup_size::" xstr(BLOCK_SIZE) "::" xstr(BLOCK_SIZE) "::1"))) +compute_shader void aobench_kernel(global TEXEL_T* out) { Ctx ctx = get_init_context(); init_scene(&ctx); int x = global_id.x; int y = global_id.y; - //int x = (int) fragCoord.x % 1024; - //int y = (int) fragCoord.y % 1024; - - // unsigned int out[3]; // = { 55, 0, 0}; - out[0] = 255; - out[1] = 255; - render_pixel(&ctx, x + 3, y, WIDTH, HEIGHT, NSUBSAMPLES, (unsigned char*) out); - //out[2] = 155; - // out[0] = x / 4; - // out[1] = y / 4; - //outColor = (vec4) { ((int) out[0]) / 255.0f, ((int) out[1]) / 255.0f, ((int) out[2]) / 255.0f, 1.0f }; -} \ No newline at end of file + render_pixel(&ctx, x, y, WIDTH, HEIGHT, NSUBSAMPLES, (TEXEL_T*) out); +} diff --git a/samples/aobench/ao.cu b/samples/aobench/ao.cu index e51799134..4262a3331 100644 --- a/samples/aobench/ao.cu +++ b/samples/aobench/ao.cu @@ -1,16 +1,20 @@ -#define FUNCTION __device__ +#define EXTERNAL_FN static inline __device__ __attribute__((always_inline)) +#define FUNCTION static inline __device__ __attribute__((always_inline)) + #include "ao.c" extern "C" { -__global__ void aobench_kernel(unsigned char* out) { +__global__ void aobench_kernel(unsigned TEXEL_T* out) { int x = threadIdx.x + blockDim.x * blockIdx.x; int y = threadIdx.y + blockDim.y * blockIdx.y; - long int ptr = (long int) out; Ctx ctx = get_init_context(); init_scene(&ctx); render_pixel(&ctx, x, y, WIDTH, HEIGHT, NSUBSAMPLES, out); + // out[3 * (y * 2048 + x) + 0] = 255; + // out[3 * (y * 2048 + x) + 1] = 255; + // out[3 * (y * 2048 + x) + 2] = 255; } } \ No newline at end of file diff --git a/samples/aobench/ao.h b/samples/aobench/ao.h index f68446109..d0b359810 100644 --- a/samples/aobench/ao.h +++ b/samples/aobench/ao.h @@ -3,6 +3,7 @@ #define NSUBSAMPLES 1 #define NAO_SAMPLES 8 #define BLOCK_SIZE 16 +#define TEXEL_T unsigned char typedef float Scalar; @@ -64,10 +65,6 @@ typedef struct { unsigned int rng; } Ctx; -#ifndef EXTERNAL_FN -#define EXTERNAL_FN static -#endif - EXTERNAL_FN Ctx get_init_context(); EXTERNAL_FN void init_scene(Ctx*); -EXTERNAL_FN void render_pixel(Ctx*, int x, int y, int w, int h, int nsubsamples, unsigned char* img); +EXTERNAL_FN void render_pixel(Ctx*, int x, int y, int w, int h, int nsubsamples, TEXEL_T* img); diff --git a/samples/aobench/ao_host.c b/samples/aobench/ao_host.c index a39213c56..5dad91dc6 100644 --- a/samples/aobench/ao_host.c +++ b/samples/aobench/ao_host.c @@ -1,3 +1,4 @@ #define private #define EXTERNAL_FN /* not static */ +#define FUNCTION static #include "ao.c" \ No newline at end of file diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 0091af0e0..2719a6700 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -1,4 +1,5 @@ #define EXTERNAL_FN /* not static */ + #include "ao.h" #include "../runtime/runtime_app_common.h" @@ -24,7 +25,7 @@ static uint64_t timespec_to_nano(struct timespec t) { return t.tv_sec * 1000000000 + t.tv_nsec; } -void saveppm(const char *fname, int w, int h, unsigned char *img) { +void saveppm(const char *fname, int w, int h, TEXEL_T* img) { FILE *fp; fp = fopen(fname, "wb"); @@ -33,11 +34,15 @@ void saveppm(const char *fname, int w, int h, unsigned char *img) { fprintf(fp, "P6\n"); fprintf(fp, "%d %d\n", w, h); fprintf(fp, "255\n"); - fwrite(img, w * h * 3, 1, fp); + // fwrite(img, w * h * 3, 1, fp); + for (size_t i = 0; i < w * h * 3; i++) { + unsigned char c = img[i]; + fwrite(&c, 1, 1, fp); + } fclose(fp); } -void render_host(unsigned char *img, int w, int h, int nsubsamples) { +void render_host(TEXEL_T* img, int w, int h, int nsubsamples) { int x, y; Scalar* fimg = (Scalar *)malloc(sizeof(Scalar) * w * h * 3); memset((void *)fimg, 0, sizeof(Scalar) * w * h * 3); @@ -68,7 +73,7 @@ typedef struct { extern Vec3u builtin_NumWorkgroups; -void render_ispc(unsigned char *img, int w, int h, int nsubsamples) { +void render_ispc(TEXEL_T* img, int w, int h, int nsubsamples) { struct timespec ts; timespec_get(&ts, TIME_UTC); uint64_t tsn = timespec_to_nano(ts); @@ -94,7 +99,7 @@ void render_ispc(unsigned char *img, int w, int h, int nsubsamples) { } #endif -void render_device(Args* args, unsigned char *img, int w, int h, int nsubsamples, String path) { +void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, String path, bool import_memory) { for (size_t i = 0; i < WIDTH; i++) { for (size_t j = 0; j < HEIGHT; j++) { img[j * WIDTH * 3 + i * 3 + 0] = 255; @@ -112,7 +117,12 @@ void render_device(Args* args, unsigned char *img, int w, int h, int nsubsamples img[0] = 69; info_print("malloc'd address is: %zu\n", (size_t) img); - Buffer* buf = import_buffer_host(device, img, sizeof(uint8_t) * WIDTH * HEIGHT * 3); + Buffer* buf; + if (import_memory) + buf = import_buffer_host(device, img, sizeof(*img) * WIDTH * HEIGHT * 3); + else + buf = allocate_buffer_device(device, sizeof(*img) * WIDTH * HEIGHT * 3); + uint64_t buf_addr = get_buffer_device_pointer(buf); info_print("Device-side address is: %zu\n", buf_addr); @@ -132,6 +142,8 @@ void render_device(Args* args, unsigned char *img, int w, int h, int nsubsamples debug_print("data %d\n", (int) img[0]); + if (!import_memory) + copy_from_buffer(buf, 0, img, sizeof(*img) * WIDTH * HEIGHT * 3); destroy_buffer(buf); shutdown_runtime(runtime); @@ -170,7 +182,7 @@ int main(int argc, char **argv) { } } - unsigned char *img = (unsigned char *)malloc(WIDTH * HEIGHT * 3); + void *img = malloc(WIDTH * HEIGHT * 3 * sizeof(TEXEL_T)); if (do_host || do_all) { render_host(img, WIDTH, HEIGHT, NSUBSAMPLES); @@ -185,7 +197,7 @@ int main(int argc, char **argv) { #endif if (do_device || do_all) { - render_device(&args, img, WIDTH, HEIGHT, NSUBSAMPLES, "./ao.comp.c.ll"); + render_device(&args, img, WIDTH, HEIGHT, NSUBSAMPLES, "./ao.comp.c.ll", false); saveppm("device.ppm", WIDTH, HEIGHT, img); } From 73210e132355025b574bf86fd840456d9aa51f62 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 14 Apr 2024 12:34:50 +0200 Subject: [PATCH 183/693] fix ao.cu --- samples/aobench/ao.c | 22 ++++++++++---------- samples/aobench/ao.cu | 9 +++++--- src/shady/emit/spirv/emit_spv_instructions.c | 5 ++++- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/samples/aobench/ao.c b/samples/aobench/ao.c index 5d6afa7cf..5d4a36860 100644 --- a/samples/aobench/ao.c +++ b/samples/aobench/ao.c @@ -6,7 +6,7 @@ #define FUNCTION #endif -FUNCTION static unsigned int FNVHash(char* str, unsigned int length) { +FUNCTION unsigned int FNVHash(char* str, unsigned int length) { const unsigned int fnv_prime = 0x811C9DC5; unsigned int hash = 0; unsigned int i = 0; @@ -20,31 +20,31 @@ FUNCTION static unsigned int FNVHash(char* str, unsigned int length) { return hash; } -FUNCTION static unsigned int nrand(unsigned int* rng) { +FUNCTION unsigned int nrand(unsigned int* rng) { unsigned int orand = *rng; *rng = FNVHash((char*) &orand, 4); return *rng; } -FUNCTION static Scalar drand48(Ctx* ctx) { +FUNCTION Scalar drand48(Ctx* ctx) { Scalar n = (nrand(&ctx->rng) / 65536.0f); n = n - floorf(n); return n; } -FUNCTION static Scalar vdot(vec v0, vec v1) +FUNCTION Scalar vdot(vec v0, vec v1) { return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z; } -FUNCTION static void vcross(vec *c, vec v0, vec v1) +FUNCTION void vcross(vec *c, vec v0, vec v1) { c->x = v0.y * v1.z - v0.z * v1.y; c->y = v0.z * v1.x - v0.x * v1.z; c->z = v0.x * v1.y - v0.y * v1.x; } -FUNCTION static void vnormalize(vec *c) +FUNCTION void vnormalize(vec *c) { Scalar length = sqrtf(vdot((*c), (*c))); @@ -55,7 +55,7 @@ FUNCTION static void vnormalize(vec *c) } } -FUNCTION static void +FUNCTION void ray_sphere_intersect(Isect *isect, const Ray *ray, const Sphere *sphere) { vec rs = { 0 }; @@ -88,7 +88,7 @@ ray_sphere_intersect(Isect *isect, const Ray *ray, const Sphere *sphere) } } -FUNCTION static void +FUNCTION void ray_plane_intersect(Isect *isect, const Ray *ray, const Plane *plane) { Scalar d = -vdot(plane->p, plane->n); @@ -110,7 +110,7 @@ ray_plane_intersect(Isect *isect, const Ray *ray, const Plane *plane) } } -FUNCTION static void +FUNCTION void orthoBasis(vec *basis, vec n) { basis[2] = n; @@ -133,7 +133,7 @@ orthoBasis(vec *basis, vec n) vnormalize(&basis[1]); } -FUNCTION static void ambient_occlusion(Ctx* ctx, vec *col, const Isect *isect) +FUNCTION void ambient_occlusion(Ctx* ctx, vec *col, const Isect *isect) { int i, j; int ntheta = NAO_SAMPLES; @@ -193,7 +193,7 @@ FUNCTION static void ambient_occlusion(Ctx* ctx, vec *col, const Isect *isect) col->z = occlusion; } -FUNCTION static unsigned char aobench_clamp(Scalar f) +FUNCTION unsigned char aobench_clamp(Scalar f) { Scalar s = (f * 255.5f); diff --git a/samples/aobench/ao.cu b/samples/aobench/ao.cu index 4262a3331..8a3168459 100644 --- a/samples/aobench/ao.cu +++ b/samples/aobench/ao.cu @@ -1,11 +1,14 @@ -#define EXTERNAL_FN static inline __device__ __attribute__((always_inline)) -#define FUNCTION static inline __device__ __attribute__((always_inline)) +// #define EXTERNAL_FN static inline __device__ __attribute__((always_inline)) +// #define FUNCTION static inline __device__ __attribute__((always_inline)) + +#define EXTERNAL_FN static __device__ +#define FUNCTION static __device__ #include "ao.c" extern "C" { -__global__ void aobench_kernel(unsigned TEXEL_T* out) { +__global__ void aobench_kernel(TEXEL_T* out) { int x = threadIdx.x + blockDim.x * blockIdx.x; int y = threadIdx.y + blockDim.y * blockIdx.y; diff --git a/src/shady/emit/spirv/emit_spv_instructions.c b/src/shady/emit/spirv/emit_spv_instructions.c index f3a7dd33f..0b45857dd 100644 --- a/src/shady/emit/spirv/emit_spv_instructions.c +++ b/src/shady/emit/spirv/emit_spv_instructions.c @@ -385,7 +385,10 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui assert(results_count == 1); results[0] = result; } else { - error("TODO: OpPtrAccessChain") + const Type* target_type = instr->type; + SpvId result = spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, emit_value(emitter, bb_builder, args.nodes[1]), args.count - 2, indices); + assert(results_count == 1); + results[0] = result; } return; } From 280cad71ab70f54f782b9662893b8cb92d055f22 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 14 Apr 2024 14:39:15 +0200 Subject: [PATCH 184/693] emit_c: fix float literal being emitted as doubles --- src/shady/emit/c/emit_c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index c1b2f822b..20bda1171 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -237,7 +237,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { float f; memcpy(&f, &v, sizeof(uint32_t)); double d = (double) f; - emitted = format_string_arena(emitter->arena->arena, "%.9g", d); break; + emitted = format_string_arena(emitter->arena->arena, "%#.9gf", d); break; } case FloatTy64: { double d; From 4d5a07621ff4eb2f204ad413a93d4e30c16b6ac0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 14 Apr 2024 14:59:55 +0200 Subject: [PATCH 185/693] fix runtime_test --- src/runtime/runtime_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index bd97c0be6..5c63b1413 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -69,7 +69,7 @@ int main(int argc, char* argv[]) { int32_t a0 = 42; uint64_t a1 = get_buffer_device_pointer(buffer); - wait_completion(launch_kernel(program, device, "my_kernel", 1, 1, 1, 2, (void*[]) { &a0, &a1 })); + wait_completion(launch_kernel(program, device, args.driver_config.config.specialization.entry_point ? args.driver_config.config.specialization.entry_point : "my_kernel", 1, 1, 1, 2, (void*[]) { &a0, &a1 })); destroy_buffer(buffer); From 81e4b19ab166c3f883fadf8023de14349a6df7f4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 14 Apr 2024 15:00:01 +0200 Subject: [PATCH 186/693] cuda_runtime: use fast math --- src/runtime/cuda/cuda_runtime_program.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 241f7d941..4a8bc0ae1 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -34,7 +34,8 @@ static bool emit_cuda_c_code(CudaKernel* spec) { static bool cuda_c_to_ptx(CudaKernel* kernel) { nvrtcProgram program; CHECK_NVRTC(nvrtcCreateProgram(&program, kernel->cuda_code, kernel->key.entry_point, 0, NULL, NULL), return false); - nvrtcResult compile_result = nvrtcCompileProgram(program, 0, false); + const char* args[] = { "--use_fast_math" }; + nvrtcResult compile_result = nvrtcCompileProgram(program, sizeof(args) / sizeof(*args), args); if (compile_result != NVRTC_SUCCESS) { error_print("NVRTC compilation failed: %s\n", nvrtcGetErrorString(compile_result)); debug_print("Dumping source:\n%s", kernel->cuda_code); From 19b16ff9a06b1e32547f576346d712fa26f2a860 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 15 Apr 2024 09:58:05 +0200 Subject: [PATCH 187/693] rejig cmake build files --- CMakeLists.txt | 11 ++--------- src/common/CMakeLists.txt | 11 ++++++++++- src/driver/CMakeLists.txt | 4 ++-- src/runtime/CMakeLists.txt | 2 ++ src/shady/CMakeLists.txt | 6 ++++-- src/shady/api/CMakeLists.txt | 1 + 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b0e42bc4..d3f0d77a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +option(BUILD_SHARED_LIBS "Build using shared libraries" ON) + if (MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() @@ -99,20 +101,11 @@ endif() include(CMakePackageConfigHelpers) -install(TARGETS api EXPORT shady_export_set) -install(TARGETS shady EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) - if (TARGET vcc) add_subdirectory(vcc-std) endif () -if (TARGET runtime) - install(TARGETS runtime EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) -endif() - -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/shady DESTINATION include) install(EXPORT shady_export_set DESTINATION share/cmake/shady/ NAMESPACE shady:: FILE shady-targets.cmake) configure_file(cmake/shady-config.cmake.in shady-config.cmake @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/shady-config.cmake" DESTINATION share/cmake/shady) -#install(FILES "${CMAKE_CURRENT_BINARY_DIR}/shady-config.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/shady) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e941ac2df..bb2735e87 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,8 +1,16 @@ add_library(common STATIC list.c dict.c log.c portability.c util.c growy.c arena.c printer.c) -target_include_directories(common INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(common PRIVATE "$") set_property(TARGET common PROPERTY POSITION_INDEPENDENT_CODE ON) +# We need to export 'common' because otherwise when using static libraries we will not be able to resolve those symbols +install(TARGETS common EXPORT shady_export_set) + +# But we don't want projects outside this to be able to see these APIs and call into them +# (Also we couldn't since the header files live with the source anyways) +add_library(common_api INTERFACE) +target_include_directories(common_api INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(common INTERFACE "$") + add_executable(embedder embed.c) function(embed_file TYPE NAME SRC) @@ -14,3 +22,4 @@ function(embed_file TYPE NAME SRC) add_dependencies(${NAME} "${NAME}_h") target_include_directories(${NAME} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) endfunction() + diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index e58a9ee01..3c0847cbc 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(driver driver.c cli.c) -target_link_libraries(driver PUBLIC "$") -target_link_libraries(driver PUBLIC "$") +target_link_libraries(driver PUBLIC "api") +target_link_libraries(driver PUBLIC "shady") set_target_properties(driver PROPERTIES OUTPUT_NAME "shady_driver") install(TARGETS driver EXPORT shady_export_set) diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index e1f271fc3..90cd98029 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -7,3 +7,5 @@ add_subdirectory(cuda) add_executable(runtime_test runtime_test.c) target_link_libraries(runtime_test runtime) + +install(TARGETS runtime EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index fb4ef271b..627726f52 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -111,6 +111,8 @@ add_subdirectory(internal) add_subdirectory(emit) target_link_libraries(shady PRIVATE "api") -target_link_libraries(shady INTERFACE "$") -target_link_libraries(shady PRIVATE "$") +target_link_libraries(shady INTERFACE "common") target_link_libraries(shady PRIVATE "$") + +install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/shady DESTINATION include) +install(TARGETS shady EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) diff --git a/src/shady/api/CMakeLists.txt b/src/shady/api/CMakeLists.txt index d993d4dcf..e4f407a01 100644 --- a/src/shady/api/CMakeLists.txt +++ b/src/shady/api/CMakeLists.txt @@ -11,3 +11,4 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grammar_generated.h DESTINATION includ add_generated_file(FILE_NAME primops_generated.h TARGET_NAME generate-primops-headers SOURCES generator_primops.c) add_dependencies(api INTERFACE generate-primops-headers) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/primops_generated.h DESTINATION include) +install(TARGETS api EXPORT shady_export_set) From 25ba91ab8578b952b5f9db14f3521353fb752cc1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 15 Apr 2024 11:34:48 +0200 Subject: [PATCH 188/693] fix textures on LLVM14 --- src/frontends/llvm/l2s_type.c | 28 +++++++++++++++------------- src/frontends/llvm/l2s_value.c | 1 + src/shady/internal/scheduler.slim | 2 +- test/vcc/textured.frag.c | 2 +- vcc-std/include/shady.h | 4 +--- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/frontends/llvm/l2s_type.c b/src/frontends/llvm/l2s_type.c index 30b1df86e..2224d01d6 100644 --- a/src/frontends/llvm/l2s_type.c +++ b/src/frontends/llvm/l2s_type.c @@ -49,18 +49,6 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { Node* decl = NULL; const Node* result = NULL; if (name) { - if (strcmp(name, "struct.__shady_builtin_sampler2D") == 0) - return sampled_image_type(a, (SampledImageType) { .image_type = image_type(a, (ImageType) { - //.sampled_type = pack_type(a, (PackType) { .element_type = float_type(a, (Float) { .width = FloatTy32 }), .width = 4 }), - .sampled_type = float_type(a, (Float) { .width = FloatTy32 }), - .dim = 1, - .depth = 0, - .arrayed = 0, - .ms = 0, - .sampled = 1, - .imageformat = 0 - } ) }); - decl = nominal_type(p->dst, empty(a), name); result = type_decl_ref_helper(a, decl); insert_dict(LLVMTypeRef, const Type*, p->map, t, result); @@ -89,7 +77,21 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { return arr_type(a, (ArrType) { .element_type = elem_t, .size = uint32_literal(a, length)}); } case LLVMPointerTypeKind: { - AddressSpace as = convert_llvm_address_space(LLVMGetPointerAddressSpace(t)); + unsigned int llvm_as = LLVMGetPointerAddressSpace(t); + switch (llvm_as) { + case 0x1000: return sampled_image_type(a, (SampledImageType) { .image_type = image_type(a, (ImageType) { + //.sampled_type = pack_type(a, (PackType) { .element_type = float_type(a, (Float) { .width = FloatTy32 }), .width = 4 }), + .sampled_type = float_type(a, (Float) { .width = FloatTy32 }), + .dim = 1, + .depth = 0, + .arrayed = 0, + .ms = 0, + .sampled = 1, + .imageformat = 0 + } ) }); + default: break; + } + AddressSpace as = convert_llvm_address_space(llvm_as); const Type* pointee = NULL; #if !UNTYPED_POINTERS LLVMTypeRef element_type = LLVMGetElementType(t); diff --git a/src/frontends/llvm/l2s_value.c b/src/frontends/llvm/l2s_value.c index 659a6b6ef..924b52cb6 100644 --- a/src/frontends/llvm/l2s_value.c +++ b/src/frontends/llvm/l2s_value.c @@ -130,6 +130,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { return get_default_zero_value(a, convert_type(p, LLVMTypeOf(v))); case LLVMConstantArrayValueKind: { assert(t->tag == ArrType_TAG); + assert(LLVMIsConstant(v)); if (LLVMIsConstantString(v)) { size_t idc; r = string_lit_helper(a, LLVMGetAsString(v, &idc)); diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index 0528f90de..f3255d125 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -19,7 +19,7 @@ @Internal var logical subgroup TreeNode active_branch; @Internal @Builtin("SubgroupLocalInvocationId") -var logical input u32 subgroup_local_id; +var input u32 subgroup_local_id; @Internal @Leaf fn builtin_init_scheduler() { diff --git a/test/vcc/textured.frag.c b/test/vcc/textured.frag.c index e575f957a..a4b043009 100644 --- a/test/vcc/textured.frag.c +++ b/test/vcc/textured.frag.c @@ -1,7 +1,7 @@ #include #include -descriptor_set(0) descriptor_binding(1) uniform sampler2D texSampler; +descriptor_set(0) descriptor_binding(1) uniform_constant sampler2D texSampler; location(0) input vec3 fragColor; location(1) input vec2 fragTexCoord; diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index 6416b3ecd..885ec40fe 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -21,18 +21,16 @@ namespace vcc { #define input __attribute__((address_space(389))) #define output __attribute__((address_space(390))) // maybe deprecate it ? -#define uniform __attribute__((annotate("shady::uniform"))) #define uniform_constant __attribute__((address_space(398))) #define uniform_block __attribute__((address_space(395))) #define push_constant __attribute__((address_space(392))) #define global __attribute__((address_space(1))) #define shared __attribute__((address_space(3))) #define private __attribute__((address_space(5))) -#define private_logical __attribute__((address_space(385))) #include "shady_vec.h" -typedef struct __shady_builtin_sampler2D {} sampler2D; +typedef __attribute__((address_space(0x1000))) struct __shady_builtin_sampler2D* sampler2D; vec4 texture2D(const sampler2D, native_vec2) __asm__("shady::prim_op::sample_texture"); From 90127fa32391923c8c444ea1596d7f9a4510251f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 15 Apr 2024 15:08:15 +0200 Subject: [PATCH 189/693] move pre-normalized IR passes in the frontends --- include/shady/driver.h | 4 +- include/shady/ir.h | 1 + include/shady/runtime.h | 2 - samples/aobench/ao_main.c | 4 +- samples/checkerboard/checkerboard.c | 5 +- src/common/log.h | 2 +- src/driver/driver.c | 19 ++++---- src/driver/vcc.c | 4 +- src/frontends/llvm/l2s.c | 18 +++++-- src/frontends/llvm/l2s.h | 2 +- src/frontends/slim/parser.c | 30 +++++++++++- src/frontends/slim/parser.h | 2 +- src/frontends/spirv/s2s.c | 9 ++-- src/frontends/spirv/s2s.h | 2 +- src/runtime/runtime_program.c | 14 +++--- src/runtime/runtime_test.c | 7 +-- src/shady/compile.c | 30 ++++++------ src/shady/passes/import.c | 61 ++++++++++++++++++++++++ src/shady/print.c | 2 +- src/shady/transform/internal_constants.c | 2 +- src/shady/transform/internal_constants.h | 6 +-- 21 files changed, 167 insertions(+), 59 deletions(-) diff --git a/include/shady/driver.h b/include/shady/driver.h index 0e5f440f1..b89e96462 100644 --- a/include/shady/driver.h +++ b/include/shady/driver.h @@ -26,8 +26,8 @@ typedef enum { } SourceLanguage; SourceLanguage guess_source_language(const char* filename); -ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t, const char* file_contents, Module* mod); -ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, Module* mod); +ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t, const char* file_contents, String, Module** mod); +ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, String, Module** mod); typedef enum { TgtAuto, diff --git a/include/shady/ir.h b/include/shady/ir.h index c573c51e1..112500ffb 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -326,6 +326,7 @@ typedef enum CompilationResult_ { } CompilationResult; CompilationResult run_compiler_passes(CompilerConfig* config, Module** mod); +void link_module(Module* dst, Module* src); //////////////////////////////// Emission //////////////////////////////// diff --git a/include/shady/runtime.h b/include/shady/runtime.h index 4064f5712..21736d1f3 100644 --- a/include/shady/runtime.h +++ b/include/shady/runtime.h @@ -29,8 +29,6 @@ typedef struct CompilerConfig_ CompilerConfig; typedef struct Module_ Module; Program* new_program_from_module(Runtime*, const CompilerConfig*, Module*); -Program* load_program(Runtime*, const CompilerConfig*, const char* program_src); -Program* load_program_from_disk(Runtime*, const CompilerConfig*, const char* path); Command* launch_kernel(Program*, Device*, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args); bool wait_completion(Command*); diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 2719a6700..3398e835b 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -127,7 +127,9 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri info_print("Device-side address is: %zu\n", buf_addr); - Program* program = load_program_from_disk(runtime, &args->compiler_config, path); + Module* m; + CHECK(driver_load_source_file_from_filename(&args->compiler_config, path, "aobench", &m) == NoError, return); + Program* program = new_program_from_module(runtime, &args->compiler_config, m); // run it twice to compile everything and benefit from caches wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr })); diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 4d120e1f4..af1d7be64 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -68,8 +68,9 @@ int main(int argc, char **argv) info_print("Device-side address is: %zu\n", buf_addr); IrArena* a = new_ir_arena(default_arena_config()); - Module* m = new_module(a, "checkerboard"); - driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, m); + Module* m; + if (driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, "checkerboard", &m) != NoError) + error("Failed to load checkerboard module"); Program* program = new_program_from_module(runtime, &compiler_config, m); wait_completion(launch_kernel(program, device, "main", 16, 16, 1, 1, (void*[]) { &buf_addr })); diff --git a/src/common/log.h b/src/common/log.h index 037f3223d..d37832c49 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -20,7 +20,7 @@ void set_log_level(LogLevel); void log_string(LogLevel level, const char* format, ...); void log_node(LogLevel level, const Node* node); typedef struct CompilerConfig_ CompilerConfig; -void log_module(LogLevel level, CompilerConfig*, Module*); +void log_module(LogLevel level, const CompilerConfig*, Module*); #define debugvv_print(...) log_string(DEBUGVV, __VA_ARGS__) #define debugv_print(...) log_string(DEBUGV, __VA_ARGS__) diff --git a/src/driver/driver.c b/src/driver/driver.c index e55e4192e..09f1cbb20 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -37,11 +37,12 @@ SourceLanguage guess_source_language(const char* filename) { return SrcSlim; } -ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t len, const char* file_contents, Module* mod) { +ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t len, const char* file_contents, String name, Module** mod) { switch (lang) { case SrcLLVM: { #ifdef LLVM_PARSER_PRESENT - parse_llvm_into_shady(config, mod, len, file_contents); + bool ok = parse_llvm_into_shady(config, len, file_contents, name, mod); + assert(ok); #else assert(false && "LLVM front-end missing in this version"); #endif @@ -49,7 +50,7 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang } case SrcSPIRV: { #ifdef SPV_PARSER_PRESENT - parse_spirv_into_shady(mod, len, file_contents); + parse_spirv_into_shady(len, file_contents, name, mod); #else assert(false && "SPIR-V front-end missing in this version"); #endif @@ -58,16 +59,16 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang case SrcShadyIR: case SrcSlim: { ParserConfig pconfig = { - .front_end = lang == SrcSlim, + .front_end = lang == SrcSlim, }; debugv_print("Parsing: \n%s\n", file_contents); - parse_shady_ir(pconfig, (const char*) file_contents, mod); + *mod = parse_slim_module(config, pconfig, (const char*) file_contents, name); } } return NoError; } -ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, Module* mod) { +ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, String name, Module** mod) { ShadyErrorCodes err; SourceLanguage lang = guess_source_language(filename); size_t len; @@ -84,7 +85,7 @@ ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* conf err = InputFileDoesNotExist; goto exit; } - err = driver_load_source_file(config, lang, len, contents, mod); + err = driver_load_source_file(config, lang, len, contents, name, mod); exit: free((void*) contents); return err; @@ -98,9 +99,11 @@ ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { size_t num_source_files = entries_count_list(args->input_filenames); for (size_t i = 0; i < num_source_files; i++) { - int err = driver_load_source_file_from_filename(&args->config, read_list(const char*, args->input_filenames)[i], mod); + Module* m; + int err = driver_load_source_file_from_filename(&args->config, read_list(const char*, args->input_filenames)[i], read_list(const char*, args->input_filenames)[i], &m); if (err) return err; + link_module(mod, m); } return NoError; diff --git a/src/driver/vcc.c b/src/driver/vcc.c index 2f7e0223f..b4404bbb7 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -70,7 +70,6 @@ int main(int argc, char** argv) { ArenaConfig aconfig = default_arena_config(); IrArena* arena = new_ir_arena(aconfig); - Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one int clang_retval = system("clang --version"); if (clang_retval != 0) @@ -140,12 +139,13 @@ int main(int argc, char** argv) { if (clang_returned) exit(ClangInvocationFailed); + Module* mod; if (!vcc_options.only_run_clang) { size_t len; char* llvm_ir; if (!read_file(vcc_options.tmp_filename, &len, &llvm_ir)) exit(InputFileIOError); - driver_load_source_file(&args.config, SrcLLVM, len, llvm_ir, mod); + driver_load_source_file(&args.config, SrcLLVM, len, llvm_ir, "my_module", &mod); // TODO name module after first filename, or perhaps the last one free(llvm_ir); if (vcc_options.delete_tmp_file) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index f6b602a45..0bf021723 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -230,7 +230,7 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { return r; } -bool parse_llvm_into_shady(const CompilerConfig* config, Module* dst, size_t len, const char* data) { +bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { LLVMContextRef context = LLVMContextCreate(); LLVMModuleRef src; LLVMMemoryBufferRef mem = LLVMCreateMemoryBufferWithMemoryRange(data, len, "my_great_buffer", false); @@ -245,7 +245,12 @@ bool parse_llvm_into_shady(const CompilerConfig* config, Module* dst, size_t len get_module_arena(dst)->config.untyped_ptrs = true; // tolerate untyped ptrs... #endif - Module* dirty = new_module(get_module_arena(dst), "dirty"); + ArenaConfig aconfig = default_arena_config(); + aconfig.check_types = false; + aconfig.allow_fold = false; + + IrArena* arena = new_ir_arena(aconfig); + Module* dirty = new_module(arena, "dirty"); Parser p = { .ctx = context, .config = config, @@ -274,7 +279,14 @@ bool parse_llvm_into_shady(const CompilerConfig* config, Module* dst, size_t len global = LLVMGetNextGlobal(global); } - postprocess(&p, dirty, dst); + aconfig.check_types = true; + aconfig.allow_fold = true; + IrArena* arena2 = new_ir_arena(aconfig); + *dst = new_module(arena2, name); + postprocess(&p, dirty, *dst); + log_module(DEBUG, config, *dst); + verify_module(config, *dst); + destroy_ir_arena(arena); destroy_dict(p.map); destroy_dict(p.annotations); diff --git a/src/frontends/llvm/l2s.h b/src/frontends/llvm/l2s.h index 62f9c464a..bdce5d35a 100644 --- a/src/frontends/llvm/l2s.h +++ b/src/frontends/llvm/l2s.h @@ -4,6 +4,6 @@ #include "shady/ir.h" #include -bool parse_llvm_into_shady(const CompilerConfig*, Module* dst, size_t len, const char* data); +bool parse_llvm_into_shady(const CompilerConfig*, size_t len, const char* data, String name, Module** dst); #endif diff --git a/src/frontends/slim/parser.c b/src/frontends/slim/parser.c index a267ad270..698b2b12c 100644 --- a/src/frontends/slim/parser.c +++ b/src/frontends/slim/parser.c @@ -1074,7 +1074,7 @@ static const Node* accept_nominal_type_decl(ctxparams, Nodes annotations) { return nom; } -void parse_shady_ir(ParserConfig config, const char* contents, Module* mod) { +static void parse_shady_ir(ParserConfig config, const char* contents, Module* mod) { IrArena* arena = get_module_arena(mod); Tokenizer* tokenizer = new_tokenizer(contents); @@ -1103,3 +1103,31 @@ void parse_shady_ir(ParserConfig config, const char* contents, Module* mod) { destroy_tokenizer(tokenizer); } + +#include "compile.h" +#include "transform/internal_constants.h" + +Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name) { + ArenaConfig aconfig = default_arena_config(); + aconfig.name_bound = false; + aconfig.check_op_classes = false; + aconfig.check_types = false; + aconfig.validate_builtin_types = false; + aconfig.allow_fold = false; + IrArena* initial_arena = new_ir_arena(aconfig); + Module* m = new_module(initial_arena, name); + parse_shady_ir(pconfig, contents, m); + Module** pmod = &m; + Module* old_mod = NULL; + + generate_dummy_constants(config, *pmod); + + RUN_PASS(bind_program) + RUN_PASS(normalize) + + RUN_PASS(normalize_builtins) + RUN_PASS(infer_program) + + destroy_ir_arena(initial_arena); + return *pmod; +} \ No newline at end of file diff --git a/src/frontends/slim/parser.h b/src/frontends/slim/parser.h index ac2f21150..c56785f1c 100644 --- a/src/frontends/slim/parser.h +++ b/src/frontends/slim/parser.h @@ -36,6 +36,6 @@ INFIX_OPERATORS() InfixOperatorsCount } InfixOperators; -void parse_shady_ir(ParserConfig config, const char* contents, Module* mod); +Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name); #endif diff --git a/src/frontends/spirv/s2s.c b/src/frontends/spirv/s2s.c index 8ad151424..8751be7b6 100644 --- a/src/frontends/spirv/s2s.c +++ b/src/frontends/spirv/s2s.c @@ -1356,13 +1356,16 @@ bool compare_spvid(SpvId* pa, SpvId* pb) { return *pa == *pb; } -S2SError parse_spirv_into_shady(Module* dst, size_t len, const char* data) { +S2SError parse_spirv_into_shady(size_t len, const char* data, String name, Module** dst) { + IrArena* a = new_ir_arena(default_arena_config()); + *dst = new_module(a, name); + SpvParser parser = { .cursor = 0, .len = len / sizeof(uint32_t), .words = (uint32_t*) data, - .mod = dst, - .arena = get_module_arena(dst), + .mod = *dst, + .arena = get_module_arena(*dst), .decorations_arena = new_arena(), .phi_arguments = new_dict(SpvId, SpvPhiArgs*, (HashFn) hash_spvid, (CmpFn) compare_spvid), diff --git a/src/frontends/spirv/s2s.h b/src/frontends/spirv/s2s.h index 5f86e26f7..9bef30671 100644 --- a/src/frontends/spirv/s2s.h +++ b/src/frontends/spirv/s2s.h @@ -8,6 +8,6 @@ typedef enum { S2S_FailedParsingGeneric, } S2SError; -S2SError parse_spirv_into_shady(Module* dst, size_t len, const char* data); +S2SError parse_spirv_into_shady(size_t len, const char* data, String name, Module**); #endif diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index a508bfb9a..25740fef8 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -25,30 +25,28 @@ Program* new_program_from_module(Runtime* runtime, const CompilerConfig* base_co } Program* load_program(Runtime* runtime, const CompilerConfig* base_config, const char* program_src) { - IrArena* arena = new_ir_arena(default_arena_config()); - Module* module = new_module(arena, "my_module"); + Module* module; - int err = driver_load_source_file(base_config, SrcShadyIR, strlen(program_src), program_src, module); + int err = driver_load_source_file(base_config, SrcShadyIR, strlen(program_src), program_src, "my_module", &module); if (err != NoError) { return NULL; } Program* program = new_program_from_module(runtime, base_config, module); - program->arena = arena; + program->arena = get_module_arena(module); return program; } Program* load_program_from_disk(Runtime* runtime, const CompilerConfig* base_config, const char* path) { - IrArena* arena = new_ir_arena(default_arena_config()); - Module* module = new_module(arena, "my_module"); + Module* module; - int err = driver_load_source_file_from_filename(base_config, path, module); + int err = driver_load_source_file_from_filename(base_config, path, "my_module", &module); if (err != NoError) { return NULL; } Program* program = new_program_from_module(runtime, base_config, module); - program->arena = arena; + program->arena = get_module_arena(module); return program; } diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 5c63b1413..82c3747ce 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -50,12 +50,13 @@ int main(int argc, char* argv[]) { Program* program; IrArena* arena = NULL; + arena = new_ir_arena(default_arena_config()); if (entries_count_list(args.driver_config.input_filenames) == 0) { - program = load_program(runtime, &args.driver_config.config, default_shader); + Module* module; + driver_load_source_file(&args.driver_config.config, SrcSlim, strlen(default_shader), default_shader, "runtime_test", &module); + program = new_program_from_module(runtime, &args.driver_config.config, module); } else { - arena = new_ir_arena(default_arena_config()); Module* module = new_module(arena, "my_module"); - int err = driver_load_source_files(&args.driver_config, module); if (err) return err; diff --git a/src/shady/compile.c b/src/shady/compile.c index 10684b025..fc0e4f980 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -51,7 +51,11 @@ CompilerConfig default_compiler_config() { ArenaConfig default_arena_config() { ArenaConfig config = { .is_simt = true, - .validate_builtin_types = false, + .name_bound = true, + .allow_fold = true, + .check_types = true, + .validate_builtin_types = true, + .check_op_classes = true, .memory = { .word_size = IntTy8, @@ -72,27 +76,23 @@ ArenaConfig default_arena_config() { return config; } +void add_scheduler_source(const CompilerConfig* config, Module* dst) { + ParserConfig pconfig = { + .front_end = true, + }; + Module* builtin_scheduler_mod = parse_slim_module(config, pconfig, shady_scheduler_src, "builtin_scheduler"); + debug_print("Adding builtin scheduler code"); + link_module(dst, builtin_scheduler_mod); +} + CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { if (config->dynamic_scheduling) { - debugv_print("Parsing builtin scheduler code"); - ParserConfig pconfig = { - .front_end = true, - }; - parse_shady_ir(pconfig, shady_scheduler_src, *pmod); + add_scheduler_source(config, *pmod); } IrArena* initial_arena = (*pmod)->arena; Module* old_mod = NULL; - generate_dummy_constants(config, *pmod); - - if (!get_module_arena(*pmod)->config.name_bound) - RUN_PASS(bind_program) - RUN_PASS(normalize) - - RUN_PASS(normalize_builtins) - RUN_PASS(infer_program) - RUN_PASS(reconvergence_heuristics) RUN_PASS(lower_cf_instrs) diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 6bb7c770e..5cf11ff70 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -1,6 +1,8 @@ #include "passes.h" #include "portability.h" +#include "log.h" +#include "../ir_private.h" #include "../rewrite.h" @@ -8,6 +10,57 @@ typedef struct { Rewriter rewriter; } Context; +static void replace_or_compare(const Node** dst, const Node* with) { + if (!*dst) + *dst = with; + else { + assert(*dst == with && "conflicting definitions"); + } +} + +const Node* import_node(Rewriter* r, const Node* node) { + if (is_declaration(node)) { + Node* existing = get_declaration(r->dst_module, get_declaration_name(node)); + if (existing) { + const Node* imported_t = rewrite_node(r, node->type); + if (imported_t != existing->type) { + error_print("Incompatible types for to-be-merged declaration: %s ", get_declaration_name(node)); + log_node(ERROR, existing->type); + error_print(" vs "); + log_node(ERROR, imported_t); + error_print(".\n"); + error_die(); + } + if (node->tag != existing->tag) { + error_print("Incompatible node types for to-be-merged declaration: %s ", get_declaration_name(node)); + error_print("%s", node_tags[existing->tag]); + error_print(" vs "); + error_print("%s", node_tags[node->tag]); + error_print(".\n"); + error_die(); + } + switch (is_declaration(node)) { + case NotADeclaration: assert(false); + case Declaration_Function_TAG: + replace_or_compare(&existing->payload.fun.body, rewrite_node(r, node->payload.fun.body)); + break; + case Declaration_Constant_TAG: + replace_or_compare(&existing->payload.constant.instruction, rewrite_node(r, node->payload.constant.instruction)); + break; + case Declaration_GlobalVariable_TAG: + replace_or_compare(&existing->payload.global_variable.init, rewrite_node(r, node->payload.global_variable.init)); + break; + case Declaration_NominalType_TAG: + replace_or_compare(&existing->payload.nom_type.body, rewrite_node(r, node->payload.nom_type.body)); + break; + } + return existing; + } + } + + return recreate_node_identity(r, node); +} + Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); IrArena* a = new_ir_arena(aconfig); @@ -20,3 +73,11 @@ Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { destroy_rewriter(&ctx.rewriter); return dst; } + +void link_module(Module* dst, Module* src) { + Context ctx = { + .rewriter = create_rewriter(src, dst, (RewriteNodeFn) import_node), + }; + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); +} diff --git a/src/shady/print.c b/src/shady/print.c index 5a5959b76..724bc2cfc 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1024,7 +1024,7 @@ void log_node(LogLevel level, const Node* node) { } } -void log_module(LogLevel level, CompilerConfig* compiler_cfg, Module* mod) { +void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) { PrintConfig config = { .color = true }; if (compiler_cfg) { config.print_generated = compiler_cfg->logging.print_generated; diff --git a/src/shady/transform/internal_constants.c b/src/shady/transform/internal_constants.c index 18eb15e95..78f61c164 100644 --- a/src/shady/transform/internal_constants.c +++ b/src/shady/transform/internal_constants.c @@ -5,7 +5,7 @@ #include -void generate_dummy_constants(SHADY_UNUSED CompilerConfig* config, Module* mod) { +void generate_dummy_constants(SHADY_UNUSED const CompilerConfig* config, Module* mod) { IrArena* arena = get_module_arena(mod); #define X(constant_name, T, placeholder) \ Node* constant_name##_var = constant(mod, singleton(annotation(arena, (Annotation) { .name = "RetainAfterSpecialization" })), T, #constant_name); \ diff --git a/src/shady/transform/internal_constants.h b/src/shady/transform/internal_constants.h index 05a7d8875..eec5b6784 100644 --- a/src/shady/transform/internal_constants.h +++ b/src/shady/transform/internal_constants.h @@ -4,9 +4,9 @@ #include "shady/ir.h" #define INTERNAL_CONSTANTS(X) \ -X(SUBGROUP_SIZE, int32_type(arena), uint32_literal(arena, config->specialization.subgroup_size)) \ -X(SUBGROUPS_PER_WG, int32_type(arena), uint32_literal(arena, 1)) \ +X(SUBGROUP_SIZE, uint32_type(arena), uint32_literal(arena, config->specialization.subgroup_size)) \ +X(SUBGROUPS_PER_WG, uint32_type(arena), uint32_literal(arena, 1)) \ -void generate_dummy_constants(CompilerConfig* config, Module*); +void generate_dummy_constants(const CompilerConfig* config, Module*); #endif From 6617053a93be1bfaab49fb3a54d1ca97216d80ac Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 15 Apr 2024 16:14:42 +0200 Subject: [PATCH 190/693] remove support for untyped ptr in the IR: instead do it in l2s --- include/shady/ir.h | 1 - src/frontends/llvm/l2s.c | 22 ++-- src/frontends/llvm/l2s_instr.c | 48 +++++++- src/frontends/llvm/l2s_meta.c | 2 +- src/frontends/llvm/l2s_postprocess.c | 45 +++++-- src/frontends/llvm/l2s_type.c | 5 + src/frontends/llvm/l2s_value.c | 5 +- src/shady/analysis/verify.c | 10 +- src/shady/compile.c | 5 +- src/shady/node.c | 27 ++--- src/shady/passes/eliminate_constants.c | 7 +- src/shady/passes/infer.c | 128 +++----------------- src/shady/passes/lower_lea.c | 6 +- src/shady/passes/reconvergence_heuristics.c | 7 ++ src/shady/passes/specialize_entry_point.c | 23 ++-- src/shady/print.c | 12 +- src/shady/type.c | 4 - src/shady/type_helpers.c | 10 +- 18 files changed, 179 insertions(+), 188 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 112500ffb..d140336fc 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -69,7 +69,6 @@ typedef struct { bool check_op_classes; bool check_types; bool allow_fold; - bool untyped_ptrs; bool validate_builtin_types; // do @Builtins variables need to match their type in builtins.h ? bool is_simt; diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 0bf021723..066154ee1 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -1,13 +1,16 @@ #include "l2s_private.h" -#include "shady/ir_private.h" + +#include "ir_private.h" +#include "type.h" +#include "analysis/verify.h" #include "log.h" #include "dict.h" #include "list.h" #include "util.h" +#include "portability.h" #include "llvm-c/IRReader.h" -#include "portability.h" #include #include @@ -80,7 +83,7 @@ static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { while (instr) { switch (LLVMGetInstructionOpcode(instr)) { case LLVMPHI: { - const Node* nparam = var(a, convert_type(p, LLVMTypeOf(instr)), "phi"); + const Node* nparam = var(a, qualified_type_helper(convert_type(p, LLVMTypeOf(instr)), false), "phi"); insert_dict(LLVMValueRef, const Node*, p->map, instr, nparam); append_list(LLVMValueRef, phis, instr); params = append_nodes(a, params, nparam); @@ -128,7 +131,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { for (LLVMValueRef oparam = LLVMGetFirstParam(fn); oparam; oparam = LLVMGetNextParam(oparam)) { LLVMTypeRef ot = LLVMTypeOf(oparam); const Type* t = convert_type(p, ot); - const Node* param = var(a, t, LLVMGetValueName(oparam)); + const Node* param = var(a, qualified_type_helper(t, false), LLVMGetValueName(oparam)); insert_dict(LLVMValueRef, const Node*, p->map, oparam, param); params = append_nodes(a, params, param); if (oparam == LLVMGetLastParam(fn)) @@ -217,6 +220,13 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { decl = global_var(p->dst, empty(a), type, name, as); if (value && as != AsUniformConstant) decl->payload.global_variable.init = convert_value(p, value); + + if (UNTYPED_POINTERS) { + Node* untyped_wrapper = constant(p->dst, empty(a), ptr_t, format_string_interned(a, "%s_untyped", name)); + untyped_wrapper->payload.constant.instruction = quote_helper(a, singleton(ref_decl_helper(a, decl))); + untyped_wrapper->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(ptr_t), singleton(ref_decl_helper(a, decl))); + decl = untyped_wrapper; + } } else { const Type* type = convert_type(p, LLVMTypeOf(global)); decl = constant(p->dst, empty(a), type, name); @@ -241,9 +251,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* error_die(); } info_print("LLVM IR parsed successfully\n"); -#if UNTYPED_POINTERS - get_module_arena(dst)->config.untyped_ptrs = true; // tolerate untyped ptrs... -#endif ArenaConfig aconfig = default_arena_config(); aconfig.check_types = false; @@ -278,6 +285,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* break; global = LLVMGetNextGlobal(global); } + log_module(DEBUG, config, dirty); aconfig.check_types = true; aconfig.allow_fold = true; diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index d8215e92e..f2bb1a39d 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -76,6 +76,15 @@ static const Node* convert_jump(Parser* p, Node* fn, Node* fn_or_bb, LLVMBasicBl return jump_helper(a, dst_bb, nodes(a, params_count, params)); } +static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* element_type) { + IrArena* a = untyped_ptr_t->arena; + assert(element_type); + assert(untyped_ptr_t->tag == PtrType_TAG); + assert(!untyped_ptr_t->payload.ptr_type.is_reference); + const Type* typed_ptr_t = ptr_type(a, (PtrType) { .pointed_type = element_type, .address_space = untyped_ptr_t->payload.ptr_type.address_space }); + return typed_ptr_t; +} + /// instr may be an instruction or a constantexpr EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { Node* fn = fn_or_bb; @@ -223,7 +232,7 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM r = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, alloca_op, singleton(allocated_t), empty(a)), singleton(allocated_ptr_t), NULL)); if (UNTYPED_POINTERS) { const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivate }); - r = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), 1, NULL)); + r = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), singleton(untyped_ptr_t), NULL)); } r = prim_op_helper(a, convert_op, singleton(t), singleton(r)); break; @@ -232,19 +241,49 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM Nodes ops = convert_operands(p, num_ops, instr); assert(ops.count == 1); const Node* ptr = first(ops); - r = prim_op_helper(a, load_op, singleton(t), singleton(ptr)); + if (UNTYPED_POINTERS) { + const Type* element_t = t; + const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); + ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); + } + r = prim_op_helper(a, load_op, empty(a), singleton(ptr)); break; } case LLVMStore: { num_results = 0; Nodes ops = convert_operands(p, num_ops, instr); assert(ops.count == 2); - r = prim_op_helper(a, store_op, UNTYPED_POINTERS ? singleton(convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0)))) : empty(a), mk_nodes(a, ops.nodes[1], ops.nodes[0])); + const Node* ptr = ops.nodes[1]; + if (UNTYPED_POINTERS) { + const Type* element_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 1))); + const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); + ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); + } + r = prim_op_helper(a, store_op, empty(a), mk_nodes(a, ptr, ops.nodes[0])); break; } case LLVMGetElementPtr: { Nodes ops = convert_operands(p, num_ops, instr); - r = prim_op_helper(a, lea_op, UNTYPED_POINTERS ? singleton(convert_type(p, LLVMGetGEPSourceElementType(instr))) : empty(a), ops); + const Node* ptr = first(ops); + if (UNTYPED_POINTERS) { + const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); + const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); + ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); + } + ops = change_node_at_index(a, ops, 0, ptr); + r = prim_op_helper(a, lea_op, empty(a), ops); + if (UNTYPED_POINTERS) { + const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); + const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + bool idk; + //element_t = qualified_type_helper(element_t, false); + enter_composite(&element_t, &idk, nodes(a, ops.count - 2, &ops.nodes[2]), true); + const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); + r = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), BIND_PREV_R(typed_ptr)); + } break; } case LLVMTrunc: @@ -493,6 +532,7 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM LLVMAttributeRef attr = attrs[i]; size_t k = LLVMGetEnumAttributeKind(attr); size_t e = LLVMGetEnumAttributeKindForName("byval", 5); + uint64_t value = LLVMGetEnumAttributeValue(attr); // printf("p = %zu, i = %zu, k = %zu, e = %zu\n", param_index, i, k, e); if (k == e) decoded[param_index].is_byval = true; diff --git a/src/frontends/llvm/l2s_meta.c b/src/frontends/llvm/l2s_meta.c index eb760f744..b095b53b5 100644 --- a/src/frontends/llvm/l2s_meta.c +++ b/src/frontends/llvm/l2s_meta.c @@ -27,7 +27,7 @@ static const Node* convert_named_tuple_metadata(Parser* p, LLVMValueRef v, Strin String name = LLVMGetValueName(v); if (!name || strlen(name) == 0) name = unique_name(a, node_name); - Node* g = global_var(p->dst, singleton(annotation(a, (Annotation) { .name = "SkipOnInfer" })), NULL, name, AsDebugInfo); + Node* g = global_var(p->dst, singleton(annotation(a, (Annotation) { .name = "LLVMMetaData" })), NULL, name, AsDebugInfo); const Node* r = ref_decl_helper(a, g); insert_dict(LLVMValueRef, const Type*, p->map, v, r); diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 5a0242c0a..faef21797 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -79,8 +79,36 @@ static Nodes remake_variables(Context* ctx, Nodes old) { static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; switch (node->tag) { - case Variable_TAG: return var(a, node->payload.var.type ? qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.var.type), false) : NULL, node->payload.var.name); + case Variable_TAG: { + assert(node->payload.var.type); + if (node->payload.var.type->tag == QualifiedType_TAG) + return var(a, node->payload.var.type ? rewrite_node(&ctx->rewriter, node->payload.var.type) : NULL, node->payload.var.name); + return var(a, qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.var.type), false), node->payload.var.name); + } + case Block_TAG: { + Nodes yield_types = rewrite_nodes(r, node->payload.block.yield_types); + const Node* ninside = rewrite_node(r, node->payload.block.inside); + const Node* term = get_abstraction_body(ninside); + while (term->tag == Let_TAG) { + term = get_abstraction_body(get_let_tail(term)); + } + assert(term->tag == Yield_TAG); + yield_types = get_values_types(a, term->payload.yield.args); + return block(a, (Block) { + .yield_types = yield_types, + .inside = ninside, + }); + } + case Constant_TAG: { + Node* new = recreate_node_identity(r, node); + BodyBuilder* bb = begin_body(a); + const Node* value = first(bind_instruction(bb, new->payload.constant.instruction)); + value = first(bind_instruction(bb, prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)))); + new->payload.constant.instruction = yield_values_and_wrap_in_block(bb, singleton(value)); + return new; + } case Function_TAG: { Context fn_ctx = *ctx; fn_ctx.curr_scope = new_scope(node); @@ -183,7 +211,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = get_variables_types(a, get_abstraction_params(dst)) }); - join_token = var(a, jp_type, get_abstraction_name(dst)); + join_token = var(a, qualified_type_helper(jp_type, false), get_abstraction_name(dst)); controls->tokens = append_nodes(a, controls->tokens, join_token); controls->destinations = append_nodes(a, controls->destinations, dst); } @@ -193,6 +221,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, if (fn->tag == BasicBlock_TAG) fn = (Node*) fn->payload.basic_block.fn; assert(fn->tag == Function_TAG); + fn = rewrite_node(r, fn); Node* wrapper = basic_block(a, fn, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name(dst))); wrapper->payload.basic_block.body = join(a, (Join) { .args = nparams, @@ -214,13 +243,15 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, break; } case GlobalVariable_TAG: { + if (lookup_annotation(node, "LLVMMetaData")) + return NULL; AddressSpace as = node->payload.global_variable.address_space; const Node* old_init = node->payload.global_variable.init; - Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations); - const Type* type = rewrite_node(&ctx->rewriter, node->payload.global_variable.type); + Nodes annotations = rewrite_nodes(r, node->payload.global_variable.annotations); + const Type* type = rewrite_node(r, node->payload.global_variable.type); ParsedAnnotation* an = find_annotation(ctx->p, node); while (an) { - annotations = append_nodes(a, annotations, an->payload); + annotations = append_nodes(a, annotations, rewrite_node(r, an->payload)); if (strcmp(get_annotation_name(an->payload), "Builtin") == 0) old_init = NULL; if (strcmp(get_annotation_name(an->payload), "UniformConstant") == 0) @@ -228,9 +259,9 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, an = an->next; } Node* decl = global_var(ctx->rewriter.dst_module, annotations, type, get_declaration_name(node), as); - register_processed(&ctx->rewriter, node, decl); + register_processed(r, node, decl); if (old_init) - decl->payload.global_variable.init = rewrite_node(&ctx->rewriter, old_init); + decl->payload.global_variable.init = rewrite_node(r, old_init); return decl; } default: break; diff --git a/src/frontends/llvm/l2s_type.c b/src/frontends/llvm/l2s_type.c index 2224d01d6..b5dc81b08 100644 --- a/src/frontends/llvm/l2s_type.c +++ b/src/frontends/llvm/l2s_type.c @@ -1,4 +1,5 @@ #include "l2s_private.h" +#include "type.h" #include "portability.h" #include "log.h" @@ -39,6 +40,8 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { const Type* ret_type = convert_type(p, LLVMGetReturnType(t)); if (LLVMGetTypeKind(LLVMGetReturnType(t)) == LLVMVoidTypeKind) ret_type = empty_multiple_return_type(a); + else + ret_type = qualified_type_helper(ret_type, false); return fn_type(a, (FnType) { .param_types = nodes(a, num_params, cparam_types), .return_types = ret_type == empty_multiple_return_type(a) ? empty(a) : singleton(ret_type) @@ -96,6 +99,8 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { #if !UNTYPED_POINTERS LLVMTypeRef element_type = LLVMGetElementType(t); pointee = convert_type(p, element_type); +#else + pointee = unit_type(a); #endif return ptr_type(a, (PtrType) { .address_space = as, diff --git a/src/frontends/llvm/l2s_value.c b/src/frontends/llvm/l2s_value.c index 924b52cb6..2680a2676 100644 --- a/src/frontends/llvm/l2s_value.c +++ b/src/frontends/llvm/l2s_value.c @@ -80,12 +80,13 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { name = unique_name(a, "constant_expr"); Nodes annotations = singleton(annotation(a, (Annotation) { .name = "SkipOnInfer" })); annotations = empty(a); - Node* decl = constant(p->dst, annotations, NULL, name); + assert(t); + Node* decl = constant(p->dst, annotations, t, name); r = ref_decl_helper(a, decl); insert_dict(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = begin_body(a); EmittedInstr emitted = convert_instruction(p, NULL, bb, v); - Nodes types = singleton(convert_type(p, LLVMTypeOf(v))); + Nodes types = singleton(t); decl->payload.constant.instruction = bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, emitted.instruction, &types); return r; } diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 807485708..1f7995bb1 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -79,10 +79,12 @@ static void verify_nominal_node(const Node* fn, const Node* n) { break; } case Constant_TAG: { - const Type* t = n->payload.constant.instruction->type; - bool u = deconstruct_qualified_type(&t); - assert(u); - assert(is_subtype(n->payload.constant.type_hint, t)); + if (n->payload.constant.instruction) { + const Type* t = n->payload.constant.instruction->type; + bool u = deconstruct_qualified_type(&t); + assert(u); + assert(is_subtype(n->payload.constant.type_hint, t)); + } break; } case GlobalVariable_TAG: { diff --git a/src/shady/compile.c b/src/shady/compile.c index fc0e4f980..e44ee8b49 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -30,8 +30,9 @@ CompilerConfig default_compiler_config() { .logging = { // most of the time, we are not interested in seeing generated & internal code in the debug output - .print_internal = true, - .print_generated = true, + //.print_internal = true, + //.print_generated = true, + .print_builtin = true, }, .optimisations = { diff --git a/src/shady/node.c b/src/shady/node.c index a6ff0d9a4..203e16e6b 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -140,7 +140,7 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi case PrimOp_TAG: { switch (node->payload.prim_op.op) { case quote_op: { - node = first(node->payload.prim_op.operands);; + node = first(node->payload.prim_op.operands); continue; } case load_op: { @@ -200,22 +200,19 @@ const char* get_string_literal(IrArena* arena, const Node* node) { if (!node) return NULL; switch (node->tag) { + case Declaration_GlobalVariable_TAG: { + const Node* init = node->payload.global_variable.init; + if (init) { + return get_string_literal(arena, init); + } + break; + } + case Declaration_Constant_TAG: { + return get_string_literal(arena, node->payload.constant.instruction); + } case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; - switch (is_declaration(decl)) { - case Declaration_GlobalVariable_TAG: { - const Node* init = decl->payload.global_variable.init; - if (init) - return get_string_literal(arena, init); - break; - } - case Declaration_Constant_TAG: { - return get_string_literal(arena, decl->payload.constant.instruction); - } - default: - break; - } - return NULL; + return get_string_literal(arena, decl); } case PrimOp_TAG: { switch (node->payload.prim_op.op) { diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index c33ab40a3..2b474a367 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -24,10 +24,13 @@ static const Node* process(Context* ctx, const Node* node) { } switch (node->tag) { - case Constant_TAG: return NULL; + case Constant_TAG: + if (!node->payload.constant.instruction) + break; + return NULL; case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; - if (decl->tag == Constant_TAG) { + if (decl->tag == Constant_TAG && decl->payload.constant.instruction) { const Node* value = get_quoted_value(decl->payload.constant.instruction); if (value) return rewrite_node(&ctx->rewriter, value); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 920ab51dd..53306c5fc 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -78,8 +78,9 @@ static const Node* infer_type(Context* ctx, const Type* type) { } case PtrType_TAG: { const Node* element_type = infer(ctx, type->payload.ptr_type.pointed_type, NULL); - if (!element_type) - element_type = unit_type(a); + assert(element_type); + //if (!element_type) + // element_type = unit_type(a); return ptr_type(a, (PtrType) { .pointed_type = element_type, .address_space = type->payload.ptr_type.address_space }); } default: return recreate_node_identity(&ctx->rewriter, type); @@ -117,15 +118,18 @@ static const Node* infer_decl(Context* ctx, const Node* node) { case Constant_TAG: { const Constant* oconstant = &node->payload.constant; const Type* imported_hint = infer(ctx, oconstant->type_hint, NULL); - const Node* instruction; + const Node* instruction = NULL; if (imported_hint) { assert(is_data_type(imported_hint)); Nodes s = singleton(qualified_type_helper(imported_hint, true)); - instruction = infer_instruction(ctx, oconstant->instruction, &s); - } else { + if (oconstant->instruction) + instruction = infer_instruction(ctx, oconstant->instruction, &s); + } else if (oconstant->instruction) { instruction = infer_instruction(ctx, oconstant->instruction, NULL); } - imported_hint = get_unqualified_type(instruction->type); + if (instruction) + imported_hint = get_unqualified_type(instruction->type); + assert(imported_hint); Node* nconstant = constant(ctx->rewriter.dst_module, infer_nodes(ctx, oconstant->annotations), imported_hint, oconstant->name); register_processed(&ctx->rewriter, node, nconstant); @@ -233,25 +237,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec case True_TAG: return true_lit(a); case False_TAG: return false_lit(a); case StringLiteral_TAG: return string_lit(a, (StringLiteral) { .string = string(a, node->payload.string_lit.string )}); - case RefDecl_TAG: { - if (get_arena_config(ctx->rewriter.src_arena).untyped_ptrs) { - const Node* ref_decl = recreate_node_identity(&ctx->rewriter, node); - assert(ref_decl->tag == RefDecl_TAG); - const Node* decl = ref_decl->payload.ref_decl.decl; - if (decl->tag == GlobalVariable_TAG) { - AddressSpace as = decl->payload.global_variable.address_space; - /*if (is_physical_as(as)) { - const Node* untyped_ptr = ptr_type(a, (PtrType) {.address_space = as, .pointed_type = unit_type(a)}); - Node* cast_constant = constant(ctx->rewriter.dst_module, empty(a), untyped_ptr, format_string_interned(a, "%s_cast", get_declaration_name(decl))); - cast_constant->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr), singleton(ref_decl)); - const Node* cast_ref_decl = ref_decl_helper(a, cast_constant); - register_processed(r, node, cast_ref_decl); - return cast_ref_decl; - }*/ - } - } - break; - } + case RefDecl_TAG: break; case FnAddr_TAG: break; case Value_Undef_TAG: break; case Value_Composite_TAG: { @@ -356,57 +342,6 @@ static const Node* _infer_basic_block(Context* ctx, const Node* node) { return bb; } -static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* element_type) { - assert(element_type); - IrArena* a = untyped_ptr_t->arena; - assert(untyped_ptr_t->tag == PtrType_TAG); - const Type* typed_ptr_t = ptr_type(a, (PtrType) { .pointed_type = element_type, .address_space = untyped_ptr_t->payload.ptr_type.address_space }); - return typed_ptr_t; -} - -static const Node* reinterpret_cast_helper(BodyBuilder* bb, const Node* ptr, const Type* typed_ptr_t) { - IrArena* a = ptr->arena; - ptr = gen_reinterpret_cast(bb, typed_ptr_t, ptr); - return ptr; -} - -// Turns untyped pointers back into typed pointers -// For physical pointers, we can just reinterpret them -// For logical pointers, we need to do some stupid best-effort tricks and pray it works out -// the sort of casts we can allow are casting a pointer to a composite to a pointer to one of it's first elements -// we just attempt to do LEAs until we hit the right type, or some unrecoverable error -static void fix_source_pointer(BodyBuilder* bb, const Node** operand, const Type* element_type) { - IrArena* a = element_type->arena; - const Type* original_operand_t = get_unqualified_type((*operand)->type); - assert(original_operand_t->tag == PtrType_TAG); - if (is_physical_ptr_type(original_operand_t)) { - // typed loads - normalise to typed ptrs instead by generating an extra cast! - const Type *ptr_type = original_operand_t; - ptr_type = type_untyped_ptr(ptr_type, element_type); - *operand = reinterpret_cast_helper(bb, *operand, ptr_type); - } else { - // we can't insert a cast but maybe we can make this work - do { - const Node* ptr_t = get_unqualified_type((*operand)->type); - const Type* pointee = get_pointer_type_element(ptr_t); - if (pointee == element_type) - return; - pointee = get_maybe_nominal_type_body(pointee); - if (pointee->tag == RecordType_TAG) { - *operand = gen_lea(bb, *operand, int32_literal(a, 0), singleton(int32_literal(a, 0))); - continue; - } - if (pointee->tag == ArrType_TAG) { - *operand = gen_lea(bb, *operand, int32_literal(a, 0), singleton(int32_literal(a, 0))); - continue; - } - // TODO: better diagnostics - error_print("Fatal: Trying to type-pun a pointer in logical memory (%s)\n", get_address_space_name(get_pointer_type_address_space(ptr_t))); - error_die(); - } while(true); - } -} - static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* expected_types) { assert(node->tag == PrimOp_TAG); IrArena* a = ctx->rewriter.dst_arena; @@ -438,27 +373,20 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp assert(type_args.count == 1); const Type* element_type = type_args.nodes[0]; assert(is_data_type(element_type)); - //new_inputs_scratch[0] = element_type; goto rebuild; } case load_op: { assert(old_operands.count == 1); assert(type_args.count <= 1); new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); - if (type_args.count == 1) { - fix_source_pointer(bb, &new_operands[0], first(type_args)); - type_args = empty(a); - } + assert(type_args.count == 0); goto rebuild; } case store_op: { assert(old_operands.count == 2); assert(type_args.count <= 1); new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); - if (type_args.count == 1) { - fix_source_pointer(bb, &new_operands[0], first(type_args)); - type_args = empty(a); - } + assert(type_args.count == 0); const Type* ptr_type = get_unqualified_type(new_operands[0]->type); assert(ptr_type->tag == PtrType_TAG); const Type* element_t = ptr_type->payload.ptr_type.pointed_type; @@ -498,33 +426,11 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp const Type* src_ptr = remove_uniformity_qualifier(new_operands[0]->type); const Type* base_datatype = src_ptr; assert(base_datatype->tag == PtrType_TAG); - AddressSpace as = get_pointer_type_address_space(base_datatype); - bool was_untyped = false; - if (type_args.count == 1) { - was_untyped = true; - base_datatype = type_untyped_ptr(base_datatype, first(type_args)); - new_operands[0] = reinterpret_cast_helper(bb, new_operands[0], base_datatype); - type_args = empty(a); - } + assert(type_args.count == 0); Nodes new_ops = nodes(a, old_operands.count, new_operands); const Node* offset = new_operands[1]; - const IntLiteral* offset_lit = resolve_to_int_literal(offset); - if ((!offset_lit || offset_lit->value) != 0 && base_datatype->tag != ArrType_TAG) { - warn_print("LEA used on a pointer to a non-array type!\n"); - const Type* arrayed_src_t = ptr_type(a, (PtrType) { - .address_space = as, - .pointed_type = arr_type(a, (ArrType) { - .element_type = get_pointer_type_element(base_datatype), - .size = NULL - }), - }); - const Node* cast_base = gen_reinterpret_cast(bb, arrayed_src_t, first(new_ops)); - Nodes final_lea_ops = mk_nodes(a, cast_base, offset, int32_literal(a, 0)); - final_lea_ops = concat_nodes(a, final_lea_ops, nodes(a, old_operands.count - 2, new_operands + 2)); - new_ops = final_lea_ops; - } const Node* result = first(bind_instruction(bb, prim_op(a, (PrimOp) { .op = lea_op, @@ -532,11 +438,6 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp .operands = new_ops }))); - if (was_untyped) { - const Type* result_t = type_untyped_ptr(base_datatype, unit_type(a)); - result = gen_reinterpret_cast(bb, result_t, result); - } - return yield_values_and_wrap_in_block(bb, singleton(result)); } case empty_mask_op: @@ -874,7 +775,6 @@ Module* infer_program(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); assert(!aconfig.check_types); aconfig.check_types = true; - aconfig.untyped_ptrs = false; aconfig.allow_fold = true; // TODO was moved here because a refactor, does this cause issues ? IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index c19eb4d92..c12b2c86a 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -37,9 +37,9 @@ static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* p const IntLiteral* offset_value = resolve_to_int_literal(offset); bool offset_is_zero = offset_value && offset_value->value == 0; if (!offset_is_zero) { - const Type* arr_type = pointer_type->payload.ptr_type.pointed_type; - assert(arr_type->tag == ArrType_TAG); - const Type* element_type = arr_type->payload.arr_type.element_type; + const Type* element_type = pointer_type->payload.ptr_type.pointed_type; + // assert(arr_type->tag == ArrType_TAG); + // const Type* element_type = arr_type->payload.arr_type.element_type; const Node* element_t_size = gen_primop_e(bb, size_of_op, singleton(element_type), empty(a)); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index e2a2604b2..e8767c86e 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -396,6 +396,13 @@ static const Node* process_node(Context* ctx, const Node* node) { destroy_scope_variables_map(ctx->scope_vars); return new; } + case Constant_TAG: { + Context new_context = *ctx; + ctx = &new_context; + ctx->current_fn = NULL; + rewriter = &ctx->rewriter; + break; + } case Case_TAG: case BasicBlock_TAG: if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 2cbe554cc..61ae0a28f 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -12,7 +12,6 @@ typedef struct { Rewriter rewriter; const Node* old_entry_point_decl; - const Node* old_wg_size_annotation; const CompilerConfig* config; } Context; @@ -54,18 +53,16 @@ static const Node* process(Context* ctx, const Node* node) { if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, ctx->config->specialization.subgroup_size))); } else if (strcmp(get_declaration_name(ncnst), "SUBGROUPS_PER_WG") == 0) { - if (ctx->old_wg_size_annotation) { - // SUBGROUPS_PER_WG = (NUMBER OF INVOCATIONS IN SUBGROUP / SUBGROUP SIZE) - // Note: this computations assumes only full subgroups are launched, if subgroups can launch partially filled then this relationship does not hold. - uint32_t wg_size[3]; - wg_size[0] = a->config.specializations.workgroup_size[0]; - wg_size[1] = a->config.specializations.workgroup_size[1]; - wg_size[2] = a->config.specializations.workgroup_size[2]; - uint32_t subgroups_per_wg = (wg_size[0] * wg_size[1] * wg_size[2]) / ctx->config->specialization.subgroup_size; - if (subgroups_per_wg == 0) - subgroups_per_wg = 1; // uh-oh - ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, subgroups_per_wg))); - } + // SUBGROUPS_PER_WG = (NUMBER OF INVOCATIONS IN SUBGROUP / SUBGROUP SIZE) + // Note: this computations assumes only full subgroups are launched, if subgroups can launch partially filled then this relationship does not hold. + uint32_t wg_size[3]; + wg_size[0] = a->config.specializations.workgroup_size[0]; + wg_size[1] = a->config.specializations.workgroup_size[1]; + wg_size[2] = a->config.specializations.workgroup_size[2]; + uint32_t subgroups_per_wg = (wg_size[0] * wg_size[1] * wg_size[2]) / ctx->config->specialization.subgroup_size; + if (subgroups_per_wg == 0) + subgroups_per_wg = 1; // uh-oh + ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, subgroups_per_wg))); } return ncnst; } diff --git a/src/shady/print.c b/src/shady/print.c index 724bc2cfc..03f7ff635 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -832,11 +832,13 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { printf(BYELLOW); printf(" %s", cnst->name); printf(RESET); - printf(" = "); - if (get_quoted_value(cnst->instruction)) - print_node(get_quoted_value(cnst->instruction)); - else - print_node(cnst->instruction); + if (cnst->instruction) { + printf(" = "); + if (get_quoted_value(cnst->instruction)) + print_node(get_quoted_value(cnst->instruction)); + else + print_node(cnst->instruction); + } printf(";\n"); break; } diff --git a/src/shady/type.c b/src/shady/type.c index 57ffcad46..c8fe2fc96 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -92,9 +92,6 @@ bool is_subtype(const Type* supertype, const Type* type) { } case PtrType_TAG: { if (supertype->payload.ptr_type.address_space != type->payload.ptr_type.address_space) return false; - // if either pointer type is untyped, both need to be - if (supertype->arena->config.untyped_ptrs && (!supertype->payload.ptr_type.pointed_type || !type->payload.ptr_type.pointed_type)) - return !supertype->payload.ptr_type.pointed_type && !type->payload.ptr_type.pointed_type; if (!supertype->payload.ptr_type.is_reference && type->payload.ptr_type.is_reference) return false; return is_subtype(supertype->payload.ptr_type.pointed_type, type->payload.ptr_type.pointed_type); @@ -786,7 +783,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const IntLiteral* lit = resolve_to_int_literal(offset); bool offset_is_zero = lit && lit->value == 0; assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); - assert(offset_is_zero || pointee_type->tag == ArrType_TAG && "if an offset is used, the base ptr must point to an array"); uniform &= offset_uniform; Nodes indices = nodes(arena, prim_op.operands.count - 2, &prim_op.operands.nodes[2]); diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 3fe05d656..0a342f433 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -58,11 +58,13 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { void step_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack) { const Type* current_type = *datatype; - const Type* selector_type = selector->type; - bool selector_uniform = deconstruct_qualified_type(&selector_type); - assert(selector_type->tag == Int_TAG && "selectors must be integers"); - *uniform &= selector_uniform; + if (selector->arena->config.check_types) { + const Type* selector_type = selector->type; + bool selector_uniform = deconstruct_qualified_type(&selector_type); + assert(selector_type->tag == Int_TAG && "selectors must be integers"); + *uniform &= selector_uniform; + } try_again: switch (current_type->tag) { From e97f49ae62eb4f7b9e8d8f91bc66e900f6f5deed Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 15 Apr 2024 17:02:18 +0200 Subject: [PATCH 191/693] fix build --- src/shady/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 627726f52..dda682a5d 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -113,6 +113,7 @@ add_subdirectory(emit) target_link_libraries(shady PRIVATE "api") target_link_libraries(shady INTERFACE "common") target_link_libraries(shady PRIVATE "$") +target_link_libraries(shady PRIVATE "$") install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/shady DESTINATION include) install(TARGETS shady EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) From c7219973b87514a610e70cfa6722ce093bc33ed8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 15 Apr 2024 17:29:13 +0200 Subject: [PATCH 192/693] fix all the asan stuff I can find --- src/driver/driver.c | 1 + src/driver/vcc.c | 1 + src/shady/analysis/free_variables.c | 1 + src/shady/compile.c | 1 + src/shady/passes/reconvergence_heuristics.c | 4 ++-- src/shady/print.c | 7 +++++-- 6 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/driver/driver.c b/src/driver/driver.c index 09f1cbb20..cd9055748 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -104,6 +104,7 @@ ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { if (err) return err; link_module(mod, m); + destroy_ir_arena(get_module_arena(m)); } return NoError; diff --git a/src/driver/vcc.c b/src/driver/vcc.c index b4404bbb7..1a39c8012 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -152,6 +152,7 @@ int main(int argc, char** argv) { remove(vcc_options.tmp_filename); driver_compile(&args, mod); + destroy_ir_arena(get_module_arena(mod)); } info_print("Done\n"); diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index a356a5453..0edbcad63 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -157,4 +157,5 @@ void destroy_scope_variables_map(struct Dict* map) { destroy_dict(value->free_set); free((void*) value); } + destroy_dict(map); } diff --git a/src/shady/compile.c b/src/shady/compile.c index e44ee8b49..4c5946acd 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -84,6 +84,7 @@ void add_scheduler_source(const CompilerConfig* config, Module* dst) { Module* builtin_scheduler_mod = parse_slim_module(config, pconfig, shady_scheduler_src, "builtin_scheduler"); debug_print("Adding builtin scheduler code"); link_module(dst, builtin_scheduler_mod); + destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); } CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index e8767c86e..189f0f498 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -378,9 +378,10 @@ static const Node* process_node(Context* ctx, const Node* node) { Rewriter* rewriter = &ctx->rewriter; IrArena* arena = rewriter->dst_arena; + Context new_context = *ctx; + switch (node->tag) { case Function_TAG: { - Context new_context = *ctx; ctx = &new_context; ctx->current_fn = node; ctx->fwd_scope = new_scope(ctx->current_fn); @@ -397,7 +398,6 @@ static const Node* process_node(Context* ctx, const Node* node) { return new; } case Constant_TAG: { - Context new_context = *ctx; ctx = &new_context; ctx->current_fn = NULL; rewriter = &ctx->rewriter; diff --git a/src/shady/print.c b/src/shady/print.c index 03f7ff635..f79338e85 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1033,8 +1033,11 @@ void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) config.print_builtin = compiler_cfg->logging.print_builtin; config.print_internal = compiler_cfg->logging.print_internal; } - if (level >= get_log_level()) - print_module(open_file_as_printer(stderr), mod, config); + if (level >= get_log_level()) { + Printer* p = open_file_as_printer(stderr); + print_module(p, mod, config); + destroy_printer(p); + } } void print_node_operand(Printer* p, const Node* n, String name, NodeClass op_class, const Node* op, PrintConfig config) { From 9d528d6939408a4bd08468b43e992f99a181512a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 15 Apr 2024 20:19:12 +0200 Subject: [PATCH 193/693] fix incorrect usage of LLVM-C --- src/frontends/llvm/l2s_value.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/frontends/llvm/l2s_value.c b/src/frontends/llvm/l2s_value.c index 2680a2676..495fe55c1 100644 --- a/src/frontends/llvm/l2s_value.c +++ b/src/frontends/llvm/l2s_value.c @@ -131,12 +131,6 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { return get_default_zero_value(a, convert_type(p, LLVMTypeOf(v))); case LLVMConstantArrayValueKind: { assert(t->tag == ArrType_TAG); - assert(LLVMIsConstant(v)); - if (LLVMIsConstantString(v)) { - size_t idc; - r = string_lit_helper(a, LLVMGetAsString(v, &idc)); - break; - } size_t arr_size = get_int_literal_value(*resolve_to_int_literal(t->payload.arr_type.size), false); assert(arr_size >= 0 && arr_size < INT32_MAX && "sanity check"); LARRAY(const Node*, elements, arr_size); From 13276ac085482fa3cbabc7685b9ab305cfc66d4a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 16 Apr 2024 09:16:24 +0200 Subject: [PATCH 194/693] runtime/vk: fix broken hash fn for spec programs --- src/runtime/vulkan/vk_runtime_device.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index c96a883e7..11fcb7cd6 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -208,12 +208,16 @@ static bool get_physical_device_caps(SHADY_UNUSED VkrBackend* runtime, VkPhysica return false; } +KeyHash hash_string(const char** string); +bool compare_string(const char** a, const char** b); + static KeyHash hash_spec_program_key(SpecProgramKey* ptr) { - return hash_murmur(ptr, sizeof(SpecProgramKey)); + return hash_murmur(ptr->base, sizeof(Program*)) ^ hash_string(&ptr->entry_point); } static bool cmp_spec_program_keys(SpecProgramKey* a, SpecProgramKey* b) { - return memcmp(a, b, sizeof(SpecProgramKey)) == 0; + assert(!!a & !!b); + return a->base == b->base && strcmp(a->entry_point, b->entry_point) == 0; } static void obtain_device_pointers(VkrDevice* device) { From 5554b9c28850cb9107fb789884d64c558626274b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 16 Apr 2024 09:17:15 +0200 Subject: [PATCH 195/693] fix: don't mutate src module when running passes --- src/shady/compile.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 4c5946acd..21da5989c 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -88,12 +88,16 @@ void add_scheduler_source(const CompilerConfig* config, Module* dst) { } CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { - if (config->dynamic_scheduling) { - add_scheduler_source(config, *pmod); - } - IrArena* initial_arena = (*pmod)->arena; Module* old_mod = NULL; + + if (config->dynamic_scheduling) { + *pmod = import(config, *pmod); // we don't want to mess with the original module + + add_scheduler_source(config, *pmod); + log_module(ERROR, config, *pmod); + //exit(0); + } RUN_PASS(reconvergence_heuristics) From 5cea342941f4ec33781c9716a82359bcbed9d738 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 16 Apr 2024 10:54:25 +0200 Subject: [PATCH 196/693] implement an FMA op --- include/shady/primops.json | 4 ++++ src/frontends/llvm/l2s_instr.c | 5 +++-- src/shady/emit/c/emit_c_instructions.c | 17 +++++++++++++++++ src/shady/emit/spirv/emit_spv_instructions.c | 9 +++++---- src/shady/type.c | 19 +++++++++++++++++++ 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index 53cb4342c..3a7dfcd0a 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -66,6 +66,10 @@ "name": "div", "class": "arithmetic" }, + { + "name": "fma", + "class": "arithmetic" + }, { "name": "mod", "class": "arithmetic" diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index f2bb1a39d..4a2467eea 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -497,8 +497,9 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM } else if (string_starts_with(intrinsic, "llvm.fmuladd")) { Nodes ops = convert_operands(p, num_ops, instr); num_results = 1; - r = prim_op_helper(a, mul_op, empty(a), nodes(a, 2, ops.nodes)); - r = prim_op_helper(a, add_op, empty(a), mk_nodes(a, first(BIND_PREV_R(convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))))), ops.nodes[2])); + r = prim_op_helper(a, fma_op, empty(a), nodes(a, 3, ops.nodes)); + // r = prim_op_helper(a, mul_op, empty(a), nodes(a, 2, ops.nodes)); + // r = prim_op_helper(a, add_op, empty(a), mk_nodes(a, first(BIND_PREV_R(convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))))), ops.nodes[2])); break; } else if (string_starts_with(intrinsic, "llvm.fabs")) { Nodes ops = convert_operands(p, num_ops, instr); diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index bfa432e90..32fddb15e 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -270,6 +270,23 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct term = term_from_cvalue(format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); break; } + case fma_op: { + CValue a = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[0])); + CValue b = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[1])); + CValue c = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[2])); + switch (emitter->config.dialect) { + case CDialect_C11: + case CDialect_CUDA: { + term = term_from_cvalue(format_string_arena(arena->arena, "fmaf(%s, %s, %s)", a, b, c)); + break; + } + default: { + term = term_from_cvalue(format_string_arena(arena->arena, "(%s * %s) + %s", a, b, c)); + break; + } + } + break; + } case lshift_op: case rshift_arithm_op: case rshift_logical_op: { diff --git a/src/shady/emit/spirv/emit_spv_instructions.c b/src/shady/emit/spirv/emit_spv_instructions.c index 0b45857dd..c830ea00d 100644 --- a/src/shady/emit/spirv/emit_spv_instructions.c +++ b/src/shady/emit/spirv/emit_spv_instructions.c @@ -124,10 +124,11 @@ static const IselTableEntry isel_table[] = { [abs_op] = { Plain, FirstOp, Same, .extended_set = "GLSL.std.450", .fo = { (SpvOp) GLSLstd450SAbs, ISEL_ILLEGAL, (SpvOp) GLSLstd450FAbs, ISEL_ILLEGAL }}, [sign_op] = { Plain, FirstOp, Same, .extended_set = "GLSL.std.450", .fo = { (SpvOp) GLSLstd450SSign, ISEL_ILLEGAL, (SpvOp) GLSLstd450FSign, ISEL_ILLEGAL }}, - [min_op] = {Plain, FirstOp, Same, .extended_set = "GLSL.std.450", .fo = {(SpvOp) GLSLstd450SMin, (SpvOp) GLSLstd450UMin, (SpvOp) GLSLstd450FMin, ISEL_ILLEGAL, ISEL_ILLEGAL }}, - [max_op] = {Plain, FirstOp, Same, .extended_set = "GLSL.std.450", .fo = {(SpvOp) GLSLstd450SMax, (SpvOp) GLSLstd450UMax, (SpvOp) GLSLstd450FMax, ISEL_ILLEGAL, ISEL_ILLEGAL }}, - [exp_op] = {Plain, FirstOp, Same, .extended_set = "GLSL.std.450", .op = (SpvOp) GLSLstd450Exp}, - [pow_op] = {Plain, FirstOp, Same, .extended_set = "GLSL.std.450", .op = (SpvOp) GLSLstd450Pow}, + [min_op] = { Plain, FirstOp, Same, .extended_set = "GLSL.std.450", .fo = {(SpvOp) GLSLstd450SMin, (SpvOp) GLSLstd450UMin, (SpvOp) GLSLstd450FMin, ISEL_ILLEGAL, ISEL_ILLEGAL }}, + [max_op] = { Plain, FirstOp, Same, .extended_set = "GLSL.std.450", .fo = {(SpvOp) GLSLstd450SMax, (SpvOp) GLSLstd450UMax, (SpvOp) GLSLstd450FMax, ISEL_ILLEGAL, ISEL_ILLEGAL }}, + [exp_op] = { Plain, Monomorphic, Same, .extended_set = "GLSL.std.450", .op = (SpvOp) GLSLstd450Exp }, + [pow_op] = { Plain, Monomorphic, Same, .extended_set = "GLSL.std.450", .op = (SpvOp) GLSLstd450Pow }, + [fma_op] = { Plain, Monomorphic, Same, .extended_set = "GLSL.std.450", .op = (SpvOp) GLSLstd450Fma }, [debug_printf_op] = {Plain, Monomorphic, Void, .extended_set = "NonSemantic.DebugPrintf", .op = (SpvOp) NonSemanticDebugPrintfDebugPrintf}, diff --git a/src/shady/type.c b/src/shady/type.c index c8fe2fc96..6da9ed2a5 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -698,6 +698,25 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { return qualified_type_helper(first_operand_type, result_uniform); } + case fma_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 3); + const Type* first_operand_type = get_unqualified_type(first(prim_op.operands)->type); + + bool result_uniform = true; + for (size_t i = 0; i < prim_op.operands.count; i++) { + const Node* arg = prim_op.operands.nodes[i]; + const Type* operand_type = arg->type; + bool operand_uniform = deconstruct_qualified_type(&operand_type); + + assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); + assert(first_operand_type == operand_type && "operand type mismatch"); + + result_uniform &= operand_uniform; + } + + return qualified_type_helper(first_operand_type, result_uniform); + } case abs_op: case sign_op: { From 10035b85edbecd87cbf745cf8956bd8c0d210075 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 16 Apr 2024 15:20:14 +0200 Subject: [PATCH 197/693] cli: added --stack-size option --- src/driver/cli.c | 8 ++++- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_stack.c | 50 ++++++++++++++++----------- src/shady/passes/setup_stack_frames.c | 2 +- 4 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/driver/cli.c b/src/driver/cli.c index 41f9463a8..2d8a489f6 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -121,8 +121,14 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a argv[i] = NULL; i++; if (i == argc) - error("Missing subgroup size name"); + error("Missing subgroup size"); config->specialization.subgroup_size = atoi(argv[i]); + } else if (strcmp(argv[i], "--stack-size") == 0) { + argv[i] = NULL; + i++; + if (i == argc) + error("Missing stack size"); + config->per_thread_stack_size = atoi(argv[i]); } else if (strcmp(argv[i], "--execution-model") == 0) { argv[i] = NULL; i++; diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 278be673f..0814ff6fd 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -85,7 +85,7 @@ static const Node* process(Context* ctx, const Node* node) { case Function_TAG: { Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); Context ctx2 = *ctx; - ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames"); + ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; ctx2.prepared_offsets = new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); BodyBuilder* bb = begin_body(a); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 52e0dd0f5..8213bc294 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -101,17 +101,20 @@ static const Node* process_let(Context* ctx, const Node* node) { const PrimOp* oprim_op = &old_instruction->payload.prim_op; switch (oprim_op->op) { case get_stack_pointer_op: { + assert(ctx->stack); BodyBuilder* bb = begin_body(a); const Node* sp = gen_load(bb, ctx->stack_pointer); return finish_body(bb, let(a, quote_helper(a, singleton(sp)), tail)); } case set_stack_pointer_op: { + assert(ctx->stack); BodyBuilder* bb = begin_body(a); const Node* val = rewrite_node(&ctx->rewriter, oprim_op->operands.nodes[0]); gen_store(bb, ctx->stack_pointer, val); return finish_body(bb, let(a, quote_helper(a, empty(a)), tail)); } case get_stack_base_op: { + assert(ctx->stack); BodyBuilder* bb = begin_body(a); const Node* stack_pointer = ctx->stack_pointer; const Node* stack_size = gen_load(bb, stack_pointer); @@ -126,6 +129,7 @@ static const Node* process_let(Context* ctx, const Node* node) { } case push_stack_op: case pop_stack_op: { + assert(ctx->stack); BodyBuilder* bb = begin_body(a); const Type* element_type = rewrite_node(&ctx->rewriter, first(oprim_op->type_arguments)); @@ -161,8 +165,10 @@ static const Node* process_node(Context* ctx, const Node* old) { // Make sure to zero-init the stack pointers // TODO isn't this redundant with thoose things having an initial value already ? // is this an old forgotten workaround ? - const Node* stack_pointer = ctx->stack_pointer; - gen_store(bb, stack_pointer, uint32_literal(a, 0)); + if (ctx->stack) { + const Node* stack_pointer = ctx->stack_pointer; + gen_store(bb, stack_pointer, uint32_literal(a, 0)); + } new->payload.fun.body = finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body)); return new; } @@ -181,22 +187,6 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); - const Type* stack_base_element = uint8_type(a); - const Type* stack_arr_type = arr_type(a, (ArrType) { - .element_type = stack_base_element, - .size = uint32_literal(a, config->per_thread_stack_size), - }); - const Type* stack_counter_t = uint32_type(a); - - Nodes annotations = mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" })); - - // Arrays for the stacks - Node* stack_decl = global_var(dst, annotations, stack_arr_type, "stack", AsPrivate); - - // Pointers into those arrays - Node* stack_ptr_decl = global_var(dst, append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical" })), stack_counter_t, "stack_ptr", AsPrivate); - stack_ptr_decl->payload.global_variable.init = uint32_literal(a, 0); - Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), @@ -204,11 +194,29 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { .push = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), .pop = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), - - .stack = ref_decl_helper(a, stack_decl), - .stack_pointer = ref_decl_helper(a, stack_ptr_decl), }; + if (config->per_thread_stack_size > 0) { + const Type* stack_base_element = uint8_type(a); + const Type* stack_arr_type = arr_type(a, (ArrType) { + .element_type = stack_base_element, + .size = uint32_literal(a, config->per_thread_stack_size), + }); + const Type* stack_counter_t = uint32_type(a); + + Nodes annotations = mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" })); + + // Arrays for the stacks + Node* stack_decl = global_var(dst, annotations, stack_arr_type, "stack", AsPrivate); + + // Pointers into those arrays + Node* stack_ptr_decl = global_var(dst, append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical" })), stack_counter_t, "stack_ptr", AsPrivate); + stack_ptr_decl->payload.global_variable.init = uint32_literal(a, 0); + + ctx.stack = ref_decl_helper(a, stack_decl); + ctx.stack_pointer = ref_decl_helper(a, stack_ptr_decl); + } + rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 06adeef97..697d18fd6 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -31,7 +31,7 @@ static const Node* process(Context* ctx, const Node* node) { case Function_TAG: { Node* fun = recreate_decl_header_identity(r, node); Context ctx2 = *ctx; - ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames"); + ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; BodyBuilder* bb = begin_body(a); if (!ctx2.disable_lowering) { From 2826b255e96709b8d7c69b7298e7afa0b5ad7fa3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 16 Apr 2024 15:20:34 +0200 Subject: [PATCH 198/693] emit_spv: emit ArrayStride "properly" (i hope?) --- src/shady/emit/spirv/emit_spv_type.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/shady/emit/spirv/emit_spv_type.c b/src/shady/emit/spirv/emit_spv_type.c index a49d89c48..cf3595156 100644 --- a/src/shady/emit/spirv/emit_spv_type.c +++ b/src/shady/emit/spirv/emit_spv_type.c @@ -1,4 +1,5 @@ #include "emit_spv.h" +#include "type.h" #include "portability.h" #include "log.h" @@ -210,6 +211,13 @@ SpvId emit_type(Emitter* emitter, const Type* type) { case Type_JoinPointType_TAG: error("These must be lowered beforehand") } + if (is_data_type(type)) { + if (type->tag == PtrType_TAG && type->payload.ptr_type.address_space == AsGlobal) { + TypeMemLayout elem_mem_layout = get_mem_layout(emitter->arena, type->payload.ptr_type.pointed_type); + spvb_decorate(emitter->file_builder, new, SpvDecorationArrayStride, 1, (uint32_t[]) {elem_mem_layout.size_in_bytes}); + } + } + insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, type, new); return new; } From b327896a922a25cf983dbed14bd8c428f4db97b6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 16 Apr 2024 17:32:12 +0200 Subject: [PATCH 199/693] added gpu-side timings --- include/shady/runtime.h | 6 +++++- samples/aobench/ao_main.c | 10 ++++++--- samples/checkerboard/checkerboard.c | 2 +- src/runtime/cuda/cuda_runtime.c | 19 +++++++++++++++-- src/runtime/cuda/cuda_runtime_private.h | 4 ++++ src/runtime/runtime.c | 4 ++-- src/runtime/runtime_private.h | 2 +- src/runtime/runtime_test.c | 2 +- src/runtime/vulkan/vk_runtime_dispatch.c | 27 +++++++++++++++++++++++- src/runtime/vulkan/vk_runtime_private.h | 5 ++++- 10 files changed, 68 insertions(+), 13 deletions(-) diff --git a/include/shady/runtime.h b/include/shady/runtime.h index 21736d1f3..44ce53514 100644 --- a/include/shady/runtime.h +++ b/include/shady/runtime.h @@ -30,7 +30,11 @@ typedef struct Module_ Module; Program* new_program_from_module(Runtime*, const CompilerConfig*, Module*); -Command* launch_kernel(Program*, Device*, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args); +typedef struct { + uint64_t* profiled_gpu_time; +} ExtraKernelOptions; + +Command* launch_kernel(Program*, Device*, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions*); bool wait_completion(Command*); Buffer* allocate_buffer_device(Device*, size_t); diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 3398e835b..8275b6263 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -132,15 +132,19 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri Program* program = new_program_from_module(runtime, &args->compiler_config, m); // run it twice to compile everything and benefit from caches - wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr })); + wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, NULL)); struct timespec ts; timespec_get(&ts, TIME_UTC); uint64_t tsn = timespec_to_nano(ts); - wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr })); + uint64_t profiled_gpu_time = 0; + ExtraKernelOptions extra_kernel_options = { + .profiled_gpu_time = &profiled_gpu_time + }; + wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, &extra_kernel_options)); struct timespec tp; timespec_get(&tp, TIME_UTC); uint64_t tpn = timespec_to_nano(tp); - info_print("device rendering took %d us\n", (tpn - tsn) / 1000); + info_print("device rendering took %dus (gpu time: %dus)\n", (tpn - tsn) / 1000, profiled_gpu_time / 1000); debug_print("data %d\n", (int) img[0]); diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index cd14f9943..73d890d32 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -73,7 +73,7 @@ int main(int argc, char **argv) error("Failed to load checkerboard module"); Program* program = new_program_from_module(runtime, &compiler_config, m); - wait_completion(launch_kernel(program, device, "checkerboard", 16, 16, 1, 1, (void*[]) { &buf_addr })); + wait_completion(launch_kernel(program, device, "checkerboard", 16, 16, 1, 1, (void*[]) { &buf_addr }, NULL)); copy_from_buffer(buf, 0, img, buf_size); info_print("data %d\n", (int) img[0]); diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 02d01cd62..ae744c9cc 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -24,10 +24,16 @@ static void cuda_device_cleanup(CudaDevice* device) { bool cuda_command_wait(CudaCommand* command) { CHECK_CUDA(cuCtxSynchronize(), return false); + if (command->profiled_gpu_time) { + cudaEventSynchronize(command->stop); + float ms; + cudaEventElapsedTime(&ms, command->start, command->stop); + *command->profiled_gpu_time = (uint64_t) ((double) ms * 1000000); + } return true; } -CudaCommand* shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args) { +CudaCommand* shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* options) { CudaKernel* kernel = shd_cuda_get_specialized_program(device, p, entry_point); CudaCommand* cmd = calloc(sizeof(CudaCommand), 1); @@ -36,11 +42,20 @@ CudaCommand* shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry .wait_for_completion = (bool(*)(Command*)) cuda_command_wait } }; + + if (options && options->profiled_gpu_time) { + cmd->profiled_gpu_time = options->profiled_gpu_time; + cudaEventCreate(&cmd->start); + cudaEventCreate(&cmd->stop); + cudaEventRecord(cmd->start, 0); + } + ArenaConfig final_config = get_arena_config(get_module_arena(kernel->final_module)); unsigned int gx = final_config.specializations.workgroup_size[0]; unsigned int gy = final_config.specializations.workgroup_size[1]; unsigned int gz = final_config.specializations.workgroup_size[2]; CHECK_CUDA(cuLaunchKernel(kernel->entry_point_function, dimx, dimy, dimz, gx, gy, gz, 0, 0, args, NULL), return NULL); + cudaEventRecord(cmd->stop, 0); return cmd; } @@ -63,7 +78,7 @@ static CudaDevice* create_cuda_device(CudaBackend* b, int ordinal) { .allocate_buffer = (Buffer* (*)(Device*, size_t)) shd_cuda_allocate_buffer, .can_import_host_memory = (bool (*)(Device*)) shd_cuda_can_import_host_memory, .import_host_memory_as_buffer = (Buffer* (*)(Device*, void*, size_t)) shd_cuda_import_host_memory, - .launch_kernel = (Command*(*)(Device*, Program*, String, int, int, int, int, void**)) shd_cuda_launch_kernel, + .launch_kernel = (Command*(*)(Device*, Program*, String, int, int, int, int, void**, ExtraKernelOptions*)) shd_cuda_launch_kernel, }, .handle = handle, .specialized_programs = new_dict(SpecProgramKey, CudaKernel*, (HashFn) hash_spec_program_key, (CmpFn) cmp_spec_program_keys), diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index a5a6bd735..fc82eb8c6 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -4,6 +4,7 @@ #include "../runtime_private.h" #include +#include #include #define CHECK_NVRTC(x, failure_handler) { nvrtcResult the_result_ = x; if (the_result_ != NVRTC_SUCCESS) { const char* msg = nvrtcGetErrorString(the_result_); error_print(#x " failed (%s)\n", msg); failure_handler; } } @@ -40,6 +41,9 @@ typedef struct { typedef struct { Command base; + + uint64_t* profiled_gpu_time; + cudaEvent_t start, stop; } CudaCommand; typedef struct { diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 1d1c20175..5d007891d 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -74,8 +74,8 @@ Device* get_an_device(Runtime* r) { const char* get_device_name(Device* d) { return d->get_name(d); } -Command* launch_kernel(Program* p, Device* d, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args) { - return d->launch_kernel(d, p, entry_point, dimx, dimy, dimz, args_count, args); +Command* launch_kernel(Program* p, Device* d, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* extra_options) { + return d->launch_kernel(d, p, entry_point, dimx, dimy, dimz, args_count, args, extra_options); } bool wait_completion(Command* cmd) { return cmd->wait_for_completion(cmd); } diff --git a/src/runtime/runtime_private.h b/src/runtime/runtime_private.h index d225bdf85..a8d6e2d72 100644 --- a/src/runtime/runtime_private.h +++ b/src/runtime/runtime_private.h @@ -30,7 +30,7 @@ struct Device_ { void (*cleanup)(Device*); String (*get_name)(Device*); - Command* (*launch_kernel)(Device*, Program*, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args); + Command* (*launch_kernel)(Device*, Program*, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions*); Buffer* (*allocate_buffer)(Device*, size_t bytes); Buffer* (*import_host_memory_as_buffer)(Device*, void* base, size_t bytes); bool (*can_import_host_memory)(Device*); diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 82c3747ce..4e1bbba30 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -70,7 +70,7 @@ int main(int argc, char* argv[]) { int32_t a0 = 42; uint64_t a1 = get_buffer_device_pointer(buffer); - wait_completion(launch_kernel(program, device, args.driver_config.config.specialization.entry_point ? args.driver_config.config.specialization.entry_point : "my_kernel", 1, 1, 1, 2, (void*[]) { &a0, &a1 })); + wait_completion(launch_kernel(program, device, args.driver_config.config.specialization.entry_point ? args.driver_config.config.specialization.entry_point : "my_kernel", 1, 1, 1, 2, (void*[]) { &a0, &a1 }, NULL)); destroy_buffer(buffer); diff --git a/src/runtime/vulkan/vk_runtime_dispatch.c b/src/runtime/vulkan/vk_runtime_dispatch.c index 5685e22c5..4bc755022 100644 --- a/src/runtime/vulkan/vk_runtime_dispatch.c +++ b/src/runtime/vulkan/vk_runtime_dispatch.c @@ -57,7 +57,7 @@ static Command make_command_base() { }; } -VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args) { +VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* options) { assert(program && device); VkrSpecProgram* prog = get_specialized_program(program, entry_point, device); @@ -82,8 +82,26 @@ VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_ vkCmdBindPipeline(cmd->cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE, prog->pipeline); bind_program_resources(cmd, prog); + + if (options && options->profiled_gpu_time) { + VkQueryPoolCreateInfo qpci = { + .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, + .pNext = NULL, + .queryType = VK_QUERY_TYPE_TIMESTAMP, + .queryCount = 2, + }; + CHECK_VK(vkCreateQueryPool(device->device, &qpci, NULL, &cmd->query_pool), {}); + cmd->profiled_gpu_time = options->profiled_gpu_time; + vkCmdResetQueryPool(cmd->cmd_buf, cmd->query_pool, 0, 1); + vkCmdWriteTimestamp(cmd->cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, cmd->query_pool, 0); + } + vkCmdDispatch(cmd->cmd_buf, dimx, dimy, dimz); + if (options && options->profiled_gpu_time) { + vkCmdWriteTimestamp(cmd->cmd_buf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, cmd->query_pool, 1); + } + if (!vkr_submit_command(cmd)) goto err_post_commands_create; @@ -153,6 +171,11 @@ bool vkr_submit_command(VkrCommand* cmd) { bool vkr_wait_completion(VkrCommand* cmd) { assert(cmd->submitted && "Command must be submitted before they can be waited on"); CHECK_VK(vkWaitForFences(cmd->device->device, 1, (VkFence[]) { cmd->done_fence }, true, UINT32_MAX), return false); + if (cmd->profiled_gpu_time) { + uint64_t ts[2]; + CHECK_VK(vkGetQueryPoolResults(cmd->device->device, cmd->query_pool, 0, 2, sizeof(uint64_t) * 2, ts, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT), {}); + *cmd->profiled_gpu_time = ts[1] - ts[0]; + } vkr_destroy_command(cmd); return true; } @@ -160,6 +183,8 @@ bool vkr_wait_completion(VkrCommand* cmd) { void vkr_destroy_command(VkrCommand* cmd) { if (cmd->submitted) vkDestroyFence(cmd->device->device, cmd->done_fence, NULL); + if (cmd->query_pool) + vkDestroyQueryPool(cmd->device->device, cmd->query_pool, NULL); vkFreeCommandBuffers(cmd->device->device, cmd->device->cmd_pool, 1, &cmd->cmd_buf); free(cmd); } diff --git a/src/runtime/vulkan/vk_runtime_private.h b/src/runtime/vulkan/vk_runtime_private.h index fe1a16361..fa6e127a3 100644 --- a/src/runtime/vulkan/vk_runtime_private.h +++ b/src/runtime/vulkan/vk_runtime_private.h @@ -181,6 +181,9 @@ struct VkrCommand_ { VkCommandBuffer cmd_buf; VkFence done_fence; bool submitted; + + uint64_t* profiled_gpu_time; + VkQueryPool query_pool; }; VkrCommand* vkr_begin_command(VkrDevice* device); @@ -188,7 +191,7 @@ bool vkr_submit_command(VkrCommand* commands); void vkr_destroy_command(VkrCommand* commands); bool vkr_wait_completion(VkrCommand* cmd); -VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args); +VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions*); typedef struct ProgramResourceInfo_ ProgramResourceInfo; struct ProgramResourceInfo_ { From 435a59de261652abf40f8fb6c1ec116af3d17dca Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 16 Apr 2024 21:15:58 +0200 Subject: [PATCH 200/693] fix timestamp queries on non-nv hardware --- src/runtime/vulkan/vk_runtime_dispatch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/vulkan/vk_runtime_dispatch.c b/src/runtime/vulkan/vk_runtime_dispatch.c index 4bc755022..379ef7fd9 100644 --- a/src/runtime/vulkan/vk_runtime_dispatch.c +++ b/src/runtime/vulkan/vk_runtime_dispatch.c @@ -53,7 +53,7 @@ static void bind_program_resources(VkrCommand* cmd, VkrSpecProgram* prog) { static Command make_command_base() { return (Command) { - .wait_for_completion = (bool(*)(Command*)) vkr_wait_completion, + .wait_for_completion = (bool(*)(Command*)) vkr_wait_completion, }; } @@ -92,7 +92,7 @@ VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_ }; CHECK_VK(vkCreateQueryPool(device->device, &qpci, NULL, &cmd->query_pool), {}); cmd->profiled_gpu_time = options->profiled_gpu_time; - vkCmdResetQueryPool(cmd->cmd_buf, cmd->query_pool, 0, 1); + vkCmdResetQueryPool(cmd->cmd_buf, cmd->query_pool, 0, 2); vkCmdWriteTimestamp(cmd->cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, cmd->query_pool, 0); } @@ -174,7 +174,7 @@ bool vkr_wait_completion(VkrCommand* cmd) { if (cmd->profiled_gpu_time) { uint64_t ts[2]; CHECK_VK(vkGetQueryPoolResults(cmd->device->device, cmd->query_pool, 0, 2, sizeof(uint64_t) * 2, ts, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT), {}); - *cmd->profiled_gpu_time = ts[1] - ts[0]; + *cmd->profiled_gpu_time = (ts[1] - ts[0]) * cmd->device->caps.properties.base.properties.limits.timestampPeriod; } vkr_destroy_command(cmd); return true; From 4284d95559afc7361f24e9f3ddffd5cce9965ea2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 17 Apr 2024 16:15:47 +0200 Subject: [PATCH 201/693] fix stack lowering for new lea semantics --- src/shady/passes/lower_physical_ptrs.c | 4 ++-- src/shady/passes/lower_stack.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index c5ded3ba0..d244268eb 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -94,7 +94,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type } if (config->printf_trace.memory_accesses) { AddressSpace as = get_unqualified_type(arr->type)->payload.ptr_type.address_space; - String template = format_string_interned(a, "loaded %s at %s:%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); + String template = format_string_interned(a, "loaded %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); const Node* widened = acc; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, uint32_type(a), acc); @@ -198,7 +198,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element } if (config->printf_trace.memory_accesses) { AddressSpace as = get_unqualified_type(arr->type)->payload.ptr_type.address_space; - String template = format_string_interned(a, "stored %s at %s:%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); + String template = format_string_interned(a, "stored %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); const Node* widened = value; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, uint32_type(a), value); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 8213bc294..200049eb3 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -59,7 +59,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { if (!push) // for pop, we decrease the stack size first stack_size = gen_primop_ce(bb, sub_op, 2, (const Node* []) { stack_size, element_size}); - const Node* addr = gen_lea(bb, stack, stack_size, nodes(a, 1, (const Node* []) {uint32_literal(a, 0) })); + const Node* addr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); assert(get_unqualified_type(addr->type)->tag == PtrType_TAG); AddressSpace addr_space = get_unqualified_type(addr->type)->payload.ptr_type.address_space; @@ -118,7 +118,7 @@ static const Node* process_let(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); const Node* stack_pointer = ctx->stack_pointer; const Node* stack_size = gen_load(bb, stack_pointer); - const Node* stack_base_ptr = gen_lea(bb, ctx->stack, stack_size, empty(a)); + const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { if (oprim_op->op == get_stack_base_op) bind_instruction(bb, prim_op(a, (PrimOp) {.op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) {.string = "trace: stack_size=%d\n"}), stack_size)})); From a98c01df10a2b6157fc5a731ed7211a1a09de42d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 17 Apr 2024 17:18:25 +0200 Subject: [PATCH 202/693] fix driver detection --- samples/fib.slim | 2 +- src/runtime/vulkan/vk_runtime_device.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/fib.slim b/samples/fib.slim index 5e6eb8563..ed843cf45 100644 --- a/samples/fib.slim +++ b/samples/fib.slim @@ -10,7 +10,7 @@ var input u32 subgroup_local_id; @Builtin("SubgroupId") var uniform input u32 subgroup_id; -@EntryPoint("Compute") @WorkgroupSize(32, 1, 1) fn main() { +@EntryPoint("Compute") @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn main() { val n = subgroup_local_id % u32 16; debug_printf("fib(%d) = %d from thread %d:%d\n", n, fib(n), subgroup_id, subgroup_local_id); return (); diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index 11fcb7cd6..6f1584b80 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -100,6 +100,11 @@ static bool fill_device_properties(VkrDeviceCaps* caps) { append_pnext((VkBaseOutStructure*) &caps->properties.base, &caps->properties.external_memory_host); } + if (caps->supported_extensions[ShadySupportsKHR_driver_properties]) { + caps->properties.driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + append_pnext((VkBaseOutStructure*) &caps->properties.base, &caps->properties.driver_properties); + } + vkGetPhysicalDeviceProperties2(caps->physical_device, &caps->properties.base); if (caps->supported_extensions[ShadySupportsEXT_subgroup_size_control] || caps->properties.base.properties.apiVersion >= VK_MAKE_VERSION(1, 3, 0)) { @@ -110,11 +115,6 @@ static bool fill_device_properties(VkrDeviceCaps* caps) { caps->subgroup_size.min = caps->properties.subgroup.subgroupSize; } debug_print("Subgroup size range for device '%s' is [%d; %d]\n", caps->properties.base.properties.deviceName, caps->subgroup_size.min, caps->subgroup_size.max); - - if (caps->supported_extensions[ShadySupportsKHR_driver_properties]) { - caps->properties.driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; - append_pnext((VkBaseOutStructure*) &caps->properties.base, &caps->properties.driver_properties); - } return true; } From ab4bb8dc8051901a18cacc82e5f3c48f40f2633f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 17 Apr 2024 17:19:04 +0200 Subject: [PATCH 203/693] fix handling of SUBGROUP_SIZE --- src/shady/compile.c | 3 +-- src/shady/passes/specialize_entry_point.c | 7 +------ src/shady/passes/specialize_execution_model.c | 10 ++++++++++ src/shady/transform/internal_constants.h | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 21da5989c..f2b72fb59 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -113,8 +113,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lift_indirect_targets) RUN_PASS(opt_mem2reg) // run because we can now weaken non-leaking allocas - if (config->specialization.execution_model != EmNone) - RUN_PASS(specialize_execution_model) + RUN_PASS(specialize_execution_model) RUN_PASS(opt_stack) diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 61ae0a28f..519c7d70c 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -50,9 +50,7 @@ static const Node* process(Context* ctx, const Node* node) { } case Constant_TAG: { Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); - if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { - ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, ctx->config->specialization.subgroup_size))); - } else if (strcmp(get_declaration_name(ncnst), "SUBGROUPS_PER_WG") == 0) { + if (strcmp(get_declaration_name(ncnst), "SUBGROUPS_PER_WG") == 0) { // SUBGROUPS_PER_WG = (NUMBER OF INVOCATIONS IN SUBGROUP / SUBGROUP SIZE) // Note: this computations assumes only full subgroups are launched, if subgroups can launch partially filled then this relationship does not hold. uint32_t wg_size[3]; @@ -87,9 +85,6 @@ static const Node* find_entry_point(Module* m, const CompilerConfig* config) { } static void specialize_arena_config(const CompilerConfig* config, Module* src, ArenaConfig* target) { - size_t subgroup_size = config->specialization.subgroup_size; - assert(subgroup_size); - const Node* old_entry_point_decl = find_entry_point(src, config); if (old_entry_point_decl->tag != Function_TAG) error("%s is not a function", config->specialization.entry_point); diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 0cb8b73d1..40f489a3d 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -22,6 +22,13 @@ static const Node* process(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { + case Constant_TAG: { + Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); + if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { + ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, ctx->config->specialization.subgroup_size))); + } + return ncnst; + } default: break; } return recreate_node_identity(&ctx->rewriter, node); @@ -44,6 +51,9 @@ Module* specialize_execution_model(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); + size_t subgroup_size = config->specialization.subgroup_size; + assert(subgroup_size); + Context ctx = { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/transform/internal_constants.h b/src/shady/transform/internal_constants.h index eec5b6784..bf7f61a04 100644 --- a/src/shady/transform/internal_constants.h +++ b/src/shady/transform/internal_constants.h @@ -4,7 +4,7 @@ #include "shady/ir.h" #define INTERNAL_CONSTANTS(X) \ -X(SUBGROUP_SIZE, uint32_type(arena), uint32_literal(arena, config->specialization.subgroup_size)) \ +X(SUBGROUP_SIZE, uint32_type(arena), uint32_literal(arena, 64)) \ X(SUBGROUPS_PER_WG, uint32_type(arena), uint32_literal(arena, 1)) \ void generate_dummy_constants(const CompilerConfig* config, Module*); From 853af249ab99b566a156aa15507437d63d74d543 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 17 Apr 2024 17:19:36 +0200 Subject: [PATCH 204/693] fixed lift_indirect_targets --- src/shady/passes/lift_indirect_targets.c | 149 +++++++++++++++-------- src/shady/rewrite.c | 30 ++++- src/shady/rewrite.h | 3 + 3 files changed, 127 insertions(+), 55 deletions(-) diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 0ca9c1442..6d58b6d76 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -15,6 +15,7 @@ #include "../analysis/free_variables.h" #include "../analysis/uses.h" #include "../analysis/leak.h" +#include "../analysis/verify.h" #include #include @@ -31,6 +32,8 @@ typedef struct Context_ { struct Dict* lifted; bool disable_lowering; const CompilerConfig* config; + + bool* todo; } Context; static const Node* process_node(Context* ctx, const Node* node); @@ -66,6 +69,20 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, struct L return sp; } +static void add_to_recover_context(struct List* recover_context, struct Dict* set, const Node* except) { + Nodes params = get_abstraction_params(except); + size_t i = 0; + const Node* item; + while (dict_iter(set, &i, &item, NULL)) { + for (size_t j = 0; j < params.count; j++) { + if (item == params.nodes[j]) + goto skip; + } + append_list(const Node*, recover_context, item ); + skip:; + } +} + static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name) { assert(is_basic_block(cont) || is_case(cont)); LiftedCont** found = find_value_dict(const Node*, LiftedCont*, ctx->lifted, cont); @@ -82,20 +99,19 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name CFNode* cf_node = scope_lookup(ctx->scope, cont); CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_node); struct List* recover_context = new_list(const Node*); - size_t recover_context_size = entries_count_dict(node_vars->free_set); - - { - debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", name, entries_count_dict(node_vars->free_set)); - size_t i = 0; - const Node* item; - while (dict_iter(node_vars->free_set, &i, &item, NULL)) { - append_list(const Node*, recover_context, item ); - debugv_print(get_value_name_safe(item)); - if (i + 1 < recover_context_size) - debugv_print(", "); - } - debugv_print("\n"); + + // add_to_recover_context(recover_context, node_vars->free_set, cont); + add_to_recover_context(recover_context, node_vars->bound_set, cont); + size_t recover_context_size = entries_count_list(recover_context); + + debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", name, recover_context_size); + for (size_t i = 0; i < recover_context_size; i++) { + const Node* item = read_list(const Node*, recover_context)[i]; + debugv_print(get_value_name_safe(item)); + if (i + 1 < recover_context_size) + debugv_print(", "); } + debugv_print("\n"); // Create and register new parameters for the lifted continuation Nodes new_params = recreate_variables(&ctx->rewriter, oparams); @@ -106,7 +122,13 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name insert_dict(const Node*, LiftedCont*, ctx->lifted, cont, lifted_cont); Context lifting_ctx = *ctx; - lifting_ctx.rewriter = create_rewriter(ctx->rewriter.src_module, ctx->rewriter.dst_module, (RewriteNodeFn) process_node); + // struct Dict* old_map = lifting_ctx.rewriter.map; + // lifting_ctx.rewriter.map = clone_dict(lifting_ctx.rewriter.map); + + // lifting_ctx.rewriter = create_rewriter(ctx->rewriter.src_module, ctx->rewriter.dst_module, (RewriteNodeFn) process_node); + // lifting_ctx.rewriter.decls_map = NULL; + lifting_ctx.rewriter.map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + lifting_ctx.rewriter.parent = &ctx->rewriter; register_processed_list(&lifting_ctx.rewriter, oparams, new_params); const Node* payload = var(a, qualified_type_helper(uint32_type(a), false), "sp"); @@ -140,6 +162,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name const Node* substituted = rewrite_node(&lifting_ctx.rewriter, obody); //destroy_dict(lifting_ctx.rewriter.processed); destroy_rewriter(&lifting_ctx.rewriter); + // lifting_ctx.rewriter.map = old_map; assert(is_terminator(substituted)); new_fn->payload.fun.body = finish_body(bb, substituted); @@ -151,27 +174,18 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* found = search_processed(&ctx->rewriter, node); if (found) return found; - // TODO: share this code - if (is_declaration(node)) { - String name = get_declaration_name(node); - Nodes decls = get_module_declarations(ctx->rewriter.dst_module); - for (size_t i = 0; i < decls.count; i++) { - if (strcmp(get_declaration_name(decls.nodes[i]), name) == 0) - return decls.nodes[i]; - } - } - IrArena* a = ctx->rewriter.dst_arena; - if (ctx->disable_lowering) - return recreate_node_identity(&ctx->rewriter, node); - - switch (node->tag) { + switch (is_declaration(node)) { case Function_TAG: { + while (ctx->rewriter.parent) + ctx = (Context*) ctx->rewriter.parent; + Context fn_ctx = *ctx; fn_ctx.scope = new_scope(node); fn_ctx.scope_uses = create_uses_map(node, (NcDeclaration | NcType)); fn_ctx.scope_vars = compute_scope_variables_map(fn_ctx.scope); + fn_ctx.disable_lowering = lookup_annotation(node, "Internal"); ctx = &fn_ctx; Node* new = recreate_decl_header_identity(&ctx->rewriter, node); @@ -182,12 +196,22 @@ static const Node* process_node(Context* ctx, const Node* node) { destroy_scope(ctx->scope); return new; } + default: + break; + } + + if (ctx->disable_lowering) + return recreate_node_identity(&ctx->rewriter, node); + + switch (node->tag) { case Let_TAG: { const Node* oinstruction = get_let_instruction(node); if (oinstruction->tag == Control_TAG) { const Node* oinside = oinstruction->payload.control.inside; assert(is_case(oinside)); if (!is_control_static(ctx->scope_uses, oinstruction) || ctx->config->hacks.force_join_point_lifting) { + *ctx->todo = true; + const Node* otail = get_let_tail(node); BodyBuilder* bb = begin_body(a); LiftedCont* lifted_tail = lambda_lift(ctx, otail, unique_name(a, format_string_arena(a->arena, "post_control_%s", get_abstraction_name(ctx->scope->entry->node)))); @@ -195,38 +219,65 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); const Node* jp = gen_primop_e(bb, create_joint_point_op, rewrite_nodes(&ctx->rewriter, oinstruction->payload.control.yield_types), mk_nodes(a, tail_ptr, sp)); + // dumbass hack + jp = gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(jp)); return finish_body(bb, let(a, quote_helper(a, singleton(jp)), rewrite_node(&ctx->rewriter, oinside))); } } - - return recreate_node_identity(&ctx->rewriter, node); + break; } - default: return recreate_node_identity(&ctx->rewriter, node); + default: break; } + return recreate_node_identity(&ctx->rewriter, node); } Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + IrArena* a = NULL; + Module* dst; + + int round = 0; + while (true) { + debugv_print("lift_indirect_target: round %d\n", round++); + IrArena* oa = a; + a = new_ir_arena(aconfig); + dst = new_module(a, get_module_name(src)); + bool todo = false; + Context ctx = { + .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .lifted = new_dict(const Node*, LiftedCont*, (HashFn) hash_node, (CmpFn) compare_node), + .config = config, + + .todo = &todo + }; + + rewrite_module(&ctx.rewriter); + + size_t iter = 0; + LiftedCont* lifted_cont; + while (dict_iter(ctx.lifted, &iter, NULL, &lifted_cont)) { + destroy_list(lifted_cont->save_values); + free(lifted_cont); + } + destroy_dict(ctx.lifted); + destroy_rewriter(&ctx.rewriter); + log_module(DEBUGVV, config, dst); + verify_module(config, dst); + src = dst; + if (oa) + destroy_ir_arena(oa); + if (!todo) { + break; + } + } + // this will be safe now since we won't lift any more code after this pass aconfig.optimisations.weaken_non_leaking_allocas = true; - IrArena* a = new_ir_arena(aconfig); - Module* dst = new_module(a, get_module_name(src)); - Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), - .lifted = new_dict(const Node*, LiftedCont*, (HashFn) hash_node, (CmpFn) compare_node), - .config = config, - }; - - rewrite_module(&ctx.rewriter); - - size_t iter = 0; - LiftedCont* lifted_cont; - while (dict_iter(ctx.lifted, &iter, NULL, &lifted_cont)) { - destroy_list(lifted_cont->save_values); - free(lifted_cont); - } - destroy_dict(ctx.lifted); - destroy_rewriter(&ctx.rewriter); + IrArena* a2 = new_ir_arena(aconfig); + dst = new_module(a2, get_module_name(src)); + Rewriter r = create_importer(src, dst); + rewrite_module(&r); + destroy_ir_arena(a); return dst; } diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 80e012c0e..f7b347c03 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -33,7 +33,8 @@ Rewriter create_rewriter(Module* src, Module* dst, RewriteNodeFn fn) { void destroy_rewriter(Rewriter* r) { assert(r->map); destroy_dict(r->map); - destroy_dict(r->decls_map); + if (!r->parent) + destroy_dict(r->decls_map); } Rewriter create_importer(Module* src, Module* dst) { @@ -137,11 +138,27 @@ static Nodes rewrite_ops_helper(Rewriter* rewriter, NodeClass class, String op_n return rewrite_nodes_with_fn(rewriter, old_nodes, rewriter->rewrite_fn); } +static const Node* search_processed_(const Rewriter* ctx, const Node* old, bool deep) { + if (is_declaration(old)) { + const Node** found = find_value_dict(const Node*, const Node*, ctx->decls_map, old); + return found ? *found : NULL; + } + + while (ctx) { + assert(ctx->map && "this rewriter has no processed cache"); + const Node** found = find_value_dict(const Node*, const Node*, ctx->map, old); + if (found) + return *found; + if (deep) + ctx = ctx->parent; + else + ctx = NULL; + } + return NULL; +} + const Node* search_processed(const Rewriter* ctx, const Node* old) { - struct Dict* map = is_declaration(old) ? ctx->decls_map : ctx->map; - assert(map && "this rewriter has no processed cache"); - const Node** found = find_value_dict(const Node*, const Node*, map, old); - return found ? *found : NULL; + return search_processed_(ctx, old, false); } const Node* find_processed(const Rewriter* ctx, const Node* old) { @@ -154,7 +171,7 @@ void register_processed(Rewriter* ctx, const Node* old, const Node* new) { assert(old->arena == ctx->src_arena); assert(new->arena == ctx->dst_arena); #ifndef NDEBUG - const Node* found = search_processed(ctx, old); + const Node* found = search_processed_(ctx, old, false); if (found) { error_print("Trying to replace "); log_node(ERROR, old); @@ -190,6 +207,7 @@ bool compare_node(Node**, Node**); #include "rewrite_generated.c" void rewrite_module(Rewriter* rewriter) { + assert(rewriter->dst_module != rewriter->src_module); Nodes old_decls = get_module_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { if (old_decls.nodes[i]->tag == NominalType_TAG) continue; diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index d97bea438..315e2f4ee 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -37,6 +37,9 @@ struct Rewriter_ { bool fold_quote; bool process_variables; } config; + + Rewriter* parent; + struct Dict* map; struct Dict* decls_map; }; From cfa9a7746890f149cd9f9e38b20aa56a203cd165 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 10:08:09 +0200 Subject: [PATCH 205/693] added cli parsing for runtime options --- include/shady/driver.h | 2 - include/shady/runtime.h | 3 ++ samples/aobench/ao_main.c | 6 +-- samples/checkerboard/checkerboard.c | 6 +-- src/driver/cli.c | 36 ++++++++---------- src/driver/cli.h | 15 ++++++++ src/runtime/CMakeLists.txt | 2 +- src/runtime/runtime_cli.c | 47 ++++++++++++++++++++++++ src/runtime/runtime_test.c | 6 +-- src/shady/passes/lower_tailcalls.c | 2 +- test/driver/test_scalarisation_loop.slim | 5 ++- 11 files changed, 92 insertions(+), 38 deletions(-) create mode 100644 src/driver/cli.h create mode 100644 src/runtime/runtime_cli.c diff --git a/include/shady/driver.h b/include/shady/driver.h index b89e96462..b67cee362 100644 --- a/include/shady/driver.h +++ b/include/shady/driver.h @@ -39,8 +39,6 @@ typedef enum { CodegenTarget guess_target(const char* filename); -void cli_pack_remaining_args(int* pargc, char** argv); - // parses 'common' arguments such as log level etc void cli_parse_common_args(int* pargc, char** argv); // parses compiler pipeline options diff --git a/include/shady/runtime.h b/include/shady/runtime.h index 44ce53514..509ed7fdc 100644 --- a/include/shady/runtime.h +++ b/include/shady/runtime.h @@ -11,6 +11,9 @@ typedef struct { bool allow_no_devices; } RuntimeConfig; +RuntimeConfig default_runtime_config(); +void cli_parse_runtime_config(RuntimeConfig* config, int* pargc, char** argv); + typedef struct Runtime_ Runtime; typedef struct Device_ Device; typedef struct Program_ Program; diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 8275b6263..d2dd5e228 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -159,16 +159,14 @@ int main(int argc, char **argv) { set_log_level(INFO); Args args = { .compiler_config = default_compiler_config(), - .runtime_config = { - .use_validation = true, - .dump_spv = true, - } + .runtime_config = default_runtime_config(), }; args.compiler_config.hacks.restructure_everything = true; cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.compiler_config, &argc, argv); + cli_parse_runtime_config(&args.runtime_config, &argc, argv); cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); bool do_host = false, do_ispc = false, do_device = false, do_all = true; diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 73d890d32..84af926d0 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -43,13 +43,11 @@ int main(int argc, char **argv) set_log_level(INFO); CompilerConfig compiler_config = default_compiler_config(); - RuntimeConfig runtime_config = (RuntimeConfig) { - .use_validation = true, - .dump_spv = true, - }; + RuntimeConfig runtime_config = default_runtime_config(); cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&compiler_config, &argc, argv); + cli_parse_runtime_config(&runtime_config, &argc, argv); info_print("Shady checkerboard test starting...\n"); diff --git a/src/driver/cli.c b/src/driver/cli.c index 2d8a489f6..10932017a 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -1,9 +1,10 @@ +#include "cli.h" + #include "shady/driver.h" #include "shady/ir.h" #include #include -#include #include "log.h" #include "portability.h" @@ -81,25 +82,18 @@ void cli_parse_common_args(int* pargc, char** argv) { cli_pack_remaining_args(pargc, argv); } -#define PARSE_TOGGLE_OPTION(f, name) \ -if (strcmp(argv[i], "--no-"#name) == 0) { \ - config->f = false; argv[i] = NULL; continue; \ -} else if (strcmp(argv[i], "--"#name) == 0) { \ - config->f = true; argv[i] = NULL; continue; \ -} - -#define TOGGLE_OPTIONS(F) \ -F(lower.emulate_physical_memory, emulate-physical-memory) \ -F(lower.emulate_generic_ptrs, emulate-generic-pointers) \ -F(dynamic_scheduling, dynamic-scheduling) \ -F(hacks.force_join_point_lifting, lift-join-points) \ -F(logging.print_internal, print-internal) \ -F(logging.print_generated, print-builtin) \ -F(logging.print_generated, print-generated) \ -F(lower.simt_to_explicit_simd, lower-simt-to-simd) \ -F(optimisations.inline_everything, inline-everything) \ -F(hacks.restructure_everything, restructure-everything) \ -F(hacks.recover_structure, recover-structure) \ +#define COMPILER_CONFIG_TOGGLE_OPTIONS(F) \ +F(config->lower.emulate_physical_memory, emulate-physical-memory) \ +F(config->lower.emulate_generic_ptrs, emulate-generic-pointers) \ +F(config->dynamic_scheduling, dynamic-scheduling) \ +F(config->hacks.force_join_point_lifting, lift-join-points) \ +F(config->logging.print_internal, print-internal) \ +F(config->logging.print_generated, print-builtin) \ +F(config->logging.print_generated, print-generated) \ +F(config->lower.simt_to_explicit_simd, lower-simt-to-simd) \ +F(config->optimisations.inline_everything, inline-everything) \ +F(config->hacks.restructure_everything, restructure-everything) \ +F(config->hacks.recover_structure, recover-structure) \ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { int argc = *pargc; @@ -109,7 +103,7 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a if (argv[i] == NULL) continue; - TOGGLE_OPTIONS(PARSE_TOGGLE_OPTION) + COMPILER_CONFIG_TOGGLE_OPTIONS(PARSE_TOGGLE_OPTION) if (strcmp(argv[i], "--entry-point") == 0) { argv[i] = NULL; diff --git a/src/driver/cli.h b/src/driver/cli.h new file mode 100644 index 000000000..908eb5808 --- /dev/null +++ b/src/driver/cli.h @@ -0,0 +1,15 @@ +#ifndef CLI_H +#define CLI_H + +#include + +#define PARSE_TOGGLE_OPTION(f, name) \ +if (strcmp(argv[i], "--no-"#name) == 0) { \ + f = false; argv[i] = NULL; continue; \ +} else if (strcmp(argv[i], "--"#name) == 0) { \ + f = true; argv[i] = NULL; continue; \ +} + +void cli_pack_remaining_args(int* pargc, char** argv); + +#endif CLI_H diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index 90cd98029..9566d87a9 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(runtime runtime.c runtime_program.c) +add_library(runtime runtime.c runtime_program.c runtime_cli.c) target_link_libraries(runtime PUBLIC driver) set_target_properties(runtime PROPERTIES OUTPUT_NAME "shady_runtime") diff --git a/src/runtime/runtime_cli.c b/src/runtime/runtime_cli.c new file mode 100644 index 000000000..27b78e771 --- /dev/null +++ b/src/runtime/runtime_cli.c @@ -0,0 +1,47 @@ +#include "runtime_private.h" +#include "driver/cli.h" + +#include "common/log.h" + +RuntimeConfig default_runtime_config() { + return (RuntimeConfig) { +#ifndef NDEBUG + .dump_spv = true, + .use_validation = true, +#endif + }; +} + +#define DRIVER_CONFIG_OPTIONS(F) \ +F(config->use_validation, api-validation) \ +F(config->dump_spv, dump-spv) \ + +void cli_parse_runtime_config(RuntimeConfig* config, int* pargc, char** argv) { + int argc = *pargc; + + bool help = false; + for (int i = 1; i < argc; i++) { + + DRIVER_CONFIG_OPTIONS(PARSE_TOGGLE_OPTION) + + if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + help = true; + continue; + } else { + continue; + } + argv[i] = NULL; + } + + if (help) { + // error_print("Usage: slim source.slim\n"); + // error_print("Available arguments: \n"); + error_print(" --target \n"); + error_print(" --output , -o \n"); + error_print(" --dump-cfg Dumps the control flow graph of the final IR\n"); + error_print(" --dump-loop-tree \n"); + error_print(" --dump-ir Dumps the final IR\n"); + } + + cli_pack_remaining_args(pargc, argv); +} \ No newline at end of file diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 4e1bbba30..0b20b7894 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -32,13 +32,11 @@ int main(int argc, char* argv[]) { set_log_level(INFO); Args args = { .driver_config = default_driver_config(), - }; - args.runtime_config = (RuntimeConfig) { - .use_validation = true, - .dump_spv = true, + .runtime_config = default_runtime_config(), }; cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); cli_parse_common_args(&argc, argv); + cli_parse_runtime_config(&args.runtime_config, &argc, argv); cli_parse_compiler_config_args(&args.driver_config.config, &argc, argv); cli_parse_input_files(args.driver_config.input_filenames, &argc, argv); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 32b9719a6..3e15e646f 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -357,7 +357,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { BodyBuilder* if_builder = begin_body(a); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); - bind_instruction(if_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: thread %d:%d will run fn %d with mask = %lx\n" }), sid, local_id, fn_lit, next_mask) })); + bind_instruction(if_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: thread %d:%d will run fn %ul with mask = %lx\n" }), sid, local_id, fn_lit, next_mask) })); } bind_instruction(if_builder, call(a, (Call) { .callee = fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), diff --git a/test/driver/test_scalarisation_loop.slim b/test/driver/test_scalarisation_loop.slim index ef9afc4af..dc0ebf364 100644 --- a/test/driver/test_scalarisation_loop.slim +++ b/test/driver/test_scalarisation_loop.slim @@ -1,4 +1,7 @@ -@EntryPoint("compute") @WorkgroupSize(64, 1, 1) fn main() { +@Internal @Builtin("SubgroupLocalInvocationId") +var input u32 subgroup_local_id; + +@EntryPoint("Compute") @WorkgroupSize(32, 1, 1) fn main() { val tid = subgroup_local_id; val x = tid / u32 4; debug_printf("tid = %d x = %d\n", tid, x); From 4fe8978236ccc7ac87cf96584931f9e9803d969a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 11:29:58 +0200 Subject: [PATCH 206/693] misc cleanup --- include/shady/driver.h | 2 ++ samples/aobench/ao_main.c | 3 +-- src/common/CMakeLists.txt | 2 +- src/shady/node.c | 4 ++-- src/shady/passes/lift_indirect_targets.c | 13 ++----------- src/shady/rewrite.c | 7 +++++++ src/shady/rewrite.h | 2 ++ 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/include/shady/driver.h b/include/shady/driver.h index b67cee362..b89e96462 100644 --- a/include/shady/driver.h +++ b/include/shady/driver.h @@ -39,6 +39,8 @@ typedef enum { CodegenTarget guess_target(const char* filename); +void cli_pack_remaining_args(int* pargc, char** argv); + // parses 'common' arguments such as log level etc void cli_parse_common_args(int* pargc, char** argv); // parses compiler pipeline options diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index d2dd5e228..ef6d759cc 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -146,10 +146,9 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri uint64_t tpn = timespec_to_nano(tp); info_print("device rendering took %dus (gpu time: %dus)\n", (tpn - tsn) / 1000, profiled_gpu_time / 1000); - debug_print("data %d\n", (int) img[0]); - if (!import_memory) copy_from_buffer(buf, 0, img, sizeof(*img) * WIDTH * HEIGHT * 3); + debug_print("data %d\n", (int) img[0]); destroy_buffer(buf); shutdown_runtime(runtime); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index bb2735e87..e26da894d 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(common STATIC list.c dict.c log.c portability.c util.c growy.c arena.c printer.c) +add_library(common list.c dict.c log.c portability.c util.c growy.c arena.c printer.c) target_link_libraries(common PRIVATE "$") set_property(TARGET common PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/shady/node.c b/src/shady/node.c index 203e16e6b..0688fcfcb 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -17,10 +17,10 @@ String get_value_name(const Node* v) { String get_value_name_safe(const Node* v) { String name = get_value_name(v); - if (name) + if (name && strlen(name) > 0) return name; if (v->tag == Variable_TAG) - return format_string_interned(v->arena, "v%d", v->id); + return format_string_interned(v->arena, "%%%d", v->id); return node_tags[v->tag]; } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 6d58b6d76..ef24b3e7d 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -100,14 +100,13 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_node); struct List* recover_context = new_list(const Node*); - // add_to_recover_context(recover_context, node_vars->free_set, cont); add_to_recover_context(recover_context, node_vars->bound_set, cont); size_t recover_context_size = entries_count_list(recover_context); debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", name, recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { const Node* item = read_list(const Node*, recover_context)[i]; - debugv_print(get_value_name_safe(item)); + debugv_print("%s %%%d", get_value_name(item) ? get_value_name(item) : "", item->id); if (i + 1 < recover_context_size) debugv_print(", "); } @@ -122,13 +121,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name insert_dict(const Node*, LiftedCont*, ctx->lifted, cont, lifted_cont); Context lifting_ctx = *ctx; - // struct Dict* old_map = lifting_ctx.rewriter.map; - // lifting_ctx.rewriter.map = clone_dict(lifting_ctx.rewriter.map); - - // lifting_ctx.rewriter = create_rewriter(ctx->rewriter.src_module, ctx->rewriter.dst_module, (RewriteNodeFn) process_node); - // lifting_ctx.rewriter.decls_map = NULL; - lifting_ctx.rewriter.map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); - lifting_ctx.rewriter.parent = &ctx->rewriter; + lifting_ctx.rewriter = create_children_rewriter(&ctx->rewriter); register_processed_list(&lifting_ctx.rewriter, oparams, new_params); const Node* payload = var(a, qualified_type_helper(uint32_type(a), false), "sp"); @@ -160,9 +153,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name } const Node* substituted = rewrite_node(&lifting_ctx.rewriter, obody); - //destroy_dict(lifting_ctx.rewriter.processed); destroy_rewriter(&lifting_ctx.rewriter); - // lifting_ctx.rewriter.map = old_map; assert(is_terminator(substituted)); new_fn->payload.fun.body = finish_body(bb, substituted); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index f7b347c03..2ad0249a9 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -50,6 +50,13 @@ Module* rebuild_module(Module* src) { return dst; } +Rewriter create_children_rewriter(Rewriter* parent) { + Rewriter r = *parent; + r.map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + r.parent = parent; + return r; +} + const Node* rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNodeFn fn) { assert(rewriter->rewrite_fn); if (!node) diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index 315e2f4ee..af7e10211 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -48,6 +48,8 @@ Rewriter create_rewriter(Module* src, Module* dst, RewriteNodeFn fn); Rewriter create_importer(Module* src, Module* dst); Module* rebuild_module(Module*); Rewriter create_substituter(Module* arena); + +Rewriter create_children_rewriter(Rewriter* parent); void destroy_rewriter(Rewriter*); void rewrite_module(Rewriter*); From 56870b7beb0e2942c85d28ffb32b695df6104bfa Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 11:30:13 +0200 Subject: [PATCH 207/693] fix some ptr issues --- src/shady/emit/c/emit_c_instructions.c | 2 +- src/shady/passes/opt_mem2reg.c | 3 +++ src/shady/type.c | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 32fddb15e..1657a90af 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -349,7 +349,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct // this means such code is never going to be legal in GLSL // also the cast is to account for our arrays-in-structs hack const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); - acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &%s)", emit_type(emitter, curr_ptr_type, NULL), index_into_array(emitter, pointee_type, acc, offset))); + acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &(%s)[%s])", emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); uniform &= is_qualified_type_uniform(prim_op->operands.nodes[1]->type); } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 223aa2dc3..7fce26a1a 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -352,6 +352,9 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No // } return prim_op_helper(a, load_op, empty(a), singleton(rewrite_node(r, optr))); } + // case memcpy_op: { + // const Node* optr = first(payload.operands); + // } case store_op: { const Node* optr = first(payload.operands); PtrKnowledge* k = find_or_create_ptr_knowledge_for_updating(ctx, kb, optr, true); diff --git a/src/shady/type.c b/src/shady/type.c index 6da9ed2a5..fe7556c1d 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -802,6 +802,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const IntLiteral* lit = resolve_to_int_literal(offset); bool offset_is_zero = lit && lit->value == 0; assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); + assert(offset_is_zero || is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); uniform &= offset_uniform; Nodes indices = nodes(arena, prim_op.operands.count - 2, &prim_op.operands.nodes[2]); @@ -1036,7 +1037,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case get_stack_base_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 0); - const Node* ptr = ptr_type(arena, (PtrType) { .pointed_type = arr_type(arena, (ArrType) { .element_type = uint8_type(arena), .size = NULL }), .address_space = AsPrivate}); + const Node* ptr = ptr_type(arena, (PtrType) { .pointed_type = uint8_type(arena), .address_space = AsPrivate}); return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = ptr }); } case set_stack_pointer_op: { From 27876afdd04b7fa4230ab0d51abe0f2dcad74232 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 14:19:21 +0200 Subject: [PATCH 208/693] rename stack size primops --- include/shady/primops.json | 4 ++-- src/shady/passes/lift_indirect_targets.c | 4 ++-- src/shady/passes/lower_alloca.c | 4 ++-- src/shady/passes/lower_stack.c | 4 ++-- src/shady/passes/setup_stack_frames.c | 4 ++-- src/shady/type.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index 3a7dfcd0a..3494fd0f1 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -197,7 +197,7 @@ "side-effects": true }, { - "name": "get_stack_pointer", + "name": "get_stack_size", "class": "stack" }, { @@ -205,7 +205,7 @@ "class": "stack" }, { - "name": "set_stack_pointer", + "name": "set_stack_size", "class": "stack", "side-effects": true }, diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index ef24b3e7d..64ef9b85c 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -64,7 +64,7 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, struct L bind_instruction(builder, save_instruction); } - const Node* sp = gen_primop_ce(builder, get_stack_pointer_op, 0, NULL); + const Node* sp = gen_primop_ce(builder, get_stack_size_op, 0, NULL); return sp; } @@ -134,7 +134,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name // Recover that stuff inside the new body BodyBuilder* bb = begin_body(a); - gen_primop(bb, set_stack_pointer_op, empty(a), singleton(payload)); + gen_primop(bb, set_stack_size_op, empty(a), singleton(payload)); for (size_t i = recover_context_size - 1; i < recover_context_size; i--) { const Node* ovar = read_list(const Node*, recover_context)[i]; assert(ovar->tag == Variable_TAG); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 0814ff6fd..c1c462354 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -142,7 +142,7 @@ static const Node* process(Context* ctx, const Node* node) { if (!ctx->entry_stack_offset) { //String tmp_name = format_string_arena(a->arena, "stack_ptr_before_alloca_%s", get_abstraction_name(fun)); String tmp_name = "stack_ptr_before_alloca"; - ctx->entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_pointer_op } ), (String []) { tmp_name })); + ctx->entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_size_op } ), (String []) { tmp_name })); } //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); @@ -154,7 +154,7 @@ static const Node* process(Context* ctx, const Node* node) { //bool last = found_slot->i == ctx->num_slots - 1; //if (last) { const Node* updated_stack_ptr = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->entry_stack_offset, ctx->frame_size)); - gen_primop(bb, set_stack_pointer_op, empty(a), singleton(updated_stack_ptr)); + gen_primop(bb, set_stack_size_op, empty(a), singleton(updated_stack_ptr)); //} return yield_values_and_wrap_in_block(bb, singleton(slot)); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 200049eb3..d745c6a4f 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -100,13 +100,13 @@ static const Node* process_let(Context* ctx, const Node* node) { if (old_instruction->tag == PrimOp_TAG) { const PrimOp* oprim_op = &old_instruction->payload.prim_op; switch (oprim_op->op) { - case get_stack_pointer_op: { + case get_stack_size_op: { assert(ctx->stack); BodyBuilder* bb = begin_body(a); const Node* sp = gen_load(bb, ctx->stack_pointer); return finish_body(bb, let(a, quote_helper(a, singleton(sp)), tail)); } - case set_stack_pointer_op: { + case set_stack_size_op: { assert(ctx->stack); BodyBuilder* bb = begin_body(a); const Node* val = rewrite_node(&ctx->rewriter, oprim_op->operands.nodes[0]); diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 697d18fd6..a8eb18211 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -35,7 +35,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); if (!ctx2.disable_lowering) { - ctx2.entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_pointer_op } ), (String []) {format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun)) })); + ctx2.entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_size_op } ), (String []) {format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun)) })); } if (node->payload.fun.body) fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); @@ -49,7 +49,7 @@ static const Node* process(Context* ctx, const Node* node) { assert(ctx->entry_stack_offset); // Restore SP before calling exit bind_instruction(bb, prim_op(a, (PrimOp) { - .op = set_stack_pointer_op, + .op = set_stack_size_op, .operands = nodes(a, 1, (const Node* []) {ctx->entry_stack_offset }) })); } diff --git a/src/shady/type.c b/src/shady/type.c index fe7556c1d..082211ed8 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1029,7 +1029,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { return qualified_type(arena, (QualifiedType) { .type = join_point_type(arena, (JoinPointType) { .yield_types = empty(arena) }), .is_uniform = true }); } // Stack stuff - case get_stack_pointer_op: { + case get_stack_size_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 0); return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = uint32_type(arena) }); @@ -1040,7 +1040,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Node* ptr = ptr_type(arena, (PtrType) { .pointed_type = uint8_type(arena), .address_space = AsPrivate}); return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = ptr }); } - case set_stack_pointer_op: { + case set_stack_size_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); assert(get_unqualified_type(prim_op.operands.nodes[0]->type) == uint32_type(arena)); From 72f1191837d1a79e899ea45f315168c7d38407d6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 14:19:31 +0200 Subject: [PATCH 209/693] fix debugprintf in l2s --- src/frontends/llvm/l2s_postprocess.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index faef21797..c67b99a22 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -109,6 +109,22 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, new->payload.constant.instruction = yield_values_and_wrap_in_block(bb, singleton(value)); return new; } + case PrimOp_TAG: { + Nodes old_operands = node->payload.prim_op.operands; + switch (node->payload.prim_op.op) { + case debug_printf_op: { + Nodes new_operands = rewrite_nodes(r, old_operands); + String lit = get_string_literal(a, old_operands.nodes[0]); + assert(lit && "debug_printf requires a string literal"); + new_operands = change_node_at_index(a, new_operands, 0, string_lit_helper(a, lit)); + // for (size_t i = 1; i < old_operands.count; i++) + // new_operands[i] = infer(ctx, old_operands.nodes[i], NULL); + return prim_op_helper(a, debug_printf_op, empty(a), new_operands); + } + default: break; + } + break; + } case Function_TAG: { Context fn_ctx = *ctx; fn_ctx.curr_scope = new_scope(node); From d1122d5cf17d5a24f81a9121bcd0a75934016295 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 14:19:41 +0200 Subject: [PATCH 210/693] cuda: skip compilation when overriding PTX file --- src/runtime/cuda/cuda_runtime_program.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 68036539f..828b3b60b 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -36,6 +36,12 @@ static bool emit_cuda_c_code(CudaKernel* spec) { } static bool cuda_c_to_ptx(CudaKernel* kernel) { + String override_file = getenv("SHADY_OVERRIDE_PTX"); + if (override_file) { + read_file(override_file, &kernel->ptx_size, &kernel->ptx); + return true; + } + nvrtcProgram program; CHECK_NVRTC(nvrtcCreateProgram(&program, kernel->cuda_code, kernel->key.entry_point, 0, NULL, NULL), return false); @@ -68,11 +74,6 @@ static bool cuda_c_to_ptx(CudaKernel* kernel) { CHECK_NVRTC(nvrtcGetPTX(program, kernel->ptx), return false); CHECK_NVRTC(nvrtcDestroyProgram(&program), return false); - String override_file = getenv("SHADY_OVERRIDE_PTX"); - if (override_file) { - read_file(override_file, &kernel->ptx_size, &kernel->ptx); - } - if (get_log_level() <= DEBUG) write_file("cuda_dump.ptx", kernel->ptx_size - 1, kernel->ptx); From 29672343e58a7abc77e49586738b575d9f9f346c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 14:20:05 +0200 Subject: [PATCH 211/693] cuda: emit is_first/broadcast_first --- src/shady/emit/c/cuda_builtins.cu | 17 +++++++++++++++++ src/shady/emit/c/emit_c_instructions.c | 8 ++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/shady/emit/c/cuda_builtins.cu b/src/shady/emit/c/cuda_builtins.cu index 38a7c2ec2..2a4c6eea7 100644 --- a/src/shady/emit/c/cuda_builtins.cu +++ b/src/shady/emit/c/cuda_builtins.cu @@ -12,3 +12,20 @@ __device__ void __shady_prepare_builtins() { GlobalInvocationId.arr[1] = threadIdx.y + blockDim.y * blockIdx.y; GlobalInvocationId.arr[2] = threadIdx.z + blockDim.z * blockIdx.z; } + +__device__ bool __shady_elect_first() { + unsigned int writemask = __activemask(); + // Find the lowest-numbered active lane + int elected_lane = __ffs(writemask) - 1; + return threadIdx.x == __shfl_sync(writemask, threadIdx.x, elected_lane) + && threadIdx.y == __shfl_sync(writemask, threadIdx.y, elected_lane) + && threadIdx.z == __shfl_sync(writemask, threadIdx.z, elected_lane); +} + +template +__device__ T __shady_broadcast_first(T t) { + unsigned int writemask = __activemask(); + // Find the lowest-numbered active lane + int elected_lane = __ffs(writemask) - 1; + return __shfl_sync(writemask, t, elected_lane); +} diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 1657a90af..e9299acf1 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -618,13 +618,13 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case get_stack_base_op: case push_stack_op: case pop_stack_op: - case get_stack_pointer_op: - case set_stack_pointer_op: error("Stack operations need to be lowered."); + case get_stack_size_op: + case set_stack_size_op: error("Stack operations need to be lowered."); case default_join_point_op: case create_joint_point_op: error("lowered in lower_tailcalls.c"); case subgroup_elect_first_op: { switch (emitter->config.dialect) { - case CDialect_CUDA: error("TODO") + case CDialect_CUDA: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_elect_first()")); break; case CDialect_ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); break; case CDialect_C11: case CDialect_GLSL: error("TODO") @@ -641,7 +641,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case subgroup_broadcast_first_op: { CValue value = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); switch (emitter->config.dialect) { - case CDialect_CUDA: error("TODO") + case CDialect_CUDA: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; case CDialect_ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; case CDialect_C11: case CDialect_GLSL: error("TODO") From d5bbedf5e74d7a51360351a63cb806f4ee730224 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 14:20:21 +0200 Subject: [PATCH 212/693] lower_subgroup_ops: deal with ptrs --- src/shady/passes/lower_subgroup_ops.c | 34 +++++++++++++++++---------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 98045e369..755f6ab2f 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -41,9 +41,8 @@ static bool is_supported_natively(Context* ctx, const Type* element_type) { static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* src); -static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* t) { +static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* t, const Node* param) { IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* bb = begin_body(a); const Type* original_t = t; t = get_maybe_nominal_type_body(t); switch (is_type(t)) { @@ -56,11 +55,7 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* const Node* e = gen_extract(bb, param, singleton(uint32_literal(a, i))); elements[i] = build_subgroup_first(ctx, bb, e); } - fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { - .fn = fn, - .args = singleton(composite_helper(a, original_t, nodes(a, element_types.count, elements))) - })); - return; + return composite_helper(a, original_t, nodes(a, element_types.count, elements)); } case Type_Int_TAG: { if (t->payload.int_type.width == IntTy64) { @@ -73,17 +68,30 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* hi = convert_int_zero_extend(bb, it, hi); lo = convert_int_zero_extend(bb, it, lo); hi = gen_primop_e(bb, lshift_op, empty(a), mk_nodes(a, hi, int32_literal(a, 32))); - const Node* result = gen_primop_e(bb, or_op, empty(a), mk_nodes(a, lo, hi)); - fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { - .fn = fn, - .args = singleton(result) - })); - return; + return gen_primop_e(bb, or_op, empty(a), mk_nodes(a, lo, hi)); } break; } + case Type_PtrType_TAG: { + param = gen_reinterpret_cast(bb, uint64_type(a), param); + return gen_reinterpret_cast(bb, t, generate(ctx, bb, uint64_type(a), param)); + } default: break; } + return NULL; +} + +static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* t) { + IrArena* a = ctx->rewriter.dst_arena; + BodyBuilder* bb = begin_body(a); + const Node* result = generate(ctx, bb, t, param); + if (result) { + fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { + .fn = fn, + .args = singleton(result) + })); + return; + } log_string(ERROR, "subgroup_first emulation is not supported for "); log_node(ERROR, t); From d6139bf1b6928e2ce53986609c3b1e2744f63bfd Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Apr 2024 18:16:22 +0200 Subject: [PATCH 213/693] fix fn pointers and global data --- src/frontends/llvm/l2s_instr.c | 11 +++- src/frontends/llvm/l2s_type.c | 2 +- src/runtime/vulkan/vk_runtime_program.c | 64 ++++++++++++++++++++-- src/shady/analysis/callgraph.c | 36 ++++++++++-- src/shady/analysis/callgraph.h | 1 + src/shady/passes/lower_callf.c | 14 +++++ src/shady/passes/mark_leaf_functions.c | 22 +++++++- src/shady/passes/spirv_lift_globals_ssbo.c | 2 +- 8 files changed, 136 insertions(+), 16 deletions(-) diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index 4a2467eea..515931448 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -452,13 +452,18 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM LLVMValueRef callee = LLVMGetCalledValue(instr); callee = remove_ptr_bitcasts(p, callee); assert(num_args + 1 == num_ops); - String intrinsic = is_llvm_intrinsic(callee); - if (!intrinsic) - intrinsic = is_shady_intrinsic(callee); + String intrinsic = NULL; + if (LLVMIsAFunction(callee) || LLVMIsAConstant(callee)) { + intrinsic = is_llvm_intrinsic(callee); + if (!intrinsic) + intrinsic = is_shady_intrinsic(callee); + } if (intrinsic) { assert(LLVMIsAFunction(callee)); if (strcmp(intrinsic, "llvm.dbg.declare") == 0) { const Node* target = convert_value(p, LLVMGetOperand(instr, 0)); + if (target->tag != Variable_TAG) + return (EmittedInstr) { 0 }; assert(target->tag == Variable_TAG); const Node* meta = convert_value(p, LLVMGetOperand(instr, 1)); assert(meta->tag == RefDecl_TAG); diff --git a/src/frontends/llvm/l2s_type.c b/src/frontends/llvm/l2s_type.c index b5dc81b08..7ca93031b 100644 --- a/src/frontends/llvm/l2s_type.c +++ b/src/frontends/llvm/l2s_type.c @@ -36,7 +36,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { LLVMGetParamTypes(t, param_types); LARRAY(const Type*, cparam_types, num_params); for (size_t i = 0; i < num_params; i++) - cparam_types[i] = convert_type(p, param_types[i]); + cparam_types[i] = qualified_type_helper(convert_type(p, param_types[i]), false); const Type* ret_type = convert_type(p, LLVMGetReturnType(t)); if (LLVMGetTypeKind(LLVMGetReturnType(t)) == LLVMVoidTypeKind) ret_type = empty_multiple_return_type(a); diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 7dd44194e..a18960fdd 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -8,6 +8,7 @@ #include "arena.h" #include "util.h" +#include "type.h" #include "../../shady/transform/memory_layout.h" @@ -42,6 +43,46 @@ VkDescriptorType as_to_descriptor_type(AddressSpace as) { } } +static void write_value(unsigned char* tgt, const Node* value) { + IrArena* a = value->arena; + switch (value->tag) { + case IntLiteral_TAG: { + switch (value->payload.int_literal.width) { + case IntTy8: *((uint8_t*) tgt) = (uint8_t) (value->payload.int_literal.value & 0xFF); break; + case IntTy16: *((uint16_t*) tgt) = (uint16_t) (value->payload.int_literal.value & 0xFFFF); break; + case IntTy32: *((uint32_t*) tgt) = (uint32_t) (value->payload.int_literal.value & 0xFFFFFFFF); break; + case IntTy64: *((uint64_t*) tgt) = (uint64_t) (value->payload.int_literal.value); break; + } + break; + } + case Composite_TAG: { + Nodes values = value->payload.composite.contents; + const Type* struct_t = value->payload.composite.type; + struct_t = get_maybe_nominal_type_body(struct_t); + + if (struct_t->tag == RecordType_TAG) { + LARRAY(FieldLayout, fields, values.count); + get_record_layout(a, struct_t, fields); + for (size_t i = 0; i < values.count; i++) { + // TypeMemLayout layout = get_mem_layout(value->arena, get_unqualified_type(element->type)); + write_value(tgt + fields->offset_in_bytes, values.nodes[i]); + } + } else if (struct_t->tag == ArrType_TAG) { + for (size_t i = 0; i < values.count; i++) { + TypeMemLayout layout = get_mem_layout(value->arena, get_unqualified_type(values.nodes[i]->type)); + write_value(tgt, values.nodes[i]); + tgt += layout.size_in_bytes; + } + } else { + assert(false); + } + break; + } + default: + assert(false); + } +} + static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLayout layouts[]) { VkDescriptorSetLayoutCreateInfo layout_create_infos[MAX_DESCRIPTOR_SETS] = { 0 }; Growy* bindings_lists[MAX_DESCRIPTOR_SETS] = { 0 }; @@ -78,6 +119,8 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay for (size_t j = 0; j < struct_t->payload.record_type.members.count; j++) { const Type* member_t = struct_t->payload.record_type.members.nodes[j]; + assert(member_t->tag == PtrType_TAG); + member_t = get_pointee_type(program->arena, member_t); TypeMemLayout layout = get_mem_layout(program->specialized_module->arena, member_t); ProgramResourceInfo* constant_res_info = arena_alloc(program->arena, sizeof(ProgramResourceInfo)); @@ -93,6 +136,15 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay res_info->size += sizeof(void*); // TODO initial value + Nodes annotations = get_declaration_annotations(decl); + for (size_t k = 0; k < annotations.count; k++) { + const Node* a = annotations.nodes[k]; + if ((strcmp(get_annotation_name(a), "InitialValue") == 0) && resolve_to_int_literal(first(get_annotation_values(a)))->value == j) { + constant_res_info->default_data = calloc(1, layout.size_in_bytes); + write_value(constant_res_info->default_data, get_annotation_values(a).nodes[1]); + //printf("wowie"); + } + } } if (vkr_can_import_host_memory(program->device)) @@ -394,11 +446,13 @@ static bool prepare_resources(VkrSpecProgram* program) { resource->buffer = allocate_buffer_device(program->device, resource->size); } - // TODO: initial data! - // if (!resource->host_owned) - char* zeroes = calloc(1, resource->size); - copy_to_buffer(resource->buffer, 0, zeroes, resource->size); - free(zeroes); + if (resource->default_data) { + copy_to_buffer(resource->buffer, 0, resource->default_data, resource->size); + } else { + char* zeroes = calloc(1, resource->size); + copy_to_buffer(resource->buffer, 0, zeroes, resource->size); + free(zeroes); + } if (resource->parent) { char* dst = resource->parent->host_ptr; diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index 69f3f7e6a..78bcee923 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -38,7 +38,10 @@ static const Node* ignore_immediate_fn_addr(const Node* node) { return node; } +static CGNode* analyze_fn(CallGraph* graph, const Node* fn); + static void visit_callsite(CGVisitor* visitor, const Node* callee, const Node* instr) { + assert(visitor->root); assert(callee->tag == Function_TAG); CGNode* target = analyze_fn(visitor->graph, callee); // Immediate recursion @@ -55,10 +58,11 @@ static void visit_callsite(CGVisitor* visitor, const Node* callee, const Node* i } static void search_for_callsites(CGVisitor* visitor, const Node* node) { - assert(is_abstraction(visitor->abs)); + assert((visitor->abs && is_abstraction(visitor->abs)) || !visitor->root); switch (node->tag) { case Function_TAG: { assert(false); + // analyze_fn(visitor->graph, node)->is_address_captured = true; break; } case BasicBlock_TAG: @@ -74,12 +78,15 @@ static void search_for_callsites(CGVisitor* visitor, const Node* node) { break; } case Call_TAG: { + assert(visitor->root && "calls can only occur in functions"); const Node* callee = node->payload.call.callee; callee = ignore_immediate_fn_addr(callee); if (callee->tag == Function_TAG) visit_callsite(visitor, callee, node); - else + else { + visitor->root->calls_indirect = true; visit_op(&visitor->visitor, NcValue, "callee", callee); + } visit_ops(&visitor->visitor, NcValue, "args", node->payload.call.args); break; } @@ -216,8 +223,29 @@ CallGraph* new_callgraph(Module* mod) { Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) { - if (decls.nodes[i]->tag == Function_TAG) { - analyze_fn(graph, decls.nodes[i]); + const Node* decl = decls.nodes[i]; + if (decl->tag == Function_TAG) { + analyze_fn(graph, decl); + } else if (decl->tag == GlobalVariable_TAG && decl->payload.global_variable.init) { + CGVisitor v = { + .visitor = { + .visit_node_fn = (VisitNodeFn) search_for_callsites + }, + .graph = graph, + .root = NULL, + .abs = NULL, + }; + search_for_callsites(&v, decl->payload.global_variable.init); + } else if (decl->tag == Constant_TAG && decl->payload.constant.instruction) { + CGVisitor v = { + .visitor = { + .visit_node_fn = (VisitNodeFn) search_for_callsites + }, + .graph = graph, + .root = NULL, + .abs = NULL, + }; + search_for_callsites(&v, decl->payload.constant.instruction); } } diff --git a/src/shady/analysis/callgraph.h b/src/shady/analysis/callgraph.h index 13fd9bfcb..b28d989c3 100644 --- a/src/shady/analysis/callgraph.h +++ b/src/shady/analysis/callgraph.h @@ -24,6 +24,7 @@ struct CGNode_ { bool is_recursive; /// set to true if the address of this is captured by a FnAddr node that is not immediately consumed by a call bool is_address_captured; + bool calls_indirect; }; typedef struct Callgraph_ { diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 0a6c005b0..940c1dbda 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -24,6 +24,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { if (found) return found; IrArena* a = ctx->rewriter.dst_arena; Module* m = ctx->rewriter.dst_module; + Rewriter* r = &ctx->rewriter; if (old->tag == Function_TAG) { Context ctx2 = *ctx; @@ -67,6 +68,19 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { return recreate_node_identity(&ctx->rewriter, old); switch (old->tag) { + case FnType_TAG: { + Nodes param_types = rewrite_nodes(r, old->payload.fn_type.param_types); + Nodes returned_types = rewrite_nodes(&ctx->rewriter, old->payload.fn_type.return_types); + const Type* jp_type = qualified_type(a, (QualifiedType) { + .type = join_point_type(a, (JoinPointType) { .yield_types = strip_qualifiers(a, returned_types) }), + .is_uniform = false + }); + param_types = append_nodes(a, param_types, jp_type); + return fn_type(a, (FnType) { + .param_types = param_types, + .return_types = empty(a), + }); + } case Return_TAG: { Nodes nargs = rewrite_nodes(&ctx->rewriter, old->payload.fn_ret.args); diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index 101109359..3925b4171 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -47,10 +47,28 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { info = find_value_dict(const Node*, FnInfo, ctx->fns, fn_node->fn); assert(info); - if (fn_node->is_address_captured || fn_node->is_recursive) { + if (fn_node->is_address_captured || fn_node->is_recursive || fn_node->calls_indirect) { info->is_leaf = false; info->done = true; - debugv_print("Function %s can't be a leaf function because %s.\n", get_abstraction_name(fn_node->fn), fn_node->is_address_captured ? "its address is captured" : "it is recursive" ); + debugv_print("Function %s can't be a leaf function because", get_abstraction_name(fn_node->fn)); + bool and = false; + if (fn_node->is_address_captured) { + debugv_print("its address is captured"); + and = true; + } + if (fn_node->is_recursive) { + if (and) + debugv_print(" and "); + debugv_print("it is recursive"); + and = true; + } + if (fn_node->calls_indirect) { + if (and) + debugv_print(" and "); + debugv_print("it makes indirect calls"); + and = true; + } + debugv_print(".\n"); return false; } diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index 9f9d79dec..4523b5025 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -104,7 +104,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) continue; if (odecl->payload.global_variable.init) - annotations = append_nodes(a, annotations, annotation_values(a, (AnnotationValues) { + ctx.lifted_globals_decl->payload.global_variable.annotations = append_nodes(a, ctx.lifted_globals_decl->payload.global_variable.annotations, annotation_values(a, (AnnotationValues) { .name = "InitialValue", .values = mk_nodes(a, int32_literal(a, lifted_globals_count), rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) })); From 6699d9bcd41ee0c1f4bee8c61c002ca24dda96f5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 19 Apr 2024 14:58:10 +0200 Subject: [PATCH 214/693] added lower_nullptr pass --- src/shady/CMakeLists.txt | 1 + src/shady/compile.c | 1 + src/shady/passes/lower_nullptr.c | 64 ++++++++++++++++++++++++++++++++ src/shady/passes/passes.h | 1 + 4 files changed, 67 insertions(+) create mode 100644 src/shady/passes/lower_nullptr.c diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index dda682a5d..5d6884b09 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -70,6 +70,7 @@ set(SHADY_SOURCES passes/lower_tailcalls.c passes/lower_mask.c passes/lower_fill.c + passes/lower_nullptr.c passes/lower_switch_btree.c passes/setup_stack_frames.c passes/eliminate_constants.c diff --git a/src/shady/compile.c b/src/shady/compile.c index f2b72fb59..011875717 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -151,6 +151,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { if (config->lower.simt_to_explicit_simd) RUN_PASS(simt2d) RUN_PASS(lower_fill) + RUN_PASS(lower_nullptr) RUN_PASS(normalize_builtins) return CompilationNoError; diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c new file mode 100644 index 000000000..ff76b72d5 --- /dev/null +++ b/src/shady/passes/lower_nullptr.c @@ -0,0 +1,64 @@ +#include "passes.h" + +#include "log.h" +#include "portability.h" +#include "dict.h" + +#include "../ir_private.h" +#include "../type.h" +#include "../rewrite.h" +#include "../transform/ir_gen_helpers.h" + +typedef struct { + Rewriter rewriter; + struct Dict* map; +} Context; + +static const Node* make_nullptr(Context* ctx, const Type* t) { + IrArena* a = ctx->rewriter.dst_arena; + const Node** found = find_value_dict(const Type*, const Node*, ctx->map, t); + if (found) + return *found; + + BodyBuilder* bb = begin_body(a); + const Node* nul = gen_reinterpret_cast(bb, t, uint64_literal(a, 0)); + Node* decl = constant(ctx->rewriter.dst_module, singleton(annotation(a, (Annotation) { + .name = "Generated", + })), t, format_string_interned(a, "nullptr_%s", name_type_safe(a, t))); + decl->payload.constant.instruction = yield_values_and_wrap_in_block(bb, singleton(nul)); + const Node* ref = ref_decl_helper(a, decl); + insert_dict(const Type*, const Node*, ctx->map, t, ref); + return ref; +} + +static const Node* process(Context* ctx, const Node* node) { + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + switch (node->tag) { + case NullPtr_TAG: { + const Type* t = rewrite_node(r, node->payload.null_ptr.ptr_type); + assert(t->tag == PtrType_TAG); + return make_nullptr(ctx, t); + } + default: break; + } + + return recreate_node_identity(&ctx->rewriter, node); +} + +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + +Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(aconfig); + Module* dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + }; + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + destroy_dict(ctx.map); + return dst; +} diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index fee940885..89b32ea53 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -98,6 +98,7 @@ RewritePass lower_int; RewritePass lower_vec_arr; RewritePass lower_workgroups; RewritePass lower_fill; +RewritePass lower_nullptr; /// @} From 0da4120b8d0dc506cbb8707af1ab5dd53c4a8770 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 19 Apr 2024 14:58:31 +0200 Subject: [PATCH 215/693] fix a few more spirv issues --- src/shady/emit/spirv/emit_spv_instructions.c | 27 ++++++++++++++------ src/shady/emit/spirv/emit_spv_type.c | 15 +++++++++-- src/shady/emit/spirv/spirv_builder.c | 15 +++++++++++ src/shady/emit/spirv/spirv_builder.h | 2 ++ src/shady/type.c | 2 +- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/shady/emit/spirv/emit_spv_instructions.c b/src/shady/emit/spirv/emit_spv_instructions.c index c830ea00d..ba48e6f95 100644 --- a/src/shady/emit/spirv/emit_spv_instructions.c +++ b/src/shady/emit/spirv/emit_spv_instructions.c @@ -79,12 +79,12 @@ static const IselTableEntry isel_table[] = { [neg_op] = {Plain, FirstOp, Same, .fo = {SpvOpSNegate, SpvOpSNegate, SpvOpFNegate }}, - [eq_op] = {Plain, FirstOp, Bool, .fo = {SpvOpIEqual, SpvOpIEqual, SpvOpFOrdEqual, SpvOpLogicalEqual }}, - [neq_op] = {Plain, FirstOp, Bool, .fo = {SpvOpINotEqual, SpvOpINotEqual, SpvOpFOrdNotEqual, SpvOpLogicalNotEqual }}, - [lt_op] = {Plain, FirstOp, Bool, .fo = {SpvOpSLessThan, SpvOpULessThan, SpvOpFOrdLessThan, ISEL_IDENTITY }}, - [lte_op] = {Plain, FirstOp, Bool, .fo = {SpvOpSLessThanEqual, SpvOpULessThanEqual, SpvOpFOrdLessThanEqual, ISEL_IDENTITY }}, - [gt_op] = {Plain, FirstOp, Bool, .fo = {SpvOpSGreaterThan, SpvOpUGreaterThan, SpvOpFOrdGreaterThan, ISEL_IDENTITY }}, - [gte_op] = {Plain, FirstOp, Bool, .fo = {SpvOpSGreaterThanEqual, SpvOpUGreaterThanEqual, SpvOpFOrdGreaterThanEqual, ISEL_IDENTITY }}, + [eq_op] = {Plain, FirstOp, Bool, .fo = {SpvOpIEqual, SpvOpIEqual, SpvOpFOrdEqual, SpvOpLogicalEqual, SpvOpPtrEqual }}, + [neq_op] = {Plain, FirstOp, Bool, .fo = {SpvOpINotEqual, SpvOpINotEqual, SpvOpFOrdNotEqual, SpvOpLogicalNotEqual, SpvOpPtrNotEqual }}, + [lt_op] = {Plain, FirstOp, Bool, .fo = {SpvOpSLessThan, SpvOpULessThan, SpvOpFOrdLessThan, ISEL_ILLEGAL, ISEL_ILLEGAL }}, + [lte_op] = {Plain, FirstOp, Bool, .fo = {SpvOpSLessThanEqual, SpvOpULessThanEqual, SpvOpFOrdLessThanEqual, ISEL_ILLEGAL, ISEL_ILLEGAL}}, + [gt_op] = {Plain, FirstOp, Bool, .fo = {SpvOpSGreaterThan, SpvOpUGreaterThan, SpvOpFOrdGreaterThan, ISEL_ILLEGAL, ISEL_ILLEGAL}}, + [gte_op] = {Plain, FirstOp, Bool, .fo = {SpvOpSGreaterThanEqual, SpvOpUGreaterThanEqual, SpvOpFOrdGreaterThanEqual, ISEL_ILLEGAL, ISEL_ILLEGAL }}, [not_op] = {Plain, FirstOp, Same, .fo = {SpvOpNot, SpvOpNot, ISEL_ILLEGAL, SpvOpLogicalNot }}, @@ -109,7 +109,7 @@ static const IselTableEntry isel_table[] = { { SpvOpBitcast, ISEL_ILLEGAL, SpvOpBitcast, ISEL_ILLEGAL, SpvOpConvertUToPtr }, { SpvOpBitcast, SpvOpBitcast, ISEL_IDENTITY, ISEL_ILLEGAL, ISEL_ILLEGAL /* no fp-ptr casts */ }, { ISEL_ILLEGAL, ISEL_ILLEGAL, ISEL_ILLEGAL, ISEL_IDENTITY, ISEL_ILLEGAL /* no bool reinterpret */ }, - { SpvOpConvertPtrToU, SpvOpConvertPtrToU, ISEL_ILLEGAL, ISEL_ILLEGAL, ISEL_IDENTITY } + { SpvOpConvertPtrToU, SpvOpConvertPtrToU, ISEL_ILLEGAL, ISEL_ILLEGAL, ISEL_CUSTOM } }}, [sqrt_op] = { Plain, Monomorphic, Same, .extended_set = "GLSL.std.450", .op = (SpvOp) GLSLstd450Sqrt }, @@ -195,7 +195,8 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui Nodes results_ts = unwrap_multiple_yield_types(emitter->arena, instr->type); SpvId result_t = results_ts.count >= 1 ? emit_type(emitter, instr->type) : emitter->void_t; - assert(opcode != SpvOpMax); + if (opcode == SpvOpMax) + goto custom; if (entry.extended_set) { SpvId set_id = get_extended_instruction_set(emitter, entry.extended_set); @@ -215,7 +216,17 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui return; } + + custom: switch (the_op.op) { + case reinterpret_op: { + const Type* dst = first(the_op.type_arguments); + const Type* src = get_unqualified_type(first(the_op.operands)->type); + assert(dst->tag == PtrType_TAG && src->tag == PtrType_TAG); + assert(src != dst); + results[0] = spvb_op(bb_builder, SpvOpBitcast, emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, bb_builder, first(the_op.operands)) }); + return; + } case subgroup_ballot_op: { const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = uint32_type(emitter->arena) }); SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); diff --git a/src/shady/emit/spirv/emit_spv_type.c b/src/shady/emit/spirv/emit_spv_type.c index cf3595156..389132ee0 100644 --- a/src/shady/emit/spirv/emit_spv_type.c +++ b/src/shady/emit/spirv/emit_spv_type.c @@ -144,9 +144,19 @@ SpvId emit_type(Emitter* emitter, const Type* type) { new = spvb_float_type(emitter->file_builder, width); break; } case PtrType_TAG: { - SpvId pointee = emit_type(emitter, type->payload.ptr_type.pointed_type); SpvStorageClass sc = emit_addr_space(emitter, type->payload.ptr_type.address_space); + const Type* pointed_type = type->payload.ptr_type.pointed_type; + if (get_maybe_nominal_type_decl(pointed_type) && sc == SpvStorageClassPhysicalStorageBuffer) { + new = spvb_forward_ptr_type(emitter->file_builder, sc); + insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, type, new); + SpvId pointee = emit_type(emitter, pointed_type); + spvb_ptr_type_define(emitter->file_builder, new, sc, pointee); + return new; + } + + SpvId pointee = emit_type(emitter, pointed_type); new = spvb_ptr_type(emitter->file_builder, sc, pointee); + //if (is_physical_as(type->payload.ptr_type.address_space) && type->payload.ptr_type.pointed_type->tag == ArrType_TAG) { // TypeMemLayout elem_mem_layout = get_mem_layout(emitter->arena, type->payload.ptr_type.pointed_type); // spvb_decorate(emitter->file_builder, new, SpvDecorationArrayStride, 1, (uint32_t[]) {elem_mem_layout.size_in_bytes}); @@ -193,8 +203,9 @@ SpvId emit_type(Emitter* emitter, const Type* type) { break; } new = spvb_fresh_id(emitter->file_builder); + insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, type, new); emit_nominal_type_body(emitter, type, new); - break; + return new; } case Type_TypeDeclRef_TAG: { new = emit_decl(emitter, type->payload.type_decl_ref.decl); diff --git a/src/shady/emit/spirv/spirv_builder.c b/src/shady/emit/spirv/spirv_builder.c index 419482c15..cdef57206 100644 --- a/src/shady/emit/spirv/spirv_builder.c +++ b/src/shady/emit/spirv/spirv_builder.c @@ -349,6 +349,21 @@ SpvId spvb_ptr_type(SpvbFileBuilder* file_builder, SpvStorageClass storage_class return id; } +SpvId spvb_forward_ptr_type(SpvbFileBuilder* file_builder, SpvStorageClass storage_class) { + op(SpvOpTypeForwardPointer, 3); + SpvId id = spvb_fresh_id(file_builder); + ref_id(id); + literal_int(storage_class); + return id; +} + +void spvb_ptr_type_define(SpvbFileBuilder* file_builder, SpvId id, SpvStorageClass storage_class, SpvId element_type) { + op(SpvOpTypePointer, 4); + ref_id(id); + literal_int(storage_class); + ref_id(element_type); +} + SpvId spvb_array_type(SpvbFileBuilder* file_builder, SpvId element_type, SpvId dim) { op(SpvOpTypeArray, 4); SpvId id = spvb_fresh_id(file_builder); diff --git a/src/shady/emit/spirv/spirv_builder.h b/src/shady/emit/spirv/spirv_builder.h index 6e8b74421..d769336a5 100644 --- a/src/shady/emit/spirv/spirv_builder.h +++ b/src/shady/emit/spirv/spirv_builder.h @@ -44,6 +44,8 @@ SpvId spvb_void_type(SpvbFileBuilder*); SpvId spvb_bool_type(SpvbFileBuilder*); SpvId spvb_int_type(SpvbFileBuilder*, int width, bool signed_); SpvId spvb_float_type(SpvbFileBuilder*, int width); +SpvId spvb_forward_ptr_type(SpvbFileBuilder*, SpvStorageClass storage_class); +void spvb_ptr_type_define(SpvbFileBuilder*, SpvId id, SpvStorageClass storage_class, SpvId element_type); SpvId spvb_ptr_type(SpvbFileBuilder*, SpvStorageClass storage_class, SpvId element_type); SpvId spvb_array_type(SpvbFileBuilder*, SpvId element_type, SpvId dim); SpvId spvb_runtime_array_type(SpvbFileBuilder*, SpvId element_type); diff --git a/src/shady/type.c b/src/shady/type.c index 082211ed8..a4c9d8de3 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -410,7 +410,7 @@ const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { const Node* maybe_record_type = ptr_type.pointed_type; if (maybe_record_type->tag == TypeDeclRef_TAG) maybe_record_type = get_nominal_type_body(maybe_record_type); - if (maybe_record_type->tag == RecordType_TAG && maybe_record_type->payload.record_type.special == DecorateBlock) { + if (maybe_record_type && maybe_record_type->tag == RecordType_TAG && maybe_record_type->payload.record_type.special == DecorateBlock) { return NULL; } assert(is_data_type(ptr_type.pointed_type)); From 7c4a114df50a3391cbe27d6c87d1bf8d5cd46d51 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Apr 2024 13:50:59 +0200 Subject: [PATCH 216/693] add config options for FetchContent and martty's llvm fixes --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4fd890e8..2aaf7a804 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,8 @@ set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) option(BUILD_SHARED_LIBS "Build using shared libraries" ON) +option(SHADY_USE_FETCHCONTENT "Use FetchContent to grab json-c" ON) +option(SHADY_WIN32_FIX_PARTIAL_LLVM_INSTALL "If you install LLVM on windows, it doesn't come with header files. This fixes it" ON) if (MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) @@ -22,7 +24,7 @@ endif() add_subdirectory(SPIRV-Headers) -if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24") +if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24" AND ${SHADY_USE_FETCHCONTENT}) FetchContent_Declare( json-c GIT_REPOSITORY https://github.com/json-c/json-c @@ -39,7 +41,7 @@ else () endif () find_package(LLVM QUIET) -if(NOT ${LLVM_FOUND} AND WIN32) +if(NOT ${LLVM_FOUND} AND WIN32 AND ${SHADY_WIN32_FIX_PARTIAL_LLVM_INSTALL}) find_program(clang_exe "clang.exe") if(${clang_exe} STREQUAL "clang_exe-NOTFOUND") message(STATUS "Win32: Installed LLVM not found") From e82df2af327c2bf068816cadb0b19c76ce2348e1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Apr 2024 14:52:33 +0200 Subject: [PATCH 217/693] l2s: support switchinst --- src/frontends/llvm/l2s_instr.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index 515931448..8e3ba42d1 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -140,12 +140,12 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM }) }; case LLVMBr: { - unsigned n_successors = LLVMGetNumSuccessors(instr); - LARRAY(LLVMBasicBlockRef , targets, n_successors); - for (size_t i = 0; i < n_successors; i++) + unsigned n_targets = LLVMGetNumSuccessors(instr); + LARRAY(LLVMBasicBlockRef, targets, n_targets); + for (size_t i = 0; i < n_targets; i++) targets[i] = LLVMGetSuccessor(instr, i); if (LLVMIsConditional(instr)) { - assert(n_successors == 2); + assert(n_targets == 2); const Node* condition = convert_value(p, LLVMGetCondition(instr)); return (EmittedInstr) { .terminator = branch(a, (Branch) { @@ -155,14 +155,31 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM }) }; } else { - assert(n_successors == 1); + assert(n_targets == 1); return (EmittedInstr) { .terminator = convert_jump(p, fn, fn_or_bb, targets[0]) }; } } - case LLVMSwitch: - goto unimplemented; + case LLVMSwitch: { + const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); + const Node* default_jump = convert_jump(p, fn, fn_or_bb, LLVMGetOperand(instr, 1)); + int n_targets = LLVMGetNumOperands(instr) / 2 - 1; + LARRAY(const Node*, targets, n_targets); + LARRAY(const Node*, literals, n_targets); + for (size_t i = 0; i < n_targets; i++) { + literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); + targets[i] = convert_jump(p, fn, fn_or_bb, LLVMGetOperand(instr, i * 2 + 3)); + } + return (EmittedInstr) { + .terminator = br_switch(a, (Switch) { + .switch_value = inspectee, + .default_jump = default_jump, + .case_values = nodes(a, n_targets, literals), + .case_jumps = nodes(a, n_targets, targets) + }) + }; + } case LLVMIndirectBr: goto unimplemented; case LLVMInvoke: From 2605935a4ce50df01404d457ca27e96ef979fb7f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Apr 2024 14:52:46 +0200 Subject: [PATCH 218/693] lift_indirect_targets: use assume_uniform instead of broadcast_first --- src/shady/passes/lift_indirect_targets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 64ef9b85c..0832c642b 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -147,7 +147,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name }), &ovar->payload.var.name)); if (is_qualified_type_uniform(ovar->type)) - recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_broadcast_first_op, .operands = singleton(recovered_value) }), &ovar->payload.var.name)); + recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }), &ovar->payload.var.name)); register_processed(&lifting_ctx.rewriter, ovar, recovered_value); } From 189814768a6b5f16122ab23dce9816cb2cf3a5bb Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Apr 2024 15:13:45 +0200 Subject: [PATCH 219/693] renamed 'scope.h' to 'cfg.h' --- include/shady/ir.h | 2 +- src/driver/driver.c | 2 +- src/frontends/llvm/l2s_postprocess.c | 12 +- src/shady/CMakeLists.txt | 4 +- src/shady/analysis/{scope.c => cfg.c} | 165 +++++++++--------- src/shady/analysis/{scope.h => cfg.h} | 45 ++--- .../analysis/{scope_dump.c => cfg_dump.c} | 44 ++--- src/shady/analysis/free_variables.c | 10 +- src/shady/analysis/free_variables.h | 6 +- src/shady/analysis/leak.h | 2 +- src/shady/analysis/looptree.c | 16 +- src/shady/analysis/looptree.h | 4 +- src/shady/analysis/uses.h | 2 +- src/shady/analysis/verify.c | 36 ++-- src/shady/emit/spirv/emit_spv.c | 26 +-- src/shady/passes/lift_indirect_targets.c | 28 +-- src/shady/passes/lower_cf_instrs.c | 12 +- src/shady/passes/lower_tailcalls.c | 20 +-- src/shady/passes/mark_leaf_functions.c | 20 +-- src/shady/passes/opt_demote_alloca.c | 16 +- src/shady/passes/opt_mem2reg.c | 30 ++-- src/shady/passes/reconvergence_heuristics.c | 52 +++--- src/shady/print.c | 30 ++-- src/shady/visit.c | 12 +- 24 files changed, 294 insertions(+), 302 deletions(-) rename src/shady/analysis/{scope.c => cfg.c} (75%) rename src/shady/analysis/{scope.h => cfg.h} (64%) rename src/shady/analysis/{scope_dump.c => cfg_dump.c} (83%) diff --git a/include/shady/ir.h b/include/shady/ir.h index d140336fc..10d4e08b2 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -347,7 +347,7 @@ typedef struct { void emit_c(CompilerConfig compiler_config, CEmitterConfig emitter_config, Module*, size_t* output_size, char** output, Module** new_mod); -void dump_cfg(FILE* file, Module*); +void dump_cfgs(FILE* output, Module* mod); void dump_loop_trees(FILE* output, Module* mod); void free_output(char* output); diff --git a/src/driver/driver.c b/src/driver/driver.c index 0e2176804..b008374f8 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -125,7 +125,7 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { if (args->cfg_output_filename) { FILE* f = fopen(args->cfg_output_filename, "wb"); assert(f); - dump_cfg(f, mod); + dump_cfgs(f, mod); fclose(f); debug_print("CFG dumped\n"); } diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index c67b99a22..71aec8269 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -7,13 +7,13 @@ #include "../shady/rewrite.h" #include "../shady/type.h" #include "../shady/ir_private.h" -#include "../shady/analysis/scope.h" +#include "../shady/analysis/cfg.h" typedef struct { Rewriter rewriter; const CompilerConfig* config; Parser* p; - Scope* curr_scope; + CFG* cfg; const Node* old_fn_or_bb; struct Dict* controls; } Context; @@ -127,7 +127,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } case Function_TAG: { Context fn_ctx = *ctx; - fn_ctx.curr_scope = new_scope(node); + fn_ctx.cfg = build_fn_cfg(node); fn_ctx.old_fn_or_bb = node; Controls controls; initialize_controls(ctx, &controls, node); @@ -165,7 +165,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, }); } else decl->payload.fun.body = rewrite_node(&fn_ctx.rewriter, node->payload.fun.body); - destroy_scope(fn_ctx.curr_scope); + destroy_cfg(fn_ctx.cfg); return decl; } case BasicBlock_TAG: { @@ -198,9 +198,9 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name(src), get_abstraction_name(dst)); - CFNode* src_cfnode = scope_lookup(ctx->curr_scope, src); + CFNode* src_cfnode = cfg_lookup(ctx->cfg, src); assert(src_cfnode->node); - CFNode* target_cfnode = scope_lookup(ctx->curr_scope, dst); + CFNode* target_cfnode = cfg_lookup(ctx->cfg, dst); assert(src_cfnode && target_cfnode); CFNode* dom = src_cfnode->idom; while (dom) { diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 5d6884b09..e83c3793f 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -38,8 +38,8 @@ set(SHADY_SOURCES annotation.c module.c - analysis/scope.c - analysis/scope_dump.c + analysis/cfg.c + analysis/cfg_dump.c analysis/free_variables.c analysis/verify.c analysis/callgraph.c diff --git a/src/shady/analysis/scope.c b/src/shady/analysis/cfg.c similarity index 75% rename from src/shady/analysis/scope.c rename to src/shady/analysis/cfg.c index 26f8973c3..9e2999abb 100644 --- a/src/shady/analysis/scope.c +++ b/src/shady/analysis/cfg.c @@ -1,4 +1,4 @@ -#include "scope.h" +#include "cfg.h" #include "looptree.h" #include "log.h" @@ -12,18 +12,18 @@ #include #include -struct List* build_scopes(Module* mod) { - struct List* scopes = new_list(Scope*); +struct List* build_cfgs(Module* mod) { + struct List* cfgs = new_list(CFG*); Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag != Function_TAG) continue; - Scope* scope = new_scope(decl); - append_list(Scope*, scopes, scope); + CFG* cfg = build_fn_cfg(decl); + append_list(CFG*, cfgs, cfg); } - return scopes; + return cfgs; } KeyHash hash_node(const Node**); @@ -31,6 +31,7 @@ bool compare_node(const Node**, const Node**); typedef struct { Arena* arena; + const Node* function; const Node* entry; LoopTree* lt; struct Dict* nodes; @@ -38,10 +39,10 @@ typedef struct { struct List* contents; struct Dict* join_point_values; -} ScopeBuildContext; +} CfgBuildContext; -CFNode* scope_lookup(Scope* scope, const Node* abs) { - CFNode** found = find_value_dict(const Node*, CFNode*, scope->map, abs); +CFNode* cfg_lookup(CFG* cfg, const Node* abs) { + CFNode** found = find_value_dict(const Node*, CFNode*, cfg->map, abs); if (found) { CFNode* cfnode = *found; assert(cfnode->node); @@ -65,9 +66,9 @@ static CFNode* new_cfnode(Arena* a) { return new; } -static CFNode* get_or_enqueue(ScopeBuildContext* ctx, const Node* abs) { +static CFNode* get_or_enqueue(CfgBuildContext* ctx, const Node* abs) { assert(is_abstraction(abs)); - assert(!is_function(abs) || abs == ctx->entry); + assert(!is_function(abs) || abs == ctx->function); CFNode** found = find_value_dict(const Node*, CFNode*, ctx->nodes, abs); if (found) return *found; @@ -102,7 +103,7 @@ static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { static bool is_structural_edge(CFEdgeType edge_type) { return edge_type != JumpEdge; } /// Adds an edge to somewhere inside a basic block -static void add_edge(ScopeBuildContext* ctx, const Node* src, const Node* dst, CFEdgeType type) { +static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFEdgeType type) { assert(is_abstraction(src) && is_abstraction(dst)); assert(!is_function(dst)); assert(is_structural_edge(type) == (bool) is_case(dst)); @@ -123,18 +124,18 @@ static void add_edge(ScopeBuildContext* ctx, const Node* src, const Node* dst, C append_list(CFEdge, dst_node->pred_edges, edge); } -static void add_structural_dominance_edge(ScopeBuildContext* ctx, CFNode* parent, const Node* dst, CFEdgeType type) { +static void add_structural_dominance_edge(CfgBuildContext* ctx, CFNode* parent, const Node* dst, CFEdgeType type) { add_edge(ctx, parent->node, dst, type); insert_set_get_result(const Node*, parent->structurally_dominates, dst); } -static void add_jump_edge(ScopeBuildContext* ctx, const Node* src, const Node* j) { +static void add_jump_edge(CfgBuildContext* ctx, const Node* src, const Node* j) { assert(j->tag == Jump_TAG); const Node* target = j->payload.jump.target; add_edge(ctx, src, target, JumpEdge); } -static void process_instruction(ScopeBuildContext* ctx, CFNode* parent, const Node* instruction, const Node* let_tail) { +static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node* instruction, const Node* let_tail) { switch (is_instruction(instruction)) { case NotAnInstruction: error("Grammar problem"); case Instruction_Call_TAG: @@ -169,10 +170,10 @@ static void process_instruction(ScopeBuildContext* ctx, CFNode* parent, const No add_structural_dominance_edge(ctx, parent, let_tail, StructuredPseudoExitEdge); } -static void process_cf_node(ScopeBuildContext* ctx, CFNode* node) { +static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { const Node* const abs = node->node; assert(is_abstraction(abs)); - assert(!is_function(abs) || abs == ctx->entry); + assert(!is_function(abs) || abs == ctx->function); const Node* terminator = get_abstraction_body(abs); if (!terminator) return; @@ -218,13 +219,13 @@ static void process_cf_node(ScopeBuildContext* ctx, CFNode* node) { } /** - * Invert all edges in this scope. Used to compute a post dominance tree. + * Invert all edges in this cfg. Used to compute a post dominance tree. */ -static void flip_scope(Scope* scope) { - scope->entry = NULL; +static void flip_cfg(CFG* cfg) { + cfg->entry = NULL; - for (size_t i = 0; i < scope->size; i++) { - CFNode* cur = read_list(CFNode*, scope->contents)[i]; + for (size_t i = 0; i < cfg->size; i++) { + CFNode* cur = read_list(CFNode*, cfg->contents)[i]; struct List* tmp = cur->succ_edges; cur->succ_edges = cur->pred_edges; @@ -247,42 +248,42 @@ static void flip_scope(Scope* scope) { } if (entries_count_list(cur->pred_edges) == 0) { - if (scope->entry != NULL) { - if (scope->entry->node) { - CFNode* new_entry = new_cfnode(scope->arena); + if (cfg->entry != NULL) { + if (cfg->entry->node) { + CFNode* new_entry = new_cfnode(cfg->arena); CFEdge prev_entry_edge = { .type = JumpEdge, .src = new_entry, - .dst = scope->entry + .dst = cfg->entry }; append_list(CFEdge, new_entry->succ_edges, prev_entry_edge); - append_list(CFEdge, scope->entry->pred_edges, prev_entry_edge); - scope->entry = new_entry; + append_list(CFEdge, cfg->entry->pred_edges, prev_entry_edge); + cfg->entry = new_entry; } CFEdge new_edge = { .type = JumpEdge, - .src = scope->entry, + .src = cfg->entry, .dst = cur }; - append_list(CFEdge, scope->entry->succ_edges, new_edge); + append_list(CFEdge, cfg->entry->succ_edges, new_edge); append_list(CFEdge, cur->pred_edges, new_edge); } else { - scope->entry = cur; + cfg->entry = cur; } } } - assert(scope->entry); - if (!scope->entry->node) { - scope->size += 1; - append_list(Node*, scope->contents, scope->entry); + assert(cfg->entry); + if (!cfg->entry->node) { + cfg->size += 1; + append_list(Node*, cfg->contents, cfg->entry); } } -static void validate_scope(Scope* scope) { - for (size_t i = 0; i < scope->size; i++) { - CFNode* node = read_list(CFNode*, scope->contents)[i]; +static void validate_cfg(CFG* cfg) { + for (size_t i = 0; i < cfg->size; i++) { + CFNode* node = read_list(CFNode*, cfg->contents)[i]; if (is_case(node->node)) { size_t structured_body_uses = 0; for (size_t j = 0; j < entries_count_list(node->pred_edges); j++) { @@ -303,7 +304,7 @@ static void validate_scope(Scope* scope) { break; } } - if (structured_body_uses != 1 && node != scope->entry /* this exception exists since we might build scopes rooted in cases */) { + if (structured_body_uses != 1 && node != cfg->entry /* this exception exists since we might build CFGs rooted in cases */) { error_print("reachable cases must be used be as bodies exactly once (actual uses: %zu)", structured_body_uses); error_die(); } @@ -311,12 +312,14 @@ static void validate_scope(Scope* scope) { } } -Scope* new_scope_impl(const Node* entry, LoopTree* lt, bool flipped) { +CFG* build_cfg(const Node* function, const Node* entry, LoopTree* lt, bool flipped) { + assert(function && function->tag == Function_TAG); assert(is_abstraction(entry)); Arena* arena = new_arena(); - ScopeBuildContext context = { + CfgBuildContext context = { .arena = arena, + .function = function, .entry = entry, .lt = lt, .nodes = new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), @@ -335,8 +338,8 @@ Scope* new_scope_impl(const Node* entry, LoopTree* lt, bool flipped) { destroy_list(context.queue); destroy_dict(context.join_point_values); - Scope* scope = calloc(sizeof(Scope), 1); - *scope = (Scope) { + CFG* cfg = calloc(sizeof(CFG), 1); + *cfg = (CFG) { .arena = arena, .entry = entry_node, .size = entries_count_list(context.contents), @@ -346,22 +349,22 @@ Scope* new_scope_impl(const Node* entry, LoopTree* lt, bool flipped) { .rpo = NULL }; - validate_scope(scope); + validate_cfg(cfg); if (flipped) - flip_scope(scope); + flip_cfg(cfg); - compute_rpo(scope); - compute_domtree(scope); + compute_rpo(cfg); + compute_domtree(cfg); - return scope; + return cfg; } -void destroy_scope(Scope* scope) { +void destroy_cfg(CFG* cfg) { bool entry_destroyed = false; - for (size_t i = 0; i < scope->size; i++) { - CFNode* node = read_list(CFNode*, scope->contents)[i]; - entry_destroyed |= node == scope->entry; + for (size_t i = 0; i < cfg->size; i++) { + CFNode* node = read_list(CFNode*, cfg->contents)[i]; + entry_destroyed |= node == cfg->entry; destroy_list(node->pred_edges); destroy_list(node->succ_edges); if (node->dominates) @@ -370,40 +373,40 @@ void destroy_scope(Scope* scope) { destroy_dict(node->structurally_dominates); } if (!entry_destroyed) { - destroy_list(scope->entry->pred_edges); - destroy_list(scope->entry->succ_edges); - if (scope->entry->dominates) - destroy_list(scope->entry->dominates); + destroy_list(cfg->entry->pred_edges); + destroy_list(cfg->entry->succ_edges); + if (cfg->entry->dominates) + destroy_list(cfg->entry->dominates); } - destroy_dict(scope->map); - destroy_arena(scope->arena); - free(scope->rpo); - destroy_list(scope->contents); - free(scope); + destroy_dict(cfg->map); + destroy_arena(cfg->arena); + free(cfg->rpo); + destroy_list(cfg->contents); + free(cfg); } -static size_t post_order_visit(Scope* scope, CFNode* n, size_t i) { +static size_t post_order_visit(CFG* cfg, CFNode* n, size_t i) { n->rpo_index = -2; for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { CFEdge edge = read_list(CFEdge, n->succ_edges)[j]; if (edge.dst->rpo_index == SIZE_MAX) - i = post_order_visit(scope, edge.dst, i); + i = post_order_visit(cfg, edge.dst, i); } n->rpo_index = i - 1; - scope->rpo[n->rpo_index] = n; + cfg->rpo[n->rpo_index] = n; return n->rpo_index; } -void compute_rpo(Scope* scope) { - scope->rpo = malloc(sizeof(const CFNode*) * scope->size); - size_t index = post_order_visit(scope, scope->entry, scope->size); +void compute_rpo(CFG* cfg) { + cfg->rpo = malloc(sizeof(const CFNode*) * cfg->size); + size_t index = post_order_visit(cfg, cfg->entry, cfg->size); assert(index == 0); // debug_print("RPO: "); - // for (size_t i = 0; i < scope->size; i++) { - // debug_print("%s, ", scope->rpo[i]->node->payload.lam.name); + // for (size_t i = 0; i < cfg->size; i++) { + // debug_print("%s, ", cfg->rpo[i]->node->payload.lam.name); // } // debug_print("\n"); } @@ -417,10 +420,10 @@ CFNode* least_common_ancestor(CFNode* i, CFNode* j) { return i; } -void compute_domtree(Scope* scope) { - for (size_t i = 0; i < scope->size; i++) { - CFNode* n = read_list(CFNode*, scope->contents)[i]; - if (n == scope->entry) +void compute_domtree(CFG* cfg) { + for (size_t i = 0; i < cfg->size; i++) { + CFNode* n = read_list(CFNode*, cfg->contents)[i]; + if (n == cfg->entry) continue; for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { CFEdge e = read_list(CFEdge, n->pred_edges)[j]; @@ -437,9 +440,9 @@ void compute_domtree(Scope* scope) { bool todo = true; while (todo) { todo = false; - for (size_t i = 0; i < scope->size; i++) { - CFNode* n = read_list(CFNode*, scope->contents)[i]; - if (n == scope->entry) + for (size_t i = 0; i < cfg->size; i++) { + CFNode* n = read_list(CFNode*, cfg->contents)[i]; + if (n == cfg->entry) continue; CFNode* new_idom = NULL; for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { @@ -455,13 +458,13 @@ void compute_domtree(Scope* scope) { } } - for (size_t i = 0; i < scope->size; i++) { - CFNode* n = read_list(CFNode*, scope->contents)[i]; + for (size_t i = 0; i < cfg->size; i++) { + CFNode* n = read_list(CFNode*, cfg->contents)[i]; n->dominates = new_list(CFNode*); } - for (size_t i = 0; i < scope->size; i++) { - CFNode* n = read_list(CFNode*, scope->contents)[i]; - if (n == scope->entry) + for (size_t i = 0; i < cfg->size; i++) { + CFNode* n = read_list(CFNode*, cfg->contents)[i]; + if (n == cfg->entry) continue; append_list(CFNode*, n->idom->dominates, n); } diff --git a/src/shady/analysis/scope.h b/src/shady/analysis/cfg.h similarity index 64% rename from src/shady/analysis/scope.h rename to src/shady/analysis/cfg.h index c6b76402a..eb9cac35e 100644 --- a/src/shady/analysis/scope.h +++ b/src/shady/analysis/cfg.h @@ -1,4 +1,5 @@ -#ifndef SHADY_SCOPE_H +#ifndef SHADY_CFG_H +#define SHADY_CFG_H #include "shady/ir.h" @@ -52,7 +53,7 @@ struct CFNode_ { }; typedef struct Arena_ Arena; -typedef struct Scope_ { +typedef struct CFG_ { Arena* arena; size_t size; bool flipped; @@ -70,48 +71,36 @@ typedef struct Scope_ { CFNode* entry; // set by compute_rpo CFNode** rpo; -} Scope; +} CFG; /** - * @returns @ref List of @ref Scope* + * @returns @ref List of @ref CFG* */ -struct List* build_scopes(Module*); +struct List* build_cfgs(Module*); typedef struct LoopTree_ LoopTree; -/** Construct the scope stating in Node. +/** Construct the CFG starting in node. */ -Scope* new_scope_impl(const Node* entry, LoopTree* lt, bool flipped); +CFG* build_cfg(const Node* fn, const Node* entry, LoopTree* lt, bool flipped); -#define new_scope_lt(node, lt) new_scope_impl(node, lt, false); -#define new_scope_lt_flipped(node, lt) new_scope_impl(node, lt, true); - -Scope* new_scope_lt_impl(const Node* entry, LoopTree* lt, bool flipped); - -/** Construct the scope starting in Node. +/** Construct the CFG starting in node. * Dominance will only be computed with respect to the nodes reachable by @p entry. */ -#define new_scope(node) new_scope_impl(node, NULL, false); +#define build_fn_cfg(node) build_cfg(node, node, NULL, false); -/** Construct the scope stating in Node. +/** Construct the CFG stating in Node. * Dominance will only be computed with respect to the nodes reachable by @p entry. - * This scope will contain post dominance information instead of regular dominance! + * This CFG will contain post dominance information instead of regular dominance! */ -#define new_scope_flipped(node) new_scope_impl(node, NULL, true); +#define build_fn_cfg_flipped(node) build_cfg(node, node, NULL, true); -CFNode* scope_lookup(Scope*, const Node* abs); -void compute_rpo(Scope*); -void compute_domtree(Scope*); +CFNode* cfg_lookup(CFG* cfg, const Node* abs); +void compute_rpo(CFG*); +void compute_domtree(CFG*); CFNode* least_common_ancestor(CFNode* i, CFNode* j); -void destroy_scope(Scope*); - -/** - * @returns @ref List of @ref CFNode* - */ -struct List* scope_get_dom_frontier(Scope*, const CFNode* node); - -#define SHADY_SCOPE_H +void destroy_cfg(CFG* cfg); #endif diff --git a/src/shady/analysis/scope_dump.c b/src/shady/analysis/cfg_dump.c similarity index 83% rename from src/shady/analysis/scope_dump.c rename to src/shady/analysis/cfg_dump.c index 5f7235625..5ebf1e5a1 100644 --- a/src/shady/analysis/scope_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -1,4 +1,4 @@ -#include "scope.h" +#include "cfg.h" #include "shady/ir_private.h" #include "shady/print.h" @@ -99,18 +99,18 @@ static void dump_cf_node(FILE* output, const CFNode* n) { } } -static void dump_cfg_scope(FILE* output, Scope* scope) { +static void dump_cfg(FILE* output, CFG* cfg) { extra_uniqueness++; - const Node* entry = scope->entry->node; + const Node* entry = cfg->entry->node; fprintf(output, "subgraph cluster_%s {\n", get_abstraction_name(entry)); fprintf(output, "label = \"%s\";\n", get_abstraction_name(entry)); - for (size_t i = 0; i < entries_count_list(scope->contents); i++) { - const CFNode* n = read_list(const CFNode*, scope->contents)[i]; + for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { + const CFNode* n = read_list(const CFNode*, cfg->contents)[i]; dump_cf_node(output, n); } - for (size_t i = 0; i < entries_count_list(scope->contents); i++) { - const CFNode* bb_node = read_list(const CFNode*, scope->contents)[i]; + for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { + const CFNode* bb_node = read_list(const CFNode*, cfg->contents)[i]; const CFNode* src_node = bb_node; while (true) { const CFNode* let_parent = get_let_pred(src_node); @@ -142,24 +142,24 @@ static void dump_cfg_scope(FILE* output, Scope* scope) { fprintf(output, "}\n"); } -void dump_cfg(FILE* output, Module* mod) { +void dump_cfgs(FILE* output, Module* mod) { if (output == NULL) output = stderr; fprintf(output, "digraph G {\n"); - struct List* scopes = build_scopes(mod); - for (size_t i = 0; i < entries_count_list(scopes); i++) { - Scope* scope = read_list(Scope*, scopes)[i]; - dump_cfg_scope(output, scope); - destroy_scope(scope); + struct List* cfgs = build_cfgs(mod); + for (size_t i = 0; i < entries_count_list(cfgs); i++) { + CFG* cfg = read_list(CFG*, cfgs)[i]; + dump_cfg(output, cfg); + destroy_cfg(cfg); } - destroy_list(scopes); + destroy_list(cfgs); fprintf(output, "}\n"); } void dump_cfg_auto(Module* mod) { FILE* f = fopen("cfg.dot", "wb"); - dump_cfg(f, mod); + dump_cfgs(f, mod); fclose(f); } @@ -177,7 +177,7 @@ static void dump_domtree_cfnode(Printer* p, CFNode* idom) { } } -void dump_domtree_scope(Printer* p, Scope* s) { +void dump_domtree_cfg(Printer* p, CFG* s) { print(p, "subgraph cluster_%s {\n", get_abstraction_name(s->entry->node)); dump_domtree_cfnode(p, s->entry); print(p, "}\n"); @@ -185,13 +185,13 @@ void dump_domtree_scope(Printer* p, Scope* s) { void dump_domtree_module(Printer* p, Module* mod) { print(p, "digraph G {\n"); - struct List* scopes = build_scopes(mod); - for (size_t i = 0; i < entries_count_list(scopes); i++) { - Scope* scope = read_list(Scope*, scopes)[i]; - dump_domtree_scope(p, scope); - destroy_scope(scope); + struct List* cfgs = build_cfgs(mod); + for (size_t i = 0; i < entries_count_list(cfgs); i++) { + CFG* cfg = read_list(CFG*, cfgs)[i]; + dump_domtree_cfg(p, cfg); + destroy_cfg(cfg); } - destroy_list(scopes); + destroy_list(cfgs); print(p, "}\n"); } diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index 0edbcad63..fdf119236 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -3,7 +3,7 @@ #include "log.h" #include "../visit.h" -#include "../analysis/scope.h" +#include "../analysis/cfg.h" #include "list.h" #include "dict.h" @@ -136,7 +136,7 @@ static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, C return ctx->current_scope; } -struct Dict* compute_scope_variables_map(const Scope* scope) { +struct Dict* compute_cfg_variables_map(const CFG* cfg) { Context ctx = { .visitor = { .visit_op_fn = (VisitOpFn) search_op_for_free_variables, @@ -144,12 +144,12 @@ struct Dict* compute_scope_variables_map(const Scope* scope) { .map = new_dict(CFNode*, CFNodeVariables*, (HashFn) hash_ptr, (CmpFn) compare_ptrs), }; - debugv_print("Computing free variables for function '%s' ...\n", get_abstraction_name(scope->entry->node)); - visit_domtree(&ctx, scope->entry, 0, NULL); + debugv_print("Computing free variables for function '%s' ...\n", get_abstraction_name(cfg->entry->node)); + visit_domtree(&ctx, cfg->entry, 0, NULL); return ctx.map; } -void destroy_scope_variables_map(struct Dict* map) { +void destroy_cfg_variables_map(struct Dict* map) { size_t i = 0; CFNodeVariables* value; while (dict_iter(map, &i, NULL, &value)) { diff --git a/src/shady/analysis/free_variables.h b/src/shady/analysis/free_variables.h index a0754dba2..02105b086 100644 --- a/src/shady/analysis/free_variables.h +++ b/src/shady/analysis/free_variables.h @@ -3,7 +3,7 @@ #include "shady/ir.h" -typedef struct Scope_ Scope; +typedef struct CFG_ CFG; typedef struct CFNode_ CFNode; typedef struct { @@ -12,7 +12,7 @@ typedef struct { struct Dict* free_set; } CFNodeVariables; -struct Dict* compute_scope_variables_map(const Scope* scope); -void destroy_scope_variables_map(struct Dict*); +struct Dict* compute_cfg_variables_map(const CFG* cfg); +void destroy_cfg_variables_map(struct Dict*); #endif diff --git a/src/shady/analysis/leak.h b/src/shady/analysis/leak.h index c232c7a42..27913de9d 100644 --- a/src/shady/analysis/leak.h +++ b/src/shady/analysis/leak.h @@ -4,7 +4,7 @@ #include #include "uses.h" -#include "scope.h" +#include "cfg.h" typedef void (VisitEnclosingAbsCallback)(void*, const Use*); void visit_enclosing_abstractions(UsesMap*, const Node*, void* uptr, VisitEnclosingAbsCallback fn); diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index ebe8d4bcc..dfead5844 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -14,7 +14,7 @@ typedef struct { } State; typedef struct { - Scope* s; + CFG* s; State* states; /** @@ -193,7 +193,7 @@ LTNode* looptree_lookup(LoopTree* lt, const Node* block) { assert(false); } -LoopTree* build_loop_tree(Scope* s) { +LoopTree* build_loop_tree(CFG* s) { LARRAY(State, states, s->size); for (size_t i = 0; i < s->size; i++) { states[i] = (State) { @@ -284,15 +284,15 @@ void dump_loop_trees(FILE* output, Module* mod) { output = stderr; fprintf(output, "digraph G {\n"); - struct List* scopes = build_scopes(mod); - for (size_t i = 0; i < entries_count_list(scopes); i++) { - Scope* scope = read_list(Scope*, scopes)[i]; - LoopTree* lt = build_loop_tree(scope); + struct List* cfgs = build_cfgs(mod); + for (size_t i = 0; i < entries_count_list(cfgs); i++) { + CFG* cfg = read_list(CFG*, cfgs)[i]; + LoopTree* lt = build_loop_tree(cfg); dump_loop_tree(output, lt); destroy_loop_tree(lt); - destroy_scope(scope); + destroy_cfg(cfg); } - destroy_list(scopes); + destroy_list(cfgs); fprintf(output, "}\n"); } diff --git a/src/shady/analysis/looptree.h b/src/shady/analysis/looptree.h index 838ae0c66..50b649aa1 100644 --- a/src/shady/analysis/looptree.h +++ b/src/shady/analysis/looptree.h @@ -1,7 +1,7 @@ #ifndef SHADY_LOOPTREE_H #define SHADY_LOOPTREE_H -#include "scope.h" +#include "cfg.h" // Loop tree implementation based on Thorin, translated to C and somewhat simplified // https://github.com/AnyDSL/thorin @@ -44,7 +44,7 @@ LTNode* looptree_lookup(LoopTree*, const Node* block); static void destroy_lt_node(LTNode* n); void destroy_loop_tree(LoopTree* lt); -LoopTree* build_loop_tree(Scope* s); +LoopTree* build_loop_tree(CFG* s); void dump_loop_trees(FILE* output, Module* mod); #endif // SHADY_LOOPTREE_H diff --git a/src/shady/analysis/uses.h b/src/shady/analysis/uses.h index 3ebd1424d..c978431bd 100644 --- a/src/shady/analysis/uses.h +++ b/src/shady/analysis/uses.h @@ -2,7 +2,7 @@ #define SHADY_USAGES #include "shady/ir.h" -#include "scope.h" +#include "cfg.h" #include "list.h" #include "dict.h" #include "arena.h" diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 1f7995bb1..873550d08 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -1,6 +1,6 @@ #include "verify.h" #include "free_variables.h" -#include "scope.h" +#include "cfg.h" #include "log.h" #include "../visit.h" @@ -43,11 +43,11 @@ static void verify_same_arena(Module* mod) { } static void verify_scoping(const CompilerConfig* config, Module* mod) { - struct List* scopes = build_scopes(mod); - for (size_t i = 0; i < entries_count_list(scopes); i++) { - Scope* scope = read_list(Scope*, scopes)[i]; - struct Dict* map = compute_scope_variables_map(scope); - CFNodeVariables* entry_vars = *find_value_dict(CFNode*, CFNodeVariables*, map, scope->entry); + struct List* cfgs = build_cfgs(mod); + for (size_t i = 0; i < entries_count_list(cfgs); i++) { + CFG* cfg = read_list(CFG*, cfgs)[i]; + struct Dict* map = compute_cfg_variables_map(cfg); + CFNodeVariables* entry_vars = *find_value_dict(CFNode*, CFNodeVariables*, map, cfg->entry); size_t j = 0; const Node* leaking; while (dict_iter(entry_vars->free_set, &j, &leaking, NULL)) { @@ -58,16 +58,16 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { log_module(ERROR, config, mod); error_die(); } - destroy_scope_variables_map(map); - destroy_scope(scope); + destroy_cfg_variables_map(map); + destroy_cfg(cfg); } - destroy_list(scopes); + destroy_list(cfgs); } static void verify_nominal_node(const Node* fn, const Node* n) { switch (n->tag) { case Function_TAG: { - assert(!fn && "functions cannot be part of a scope, except as the entry"); + assert(!fn && "functions cannot be part of a CFG, except as the entry"); break; } case BasicBlock_TAG: { @@ -101,20 +101,20 @@ static void verify_nominal_node(const Node* fn, const Node* n) { } static void verify_bodies(Module* mod) { - struct List* scopes = build_scopes(mod); - for (size_t i = 0; i < entries_count_list(scopes); i++) { - Scope* scope = read_list(Scope*, scopes)[i]; + struct List* cfgs = build_cfgs(mod); + for (size_t i = 0; i < entries_count_list(cfgs); i++) { + CFG* cfg = read_list(CFG*, cfgs)[i]; - for (size_t j = 0; j < scope->size; j++) { - CFNode* n = scope->rpo[j]; + for (size_t j = 0; j < cfg->size; j++) { + CFNode* n = cfg->rpo[j]; if (n->node->tag == BasicBlock_TAG) { - verify_nominal_node(scope->entry->node, n->node); + verify_nominal_node(cfg->entry->node, n->node); } } - destroy_scope(scope); + destroy_cfg(cfg); } - destroy_list(scopes); + destroy_list(cfgs); Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) { diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 69d9ee087..59a980fe7 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -7,7 +7,7 @@ #include "shady/builtins.h" #include "../../ir_private.h" -#include "../../analysis/scope.h" +#include "../../analysis/cfg.h" #include "../../type.h" #include "../../compile.h" @@ -255,9 +255,9 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo SHADY_UNREACHABLE; } -static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const Scope* scope, const CFNode* cf_node) { +static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const CFG* cfg, const CFNode* cf_node) { const Node* bb_node = cf_node->node; - assert(is_basic_block(bb_node) || cf_node == scope->entry); + assert(is_basic_block(bb_node) || cf_node == cfg->entry); const Node* body = get_abstraction_body(bb_node); @@ -297,10 +297,10 @@ static void emit_function(Emitter* emitter, const Node* node) { } if (node->payload.fun.body) { - Scope* scope = new_scope(node); - // reserve a bunch of identifiers for the basic blocks in the scope - for (size_t i = 0; i < scope->size; i++) { - CFNode* cfnode = read_list(CFNode*, scope->contents)[i]; + CFG* cfg = build_fn_cfg(node); + // reserve a bunch of identifiers for the basic blocks in the CFG + for (size_t i = 0; i < cfg->size; i++) { + CFNode* cfnode = read_list(CFNode*, cfg->contents)[i]; assert(cfnode); const Node* bb = cfnode->node; if (is_case(bb)) @@ -322,17 +322,17 @@ static void emit_function(Emitter* emitter, const Node* node) { } } // emit the blocks using the dominator tree - //emit_basic_block(emitter, fn_builder, &scope, scope.entry); - for (size_t i = 0; i < scope->size; i++) { - CFNode* cfnode = scope->rpo[i]; + //emit_basic_block(emitter, fn_builder, &cfg, cfg.entry); + for (size_t i = 0; i < cfg->size; i++) { + CFNode* cfnode = cfg->rpo[i]; if (i == 0) - assert(cfnode == scope->entry); + assert(cfnode == cfg->entry); if (is_case(cfnode->node)) continue; - emit_basic_block(emitter, fn_builder, scope, cfnode); + emit_basic_block(emitter, fn_builder, cfg, cfnode); } - destroy_scope(scope); + destroy_cfg(cfg); spvb_define_function(emitter->file_builder, fn_builder); } else { diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 0832c642b..6d0f2dff7 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -11,7 +11,7 @@ #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" -#include "../analysis/scope.h" +#include "../analysis/cfg.h" #include "../analysis/free_variables.h" #include "../analysis/uses.h" #include "../analysis/leak.h" @@ -25,9 +25,9 @@ bool compare_node(Node**, Node**); typedef struct Context_ { Rewriter rewriter; - Scope* scope; - const UsesMap* scope_uses; - struct Dict* scope_vars; + CFG* cfg; + const UsesMap* uses; + struct Dict* live_vars; struct Dict* lifted; bool disable_lowering; @@ -96,8 +96,8 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name String name = is_basic_block(cont) ? format_string_arena(a->arena, "%s_%s", get_abstraction_name(cont->payload.basic_block.fn), get_abstraction_name(cont)) : unique_name(a, given_name); // Compute the live stuff we'll need - CFNode* cf_node = scope_lookup(ctx->scope, cont); - CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_node); + CFNode* cf_node = cfg_lookup(ctx->cfg, cont); + CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_node); struct List* recover_context = new_list(const Node*); add_to_recover_context(recover_context, node_vars->bound_set, cont); @@ -173,18 +173,18 @@ static const Node* process_node(Context* ctx, const Node* node) { ctx = (Context*) ctx->rewriter.parent; Context fn_ctx = *ctx; - fn_ctx.scope = new_scope(node); - fn_ctx.scope_uses = create_uses_map(node, (NcDeclaration | NcType)); - fn_ctx.scope_vars = compute_scope_variables_map(fn_ctx.scope); + fn_ctx.cfg = build_fn_cfg(node); + fn_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); + fn_ctx.live_vars = compute_cfg_variables_map(fn_ctx.cfg); fn_ctx.disable_lowering = lookup_annotation(node, "Internal"); ctx = &fn_ctx; Node* new = recreate_decl_header_identity(&ctx->rewriter, node); recreate_decl_body_identity(&ctx->rewriter, node, new); - destroy_uses_map(ctx->scope_uses); - destroy_scope_variables_map(ctx->scope_vars); - destroy_scope(ctx->scope); + destroy_uses_map(ctx->uses); + destroy_cfg_variables_map(ctx->live_vars); + destroy_cfg(ctx->cfg); return new; } default: @@ -200,12 +200,12 @@ static const Node* process_node(Context* ctx, const Node* node) { if (oinstruction->tag == Control_TAG) { const Node* oinside = oinstruction->payload.control.inside; assert(is_case(oinside)); - if (!is_control_static(ctx->scope_uses, oinstruction) || ctx->config->hacks.force_join_point_lifting) { + if (!is_control_static(ctx->uses, oinstruction) || ctx->config->hacks.force_join_point_lifting) { *ctx->todo = true; const Node* otail = get_let_tail(node); BodyBuilder* bb = begin_body(a); - LiftedCont* lifted_tail = lambda_lift(ctx, otail, unique_name(a, format_string_arena(a->arena, "post_control_%s", get_abstraction_name(ctx->scope->entry->node)))); + LiftedCont* lifted_tail = lambda_lift(ctx, otail, unique_name(a, format_string_arena(a->arena, "post_control_%s", get_abstraction_name(ctx->cfg->entry->node)))); const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index a190c4202..50c07b492 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -6,7 +6,7 @@ #include "../type.h" #include "../rewrite.h" -#include "../analysis/scope.h" +#include "../analysis/cfg.h" #include @@ -16,7 +16,7 @@ typedef struct Context_ { Node* current_fn; struct Dict* structured_join_tokens; - Scope* scope; + CFG* cfg; const Node* abs; } Context; @@ -141,13 +141,13 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); sub_ctx.disable_lowering = lookup_annotation(fun, "Structured"); sub_ctx.current_fn = fun; - sub_ctx.scope = new_scope(node); + sub_ctx.cfg = build_fn_cfg(node); sub_ctx.abs = node; fun->payload.fun.body = rewrite_node(&sub_ctx.rewriter, node->payload.fun.body); - destroy_scope(sub_ctx.scope); + destroy_cfg(sub_ctx.cfg); return fun; } else if (node->tag == Constant_TAG) { - sub_ctx.scope = NULL; + sub_ctx.cfg = NULL; sub_ctx.abs = NULL; sub_ctx.current_fn = NULL; ctx = &sub_ctx; @@ -161,7 +161,7 @@ static const Node* process_node(Context* ctx, const Node* node) { if (ctx->disable_lowering) return recreate_node_identity(&ctx->rewriter, node); - CFNode* cfnode = ctx->scope ? scope_lookup(ctx->scope, ctx->abs) : NULL; + CFNode* cfnode = ctx->cfg ? cfg_lookup(ctx->cfg, ctx->abs) : NULL; switch (node->tag) { case Let_TAG: return process_let(ctx, node); case Yield_TAG: { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 3e15e646f..c3eac3153 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -8,7 +8,7 @@ #include "../type.h" #include "../ir_private.h" -#include "../analysis/scope.h" +#include "../analysis/cfg.h" #include "../analysis/uses.h" #include "../analysis/leak.h" #include "../transform/ir_gen_helpers.h" @@ -28,8 +28,8 @@ typedef struct Context_ { struct Dict* assigned_fn_ptrs; FnPtr* next_fn_ptr; - Scope* scope; - const UsesMap* scope_uses; + CFG* cfg; + const UsesMap* uses; Node** top_dispatcher_fn; Node* init_fn; @@ -103,8 +103,8 @@ static const Node* process(Context* ctx, const Node* old) { switch (old->tag) { case Function_TAG: { Context ctx2 = *ctx; - ctx2.scope = new_scope(old); - ctx2.scope_uses = create_uses_map(old, (NcDeclaration | NcType)); + ctx2.cfg = build_fn_cfg(old); + ctx2.uses = create_uses_map(old, (NcDeclaration | NcType)); ctx = &ctx2; const Node* entry_point_annotation = lookup_annotation_list(old->payload.fun.annotations, "EntryPoint"); @@ -122,8 +122,8 @@ static const Node* process(Context* ctx, const Node* old) { fun->payload.fun.body = nbody; } - destroy_uses_map(ctx2.scope_uses); - destroy_scope(ctx2.scope); + destroy_uses_map(ctx2.uses); + destroy_cfg(ctx2.cfg); return fun; } @@ -153,8 +153,8 @@ static const Node* process(Context* ctx, const Node* old) { register_processed(&ctx->rewriter, old_param, popped); } fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body)); - destroy_uses_map(ctx2.scope_uses); - destroy_scope(ctx2.scope); + destroy_uses_map(ctx2.uses); + destroy_cfg(ctx2.cfg); return fun; } case FnAddr_TAG: return lower_fn_addr(ctx, old->payload.fn_addr.fn); @@ -243,7 +243,7 @@ static const Node* process(Context* ctx, const Node* old) { break; } case Control_TAG: { - if (is_control_static(ctx->scope_uses, old)) { + if (is_control_static(ctx->uses, old)) { const Node* old_inside = old->payload.control.inside; const Node* old_jp = first(get_abstraction_params(old_inside)); assert(old_jp->tag == Variable_TAG); diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index 3925b4171..a81d10c1e 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -7,7 +7,7 @@ #include "../rewrite.h" #include "../analysis/callgraph.h" -#include "../analysis/scope.h" +#include "../analysis/cfg.h" #include "../analysis/uses.h" #include "../analysis/leak.h" @@ -17,8 +17,8 @@ typedef struct { struct Dict* fns; bool is_leaf; - Scope* scope; - const UsesMap* scope_uses; + CFG* cfg; + const UsesMap* uses; } Context; typedef struct { @@ -104,8 +104,8 @@ static const Node* process(Context* ctx, const Node* node) { Context fn_ctx = *ctx; CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, node); fn_ctx.is_leaf = is_leaf_fn(ctx, fn_node); - fn_ctx.scope = new_scope(node); - fn_ctx.scope_uses = create_uses_map(node, (NcDeclaration | NcType)); + fn_ctx.cfg = build_fn_cfg(node); + fn_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); ctx = &fn_ctx; Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); @@ -122,13 +122,13 @@ static const Node* process(Context* ctx, const Node* node) { })); } - destroy_uses_map(fn_ctx.scope_uses); - destroy_scope(fn_ctx.scope); + destroy_uses_map(fn_ctx.uses); + destroy_cfg(fn_ctx.cfg); return new; } case Control_TAG: { - if (!is_control_static(ctx->scope_uses, node)) { - debugv_print("Function %s can't be a leaf function because the join point ", get_abstraction_name(ctx->scope->entry->node)); + if (!is_control_static(ctx->uses, node)) { + debugv_print("Function %s can't be a leaf function because the join point ", get_abstraction_name(ctx->cfg->entry->node)); log_node(DEBUGV, first(node->payload.control.inside->payload.case_.params)); debugv_print("escapes its control block, preventing restructuring.\n"); ctx->is_leaf = false; @@ -149,7 +149,7 @@ static const Node* process(Context* ctx, const Node* node) { break; } } - debugv_print("Function %s can't be a leaf function because it joins with ", get_abstraction_name(ctx->scope->entry->node)); + debugv_print("Function %s can't be a leaf function because it joins with ", get_abstraction_name(ctx->cfg->entry->node)); log_node(DEBUGV, old_jp); debugv_print("which is not bound by a control node within that function.\n"); // we join with some random join point; we can't be a leaf :( diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 1a40cef0e..96f285d85 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -20,7 +20,7 @@ typedef struct Context_ { Rewriter rewriter; bool disable_lowering; - const UsesMap* scope_uses; + const UsesMap* uses; const CompilerConfig* config; Arena* arena; struct Dict* alloca_info; @@ -129,8 +129,8 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { PtrSourceKnowledge k = { 0 }; while (ptr) { assert(is_value(ptr)); - if (ptr->tag == Variable_TAG && ctx->scope_uses) { - const Node* instr = get_var_instruction(ctx->scope_uses, ptr); + if (ptr->tag == Variable_TAG && ctx->uses) { + const Node* instr = get_var_instruction(ctx->uses, ptr); if (instr) { PrimOp payload = instr->payload.prim_op; switch (payload.op) { @@ -166,16 +166,16 @@ static const Node* process(Context* ctx, const Node* old) { case Function_TAG: { Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); Context fun_ctx = *ctx; - fun_ctx.scope_uses = create_uses_map(old, (NcDeclaration | NcType)); + fun_ctx.uses = create_uses_map(old, (NcDeclaration | NcType)); fun_ctx.disable_lowering = lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); if (old->payload.fun.body) fun->payload.fun.body = rewrite_node(&fun_ctx.rewriter, old->payload.fun.body); - destroy_uses_map(fun_ctx.scope_uses); + destroy_uses_map(fun_ctx.uses); return fun; } case Constant_TAG: { Context fun_ctx = *ctx; - fun_ctx.scope_uses = NULL; + fun_ctx.uses = NULL; return recreate_node_identity(&fun_ctx.rewriter, old); } case Let_TAG: { @@ -210,8 +210,8 @@ static const Node* process(Context* ctx, const Node* old) { case alloca_logical_op: { AllocaInfo* k = arena_alloc(ctx->arena, sizeof(AllocaInfo)); *k = (AllocaInfo) { .type = rewrite_node(r, first(payload.type_arguments)) }; - assert(ctx->scope_uses); - visit_ptr_uses(old, first(payload.type_arguments), k, ctx->scope_uses); + assert(ctx->uses); + visit_ptr_uses(old, first(payload.type_arguments), k, ctx->uses); insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, old, k); debugv_print("demote_alloca: uses analysis results for "); log_node(DEBUGV, old); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 7fce26a1a..63a6bcd6b 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -5,7 +5,7 @@ #include "arena.h" #include "log.h" -#include "../analysis/scope.h" +#include "../analysis/cfg.h" #include "../analysis/uses.h" #include "../analysis/leak.h" #include "../analysis/verify.h" @@ -58,7 +58,7 @@ typedef struct { typedef struct { Rewriter rewriter; - Scope* scope; + CFG* cfg; struct Dict* abs_to_kb; const Node* oabs; Arena* a; @@ -138,16 +138,16 @@ static void destroy_kb(KnowledgeBase* kb) { } static KnowledgeBase* get_kb(Context* ctx, const Node* abs) { - assert(ctx->scope); + assert(ctx->cfg); KnowledgeBase** found = find_value_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, abs); assert(found); return *found; } static KnowledgeBase* create_kb(Context* ctx, const Node* old) { - assert(ctx->scope); + assert(ctx->cfg); arena_alloc(ctx->a, sizeof(KnowledgeBase)); - CFNode* cf_node = scope_lookup(ctx->scope, old); + CFNode* cf_node = cfg_lookup(ctx->cfg, old); KnowledgeBase* kb = arena_alloc(ctx->a, sizeof(KnowledgeBase)); *kb = (KnowledgeBase) { .cfnode = cf_node, @@ -228,7 +228,7 @@ static PtrKnowledge* find_or_create_ptr_knowledge_for_updating(Context* ctx, Kno k = update_ptr_knowledge(kb, optr, k); } else { PtrSourceKnowledge* sk = NULL; - CFNode* cf_node = scope_lookup(ctx->scope, ctx->oabs); + CFNode* cf_node = cfg_lookup(ctx->cfg, ctx->oabs); // we're creating a new chain of knowledge, but we want to use the same source if possible while (cf_node) { KnowledgeBase* kb2 = get_kb(ctx, cf_node->node); @@ -507,7 +507,7 @@ static void handle_bb(Context* ctx, const Node* old) { const Node* nbody = rewrite_node(&ctx->rewriter, get_abstraction_body(old)); nbody = let(a, quote_helper(a, params), case_(a, let_params, nbody)); - CFNode* cfnode = scope_lookup(ctx->scope, old); + CFNode* cfnode = cfg_lookup(ctx->cfg, old); BodyBuilder* bb = begin_body(a); size_t i = 0; const Node* ptr; @@ -574,7 +574,7 @@ static void handle_bb(Context* ctx, const Node* old) { next_potential_param: continue; } - Node* fn = (Node*) rewrite_node(&ctx->rewriter, ctx->scope->entry->node); + Node* fn = (Node*) rewrite_node(&ctx->rewriter, ctx->cfg->entry->node); String s = format_string_interned(a, "%s_", get_abstraction_name(old)); //String s = get_abstraction_name(old); Node* new_bb = basic_block(a, fn, params, s); @@ -637,17 +637,17 @@ static const Node* process(Context* ctx, const Node* old) { KnowledgeBase* kb = NULL; if (old->tag == Function_TAG) { // if (lookup_annotation(old, "Internal")) { - // fn_ctx.scope = NULL; + // fn_ctx.cfg = NULL; // return recreate_node_identity(&fn_ctx.rewriter, old);; // } - fn_ctx.scope = new_scope(old); + fn_ctx.cfg = build_fn_cfg(old); fn_ctx.abs_to_kb = new_dict(const Node*, KnowledgeBase**, (HashFn) hash_node, (CmpFn) compare_node); fn_ctx.todo_jumps = new_list(TodoJump), kb = create_kb(ctx, old); const Node* new_fn = recreate_node_identity(&fn_ctx.rewriter, old); - for (size_t i = 1; i < ctx->scope->size; i++) { - CFNode* cf_node = ctx->scope->rpo[i]; + for (size_t i = 1; i < ctx->cfg->size; i++) { + CFNode* cf_node = ctx->cfg->rpo[i]; if (cf_node->node->tag == BasicBlock_TAG) handle_bb(ctx, cf_node->node); } @@ -657,7 +657,7 @@ static const Node* process(Context* ctx, const Node* old) { handle_jump_wrappers(ctx); destroy_list(fn_ctx.todo_jumps); - destroy_scope(fn_ctx.scope); + destroy_cfg(fn_ctx.cfg); size_t i = 0; while (dict_iter(fn_ctx.abs_to_kb, &i, NULL, &kb)) { destroy_kb(kb); @@ -665,14 +665,14 @@ static const Node* process(Context* ctx, const Node* old) { destroy_dict(fn_ctx.abs_to_kb); return new_fn; } else if (old->tag == Constant_TAG) { - fn_ctx.scope = NULL; + fn_ctx.cfg = NULL; fn_ctx.abs_to_kb = NULL; fn_ctx.todo_jumps = NULL; ctx = &fn_ctx; } // setup a new KB if this is a fresh abstraction - if (is_abstraction(old) && ctx->scope) { + if (is_abstraction(old) && ctx->cfg) { kb = create_kb(ctx, old); } else if (ctx->oabs && ctx->abs_to_kb) { // otherwise look up the enclosing one, if any diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 189f0f498..724d8be69 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -11,7 +11,7 @@ #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" -#include "../analysis/scope.h" +#include "../analysis/cfg.h" #include "../analysis/looptree.h" #include "../analysis/free_variables.h" @@ -22,10 +22,10 @@ typedef struct Context_ { const CompilerConfig* config; const Node* current_fn; const Node* current_abstraction; - Scope* fwd_scope; - Scope* back_scope; + CFG* fwd_cfg; + CFG* rev_cfg; LoopTree* current_looptree; - struct Dict* scope_vars; + struct Dict* live_vars; } Context; static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { @@ -92,7 +92,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Rewriter* rewriter = &ctx->rewriter; IrArena* arena = rewriter->dst_arena; - CFNode* current_node = scope_lookup(ctx->fwd_scope, node); + CFNode* current_node = cfg_lookup(ctx->fwd_cfg, node); LTNode* lt_node = looptree_lookup(ctx->current_looptree, node); LTNode* loop_header = NULL; @@ -127,10 +127,10 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Nodes nparams = recreate_variables(rewriter, get_abstraction_params(node)); Nodes inner_yield_types = strip_qualifiers(arena, get_variables_types(arena, nparams)); - CFNode* cf_pre = scope_lookup(ctx->fwd_scope, node); + CFNode* cf_pre = cfg_lookup(ctx->fwd_cfg, node); // assert(cf_pre->idom && "cfg entry nodes can't be loop headers anyhow"); // cf_pre = cf_pre->idom; - CFNodeVariables* pre = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_pre); + CFNodeVariables* pre = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_pre); LARRAY(Nodes, exit_param_allocas, exiting_nodes_count); LARRAY(struct List*, leaking, exiting_nodes_count); @@ -145,8 +145,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { // Search for what's required after the exit but not in scope at the loop header // this is similar to the LCSSA constraint, but here it's because controls have hard scopes - CFNode* cf_post = scope_lookup(ctx->fwd_scope, exiting_node->node); - CFNodeVariables* post = *find_value_dict(CFNode*, CFNodeVariables*, ctx->scope_vars, cf_post); + CFNode* cf_post = cfg_lookup(ctx->fwd_cfg, exiting_node->node); + CFNodeVariables* post = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_post); leaking[i] = new_list(const Type*); find_unbound_vars(exiting_node->node, pre->bound_set, post->free_set, leaking[i]); @@ -384,17 +384,17 @@ static const Node* process_node(Context* ctx, const Node* node) { case Function_TAG: { ctx = &new_context; ctx->current_fn = node; - ctx->fwd_scope = new_scope(ctx->current_fn); - ctx->back_scope = new_scope_flipped(ctx->current_fn); - ctx->current_looptree = build_loop_tree(ctx->fwd_scope); - ctx->scope_vars = compute_scope_variables_map(ctx->fwd_scope); + ctx->fwd_cfg = build_cfg(ctx->current_fn, ctx->current_fn, NULL, false); + ctx->rev_cfg = build_cfg(ctx->current_fn, ctx->current_fn, NULL, true); + ctx->current_looptree = build_loop_tree(ctx->fwd_cfg); + ctx->live_vars = compute_cfg_variables_map(ctx->fwd_cfg); const Node* new = process_abstraction(ctx, node);; - destroy_scope(ctx->fwd_scope); - destroy_scope(ctx->back_scope); + destroy_cfg(ctx->fwd_cfg); + destroy_cfg(ctx->rev_cfg); destroy_loop_tree(ctx->current_looptree); - destroy_scope_variables_map(ctx->scope_vars); + destroy_cfg_variables_map(ctx->live_vars); return new; } case Constant_TAG: { @@ -411,9 +411,9 @@ static const Node* process_node(Context* ctx, const Node* node) { case Branch_TAG: { if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) break; - assert(ctx->fwd_scope); + assert(ctx->fwd_cfg); - CFNode* cfnode = scope_lookup(ctx->back_scope, ctx->current_abstraction); + CFNode* cfnode = cfg_lookup(ctx->rev_cfg, ctx->current_abstraction); const Node* idom = NULL; LTNode* current_loop = looptree_lookup(ctx->current_looptree, ctx->current_abstraction)->parent; @@ -421,7 +421,7 @@ static const Node* process_node(Context* ctx, const Node* node) { if (entries_count_list(current_loop->cf_nodes)) { bool leaves_loop = false; - CFNode* current_node = scope_lookup(ctx->fwd_scope, ctx->current_abstraction); + CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); for (size_t i = 0; i < entries_count_list(current_node->succ_edges); i++) { CFEdge edge = read_list(CFEdge, current_node->succ_edges)[i]; LTNode* lt_target = looptree_lookup(ctx->current_looptree, edge.dst->node); @@ -434,11 +434,11 @@ static const Node* process_node(Context* ctx, const Node* node) { if (!leaves_loop) { const Node* current_loop_head = read_list(CFNode*, current_loop->cf_nodes)[0]->node; - Scope* loop_scope = new_scope_lt_flipped(current_loop_head, ctx->current_looptree); - CFNode* idom_cf = scope_lookup(loop_scope, ctx->current_abstraction)->idom; + CFG* loop_cfg = build_cfg(ctx->current_fn, current_loop_head, ctx->current_looptree, true); + CFNode* idom_cf = cfg_lookup(loop_cfg, ctx->current_abstraction)->idom; if (idom_cf) idom = idom_cf->node; - destroy_scope(loop_scope); + destroy_cfg(loop_cfg); } } else { idom = cfnode->idom->node; @@ -448,14 +448,14 @@ static const Node* process_node(Context* ctx, const Node* node) { break; } - if (scope_lookup(ctx->fwd_scope, idom)->idom->node!= ctx->current_abstraction) + if (cfg_lookup(ctx->fwd_cfg, idom)->idom->node != ctx->current_abstraction) break; assert(is_abstraction(idom) && idom->tag != Function_TAG); LTNode* lt_node = looptree_lookup(ctx->current_looptree, ctx->current_abstraction); LTNode* idom_lt_node = looptree_lookup(ctx->current_looptree, idom); - CFNode* current_node = scope_lookup(ctx->fwd_scope, ctx->current_abstraction); + CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); assert(lt_node); assert(idom_lt_node); @@ -563,8 +563,8 @@ Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .current_fn = NULL, - .fwd_scope = NULL, - .back_scope = NULL, + .fwd_cfg = NULL, + .rev_cfg = NULL, .current_looptree = NULL, }; diff --git a/src/shady/print.c b/src/shady/print.c index f79338e85..a7c47f7a9 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1,6 +1,6 @@ #include "print.h" #include "ir_private.h" -#include "analysis/scope.h" +#include "analysis/cfg.h" #include "analysis/uses.h" #include "analysis/leak.h" @@ -21,8 +21,8 @@ typedef struct PrinterCtx_ PrinterCtx; struct PrinterCtx_ { Printer* printer; const Node* fn; - Scope* scope; - const UsesMap* scope_uses; + CFG* cfg; + const UsesMap* uses; long int min_rpo; PrintConfig config; }; @@ -161,8 +161,8 @@ static void print_abs_body(PrinterCtx* ctx, const Node* block) { print_node(get_abstraction_body(block)); // TODO: it's likely cleaner to instead print things according to the dominator tree in the first place. - if (ctx->scope != NULL) { - const CFNode* dominator = scope_lookup(ctx->scope, block); + if (ctx->cfg != NULL) { + const CFNode* dominator = cfg_lookup(ctx->cfg, block); if (ctx->min_rpo < ((long int) dominator->rpo_index)) { size_t save_rpo = ctx->min_rpo; ctx->min_rpo = dominator->rpo_index; @@ -187,11 +187,11 @@ static void print_function(PrinterCtx* ctx, const Node* node) { PrinterCtx sub_ctx = *ctx; if (node->arena->config.check_op_classes) { - Scope* scope = new_scope(node); - sub_ctx.scope = scope; + CFG* cfg = build_fn_cfg(node); + sub_ctx.cfg = cfg; sub_ctx.fn = node; if (node->arena->config.check_types && node->arena->config.allow_fold) { - sub_ctx.scope_uses = create_uses_map(node, (NcDeclaration | NcType)); + sub_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); } } ctx = &sub_ctx; @@ -214,9 +214,9 @@ static void print_function(PrinterCtx* ctx, const Node* node) { printf("\n}"); if (node->arena->config.check_op_classes) { - if (sub_ctx.scope_uses) - destroy_uses_map(sub_ctx.scope_uses); - destroy_scope(sub_ctx.scope); + if (sub_ctx.uses) + destroy_uses_map(sub_ctx.uses); + destroy_cfg(sub_ctx.cfg); } } @@ -405,7 +405,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { break; } case Variable_TAG: - if (ctx->scope_uses) { + if (ctx->uses) { // if ((*find_value_dict(const Node*, Uses*, ctx->uses->map, node))->escapes_defining_block) // printf(MANGENTA); // else @@ -624,8 +624,8 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { break; } case Control_TAG: { printf(BGREEN); - if (ctx->scope_uses) { - if (is_control_static(ctx->scope_uses, node)) + if (ctx->uses) { + if (is_control_static(ctx->uses, node)) printf("static "); } printf("control"); @@ -799,7 +799,7 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { return; PrinterCtx sub_ctx = *ctx; - sub_ctx.scope = NULL; + sub_ctx.cfg = NULL; ctx = &sub_ctx; switch (node->tag) { diff --git a/src/shady/visit.c b/src/shady/visit.c index 3d0f4ac13..9ed015ab5 100644 --- a/src/shady/visit.c +++ b/src/shady/visit.c @@ -1,7 +1,7 @@ #include "shady/ir.h" #include "log.h" #include "visit.h" -#include "analysis/scope.h" +#include "analysis/cfg.h" #include @@ -33,13 +33,13 @@ void visit_ops(Visitor* visitor, NodeClass op_class, String op_name, Nodes ops) void visit_function_rpo(Visitor* visitor, const Node* function) { assert(function->tag == Function_TAG); - Scope* scope = new_scope(function); - assert(scope->rpo[0]->node == function); - for (size_t i = 1; i < scope->size; i++) { - const Node* node = scope->rpo[i]->node; + CFG* cfg = build_fn_cfg(function); + assert(cfg->rpo[0]->node == function); + for (size_t i = 1; i < cfg->size; i++) { + const Node* node = cfg->rpo[i]->node; visit_node(visitor, node); } - destroy_scope(scope); + destroy_cfg(cfg); } #pragma GCC diagnostic error "-Wswitch" From d34bfea0fbb70dc1d09cd108530d3aa4fb7de677 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Apr 2024 09:45:43 +0200 Subject: [PATCH 220/693] compile.h: make RUN_PASS's complex body into a function --- src/shady/compile.c | 23 ++++++++++++++++++++++- src/shady/compile.h | 23 +++-------------------- src/shady/emit/c/emit_c.c | 1 - src/shady/emit/spirv/emit_spv.c | 1 - 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 011875717..511856e1f 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -87,9 +87,30 @@ void add_scheduler_source(const CompilerConfig* config, Module* dst) { destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); } +void run_pass_impl(CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name) { + Module* old_mod = NULL; + old_mod = *pmod; + *pmod = pass(config, *pmod); + (*pmod)->sealed = true; + if (SHADY_RUN_VERIFY) + verify_module(config, *pmod); + if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) + destroy_ir_arena(get_module_arena(old_mod)); + old_mod = *pmod; + if (config->optimisations.cleanup.after_every_pass) + *pmod = cleanup(config, *pmod); + debugvv_print("After pass %s: \n", pass_name); + log_module(DEBUGVV, config, *pmod); + if (SHADY_RUN_VERIFY) + verify_module(config, *pmod); + if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) + destroy_ir_arena(get_module_arena(old_mod)); + if (config->hooks.after_pass.fn) + config->hooks.after_pass.fn(config->hooks.after_pass.uptr, pass_name, *pmod); +} + CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { IrArena* initial_arena = (*pmod)->arena; - Module* old_mod = NULL; if (config->dynamic_scheduling) { *pmod = import(config, *pmod); // we don't want to mess with the original module diff --git a/src/shady/compile.h b/src/shady/compile.h index 2e9500007..4672578b7 100644 --- a/src/shady/compile.h +++ b/src/shady/compile.h @@ -12,25 +12,8 @@ #define SHADY_RUN_VERIFY 1 #endif -#define RUN_PASS(pass_name) { \ -old_mod = *pmod; \ -*pmod = pass_name(config, *pmod); \ -(*pmod)->sealed = true; \ -if (SHADY_RUN_VERIFY) \ - verify_module(config, *pmod); \ -if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) \ - destroy_ir_arena(get_module_arena(old_mod)); \ -old_mod = *pmod; \ -if (config->optimisations.cleanup.after_every_pass) \ - *pmod = cleanup(config, *pmod); \ -debugvv_print("After "#pass_name" pass: \n"); \ -log_module(DEBUGVV, config, *pmod); \ -if (SHADY_RUN_VERIFY) \ - verify_module(config, *pmod); \ -if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) \ - destroy_ir_arena(get_module_arena(old_mod)); \ -if (config->hooks.after_pass.fn) \ - config->hooks.after_pass.fn(config->hooks.after_pass.uptr, #pass_name, *pmod); \ -} \ +void run_pass_impl(CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name); + +#define RUN_PASS(pass_name) run_pass_impl(config, pmod, initial_arena, pass_name, #pass_name); #endif diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 1a5146882..6b8849967 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -688,7 +688,6 @@ bool compare_node(Node**, Node**); static Module* run_backend_specific_passes(CompilerConfig* config, CEmitterConfig* econfig, Module* initial_mod) { IrArena* initial_arena = initial_mod->arena; - Module* old_mod = NULL; Module** pmod = &initial_mod; // C lacks a nice way to express constants that can be used in type definitions afterwards, so let's just inline them all. diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 59a980fe7..7ef645383 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -520,7 +520,6 @@ bool compare_string(const char** a, const char** b); static Module* run_backend_specific_passes(CompilerConfig* config, Module* initial_mod) { IrArena* initial_arena = initial_mod->arena; - Module* old_mod = NULL; Module** pmod = &initial_mod; RUN_PASS(lower_entrypoint_args) From e0a2989247341c347e586c7bbe6bb5d451e7db64 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Apr 2024 11:49:17 +0200 Subject: [PATCH 221/693] l2s: rewrite bb in visiting order, do jumps later --- src/frontends/llvm/l2s.c | 57 ++++++++++++-------------------- src/frontends/llvm/l2s_instr.c | 30 ++++++++++++----- src/frontends/llvm/l2s_private.h | 9 +++++ 3 files changed, 51 insertions(+), 45 deletions(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 066154ee1..bf009334f 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -65,15 +65,9 @@ typedef struct { Node* nbb; } TodoBB; -const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb) { - const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); - if (found) return *found; - assert(false); -} - static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); - debug_print("l2s: converting BB %s %d\n", LLVMGetBasicBlockName(bb), bb); + debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); if (get_log_level() <= DEBUG) LLVMDumpValue(bb); @@ -112,6 +106,18 @@ static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { } } +const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb) { + IrArena* a = get_module_arena(p->dst); + const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); + if (found) return *found; + // assert(false); + + TodoBB todo = prepare_bb(p, fn, bb); + BodyBuilder* bb_bb = begin_body(a); + todo.nbb->payload.basic_block.body = write_bb_tail(p, todo.nbb, bb_bb, todo.bb, todo.instr); + return todo.nbb; +} + const Node* convert_function(Parser* p, LLVMValueRef fn) { if (is_llvm_intrinsic(fn)) { warn_print("Skipping unknown LLVM intrinsic function: %s\n", LLVMGetValueName(fn)); @@ -154,39 +160,16 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { const Node* r = fn_addr_helper(a, f); insert_dict(LLVMValueRef, const Node*, p->map, fn, r); - /*if (LLVMCountBasicBlocks(fn) > 0) { + if (LLVMCountBasicBlocks(fn) > 0) { LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); - BodyBuilder* b = begin_body(a); insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); + BodyBuilder* b = begin_body(a); f->payload.fun.body = write_bb_tail(p, f, b, first_bb, LLVMGetFirstInstruction(first_bb)); - }*/ - - if (LLVMCountBasicBlocks(fn) > 0) { - struct List* todo_bbs = new_list(TodoBB); - - for (LLVMBasicBlockRef bb = LLVMGetEntryBasicBlock(fn); bb; bb = LLVMGetNextBasicBlock(bb)) { - if (bb == LLVMGetEntryBasicBlock(fn)) { - LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); - insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); - } else { - TodoBB todo = prepare_bb(p, f, bb); - append_list(TodoBB, todo_bbs, todo); - } - if (bb == LLVMGetLastBasicBlock(fn)) - break; - } - - LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); - BodyBuilder* entry_bb = begin_body(a); - f->payload.fun.body = write_bb_tail(p, f, entry_bb, first_bb, LLVMGetFirstInstruction(first_bb)); - - for (size_t i = 0; i < entries_count_list(todo_bbs); i++) { - TodoBB todo = read_list(TodoBB, todo_bbs)[i]; - BodyBuilder* bb = begin_body(a); - todo.nbb->payload.basic_block.body = write_bb_tail(p, todo.nbb, bb, todo.bb, todo.instr); - } + } - destroy_list(todo_bbs); + while (entries_count_list(p->jumps_todo) > 0) { + JumpTodo todo = pop_last_list(JumpTodo, p->jumps_todo); + convert_jump_finish(p, f, todo); } return r; @@ -265,6 +248,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .scopes = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), + .jumps_todo = new_list(JumpTodo), .annotations_arena = new_arena(), .src = src, .dst = dirty, @@ -307,6 +291,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* } } destroy_dict(p.phis); + destroy_list(p.jumps_todo); destroy_arena(p.annotations_arena); LLVMContextDispose(context); diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index 8e3ba42d1..fc4ece539 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -55,9 +55,21 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { return v; } -static const Node* convert_jump(Parser* p, Node* fn, Node* fn_or_bb, LLVMBasicBlockRef dst) { +static const Node* convert_jump_lazy(Parser* p, Node* fn, Node* fn_or_bb, LLVMBasicBlockRef dst) { IrArena* a = fn->arena; - const Node* dst_bb = convert_basic_block(p, fn, dst); + const Node* wrapper_bb = basic_block(a, fn, empty(a), NULL); + JumpTodo todo = { + .wrapper = wrapper_bb, + .src = fn_or_bb, + .dst = dst, + }; + append_list(JumpTodo, p->jumps_todo, todo); + return jump_helper(a, wrapper_bb, empty(a)); +} + +void convert_jump_finish(Parser* p, Node* fn, JumpTodo todo) { + IrArena* a = fn->arena; + const Node* dst_bb = convert_basic_block(p, fn, todo.dst); BBPhis* phis = find_value_dict(const Node*, BBPhis, p->phis, dst_bb); assert(phis); size_t params_count = entries_count_list(phis->list); @@ -65,7 +77,7 @@ static const Node* convert_jump(Parser* p, Node* fn, Node* fn_or_bb, LLVMBasicBl for (size_t i = 0; i < params_count; i++) { LLVMValueRef phi = read_list(LLVMValueRef, phis->list)[i]; for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { - if (convert_basic_block(p, fn, LLVMGetIncomingBlock(phi, j)) == fn_or_bb) { + if (convert_basic_block(p, fn, LLVMGetIncomingBlock(phi, j)) == todo.src) { params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); goto next; } @@ -73,7 +85,7 @@ static const Node* convert_jump(Parser* p, Node* fn, Node* fn_or_bb, LLVMBasicBl assert(false && "failed to find the appropriate source"); next: continue; } - return jump_helper(a, dst_bb, nodes(a, params_count, params)); + todo.wrapper->payload.basic_block.body = jump_helper(a, dst_bb, nodes(a, params_count, params)); } static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* element_type) { @@ -150,26 +162,26 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM return (EmittedInstr) { .terminator = branch(a, (Branch) { .branch_condition = condition, - .true_jump = convert_jump(p, fn, fn_or_bb, targets[0]), - .false_jump = convert_jump(p, fn, fn_or_bb, targets[1]), + .true_jump = convert_jump_lazy(p, fn, fn_or_bb, targets[0]), + .false_jump = convert_jump_lazy(p, fn, fn_or_bb, targets[1]), }) }; } else { assert(n_targets == 1); return (EmittedInstr) { - .terminator = convert_jump(p, fn, fn_or_bb, targets[0]) + .terminator = convert_jump_lazy(p, fn, fn_or_bb, targets[0]) }; } } case LLVMSwitch: { const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); - const Node* default_jump = convert_jump(p, fn, fn_or_bb, LLVMGetOperand(instr, 1)); + const Node* default_jump = convert_jump_lazy(p, fn, fn_or_bb, LLVMGetOperand(instr, 1)); int n_targets = LLVMGetNumOperands(instr) / 2 - 1; LARRAY(const Node*, targets, n_targets); LARRAY(const Node*, literals, n_targets); for (size_t i = 0; i < n_targets; i++) { literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); - targets[i] = convert_jump(p, fn, fn_or_bb, LLVMGetOperand(instr, i * 2 + 3)); + targets[i] = convert_jump_lazy(p, fn, fn_or_bb, LLVMGetOperand(instr, i * 2 + 3)); } return (EmittedInstr) { .terminator = br_switch(a, (Switch) { diff --git a/src/frontends/llvm/l2s_private.h b/src/frontends/llvm/l2s_private.h index e9fdb048a..18c36ac47 100644 --- a/src/frontends/llvm/l2s_private.h +++ b/src/frontends/llvm/l2s_private.h @@ -17,6 +17,7 @@ typedef struct { struct Dict* annotations; struct Dict* scopes; struct Dict* phis; + struct List* jumps_todo; Arena* annotations_arena; LLVMModuleRef src; Module* dst; @@ -58,6 +59,14 @@ typedef struct { struct List* list; } BBPhis; +typedef struct { + Node* wrapper; + Node* src; + LLVMBasicBlockRef dst; +} JumpTodo; + +void convert_jump_finish(Parser* p, Node* fn, JumpTodo todo); + EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc); From 39cad27d6c4b35db316ee0b1144b507232a9215d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Apr 2024 11:51:15 +0200 Subject: [PATCH 222/693] reconvergence_heuristics: fix stale versions of loop variables being used --- include/shady/ir.h | 1 + src/shady/node.c | 7 ++++++ src/shady/passes/reconvergence_heuristics.c | 24 ++++++++++++++------- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 10d4e08b2..1657517c6 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -140,6 +140,7 @@ Nodes filter_out_annotation(IrArena*, Nodes, const char* name); bool is_abstraction (const Node*); String get_abstraction_name (const Node* abs); String get_abstraction_name_unsafe(const Node* abs); +String get_abstraction_name_safe(const Node* abs); const Node* get_abstraction_body (const Node* abs); Nodes get_abstraction_params(const Node* abs); diff --git a/src/shady/node.c b/src/shady/node.c index 0688fcfcb..3d85cb2ae 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -274,6 +274,13 @@ String get_abstraction_name_unsafe(const Node* abs) { } } +String get_abstraction_name_safe(const Node* abs) { + String name = get_abstraction_name_unsafe(abs); + if (name) + return name; + return format_string_interned(abs->arena, "%%%d", abs->id); +} + const Node* get_abstraction_body(const Node* abs) { assert(is_abstraction(abs)); switch (abs->tag) { diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 724d8be69..18e14cd9b 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -60,14 +60,22 @@ static void gather_exiting_nodes(LoopTree* lt, const CFNode* entry, const CFNode } } -static void find_unbound_vars(const Node* node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { +static bool find_in_nodes(Nodes nodes, const Node* n) { + for (size_t i = 0; i < nodes.count; i++) + if (nodes.nodes[i] == n) + return true; + return false; +} + +static void find_unbound_vars(const Node* loop_header, const Node* exiting_node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { const Node* free_post; size_t i = 0; + Nodes ignore = get_abstraction_params(loop_header); while (dict_iter(free_set, &i, &free_post, NULL)) { const Node* bound_pre; size_t j = 0; while (dict_iter(bound_set, &j, &bound_pre, NULL)) { - if (bound_pre == free_post) { + if (bound_pre == free_post && !find_in_nodes(ignore, bound_pre)) { goto next; } } @@ -75,7 +83,7 @@ static void find_unbound_vars(const Node* node, struct Dict* bound_set, struct D log_string(DEBUGVV, "Found variable used outside it's control scope: "); log_node(DEBUGVV, free_post); log_string(DEBUGVV, " (original:"); - log_node(DEBUGVV, node); + log_node(DEBUGVV, exiting_node); log_string(DEBUGVV, " )\n"); append_list(const Node*, leaking, free_post); @@ -117,7 +125,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { gather_exiting_nodes(ctx->current_looptree, current_node, current_node, exiting_nodes); for (size_t i = 0; i < entries_count_list(exiting_nodes); i++) { - debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name(read_list(CFNode*, exiting_nodes)[i]->node), get_abstraction_name(node)); + debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(read_list(CFNode*, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); } BodyBuilder* outer_bb = begin_body(arena); @@ -148,7 +156,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { CFNode* cf_post = cfg_lookup(ctx->fwd_cfg, exiting_node->node); CFNodeVariables* post = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_post); leaking[i] = new_list(const Type*); - find_unbound_vars(exiting_node->node, pre->bound_set, post->free_set, leaking[i]); + find_unbound_vars(node, exiting_node->node, pre->bound_set, post->free_set, leaking[i]); size_t leaking_count = entries_count_list(leaking[i]); LARRAY(const Node*, exit_fwd_allocas_tmp, leaking_count); @@ -267,7 +275,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { destroy_dict(rewriter->map); rewriter->map = old_map; - register_processed_list(rewriter, get_abstraction_params(node), nparams); + //register_processed_list(rewriter, get_abstraction_params(node), nparams); // restore the old context for (size_t i = 0; i < exiting_nodes_count; i++) { @@ -321,7 +329,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { recovered_args[j] = gen_load(exit_recover_bb, exit_param_allocas[i].nodes[j]); exit_numbers[i] = int32_literal(arena, i); - Node* exit_bb = basic_block(arena, fn, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name(exiting_node->node))); + Node* exit_bb = basic_block(arena, fn, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); if (recreated_exit->tag == BasicBlock_TAG) { exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, jump(arena, (Jump) { .target = recreated_exit, @@ -502,7 +510,7 @@ static const Node* process_node(Context* ctx, const Node* node) { .yield_types = yield_types }), true), "jp_postdom"); - Node* pre_join = basic_block(arena, fn, exit_args, format_string_arena(arena->arena, "merge_%s_%s", get_abstraction_name(ctx->current_abstraction) , get_abstraction_name(idom))); + Node* pre_join = basic_block(arena, fn, exit_args, format_string_arena(arena->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); pre_join->payload.basic_block.body = join(arena, (Join) { .join_point = join_token, .args = exit_args From b5552d1c697195de614373272618f48278634898 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Apr 2024 11:51:50 +0200 Subject: [PATCH 223/693] print: deal with anonymous BBs properly --- src/shady/print.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/shady/print.c b/src/shady/print.c index a7c47f7a9..c2a191482 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -126,7 +126,10 @@ static void print_basic_block(PrinterCtx* ctx, const Node* bb) { printf(GREEN); printf("\n\ncont"); printf(BYELLOW); - printf(" %s", bb->payload.basic_block.name); + if (bb->payload.basic_block.name && strlen(bb->payload.basic_block.name) > 0) + printf(" %s", bb->payload.basic_block.name); + else + printf(" %%%d", bb->id); printf(RESET); if (ctx->config.print_ptrs) { printf(" %zu:: ", (size_t)(void*)bb); @@ -948,7 +951,10 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { } case BasicBlock_TAG: { printf(BYELLOW); - printf("%s", node->payload.basic_block.name); + if (node->payload.basic_block.name && strlen(node->payload.basic_block.name) > 0) + printf("%s", node->payload.basic_block.name); + else + printf("%%%d", node->id); printf(RESET); break; } From eb37f7764ea9dcd0d886d2c95e707f408f0d5604 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Apr 2024 12:05:17 +0200 Subject: [PATCH 224/693] lift_indirect_targets: compute the CFG where the liftee is the entry and use that to compute free variables --- src/shady/passes/lift_indirect_targets.c | 36 +++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 6d0f2dff7..92db8c23e 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -27,7 +27,6 @@ typedef struct Context_ { Rewriter rewriter; CFG* cfg; const UsesMap* uses; - struct Dict* live_vars; struct Dict* lifted; bool disable_lowering; @@ -83,27 +82,32 @@ static void add_to_recover_context(struct List* recover_context, struct Dict* se } } -static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name) { - assert(is_basic_block(cont) || is_case(cont)); - LiftedCont** found = find_value_dict(const Node*, LiftedCont*, ctx->lifted, cont); +static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, String given_name) { + assert(is_basic_block(liftee) || is_case(liftee)); + LiftedCont** found = find_value_dict(const Node*, LiftedCont*, ctx->lifted, liftee); if (found) return *found; IrArena* a = ctx->rewriter.dst_arena; - Nodes oparams = get_abstraction_params(cont); - const Node* obody = get_abstraction_body(cont); + Nodes oparams = get_abstraction_params(liftee); + const Node* obody = get_abstraction_body(liftee); - String name = is_basic_block(cont) ? format_string_arena(a->arena, "%s_%s", get_abstraction_name(cont->payload.basic_block.fn), get_abstraction_name(cont)) : unique_name(a, given_name); + String name = is_basic_block(liftee) ? format_string_arena(a->arena, "%s_%s", get_abstraction_name(liftee->payload.basic_block.fn), get_abstraction_name(liftee)) : unique_name(a, given_name); // Compute the live stuff we'll need - CFNode* cf_node = cfg_lookup(ctx->cfg, cont); - CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_node); + CFG* cfg_rooted_in_liftee = build_cfg(ctx->cfg->entry->node, liftee, NULL, false); + CFNode* cf_node = cfg_lookup(cfg_rooted_in_liftee, liftee); + struct Dict* live_vars = compute_cfg_variables_map(cfg_rooted_in_liftee); + CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, live_vars, cf_node); struct List* recover_context = new_list(const Node*); - add_to_recover_context(recover_context, node_vars->bound_set, cont); + add_to_recover_context(recover_context, node_vars->free_set, liftee); size_t recover_context_size = entries_count_list(recover_context); - debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", name, recover_context_size); + destroy_cfg_variables_map(live_vars); + destroy_cfg(cfg_rooted_in_liftee); + + debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { const Node* item = read_list(const Node*, recover_context)[i]; debugv_print("%s %%%d", get_value_name(item) ? get_value_name(item) : "", item->id); @@ -116,9 +120,9 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* cont, String given_name Nodes new_params = recreate_variables(&ctx->rewriter, oparams); LiftedCont* lifted_cont = calloc(sizeof(LiftedCont), 1); - lifted_cont->old_cont = cont; + lifted_cont->old_cont = liftee; lifted_cont->save_values = recover_context; - insert_dict(const Node*, LiftedCont*, ctx->lifted, cont, lifted_cont); + insert_dict(const Node*, LiftedCont*, ctx->lifted, liftee, lifted_cont); Context lifting_ctx = *ctx; lifting_ctx.rewriter = create_children_rewriter(&ctx->rewriter); @@ -175,7 +179,6 @@ static const Node* process_node(Context* ctx, const Node* node) { Context fn_ctx = *ctx; fn_ctx.cfg = build_fn_cfg(node); fn_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); - fn_ctx.live_vars = compute_cfg_variables_map(fn_ctx.cfg); fn_ctx.disable_lowering = lookup_annotation(node, "Internal"); ctx = &fn_ctx; @@ -183,7 +186,6 @@ static const Node* process_node(Context* ctx, const Node* node) { recreate_decl_body_identity(&ctx->rewriter, node, new); destroy_uses_map(ctx->uses); - destroy_cfg_variables_map(ctx->live_vars); destroy_cfg(ctx->cfg); return new; } @@ -205,7 +207,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* otail = get_let_tail(node); BodyBuilder* bb = begin_body(a); - LiftedCont* lifted_tail = lambda_lift(ctx, otail, unique_name(a, format_string_arena(a->arena, "post_control_%s", get_abstraction_name(ctx->cfg->entry->node)))); + LiftedCont* lifted_tail = lambda_lift(ctx, otail, unique_name(a, format_string_arena(a->arena, "lifted %s", get_abstraction_name_safe(otail)))); const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); @@ -253,7 +255,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { } destroy_dict(ctx.lifted); destroy_rewriter(&ctx.rewriter); - log_module(DEBUGVV, config, dst); + // log_module(DEBUGVV, config, dst); verify_module(config, dst); src = dst; if (oa) From cc24ad2b0d3531fbf455de8a7fb7ee2052b8dc67 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 27 Apr 2024 18:19:56 +0200 Subject: [PATCH 225/693] fix LLVM front-end for the 10 trillionth time --- src/frontends/llvm/l2s.c | 52 +++++++++++++++++--------------- src/frontends/llvm/l2s_instr.c | 48 ++++++++++++++--------------- src/frontends/llvm/l2s_private.h | 15 +++++---- src/frontends/llvm/l2s_value.c | 2 +- 4 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index bf009334f..822b5105b 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -36,7 +36,8 @@ static bool cmp_opaque_ptr(OpaqueRef* a, OpaqueRef* b) { KeyHash hash_node(Node**); bool compare_node(Node**, Node**); -static const Node* write_bb_tail(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMBasicBlockRef bb, LLVMValueRef first_instr) { +static const Node* write_bb_tail(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef bb, LLVMValueRef first_instr) { + BodyBuilder* b = begin_body(fn_or_bb->arena); LLVMValueRef instr; for (instr = first_instr; instr; instr = LLVMGetNextInstruction(instr)) { bool last = instr == LLVMGetLastInstruction(bb); @@ -44,7 +45,7 @@ static const Node* write_bb_tail(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM assert(LLVMGetBasicBlockTerminator(bb) == instr); // LLVMDumpValue(instr); // printf("\n"); - EmittedInstr emitted = convert_instruction(p, fn_or_bb, b, instr); + EmittedInstr emitted = convert_instruction(p, fn_ctx, fn_or_bb, b, instr); if (emitted.terminator) return finish_body(b, emitted.terminator); if (!emitted.instruction) @@ -65,7 +66,7 @@ typedef struct { Node* nbb; } TodoBB; -static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { +static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); if (get_log_level() <= DEBUG) @@ -92,9 +93,9 @@ static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { String name = LLVMGetBasicBlockName(bb); if (!name || strlen(name) == 0) name = unique_name(a, "bb"); - Node* nbb = basic_block(a, fn, params, name); + Node* nbb = basic_block(a, fn_ctx->fn, params, name); insert_dict(LLVMValueRef, const Node*, p->map, bb, nbb); - insert_dict(const Node*, struct List*, p->phis, nbb, phis); + insert_dict(const Node*, struct List*, fn_ctx->phis, nbb, phis); TodoBB todo = { .bb = bb, .instr = instr, @@ -106,15 +107,14 @@ static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { } } -const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb) { +const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); if (found) return *found; // assert(false); - TodoBB todo = prepare_bb(p, fn, bb); - BodyBuilder* bb_bb = begin_body(a); - todo.nbb->payload.basic_block.body = write_bb_tail(p, todo.nbb, bb_bb, todo.bb, todo.instr); + TodoBB todo = prepare_bb(p, fn_ctx, bb); + todo.nbb->payload.basic_block.body = write_bb_tail(p, fn_ctx, todo.nbb, todo.bb, todo.instr); return todo.nbb; } @@ -157,20 +157,33 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { break; } Node* f = function(p->dst, params, LLVMGetValueName(fn), annotations, fn_type->payload.fn_type.return_types); + FnParseCtx fn_parse_ctx = { + .fn = f, + .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), + .jumps_todo = new_list(JumpTodo), + }; const Node* r = fn_addr_helper(a, f); insert_dict(LLVMValueRef, const Node*, p->map, fn, r); if (LLVMCountBasicBlocks(fn) > 0) { LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); - BodyBuilder* b = begin_body(a); - f->payload.fun.body = write_bb_tail(p, f, b, first_bb, LLVMGetFirstInstruction(first_bb)); + f->payload.fun.body = write_bb_tail(p, &fn_parse_ctx, f, first_bb, LLVMGetFirstInstruction(first_bb)); } - while (entries_count_list(p->jumps_todo) > 0) { - JumpTodo todo = pop_last_list(JumpTodo, p->jumps_todo); - convert_jump_finish(p, f, todo); + while (entries_count_list(fn_parse_ctx.jumps_todo) > 0) { + JumpTodo todo = pop_last_list(JumpTodo, fn_parse_ctx.jumps_todo); + convert_jump_finish(p, &fn_parse_ctx, todo); + } + { + size_t i = 0; + struct List* phis_list; + while (dict_iter(fn_parse_ctx.phis, &i, NULL, &phis_list)) { + destroy_list(phis_list); + } } + destroy_dict(fn_parse_ctx.phis); + destroy_list(fn_parse_ctx.jumps_todo); return r; } @@ -247,8 +260,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .scopes = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), - .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), - .jumps_todo = new_list(JumpTodo), .annotations_arena = new_arena(), .src = src, .dst = dirty, @@ -283,15 +294,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* destroy_dict(p.map); destroy_dict(p.annotations); destroy_dict(p.scopes); - { - size_t i = 0; - struct List* phis_list; - while (dict_iter(p.phis, &i, NULL, &phis_list)) { - destroy_list(phis_list); - } - } - destroy_dict(p.phis); - destroy_list(p.jumps_todo); destroy_arena(p.annotations_arena); LLVMContextDispose(context); diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index fc4ece539..45c054c72 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -55,29 +55,30 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { return v; } -static const Node* convert_jump_lazy(Parser* p, Node* fn, Node* fn_or_bb, LLVMBasicBlockRef dst) { - IrArena* a = fn->arena; - const Node* wrapper_bb = basic_block(a, fn, empty(a), NULL); +static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef dst) { + IrArena* a = fn_or_bb->arena; + const Node* wrapper_bb = basic_block(a, fn_ctx->fn, empty(a), NULL); JumpTodo todo = { .wrapper = wrapper_bb, .src = fn_or_bb, .dst = dst, }; - append_list(JumpTodo, p->jumps_todo, todo); + append_list(JumpTodo, fn_ctx->jumps_todo, todo); + convert_basic_block(p, fn_ctx, dst); return jump_helper(a, wrapper_bb, empty(a)); } -void convert_jump_finish(Parser* p, Node* fn, JumpTodo todo) { - IrArena* a = fn->arena; - const Node* dst_bb = convert_basic_block(p, fn, todo.dst); - BBPhis* phis = find_value_dict(const Node*, BBPhis, p->phis, dst_bb); +void convert_jump_finish(Parser* p, FnParseCtx* fn_ctx, JumpTodo todo) { + IrArena* a = fn_ctx->fn->arena; + const Node* dst_bb = convert_basic_block(p, fn_ctx, todo.dst); + BBPhis* phis = find_value_dict(const Node*, BBPhis, fn_ctx->phis, dst_bb); assert(phis); size_t params_count = entries_count_list(phis->list); LARRAY(const Node*, params, params_count); for (size_t i = 0; i < params_count; i++) { LLVMValueRef phi = read_list(LLVMValueRef, phis->list)[i]; for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { - if (convert_basic_block(p, fn, LLVMGetIncomingBlock(phi, j)) == todo.src) { + if (convert_basic_block(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == todo.src) { params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); goto next; } @@ -98,13 +99,8 @@ static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* eleme } /// instr may be an instruction or a constantexpr -EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { - Node* fn = fn_or_bb; - if (fn) { - if (fn_or_bb->tag == BasicBlock_TAG) - fn = (Node*) fn_or_bb->payload.basic_block.fn; - assert(fn->tag == Function_TAG); - } +EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { + Node* fn = fn_ctx ? fn_ctx->fn : NULL; IrArena* a = get_module_arena(p->dst); int num_ops = LLVMGetNumOperands(instr); @@ -133,13 +129,13 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM if (!found) { Nodes str = scope_to_string(p, dbgloc); insert_dict(const Node*, Nodes, p->scopes, fn_or_bb, str); - debug_print("Found a debug location for "); - log_node(DEBUG, fn_or_bb); + debugv_print("Found a debug location for "); + log_node(DEBUGV, fn_or_bb); for (size_t i = 0; i < str.count; i++) { - log_node(DEBUG, str.nodes[i]); - debug_print(" -> "); + log_node(DEBUGV, str.nodes[i]); + debugv_print(" -> "); } - debug_print(" (depth= %zu)\n", str.count); + debugv_print(" (depth= %zu)\n", str.count); } } } @@ -162,26 +158,26 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM return (EmittedInstr) { .terminator = branch(a, (Branch) { .branch_condition = condition, - .true_jump = convert_jump_lazy(p, fn, fn_or_bb, targets[0]), - .false_jump = convert_jump_lazy(p, fn, fn_or_bb, targets[1]), + .true_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0]), + .false_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[1]), }) }; } else { assert(n_targets == 1); return (EmittedInstr) { - .terminator = convert_jump_lazy(p, fn, fn_or_bb, targets[0]) + .terminator = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0]) }; } } case LLVMSwitch: { const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); - const Node* default_jump = convert_jump_lazy(p, fn, fn_or_bb, LLVMGetOperand(instr, 1)); + const Node* default_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, LLVMGetOperand(instr, 1)); int n_targets = LLVMGetNumOperands(instr) / 2 - 1; LARRAY(const Node*, targets, n_targets); LARRAY(const Node*, literals, n_targets); for (size_t i = 0; i < n_targets; i++) { literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); - targets[i] = convert_jump_lazy(p, fn, fn_or_bb, LLVMGetOperand(instr, i * 2 + 3)); + targets[i] = convert_jump_lazy(p, fn_ctx, fn_or_bb, LLVMGetOperand(instr, i * 2 + 3)); } return (EmittedInstr) { .terminator = br_switch(a, (Switch) { diff --git a/src/frontends/llvm/l2s_private.h b/src/frontends/llvm/l2s_private.h index 18c36ac47..24f2ab694 100644 --- a/src/frontends/llvm/l2s_private.h +++ b/src/frontends/llvm/l2s_private.h @@ -16,13 +16,17 @@ typedef struct { struct Dict* map; struct Dict* annotations; struct Dict* scopes; - struct Dict* phis; - struct List* jumps_todo; Arena* annotations_arena; LLVMModuleRef src; Module* dst; } Parser; +typedef struct { + Node* fn; + struct Dict* phis; + struct List* jumps_todo; +} FnParseCtx; + #ifndef LLVM_VERSION_MAJOR #error "Missing LLVM_VERSION_MAJOR" #else @@ -47,7 +51,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t); const Node* convert_metadata(Parser* p, LLVMMetadataRef meta); const Node* convert_global(Parser* p, LLVMValueRef global); const Node* convert_function(Parser* p, LLVMValueRef fn); -const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb); +const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); typedef struct { const Node* terminator; @@ -65,9 +69,8 @@ typedef struct { LLVMBasicBlockRef dst; } JumpTodo; -void convert_jump_finish(Parser* p, Node* fn, JumpTodo todo); - -EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); +void convert_jump_finish(Parser* p, FnParseCtx*, JumpTodo todo); +EmittedInstr convert_instruction(Parser* p, FnParseCtx*, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc); diff --git a/src/frontends/llvm/l2s_value.c b/src/frontends/llvm/l2s_value.c index 495fe55c1..4d9a36284 100644 --- a/src/frontends/llvm/l2s_value.c +++ b/src/frontends/llvm/l2s_value.c @@ -85,7 +85,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { r = ref_decl_helper(a, decl); insert_dict(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = begin_body(a); - EmittedInstr emitted = convert_instruction(p, NULL, bb, v); + EmittedInstr emitted = convert_instruction(p, NULL, NULL, bb, v); Nodes types = singleton(t); decl->payload.constant.instruction = bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, emitted.instruction, &types); return r; From 02e84fc3e986294197ea7394e14dd65311b9cca4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 28 Apr 2024 11:41:25 +0200 Subject: [PATCH 226/693] fix cmake on fedora --- CMakeLists.txt | 2 +- src/shady/config.c | 0 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/shady/config.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2aaf7a804..af3b947db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,7 +86,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # required for MSVC diff --git a/src/shady/config.c b/src/shady/config.c new file mode 100644 index 000000000..e69de29bb From 50aa70ee523d3ce26f55facd646d3c040343783f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 28 Apr 2024 11:41:47 +0200 Subject: [PATCH 227/693] added flag to set word and ptr size --- include/shady/ir.h | 22 ++++++--- samples/checkerboard/checkerboard.c | 2 +- src/driver/cli.c | 22 +++++++++ src/driver/driver.c | 2 +- src/driver/slim.c | 2 +- src/driver/vcc.c | 2 +- src/frontends/llvm/l2s.c | 2 +- src/frontends/slim/parser.c | 2 +- src/frontends/spirv/s2s.c | 4 +- src/frontends/spirv/s2s.h | 2 +- src/runtime/runtime_test.c | 2 +- src/shady/CMakeLists.txt | 1 + src/shady/compile.c | 67 ------------------------- src/shady/config.c | 76 +++++++++++++++++++++++++++++ test/test_math.c | 3 +- 15 files changed, 127 insertions(+), 84 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 1657517c6..1368c2d7d 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -64,6 +64,18 @@ const Node* get_declaration(const Module*, String); //////////////////////////////// IR Arena //////////////////////////////// +typedef struct { + IntSizes ptr_size; + /// The base type for emulated memory + IntSizes word_size; +} PointerModel; + +typedef struct { + PointerModel memory; +} TargetConfig; + +TargetConfig default_target_config(); + typedef struct { bool name_bound; bool check_op_classes; @@ -89,11 +101,7 @@ typedef struct { uint32_t workgroup_size[3]; } specializations; - struct { - IntSizes ptr_size; - /// The base type for emulated memory - IntSizes word_size; - } memory; + PointerModel memory; /// 'folding' optimisations - happen in the constructors directly struct { @@ -102,7 +110,7 @@ typedef struct { } optimisations; } ArenaConfig; -ArenaConfig default_arena_config(); +ArenaConfig default_arena_config(const TargetConfig* target); IrArena* new_ir_arena(ArenaConfig); void destroy_ir_arena(IrArena*); @@ -314,6 +322,8 @@ typedef struct CompilerConfig_ { uint32_t subgroup_size; } specialization; + TargetConfig target; + struct { struct { void* uptr; void (*fn)(void*, String, Module*); } after_pass; } hooks; diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 84af926d0..052fd572e 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -65,7 +65,7 @@ int main(int argc, char **argv) info_print("Device-side address is: %zu\n", buf_addr); - IrArena* a = new_ir_arena(default_arena_config()); + IrArena* a = new_ir_arena(default_arena_config(&compiler_config.target)); Module* m; if (driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, "checkerboard", &m) != NoError) error("Failed to load checkerboard module"); diff --git a/src/driver/cli.c b/src/driver/cli.c index 10932017a..8bd18762c 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -95,6 +95,18 @@ F(config->optimisations.inline_everything, inline-everything) \ F(config->hacks.restructure_everything, restructure-everything) \ F(config->hacks.recover_structure, recover-structure) \ +static IntSizes parse_int_size(String argv) { + if (strcmp(argv, "8") == 0) + return IntTy8; + if (strcmp(argv, "16") == 0) + return IntTy16; + if (strcmp(argv, "32") == 0) + return IntTy32; + if (strcmp(argv, "64") == 0) + return IntTy64; + error("Valid pointer sizes are 8, 16, 32 or 64."); +} + void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { int argc = *pargc; @@ -142,6 +154,14 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a default: break; } config->specialization.execution_model = em; + } else if (strcmp(argv[i], "--word-size") == 0) { + argv[i] = NULL; + i++; + config->target.memory.word_size = parse_int_size(argv[i]); + } else if (strcmp(argv[i], "--pointer-size") == 0) { + argv[i] = NULL; + i++; + config->target.memory.ptr_size = parse_int_size(argv[i]); } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { help = true; continue; @@ -157,6 +177,8 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a error_print(" --no-dynamic-scheduling Disable the built-in dynamic scheduler, restricts code to only leaf functions\n"); error_print(" --simt2d Emits SIMD code instead of SIMT, only effective with the C backend.\n"); error_print(" --entry-point Selects an entry point for the program to be specialized on.\n"); + error_print(" --word-size <8|16|32|64> Sets the word size for physical memory emulation (default=32)\n"); + error_print(" --pointer-size <8|16|32|64> Sets the pointer size for physical pointers (default=64)\n"); #define EM(name, _) #name", " error_print(" --execution-model Selects an entry point for the program to be specialized on.\nPossible values: " EXECUTION_MODELS(EM)); #undef EM diff --git a/src/driver/driver.c b/src/driver/driver.c index b008374f8..4eeba9344 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -50,7 +50,7 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang } case SrcSPIRV: { #ifdef SPV_PARSER_PRESENT - parse_spirv_into_shady(len, file_contents, name, mod); + parse_spirv_into_shady(config, len, file_contents, name, mod); #else assert(false && "SPIR-V front-end missing in this version"); #endif diff --git a/src/driver/slim.c b/src/driver/slim.c index d860e6e61..95d399e60 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -22,7 +22,7 @@ int main(int argc, char** argv) { cli_parse_compiler_config_args(&args.config, &argc, argv); cli_parse_input_files(args.input_filenames, &argc, argv); - IrArena* arena = new_ir_arena(default_arena_config()); + IrArena* arena = new_ir_arena(default_arena_config(&args.config.target)); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one driver_load_source_files(&args, mod); diff --git a/src/driver/vcc.c b/src/driver/vcc.c index 1a39c8012..f74937117 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -68,7 +68,7 @@ int main(int argc, char** argv) { exit(MissingInputArg); } - ArenaConfig aconfig = default_arena_config(); + ArenaConfig aconfig = default_arena_config(&args.config.target); IrArena* arena = new_ir_arena(aconfig); int clang_retval = system("clang --version"); diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 822b5105b..40d31c6ea 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -248,7 +248,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* } info_print("LLVM IR parsed successfully\n"); - ArenaConfig aconfig = default_arena_config(); + ArenaConfig aconfig = default_arena_config(&config->target); aconfig.check_types = false; aconfig.allow_fold = false; diff --git a/src/frontends/slim/parser.c b/src/frontends/slim/parser.c index 698b2b12c..4fbf511e8 100644 --- a/src/frontends/slim/parser.c +++ b/src/frontends/slim/parser.c @@ -1108,7 +1108,7 @@ static void parse_shady_ir(ParserConfig config, const char* contents, Module* mo #include "transform/internal_constants.h" Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name) { - ArenaConfig aconfig = default_arena_config(); + ArenaConfig aconfig = default_arena_config(&config->target); aconfig.name_bound = false; aconfig.check_op_classes = false; aconfig.check_types = false; diff --git a/src/frontends/spirv/s2s.c b/src/frontends/spirv/s2s.c index 8751be7b6..c7d929f71 100644 --- a/src/frontends/spirv/s2s.c +++ b/src/frontends/spirv/s2s.c @@ -1356,8 +1356,8 @@ bool compare_spvid(SpvId* pa, SpvId* pb) { return *pa == *pb; } -S2SError parse_spirv_into_shady(size_t len, const char* data, String name, Module** dst) { - IrArena* a = new_ir_arena(default_arena_config()); +S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { + IrArena* a = new_ir_arena(default_arena_config(&config->target)); *dst = new_module(a, name); SpvParser parser = { diff --git a/src/frontends/spirv/s2s.h b/src/frontends/spirv/s2s.h index 9bef30671..a05e98265 100644 --- a/src/frontends/spirv/s2s.h +++ b/src/frontends/spirv/s2s.h @@ -8,6 +8,6 @@ typedef enum { S2S_FailedParsingGeneric, } S2SError; -S2SError parse_spirv_into_shady(size_t len, const char* data, String name, Module**); +S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const char* data, String name, Module**); #endif diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 0b20b7894..64fb9afa0 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -48,7 +48,7 @@ int main(int argc, char* argv[]) { Program* program; IrArena* arena = NULL; - arena = new_ir_arena(default_arena_config()); + arena = new_ir_arena(default_arena_config(&args.driver_config.config.target)); if (entries_count_list(args.driver_config.input_filenames) == 0) { Module* module; driver_load_source_file(&args.driver_config.config, SrcSlim, strlen(default_shader), default_shader, "runtime_test", &module); diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index e83c3793f..d43827ff7 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -37,6 +37,7 @@ set(SHADY_SOURCES compile.c annotation.c module.c + config.c analysis/cfg.c analysis/cfg_dump.c diff --git a/src/shady/compile.c b/src/shady/compile.c index 511856e1f..31f6d9347 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -10,73 +10,6 @@ #include -#define KiB * 1024 -#define MiB * 1024 KiB - -CompilerConfig default_compiler_config() { - return (CompilerConfig) { - .dynamic_scheduling = true, - .per_thread_stack_size = 4 KiB, - - .target_spirv_version = { - .major = 1, - .minor = 4 - }, - - .lower = { - .emulate_physical_memory = true, - .emulate_generic_ptrs = true, - }, - - .logging = { - // most of the time, we are not interested in seeing generated & internal code in the debug output - //.print_internal = true, - //.print_generated = true, - .print_builtin = true, - }, - - .optimisations = { - .cleanup = { - .after_every_pass = true, - .delete_unused_instructions = true, - } - }, - - .specialization = { - .subgroup_size = 8, - .entry_point = NULL - } - }; -} - -ArenaConfig default_arena_config() { - ArenaConfig config = { - .is_simt = true, - .name_bound = true, - .allow_fold = true, - .check_types = true, - .validate_builtin_types = true, - .check_op_classes = true, - - .memory = { - .word_size = IntTy8, - .ptr_size = IntTy64, - }, - - .optimisations = { - .delete_unreachable_structured_cases = true, - }, - }; - - for (size_t i = 0; i < NumAddressSpaces; i++) { - // by default, all address spaces are physical ! - config.address_spaces[i].physical = true; - config.address_spaces[i].allowed = true; - } - - return config; -} - void add_scheduler_source(const CompilerConfig* config, Module* dst) { ParserConfig pconfig = { .front_end = true, diff --git a/src/shady/config.c b/src/shady/config.c index e69de29bb..902d47652 100644 --- a/src/shady/config.c +++ b/src/shady/config.c @@ -0,0 +1,76 @@ +#include "shady/ir.h" + +#define KiB * 1024 +#define MiB * 1024 KiB + +CompilerConfig default_compiler_config() { + return (CompilerConfig) { + .dynamic_scheduling = true, + .per_thread_stack_size = 4 KiB, + + .target_spirv_version = { + .major = 1, + .minor = 4 + }, + + .lower = { + .emulate_physical_memory = true, + .emulate_generic_ptrs = true, + }, + + .logging = { + // most of the time, we are not interested in seeing generated & internal code in the debug output + //.print_internal = true, + //.print_generated = true, + .print_builtin = true, + }, + + .optimisations = { + .cleanup = { + .after_every_pass = true, + .delete_unused_instructions = true, + } + }, + + .target = default_target_config(), + + .specialization = { + .subgroup_size = 8, + .entry_point = NULL + } + }; +} + +TargetConfig default_target_config() { + return (TargetConfig) { + .memory = { + .word_size = IntTy32, + .ptr_size = IntTy64, + }, + }; +} + +ArenaConfig default_arena_config(const TargetConfig* target) { + ArenaConfig config = { + .is_simt = true, + .name_bound = true, + .allow_fold = true, + .check_types = true, + .validate_builtin_types = true, + .check_op_classes = true, + + .optimisations = { + .delete_unreachable_structured_cases = true, + }, + + .memory = target->memory + }; + + for (size_t i = 0; i < NumAddressSpaces; i++) { + // by default, all address spaces are physical ! + config.address_spaces[i].physical = true; + config.address_spaces[i].allowed = true; + } + + return config; +} \ No newline at end of file diff --git a/test/test_math.c b/test/test_math.c index de7335761..9db08a674 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -91,7 +91,8 @@ static void test_int_literals(IrArena* a) { int main(int argc, char** argv) { cli_parse_common_args(&argc, argv); - ArenaConfig acfg = default_arena_config(); + TargetConfig target_config = default_target_config(); + ArenaConfig acfg = default_arena_config(&target_config); acfg.check_types = true; acfg.allow_fold = true; IrArena* a = new_ir_arena(acfg); From 18e39cde063d93a4bccd778cc715ab999592e2d8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 28 Apr 2024 11:41:56 +0200 Subject: [PATCH 228/693] emit_spv: fix unintended fallthrough --- src/shady/emit/spirv/emit_spv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 7ef645383..9df983605 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -204,12 +204,14 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo case Jump_TAG: { add_branch_phis(emitter, fn_builder, basic_block_builder, terminator); spvb_branch(basic_block_builder, find_reserved_id(emitter, terminator->payload.jump.target)); + return; } case Branch_TAG: { SpvId condition = emit_value(emitter, basic_block_builder, terminator->payload.branch.branch_condition); add_branch_phis(emitter, fn_builder, basic_block_builder, terminator->payload.branch.true_jump); add_branch_phis(emitter, fn_builder, basic_block_builder, terminator->payload.branch.false_jump); spvb_branch_conditional(basic_block_builder, condition, find_reserved_id(emitter, terminator->payload.branch.true_jump->payload.jump.target), find_reserved_id(emitter, terminator->payload.branch.false_jump->payload.jump.target)); + return; } case Switch_TAG: { SpvId inspectee = emit_value(emitter, basic_block_builder, terminator->payload.br_switch.switch_value); @@ -222,6 +224,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo SpvId default_tgt = find_reserved_id(emitter, terminator->payload.br_switch.default_jump->payload.jump.target); spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); + return; } case TailCall_TAG: case Join_TAG: error("Lower me"); From 15dd8902c18badfbda90fc021b91e903a2b09de9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 3 May 2024 10:15:14 +0200 Subject: [PATCH 229/693] cmake: include GNUIncludeDirs for proper access to its variables --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index af3b947db..88c5852e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,8 @@ else() message("LLVM ${LLVM_VERSION} found") endif() +include(GNUInstallDirs) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) From c963da455de5a740b53c3faa506ca47a0cefad34 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 3 May 2024 10:15:39 +0200 Subject: [PATCH 230/693] remove debug log when including scheduler src --- src/shady/compile.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 31f6d9347..8dccf8b39 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -49,8 +49,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { *pmod = import(config, *pmod); // we don't want to mess with the original module add_scheduler_source(config, *pmod); - log_module(ERROR, config, *pmod); - //exit(0); } RUN_PASS(reconvergence_heuristics) From 4d4dd59fbb80ad3fb9d919c132639659a2db76c4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 3 May 2024 13:32:20 +0200 Subject: [PATCH 231/693] introduce Params --- include/shady/grammar.h | 2 +- include/shady/grammar.json | 26 +++++++---- include/shady/ir.h | 6 +-- src/frontends/llvm/l2s_instr.c | 4 +- src/frontends/llvm/l2s_postprocess.c | 32 ++++++------- src/frontends/spirv/s2s.c | 2 +- src/shady/analysis/free_variables.c | 6 ++- src/shady/analysis/leak.c | 34 -------------- src/shady/analysis/leak.h | 5 -- src/shady/body_builder.c | 4 +- src/shady/constructors.c | 52 ++++++++++++++------- src/shady/emit/c/emit_c.c | 7 +-- src/shady/emit/c/emit_c_instructions.c | 4 +- src/shady/emit/c/emit_c_signatures.c | 2 +- src/shady/emit/spirv/emit_spv.c | 7 +-- src/shady/fold.c | 2 +- src/shady/node.c | 36 ++++++-------- src/shady/passes/bind.c | 23 ++++----- src/shady/passes/infer.c | 25 +++++----- src/shady/passes/lift_indirect_targets.c | 14 +++--- src/shady/passes/lower_callf.c | 2 +- src/shady/passes/lower_cf_instrs.c | 4 +- src/shady/passes/lower_memcpy.c | 4 +- src/shady/passes/lower_tailcalls.c | 12 ++--- src/shady/passes/lower_workgroups.c | 4 +- src/shady/passes/mark_leaf_functions.c | 6 +-- src/shady/passes/normalize.c | 9 ++-- src/shady/passes/normalize_builtins.c | 11 +---- src/shady/passes/opt_demote_alloca.c | 9 ++-- src/shady/passes/opt_inline.c | 4 +- src/shady/passes/opt_mem2reg.c | 9 ++-- src/shady/passes/opt_restructure.c | 2 +- src/shady/passes/reconvergence_heuristics.c | 26 +++++------ src/shady/print.c | 13 ++++-- src/shady/rewrite.c | 47 ++++++++++--------- src/shady/rewrite.h | 8 ++-- src/shady/type.c | 16 +++++-- src/shady/type.h | 2 +- src/shady/type_helpers.c | 6 +-- 39 files changed, 245 insertions(+), 242 deletions(-) diff --git a/include/shady/grammar.h b/include/shady/grammar.h index a49d64701..462ab1eb3 100644 --- a/include/shady/grammar.h +++ b/include/shady/grammar.h @@ -85,7 +85,7 @@ inline static bool is_nominal(const Node* node) { NodeTag tag = node->tag; if (node->tag == PrimOp_TAG && has_primop_got_side_effects(node->payload.prim_op.op)) return true; - return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Variable_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG; + return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Param_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG; } inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 9cc76508a..c986b2298 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -85,7 +85,7 @@ "name": "value" }, { - "name": "variable", + "name": "param", "generate-enum": false }, { @@ -241,9 +241,8 @@ ] }, { - "name": "Variable", - "snake_name": "var", - "class": ["value", "variable"], + "name": "Param", + "class": ["value", "param"], "constructor": "custom", "ops": [ { "name": "type", "class": "type" }, @@ -252,6 +251,17 @@ { "name": "pindex", "type": "unsigned", "ignore": true } ] }, + { + "name": "Variablez", + "snake_name": "varz", + "class": ["value"], + "constructor": "custom", + "ops": [ + { "name": "name", "class": "string" }, + { "name": "instruction", "class": "instruction" }, + { "name": "iindex", "type": "unsigned" } + ] + }, { "name": "ConstrainedValue", "snake_name": "constrained", @@ -448,7 +458,7 @@ "front-end-only": true, "ops": [ { "name": "instruction", "class": "instruction" }, - { "name": "variables", "class": "variable", "list": true } + { "name": "variables", "class": "param", "list": true } ] }, { @@ -548,7 +558,7 @@ { "name": "module", "type": "Module*", "ignore": true }, { "name": "name", "class": "string" }, { "name": "annotations", "class": "annotation", "list": true }, - { "name": "params", "class": "variable", "list": true }, + { "name": "params", "class": "param", "list": true }, { "name": "body", "class": "terminator" }, { "name": "return_types", "class": "type", "list": true } ] @@ -633,7 +643,7 @@ "description": "A named abstraction that lives inside a function and can be jumped to", "class": "basic_block", "ops": [ - { "name": "params", "class": "variable", "list": true }, + { "name": "params", "class": "param", "list": true }, { "name": "body", "class": "terminator" }, { "name": "fn", "class": "declaration" }, { "name": "name", "class": "string" } @@ -649,7 +659,7 @@ "Most notably, the tails of standard `let` nodes" ], "ops": [ - { "name": "params", "class": "variable", "list": true }, + { "name": "params", "class": "param", "list": true }, { "name": "body", "class": "terminator" }, { "name": "structured_construct", "type": "const Node*", "ignored": true } ] diff --git a/include/shady/ir.h b/include/shady/ir.h index 1368c2d7d..238905733 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -120,8 +120,8 @@ const Node* get_node_by_id(const IrArena*, NodeId); //////////////////////////////// Getters //////////////////////////////// /// Get the name out of a global variable, function or constant -String get_value_name(const Node*); String get_value_name_safe(const Node*); +String get_value_name_unsafe(const Node*); void set_variable_name(Node* var, String); const Node* get_quoted_value(const Node* instruction); @@ -166,7 +166,7 @@ NodeResolveConfig default_node_resolve_config(); const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config); /// Resolves a variable to the instruction that produces its value (if any) -const Node* get_var_def(Variable var); +const Node* get_var_def(Variablez var); const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config); //////////////////////////////// Constructors //////////////////////////////// @@ -209,7 +209,7 @@ const Node* fp_literal_helper(IrArena*, FloatSizes, double); const Node* type_decl_ref_helper(IrArena*, const Node* decl); // values -Node* var(IrArena*, const Type* type, const char* name); +Node* param(IrArena*, const Type* type, const char* name); const Node* tuple_helper(IrArena*, Nodes contents); const Node* composite_helper(IrArena*, const Type*, Nodes contents); diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index 45c054c72..c84fbfe11 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -487,9 +487,9 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, assert(LLVMIsAFunction(callee)); if (strcmp(intrinsic, "llvm.dbg.declare") == 0) { const Node* target = convert_value(p, LLVMGetOperand(instr, 0)); - if (target->tag != Variable_TAG) + if (target->tag != Variablez_TAG) return (EmittedInstr) { 0 }; - assert(target->tag == Variable_TAG); + assert(target->tag == Variablez_TAG); const Node* meta = convert_value(p, LLVMGetOperand(instr, 1)); assert(meta->tag == RefDecl_TAG); meta = meta->payload.ref_decl.decl; diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 71aec8269..bca050d48 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -41,10 +41,10 @@ static const Node* wrap_in_controls(Context* ctx, Controls* controls, const Node Nodes o_dst_params = get_abstraction_params(dst); LARRAY(const Node*, new_control_params, o_dst_params.count); for (size_t j = 0; j < o_dst_params.count; j++) - new_control_params[j] = var(a, o_dst_params.nodes[j]->payload.var.type, unique_name(a, "v")); + new_control_params[j] = param(a, o_dst_params.nodes[j]->payload.param.type, unique_name(a, "v")); Nodes nparams = nodes(a, o_dst_params.count, new_control_params); body = let(a, control(a, (Control) { - .yield_types = get_variables_types(a, o_dst_params), + .yield_types = get_param_types(a, o_dst_params), .inside = case_(a, singleton(token), body) }), case_(a, nparams, jump_helper(a, rewrite_node(&ctx->rewriter, dst), nparams))); } @@ -66,13 +66,13 @@ bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { bool compare_nodes(Nodes* a, Nodes* b); -static Nodes remake_variables(Context* ctx, Nodes old) { +static Nodes remake_params(Context* ctx, Nodes old) { IrArena* a = ctx->rewriter.dst_arena; LARRAY(const Node*, nvars, old.count); for (size_t i = 0; i < old.count; i++) { const Node* node = old.nodes[i]; - nvars[i] = var(a, node->payload.var.type ? qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.var.type), false) : NULL, node->payload.var.name); - assert(nvars[i]->tag == Variable_TAG); + nvars[i] = param(a, node->payload.param.type ? qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.param.type), false) : NULL, node->payload.param.name); + assert(nvars[i]->tag == Param_TAG); } return nodes(a, old.count, nvars); } @@ -81,11 +81,11 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (node->tag) { - case Variable_TAG: { - assert(node->payload.var.type); - if (node->payload.var.type->tag == QualifiedType_TAG) - return var(a, node->payload.var.type ? rewrite_node(&ctx->rewriter, node->payload.var.type) : NULL, node->payload.var.name); - return var(a, qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.var.type), false), node->payload.var.name); + case Param_TAG: { + assert(node->payload.param.type); + if (node->payload.param.type->tag == QualifiedType_TAG) + return param(a, node->payload.param.type ? rewrite_node(&ctx->rewriter, node->payload.param.type) : NULL, node->payload.param.name); + return param(a, qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.param.type), false), node->payload.param.name); } case Block_TAG: { Nodes yield_types = rewrite_nodes(r, node->payload.block.yield_types); @@ -131,7 +131,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, fn_ctx.old_fn_or_bb = node; Controls controls; initialize_controls(ctx, &controls, node); - Nodes new_params = recreate_variables(&fn_ctx.rewriter, node->payload.fun.params); + Nodes new_params = recreate_params(&fn_ctx.rewriter, node->payload.fun.params); Nodes old_annotations = node->payload.fun.annotations; ParsedAnnotation* an = find_annotation(ctx->p, node); Op primop_intrinsic = PRIMOPS_COUNT; @@ -150,7 +150,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, primop_intrinsic = op; } else if (strcmp(get_annotation_name(an->payload), "EntryPoint") == 0) { for (size_t i = 0; i < new_params.count; i++) - new_params = change_node_at_index(a, new_params, i, var(a, qualified_type_helper(get_unqualified_type(new_params.nodes[i]->payload.var.type), true), new_params.nodes[i]->payload.var.name)); + new_params = change_node_at_index(a, new_params, i, param(a, qualified_type_helper(get_unqualified_type(new_params.nodes[i]->payload.param.type), true), new_params.nodes[i]->payload.param.name)); } old_annotations = append_nodes(a, old_annotations, an->payload); an = an->next; @@ -225,13 +225,13 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } if (!join_token) { const Type* jp_type = join_point_type(a, (JoinPointType) { - .yield_types = get_variables_types(a, get_abstraction_params(dst)) + .yield_types = get_param_types(a, get_abstraction_params(dst)) }); - join_token = var(a, qualified_type_helper(jp_type, false), get_abstraction_name(dst)); + join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name(dst)); controls->tokens = append_nodes(a, controls->tokens, join_token); controls->destinations = append_nodes(a, controls->destinations, dst); } - Nodes nparams = remake_variables(ctx, get_abstraction_params(dst)); + Nodes nparams = remake_params(ctx, get_abstraction_params(dst)); //register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); Node* fn = src; if (fn->tag == BasicBlock_TAG) @@ -307,7 +307,7 @@ void postprocess(Parser* p, Module* src, Module* dst) { }; ctx.rewriter.rewrite_op_fn = (RewriteOpFn) process_op; - ctx.rewriter.config.process_variables = true; + ctx.rewriter.config.process_params = true; ctx.rewriter.config.search_map = true; // ctx.rewriter.config.write_map = false; diff --git a/src/frontends/spirv/s2s.c b/src/frontends/spirv/s2s.c index c7d929f71..d13988096 100644 --- a/src/frontends/spirv/s2s.c +++ b/src/frontends/spirv/s2s.c @@ -890,7 +890,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { assert(s > 0); if (is_param) { const Node* param = get_definition_by_id(parser, get_result_defined_at(parser, instruction_offset))->node; - assert(param && param->tag == Variable_TAG); + assert(param && param->tag == Param_TAG); params = concat_nodes(parser->arena, params, singleton(param)); } size += s; diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index fdf119236..26654c47c 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -23,7 +23,7 @@ typedef struct { static void search_op_for_free_variables(Context* visitor, NodeClass class, String op_name, const Node* node) { assert(node); switch (node->tag) { - case Variable_TAG: { + case Param_TAG: { Nodes params = get_abstraction_params(visitor->current_scope->node->node); for (size_t i = 0; i < params.count; i++) { if (params.nodes[i] == node) @@ -32,6 +32,10 @@ static void search_op_for_free_variables(Context* visitor, NodeClass class, Stri insert_set_get_result(const Node*, visitor->current_scope->free_set, node); break; } + case Variablez_TAG: { + insert_set_get_result(const Node*, visitor->current_scope->free_set, node); + break; + } case Function_TAG: case Case_TAG: case BasicBlock_TAG: assert(false); diff --git a/src/shady/analysis/leak.c b/src/shady/analysis/leak.c index c62f249ad..9391e1068 100644 --- a/src/shady/analysis/leak.c +++ b/src/shady/analysis/leak.c @@ -20,40 +20,6 @@ void visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, Visit } } -const Node* get_var_binding_abstraction(const UsesMap* map, const Node* var) { - assert(var->tag == Variable_TAG); - const Use* use = get_first_use(map, var); - assert(use); - const Use* binding_use = NULL; - for (;use; use = use->next_use) { - if (is_abstraction(use->user) && use->operand_class == NcVariable) { - assert(!binding_use); - binding_use = use; - } - } - assert(binding_use && "Failed to find the binding abstraction in the uses map"); - return binding_use->user; -} - -const Node* get_case_user(const UsesMap* map, const Node* cas) { - const Use* use = get_first_use(map, cas); - if (!use) - return NULL; - assert(!use->next_use); - assert(use->operand_class == NcCase); - return use->user; -} - -const Node* get_var_instruction(const UsesMap* map, const Node* var) { - const Node* abs = get_var_binding_abstraction(map, var); - if (!abs || abs->tag != Case_TAG) - return NULL; // variable is not bound by a case - const Node* case_user = get_case_user(map, abs); - if (!case_user || case_user->tag != Let_TAG) - return NULL; - return case_user->payload.let.instruction; -} - bool is_control_static(const UsesMap* map, const Node* control) { assert(control->tag == Control_TAG); const Node* inside = control->payload.control.inside; diff --git a/src/shady/analysis/leak.h b/src/shady/analysis/leak.h index 27913de9d..bc32c163e 100644 --- a/src/shady/analysis/leak.h +++ b/src/shady/analysis/leak.h @@ -9,11 +9,6 @@ typedef void (VisitEnclosingAbsCallback)(void*, const Use*); void visit_enclosing_abstractions(UsesMap*, const Node*, void* uptr, VisitEnclosingAbsCallback fn); -const Node* get_var_binding_abstraction(const UsesMap*, const Node* var); -const Node* get_case_user(const UsesMap*, const Node* cas); - -const Node* get_var_instruction(const UsesMap*, const Node* var); - bool is_control_static(const UsesMap*, const Node* control); #endif diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index c57f40d18..9d8a5453a 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -23,6 +23,8 @@ BodyBuilder* begin_body(IrArena* a) { return bb; } +Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i); + static Nodes create_output_variables(IrArena* a, const Node* value, size_t outputs_count, const Node** output_types, String const output_names[]) { Nodes types; if (a->config.check_types) { @@ -51,7 +53,7 @@ static Nodes create_output_variables(IrArena* a, const Node* value, size_t outpu LARRAY(Node*, vars, types.count); for (size_t i = 0; i < types.count; i++) { String var_name = output_names ? output_names[i] : NULL; - vars[i] = (Node*) var(a, types.nodes[i], var_name); + vars[i] = (Node*) var(a, var_name, value, i); } // for (size_t i = 0; i < outputs_count; i++) { diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 431b1192d..927621523 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -91,8 +91,26 @@ const Node* let(IrArena* arena, const Node* instruction, const Node* tail) { return create_node_helper(arena, node, NULL); } -Node* var(IrArena* arena, const Type* type, const char* name) { - Variable variable = { +Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i) { + Variablez variable = { + .name = string(arena, name), + .instruction = instruction, + .iindex = i, + }; + + Node node; + memset((void*) &node, 0, sizeof(Node)); + node = (Node) { + .arena = arena, + .type = arena->config.check_types ? check_type_varz(arena, variable) : NULL, + .tag = Variablez_TAG, + .payload.varz = variable + }; + return create_node_helper(arena, node, NULL); +} + +Node* param(IrArena* arena, const Type* type, const char* name) { + Param param = { .type = type, .name = string(arena, name), }; @@ -101,9 +119,9 @@ Node* var(IrArena* arena, const Type* type, const char* name) { memset((void*) &node, 0, sizeof(Node)); node = (Node) { .arena = arena, - .type = arena->config.check_types ? check_type_var(arena, variable) : NULL, - .tag = Variable_TAG, - .payload.var = variable + .type = arena->config.check_types ? check_type_param(arena, param) : NULL, + .tag = Param_TAG, + .payload.param = param }; return create_node_helper(arena, node, NULL); } @@ -177,10 +195,10 @@ Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, N for (size_t i = 0; i < params.count; i++) { Node* param = (Node*) params.nodes[i]; - assert(param->tag == Variable_TAG); - assert(!param->payload.var.abs); - param->payload.var.abs = fn; - param->payload.var.pindex = i; + assert(param->tag == Param_TAG); + assert(!param->payload.param.abs); + param->payload.param.abs = fn; + param->payload.param.pindex = i; } return fn; @@ -208,10 +226,10 @@ Node* basic_block(IrArena* arena, Node* fn, Nodes params, const char* name) { for (size_t i = 0; i < params.count; i++) { Node* param = (Node*) params.nodes[i]; - assert(param->tag == Variable_TAG); - assert(!param->payload.var.abs); - param->payload.var.abs = bb; - param->payload.var.pindex = i; + assert(param->tag == Param_TAG); + assert(!param->payload.param.abs); + param->payload.param.abs = bb; + param->payload.param.pindex = i; } return bb; @@ -238,10 +256,10 @@ const Node* case_(IrArena* a, Nodes params, const Node* body) { if (fresh || true) { for (size_t i = 0; i < params.count; i++) { Node* param = (Node*) params.nodes[i]; - assert(param->tag == Variable_TAG); - assert(!param->payload.var.abs); - param->payload.var.abs = lam; - param->payload.var.pindex = i; + assert(param->tag == Param_TAG); + assert(!param->payload.param.abs); + param->payload.param.abs = lam; + param->payload.param.pindex = i; } } diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 6b8849967..71d3235fc 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -210,7 +210,8 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { case NotAValue: assert(false); case Value_ConstrainedValue_TAG: case Value_UntypedNumber_TAG: error("lower me"); - case Value_Variable_TAG: error("variables need to be emitted beforehand"); + case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); + case Variablez_TAG: error("tried to emit a variable: all variables should be register by their binding let !"); case Value_IntLiteral_TAG: { if (value->payload.int_literal.is_signed) emitted = format_string_arena(emitter->arena->arena, "%" PRIi64, value->payload.int_literal.value); @@ -444,7 +445,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node break; } case LetBinding: { - String variable_name = get_value_name(tail_params.nodes[i]); + String variable_name = get_value_name_unsafe(tail_params.nodes[i]); if (!variable_name) variable_name = ""; @@ -612,7 +613,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { if (body) { for (size_t i = 0; i < decl->payload.fun.params.count; i++) { String param_name; - String variable_name = get_value_name(decl->payload.fun.params.nodes[i]); + String variable_name = get_value_name_unsafe(decl->payload.fun.params.nodes[i]); param_name = format_string_interned(emitter->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); register_emitted(emitter, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index e9299acf1..3fe4634fc 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -817,12 +817,12 @@ static void emit_loop(Emitter* emitter, Printer* p, const Node* loop_instr, Inst Nodes variables = params; LARRAY(String, arr, variables.count); for (size_t i = 0; i < variables.count; i++) { - arr[i] = get_value_name(variables.nodes[i]); + arr[i] = get_value_name_unsafe(variables.nodes[i]); if (!arr[i]) arr[i] = unique_name(emitter->arena, "phi"); } Strings param_names = strings(emitter->arena, variables.count, arr); - Strings eparams = emit_variable_declarations(emitter, p, NULL, ¶m_names, get_variables_types(emitter->arena, params), true, &loop_instr->payload.loop_instr.initial_args); + Strings eparams = emit_variable_declarations(emitter, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop_instr->payload.loop_instr.initial_args); for (size_t i = 0; i < params.count; i++) register_emitted(&sub_emiter, params.nodes[i], term_from_cvalue(eparams.strings[i])); diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index a56ef2235..74b3df8b4 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -65,7 +65,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const } for (size_t i = 0; i < dom.count; i++) { String param_name; - String variable_name = get_value_name(fn->payload.fun.params.nodes[i]); + String variable_name = get_value_name_unsafe(fn->payload.fun.params.nodes[i]); param_name = format_string_interned(emitter->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); print(paramp, emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 9df983605..d9faba144 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -23,7 +23,7 @@ extern SpvBuiltIn spv_builtins[]; void register_result(Emitter* emitter, const Node* node, SpvId id) { if (is_value(node)) { - String name = get_value_name(node); + String name = get_value_name_unsafe(node); if (name) spvb_name(emitter->file_builder, id, name); } @@ -38,7 +38,8 @@ SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { SpvId new; switch (is_value(node)) { case NotAValue: error(""); - case Variable_TAG: error("tried to emit a variable: but all variables should be emitted by enclosing scope or preceding instructions !"); + case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); + case Variablez_TAG: error("tried to emit a variable: all variables should be register by their binding let !"); case Value_ConstrainedValue_TAG: case Value_UntypedNumber_TAG: case Value_FnAddr_TAG: error("Should be lowered away earlier!"); @@ -290,7 +291,7 @@ static void emit_function(Emitter* emitter, const Node* node) { Nodes params = node->payload.fun.params; for (size_t i = 0; i < params.count; i++) { - const Type* param_type = params.nodes[i]->payload.var.type; + const Type* param_type = params.nodes[i]->payload.param.type; SpvId param_id = spvb_parameter(fn_builder, emit_type(emitter, param_type)); insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, params.nodes[i], param_id); deconstruct_qualified_type(¶m_type); diff --git a/src/shady/fold.c b/src/shady/fold.c index 699ecc3ab..d9a440ae6 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -90,7 +90,7 @@ static const Node* fold_let(IrArena* arena, const Node* node) { Nodes params = get_abstraction_params(olam); for (size_t j = 0; j < params.count; j++) { // recycle the params by setting their abs value to NULL - *((Node**) &(params.nodes[j]->payload.var.abs)) = NULL; + *((Node**) &(params.nodes[j]->payload.param.abs)) = NULL; } const Node* nlam = case_(arena, params, acc); acc = let(arena, get_let_instruction(olet), nlam); diff --git a/src/shady/node.c b/src/shady/node.c index 3d85cb2ae..94709d4f3 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -8,25 +8,27 @@ #include #include -String get_value_name(const Node* v) { +String get_value_name_unsafe(const Node* v) { assert(v && is_value(v)); - if (v->tag == Variable_TAG) - return v->payload.var.name; + if (v->tag == Param_TAG) + return v->payload.param.name; + if (v->tag == Variablez_TAG) + return v->payload.varz.name; return NULL; } String get_value_name_safe(const Node* v) { - String name = get_value_name(v); + String name = get_value_name_unsafe(v); if (name && strlen(name) > 0) return name; - if (v->tag == Variable_TAG) - return format_string_interned(v->arena, "%%%d", v->id); - return node_tags[v->tag]; + //if (v->tag == Variable_TAG) + return format_string_interned(v->arena, "%%%d", v->id); + //return node_tags[v->tag]; } void set_variable_name(Node* var, String name) { - assert(var->tag == Variable_TAG); - var->payload.var.name = string(var->arena, name); + assert(var->tag == Variablez_TAG); + var->payload.varz.name = string(var->arena, name); } int64_t get_int_literal_value(IntLiteral literal, bool sign_extend) { @@ -109,16 +111,8 @@ NodeResolveConfig default_node_resolve_config() { }; } -const Node* get_var_def(Variable var) { - if (var.pindex != 0) - return NULL; - const Node* abs = var.abs; - if (!abs || abs->tag != Case_TAG) - return NULL; - const Node* user = abs->payload.case_.structured_construct; - if (user->tag != Let_TAG) - return NULL; - return user->payload.let.instruction; +const Node* get_var_def(Variablez var) { + return var.instruction; } const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config) { @@ -130,8 +124,8 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi case RefDecl_TAG: node = node->payload.ref_decl.decl; continue; - case Variable_TAG: { - const Node* def = get_var_def(node->payload.var); + case Variablez_TAG: { + const Node* def = get_var_def(node->payload.varz); if (!def) break; node = def; diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 61ea7be09..32251f331 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -129,21 +129,21 @@ static const Node* desugar_let_mut(Context* ctx, const Node* node) { Nodes initial_values = bind_instruction_outputs_count(bb, ninstruction, old_params.count, NULL); for (size_t i = 0; i < old_params.count; i++) { const Node* oparam = old_params.nodes[i]; - const Type* type_annotation = oparam->payload.var.type; + const Type* type_annotation = oparam->payload.param.type; assert(type_annotation); const Node* alloca = prim_op(a, (PrimOp) { .op = alloca_op, .type_arguments = nodes(a, 1, (const Node* []){rewrite_node(&ctx->rewriter, type_annotation) }), .operands = nodes(a, 0, NULL) }); - const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.var.name).nodes[0]; + const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.param.name).nodes[0]; const Node* store = prim_op(a, (PrimOp) { .op = store_op, .operands = nodes(a, 2, (const Node* []) {ptr, initial_values.nodes[0] }) }); bind_instruction_outputs_count(bb, store, 0, NULL); - add_binding(ctx, true, oparam->payload.var.name, ptr); + add_binding(ctx, true, oparam->payload.param.name, ptr); log_string(DEBUGV, "Lowered mutable variable "); log_node(DEBUGV, oparam); log_string(DEBUGV, ".\n;"); @@ -171,12 +171,12 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { return bound; } case Function_TAG: { - Nodes new_fn_params = recreate_variables(&ctx->rewriter, decl->payload.fun.params); + Nodes new_fn_params = recreate_params(&ctx->rewriter, decl->payload.fun.params); Node* bound = function(ctx->rewriter.dst_module, new_fn_params, decl->payload.fun.name, rewrite_nodes(&ctx->rewriter, decl->payload.fun.annotations), rewrite_nodes(&ctx->rewriter, decl->payload.fun.return_types)); register_processed(&ctx->rewriter, decl, bound); Context fn_ctx = *ctx; for (size_t i = 0; i < new_fn_params.count; i++) { - add_binding(&fn_ctx, false, decl->payload.fun.params.nodes[i]->payload.var.name, new_fn_params.nodes[i]); + add_binding(&fn_ctx, false, decl->payload.fun.params.nodes[i]->payload.param.name, new_fn_params.nodes[i]); } register_processed_list(&ctx->rewriter, decl->payload.fun.params, new_fn_params); @@ -223,7 +223,8 @@ static const Node* bind_node(Context* ctx, const Node* node) { assert(is_declaration(node)); return rewrite_decl(ctx, node); } - case Variable_TAG: error("the binders should be handled such that this node is never reached"); + case Variablez_TAG: + case Param_TAG: error("the binders should be handled such that this node is never reached"); case Unbound_TAG: { Resolved entry = resolve_using_name(ctx, node->payload.unbound.name); assert(!entry.is_var); @@ -237,7 +238,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { for (size_t i = 0; i < unbound_blocks.count; i++) { const Node* old_bb = unbound_blocks.nodes[i]; assert(is_basic_block(old_bb)); - Nodes new_bb_params = recreate_variables(&ctx->rewriter, old_bb->payload.basic_block.params); + Nodes new_bb_params = recreate_params(&ctx->rewriter, old_bb->payload.basic_block.params); Node* new_bb = basic_block(a, (Node*) ctx->current_function, new_bb_params, old_bb->payload.basic_block.name); new_bbs[i] = new_bb; add_binding(ctx, false, old_bb->payload.basic_block.name, new_bb); @@ -255,7 +256,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { Context bb_ctx = *ctx; Nodes new_bb_params = get_abstraction_params(new_bb); for (size_t j = 0; j < new_bb_params.count; j++) - add_binding(&bb_ctx, false, new_bb->payload.basic_block.params.nodes[j]->payload.var.name, new_bb_params.nodes[j]); + add_binding(&bb_ctx, false, new_bb->payload.basic_block.params.nodes[j]->payload.param.name, new_bb_params.nodes[j]); new_bb->payload.basic_block.body = rewrite_node(&bb_ctx.rewriter, old_bb->payload.basic_block.body); debugv_print("Bound basic block %s\n", new_bb->payload.basic_block.name); @@ -265,7 +266,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { } case BasicBlock_TAG: { assert(is_basic_block(node)); - Nodes new_bb_params = recreate_variables(&ctx->rewriter, node->payload.basic_block.params); + Nodes new_bb_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); Node* new_bb = basic_block(a, (Node*) ctx->current_function, new_bb_params, node->payload.basic_block.name); Context bb_ctx = *ctx; ctx = &bb_ctx; @@ -277,9 +278,9 @@ static const Node* bind_node(Context* ctx, const Node* node) { } case Case_TAG: { Nodes old_params = node->payload.case_.params; - Nodes new_params = recreate_variables(&ctx->rewriter, old_params); + Nodes new_params = recreate_params(&ctx->rewriter, old_params); for (size_t i = 0; i < new_params.count; i++) - add_binding(ctx, false, old_params.nodes[i]->payload.var.name, new_params.nodes[i]); + add_binding(ctx, false, old_params.nodes[i]->payload.param.name, new_params.nodes[i]); register_processed_list(&ctx->rewriter, old_params, new_params); const Node* new_body = rewrite_node(&ctx->rewriter, node->payload.case_.body); return case_(a, new_params, new_body); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 53306c5fc..a4c998ab5 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -103,9 +103,9 @@ static const Node* infer_decl(Context* ctx, const Node* node) { LARRAY(const Node*, nparams, node->payload.fun.params.count); for (size_t i = 0; i < node->payload.fun.params.count; i++) { - const Variable* old_param = &node->payload.fun.params.nodes[i]->payload.var; + const Param* old_param = &node->payload.fun.params.nodes[i]->payload.param; const Type* imported_param_type = infer(ctx, old_param->type, NULL); - nparams[i] = var(a, imported_param_type, old_param->name); + nparams[i] = param(a, imported_param_type, old_param->name); register_processed(&body_context.rewriter, node->payload.fun.params.nodes[i], nparams[i]); } @@ -171,7 +171,8 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec Rewriter* r = &ctx->rewriter; switch (is_value(node)) { case NotAValue: error(""); - case Variable_TAG: return find_processed(&ctx->rewriter, node); + case Param_TAG: + case Variablez_TAG: return find_processed(&ctx->rewriter, node); case Value_ConstrainedValue_TAG: { const Type* type = infer(ctx, node->payload.constrained.type, NULL); bool expect_uniform = false; @@ -298,9 +299,9 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg for (size_t i = 0; i < inferred_arg_type.count; i++) { if (node->payload.case_.params.count == 0) { // syntax sugar: make up a parameter if there was none - nparams[i] = var(a, inferred_arg_type.nodes[i], unique_name(a, "_")); + nparams[i] = param(a, inferred_arg_type.nodes[i], unique_name(a, "_")); } else { - const Variable* old_param = &node->payload.case_.params.nodes[i]->payload.var; + const Param* old_param = &node->payload.case_.params.nodes[i]->payload.param; // for the param type: use the inferred one if none is already provided // if one is provided, check the inferred argument type is a subtype of the param type const Type* param_type = old_param->type ? infer_type(ctx, old_param->type) : NULL; @@ -308,7 +309,7 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg if (!param_type || param_type->tag != PtrType_TAG || param_type->payload.ptr_type.pointed_type) param_type = inferred_arg_type.nodes[i]; assert(is_subtype(param_type, inferred_arg_type.nodes[i])); - nparams[i] = var(a, param_type, old_param->name); + nparams[i] = param(a, param_type, old_param->name); register_processed(&body_context.rewriter, node->payload.case_.params.nodes[i], nparams[i]); } } @@ -324,12 +325,12 @@ static const Node* _infer_basic_block(Context* ctx, const Node* node) { Context body_context = *ctx; LARRAY(const Node*, nparams, node->payload.basic_block.params.count); for (size_t i = 0; i < node->payload.basic_block.params.count; i++) { - const Variable* old_param = &node->payload.basic_block.params.nodes[i]->payload.var; + const Param* old_param = &node->payload.basic_block.params.nodes[i]->payload.param; // for the param type: use the inferred one if none is already provided // if one is provided, check the inferred argument type is a subtype of the param type const Type* param_type = infer(ctx, old_param->type, NULL); assert(param_type); - nparams[i] = var(a, param_type, old_param->name); + nparams[i] = param(a, param_type, old_param->name); register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); } @@ -546,7 +547,7 @@ static const Node* infer_loop(Context* ctx, const Node* node, const Nodes* expec const Node* old_body = node->payload.loop_instr.body; Nodes old_params = get_abstraction_params(old_body); - Nodes old_params_types = get_variables_types(a, old_params); + Nodes old_params_types = get_param_types(a, old_params); Nodes new_params_types = infer_nodes(ctx, old_params_types); new_params_types = annotate_all_types(a, new_params_types, false); @@ -586,7 +587,7 @@ static const Node* infer_control(Context* ctx, const Node* node, const Nodes* ex .yield_types = yield_types }); jpt = qualified_type(a, (QualifiedType) { .is_uniform = true, .type = jpt }); - const Node* jp = var(a, jpt, ojp->payload.var.name); + const Node* jp = param(a, jpt, ojp->payload.param.name); register_processed(&joinable_ctx.rewriter, ojp, jp); const Node* nlam = case_(a, singleton(jp), infer(&joinable_ctx, get_abstraction_body(olam), NULL)); @@ -635,7 +636,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { case NotATerminator: assert(false); case Let_TAG: { const Node* otail = node->payload.let.tail; - Nodes annotated_types = get_variables_types(a, otail->payload.case_.params); + Nodes annotated_types = get_param_types(a, otail->payload.case_.params); const Node* inferred_instruction = infer_instruction(ctx, node->payload.let.instruction, &annotated_types); Nodes inferred_yield_types = unwrap_multiple_yield_types(a, inferred_instruction->type); for (size_t i = 0; i < inferred_yield_types.count; i++) { @@ -660,7 +661,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { case Jump_TAG: { assert(is_basic_block(node->payload.jump.target)); const Node* ntarget = infer(ctx, node->payload.jump.target, NULL); - Nodes param_types = get_variables_types(a, get_abstraction_params(ntarget)); + Nodes param_types = get_param_types(a, get_abstraction_params(ntarget)); LARRAY(const Node*, tmp, node->payload.jump.args.count); for (size_t i = 0; i < node->payload.jump.args.count; i++) diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 92db8c23e..f25820d79 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -110,14 +110,15 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, String given_na debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { const Node* item = read_list(const Node*, recover_context)[i]; - debugv_print("%s %%%d", get_value_name(item) ? get_value_name(item) : "", item->id); + String item_name = get_value_name_unsafe(item); + debugv_print("%s %%%d", item_name ? item_name : "", item->id); if (i + 1 < recover_context_size) debugv_print(", "); } debugv_print("\n"); // Create and register new parameters for the lifted continuation - Nodes new_params = recreate_variables(&ctx->rewriter, oparams); + Nodes new_params = recreate_params(&ctx->rewriter, oparams); LiftedCont* lifted_cont = calloc(sizeof(LiftedCont), 1); lifted_cont->old_cont = liftee; @@ -128,7 +129,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, String given_na lifting_ctx.rewriter = create_children_rewriter(&ctx->rewriter); register_processed_list(&lifting_ctx.rewriter, oparams, new_params); - const Node* payload = var(a, qualified_type_helper(uint32_type(a), false), "sp"); + const Node* payload = param(a, qualified_type_helper(uint32_type(a), false), "sp"); // Keep annotations the same Nodes annotations = nodes(a, 0, NULL); @@ -141,17 +142,18 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, String given_na gen_primop(bb, set_stack_size_op, empty(a), singleton(payload)); for (size_t i = recover_context_size - 1; i < recover_context_size; i--) { const Node* ovar = read_list(const Node*, recover_context)[i]; - assert(ovar->tag == Variable_TAG); + // assert(ovar->tag == Variable_TAG); const Type* value_type = rewrite_node(&ctx->rewriter, ovar->type); + String param_name = get_value_name_unsafe(ovar); const Node* recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = pop_stack_op, .type_arguments = singleton(get_unqualified_type(value_type)) - }), &ovar->payload.var.name)); + }), ¶m_name)); if (is_qualified_type_uniform(ovar->type)) - recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }), &ovar->payload.var.name)); + recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }), ¶m_name)); register_processed(&lifting_ctx.rewriter, ovar, recovered_value); } diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 940c1dbda..8ad7e6b3c 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -35,7 +35,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body(a); if (!ctx2.disable_lowering) { Nodes oparams = get_abstraction_params(old); - Nodes nparams = recreate_variables(&ctx->rewriter, oparams); + Nodes nparams = recreate_params(&ctx->rewriter, oparams); register_processed_list(&ctx->rewriter, oparams, nparams); // Supplement an additional parameter for the join point diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 50c07b492..24f801f46 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -74,7 +74,7 @@ static const Node* process_let(Context* ctx, const Node* node) { assert(is_case(old_loop_body)); Nodes yield_types = rewrite_nodes(&ctx->rewriter, old_instruction->payload.loop_instr.yield_types); - Nodes param_types = rewrite_nodes(&ctx->rewriter, get_variables_types(a, old_loop_body->payload.case_.params)); + Nodes param_types = rewrite_nodes(&ctx->rewriter, get_param_types(a, old_loop_body->payload.case_.params)); param_types = strip_qualifiers(a, param_types); const Type* break_jp_type = qualified_type(a, (QualifiedType) { @@ -91,7 +91,7 @@ static const Node* process_let(Context* ctx, const Node* node) { Nodes jps = mk_nodes(a, break_point, continue_point); insert_dict(const Node*, Nodes, ctx->structured_join_tokens, old_instruction, jps); - Nodes new_params = recreate_variables(&ctx->rewriter, old_loop_body->payload.case_.params); + Nodes new_params = recreate_params(&ctx->rewriter, old_loop_body->payload.case_.params); Node* loop_body = basic_block(a, ctx->current_fn, new_params, unique_name(a, "loop_body")); register_processed_list(&join_context.rewriter, old_loop_body->payload.case_.params, loop_body->payload.basic_block.params); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index d076c2a3f..4115d9800 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -55,7 +55,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num = rewrite_node(&ctx->rewriter, old_ops.nodes[2]); const Node* num_in_bytes = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); - const Node* index = var(a, qualified_type_helper(uint32_type(a), false), "memcpy_i"); + const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memcpy_i"); BodyBuilder* loop_bb = begin_body(a); const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, singleton(uint32_literal(a, 0)))); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, singleton(uint32_literal(a, 0))), loaded_word); @@ -97,7 +97,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num = rewrite_node(&ctx->rewriter, old_ops.nodes[2]); const Node* num_in_bytes = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); - const Node* index = var(a, qualified_type_helper(uint32_type(a), false), "memset_i"); + const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memset_i"); BodyBuilder* loop_bb = begin_body(a); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, singleton(uint32_literal(a, 0))), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index c3eac3153..254296bc1 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -61,7 +61,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { Context ctx2 = *ctx; IrArena* a = ctx->rewriter.dst_arena; // For the lifted entry point, we keep _all_ annotations - Nodes rewritten_params = recreate_variables(&ctx2.rewriter, old->payload.fun.params); + Nodes rewritten_params = recreate_params(&ctx2.rewriter, old->payload.fun.params); Node* new_entry_pt = function(ctx2.rewriter.dst_module, rewritten_params, old->payload.fun.name, rewrite_nodes(&ctx2.rewriter, old->payload.fun.annotations), nodes(a, 0, NULL)); BodyBuilder* bb = begin_body(a); @@ -146,10 +146,10 @@ static const Node* process(Context* ctx, const Node* old) { for (size_t i = 0; i < old->payload.fun.params.count; i++) { const Node* old_param = old->payload.fun.params.nodes[i]; const Type* new_param_type = rewrite_node(&ctx->rewriter, get_unqualified_type(old_param->type)); - const Node* popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = pop_stack_op, .type_arguments = singleton(new_param_type), .operands = empty(a) }), &old_param->payload.var.name)); + const Node* popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = pop_stack_op, .type_arguments = singleton(new_param_type), .operands = empty(a) }), &old_param->payload.param.name)); // TODO use the uniform stack instead ? or no ? if (is_qualified_type_uniform(old_param->type)) - popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_broadcast_first_op, .type_arguments = empty(a), .operands =singleton(popped) }), &old_param->payload.var.name)); + popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_broadcast_first_op, .type_arguments = empty(a), .operands =singleton(popped) }), &old_param->payload.param.name)); register_processed(&ctx->rewriter, old_param, popped); } fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body)); @@ -246,14 +246,14 @@ static const Node* process(Context* ctx, const Node* old) { if (is_control_static(ctx->uses, old)) { const Node* old_inside = old->payload.control.inside; const Node* old_jp = first(get_abstraction_params(old_inside)); - assert(old_jp->tag == Variable_TAG); + assert(old_jp->tag == Param_TAG); const Node* old_jp_type = old_jp->type; deconstruct_qualified_type(&old_jp_type); assert(old_jp_type->tag == JoinPointType_TAG); const Node* new_jp_type = join_point_type(a, (JoinPointType) { .yield_types = rewrite_nodes(&ctx->rewriter, old_jp_type->payload.join_point_type.yield_types), }); - const Node* new_jp = var(a, qualified_type_helper(new_jp_type, true), old_jp->payload.var.name); + const Node* new_jp = param(a, qualified_type_helper(new_jp_type, true), old_jp->payload.param.name); register_processed(&ctx->rewriter, old_jp, new_jp); const Node* new_body = case_(a, singleton(new_jp), rewrite_node(&ctx->rewriter, get_abstraction_body(old_inside))); return control(a, (Control) { @@ -286,7 +286,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { bool count_iterations = ctx->config->shader_diagnostics.max_top_iterations > 0; const Node* iterations_count_param = NULL; if (count_iterations) - iterations_count_param = var(a, qualified_type(a, (QualifiedType) { .type = int32_type(a), .is_uniform = true }), "iterations"); + iterations_count_param = param(a, qualified_type(a, (QualifiedType) { .type = int32_type(a), .is_uniform = true }), "iterations"); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index e70f12693..665039573 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -52,13 +52,13 @@ static const Node* process(Context* ctx, const Node* node) { assert(node->payload.fun.return_types.count == 0 && "entry points do not return at this stage"); Nodes wannotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); - Nodes wparams = recreate_variables(&ctx->rewriter, node->payload.fun.params); + Nodes wparams = recreate_params(&ctx->rewriter, node->payload.fun.params); Node* wrapper = function(m, wparams, get_abstraction_name(node), wannotations, empty(a)); register_processed(&ctx->rewriter, node, wrapper); // recreate the old entry point, but this time it's not the entry point anymore Nodes nannotations = filter_out_annotation(a, wannotations, "EntryPoint"); - Nodes nparams = recreate_variables(&ctx->rewriter, node->payload.fun.params); + Nodes nparams = recreate_params(&ctx->rewriter, node->payload.fun.params); Node* inner = function(m, nparams, format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, empty(a)); register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); inner->payload.fun.body = recreate_node_identity(&ctx->rewriter, node->payload.fun.body); diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index a81d10c1e..f7b8cc897 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -109,7 +109,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx = &fn_ctx; Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); - Node* new = function(ctx->rewriter.dst_module, recreate_variables(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); + Node* new = function(ctx->rewriter.dst_module, recreate_params(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); for (size_t i = 0; i < new->payload.fun.params.count; i++) register_processed(&ctx->rewriter, node->payload.fun.params.nodes[i], new->payload.fun.params.nodes[i]); register_processed(&ctx->rewriter, node, new); @@ -138,8 +138,8 @@ static const Node* process(Context* ctx, const Node* node) { case Join_TAG: { const Node* old_jp = node->payload.join.join_point; // is it associated with a control node ? - if (old_jp->tag == Variable_TAG) { - const Node* abs = old_jp->payload.var.abs; + if (old_jp->tag == Param_TAG) { + const Node* abs = old_jp->payload.param.abs; assert(abs); if (abs->tag == Case_TAG) { const Node* structured = abs->payload.case_.structured_construct; diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index 9f21a4892..783b1aa3b 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -34,7 +34,8 @@ static const Node* force_to_be_value(Context* ctx, const Node* node) { case Function_TAG: { return fn_addr_helper(a, process_node(ctx, node)); } - case Variable_TAG: return find_processed(&ctx->rewriter, node); + case Variablez_TAG: + case Param_TAG: return find_processed(&ctx->rewriter, node); default: break; } @@ -65,7 +66,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str } case NcValue: return force_to_be_value(ctx, node); - case NcVariable: + case NcParam: break; case NcInstruction: { if (is_instruction(node)) @@ -111,7 +112,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return new; } case BasicBlock_TAG: { - Node* new = basic_block(a, (Node*) rewrite_node(&ctx->rewriter, node->payload.basic_block.fn), recreate_variables(&ctx->rewriter, node->payload.basic_block.params), node->payload.basic_block.name); + Node* new = basic_block(a, (Node*) rewrite_node(&ctx->rewriter, node->payload.basic_block.fn), recreate_params(&ctx->rewriter, node->payload.basic_block.params), node->payload.basic_block.name); register_processed(&ctx->rewriter, node, new); register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new->payload.basic_block.params); BodyBuilder* bb = begin_body(a); @@ -122,7 +123,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return new; } case Case_TAG: { - Nodes new_params = recreate_variables(&ctx->rewriter, node->payload.case_.params); + Nodes new_params = recreate_params(&ctx->rewriter, node->payload.case_.params); register_processed_list(&ctx->rewriter, node->payload.case_.params, new_params); BodyBuilder* bb = begin_body(a); Context ctx2 = *ctx; diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 1c56f554a..678635896 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -37,15 +37,8 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { break; } case RefDecl_TAG: return get_req_cast(ctx, src->payload.ref_decl.decl); - case Variable_TAG: { - const Node* abs = src->payload.var.abs; - if (abs) { - const Node* construct = abs->payload.case_.structured_construct; - if (construct && construct->tag == Let_TAG) { - return get_req_cast(ctx, construct->payload.let.instruction); - } - } - break; + case Variablez_TAG: { + return get_req_cast(ctx, get_var_def(src->payload.varz)); } case PrimOp_TAG: { PrimOp prim_op = src->payload.prim_op; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 96f285d85..3ecf50622 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -46,7 +46,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca const Use* use = get_first_use(map, ptr_value); for (;use; use = use->next_use) { - if (is_abstraction(use->user) && use->operand_class == NcVariable) + if (is_abstraction(use->user) && use->operand_class == NcParam) continue; else if (use->user->tag == Let_TAG && use->operand_class == NcInstruction) { Nodes vars = get_abstraction_params(get_let_tail(use->user)); @@ -129,8 +129,8 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { PtrSourceKnowledge k = { 0 }; while (ptr) { assert(is_value(ptr)); - if (ptr->tag == Variable_TAG && ctx->uses) { - const Node* instr = get_var_instruction(ctx->uses, ptr); + if (ptr->tag == Variablez_TAG && ctx->uses) { + const Node* instr = get_var_def(ptr->payload.varz); if (instr) { PrimOp payload = instr->payload.prim_op; switch (payload.op) { @@ -192,9 +192,10 @@ static const Node* process(Context* ctx, const Node* old) { Nodes oparams = otail->payload.case_.params; Nodes ntypes = unwrap_multiple_yield_types(r->dst_arena, ninstruction->type); assert(ntypes.count == oparams.count); + // TODO use recreate_params() LARRAY(const Node*, new_params, oparams.count); for (size_t i = 0; i < oparams.count; i++) { - new_params[i] = var(r->dst_arena, ntypes.nodes[i], oparams.nodes[i]->payload.var.name); + new_params[i] = param(r->dst_arena, ntypes.nodes[i], oparams.nodes[i]->payload.param.name); register_processed(r, oparams.nodes[i], new_params[i]); } if (info) diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index c77952be4..9e7bf70f8 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -152,7 +152,7 @@ static const Node* process(Context* ctx, const Node* node) { } Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); - Node* new = function(ctx->rewriter.dst_module, recreate_variables(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); + Node* new = function(ctx->rewriter.dst_module, recreate_params(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); register_processed(r, node, new); Context fn_ctx = *ctx; @@ -201,7 +201,7 @@ static const Node* process(Context* ctx, const Node* node) { nfn = ctx->inlined_call->host_fn; else nfn = rewrite_node(r, ofn); - Nodes nparams = recreate_variables(r, get_abstraction_params(node)); + Nodes nparams = recreate_params(r, get_abstraction_params(node)); register_processed_list(r, get_abstraction_params(node), nparams); Node* bb = basic_block(a, (Node*) nfn, nparams, get_abstraction_name(node)); register_processed(r, node, bb); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 63a6bcd6b..1eaa8c9a0 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -277,7 +277,8 @@ static void mark_value_as_escaping(Context* ctx, KnowledgeBase* kb, const Node* } switch (is_value(value)) { case NotAValue: assert(false); - case Value_Variable_TAG: + case Value_Param_TAG: + case Value_Variablez_TAG: break; case Value_ConstrainedValue_TAG: break; @@ -454,7 +455,7 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod //String s = format_string_interned(a, "%s_", get_abstraction_name(old_target)); String s = get_abstraction_name(old_target); - Node* wrapper = basic_block(a, (Node*) rewrite_node(r, old_target->payload.basic_block.fn), recreate_variables(r, get_abstraction_params(old_target)), s); + Node* wrapper = basic_block(a, (Node*) rewrite_node(r, old_target->payload.basic_block.fn), recreate_params(r, get_abstraction_params(old_target)), s); TodoJump todo = { .old_jump = old, .wrapper_bb = wrapper, @@ -501,8 +502,8 @@ static void handle_bb(Context* ctx, const Node* old) { fn_ctx.oabs = old; ctx = &fn_ctx; - Nodes params = recreate_variables(&ctx->rewriter, get_abstraction_params(old)); - Nodes let_params = recreate_variables(&ctx->rewriter, get_abstraction_params(old)); + Nodes params = recreate_params(&ctx->rewriter, get_abstraction_params(old)); + Nodes let_params = recreate_params(&ctx->rewriter, get_abstraction_params(old)); register_processed_list(&ctx->rewriter, get_abstraction_params(old), let_params); const Node* nbody = rewrite_node(&ctx->rewriter, get_abstraction_body(old)); nbody = let(a, quote_helper(a, params), case_(a, let_params, nbody)); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 2a35b65d4..cef2a280c 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -155,7 +155,7 @@ static const Node* rebuild_let(Context* ctx, const Node* old_let, const Node* ne const Node* old_tail = get_let_tail(old_let); Nodes otail_params = get_abstraction_params(old_tail); - Nodes rewritten_params = recreate_variables(&ctx->rewriter, otail_params); + Nodes rewritten_params = recreate_params(&ctx->rewriter, otail_params); register_processed_list(&ctx->rewriter, otail_params, rewritten_params); const Node* structured_lam = case_(a, rewritten_params, structure(ctx, old_tail, exit_ladder)); return let(a, new_instruction, structured_lam); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 18e14cd9b..2b2cfefe9 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -132,8 +132,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { size_t exiting_nodes_count = entries_count_list(exiting_nodes); if (exiting_nodes_count > 0) { - Nodes nparams = recreate_variables(rewriter, get_abstraction_params(node)); - Nodes inner_yield_types = strip_qualifiers(arena, get_variables_types(arena, nparams)); + Nodes nparams = recreate_params(rewriter, get_abstraction_params(node)); + Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); CFNode* cf_pre = cfg_lookup(ctx->fwd_cfg, node); // assert(cf_pre->idom && "cfg entry nodes can't be loop headers anyhow"); @@ -145,7 +145,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(Nodes, exit_fwd_allocas, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; - Nodes exit_param_types = rewrite_nodes(rewriter, get_variables_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); + Nodes exit_param_types = rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); LARRAY(const Node*, exit_param_allocas_tmp, exit_param_types.count); for (size_t j = 0; j < exit_param_types.count; j++) exit_param_allocas_tmp[j] = gen_primop_e(outer_bb, alloca_op, singleton(get_unqualified_type(exit_param_types.nodes[j])), empty(arena)); @@ -171,11 +171,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Node* fn = (Node*) find_processed(rewriter, ctx->current_fn); - const Node* join_token_exit = var(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { + const Node* join_token_exit = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { .yield_types = empty(arena) }), true), "jp_exit"); - const Node* join_token_continue = var(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { + const Node* join_token_continue = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { .yield_types = inner_yield_types }), true), "jp_continue"); @@ -186,7 +186,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); - Nodes exit_wrapper_params = recreate_variables(&ctx->rewriter, get_abstraction_params(exiting_node->node)); + Nodes exit_wrapper_params = recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); switch (exiting_node->node->tag) { case BasicBlock_TAG: { @@ -203,7 +203,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { } } - Nodes continue_wrapper_params = recreate_variables(rewriter, get_abstraction_params(node)); + Nodes continue_wrapper_params = recreate_params(rewriter, get_abstraction_params(node)); const Node* continue_wrapper_body = join(arena, (Join) { .join_point = join_token_continue, .args = continue_wrapper_params @@ -245,7 +245,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { struct Dict* old_map = rewriter->map; rewriter->map = clone_dict(rewriter->map); - Nodes inner_loop_params = recreate_variables(rewriter, get_abstraction_params(node)); + Nodes inner_loop_params = recreate_params(rewriter, get_abstraction_params(node)); register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); const Node* loop_body = recreate_node_identity(rewriter, get_abstraction_body(node)); @@ -489,16 +489,16 @@ static const Node* process_node(Context* ctx, const Node* node) { for (size_t j = 0; j < old_params.count; j++) { //TODO: Is this correct? - assert(old_params.nodes[j]->tag == Variable_TAG); - const Node* qualified_type = rewrite_node(rewriter, old_params.nodes[j]->payload.var.type); + assert(old_params.nodes[j]->tag == Param_TAG); + const Node* qualified_type = rewrite_node(rewriter, old_params.nodes[j]->payload.param.type); //const Node* qualified_type = rewrite_node(rewriter, old_params.nodes[j]->type); //This should always contain a qualified type? //if (contains_qualified_type(types[j])) types[j] = get_unqualified_type(qualified_type); - inner_args[j] = var(arena, qualified_type, old_params.nodes[j]->payload.var.name); - outer_args[j] = var(arena, qualified_type, old_params.nodes[j]->payload.var.name); + inner_args[j] = param(arena, qualified_type, old_params.nodes[j]->payload.param.name); + outer_args[j] = param(arena, qualified_type, old_params.nodes[j]->payload.param.name); } yield_types = nodes(arena, old_params.count, types); @@ -506,7 +506,7 @@ static const Node* process_node(Context* ctx, const Node* node) { lambda_args = nodes(arena, old_params.count, outer_args); } - const Node* join_token = var(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { + const Node* join_token = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { .yield_types = yield_types }), true), "jp_postdom"); diff --git a/src/shady/print.c b/src/shady/print.c index c2a191482..12b085fdc 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -61,7 +61,7 @@ static void print_param_list(PrinterCtx* ctx, Nodes params, const Nodes* default for (size_t i = 0; i < params.count; i++) { const Node* param = params.nodes[i]; if (ctx->config.print_ptrs) printf("%zu::", (size_t)(void*) param); - print_node(param->payload.var.type); + print_node(param->payload.param.type); printf(" "); print_node(param); printf(RESET); @@ -407,7 +407,8 @@ static void print_value(PrinterCtx* ctx, const Node* node) { print_node(node->payload.constrained.value); break; } - case Variable_TAG: + case Value_Variablez_TAG: + case Value_Param_TAG: if (ctx->uses) { // if ((*find_value_dict(const Node*, Uses*, ctx->uses->map, node))->escapes_defining_block) // printf(MANGENTA); @@ -415,7 +416,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { printf(YELLOW); } else printf(YELLOW); - String name = get_value_name(node); + String name = get_value_name_unsafe(node); if (name && strlen(name) > 0) printf("%s_", name); printf("%%%d", node->id); @@ -683,7 +684,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { for (size_t i = 0; i < params.count; i++) { if (mut || !ctx->config.reparseable) { printf(" "); - print_node(params.nodes[i]->payload.var.type); + print_node(params.nodes[i]->payload.param.type); } printf(" "); print_node(params.nodes[i]); @@ -1129,4 +1130,8 @@ void print_node_operand_bool(Printer* p, const Node* n, String name, bool b, Pri print(p, "false"); } +void print_node_operand_unsigned(Printer* p, const Node* n, String name, unsigned u, PrintConfig config) { + print(p, " '%s': %u", name, u); +} + #include "print_generated.c" diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 2ad0249a9..44c101b9b 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -222,21 +222,21 @@ void rewrite_module(Rewriter* rewriter) { } } -const Node* recreate_variable(Rewriter* rewriter, const Node* old) { - assert(old->tag == Variable_TAG); - return var(rewriter->dst_arena, rewrite_op_helper(rewriter, NcType, "type", old->payload.var.type), old->payload.var.name); +const Node* recreate_param(Rewriter* rewriter, const Node* old) { + assert(old->tag == Param_TAG); + return param(rewriter->dst_arena, rewrite_op_helper(rewriter, NcType, "type", old->payload.param.type), old->payload.param.name); } -Nodes recreate_variables(Rewriter* rewriter, Nodes old) { - LARRAY(const Node*, nvars, old.count); - for (size_t i = 0; i < old.count; i++) { - if (rewriter->config.process_variables) - nvars[i] = rewrite_node(rewriter, old.nodes[i]); +Nodes recreate_params(Rewriter* rewriter, Nodes oparams) { + LARRAY(const Node*, nparams, oparams.count); + for (size_t i = 0; i < oparams.count; i++) { + if (rewriter->config.process_params) + nparams[i] = rewrite_node(rewriter, oparams.nodes[i]); else - nvars[i] = recreate_variable(rewriter, old.nodes[i]); - assert(nvars[i]->tag == Variable_TAG); + nparams[i] = recreate_param(rewriter, oparams.nodes[i]); + assert(nparams[i]->tag == Param_TAG); } - return nodes(rewriter->dst_arena, old.count, nvars); + return nodes(rewriter->dst_arena, oparams.count, nparams); } Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { @@ -263,7 +263,7 @@ Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { } case Function_TAG: { Nodes new_annotations = rewrite_ops_helper(rewriter, NcAnnotation, "annotations", old->payload.fun.annotations); - Nodes new_params = recreate_variables(rewriter, old->payload.fun.params); + Nodes new_params = recreate_params(rewriter, old->payload.fun.params); Nodes nyield_types = rewrite_ops_helper(rewriter, NcType, "return_types", old->payload.fun.return_types); new = function(rewriter->dst_module, new_params, old->payload.fun.name, new_annotations, nyield_types); assert(new && new->tag == Function_TAG); @@ -307,7 +307,7 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) } } -const Node* rebind_let(Rewriter* rewriter, const Node* ninstruction, const Node* olam) { +/*const Node* rebind_let(Rewriter* rewriter, const Node* ninstruction, const Node* olam) { assert(olam->tag == Case_TAG); Nodes oparams = olam->payload.case_.params; Nodes ntypes = unwrap_multiple_yield_types(rewriter->dst_arena, ninstruction->type); @@ -320,7 +320,7 @@ const Node* rebind_let(Rewriter* rewriter, const Node* ninstruction, const Node* const Node* nbody = rewrite_node(rewriter, olam->payload.case_.body); const Node* tail = case_(rewriter->dst_arena, nodes(rewriter->dst_arena, oparams.count, new_params), nbody); return tail; -} +}*/ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { if (node == NULL) @@ -341,7 +341,8 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { recreate_decl_body_identity(rewriter, node, new); return new; } - case Variable_TAG: error("variables should be recreated as part of decl handling"); + case Param_TAG: error("params should be rewritten by the abstraction rewrite logic"); + case Variablez_TAG: error("variables should be rewritten by the binding let"); case Let_TAG: { const Node* instruction = rewrite_op_helper(rewriter, NcInstruction, "instruction", node->payload.let.instruction); if (arena->config.allow_fold && rewriter->config.fold_quote && instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { @@ -350,25 +351,25 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { assert(old_params.count == new_args.count); register_processed_list(rewriter, old_params, new_args); for (size_t i = 0; i < old_params.count; i++) { - String old_name = get_value_name(old_params.nodes[i]); + String old_name = get_value_name_unsafe(old_params.nodes[i]); if (!old_name) continue; const Node* new_arg = new_args.nodes[i]; - if (new_arg->tag == Variable_TAG && !get_value_name(new_arg)) { + if (new_arg->tag == Variablez_TAG && !get_value_name_unsafe(new_arg)) { set_variable_name((Node*) new_arg, old_name); } } return rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.let.tail->payload.case_.body); } const Node* tail; - if (rewriter->config.rebind_let) - tail = rebind_let(rewriter, instruction, node->payload.let.tail); - else - tail = rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail); + // if (rewriter->config.rebind_let) + // tail = rebind_let(rewriter, instruction, node->payload.let.tail); + // else + tail = rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail); //TODO return let(arena, instruction, tail); } case LetMut_TAG: error("De-sugar this by hand") case Case_TAG: { - Nodes params = recreate_variables(rewriter, node->payload.case_.params); + Nodes params = recreate_params(rewriter, node->payload.case_.params); register_processed_list(rewriter, node->payload.case_.params, params); const Node* nterminator = rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.case_.body); const Node* nlam = case_(rewriter->dst_arena, params, nterminator); @@ -376,7 +377,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { return nlam; } case BasicBlock_TAG: { - Nodes params = recreate_variables(rewriter, node->payload.basic_block.params); + Nodes params = recreate_params(rewriter, node->payload.basic_block.params); register_processed_list(rewriter, node->payload.basic_block.params, params); const Node* fn = rewrite_op_helper(rewriter, NcDeclaration, "fn", node->payload.basic_block.fn); Node* bb = basic_block(arena, (Node*) fn, params, node->payload.basic_block.name); diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index af7e10211..36e8d1fde 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -35,7 +35,7 @@ struct Rewriter_ { bool write_map; bool rebind_let; bool fold_quote; - bool process_variables; + bool process_params; } config; Rewriter* parent; @@ -62,10 +62,10 @@ Node* recreate_decl_header_identity(Rewriter*, const Node*); void recreate_decl_body_identity(Rewriter*, const Node*, Node*); /// Rewrites a variable under a new identity -const Node* recreate_variable(Rewriter* rewriter, const Node* old); -Nodes recreate_variables(Rewriter* rewriter, Nodes old); +const Node* recreate_param(Rewriter* rewriter, const Node* old); +Nodes recreate_params(Rewriter* rewriter, Nodes oparams); Node* clone_bb_head(Rewriter*, const Node* bb); -const Node* rebind_let(Rewriter*, const Node* ninstruction, const Node* ocase); +//const Node* rebind_let(Rewriter*, const Node* ninstruction, const Node* ocase); /// Looks up if the node was already processed const Node* search_processed(const Rewriter*, const Node*); diff --git a/src/shady/type.c b/src/shady/type.c index a4c9d8de3..972f5484a 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -418,11 +418,17 @@ const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { return NULL; } -const Type* check_type_var(IrArena* arena, Variable variable) { +const Type* check_type_param(IrArena* arena, Param variable) { assert(is_value_type(variable.type)); return variable.type; } +const Type* check_type_varz(IrArena* arena, Variablez variable) { + Nodes types = unwrap_multiple_yield_types(arena, variable.instruction->type); + assert(variable.iindex < types.count); + return types.nodes[variable.iindex]; +} + const Type* check_type_untyped_number(IrArena* arena, UntypedNumber untyped) { error("should never happen"); } @@ -1214,7 +1220,7 @@ const Type* check_type_let(IrArena* arena, Let let) { assert(is_instruction(let.instruction)); assert(is_case(let.tail)); Nodes produced_types = unwrap_multiple_yield_types(arena, let.instruction->type); - Nodes param_types = get_variables_types(arena, let.tail->payload.case_.params); + Nodes param_types = get_param_types(arena, let.tail->payload.case_.params); check_arguments_types_against_parameters_helper(param_types, produced_types); return noret_type(arena); @@ -1309,15 +1315,15 @@ const Type* check_type_fun(IrArena* arena, Function fn) { for (size_t i = 0; i < fn.return_types.count; i++) { assert(is_value_type(fn.return_types.nodes[i])); } - return fn_type(arena, (FnType) { .param_types = get_variables_types(arena, (&fn)->params), .return_types = (&fn)->return_types }); + return fn_type(arena, (FnType) { .param_types = get_param_types(arena, (&fn)->params), .return_types = (&fn)->return_types }); } const Type* check_type_basic_block(IrArena* arena, BasicBlock bb) { - return bb_type(arena, (BBType) { .param_types = get_variables_types(arena, (&bb)->params) }); + return bb_type(arena, (BBType) { .param_types = get_param_types(arena, (&bb)->params) }); } const Type* check_type_case_(IrArena* arena, Case lam) { - return lam_type(arena, (LamType) { .param_types = get_variables_types(arena, (&lam)->params) }); + return lam_type(arena, (LamType) { .param_types = get_param_types(arena, (&lam)->params) }); } const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_variable) { diff --git a/src/shady/type.h b/src/shady/type.h index 39152e3e6..07fb7a9a7 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -41,7 +41,7 @@ void enter_composite(const Type** datatype, bool* u, Nodes indices, bool allow_e /// Collects the annotated types in the list of variables /// NB: this is different from get_values_types, that function uses node.type, whereas this one uses node.payload.var.type /// This means this function works in untyped modules where node.type is NULL. -Nodes get_variables_types(IrArena*, Nodes); +Nodes get_param_types(IrArena* arena, Nodes variables); Nodes get_values_types(IrArena*, Nodes); diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 0a342f433..bdcf28bed 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -112,11 +112,11 @@ void enter_composite(const Type** datatype, bool* uniform, Nodes indices, bool a } } -Nodes get_variables_types(IrArena* arena, Nodes variables) { +Nodes get_param_types(IrArena* arena, Nodes variables) { LARRAY(const Type*, arr, variables.count); for (size_t i = 0; i < variables.count; i++) { - assert(variables.nodes[i]->tag == Variable_TAG); - arr[i] = variables.nodes[i]->payload.var.type; + assert(variables.nodes[i]->tag == Param_TAG); + arr[i] = variables.nodes[i]->payload.param.type; } return nodes(arena, variables.count, arr); } From f415a1bcb80c098b5429087e51167dbb04c19001 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 3 May 2024 17:27:33 +0200 Subject: [PATCH 232/693] make Let bind variables --- include/shady/grammar.h | 2 +- include/shady/grammar.json | 13 ++- include/shady/ir.h | 5 +- src/frontends/llvm/l2s.c | 8 +- src/frontends/llvm/l2s_postprocess.c | 14 ++-- src/frontends/slim/parser.c | 17 +++- src/frontends/spirv/s2s.c | 4 +- src/shady/analysis/free_variables.c | 46 ++++++----- src/shady/body_builder.c | 15 +++- src/shady/compile.c | 2 +- src/shady/constructors.c | 10 ++- src/shady/emit/spirv/emit_spv.c | 10 +-- src/shady/fold.c | 87 -------------------- src/shady/passes/bind.c | 15 +++- src/shady/passes/cleanup.c | 21 +++-- src/shady/passes/infer.c | 14 ++-- src/shady/passes/lift_indirect_targets.c | 4 +- src/shady/passes/lower_callf.c | 4 +- src/shady/passes/lower_cf_instrs.c | 36 +++------ src/shady/passes/lower_generic_ptrs.c | 4 +- src/shady/passes/lower_physical_ptrs.c | 4 +- src/shady/passes/lower_stack.c | 74 +++++++---------- src/shady/passes/lower_subgroup_ops.c | 6 +- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/lower_workgroups.c | 4 +- src/shady/passes/opt_demote_alloca.c | 26 +++--- src/shady/passes/opt_inline.c | 2 +- src/shady/passes/opt_mem2reg.c | 26 +++--- src/shady/passes/opt_restructure.c | 26 +++--- src/shady/passes/opt_stack.c | 5 +- src/shady/passes/reconvergence_heuristics.c | 30 +++---- src/shady/print.c | 15 ++-- src/shady/rewrite.c | 90 ++++++++++++++++----- src/shady/rewrite.h | 1 + src/shady/type.c | 6 +- 35 files changed, 314 insertions(+), 334 deletions(-) diff --git a/include/shady/grammar.h b/include/shady/grammar.h index 462ab1eb3..1acb94015 100644 --- a/include/shady/grammar.h +++ b/include/shady/grammar.h @@ -85,7 +85,7 @@ inline static bool is_nominal(const Node* node) { NodeTag tag = node->tag; if (node->tag == PrimOp_TAG && has_primop_got_side_effects(node->payload.prim_op.op)) return true; - return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Param_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG; + return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Param_TAG || tag == Variablez_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG; } inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } diff --git a/include/shady/grammar.json b/include/shady/grammar.json index c986b2298..80763c6fe 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -88,6 +88,10 @@ "name": "param", "generate-enum": false }, + { + "name": "variable", + "generate-enum": false + }, { "name": "instruction" }, @@ -254,7 +258,7 @@ { "name": "Variablez", "snake_name": "varz", - "class": ["value"], + "class": ["value", "variable"], "constructor": "custom", "ops": [ { "name": "name", "class": "string" }, @@ -448,6 +452,7 @@ "constructor": "custom", "ops": [ { "name": "instruction", "class": "instruction" }, + { "name": "variables", "class": "variable", "list": true }, { "name": "tail", "class": "case" } ] }, @@ -458,7 +463,8 @@ "front-end-only": true, "ops": [ { "name": "instruction", "class": "instruction" }, - { "name": "variables", "class": "param", "list": true } + { "name": "variables", "class": "param", "list": true }, + { "name": "types", "class": "type", "list": true } ] }, { @@ -655,8 +661,7 @@ "constructor": "custom", "class": "case", "description": [ - "An unnamed abstraction that lives inside a function, and can be used as part of various control-flow constructs", - "Most notably, the tails of standard `let` nodes" + "An unnamed abstraction that lives inside a function, and can be used as part of various control-flow constructs" ], "ops": [ { "name": "params", "class": "param", "list": true }, diff --git a/include/shady/ir.h b/include/shady/ir.h index 238905733..847c0a68f 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -225,8 +225,9 @@ const Node* quote_helper(IrArena*, Nodes values); const Node* prim_op_helper(IrArena*, Op, Nodes, Nodes); // terminators -const Node* let(IrArena*, const Node* instruction, const Node* tail); -const Node* let_mut(IrArena*, const Node* instruction, Nodes variables); +const Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i); +const Node* let(IrArena*, const Node* instruction, Nodes vars, const Node* tail); +const Node* let_mut(IrArena*, const Node* instruction, Nodes variables, Nodes types); const Node* jump_helper(IrArena* a, const Node* dst, Nodes args); // decl ctors diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 40d31c6ea..b4b225a90 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -78,7 +78,7 @@ static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { while (instr) { switch (LLVMGetInstructionOpcode(instr)) { case LLVMPHI: { - const Node* nparam = var(a, qualified_type_helper(convert_type(p, LLVMTypeOf(instr)), false), "phi"); + const Node* nparam = param(a, qualified_type_helper(convert_type(p, LLVMTypeOf(instr)), false), "phi"); insert_dict(LLVMValueRef, const Node*, p->map, instr, nparam); append_list(LLVMValueRef, phis, instr); params = append_nodes(a, params, nparam); @@ -137,9 +137,9 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { for (LLVMValueRef oparam = LLVMGetFirstParam(fn); oparam; oparam = LLVMGetNextParam(oparam)) { LLVMTypeRef ot = LLVMTypeOf(oparam); const Type* t = convert_type(p, ot); - const Node* param = var(a, qualified_type_helper(t, false), LLVMGetValueName(oparam)); - insert_dict(LLVMValueRef, const Node*, p->map, oparam, param); - params = append_nodes(a, params, param); + const Node* nparam = param(a, qualified_type_helper(t, false), LLVMGetValueName(oparam)); + insert_dict(LLVMValueRef, const Node*, p->map, oparam, nparam); + params = append_nodes(a, params, nparam); if (oparam == LLVMGetLastParam(fn)) break; } diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index bca050d48..7eba11008 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -39,14 +39,12 @@ static const Node* wrap_in_controls(Context* ctx, Controls* controls, const Node const Node* token = controls->tokens.nodes[i]; const Node* dst = controls->destinations.nodes[i]; Nodes o_dst_params = get_abstraction_params(dst); - LARRAY(const Node*, new_control_params, o_dst_params.count); - for (size_t j = 0; j < o_dst_params.count; j++) - new_control_params[j] = param(a, o_dst_params.nodes[j]->payload.param.type, unique_name(a, "v")); - Nodes nparams = nodes(a, o_dst_params.count, new_control_params); - body = let(a, control(a, (Control) { - .yield_types = get_param_types(a, o_dst_params), - .inside = case_(a, singleton(token), body) - }), case_(a, nparams, jump_helper(a, rewrite_node(&ctx->rewriter, dst), nparams))); + BodyBuilder* bb = begin_body(a); + Nodes results = bind_instruction(bb, control(a, (Control) { + .yield_types = get_param_types(a, o_dst_params), + .inside = case_(a, singleton(token), body) + })); + body = finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results)); } return body; } diff --git a/src/frontends/slim/parser.c b/src/frontends/slim/parser.c index 4fbf511e8..188cd71c9 100644 --- a/src/frontends/slim/parser.c +++ b/src/frontends/slim/parser.c @@ -368,7 +368,7 @@ static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_value const char* id = accept_identifier(ctx); expect(id); - const Node* node = var(arena, qtype, id); + const Node* node = param(arena, qtype, id); append_list(Node*, params, node); if (default_values) { @@ -617,11 +617,11 @@ static const Node* accept_control_flow_instruction(ctxparams, Node* fn) { expect(accept_token(ctx, lpar_tok)); String str = accept_identifier(ctx); expect(str); - const Node* param = var(arena, join_point_type(arena, (JoinPointType) { + const Node* jp = param(arena, join_point_type(arena, (JoinPointType) { .yield_types = yield_types, }), str); expect(accept_token(ctx, rpar_tok)); - const Node* body = case_(arena, singleton(param), expect_body(ctx, fn, NULL)); + const Node* body = case_(arena, singleton(jp), expect_body(ctx, fn, NULL)); return control(arena, (Control) { .inside = body, .yield_types = yield_types @@ -726,6 +726,15 @@ static const Node* expect_jump(ctxparams) { }); } +/// for convenience, parse variables as parameters +static Nodes params2vars(IrArena* arena, const Node* instruction, Nodes params) { + LARRAY(const Node*, vars, params.count); + for (size_t i = 0; i < params.count; i++) { + vars[i] = var(arena, params.nodes[i]->payload.param.name, instruction, i); + } + return nodes(arena, params.count, vars); +} + static const Node* accept_terminator(ctxparams, Node* fn) { TokenTag tag = curr_token(tokenizer).tag; switch (tag) { @@ -738,7 +747,7 @@ static const Node* accept_terminator(ctxparams, Node* fn) { case let_tok: { const Node* lam = accept_case(ctx, fn); expect(lam); - return let(arena, instruction, lam); + return let(arena, instruction, params2vars(arena, instruction, get_abstraction_params(lam)), get_abstraction_body(lam)); } default: SHADY_UNREACHABLE; } diff --git a/src/frontends/spirv/s2s.c b/src/frontends/spirv/s2s.c index d13988096..81d173f47 100644 --- a/src/frontends/spirv/s2s.c +++ b/src/frontends/spirv/s2s.c @@ -864,7 +864,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].type = Value; String param_name = get_name(parser, result); param_name = param_name ? param_name : format_string_arena(parser->arena->arena, "param%d", parser->fun_arg_i); - parser->defs[result].node = var(parser->arena, qualified_type_helper(get_def_type(parser, result_t), parser->is_entry_pt), param_name); + parser->defs[result].node = param(parser->arena, qualified_type_helper(get_def_type(parser, result_t), parser->is_entry_pt), param_name); break; } case SpvOpLabel: { @@ -923,7 +923,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].type = Value; String phi_name = get_name(parser, result); phi_name = phi_name ? phi_name : unique_name(parser->arena, "phi"); - parser->defs[result].node = var(parser->arena, qualified_type_helper(get_def_type(parser, result_t), false), phi_name); + parser->defs[result].node = param(parser->arena, qualified_type_helper(get_def_type(parser, result_t), false), phi_name); assert(size % 2 == 1); int num_callsites = (size - 3) / 2; for (size_t i = 0; i < num_callsites; i++) { diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index 26654c47c..145424e87 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -23,24 +23,28 @@ typedef struct { static void search_op_for_free_variables(Context* visitor, NodeClass class, String op_name, const Node* node) { assert(node); switch (node->tag) { - case Param_TAG: { - Nodes params = get_abstraction_params(visitor->current_scope->node->node); - for (size_t i = 0; i < params.count; i++) { - if (params.nodes[i] == node) - return; + case Let_TAG: { + Nodes variables = node->payload.let.variables; + for (size_t j = 0; j < variables.count; j++) { + const Node* var = variables.nodes[j]; + bool r = insert_set_get_result(const Node*, visitor->current_scope->bound_set, var); + assert(r); } - insert_set_get_result(const Node*, visitor->current_scope->free_set, node); break; } - case Variablez_TAG: { - insert_set_get_result(const Node*, visitor->current_scope->free_set, node); - break; + case Variablez_TAG: + case Param_TAG: { + const Node** found = find_key_dict(const Node*, visitor->current_scope->bound_set, node); + if (!found) + insert_set_get_result(const Node*, visitor->current_scope->free_set, node); + return; } case Function_TAG: case Case_TAG: case BasicBlock_TAG: assert(false); - default: visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK, node); break; + default: break; } + visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK | NcVariable, node); } static CFNodeVariables* create_node_variables(CFNode* cfnode) { @@ -57,11 +61,7 @@ static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, C ctx = &new_context; ctx->current_scope = create_node_variables(cfnode); - if (parent) { - ctx->current_scope->bound_set = clone_dict(parent->bound_set); - } else { - ctx->current_scope->bound_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - } + ctx->current_scope->bound_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); insert_dict(CFNode*, CFNodeVariables*, ctx->map, cfnode, ctx->current_scope); const Node* abs = cfnode->node; @@ -85,15 +85,21 @@ static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, C size_t j = 0; const Node* free_var; while (dict_iter(child_variables->free_set, &j, &free_var, NULL)) { - for (size_t k = 0; k < params.count; k++) { - if (params.nodes[k] == free_var) - goto next; - } - insert_set_get_result(const Node*, ctx->current_scope->free_set, free_var); + const Node** found = find_key_dict(const Node*, ctx->current_scope->bound_set, free_var); + if (!found) + insert_set_get_result(const Node*, ctx->current_scope->free_set, free_var); next:; } } + if (parent) { + size_t j = 0; + const Node* bound; + while (dict_iter(parent->bound_set, &j, &bound, NULL)) { + insert_set_get_result(const Node*, ctx->current_scope->bound_set, bound); + } + } + /*String abs_name = get_abstraction_name_unsafe(abs); for (int i = 0; i < depth; i++) debugvv_print(" "); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 9d8a5453a..6139bcf4c 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -23,7 +23,7 @@ BodyBuilder* begin_body(IrArena* a) { return bb; } -Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i); +const Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i); static Nodes create_output_variables(IrArena* a, const Node* value, size_t outputs_count, const Node** output_types, String const output_names[]) { Nodes types; @@ -93,7 +93,7 @@ Nodes bind_instruction_explicit_result_types(BodyBuilder* bb, const Node* instru Nodes create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[]) { Nodes mutable_vars = create_output_variables(bb->arena, instruction, provided_types.count, provided_types.nodes, output_names); - const Node* let_mut_instr = let_mut(bb->arena, instruction, mutable_vars); + const Node* let_mut_instr = let_mut(bb->arena, instruction, mutable_vars, provided_types); return bind_internal(bb, let_mut_instr, 0, NULL, NULL); } @@ -109,12 +109,19 @@ void bind_variables(BodyBuilder* bb, Nodes vars, Nodes values) { append_list(StackEntry, bb->stack, entry); } +void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr) { + StackEntry entry = { + .instr = instr, + .vars = vars, + }; + append_list(StackEntry, bb->stack, entry); +} + const Node* finish_body(BodyBuilder* bb, const Node* terminator) { size_t stack_size = entries_count_list(bb->stack); for (size_t i = stack_size - 1; i < stack_size; i--) { StackEntry entry = read_list(StackEntry, bb->stack)[i]; - const Node* lam = case_(bb->arena, entry.vars, terminator); - terminator = let(bb->arena, entry.instr, lam); + terminator = let(bb->arena, entry.instr, entry.vars, case_(bb->arena, empty(bb->arena), terminator)); } destroy_list(bb->stack); diff --git a/src/shady/compile.c b/src/shady/compile.c index 8dccf8b39..9a576a55e 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -67,7 +67,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(specialize_execution_model) - RUN_PASS(opt_stack) + //RUN_PASS(opt_stack) RUN_PASS(lower_tailcalls) RUN_PASS(lower_switch_btree) diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 927621523..129ea1608 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -74,12 +74,15 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { #include "constructors_generated.c" -const Node* let(IrArena* arena, const Node* instruction, const Node* tail) { +const Node* let(IrArena* arena, const Node* instruction, Nodes vars, const Node* tail) { Let payload = { .instruction = instruction, + .variables = vars, .tail = tail, }; + assert(is_case(tail) && get_abstraction_params(tail).count == 0); + Node node; memset((void*) &node, 0, sizeof(Node)); node = (Node) { @@ -91,7 +94,7 @@ const Node* let(IrArena* arena, const Node* instruction, const Node* tail) { return create_node_helper(arena, node, NULL); } -Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i) { +const Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i) { Variablez variable = { .name = string(arena, name), .instruction = instruction, @@ -126,10 +129,11 @@ Node* param(IrArena* arena, const Type* type, const char* name) { return create_node_helper(arena, node, NULL); } -const Node* let_mut(IrArena* arena, const Node* instruction, Nodes variables) { +const Node* let_mut(IrArena* arena, const Node* instruction, Nodes variables, Nodes types) { LetMut payload = { .instruction = instruction, .variables = variables, + .types = types, }; Node node; diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index d9faba144..085a08ce3 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -192,13 +192,13 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo } case Let_TAG: { const Node* tail = get_let_tail(terminator); - Nodes params = tail->payload.case_.params; - LARRAY(SpvId, results, params.count); - emit_instruction(emitter, fn_builder, &basic_block_builder, &merge_targets, get_let_instruction(terminator), params.count, results); + Nodes vars = terminator->payload.let.variables; + LARRAY(SpvId, results, vars.count); + emit_instruction(emitter, fn_builder, &basic_block_builder, &merge_targets, get_let_instruction(terminator), vars.count, results); assert(tail->tag == Case_TAG); - for (size_t i = 0; i < params.count; i++) - register_result(emitter, params.nodes[i], results[i]); + for (size_t i = 0; i < vars.count; i++) + register_result(emitter, vars.nodes[i], results[i]); emit_terminator(emitter, fn_builder, basic_block_builder, merge_targets, tail->payload.case_.body); return; } diff --git a/src/shady/fold.c b/src/shady/fold.c index d9a440ae6..f8dc1ae9c 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -27,92 +27,6 @@ static bool is_one(const Node* node) { return false; } -static const Node* fold_let(IrArena* arena, const Node* node) { - assert(node->tag == Let_TAG); - const Node* instruction = node->payload.let.instruction; - const Node* tail = node->payload.let.tail; - switch (instruction->tag) { - // eliminates blocks by "lifting" their contents out and replacing yield with the tail of the outer let - // In other words, we turn these patterns: - // - // let block { - // let I in case(x) => - // let J in case(y) => - // let K in case(z) => - // ... - // yield (x, y, z) } - // in case(a, b, c) => R - // - // into these: - // - // let I in case(x) => - // let J in case(y) => - // let K in case(z) => - // ... - // R[a->x, b->y, c->z] - case Block_TAG: { - // follow the terminator of the block until we hit a yield() - const Node* lam = instruction->payload.block.inside; - const Node* terminator = get_abstraction_body(lam); - size_t depth = 0; - bool dry_run = true; - const Node** lets = NULL; - while (true) { - assert(is_case(lam)); - switch (is_terminator(terminator)) { - case NotATerminator: assert(false); - case Terminator_Let_TAG: { - if (lets) - lets[depth] = terminator; - lam = get_let_tail(terminator); - terminator = get_abstraction_body(lam); - depth++; - continue; - } - case Terminator_Yield_TAG: { - if (dry_run) { - lets = calloc(sizeof(const Node*), depth); - dry_run = false; - depth = 0; - // Start over ! - lam = instruction->payload.block.inside; - terminator = get_abstraction_body(lam); - continue; - } else { - // wrap the original tail with the args of join() - assert(is_case(tail)); - const Node* acc = let(arena, quote_helper(arena, terminator->payload.yield.args), tail); - // rebuild the let chain that we traversed - for (size_t i = 0; i < depth; i++) { - const Node* olet = lets[depth - 1 - i]; - const Node* olam = get_let_tail(olet); - assert(olam->tag == Case_TAG); - Nodes params = get_abstraction_params(olam); - for (size_t j = 0; j < params.count; j++) { - // recycle the params by setting their abs value to NULL - *((Node**) &(params.nodes[j]->payload.param.abs)) = NULL; - } - const Node* nlam = case_(arena, params, acc); - acc = let(arena, get_let_instruction(olet), nlam); - } - free(lets); - return acc; - } - } - // if we see anything else, give up - default: { - assert(dry_run); - return node; - } - } - } - } - default: break; - } - - return node; -} - static const Node* fold_prim_op(IrArena* arena, const Node* node) { PrimOp payload = node->payload.prim_op; @@ -283,7 +197,6 @@ static bool is_unreachable_case(const Node* c) { const Node* fold_node(IrArena* arena, const Node* node) { const Node* folded = node; switch (node->tag) { - case Let_TAG: folded = fold_let(arena, node); break; case PrimOp_TAG: folded = fold_prim_op(arena, node); break; case Block_TAG: { const Node* lam = node->payload.block.inside; diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 32251f331..cbdf9c386 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -129,21 +129,21 @@ static const Node* desugar_let_mut(Context* ctx, const Node* node) { Nodes initial_values = bind_instruction_outputs_count(bb, ninstruction, old_params.count, NULL); for (size_t i = 0; i < old_params.count; i++) { const Node* oparam = old_params.nodes[i]; - const Type* type_annotation = oparam->payload.param.type; + const Type* type_annotation = node->payload.let_mut.types.nodes[i]; assert(type_annotation); const Node* alloca = prim_op(a, (PrimOp) { .op = alloca_op, .type_arguments = nodes(a, 1, (const Node* []){rewrite_node(&ctx->rewriter, type_annotation) }), .operands = nodes(a, 0, NULL) }); - const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.param.name).nodes[0]; + const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.varz.name).nodes[0]; const Node* store = prim_op(a, (PrimOp) { .op = store_op, .operands = nodes(a, 2, (const Node* []) {ptr, initial_values.nodes[0] }) }); bind_instruction_outputs_count(bb, store, 0, NULL); - add_binding(ctx, true, oparam->payload.param.name, ptr); + add_binding(ctx, true, oparam->payload.varz.name, ptr); log_string(DEBUGV, "Lowered mutable variable "); log_node(DEBUGV, oparam); log_string(DEBUGV, ".\n;"); @@ -200,6 +200,7 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { static const Node* bind_node(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; if (node == NULL) return NULL; @@ -276,6 +277,14 @@ static const Node* bind_node(Context* ctx, const Node* node) { new_bb->payload.basic_block.body = rewrite_node(&ctx->rewriter, node->payload.basic_block.body); return new_bb; } + case Let_TAG: { + const Node* ninstr = rewrite_node(r, get_let_instruction(node)); + Nodes ovars = node->payload.let.variables; + Nodes nvars = recreate_vars(a, ovars, ninstr); + for (size_t i = 0; i < nvars.count; i++) + add_binding(ctx, false, nvars.nodes[i]->payload.varz.name, nvars.nodes[i]); + return let(a, ninstr, nvars, rewrite_node(r, get_let_tail(node))); + } case Case_TAG: { Nodes old_params = node->payload.case_.params; Nodes new_params = recreate_params(&ctx->rewriter, old_params); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index d8fc3f6f2..82a7b8c36 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -45,13 +45,12 @@ const Node* process(Context* ctx, const Node* old) { if (payload.instruction->tag == PrimOp_TAG) side_effects = has_primop_got_side_effects(payload.instruction->payload.prim_op.op); bool consumed = false; - const Node* tail_case = payload.tail; - Nodes tail_params = get_abstraction_params(tail_case); - for (size_t i = 0; i < tail_params.count; i++) { - const Use* use = get_first_use(ctx->map, tail_params.nodes[i]); + Nodes vars = payload.variables; + for (size_t i = 0; i < vars.count; i++) { + const Use* use = get_first_use(ctx->map, vars.nodes[i]); assert(use); for (;use; use = use->next_use) { - if (use->user == tail_case) + if (use->user == old) continue; consumed = true; break; @@ -60,18 +59,18 @@ const Node* process(Context* ctx, const Node* old) { break; } if (!consumed && !side_effects && ctx->rewriter.dst_arena) { - debug_print("Cleanup: found an unused instruction: "); - log_node(DEBUG, payload.instruction); - debug_print("\n"); + debugvv_print("Cleanup: found an unused instruction: "); + log_node(DEBUGVV, payload.instruction); + debugvv_print("\n"); ctx->todo = true; - return rewrite_node(&ctx->rewriter, get_abstraction_body(tail_case)); + return rewrite_node(&ctx->rewriter, get_abstraction_body(payload.tail)); } break; } case BasicBlock_TAG: { size_t uses = count_calls(ctx->map, old); if (uses <= 1) { - log_string(DEBUGV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name(old), uses); + log_string(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name(old), uses); return NULL; } break; @@ -90,7 +89,7 @@ const Node* process(Context* ctx, const Node* old) { default: break; } - return recreate_node_identity(&ctx->rewriter, old);; + return recreate_node_identity(&ctx->rewriter, old); } OptPass simplify; diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index a4c998ab5..f1ed57cbd 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -635,15 +635,19 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { switch (is_terminator(node)) { case NotATerminator: assert(false); case Let_TAG: { - const Node* otail = node->payload.let.tail; - Nodes annotated_types = get_param_types(a, otail->payload.case_.params); - const Node* inferred_instruction = infer_instruction(ctx, node->payload.let.instruction, &annotated_types); + // const Node* otail = node->payload.let.ttail; + // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); + const Node* inferred_instruction = infer_instruction(ctx, node->payload.let.instruction, NULL); Nodes inferred_yield_types = unwrap_multiple_yield_types(a, inferred_instruction->type); + LARRAY(const Node*, vars, inferred_yield_types.count); for (size_t i = 0; i < inferred_yield_types.count; i++) { assert(is_value_type(inferred_yield_types.nodes[i])); } - const Node* inferred_tail = infer_case(ctx, otail, inferred_yield_types); - return let(a, inferred_instruction, inferred_tail); + // const Node* inferred_tail = infer_case(ctx, otail, inferred_yield_types); + Nodes ovars = node->payload.let.variables; + Nodes nvars = recreate_vars(a, ovars, inferred_instruction); + register_processed_list(&ctx->rewriter, ovars, nvars); + return let(a, inferred_instruction, nvars, infer_case(ctx, node->payload.let.tail, empty(a))); } case Return_TAG: { const Node* imported_fn = infer(ctx, node->payload.fn_ret.fn, NULL); diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index f25820d79..15f0ac6f2 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -172,6 +172,7 @@ static const Node* process_node(Context* ctx, const Node* node) { if (found) return found; IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; switch (is_declaration(node)) { case Function_TAG: { @@ -217,7 +218,8 @@ static const Node* process_node(Context* ctx, const Node* node) { // dumbass hack jp = gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(jp)); - return finish_body(bb, let(a, quote_helper(a, singleton(jp)), rewrite_node(&ctx->rewriter, oinside))); + register_processed(r, first(get_abstraction_params(oinside)), jp); + return finish_body(bb, rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); } } break; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 8ad7e6b3c..b2cc8fcbb 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -46,7 +46,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { if (lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { ctx2.return_jp = gen_primop_e(bb, default_join_point_op, empty(a), empty(a)); } else { - const Node* jp_variable = var(a, qualified_type_helper(jp_type, false), "return_jp"); + const Node* jp_variable = param(a, qualified_type_helper(jp_type, false), "return_jp"); nparams = append_nodes(a, nparams, jp_variable); ctx2.return_jp = jp_variable; } @@ -120,7 +120,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .type = join_point_type(a, (JoinPointType) { .yield_types = strip_qualifiers(a, returned_types) }), .is_uniform = false }); - const Node* jp = var(a, jp_type, "fn_return_point"); + const Node* jp = param(a, jp_type, "fn_return_point"); // Add that join point as the last argument to the newly made function nargs = append_nodes(a, nargs, jp); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 24f801f46..a1d44d606 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -22,15 +22,9 @@ typedef struct Context_ { static const Node* process_node(Context* ctx, const Node* node); -static const Node* process_let(Context* ctx, const Node* node) { - assert(node->tag == Let_TAG); +static const Node* process_instruction(Context* ctx, const Node* old_instruction) { IrArena* a = ctx->rewriter.dst_arena; - const Node* old_instruction = node->payload.let.instruction; - const Node* new_instruction = NULL; - const Node* old_tail = node->payload.let.tail; - const Node* new_tail = NULL; - switch (old_instruction->tag) { case If_TAG: { bool has_false_branch = old_instruction->payload.if_instr.if_false; @@ -40,9 +34,9 @@ static const Node* process_let(Context* ctx, const Node* node) { .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), .is_uniform = false, }); - const Node* join_point = var(a, jp_type, "if_join"); + const Node* jp = param(a, jp_type, "if_join"); Context join_context = *ctx; - Nodes jps = singleton(join_point); + Nodes jps = singleton(jp); insert_dict(const Node*, Nodes, ctx->structured_join_tokens, old_instruction, jps); Node* true_block = basic_block(a, ctx->current_fn, nodes(a, 0, NULL), unique_name(a, "if_true")); @@ -55,7 +49,7 @@ static const Node* process_let(Context* ctx, const Node* node) { flse_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, old_instruction->payload.if_instr.if_false->payload.case_.body); } else { assert(yield_types.count == 0); - flse_block->payload.basic_block.body = join(a, (Join) { .join_point = join_point, .args = nodes(a, 0, NULL) }); + flse_block->payload.basic_block.body = join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL) }); } const Node* control_body = branch(a, (Branch) { @@ -64,9 +58,8 @@ static const Node* process_let(Context* ctx, const Node* node) { .false_jump = jump_helper(a, flse_block, empty(a)), }); - const Node* control_lam = case_(a, nodes(a, 1, (const Node* []) {join_point}), control_body); - new_instruction = control(a, (Control) { .yield_types = yield_types, .inside = control_lam }); - break; + const Node* control_lam = case_(a, nodes(a, 1, (const Node* []) {jp}), control_body); + return control(a, (Control) { .yield_types = yield_types, .inside = control_lam }); } // TODO: match case Loop_TAG: { @@ -85,8 +78,8 @@ static const Node* process_let(Context* ctx, const Node* node) { .type = join_point_type(a, (JoinPointType) { .yield_types = param_types }), .is_uniform = false, }); - const Node* break_point = var(a, break_jp_type, "loop_break_point"); - const Node* continue_point = var(a, continue_jp_type, "loop_continue_point"); + const Node* break_point = param(a, break_jp_type, "loop_break_point"); + const Node* continue_point = param(a, continue_jp_type, "loop_continue_point"); Context join_context = *ctx; Nodes jps = mk_nodes(a, break_point, continue_point); insert_dict(const Node*, Nodes, ctx->structured_join_tokens, old_instruction, jps); @@ -114,19 +107,13 @@ static const Node* process_let(Context* ctx, const Node* node) { .args = rewrite_nodes(&ctx->rewriter, old_instruction->payload.loop_instr.initial_args), }); const Node* outer_body = case_(a, nodes(a, 1, (const Node* []) {break_point}), initial_jump); - new_instruction = control(a, (Control) { .yield_types = yield_types, .inside = outer_body }); - break; + return control(a, (Control) { .yield_types = yield_types, .inside = outer_body }); } default: - new_instruction = rewrite_node(&ctx->rewriter, old_instruction); break; } - if (!new_tail) - new_tail = rewrite_node(&ctx->rewriter, old_tail); - - assert(new_instruction && new_tail); - return let(a, new_instruction, new_tail); + return recreate_node_identity(&ctx->rewriter, old_instruction); } static const Node* process_node(Context* ctx, const Node* node) { @@ -162,8 +149,9 @@ static const Node* process_node(Context* ctx, const Node* node) { return recreate_node_identity(&ctx->rewriter, node); CFNode* cfnode = ctx->cfg ? cfg_lookup(ctx->cfg, ctx->abs) : NULL; + if (is_instruction(node)) + return process_instruction(ctx, node); switch (node->tag) { - case Let_TAG: return process_let(ctx, node); case Yield_TAG: { if (!cfnode) break; diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index f2e03ad80..cb41529e1 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -81,7 +81,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo if (found) return *found; - const Node* ptr_param = var(a, qualified_type_helper(ctx->generic_ptr_type, uniform_ptr), "ptr"); + const Node* ptr_param = param(a, qualified_type_helper(ctx->generic_ptr_type, uniform_ptr), "ptr"); const Node* value_param; Nodes params = singleton(ptr_param); Nodes return_ts = empty(a); @@ -90,7 +90,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo return_ts = singleton(qualified_type_helper(t, uniform_ptr)); break; case StoreFn: - value_param = var(a, qualified_type_helper(t, false), "value"); + value_param = param(a, qualified_type_helper(t, false), "value"); params = append_nodes(a, params, value_param); break; } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index d244268eb..2210c0d3b 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -265,10 +265,10 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un IrArena* a = ctx->rewriter.dst_arena; const Type* emulated_ptr_type = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); - const Node* address_param = var(a, qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || uniform_address, .type = emulated_ptr_type }), "ptr"); + const Node* address_param = param(a, qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || uniform_address, .type = emulated_ptr_type }), "ptr"); const Type* input_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && is_addr_space_uniform(a, as) && false), .type = element_type }); - const Node* value_param = ser ? var(a, input_value_t, "value") : NULL; + const Node* value_param = ser ? param(a, input_value_t, "value") : NULL; Nodes params = ser ? mk_nodes(a, address_param, value_param) : singleton(address_param); const Type* return_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && is_addr_space_uniform(a, as)), .type = element_type }); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index d745c6a4f..29d6364f4 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -38,8 +38,8 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { IrArena* a = ctx->rewriter.dst_arena; const Type* qualified_t = qualified_type(a, (QualifiedType) { .is_uniform = false, .type = element_type }); - const Node* param = push ? var(a, qualified_t, "value") : NULL; - Nodes params = push ? singleton(param) : empty(a); + const Node* value_param = push ? param(a, qualified_t, "value") : NULL; + Nodes params = push ? singleton(value_param) : empty(a); Nodes return_ts = push ? empty(a) : singleton(qualified_t); String name = format_string_arena(a->arena, "generated_%s_%s", push ? "push" : "pop", name_type_safe(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, singleton(annotation(a, (Annotation) { .name = "Generated" })), return_ts); @@ -90,28 +90,42 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { return fun; } -static const Node* process_let(Context* ctx, const Node* node) { - assert(node->tag == Let_TAG); +static const Node* process_node(Context* ctx, const Node* old) { + const Node* found = search_processed(&ctx->rewriter, old); + if (found) return found; + IrArena* a = ctx->rewriter.dst_arena; - const Node* old_instruction = node->payload.let.instruction; - const Node* tail = rewrite_node(&ctx->rewriter, node->payload.let.tail); + if (old->tag == Function_TAG && strcmp(get_abstraction_name(old), "generated_init") == 0) { + Node* new = recreate_decl_header_identity(&ctx->rewriter, old); + BodyBuilder* bb = begin_body(a); - if (old_instruction->tag == PrimOp_TAG) { - const PrimOp* oprim_op = &old_instruction->payload.prim_op; + // Make sure to zero-init the stack pointers + // TODO isn't this redundant with thoose things having an initial value already ? + // is this an old forgotten workaround ? + if (ctx->stack) { + const Node* stack_pointer = ctx->stack_pointer; + gen_store(bb, stack_pointer, uint32_literal(a, 0)); + } + new->payload.fun.body = finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body)); + return new; + } + + if (old->tag == PrimOp_TAG) { + const PrimOp* oprim_op = &old->payload.prim_op; switch (oprim_op->op) { case get_stack_size_op: { assert(ctx->stack); BodyBuilder* bb = begin_body(a); const Node* sp = gen_load(bb, ctx->stack_pointer); - return finish_body(bb, let(a, quote_helper(a, singleton(sp)), tail)); + return yield_values_and_wrap_in_block(bb, singleton(sp)); } case set_stack_size_op: { assert(ctx->stack); BodyBuilder* bb = begin_body(a); const Node* val = rewrite_node(&ctx->rewriter, oprim_op->operands.nodes[0]); gen_store(bb, ctx->stack_pointer, val); - return finish_body(bb, let(a, quote_helper(a, empty(a)), tail)); + return yield_values_and_wrap_in_block(bb, empty(a)); } case get_stack_base_op: { assert(ctx->stack); @@ -120,12 +134,9 @@ static const Node* process_let(Context* ctx, const Node* node) { const Node* stack_size = gen_load(bb, stack_pointer); const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { - if (oprim_op->op == get_stack_base_op) - bind_instruction(bb, prim_op(a, (PrimOp) {.op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) {.string = "trace: stack_size=%d\n"}), stack_size)})); - else - bind_instruction(bb, prim_op(a, (PrimOp) {.op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) {.string = "trace: uniform stack_size=%d\n"}), stack_size)})); + bind_instruction(bb, prim_op(a, (PrimOp) {.op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) {.string = "trace: stack_size=%d\n"}), stack_size)})); } - return finish_body(bb, let(a, quote_helper(a, singleton(stack_base_ptr)), tail)); + return yield_values_and_wrap_in_block(bb, singleton(stack_base_ptr)); } case push_stack_op: case pop_stack_op: { @@ -140,43 +151,16 @@ static const Node* process_let(Context* ctx, const Node* node) { Nodes results = bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = args})); if (push) - return finish_body(bb, let(a, quote_helper(a, empty(a)), tail)); + return yield_values_and_wrap_in_block(bb, empty(a)); assert(results.count == 1); - return finish_body(bb, let(a, quote_helper(a, results), tail)); + return yield_values_and_wrap_in_block(bb, results); } default: break; } } - return let(a, rewrite_node(&ctx->rewriter, old_instruction), tail); -} - -static const Node* process_node(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - - IrArena* a = ctx->rewriter.dst_arena; - - if (old->tag == Function_TAG && strcmp(get_abstraction_name(old), "generated_init") == 0) { - Node* new = recreate_decl_header_identity(&ctx->rewriter, old); - BodyBuilder* bb = begin_body(a); - - // Make sure to zero-init the stack pointers - // TODO isn't this redundant with thoose things having an initial value already ? - // is this an old forgotten workaround ? - if (ctx->stack) { - const Node* stack_pointer = ctx->stack_pointer; - gen_store(bb, stack_pointer, uint32_literal(a, 0)); - } - new->payload.fun.body = finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body)); - return new; - } - - switch (old->tag) { - case Let_TAG: return process_let(ctx, old); - default: return recreate_node_identity(&ctx->rewriter, old); - } + return recreate_node_identity(&ctx->rewriter, old); } KeyHash hash_node(Node**); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 755f6ab2f..17a947736 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -111,11 +111,11 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod if (found) fn = *found; else { - const Node* param = var(a, qualified_type_helper(t, false), "src"); - fn = function(m, singleton(param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), + const Node* src_param = param(a, qualified_type_helper(t, false), "src"); + fn = function(m, singleton(src_param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), singleton(annotation(a, (Annotation) { .name = "Generated"})), singleton(qualified_type_helper(t, true))); insert_dict(const Node*, Node*, ctx->fns, t, fn); - build_fn_body(ctx, fn, param, t); + build_fn_body(ctx, fn, src_param, t); } return first(gen_call(bb, fn_addr_helper(a, fn), singleton(src))); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 254296bc1..cf50292e2 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -117,7 +117,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* nbody = rewrite_node(&ctx2.rewriter, old->payload.fun.body); if (entry_point_annotation) { const Node* lam = case_(a, empty(a), nbody); - nbody = let(a, call(a, (Call) { .callee = fn_addr_helper(a, ctx2.init_fn), .args = empty(a)}), lam); + nbody = let(a, call(a, (Call) { .callee = fn_addr_helper(a, ctx2.init_fn), .args = empty(a)}), empty(a), lam); } fun->payload.fun.body = nbody; } diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 665039573..606d9db9a 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -72,7 +72,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* workgroup_id[3]; const Node* num_workgroups[3]; for (int dim = 0; dim < 3; dim++) { - workgroup_id[dim] = var(a, qualified_type_helper(uint32_type(a), false), names[dim]); + workgroup_id[dim] = param(a, qualified_type_helper(uint32_type(a), false), names[dim]); num_workgroups[dim] = gen_extract(bb, workgroup_num_vec3, singleton(uint32_literal(a, dim))); } @@ -87,7 +87,7 @@ static const Node* process(Context* ctx, const Node* node) { num_subgroups[2] = a->config.specializations.workgroup_size[2]; String names2[] = { "sgx", "sgy", "sgz" }; for (int dim = 0; dim < 3; dim++) { - subgroup_id[dim] = var(a, qualified_type_helper(uint32_type(a), false), names2[dim]); + subgroup_id[dim] = param(a, qualified_type_helper(uint32_type(a), false), names2[dim]); num_subgroups_literals[dim] = uint32_literal(a, num_subgroups[dim]); } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 3ecf50622..8063efbae 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -49,7 +49,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca if (is_abstraction(use->user) && use->operand_class == NcParam) continue; else if (use->user->tag == Let_TAG && use->operand_class == NcInstruction) { - Nodes vars = get_abstraction_params(get_let_tail(use->user)); + Nodes vars = use->user->payload.let.variables; for (size_t i = 0; i < vars.count; i++) { debugv_print("demote_alloca leak analysis: following let-bound variable: "); log_node(DEBUGV, vars.nodes[i]); @@ -131,7 +131,7 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { assert(is_value(ptr)); if (ptr->tag == Variablez_TAG && ctx->uses) { const Node* instr = get_var_def(ptr->payload.varz); - if (instr) { + if (instr->tag == PrimOp_TAG) { PrimOp payload = instr->payload.prim_op; switch (payload.op) { case alloca_logical_op: @@ -180,29 +180,25 @@ static const Node* process(Context* ctx, const Node* old) { } case Let_TAG: { const Node* oinstruction = get_let_instruction(old); + Nodes ovars = old->payload.let.variables; const Node* otail = get_let_tail(old); const Node* ninstruction = rewrite_node(r, oinstruction); AllocaInfo** found_info = find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, oinstruction); AllocaInfo* info = NULL; if (found_info) { - const Node* ovar = first(get_abstraction_params(otail)); + const Node* ovar = first(ovars); info = *found_info; insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, ovar, info); } - Nodes oparams = otail->payload.case_.params; Nodes ntypes = unwrap_multiple_yield_types(r->dst_arena, ninstruction->type); - assert(ntypes.count == oparams.count); - // TODO use recreate_params() - LARRAY(const Node*, new_params, oparams.count); - for (size_t i = 0; i < oparams.count; i++) { - new_params[i] = param(r->dst_arena, ntypes.nodes[i], oparams.nodes[i]->payload.param.name); - register_processed(r, oparams.nodes[i], new_params[i]); - } + assert(ntypes.count == ovars.count); + Nodes nvars = recreate_vars(a, ovars, ninstruction); + register_processed_list(r, ovars, nvars); if (info) - info->bound = new_params[0]; - const Node* nbody = rewrite_node(r, otail->payload.case_.body); - const Node* tail = case_(r->dst_arena, nodes(r->dst_arena, oparams.count, new_params), nbody); - return let(a, ninstruction, tail); + info->bound = first(nvars); + // const Node* nbody = rewrite_node(r, otail->payload.case_.body); + // const Node* tail = case_(r->dst_arena, empty(a), nbody); + return let(a, ninstruction, nvars, rewrite_node(r, otail)); } case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 9e7bf70f8..4517ddc03 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -182,7 +182,7 @@ static const Node* process(Context* ctx, const Node* node) { // Prepare a join point to replace the old function return Nodes nyield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); - const Node* join_point = var(a, qualified_type_helper(jp_type, true), format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); + const Node* join_point = param(a, qualified_type_helper(jp_type, true), format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); const Node* nbody = inline_call(ctx, ocallee, nargs, join_point); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 1eaa8c9a0..5150e1167 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -437,16 +437,17 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod const Node* oinstruction = get_let_instruction(old); const Node* ninstruction = rewrite_node(r, oinstruction); PtrKnowledge** found = find_value_dict(const Node*, PtrKnowledge*, kb->map, oinstruction); + Nodes ovars = old->payload.let.variables; if (found) { // copy any knownledge about an instruction to the bound variable - const Node* old_case = get_let_tail(old); - Nodes old_params = get_abstraction_params(old_case); - assert(old_params.count == 1); + assert(ovars.count == 1); PtrKnowledge* k = *found; - const Node* first_param = first(old_params); + const Node* first_param = first(ovars); insert_dict(const Node*, PtrKnowledge*, kb->map, first_param, k); } - return let(a, ninstruction, rewrite_node(r, get_let_tail(old))); + Nodes nvars = recreate_vars(a, ovars, ninstruction); + register_processed_list(r, ovars, nvars); + return let(a, ninstruction, nvars, rewrite_node(r, get_let_tail(old))); } case Jump_TAG: { const Node* old_target = old->payload.jump.target; @@ -503,10 +504,11 @@ static void handle_bb(Context* ctx, const Node* old) { ctx = &fn_ctx; Nodes params = recreate_params(&ctx->rewriter, get_abstraction_params(old)); - Nodes let_params = recreate_params(&ctx->rewriter, get_abstraction_params(old)); - register_processed_list(&ctx->rewriter, get_abstraction_params(old), let_params); + //Nodes let_params = recreate_params(&ctx->rewriter, get_abstraction_params(old)); + //register_processed_list(&ctx->rewriter, get_abstraction_params(old), let_params); + register_processed_list(r, get_abstraction_params(old), params); const Node* nbody = rewrite_node(&ctx->rewriter, get_abstraction_body(old)); - nbody = let(a, quote_helper(a, params), case_(a, let_params, nbody)); + //nbody = let(a, quote_helper(a, params), case_(a, let_params, nbody)); CFNode* cfnode = cfg_lookup(ctx->cfg, old); BodyBuilder* bb = begin_body(a); @@ -559,14 +561,14 @@ static void handle_bb(Context* ctx, const Node* old) { debug_print(" has a known value in all predecessors! Turning it into a new parameter.\n"); // assert(!is_qualified_type_uniform(source->type)); - const Node* param = var(a, qualified_type_helper(source->type, false), unique_name(a, "ssa_phi")); - params = append_nodes(a, params, param); + const Node* nparam = param(a, qualified_type_helper(source->type, false), unique_name(a, "ssa_phi")); + params = append_nodes(a, params, nparam); ptrs = append_nodes(ctx->rewriter.src_arena, ptrs, ptr); - gen_store(bb, rewrite_node(r, ptr), param); + gen_store(bb, rewrite_node(r, ptr), nparam); PtrKnowledge* k = arena_alloc(ctx->a, sizeof(PtrKnowledge)); *k = (PtrKnowledge) { - .ptr_value = param, + .ptr_value = nparam, .source = source, .ptr_has_leaked = uk.ptr_has_leaked }; diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index cef2a280c..5df96beb9 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -104,7 +104,7 @@ static const Node* handle_bb_callsite(Context* ctx, BodyBuilder* bb, const Node* append_list(struct Dict*, ctx->tmp_alloc_stack, tmp_processed); ctx2.rewriter.map = tmp_processed; for (size_t i = 0; i < oargs.count; i++) { - nparams[i] = var(a, rewrite_node(&ctx->rewriter, oparams.nodes[i]->type), "arg"); + nparams[i] = param(a, rewrite_node(&ctx->rewriter, oparams.nodes[i]->type), "arg"); register_processed(&ctx2.rewriter, oparams.nodes[i], nparams[i]); } @@ -115,7 +115,7 @@ static const Node* handle_bb_callsite(Context* ctx, BodyBuilder* bb, const Node* // Just jumps to the actual ladder const Node* exit_ladder_trampoline = case_(a, empty(a), jump(a, (Jump) {.target = inner_exit_ladder_bb, .args = empty(a)})); - const Node* structured = structure(&ctx2, dst, let(a, quote_helper(a, empty(a)), exit_ladder_trampoline)); + const Node* structured = structure(&ctx2, dst, let(a, quote_helper(a, empty(a)), empty(a), exit_ladder_trampoline)); assert(is_terminator(structured)); // forget we rewrote all that destroy_dict(tmp_processed); @@ -154,11 +154,14 @@ static const Node* rebuild_let(Context* ctx, const Node* old_let, const Node* ne IrArena* a = ctx->rewriter.dst_arena; const Node* old_tail = get_let_tail(old_let); Nodes otail_params = get_abstraction_params(old_tail); + assert(otail_params.count == 0); - Nodes rewritten_params = recreate_params(&ctx->rewriter, otail_params); - register_processed_list(&ctx->rewriter, otail_params, rewritten_params); - const Node* structured_lam = case_(a, rewritten_params, structure(ctx, old_tail, exit_ladder)); - return let(a, new_instruction, structured_lam); + Nodes ovars = old_let->payload.let.variables; + Nodes nvars = recreate_vars(a, ovars, new_instruction); + register_processed_list(&ctx->rewriter, ovars, nvars); + + const Node* structured_lam = case_(a, empty(a), structure(ctx, old_tail, exit_ladder)); + return let(a, new_instruction, nvars, structured_lam); } static const Node* structure(Context* ctx, const Node* abs, const Node* exit_ladder) { @@ -170,7 +173,8 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case NotATerminator: case Let_TAG: { const Node* old_tail = get_let_tail(body); - Nodes otail_params = get_abstraction_params(old_tail); + Nodes ovars = body->payload.let.variables; + //Nodes otail_params = get_abstraction_params(old_tail); const Node* old_instr = get_let_instruction(body); switch (is_instruction(old_instr)) { @@ -229,7 +233,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad LARRAY(const Node*, phi_values, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { phi_values[i] = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = load_op, .operands = singleton(phis[i]) }))); - register_processed(&ctx->rewriter, otail_params.nodes[i], phi_values[i]); + register_processed(&ctx->rewriter, ovars.nodes[i], phi_values[i]); } // Wrap the tail in a guarded if, to handle 'far' joins @@ -245,7 +249,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad })); const Node* tail_lambda = case_(a, empty(a), finish_body(bb2, exit_ladder)); - return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), tail_lambda))); + return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), empty(a), tail_lambda))); } default: { break; @@ -278,7 +282,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad .if_false = if_false_lam, }); const Node* post_merge_lam = case_(a, empty(a), exit_ladder); - return let(a, instr, post_merge_lam); + return let(a, instr, empty(a), post_merge_lam); } case Switch_TAG: { const Node* switch_value = rewrite_node(&ctx->rewriter, body->payload.br_switch.switch_value); @@ -300,7 +304,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad .cases = nodes(a, body->payload.br_switch.case_jumps.count, cases), .literals = rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), }); - return let(a, instr, case_(a, empty(a), exit_ladder)); + return let(a, instr, empty(a), case_(a, empty(a), exit_ladder)); } case Join_TAG: { ControlEntry* control = search_containing_control(ctx, body->payload.join.join_point); diff --git a/src/shady/passes/opt_stack.c b/src/shady/passes/opt_stack.c index e2c9cd617..cc019a0ca 100644 --- a/src/shady/passes/opt_stack.c +++ b/src/shady/passes/opt_stack.c @@ -101,7 +101,10 @@ static const Node* process(Context* ctx, const Node* node) { ninstruction = recreate_node_identity(&ctx->rewriter, old_instruction); } assert(ninstruction); - return let(a, ninstruction, ntail); + Nodes ovars = node->payload.let.variables; + Nodes nvars = recreate_vars(a, ovars, ninstruction); + register_processed_list(&ctx->rewriter, ovars, nvars); + return let(a, ninstruction, nvars, ntail); } // Unreachable is assumed to never happen, so it doesn't observe the stack state case NotATerminator: break; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 2b2cfefe9..476981783 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -336,8 +336,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .args = nodes(arena, exit_param_allocas[i].count, recovered_args), })); } else { - assert(recreated_exit->tag == Case_TAG); - exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, let(arena, quote_helper(arena, nodes(arena, exit_param_allocas[i].count, recovered_args)), recreated_exit)); + // TODO: rewrite + assert(get_abstraction_params(recreated_exit).count == 0); + error("") + // assert(recreated_exit->tag == Case_TAG); + // exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, let(arena, quote_helper(arena, nodes(arena, exit_param_allocas[i].count, recovered_args)), recreated_exit)); } exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena)); destroy_list(leaking[i]); @@ -474,18 +477,15 @@ static const Node* process_node(Context* ctx, const Node* node) { //Regular if/then/else case. Control flow joins at the immediate post dominator. Nodes yield_types; Nodes exit_args; - Nodes lambda_args; Nodes old_params = get_abstraction_params(idom); if (old_params.count == 0) { yield_types = empty(arena); exit_args = empty(arena); - lambda_args = empty(arena); } else { LARRAY(const Node*, types,old_params.count); LARRAY(const Node*, inner_args,old_params.count); - LARRAY(const Node*, outer_args,old_params.count); for (size_t j = 0; j < old_params.count; j++) { //TODO: Is this correct? @@ -498,12 +498,10 @@ static const Node* process_node(Context* ctx, const Node* node) { types[j] = get_unqualified_type(qualified_type); inner_args[j] = param(arena, qualified_type, old_params.nodes[j]->payload.param.name); - outer_args[j] = param(arena, qualified_type, old_params.nodes[j]->payload.param.name); } yield_types = nodes(arena, old_params.count, types); exit_args = nodes(arena, old_params.count, inner_args); - lambda_args = nodes(arena, old_params.count, outer_args); } const Node* join_token = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { @@ -532,7 +530,7 @@ static const Node* process_node(Context* ctx, const Node* node) { register_processed(rewriter, idom, cached); const Node* control_inner = case_(arena, singleton(join_token), inner_terminator); - const Node* new_target = control(arena, (Control) { + const Node* control_instruction = control(arena, (Control) { .inside = control_inner, .yield_types = yield_types }); @@ -541,18 +539,16 @@ static const Node* process_node(Context* ctx, const Node* node) { switch (idom->tag) { case BasicBlock_TAG: { - const Node* outer_terminator = jump(arena, (Jump) { + BodyBuilder* bb = begin_body(arena); + Nodes results = bind_instruction(bb, control_instruction); + return finish_body(bb, jump(arena, (Jump) { .target = recreated_join, - .args = lambda_args - }); - - const Node* c = case_(arena, lambda_args, outer_terminator); - const Node* empty_let = let(arena, new_target, c); - - return empty_let; + .args = results + })); } case Case_TAG: - return let(arena, new_target, recreated_join); + error("todo"); + // return let(arena, control_instruction, recreated_join); default: assert(false); } diff --git a/src/shady/print.c b/src/shady/print.c index 12b085fdc..44877bf50 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -669,25 +669,26 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { const Node* tail = get_let_tail(node); if (!ctx->config.reparseable) { // if the let tail is a case, we apply some syntactic sugar - if (mut || tail->payload.case_.params.count > 0) { + Nodes variables = node->payload.let.variables; + if (mut || variables.count > 0) { printf(GREEN); if (mut) printf("var"); else printf("val"); printf(RESET); - Nodes params = tail->payload.case_.params; if (mut) { - params = instruction->payload.let_mut.variables; + variables = instruction->payload.let_mut.variables; instruction = instruction->payload.let_mut.instruction; } - for (size_t i = 0; i < params.count; i++) { - if (mut || !ctx->config.reparseable) { + for (size_t i = 0; i < variables.count; i++) { + // TODO: fix let mut + if (node->arena->config.check_types && (mut || !ctx->config.reparseable)) { printf(" "); - print_node(params.nodes[i]->payload.param.type); + print_node(variables.nodes[i]->type); } printf(" "); - print_node(params.nodes[i]); + print_node(variables.nodes[i]); printf(RESET); } printf(" = "); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 44c101b9b..4f5f9ec0b 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -239,6 +239,15 @@ Nodes recreate_params(Rewriter* rewriter, Nodes oparams) { return nodes(rewriter->dst_arena, oparams.count, nparams); } +Nodes recreate_vars(IrArena* arena, Nodes ovars, const Node* instruction) { + LARRAY(const Node*, nvars_arr, ovars.count); + for (size_t i = 0; i < ovars.count; i++) { + nvars_arr[i] = var(arena, ovars.nodes[i]->payload.varz.name, instruction, i); + } + Nodes nvars = nodes(arena, ovars.count, nvars_arr); + return nvars; +} + Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { Node* new = NULL; switch (is_declaration(old)) { @@ -322,6 +331,51 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) return tail; }*/ +void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr); + +// eliminates blocks by "lifting" their contents out and replacing yield with the tail of the outer let +// In other words, we turn these patterns: +// +// let block { +// let I in case(x) => +// let J in case(y) => +// let K in case(z) => +// ... +// yield (x, y, z) } +// in case(a, b, c) => R +// +// into these: +// +// let I in case(x) => +// let J in case(y) => +// let K in case(z) => +// ... +// R[a->x, b->y, c->z] +Nodes flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* bb) { + assert(instruction->tag == Block_TAG); + // follow the terminator of the block until we hit a yield() + const Node* const lam = instruction->payload.block.inside; + assert(is_case(lam)); + const Node* terminator = get_abstraction_body(lam); + while (true) { + switch (is_terminator(terminator)) { + case NotATerminator: assert(false); + case Terminator_Let_TAG: { + bind_variables2(bb, terminator->payload.let.variables, terminator->payload.let.instruction); + terminator = get_abstraction_body(terminator->payload.let.tail); + continue; + } + case Terminator_Yield_TAG: { + return terminator->payload.yield.args; + } + // if we see anything else, give up + default: { + assert(false && "invalid block"); + } + } + } +} + const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { if (node == NULL) return NULL; @@ -344,28 +398,24 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { case Param_TAG: error("params should be rewritten by the abstraction rewrite logic"); case Variablez_TAG: error("variables should be rewritten by the binding let"); case Let_TAG: { + BodyBuilder* bb = begin_body(arena); const Node* instruction = rewrite_op_helper(rewriter, NcInstruction, "instruction", node->payload.let.instruction); - if (arena->config.allow_fold && rewriter->config.fold_quote && instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { - Nodes old_params = node->payload.let.tail->payload.case_.params; - Nodes new_args = instruction->payload.prim_op.operands; - assert(old_params.count == new_args.count); - register_processed_list(rewriter, old_params, new_args); - for (size_t i = 0; i < old_params.count; i++) { - String old_name = get_value_name_unsafe(old_params.nodes[i]); - if (!old_name) continue; - const Node* new_arg = new_args.nodes[i]; - if (new_arg->tag == Variablez_TAG && !get_value_name_unsafe(new_arg)) { - set_variable_name((Node*) new_arg, old_name); - } - } - return rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.let.tail->payload.case_.body); + // optimization: fold blocks + if (instruction->tag == Block_TAG) { + instruction = quote_helper(arena, flatten_block(arena, instruction, bb)); + } + Nodes ovars = node->payload.let.variables; + // optimization: eliminate unecessary quotes by rewriting variables into their values directly + if (instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { + register_processed_list(rewriter, ovars, instruction->payload.prim_op.operands); + return finish_body(bb, get_abstraction_body(rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail))); } - const Node* tail; - // if (rewriter->config.rebind_let) - // tail = rebind_let(rewriter, instruction, node->payload.let.tail); - // else - tail = rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail); //TODO - return let(arena, instruction, tail); + // rewrite variables now + Nodes nvars = recreate_vars(arena, ovars, instruction); + register_processed_list(rewriter, ovars, nvars); + // bind_variables2(bb, nvars, instruction); + const Node* nlet = let(arena, instruction, nvars, rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail)); + return finish_body(bb, nlet); } case LetMut_TAG: error("De-sugar this by hand") case Case_TAG: { diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index 36e8d1fde..f6fd3f876 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -64,6 +64,7 @@ void recreate_decl_body_identity(Rewriter*, const Node*, Node*); /// Rewrites a variable under a new identity const Node* recreate_param(Rewriter* rewriter, const Node* old); Nodes recreate_params(Rewriter* rewriter, Nodes oparams); +Nodes recreate_vars(IrArena* arena, Nodes ovars, const Node* instruction); Node* clone_bb_head(Rewriter*, const Node* bb); //const Node* rebind_let(Rewriter*, const Node* ninstruction, const Node* ocase); diff --git a/src/shady/type.c b/src/shady/type.c index 972f5484a..4ca21b238 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1217,12 +1217,10 @@ const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { } const Type* check_type_let(IrArena* arena, Let let) { - assert(is_instruction(let.instruction)); - assert(is_case(let.tail)); Nodes produced_types = unwrap_multiple_yield_types(arena, let.instruction->type); Nodes param_types = get_param_types(arena, let.tail->payload.case_.params); - - check_arguments_types_against_parameters_helper(param_types, produced_types); + assert(param_types.count == 0); + // check_arguments_types_against_parameters_helper(param_types, produced_types); return noret_type(arena); } From 1660bc8eb12b4f2b4b068735e87f3d222a3a3b6a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 3 May 2024 19:08:58 +0200 Subject: [PATCH 233/693] fix demote_alloca --- src/shady/passes/opt_demote_alloca.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 8063efbae..0c1d41bf7 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -48,14 +48,22 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca for (;use; use = use->next_use) { if (is_abstraction(use->user) && use->operand_class == NcParam) continue; + if (use->operand_class == NcVariable) + continue; + if (use->user->tag == Variablez_TAG) { + debugv_print("demote_alloca leak analysis: following let-bound variable: "); + log_node(DEBUGV, use->user); + debugv_print(".\n"); + visit_ptr_uses(use->user, slice_type, k, map); + } else if (use->user->tag == Let_TAG && use->operand_class == NcInstruction) { - Nodes vars = use->user->payload.let.variables; + /*Nodes vars = use->user->payload.let.variables; for (size_t i = 0; i < vars.count; i++) { debugv_print("demote_alloca leak analysis: following let-bound variable: "); log_node(DEBUGV, vars.nodes[i]); debugv_print(".\n"); visit_ptr_uses(vars.nodes[i], slice_type, k, map); - } + }*/ } else if (use->user->tag == PrimOp_TAG) { PrimOp payload = use->user->payload.prim_op; switch (payload.op) { From 4527e0d56b8d9e964305e3196075c2a021500e82 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 4 May 2024 09:21:40 +0200 Subject: [PATCH 234/693] fix msvc build on older SDKs --- src/common/dict.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/dict.h b/src/common/dict.h index 009b3e043..3d91e3f6e 100644 --- a/src/common/dict.h +++ b/src/common/dict.h @@ -6,6 +6,8 @@ #include #include +#include "portability.h" + typedef uint32_t KeyHash; typedef KeyHash (*HashFn)(void*); typedef bool (*CmpFn)(void*, void*); From b9c48f6ab7bee50d88fb2ab833d1314c8e3cdd4b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 4 May 2024 09:22:47 +0200 Subject: [PATCH 235/693] cmake: don't use CMAKE_SOURCE_DIR --- src/shady/CMakeLists.txt | 2 +- src/shady/api/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index d43827ff7..744414f96 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -117,5 +117,5 @@ target_link_libraries(shady INTERFACE "common") target_link_libraries(shady PRIVATE "$") target_link_libraries(shady PRIVATE "$") -install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/shady DESTINATION include) +install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/shady DESTINATION include) install(TARGETS shady EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) diff --git a/src/shady/api/CMakeLists.txt b/src/shady/api/CMakeLists.txt index e4f407a01..e7a10cbff 100644 --- a/src/shady/api/CMakeLists.txt +++ b/src/shady/api/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(api INTERFACE) -target_include_directories(api INTERFACE "$" "$" "$") +target_include_directories(api INTERFACE "$" "$" "$") target_include_directories(api INTERFACE "$") get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) From 1a4ac038aabe21f723fbea21ec58288e00da4b35 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 5 May 2024 12:32:29 +0200 Subject: [PATCH 236/693] fix lift_indirect_targets --- include/shady/ir.h | 1 + src/shady/ir.c | 7 ++++++ src/shady/passes/lift_indirect_targets.c | 27 ++++++++++----------- src/shady/passes/lower_stack.c | 2 +- src/shady/passes/reconvergence_heuristics.c | 7 ------ src/shady/print.c | 4 +-- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 847c0a68f..a07be5469 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -37,6 +37,7 @@ Nodes append_nodes(IrArena*, Nodes, const Node*); Nodes prepend_nodes(IrArena*, Nodes, const Node*); Nodes concat_nodes(IrArena*, Nodes, Nodes); Nodes change_node_at_index(IrArena*, Nodes, size_t, const Node*); +bool find_in_nodes(Nodes nodes, const Node* n); String string_sized(IrArena*, size_t size, const char* start); String string(IrArena*, const char*); diff --git a/src/shady/ir.c b/src/shady/ir.c index 1a2dc6287..d0c1a4ee0 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -157,6 +157,13 @@ Nodes change_node_at_index(IrArena* arena, Nodes old, size_t i, const Node* n) { return nodes(arena, old.count, tmp); } +bool find_in_nodes(Nodes nodes, const Node* n) { + for (size_t i = 0; i < nodes.count; i++) + if (nodes.nodes[i] == n) + return true; + return false; +} + /// takes care of structural sharing static const char* string_impl(IrArena* arena, size_t size, const char* zero_terminated) { if (!zero_terminated) diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 15f0ac6f2..90d35c5fb 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -68,31 +68,27 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, struct L return sp; } -static void add_to_recover_context(struct List* recover_context, struct Dict* set, const Node* except) { - Nodes params = get_abstraction_params(except); +static void add_to_recover_context(struct List* recover_context, struct Dict* set, Nodes except) { size_t i = 0; const Node* item; while (dict_iter(set, &i, &item, NULL)) { - for (size_t j = 0; j < params.count; j++) { - if (item == params.nodes[j]) - goto skip; - } + if (find_in_nodes(except, item)) + continue; append_list(const Node*, recover_context, item ); - skip:; } } -static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, String given_name) { +static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariables) { assert(is_basic_block(liftee) || is_case(liftee)); LiftedCont** found = find_value_dict(const Node*, LiftedCont*, ctx->lifted, liftee); if (found) return *found; IrArena* a = ctx->rewriter.dst_arena; - Nodes oparams = get_abstraction_params(liftee); + //Nodes oparams = get_abstraction_params(liftee); const Node* obody = get_abstraction_body(liftee); - String name = is_basic_block(liftee) ? format_string_arena(a->arena, "%s_%s", get_abstraction_name(liftee->payload.basic_block.fn), get_abstraction_name(liftee)) : unique_name(a, given_name); + String name = get_abstraction_name_safe(liftee); // Compute the live stuff we'll need CFG* cfg_rooted_in_liftee = build_cfg(ctx->cfg->entry->node, liftee, NULL, false); @@ -101,7 +97,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, String given_na CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, live_vars, cf_node); struct List* recover_context = new_list(const Node*); - add_to_recover_context(recover_context, node_vars->free_set, liftee); + add_to_recover_context(recover_context, node_vars->free_set, ovariables); size_t recover_context_size = entries_count_list(recover_context); destroy_cfg_variables_map(live_vars); @@ -118,7 +114,10 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, String given_na debugv_print("\n"); // Create and register new parameters for the lifted continuation - Nodes new_params = recreate_params(&ctx->rewriter, oparams); + LARRAY(const Node*, new_params_arr, ovariables.count); + for (size_t i = 0; i < ovariables.count; i++) + new_params_arr[i] = param(a, rewrite_node(&ctx->rewriter, ovariables.nodes[i]->type), get_value_name_unsafe(ovariables.nodes[i])); + Nodes new_params = nodes(a, ovariables.count, new_params_arr); LiftedCont* lifted_cont = calloc(sizeof(LiftedCont), 1); lifted_cont->old_cont = liftee; @@ -127,7 +126,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, String given_na Context lifting_ctx = *ctx; lifting_ctx.rewriter = create_children_rewriter(&ctx->rewriter); - register_processed_list(&lifting_ctx.rewriter, oparams, new_params); + register_processed_list(&lifting_ctx.rewriter, ovariables, new_params); const Node* payload = param(a, qualified_type_helper(uint32_type(a), false), "sp"); @@ -210,7 +209,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* otail = get_let_tail(node); BodyBuilder* bb = begin_body(a); - LiftedCont* lifted_tail = lambda_lift(ctx, otail, unique_name(a, format_string_arena(a->arena, "lifted %s", get_abstraction_name_safe(otail)))); + LiftedCont* lifted_tail = lambda_lift(ctx, otail, node->payload.let.variables); const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 29d6364f4..18f3113c8 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -67,7 +67,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { const Node* popped_value = NULL; if (push) - gen_store(bb, addr, param); + gen_store(bb, addr, value_param); else popped_value = gen_primop_ce(bb, load_op, 1, (const Node* []) { addr }); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 476981783..093969554 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -60,13 +60,6 @@ static void gather_exiting_nodes(LoopTree* lt, const CFNode* entry, const CFNode } } -static bool find_in_nodes(Nodes nodes, const Node* n) { - for (size_t i = 0; i < nodes.count; i++) - if (nodes.nodes[i] == n) - return true; - return false; -} - static void find_unbound_vars(const Node* loop_header, const Node* exiting_node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { const Node* free_post; size_t i = 0; diff --git a/src/shady/print.c b/src/shady/print.c index 44877bf50..8267c7660 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -522,13 +522,13 @@ static void print_value(PrinterCtx* ctx, const Node* node) { } case Value_RefDecl_TAG: { printf(BYELLOW); - printf((char*) get_declaration_name(node->payload.ref_decl.decl)); + printf("%s", (char*) get_declaration_name(node->payload.ref_decl.decl)); printf(RESET); break; } case FnAddr_TAG: printf(BYELLOW); - printf((char*) get_declaration_name(node->payload.fn_addr.fn)); + printf("%s", (char*) get_declaration_name(node->payload.fn_addr.fn)); printf(RESET); break; default: From 93439ee3e9e83d6d55dd1df493419e1e29d20b32 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 4 May 2024 09:21:40 +0200 Subject: [PATCH 237/693] fix msvc build on older SDKs --- src/common/dict.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/dict.h b/src/common/dict.h index 009b3e043..3d91e3f6e 100644 --- a/src/common/dict.h +++ b/src/common/dict.h @@ -6,6 +6,8 @@ #include #include +#include "portability.h" + typedef uint32_t KeyHash; typedef KeyHash (*HashFn)(void*); typedef bool (*CmpFn)(void*, void*); From 481889206826a9b58ea705d5c78c18bb33d97185 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 4 May 2024 09:22:47 +0200 Subject: [PATCH 238/693] cmake: don't use CMAKE_SOURCE_DIR --- src/shady/CMakeLists.txt | 2 +- src/shady/api/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index d43827ff7..744414f96 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -117,5 +117,5 @@ target_link_libraries(shady INTERFACE "common") target_link_libraries(shady PRIVATE "$") target_link_libraries(shady PRIVATE "$") -install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/shady DESTINATION include) +install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/shady DESTINATION include) install(TARGETS shady EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) diff --git a/src/shady/api/CMakeLists.txt b/src/shady/api/CMakeLists.txt index e4f407a01..e7a10cbff 100644 --- a/src/shady/api/CMakeLists.txt +++ b/src/shady/api/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(api INTERFACE) -target_include_directories(api INTERFACE "$" "$" "$") +target_include_directories(api INTERFACE "$" "$" "$") target_include_directories(api INTERFACE "$") get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) From ea297c244104028fff03ba6bd99b43f856a23437 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 5 May 2024 13:40:37 +0200 Subject: [PATCH 239/693] fix let emission in C backend --- src/shady/emit/c/emit_c.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 71d3235fc..fac1eed3b 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -434,18 +434,18 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node const Node* tail = get_let_tail(terminator); assert(tail->tag == Case_TAG); - const Nodes tail_params = tail->payload.case_.params; - assert(tail_params.count == yield_types.count); + Nodes vars = terminator->payload.let.variables; + assert(vars.count == yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { bool has_result = results[i].value || results[i].var; switch (bindings[i]) { case NoBinding: { assert(has_result && "unbound results can't be empty"); - register_emitted(emitter, tail_params.nodes[i], results[i]); + register_emitted(emitter, vars.nodes[i], results[i]); break; } case LetBinding: { - String variable_name = get_value_name_unsafe(tail_params.nodes[i]); + String variable_name = get_value_name_unsafe(vars.nodes[i]); if (!variable_name) variable_name = ""; @@ -459,7 +459,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node else emit_variable_declaration(emitter, block_printer, t, bind_to, false, NULL); - register_emitted(emitter, tail_params.nodes[i], term_from_cvalue(bind_to)); + register_emitted(emitter, vars.nodes[i], term_from_cvalue(bind_to)); break; } default: assert(false); From 64e9fe7b16b211309ce9e76b04ce25887fe8c5e4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 5 May 2024 21:33:58 +0200 Subject: [PATCH 240/693] fix restructure --- src/shady/passes/opt_restructure.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 5df96beb9..5135f0bd3 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -132,9 +132,12 @@ static const Node* handle_bb_callsite(Context* ctx, BodyBuilder* bb, const Node* inner_exit_ladder_bb->payload.basic_block.body = merge_break(a, (MergeBreak) { .args = empty(a) }); return finish_body(bb, exit_ladder); } else { - bind_variables(bb, nodes(a, oargs.count, nparams), rewrite_nodes(&ctx->rewriter, oargs)); + Node* bb2 = basic_block(a, ctx->fn, nodes(a, oargs.count, nparams), NULL); + bb2->payload.basic_block.body = structured; + //bind_variables(bb, nodes(a, oargs.count, nparams), rewrite_nodes(&ctx->rewriter, oargs)); inner_exit_ladder_bb->payload.basic_block.body = exit_ladder; - return finish_body(bb, structured); + //return finish_body(bb, structured); + return finish_body(bb, jump_helper(a, bb2, rewrite_nodes(&ctx->rewriter, oargs))); } } } From 9c7ec44624da5fa33cfc840ce25264aa7895106c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 6 May 2024 09:50:24 +0200 Subject: [PATCH 241/693] fix free variables analysis --- src/shady/analysis/free_variables.c | 99 ++++++++++++++--------------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index 145424e87..fea937806 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -56,51 +56,9 @@ static CFNodeVariables* create_node_variables(CFNode* cfnode) { return v; } -static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, CFNodeVariables* parent) { - Context new_context = *ctx; - ctx = &new_context; - - ctx->current_scope = create_node_variables(cfnode); - ctx->current_scope->bound_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - insert_dict(CFNode*, CFNodeVariables*, ctx->map, cfnode, ctx->current_scope); +static void dump_free_variables(Context* ctx, CFNode* cfnode, int depth) { const Node* abs = cfnode->node; - - bool is_named = abs->tag != Case_TAG; - - // Bind parameters - Nodes params = get_abstraction_params(abs); - for (size_t j = 0; j < params.count; j++) { - const Node* param = params.nodes[j]; - bool r = insert_set_get_result(const Node*, ctx->current_scope->bound_set, param); - assert(r); - } - - const Node* body = get_abstraction_body(abs); - if (body) - visit_op(&ctx->visitor, NcTerminator, "body", body); - - for (size_t i = 0; i < entries_count_list(cfnode->dominates); i++) { - CFNode* child = read_list(CFNode*, cfnode->dominates)[i]; - CFNodeVariables* child_variables = visit_domtree(ctx, child, depth + (is_named ? 1 : 1), ctx->current_scope); - size_t j = 0; - const Node* free_var; - while (dict_iter(child_variables->free_set, &j, &free_var, NULL)) { - const Node** found = find_key_dict(const Node*, ctx->current_scope->bound_set, free_var); - if (!found) - insert_set_get_result(const Node*, ctx->current_scope->free_set, free_var); - next:; - } - } - - if (parent) { - size_t j = 0; - const Node* bound; - while (dict_iter(parent->bound_set, &j, &bound, NULL)) { - insert_set_get_result(const Node*, ctx->current_scope->bound_set, bound); - } - } - - /*String abs_name = get_abstraction_name_unsafe(abs); + String abs_name = get_abstraction_name_unsafe(abs); for (int i = 0; i < depth; i++) debugvv_print(" "); if (abs_name) @@ -124,25 +82,64 @@ static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, C if (true) { debugvv_print(". Binds: "); bool prev = false; - for (size_t i = 0; i < params.count; i++) { + size_t i = 0; + const Node* bound_var; + while (dict_iter(ctx->current_scope->bound_set, &i, &bound_var, NULL)) { if (prev) { debugvv_print(", "); } - log_node(DEBUGVV, params.nodes[i]); + log_node(DEBUGVV, bound_var); prev = true; } } - debugvv_print("\n");*/ + debugvv_print("\n"); +} + +static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, CFNodeVariables* parent) { + Context new_context = *ctx; + ctx = &new_context; + + ctx->current_scope = create_node_variables(cfnode); + ctx->current_scope->bound_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); + insert_dict(CFNode*, CFNodeVariables*, ctx->map, cfnode, ctx->current_scope); + const Node* abs = cfnode->node; - // Unbind parameters + // Bind parameters + Nodes params = get_abstraction_params(abs); for (size_t j = 0; j < params.count; j++) { const Node* param = params.nodes[j]; - assert(find_key_dict(const Node*, ctx->current_scope->bound_set, param)); - //bool r = remove_dict(const Node*, ctx->current_scope->bound_set, param); - //assert(r); + bool r = insert_set_get_result(const Node*, ctx->current_scope->bound_set, param); + assert(r); + } + + const Node* body = get_abstraction_body(abs); + if (body) + visit_op(&ctx->visitor, NcTerminator, "body", body); + + if (parent) { + size_t j = 0; + const Node* bound; + while (dict_iter(parent->bound_set, &j, &bound, NULL)) { + insert_set_get_result(const Node*, ctx->current_scope->bound_set, bound); + } + } + + for (size_t i = 0; i < entries_count_list(cfnode->dominates); i++) { + CFNode* child = read_list(CFNode*, cfnode->dominates)[i]; + CFNodeVariables* child_variables = visit_domtree(ctx, child, depth + 1, ctx->current_scope); + size_t j = 0; + const Node* free_var; + while (dict_iter(child_variables->free_set, &j, &free_var, NULL)) { + const Node** found = find_key_dict(const Node*, ctx->current_scope->bound_set, free_var); + if (!found) + insert_set_get_result(const Node*, ctx->current_scope->free_set, free_var); + next:; + } } + // dump_free_variables(ctx, cfnode, depth); + return ctx->current_scope; } From 74691b7b5cd4a2231815f920eccf787653587035 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 6 May 2024 10:01:01 +0200 Subject: [PATCH 242/693] mem2reg: bail on loop back-edges for now --- src/shady/passes/opt_mem2reg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 5150e1167..b0dbe2c4a 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -140,7 +140,8 @@ static void destroy_kb(KnowledgeBase* kb) { static KnowledgeBase* get_kb(Context* ctx, const Node* abs) { assert(ctx->cfg); KnowledgeBase** found = find_value_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, abs); - assert(found); + if (!found) + return NULL; return *found; } @@ -165,6 +166,7 @@ static KnowledgeBase* create_kb(Context* ctx, const Node* old) { if (edge.type == LetTailEdge || edge.type == JumpEdge) { CFNode* dominator = edge.src; const KnowledgeBase* parent_kb = get_kb(ctx, dominator->node); + assert(parent_kb); assert(parent_kb->map); kb->dominator_kb = parent_kb; } @@ -524,6 +526,9 @@ static void handle_bb(Context* ctx, const Node* old) { if (edge.type == StructuredPseudoExitEdge) continue; // these are not real edges... KnowledgeBase* kb_at_src = get_kb(ctx, edge.src->node); + if (!kb_at_src) { + goto next_potential_param; + } const Node* kv = get_known_value(kb_at_src, get_last_valid_ptr_knowledge(kb_at_src, ptr)); if (kv) { From 160dbcbf138b92bfea51b29387266ad6133e9e38 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 6 May 2024 10:26:48 +0200 Subject: [PATCH 243/693] deal with unnamed basic blocks better --- src/frontends/llvm/l2s.c | 4 ++-- src/frontends/llvm/l2s_postprocess.c | 12 ++++++------ src/shady/emit/spirv/emit_spv.c | 5 +++-- src/shady/passes/opt_mem2reg.c | 15 ++++++--------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index b4b225a90..bb480e19e 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -91,8 +91,8 @@ static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { after_phis: { String name = LLVMGetBasicBlockName(bb); - if (!name || strlen(name) == 0) - name = unique_name(a, "bb"); + if (strlen(name) == 0) + name = NULL; Node* nbb = basic_block(a, fn_ctx->fn, params, name); insert_dict(LLVMValueRef, const Node*, p->map, bb, nbb); insert_dict(const Node*, struct List*, fn_ctx->phis, nbb, phis); diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 7eba11008..d2e377971 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -194,7 +194,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, log_node(WARN, dst); warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { - debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name(src), get_abstraction_name(dst)); + debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name_safe(src), get_abstraction_name_safe(dst)); CFNode* src_cfnode = cfg_lookup(ctx->cfg, src); assert(src_cfnode->node); @@ -203,14 +203,14 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, CFNode* dom = src_cfnode->idom; while (dom) { if (dom->node->tag == BasicBlock_TAG || dom->node->tag == Function_TAG) { - debug_print("Considering %s as a location for control\n", get_abstraction_name(dom->node)); + debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); Nodes* dom_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, dom->node); if (!dom_lexical_scope) { warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name(dom->node)); } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { - error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name(dom->node)); + error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { - debug_print("We need to introduce a control() block at %s, pointing at %s\n.", get_abstraction_name(dom->node), get_abstraction_name(dst)); + debug_print("We need to introduce a control() block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); Controls** found = find_value_dict(const Node, Controls*, ctx->controls, dom->node); if (found) { Controls* controls = *found; @@ -225,7 +225,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = get_param_types(a, get_abstraction_params(dst)) }); - join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name(dst)); + join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); controls->tokens = append_nodes(a, controls->tokens, join_token); controls->destinations = append_nodes(a, controls->destinations, dst); } @@ -236,7 +236,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, fn = (Node*) fn->payload.basic_block.fn; assert(fn->tag == Function_TAG); fn = rewrite_node(r, fn); - Node* wrapper = basic_block(a, fn, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name(dst))); + Node* wrapper = basic_block(a, fn, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); wrapper->payload.basic_block.body = join(a, (Join) { .args = nparams, .join_point = join_token diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 085a08ce3..184c55cf8 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -270,8 +270,9 @@ static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const CFG* SpvId bb_id = get_block_builder_id(bb_builder); spvb_add_bb(fn_builder, bb_builder); - if (is_basic_block(bb_node)) - spvb_name(emitter->file_builder, bb_id, bb_node->payload.basic_block.name); + String name = get_abstraction_name_unsafe(bb_node); + if (name) + spvb_name(emitter->file_builder, bb_id, name); MergeTargets merge_targets = { .continue_target = 0, diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index b0dbe2c4a..1c452353f 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -216,7 +216,7 @@ static const Node* find_or_request_known_ptr_value(Context* ctx, KnowledgeBase* } debug_print("mem2reg: It'd sure be nice to know the value of "); log_node(DEBUG, optr); - debug_print(" at phi-like node %s.\n", get_abstraction_name(phi_kb->cfnode->node)); + debug_print(" at phi-like node %s.\n", get_abstraction_name_safe(phi_kb->cfnode->node)); // log_node(DEBUG, phi_location->node); insert_set_get_key(const Node*, phi_kb->potential_additional_params, optr); } @@ -456,8 +456,7 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod // rewrite_node(&ctx->rewriter, old_target); Nodes args = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); - //String s = format_string_interned(a, "%s_", get_abstraction_name(old_target)); - String s = get_abstraction_name(old_target); + String s = get_abstraction_name_unsafe(old_target); Node* wrapper = basic_block(a, (Node*) rewrite_node(r, old_target->payload.basic_block.fn), recreate_params(r, get_abstraction_params(old_target)), s); TodoJump todo = { .old_jump = old, @@ -498,7 +497,7 @@ static void handle_bb(Context* ctx, const Node* old) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; - log_string(DEBUGV, "mem2reg: handling bb %s\n", get_abstraction_name(old)); + log_string(DEBUGV, "mem2reg: handling bb %s\n", get_abstraction_name_safe(old)); KnowledgeBase* kb = create_kb(ctx, old); Context fn_ctx = *ctx; @@ -535,7 +534,7 @@ static void handle_bb(Context* ctx, const Node* old) { log_node(DEBUG, ptr); debug_print(" has a known value ("); log_node(DEBUG, kv); - debug_print(") in %s ...\n", get_abstraction_name(edge.src->node)); + debug_print(") in %s ...\n", get_abstraction_name_safe(edge.src->node)); } else goto next_potential_param; @@ -551,7 +550,7 @@ static void handle_bb(Context* ctx, const Node* old) { //deconstruct_qualified_type(&alloca_type_t); if (kv_type != source->type && !is_reinterpret_cast_legal(kv_type, alloca_type_t)) { log_node(DEBUG, ptr); - debug_print(" has a known value in %s, but it's type ", get_abstraction_name(edge.src->node)); + debug_print(" has a known value in %s, but it's type ", get_abstraction_name_safe(edge.src->node)); log_node(DEBUG, kv_type); debug_print(" cannot be reinterpreted into the alloca type "); log_node(DEBUG, source->type); @@ -583,9 +582,7 @@ static void handle_bb(Context* ctx, const Node* old) { } Node* fn = (Node*) rewrite_node(&ctx->rewriter, ctx->cfg->entry->node); - String s = format_string_interned(a, "%s_", get_abstraction_name(old)); - //String s = get_abstraction_name(old); - Node* new_bb = basic_block(a, fn, params, s); + Node* new_bb = basic_block(a, fn, params, get_abstraction_name_unsafe(old)); register_processed(&ctx->rewriter, old, new_bb); new_bb->payload.basic_block.body = finish_body(bb, nbody); From a129705b81c38abc25bf4a79c27edd5fd21001dc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 6 May 2024 10:27:04 +0200 Subject: [PATCH 244/693] fix structure recovery code --- src/frontends/llvm/l2s.c | 2 ++ src/frontends/llvm/l2s_instr.c | 4 +++- src/frontends/llvm/l2s_postprocess.c | 12 ++++++++++-- src/frontends/llvm/l2s_private.h | 1 + 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index bb480e19e..e226c14d9 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -260,6 +260,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .scopes = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), + .wrappers_map = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), .annotations_arena = new_arena(), .src = src, .dst = dirty, @@ -294,6 +295,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* destroy_dict(p.map); destroy_dict(p.annotations); destroy_dict(p.scopes); + destroy_dict(p.wrappers_map); destroy_arena(p.annotations_arena); LLVMContextDispose(context); diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index c84fbfe11..bcdc90cb3 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -64,7 +64,8 @@ static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_ .dst = dst, }; append_list(JumpTodo, fn_ctx->jumps_todo, todo); - convert_basic_block(p, fn_ctx, dst); + const Node* dst2 = convert_basic_block(p, fn_ctx, dst); + insert_dict(const Node*, const Node*, p->wrappers_map, wrapper_bb, dst2); return jump_helper(a, wrapper_bb, empty(a)); } @@ -131,6 +132,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, insert_dict(const Node*, Nodes, p->scopes, fn_or_bb, str); debugv_print("Found a debug location for "); log_node(DEBUGV, fn_or_bb); + debugv_print(" "); for (size_t i = 0; i < str.count; i++) { log_node(DEBUGV, str.nodes[i]); debugv_print(" -> "); diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index d2e377971..0d71c7861 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -184,8 +184,14 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, if (!ctx->config->hacks.recover_structure) break; Nodes* src_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, src); + bool src_is_wrapper = find_value_dict(const Node*, const Node*, ctx->p->wrappers_map, src); + const Node** found_dst_wrapper = find_value_dict(const Node*, const Node*, ctx->p->wrappers_map, dst); + if (found_dst_wrapper) + dst = *found_dst_wrapper; Nodes* dst_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, dst); - if (!src_lexical_scope) { + if (src_is_wrapper) { + // silent + } else if (!src_lexical_scope) { warn_print("Failed to find jump source node "); log_node(WARN, src); warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); @@ -206,7 +212,9 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); Nodes* dom_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, dom->node); if (!dom_lexical_scope) { - warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name(dom->node)); + warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); + dom = dom->idom; + continue; } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { diff --git a/src/frontends/llvm/l2s_private.h b/src/frontends/llvm/l2s_private.h index 24f2ab694..8078cd60b 100644 --- a/src/frontends/llvm/l2s_private.h +++ b/src/frontends/llvm/l2s_private.h @@ -16,6 +16,7 @@ typedef struct { struct Dict* map; struct Dict* annotations; struct Dict* scopes; + struct Dict* wrappers_map; Arena* annotations_arena; LLVMModuleRef src; Module* dst; From a2f656a502f91b827c6aab6de01e509405a5c464 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 7 May 2024 11:36:54 +0200 Subject: [PATCH 245/693] reorganise fold.c --- src/shady/fold.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/shady/fold.c b/src/shady/fold.c index f8dc1ae9c..9ab08dbc0 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -27,7 +27,10 @@ static bool is_one(const Node* node) { return false; } -static const Node* fold_prim_op(IrArena* arena, const Node* node) { +#define APPLY_FOLD(F) { const Node* applied_fold = F(node); if (applied_fold) return applied_fold; } + +static inline const Node* fold_constant_math(const Node* node) { + IrArena* arena = node->arena; PrimOp payload = node->payload.prim_op; LARRAY(const FloatLiteral*, float_literals, payload.operands.count); @@ -117,6 +120,12 @@ break; } } + return NULL; +} + +static inline const Node* fold_simplify_math(const Node* node) { + IrArena* arena = node->arena; + PrimOp payload = node->payload.prim_op; switch (payload.op) { case add_op: { // If either operand is zero, destroy the add @@ -131,7 +140,7 @@ break; return quote_single(arena, payload.operands.nodes[0]); // if first operand is zero, invert the second one if (is_zero(payload.operands.nodes[0])) - return prim_op(arena, (PrimOp) { .op = neg_op, .operands = singleton(payload.operands.nodes[1]), .type_arguments = empty(arena) }); + return prim_op(arena, (PrimOp) {.op = neg_op, .operands = singleton(payload.operands.nodes[1]), .type_arguments = empty(arena)}); break; } case mul_op: { @@ -151,6 +160,18 @@ break; return quote_single(arena, payload.operands.nodes[0]); break; } + default: break; + } + + return NULL; +} + +static const Node* fold_prim_op(IrArena* arena, const Node* node) { + APPLY_FOLD(fold_constant_math) + APPLY_FOLD(fold_simplify_math) + + PrimOp payload = node->payload.prim_op; + switch (payload.op) { case subgroup_broadcast_first_op: { const Node* value = first(payload.operands); if (is_qualified_type_uniform(value->type)) From 6977e909bafe979bef3a971cc2c67a02812e35f6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 8 May 2024 13:36:18 +0200 Subject: [PATCH 246/693] added folding opt to simplify pointers --- src/shady/fold.c | 85 +++++++++++++++++++++++ test/reconvergence_heuristics/loops3.slim | 0 2 files changed, 85 insertions(+) create mode 100644 test/reconvergence_heuristics/loops3.slim diff --git a/src/shady/fold.c b/src/shady/fold.c index 9ab08dbc0..bac3d3a26 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -6,6 +6,8 @@ #include "portability.h" #include "rewrite.h" +#include "shady/transform/ir_gen_helpers.h" + #include #include @@ -166,12 +168,95 @@ static inline const Node* fold_simplify_math(const Node* node) { return NULL; } +static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { + const Node* original_ptr = ptr; + IrArena* a = ptr->arena; + const Type* t = ptr->type; + bool u = deconstruct_qualified_type(&t); + assert(t->tag == PtrType_TAG); + const Type* desired_pointee_type = t->payload.ptr_type.pointed_type; + // const Node* last_known_good = node; + + int distance = 0; + bool specialize_generic = false; + while (ptr->tag == Variablez_TAG) { + const Node* def = get_var_def(ptr->payload.varz); + if (def->tag != PrimOp_TAG) + break; + PrimOp instruction = def->payload.prim_op; + switch (instruction.op) { + case reinterpret_op: { + distance++; + ptr = first(instruction.operands); + continue; + } + case convert_op: { + // only conversions to generic pointers are acceptable + if (first(instruction.type_arguments)->tag != PtrType_TAG) + break; + assert(!specialize_generic && "something should not be converted to generic twice!"); + specialize_generic = true; + ptr = first(instruction.operands); + continue; + } + default: break; + } + break; + } + + // if there was more than one of those pointless casts... + if (distance > 1 || specialize_generic) { + const Type* new_src_ptr_type = ptr->type; + deconstruct_qualified_type(&new_src_ptr_type); + if (new_src_ptr_type->payload.ptr_type.pointed_type != desired_pointee_type) { + PtrType payload = new_src_ptr_type->payload.ptr_type; + payload.pointed_type = desired_pointee_type; + ptr = gen_reinterpret_cast(bb, ptr_type(a, payload), ptr); + } + return ptr; + } + return original_ptr; +} + +static void inline simplify_ptr_operand(IrArena* a, BodyBuilder* bb, PrimOp* payload, bool* success, int i) { + const Node* old_op = payload->operands.nodes[i]; + const Node* new_op = resolve_ptr_source(bb, old_op); + if (old_op != new_op) { + payload->operands = change_node_at_index(a, payload->operands, i, new_op); + *success = true; + } +} + +static inline const Node* fold_simplify_ptr_operand(const Node* node) { + IrArena* arena = node->arena; + PrimOp payload = node->payload.prim_op; + BodyBuilder* bb = begin_body(arena); + bool rebuild = false; + switch (payload.op) { + case store_op: + case load_op: { + simplify_ptr_operand(arena, bb, &payload, &rebuild, 0); + break; + } + default: break; + } + + if (rebuild) { + return bind_last_instruction_and_wrap_in_block(bb, prim_op(arena, payload)); + } + + cancel_body(bb); + return NULL; +} + static const Node* fold_prim_op(IrArena* arena, const Node* node) { APPLY_FOLD(fold_constant_math) APPLY_FOLD(fold_simplify_math) + APPLY_FOLD(fold_simplify_ptr_operand) PrimOp payload = node->payload.prim_op; switch (payload.op) { + case subgroup_assume_uniform_op: case subgroup_broadcast_first_op: { const Node* value = first(payload.operands); if (is_qualified_type_uniform(value->type)) diff --git a/test/reconvergence_heuristics/loops3.slim b/test/reconvergence_heuristics/loops3.slim new file mode 100644 index 000000000..e69de29bb From c1c3bcf87226aaefd2fda8fa7389584092ac3157 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 8 May 2024 13:36:44 +0200 Subject: [PATCH 247/693] bind: lower LetMut with proper scoping --- src/shady/passes/bind.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index cbdf9c386..4702069f4 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -118,13 +118,11 @@ static const Node* get_node_address(Context* ctx, const Node* node) { return got; } -static const Node* desugar_let_mut(Context* ctx, const Node* node) { +static const Node* desugar_let_mut(Context* ctx, BodyBuilder* bb, const Node* node) { assert(node->tag == LetMut_TAG); IrArena* a = ctx->rewriter.dst_arena; const Node* ninstruction = rewrite_node(&ctx->rewriter, node->payload.let_mut.instruction); - BodyBuilder* bb = begin_body(a); - Nodes old_params = node->payload.let_mut.variables; Nodes initial_values = bind_instruction_outputs_count(bb, ninstruction, old_params.count, NULL); for (size_t i = 0; i < old_params.count; i++) { @@ -150,7 +148,7 @@ static const Node* desugar_let_mut(Context* ctx, const Node* node) { } Nodes e = empty(a); - return yield_values_and_wrap_in_block_explicit_return_types(bb, empty(a), &e); + return prim_op_helper(a, quote_op, empty(a), empty(a)); } static const Node* rewrite_decl(Context* ctx, const Node* decl) { @@ -278,12 +276,19 @@ static const Node* bind_node(Context* ctx, const Node* node) { return new_bb; } case Let_TAG: { - const Node* ninstr = rewrite_node(r, get_let_instruction(node)); + const Node* oinstruction = get_let_instruction(node); + const Node* ninstr; + BodyBuilder* bb = begin_body(a); + if (oinstruction->tag == LetMut_TAG) { + ninstr = desugar_let_mut(ctx, bb, oinstruction); + } else { + ninstr = rewrite_node(r, oinstruction); + } Nodes ovars = node->payload.let.variables; Nodes nvars = recreate_vars(a, ovars, ninstr); for (size_t i = 0; i < nvars.count; i++) add_binding(ctx, false, nvars.nodes[i]->payload.varz.name, nvars.nodes[i]); - return let(a, ninstr, nvars, rewrite_node(r, get_let_tail(node))); + return finish_body(bb, let(a, ninstr, nvars, rewrite_node(r, get_let_tail(node)))); } case Case_TAG: { Nodes old_params = node->payload.case_.params; @@ -294,7 +299,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { const Node* new_body = rewrite_node(&ctx->rewriter, node->payload.case_.body); return case_(a, new_params, new_body); } - case LetMut_TAG: return desugar_let_mut(ctx, node); + case LetMut_TAG: assert(false); case Return_TAG: { assert(ctx->current_function); return fn_ret(a, (Return) { From 25d5b93c63eee621d5dd87872afc328177b56558 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 8 May 2024 13:37:34 +0200 Subject: [PATCH 248/693] move block folding to cleanup --- src/shady/passes/cleanup.c | 77 +++++++++++++++++++++++++++++++++++--- src/shady/rewrite.c | 70 +++++++++------------------------- 2 files changed, 89 insertions(+), 58 deletions(-) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 82a7b8c36..4877368e3 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -5,11 +5,12 @@ #include "../rewrite.h" #include "../analysis/uses.h" +#include "../ir_private.h" typedef struct { Rewriter rewriter; const UsesMap* map; - bool todo; + bool* todo; } Context; static size_t count_calls(const UsesMap* map, const Node* bb) { @@ -28,7 +29,53 @@ static size_t count_calls(const UsesMap* map, const Node* bb) { return count; } +void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr); + +// eliminates blocks by "lifting" their contents out and replacing yield with the tail of the outer let +// In other words, we turn these patterns: +// +// let block { +// let I in case(x) => +// let J in case(y) => +// let K in case(z) => +// ... +// yield (x, y, z) } +// in case(a, b, c) => R +// +// into these: +// +// let I in case(x) => +// let J in case(y) => +// let K in case(z) => +// ... +// R[a->x, b->y, c->z] +Nodes flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* bb) { + assert(instruction->tag == Block_TAG); + // follow the terminator of the block until we hit a yield() + const Node* const lam = instruction->payload.block.inside; + assert(is_case(lam)); + const Node* terminator = get_abstraction_body(lam); + while (true) { + switch (is_terminator(terminator)) { + case NotATerminator: assert(false); + case Terminator_Let_TAG: { + bind_variables2(bb, terminator->payload.let.variables, terminator->payload.let.instruction); + terminator = get_abstraction_body(terminator->payload.let.tail); + continue; + } + case Terminator_Yield_TAG: { + return terminator->payload.yield.args; + } + // if we see anything else, give up + default: { + assert(false && "invalid block"); + } + } + } +} + const Node* process(Context* ctx, const Node* old) { + IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; if (old->tag == Function_TAG || old->tag == Constant_TAG) { Context c = *ctx; @@ -62,10 +109,29 @@ const Node* process(Context* ctx, const Node* old) { debugvv_print("Cleanup: found an unused instruction: "); log_node(DEBUGVV, payload.instruction); debugvv_print("\n"); - ctx->todo = true; + *ctx->todo = true; return rewrite_node(&ctx->rewriter, get_abstraction_body(payload.tail)); } - break; + + BodyBuilder* bb = begin_body(a); + const Node* instruction = rewrite_node(r, old->payload.let.instruction); + // optimization: fold blocks + if (instruction->tag == Block_TAG) { + *ctx->todo = true; + instruction = quote_helper(a, flatten_block(a, instruction, bb)); + } + Nodes ovars = old->payload.let.variables; + // optimization: eliminate unecessary quotes by rewriting variables into their values directly + if (instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { + *ctx->todo = true; + register_processed_list(r, ovars, instruction->payload.prim_op.operands); + return finish_body(bb, get_abstraction_body(rewrite_node(r, old->payload.let.tail))); + } + // rewrite variables now + Nodes nvars = recreate_vars(a, ovars, instruction); + register_processed_list(r, ovars, nvars); + const Node* nlet = let(a, instruction, nvars, rewrite_node(r, old->payload.let.tail)); + return finish_body(bb, nlet); } case BasicBlock_TAG: { size_t uses = count_calls(ctx->map, old); @@ -99,11 +165,12 @@ bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { IrArena* a = get_module_arena(src); *m = new_module(a, get_module_name(*m)); - Context ctx = { .todo = false }; + bool todo = false; + Context ctx = { .todo = &todo }; ctx.rewriter = create_rewriter(src, *m, (RewriteNodeFn) process), rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - return ctx.todo; + return todo; } Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 4f5f9ec0b..99f8d2e2b 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -333,49 +333,6 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr); -// eliminates blocks by "lifting" their contents out and replacing yield with the tail of the outer let -// In other words, we turn these patterns: -// -// let block { -// let I in case(x) => -// let J in case(y) => -// let K in case(z) => -// ... -// yield (x, y, z) } -// in case(a, b, c) => R -// -// into these: -// -// let I in case(x) => -// let J in case(y) => -// let K in case(z) => -// ... -// R[a->x, b->y, c->z] -Nodes flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* bb) { - assert(instruction->tag == Block_TAG); - // follow the terminator of the block until we hit a yield() - const Node* const lam = instruction->payload.block.inside; - assert(is_case(lam)); - const Node* terminator = get_abstraction_body(lam); - while (true) { - switch (is_terminator(terminator)) { - case NotATerminator: assert(false); - case Terminator_Let_TAG: { - bind_variables2(bb, terminator->payload.let.variables, terminator->payload.let.instruction); - terminator = get_abstraction_body(terminator->payload.let.tail); - continue; - } - case Terminator_Yield_TAG: { - return terminator->payload.yield.args; - } - // if we see anything else, give up - default: { - assert(false && "invalid block"); - } - } - } -} - const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { if (node == NULL) return NULL; @@ -395,25 +352,32 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { recreate_decl_body_identity(rewriter, node, new); return new; } - case Param_TAG: error("params should be rewritten by the abstraction rewrite logic"); - case Variablez_TAG: error("variables should be rewritten by the binding let"); + case Param_TAG: + log_string(ERROR, "Can't rewrite: "); + log_node(ERROR, node); + log_string(ERROR, ", params should be rewritten by the abstraction rewrite logic"); + error_die(); + case Variablez_TAG: + log_string(ERROR, "Can't rewrite: "); + log_node(ERROR, node); + log_string(ERROR, ", variables should be rewritten by the binding let"); + error_die(); case Let_TAG: { BodyBuilder* bb = begin_body(arena); const Node* instruction = rewrite_op_helper(rewriter, NcInstruction, "instruction", node->payload.let.instruction); // optimization: fold blocks - if (instruction->tag == Block_TAG) { - instruction = quote_helper(arena, flatten_block(arena, instruction, bb)); - } + // if (instruction->tag == Block_TAG) { + // instruction = quote_helper(arena, flatten_block(arena, instruction, bb)); + // } Nodes ovars = node->payload.let.variables; // optimization: eliminate unecessary quotes by rewriting variables into their values directly - if (instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { - register_processed_list(rewriter, ovars, instruction->payload.prim_op.operands); - return finish_body(bb, get_abstraction_body(rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail))); - } + // if (instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { + // register_processed_list(rewriter, ovars, instruction->payload.prim_op.operands); + // return finish_body(bb, get_abstraction_body(rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail))); + // } // rewrite variables now Nodes nvars = recreate_vars(arena, ovars, instruction); register_processed_list(rewriter, ovars, nvars); - // bind_variables2(bb, nvars, instruction); const Node* nlet = let(arena, instruction, nvars, rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail)); return finish_body(bb, nlet); } From 0f62c3dc0e03a6cfa43ff29f2568c0b356d05757 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 8 May 2024 13:38:40 +0200 Subject: [PATCH 249/693] lower_alloca: get scoping correct --- src/shady/passes/lower_alloca.c | 76 +++++++++++++++++---------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index c1c462354..d75984803 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -84,45 +84,48 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Function_TAG: { Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); + if (!node->payload.fun.body) + return fun; + Context ctx2 = *ctx; ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; - ctx2.prepared_offsets = new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); + if (ctx2.disable_lowering) { + fun->payload.fun.body = rewrite_node(&ctx2.rewriter, node->payload.fun.body); + return fun; + } BodyBuilder* bb = begin_body(a); - if (!ctx2.disable_lowering) { - ctx2.entry_stack_offset = NULL; - ctx2.entry_base_stack_ptr = gen_primop_ce(bb, get_stack_base_op, 0, NULL); - - Node* nom_t = nominal_type(m, empty(a), format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); - VContext vctx = { - .visitor = { - .visit_node_fn = (VisitNodeFn) search_operand_for_alloca, - }, - .context = &ctx2, - .bb = bb, - .nom_t = nom_t, - .num_slots = 0, - .members = new_list(const Node*), - .prepared_offsets = ctx2.prepared_offsets, - }; - if (node->payload.fun.body) { - search_operand_for_alloca(&vctx, node->payload.fun.body); - visit_function_rpo(&vctx.visitor, node); - } - vctx.nom_t->payload.nom_type.body = record_type(a, (RecordType) { - .members = nodes(a, vctx.num_slots, read_list(const Node*, vctx.members)), - .names = strings(a, 0, NULL), - .special = 0 - }); - destroy_list(vctx.members); - ctx2.num_slots = vctx.num_slots; - ctx2.frame_size = gen_primop_e(bb, size_of_op, singleton(type_decl_ref_helper(a, vctx.nom_t)), empty(a)); - ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); - } - if (node->payload.fun.body) - fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); - else - cancel_body(bb); + ctx2.prepared_offsets = new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); + ctx2.entry_base_stack_ptr = gen_primop_ce(bb, get_stack_base_op, 0, NULL); + String tmp_name = "stack_ptr_before_alloca"; + ctx2.entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_size_op } ), (String []) { tmp_name })); + + Node* nom_t = nominal_type(m, empty(a), format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); + VContext vctx = { + .visitor = { + .visit_node_fn = (VisitNodeFn) search_operand_for_alloca, + }, + .context = &ctx2, + .bb = bb, + .nom_t = nom_t, + .num_slots = 0, + .members = new_list(const Node*), + .prepared_offsets = ctx2.prepared_offsets, + }; + search_operand_for_alloca(&vctx, node->payload.fun.body); + visit_function_rpo(&vctx.visitor, node); + + vctx.nom_t->payload.nom_type.body = record_type(a, (RecordType) { + .members = nodes(a, vctx.num_slots, read_list(const Node*, vctx.members)), + .names = strings(a, 0, NULL), + .special = 0 + }); + destroy_list(vctx.members); + ctx2.num_slots = vctx.num_slots; + ctx2.frame_size = gen_primop_e(bb, size_of_op, singleton(type_decl_ref_helper(a, vctx.nom_t)), empty(a)); + ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); + + fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); destroy_dict(ctx2.prepared_offsets); return fun; @@ -141,8 +144,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); if (!ctx->entry_stack_offset) { //String tmp_name = format_string_arena(a->arena, "stack_ptr_before_alloca_%s", get_abstraction_name(fun)); - String tmp_name = "stack_ptr_before_alloca"; - ctx->entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_size_op } ), (String []) { tmp_name })); + assert(false); } //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); From ce38e6193a4bdbebf13ecdbd6b3e517564c35795 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 8 May 2024 13:39:29 +0200 Subject: [PATCH 250/693] overhaul free variables again --- src/shady/analysis/free_variables.c | 220 +++++++++++++------- src/shady/analysis/free_variables.h | 12 +- src/shady/analysis/verify.c | 2 +- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/reconvergence_heuristics.c | 26 +-- test/reconvergence_heuristics/loops1.slim | 24 +++ test/reconvergence_heuristics/loops3.slim | 0 7 files changed, 193 insertions(+), 93 deletions(-) delete mode 100644 test/reconvergence_heuristics/loops3.slim diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index fea937806..d57bfe840 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -18,8 +18,69 @@ typedef struct { Visitor visitor; struct Dict* map; CFNodeVariables* current_scope; + struct Dict* bound; + struct Dict* live; + CfgVariablesAnalysisFlags flags; } Context; +static void copy_set(struct Dict* dst, struct Dict* src) { + size_t j = 0; + const Node* item; + while (dict_iter(src, &j, &item, NULL)) { + insert_set_get_result(const Node*, dst, item); + } +} + +void dump_set(struct Dict* set) { + bool prev = false; + size_t i = 0; + const Node* bound_var; + while (dict_iter(set, &i, &bound_var, NULL)) { + if (prev) { + debugvv_print(", "); + } + log_node(DEBUGVV, bound_var); + prev = true; + } +} + +static void dump_free_variables(Context* ctx, CFNode* cfnode, int depth) { + const Node* abs = cfnode->node; + String abs_name = get_abstraction_name_unsafe(abs); + for (int i = 0; i < depth; i++) + debugvv_print(" "); + if (abs_name) + debugvv_print("%s: ", abs_name); + else + debugvv_print("%%%d: ", abs->id); + debugvv_print("."); + + if (true) { + if(ctx->current_scope->free_set) { + debugvv_print(" Free: ["); + dump_set(ctx->current_scope->free_set); + debugvv_print("]"); + } + if(ctx->current_scope->bound_by_dominators_set) { + debugvv_print(" BoundDom: ["); + dump_set(ctx->current_scope->bound_by_dominators_set); + debugvv_print("]"); + } + if(ctx->bound) { + debugvv_print(" Bound: ["); + dump_set(ctx->bound); + debugvv_print("]"); + } + //if(ctx->live) { + // debugvv_print(" Live: ["); + // dump_set(ctx->live); + // debugvv_print("]"); + //} + } + + debugvv_print("\n"); +} + static void search_op_for_free_variables(Context* visitor, NodeClass class, String op_name, const Node* node) { assert(node); switch (node->tag) { @@ -27,16 +88,16 @@ static void search_op_for_free_variables(Context* visitor, NodeClass class, Stri Nodes variables = node->payload.let.variables; for (size_t j = 0; j < variables.count; j++) { const Node* var = variables.nodes[j]; - bool r = insert_set_get_result(const Node*, visitor->current_scope->bound_set, var); + bool r = insert_set_get_result(const Node*, visitor->bound, var); assert(r); } break; } case Variablez_TAG: case Param_TAG: { - const Node** found = find_key_dict(const Node*, visitor->current_scope->bound_set, node); - if (!found) - insert_set_get_result(const Node*, visitor->current_scope->free_set, node); + //const Node** found = find_key_dict(const Node*, visitor->bound, node); + //if (!found) + insert_set_get_result(const Node*, visitor->live, node); return; } case Function_TAG: @@ -51,118 +112,129 @@ static CFNodeVariables* create_node_variables(CFNode* cfnode) { CFNodeVariables* v = calloc(sizeof(CFNodeVariables), 1); *v = (CFNodeVariables) { .node = cfnode, - .free_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node) }; return v; } -static void dump_free_variables(Context* ctx, CFNode* cfnode, int depth) { - const Node* abs = cfnode->node; - String abs_name = get_abstraction_name_unsafe(abs); - for (int i = 0; i < depth; i++) - debugvv_print(" "); - if (abs_name) - debugvv_print("%s: ", abs_name); - else - debugvv_print("%%%d: ", abs->id); - - if (true) { - bool prev = false; - size_t i = 0; - const Node* free_var; - while (dict_iter(ctx->current_scope->free_set, &i, &free_var, NULL)) { - if (prev) { - debugvv_print(", "); - } - log_node(DEBUGVV, free_var); - prev = true; - } - } - - if (true) { - debugvv_print(". Binds: "); - bool prev = false; - size_t i = 0; - const Node* bound_var; - while (dict_iter(ctx->current_scope->bound_set, &i, &bound_var, NULL)) { - if (prev) { - debugvv_print(", "); - } - log_node(DEBUGVV, bound_var); - prev = true; - } +static Context visit_domtree(Context* parent_context, CFNode* cfnode, int depth) { + Context context = *parent_context; + + context.current_scope = create_node_variables(cfnode); + //if (depth > 0) + // context.bound = clone_dict(parent_context->bound); + //else + context.bound = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); + context.live = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); + + insert_dict(CFNode*, CFNodeVariables*, context.map, cfnode, context.current_scope); + if (context.flags & CfgVariablesAnalysisFlagDomBoundSet) { + if (depth == 0) + context.current_scope->bound_by_dominators_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); + else + context.current_scope->bound_by_dominators_set = clone_dict(parent_context->bound); } - - debugvv_print("\n"); -} - -static CFNodeVariables* visit_domtree(Context* ctx, CFNode* cfnode, int depth, CFNodeVariables* parent) { - Context new_context = *ctx; - ctx = &new_context; - - ctx->current_scope = create_node_variables(cfnode); - ctx->current_scope->bound_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - insert_dict(CFNode*, CFNodeVariables*, ctx->map, cfnode, ctx->current_scope); + if (context.flags & CfgVariablesAnalysisFlagFreeSet) + context.current_scope->free_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); const Node* abs = cfnode->node; // Bind parameters Nodes params = get_abstraction_params(abs); for (size_t j = 0; j < params.count; j++) { const Node* param = params.nodes[j]; - bool r = insert_set_get_result(const Node*, ctx->current_scope->bound_set, param); + bool r = insert_set_get_result(const Node*, context.bound, param); assert(r); } const Node* body = get_abstraction_body(abs); if (body) - visit_op(&ctx->visitor, NcTerminator, "body", body); + visit_op(&context.visitor, NcTerminator, "body", body); - if (parent) { + if (context.flags & CfgVariablesAnalysisFlagFreeSet) { size_t j = 0; - const Node* bound; - while (dict_iter(parent->bound_set, &j, &bound, NULL)) { - insert_set_get_result(const Node*, ctx->current_scope->bound_set, bound); + const Node* pfv; + while (dict_iter(context.live, &j, &pfv, NULL)) { + const Node** found = find_key_dict(const Node*, context.bound, pfv); + if (found) + continue; + insert_set_get_result(const Node*, context.current_scope->free_set, pfv); } } + struct Dict* stuff_bound_here = NULL; + // if we want to compute free variables, we need to keep arround a copy of what's bound in this abstraction + // and check the free variables against that rather than the transitively bound set we're computing right after + if (context.flags & CfgVariablesAnalysisFlagFreeSet) + stuff_bound_here = clone_dict(context.bound); + + if (depth > 0) + copy_set(context.bound, parent_context->bound); + for (size_t i = 0; i < entries_count_list(cfnode->dominates); i++) { CFNode* child = read_list(CFNode*, cfnode->dominates)[i]; - CFNodeVariables* child_variables = visit_domtree(ctx, child, depth + 1, ctx->current_scope); - size_t j = 0; - const Node* free_var; - while (dict_iter(child_variables->free_set, &j, &free_var, NULL)) { - const Node** found = find_key_dict(const Node*, ctx->current_scope->bound_set, free_var); - if (!found) - insert_set_get_result(const Node*, ctx->current_scope->free_set, free_var); - next:; + Context child_context = visit_domtree(&context, child, depth + 1); + // what's live in children is live to us, too + copy_set(context.live, child_context.live); + destroy_dict(child_context.bound); + destroy_dict(child_context.live); + + if (context.flags & CfgVariablesAnalysisFlagFreeSet) { + size_t j = 0; + const Node* pfv; + while (dict_iter(child_context.current_scope->free_set, &j, &pfv, NULL)) { + const Node** found = find_key_dict(const Node*, stuff_bound_here, pfv); + if (found) + continue; + insert_set_get_result(const Node*, context.current_scope->free_set, pfv); + } } } - // dump_free_variables(ctx, cfnode, depth); + if (stuff_bound_here) + destroy_dict(stuff_bound_here); + + if (context.flags & CfgVariablesAnalysisFlagBoundSet) + context.current_scope->bound_set = clone_dict(context.bound); + if (context.flags & CfgVariablesAnalysisFlagLiveSet) + context.current_scope->live_set = clone_dict(context.live); - return ctx->current_scope; + //dump_free_variables(&context, cfnode, depth); + + return context; } -struct Dict* compute_cfg_variables_map(const CFG* cfg) { - Context ctx = { +struct Dict* compute_cfg_variables_map(const CFG* cfg, CfgVariablesAnalysisFlags flags) { + Context root_context = { .visitor = { .visit_op_fn = (VisitOpFn) search_op_for_free_variables, }, .map = new_dict(CFNode*, CFNodeVariables*, (HashFn) hash_ptr, (CmpFn) compare_ptrs), + .flags = flags, }; debugv_print("Computing free variables for function '%s' ...\n", get_abstraction_name(cfg->entry->node)); - visit_domtree(&ctx, cfg->entry, 0, NULL); - return ctx.map; + root_context = visit_domtree(&root_context, cfg->entry, 0); + destroy_dict(root_context.bound); + destroy_dict(root_context.live); + return root_context.map; +} + +static void destroy_variables_node(CFNodeVariables* value) { + if (value->bound_by_dominators_set) + destroy_dict(value->bound_by_dominators_set); + if (value->bound_set) + destroy_dict(value->bound_set); + if (value->live_set) + destroy_dict(value->live_set); + if (value->free_set) + destroy_dict(value->free_set); + free((void*) value); } void destroy_cfg_variables_map(struct Dict* map) { size_t i = 0; CFNodeVariables* value; while (dict_iter(map, &i, NULL, &value)) { - destroy_dict(value->bound_set); - destroy_dict(value->free_set); - free((void*) value); + destroy_variables_node(value); } destroy_dict(map); } diff --git a/src/shady/analysis/free_variables.h b/src/shady/analysis/free_variables.h index 02105b086..9e4e51d17 100644 --- a/src/shady/analysis/free_variables.h +++ b/src/shady/analysis/free_variables.h @@ -8,11 +8,21 @@ typedef struct CFNode_ CFNode; typedef struct { CFNode* node; + struct Dict* bound_by_dominators_set; struct Dict* bound_set; struct Dict* free_set; + struct Dict* live_set; } CFNodeVariables; -struct Dict* compute_cfg_variables_map(const CFG* cfg); +typedef enum { + CfgVariablesAnalysisFlagNone = 0, + CfgVariablesAnalysisFlagFreeSet = 0x1, + CfgVariablesAnalysisFlagBoundSet = 0x2, + CfgVariablesAnalysisFlagDomBoundSet = 0x4, + CfgVariablesAnalysisFlagLiveSet = 0x8 +} CfgVariablesAnalysisFlags; + +struct Dict* compute_cfg_variables_map(const CFG* cfg, CfgVariablesAnalysisFlags flags); void destroy_cfg_variables_map(struct Dict*); #endif diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 873550d08..739b377a7 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -46,7 +46,7 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { struct List* cfgs = build_cfgs(mod); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; - struct Dict* map = compute_cfg_variables_map(cfg); + struct Dict* map = compute_cfg_variables_map(cfg, CfgVariablesAnalysisFlagFreeSet); CFNodeVariables* entry_vars = *find_value_dict(CFNode*, CFNodeVariables*, map, cfg->entry); size_t j = 0; const Node* leaking; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 90d35c5fb..a500e2732 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -93,7 +93,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable // Compute the live stuff we'll need CFG* cfg_rooted_in_liftee = build_cfg(ctx->cfg->entry->node, liftee, NULL, false); CFNode* cf_node = cfg_lookup(cfg_rooted_in_liftee, liftee); - struct Dict* live_vars = compute_cfg_variables_map(cfg_rooted_in_liftee); + struct Dict* live_vars = compute_cfg_variables_map(cfg_rooted_in_liftee, CfgVariablesAnalysisFlagFreeSet); CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, live_vars, cf_node); struct List* recover_context = new_list(const Node*); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 093969554..22381a8b3 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -60,26 +60,20 @@ static void gather_exiting_nodes(LoopTree* lt, const CFNode* entry, const CFNode } } -static void find_unbound_vars(const Node* loop_header, const Node* exiting_node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { - const Node* free_post; +static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { + const Node* v; size_t i = 0; - Nodes ignore = get_abstraction_params(loop_header); - while (dict_iter(free_set, &i, &free_post, NULL)) { - const Node* bound_pre; - size_t j = 0; - while (dict_iter(bound_set, &j, &bound_pre, NULL)) { - if (bound_pre == free_post && !find_in_nodes(ignore, bound_pre)) { - goto next; - } - } + while (dict_iter(free_set, &i, &v, NULL)) { + if (find_key_dict(const Node*, bound_set, v)) + continue; log_string(DEBUGVV, "Found variable used outside it's control scope: "); - log_node(DEBUGVV, free_post); - log_string(DEBUGVV, " (original:"); + log_node(DEBUGVV, v); + log_string(DEBUGVV, " (exiting_node:"); log_node(DEBUGVV, exiting_node); log_string(DEBUGVV, " )\n"); - append_list(const Node*, leaking, free_post); + append_list(const Node*, leaking, v); next:; } @@ -149,7 +143,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { CFNode* cf_post = cfg_lookup(ctx->fwd_cfg, exiting_node->node); CFNodeVariables* post = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_post); leaking[i] = new_list(const Type*); - find_unbound_vars(node, exiting_node->node, pre->bound_set, post->free_set, leaking[i]); + find_unbound_vars(exiting_node->node, pre->bound_by_dominators_set, post->free_set, leaking[i]); size_t leaking_count = entries_count_list(leaking[i]); LARRAY(const Node*, exit_fwd_allocas_tmp, leaking_count); @@ -391,7 +385,7 @@ static const Node* process_node(Context* ctx, const Node* node) { ctx->fwd_cfg = build_cfg(ctx->current_fn, ctx->current_fn, NULL, false); ctx->rev_cfg = build_cfg(ctx->current_fn, ctx->current_fn, NULL, true); ctx->current_looptree = build_loop_tree(ctx->fwd_cfg); - ctx->live_vars = compute_cfg_variables_map(ctx->fwd_cfg); + ctx->live_vars = compute_cfg_variables_map(ctx->fwd_cfg, CfgVariablesAnalysisFlagDomBoundSet | CfgVariablesAnalysisFlagLiveSet | CfgVariablesAnalysisFlagFreeSet); const Node* new = process_abstraction(ctx, node);; diff --git a/test/reconvergence_heuristics/loops1.slim b/test/reconvergence_heuristics/loops1.slim index baeac8680..a516375f7 100644 --- a/test/reconvergence_heuristics/loops1.slim +++ b/test/reconvergence_heuristics/loops1.slim @@ -75,3 +75,27 @@ fn exitingloop_values varying i32(varying i32 n) { return (k); } } + +@Restructure +fn exitingloop_values_from_loop varying i32(varying i32 n) { + var i32 r = n + 0; + var i32 k = 0; + + jump entry(); + + cont entry() { + val r1 = r + 1; + val loop_cond = (r > 0); + branch(loop_cond, loop_body(), loop_exit()); + + cont loop_exit() { + return (r1); + } + } + + cont loop_body() { + k = k + r; + r = r - 1; + jump entry(); + } +} diff --git a/test/reconvergence_heuristics/loops3.slim b/test/reconvergence_heuristics/loops3.slim deleted file mode 100644 index e69de29bb..000000000 From 7cf764a6731cc12db0c913145a0559abdadee6c5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 13 May 2024 13:24:18 +0200 Subject: [PATCH 251/693] fix lower_alloca emitting wrong stack size --- src/shady/passes/lower_alloca.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index d75984803..89e0b9633 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -46,9 +46,11 @@ typedef struct { } StackSlot; static void search_operand_for_alloca(VContext* vctx, const Node* node) { + if (node->tag == Variablez_TAG) + return; + IrArena* a = vctx->context->rewriter.dst_arena; AddressSpace as; - if (node->tag == PrimOp_TAG) { switch (node->payload.prim_op.op) { case alloca_op: as = AsPrivate; break; From 1a061d9109e0dcac3c43eef8a200ebdf0486eb63 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 14 May 2024 10:07:44 +0200 Subject: [PATCH 252/693] runtime/vulkan: add SPV file override --- src/runtime/vulkan/vk_runtime_program.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index a18960fdd..55d57cd1f 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -396,6 +396,12 @@ static bool compile_specialized_program(VkrSpecProgram* spec) { free((void*) file_name); } + String override_file = getenv("SHADY_OVERRIDE_SPV"); + if (override_file) { + read_file(override_file, &spec->spirv_size, &spec->spirv_bytes); + return true; + } + return true; } From 3952218db71a3094b4be9126dc37a67872d36757 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 14 May 2024 10:08:10 +0200 Subject: [PATCH 253/693] fix driver tests --- test/driver/test_elect_first.slim | 5 ++++- test/driver/test_scalarisation_loop.slim | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/driver/test_elect_first.slim b/test/driver/test_elect_first.slim index b07873218..cd1ee0df9 100644 --- a/test/driver/test_elect_first.slim +++ b/test/driver/test_elect_first.slim @@ -1,4 +1,7 @@ -@EntryPoint("compute") @WorkgroupSize(64, 1, 1) fn main() { +@Internal @Builtin("SubgroupLocalInvocationId") +var input u32 subgroup_local_id; + +@EntryPoint("Compute") @WorkgroupSize(64, 1, 1) fn main() { val tid = subgroup_local_id; val x = tid / u32 4; debug_printf("tid = %d x = %d\n", tid, x); diff --git a/test/driver/test_scalarisation_loop.slim b/test/driver/test_scalarisation_loop.slim index dc0ebf364..999e7ac28 100644 --- a/test/driver/test_scalarisation_loop.slim +++ b/test/driver/test_scalarisation_loop.slim @@ -16,6 +16,6 @@ var input u32 subgroup_local_id; break(); } } - debug_printf("Done SP=%d.\n", get_stack_pointer()); + debug_printf("Done SP=%d.\n", get_stack_size()); return (); } From ede983877e97c5e8947bf17793be8bc9242bfdee Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 14 May 2024 14:06:50 +0200 Subject: [PATCH 254/693] fix: try to call clang using versionned executable --- src/driver/vcc.c | 9 ++++++--- src/frontends/llvm/l2s.c | 8 ++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/driver/vcc.c b/src/driver/vcc.c index f74937117..5e4294891 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -47,6 +47,8 @@ static void cli_parse_vcc_args(VccOptions* options, int* pargc, char** argv) { uint32_t hash_murmur(const void* data, size_t size); +int vcc_get_linked_major_llvm_version(); + int main(int argc, char** argv) { platform_specific_terminal_init_extras(); @@ -71,14 +73,15 @@ int main(int argc, char** argv) { ArenaConfig aconfig = default_arena_config(&args.config.target); IrArena* arena = new_ir_arena(aconfig); - int clang_retval = system("clang --version"); + String clangname = format_string_interned(arena, "clang-%d", vcc_get_linked_major_llvm_version()); + int clang_retval = system(format_string_interned(arena, "%s --version", clangname)); if (clang_retval != 0) - error("clang not present in path or otherwise broken (retval=%d)", clang_retval); + error("%s not present in path or otherwise broken (retval=%d)", clangname, clang_retval); size_t num_source_files = entries_count_list(args.input_filenames); Growy* g = new_growy(); - growy_append_string(g, "clang"); + growy_append_string(g, clangname); char* self_path = get_executable_location(); char* working_dir = strip_path(self_path); if (!vcc_options.include_path) { diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index e226c14d9..c694bedad 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -36,6 +36,14 @@ static bool cmp_opaque_ptr(OpaqueRef* a, OpaqueRef* b) { KeyHash hash_node(Node**); bool compare_node(Node**, Node**); +#ifdef LLVM_VERSION_MAJOR +int vcc_get_linked_major_llvm_version() { + return LLVM_VERSION_MAJOR; +} +#else +#error "wat" +#endif + static const Node* write_bb_tail(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef bb, LLVMValueRef first_instr) { BodyBuilder* b = begin_body(fn_or_bb->arena); LLVMValueRef instr; From 809c090e716aec6823a237eae12e8d61c7da6275 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 14 May 2024 14:07:04 +0200 Subject: [PATCH 255/693] fix compilation on ubuntu 24.04 lts --- src/runtime/vulkan/vk_runtime_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index 6f1584b80..91d499439 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -323,7 +323,7 @@ bool probe_vkr_devices(VkrBackend* runtime) { .get_name = (String(*)(Device*)) get_vkr_device_name, .allocate_buffer = (Buffer*(*)(Device*, size_t)) vkr_allocate_buffer_device, .import_host_memory_as_buffer = (Buffer*(*)(Device*, void*, size_t)) vkr_import_buffer_host, - .launch_kernel = (Command*(*)(Device*, Program*, String, int, int, int, int, void**)) vkr_launch_kernel, + .launch_kernel = (Command*(*)(Device*, Program*, String, int, int, int, int, void**, ExtraKernelOptions*)) vkr_launch_kernel, .can_import_host_memory = (bool(*)(Device*)) vkr_can_import_host_memory, }; append_list(Device*, runtime->base.runtime->devices, device); From 93d824bc7728d96a6860d3e1c9234268dd99112b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 16 May 2024 16:10:12 +0200 Subject: [PATCH 256/693] fix broken pointer simplification when src is not a ptr --- src/shady/fold.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/shady/fold.c b/src/shady/fold.c index bac3d3a26..39bba12a7 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -179,6 +179,7 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { int distance = 0; bool specialize_generic = false; + AddressSpace src_as = t->payload.ptr_type.address_space; while (ptr->tag == Variablez_TAG) { const Node* def = get_var_def(ptr->payload.varz); if (def->tag != PrimOp_TAG) @@ -197,6 +198,7 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { assert(!specialize_generic && "something should not be converted to generic twice!"); specialize_generic = true; ptr = first(instruction.operands); + src_as = get_unqualified_type(ptr->type)->payload.ptr_type.address_space; continue; } default: break; @@ -208,9 +210,9 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { if (distance > 1 || specialize_generic) { const Type* new_src_ptr_type = ptr->type; deconstruct_qualified_type(&new_src_ptr_type); - if (new_src_ptr_type->payload.ptr_type.pointed_type != desired_pointee_type) { - PtrType payload = new_src_ptr_type->payload.ptr_type; - payload.pointed_type = desired_pointee_type; + if (new_src_ptr_type->tag != PtrType_TAG || new_src_ptr_type->payload.ptr_type.pointed_type != desired_pointee_type) { + PtrType payload = t->payload.ptr_type; + payload.address_space = src_as; ptr = gen_reinterpret_cast(bb, ptr_type(a, payload), ptr); } return ptr; From 8971886162a71c39ca30c76f84b799f52caa77ee Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 13:41:24 +0200 Subject: [PATCH 257/693] started work on zhady bindings --- CMakeLists.txt | 2 ++ zhady/CMakeLists.txt | 12 ++++++++++++ zhady/shady.i | 9 +++++++++ 3 files changed, 23 insertions(+) create mode 100644 zhady/CMakeLists.txt create mode 100644 zhady/shady.i diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b0e42bc4..5bb9788ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,8 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1) cmake_policy(SET CMP0118 NEW) add_subdirectory(src) +add_subdirectory(zhady) + include(CTest) if (BUILD_TESTING) add_subdirectory(test) diff --git a/zhady/CMakeLists.txt b/zhady/CMakeLists.txt new file mode 100644 index 000000000..3a696a2b7 --- /dev/null +++ b/zhady/CMakeLists.txt @@ -0,0 +1,12 @@ +find_package(SWIG) +find_package(JNI) + +if (SWIG_FOUND AND JNI_FOUND) + message("Enabling Java bindings") + + include(UseSWIG) + swig_add_library(zhady TYPE SHARED LANGUAGE java SOURCES shady.i) + set_property(TARGET zhady PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE) + #set_property(TARGET zhady PROPERTY SWIG_COMPILE_OPTIONS -includeall) + target_link_libraries(zhady PUBLIC JNI::JNI api shady common) +endif () \ No newline at end of file diff --git a/zhady/shady.i b/zhady/shady.i new file mode 100644 index 000000000..fbaa1fa50 --- /dev/null +++ b/zhady/shady.i @@ -0,0 +1,9 @@ +%include +//%apply int { _Bool }; + +%module shady +%{ +#include "shady/ir.h" +%} + +%include "shady/ir.h" \ No newline at end of file From 8c997599df9c187bfd7697bf1c36d48fbeb38071 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 13:50:48 +0200 Subject: [PATCH 258/693] fix minor header issues to please SWIG --- include/shady/ir.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index da5ac640a..17af6e8b6 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -64,6 +64,13 @@ const Node* get_declaration(const Module*, String); //////////////////////////////// IR Arena //////////////////////////////// +typedef enum { + /// Uses the MaskType + SubgroupMaskAbstract, + /// Uses a 64-bit integer + SubgroupMaskInt64 +} SubgroupMaskRepresentation; + typedef struct { bool name_bound; bool check_op_classes; @@ -78,12 +85,7 @@ typedef struct { struct { /// Selects which type the subgroup intrinsic primops use to manipulate masks - enum { - /// Uses the MaskType - SubgroupMaskAbstract, - /// Uses a 64-bit integer - SubgroupMaskInt64 - } subgroup_mask_representation; + SubgroupMaskRepresentation subgroup_mask_representation; uint32_t workgroup_size[3]; } specializations; @@ -348,6 +350,4 @@ void emit_c(CompilerConfig compiler_config, CEmitterConfig emitter_config, Modul void dump_cfg(FILE* file, Module*); void dump_loop_trees(FILE* output, Module* mod); -void free_output(char* output); - #endif From e23867f0759a2d7b90c504353123a2fd4b462024 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 13:51:04 +0200 Subject: [PATCH 259/693] compile zhady jar with cmake (!) --- zhady/CMakeLists.txt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/zhady/CMakeLists.txt b/zhady/CMakeLists.txt index 3a696a2b7..c951f39b4 100644 --- a/zhady/CMakeLists.txt +++ b/zhady/CMakeLists.txt @@ -1,12 +1,17 @@ find_package(SWIG) find_package(JNI) +find_package(Java) -if (SWIG_FOUND AND JNI_FOUND) +if (SWIG_FOUND AND JNI_FOUND AND Java_FOUND) message("Enabling Java bindings") include(UseSWIG) - swig_add_library(zhady TYPE SHARED LANGUAGE java SOURCES shady.i) - set_property(TARGET zhady PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE) - #set_property(TARGET zhady PROPERTY SWIG_COMPILE_OPTIONS -includeall) - target_link_libraries(zhady PUBLIC JNI::JNI api shady common) + swig_add_library(zhady_shared_lib TYPE SHARED LANGUAGE java SOURCES shady.i) + set_property(TARGET zhady_shared_lib PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE) + #set_property(TARGET zhady_shared_lib PROPERTY SWIG_COMPILE_OPTIONS -includeall) + target_link_libraries(zhady_shared_lib PUBLIC JNI::JNI api shady common) + + include(UseJava) + get_property(zhady_jar_sources TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES) + add_jar(zhady_jar SOURCES ${zhady_jar_sources}) endif () \ No newline at end of file From fdc4f826db17af68fcfd7236a40a2f2d830a558a Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 14:39:37 +0200 Subject: [PATCH 260/693] namespace zhady properly --- zhady/CMakeLists.txt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/zhady/CMakeLists.txt b/zhady/CMakeLists.txt index c951f39b4..5ce965b4d 100644 --- a/zhady/CMakeLists.txt +++ b/zhady/CMakeLists.txt @@ -5,13 +5,18 @@ find_package(Java) if (SWIG_FOUND AND JNI_FOUND AND Java_FOUND) message("Enabling Java bindings") + add_custom_target(zhady_dir COMMAND cmake -E ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady) + include(UseSWIG) - swig_add_library(zhady_shared_lib TYPE SHARED LANGUAGE java SOURCES shady.i) + swig_add_library(zhady_shared_lib TYPE SHARED LANGUAGE java SOURCES shady.i OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady) set_property(TARGET zhady_shared_lib PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE) - #set_property(TARGET zhady_shared_lib PROPERTY SWIG_COMPILE_OPTIONS -includeall) + set_property(TARGET zhady_shared_lib PROPERTY SWIG_COMPILE_OPTIONS -package de.unisaarland.zhady) target_link_libraries(zhady_shared_lib PUBLIC JNI::JNI api shady common) include(UseJava) - get_property(zhady_jar_sources TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES) - add_jar(zhady_jar SOURCES ${zhady_jar_sources}) + #get_property(zhady_jar_sources TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES) + #message(${zhady_jar_sources}) + file(GLOB_RECURSE zhady_jar_sources2 ${CMAKE_CURRENT_BINARY_DIR}/java_sources/**.java) + #message(${zhady_jar_sources2}) + add_jar(zhady_jar SOURCES ${zhady_jar_sources2}) endif () \ No newline at end of file From 5ae17effff43f54d43a32bab4d3036c9c9b47ed5 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 15:11:52 +0200 Subject: [PATCH 261/693] we're so cooking --- zhady/CMakeLists.txt | 10 ++++------ zhady/shady.i | 6 +++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/zhady/CMakeLists.txt b/zhady/CMakeLists.txt index 5ce965b4d..14e6492c9 100644 --- a/zhady/CMakeLists.txt +++ b/zhady/CMakeLists.txt @@ -11,12 +11,10 @@ if (SWIG_FOUND AND JNI_FOUND AND Java_FOUND) swig_add_library(zhady_shared_lib TYPE SHARED LANGUAGE java SOURCES shady.i OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady) set_property(TARGET zhady_shared_lib PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE) set_property(TARGET zhady_shared_lib PROPERTY SWIG_COMPILE_OPTIONS -package de.unisaarland.zhady) - target_link_libraries(zhady_shared_lib PUBLIC JNI::JNI api shady common) + target_link_libraries(zhady_shared_lib PUBLIC JNI::JNI api driver runtime) include(UseJava) - #get_property(zhady_jar_sources TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES) - #message(${zhady_jar_sources}) - file(GLOB_RECURSE zhady_jar_sources2 ${CMAKE_CURRENT_BINARY_DIR}/java_sources/**.java) - #message(${zhady_jar_sources2}) - add_jar(zhady_jar SOURCES ${zhady_jar_sources2}) + get_property(zhady_jar_sources TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES) + set(CMAKE_JAVA_COMPILE_FLAGS ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady/*.java) + add_jar(zhady_jar SOURCES ${zhady_jar_sources} ) endif () \ No newline at end of file diff --git a/zhady/shady.i b/zhady/shady.i index fbaa1fa50..0ae374ca4 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -4,6 +4,10 @@ %module shady %{ #include "shady/ir.h" +#include "shady/runtime.h" +#include "shady/driver.h" %} -%include "shady/ir.h" \ No newline at end of file +%include "shady/ir.h" +%include "shady/driver.h" +%include "shady/runtime.h" \ No newline at end of file From 31811fc1db03a92c46a8476ea34e5faebd51dd13 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 18:32:02 +0200 Subject: [PATCH 262/693] install zhady target --- zhady/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zhady/CMakeLists.txt b/zhady/CMakeLists.txt index 14e6492c9..adc05273a 100644 --- a/zhady/CMakeLists.txt +++ b/zhady/CMakeLists.txt @@ -16,5 +16,7 @@ if (SWIG_FOUND AND JNI_FOUND AND Java_FOUND) include(UseJava) get_property(zhady_jar_sources TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES) set(CMAKE_JAVA_COMPILE_FLAGS ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady/*.java) - add_jar(zhady_jar SOURCES ${zhady_jar_sources} ) -endif () \ No newline at end of file + add_jar(zhady_jar SOURCES ${zhady_jar_sources}) + + install(TARGETS zhady_shared_lib EXPORT shady_export_set) +endif () From 32e2e6f91f97f7ce998066eba0b5ca850246a632 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 23:16:49 +0200 Subject: [PATCH 263/693] vcc: split into library and executable --- include/vcc/driver.h | 22 ++++++ src/driver/CMakeLists.txt | 7 +- src/driver/vcc.c | 124 ++------------------------------ src/driver/vcc_lib.c | 145 ++++++++++++++++++++++++++++++++++++++ src/frontends/llvm/l2s.c | 2 +- zhady/common.i | 0 6 files changed, 180 insertions(+), 120 deletions(-) create mode 100644 include/vcc/driver.h create mode 100644 src/driver/vcc_lib.c create mode 100644 zhady/common.i diff --git a/include/vcc/driver.h b/include/vcc/driver.h new file mode 100644 index 000000000..3e1ca21e9 --- /dev/null +++ b/include/vcc/driver.h @@ -0,0 +1,22 @@ +#ifndef VCC_DRIVER_H +#define VCC_DRIVER_H + +#include "shady/driver.h" + +typedef struct { + bool delete_tmp_file; + bool only_run_clang; + const char* tmp_filename; + const char* include_path; +} VccConfig; + +void vcc_check_clang(); + +VccConfig vcc_init_config(); +void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv); +void destroy_vcc_options(VccConfig vcc_options); + +void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String input_filenames[]); +void vcc_parse_back_into_module(VccConfig* vcc_options, Module* mod); + +#endif diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index e58a9ee01..bcc4c91b2 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -19,9 +19,12 @@ target_link_libraries(slim PRIVATE driver) install(TARGETS slim EXPORT shady_export_set) if (TARGET shady_fe_llvm) + add_library(vcc_lib SHARED vcc_lib.c) + target_link_libraries(vcc_lib PUBLIC driver api) + add_executable(vcc vcc.c) - target_link_libraries(vcc PRIVATE driver api) - install(TARGETS vcc EXPORT shady_export_set) + target_link_libraries(vcc PRIVATE api vcc_lib) + install(TARGETS vcc_lib vcc EXPORT shady_export_set) if (WIN32) add_custom_command(TARGET vcc POST_BUILD diff --git a/src/driver/vcc.c b/src/driver/vcc.c index bd829d990..c3bab461a 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -1,5 +1,5 @@ #include "shady/ir.h" -#include "shady/driver.h" +#include "vcc/driver.h" #include "log.h" #include "list.h" @@ -10,51 +10,11 @@ #include #include -typedef struct { - char* tmp_filename; - bool delete_tmp_file; - char* include_path; - bool only_run_clang; -} VccOptions; - -static void cli_parse_vcc_args(VccOptions* options, int* pargc, char** argv) { - int argc = *pargc; - - for (int i = 1; i < argc; i++) { - if (argv[i] == NULL) - continue; - else if (strcmp(argv[i], "--vcc-keep-tmp-file") == 0) { - argv[i] = NULL; - options->delete_tmp_file = false; - options->tmp_filename = "vcc_tmp.ll"; - continue; - } else if (strcmp(argv[i], "--vcc-include-path") == 0) { - argv[i] = NULL; - i++; - if (i == argc) - error("Missing subgroup size name"); - options->include_path = argv[i]; - continue; - } else if (strcmp(argv[i], "--only-run-clang") == 0) { - argv[i] = NULL; - options->only_run_clang = true; - continue; - } - } - - cli_pack_remaining_args(pargc, argv); -} - -uint32_t hash_murmur(const void* data, size_t size); - int main(int argc, char** argv) { platform_specific_terminal_init_extras(); DriverConfig args = default_driver_config(); - VccOptions vcc_options = { - .tmp_filename = NULL, - .delete_tmp_file = true - }; + VccConfig vcc_options = vcc_init_config(); cli_parse_driver_arguments(&args, &argc, argv); cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.config, &argc, argv); @@ -70,90 +30,20 @@ int main(int argc, char** argv) { IrArena* arena = new_ir_arena(aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one - int clang_retval = system("clang --version"); - if (clang_retval != 0) - error("clang not present in path or otherwise broken (retval=%d)", clang_retval); - - size_t num_source_files = entries_count_list(args.input_filenames); - - Growy* g = new_growy(); - growy_append_string(g, "clang"); - char* self_path = get_executable_location(); - char* working_dir = strip_path(self_path); - if (!vcc_options.include_path) { - vcc_options.include_path = format_string_interned(arena, "%s/../share/vcc/include/", working_dir); - } - growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options.include_path); - free(working_dir); - free(self_path); + vcc_check_clang(); if (vcc_options.only_run_clang) - growy_append_formatted(g, " -o %s", args.output_filename); - else { - if (!vcc_options.tmp_filename) { - vcc_options.tmp_filename = alloca(33); - vcc_options.tmp_filename[32] = '\0'; - uint32_t hash = 0; - for (size_t i = 0; i < num_source_files; i++) { - String filename = read_list(const char*, args.input_filenames)[i]; - hash ^= hash_murmur(filename, strlen(filename)); - } - srand(hash); - for (size_t i = 0; i < 32; i++) { - vcc_options.tmp_filename[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % (10 + 26 * 2)]; - } - } - growy_append_formatted(g, " -o %s", vcc_options.tmp_filename); - } - - for (size_t i = 0; i < num_source_files; i++) { - String filename = read_list(const char*, args.input_filenames)[i]; - - growy_append_string(g, " \""); - growy_append_bytes(g, strlen(filename), filename); - growy_append_string(g, "\""); - } - - growy_append_bytes(g, 1, "\0"); - char* arg_string = growy_deconstruct(g); - - info_print("built command: %s\n", arg_string); - - FILE* stream = popen(arg_string, "r"); - free(arg_string); - - Growy* json_bytes = new_growy(); - while (true) { - char buf[4096]; - int read = fread(buf, 1, sizeof(buf), stream); - if (read == 0) - break; - growy_append_bytes(json_bytes, read, buf); - } - growy_append_string(json_bytes, "\0"); - char* llvm_result = growy_deconstruct(json_bytes); - int clang_returned = pclose(stream); - info_print("Clang returned %d and replied: \n%s", clang_returned, llvm_result); - free(llvm_result); - if (clang_returned) - exit(ClangInvocationFailed); + vcc_options.tmp_filename = format_string_new("%s", args.output_filename); + vcc_run_clang(&vcc_options, entries_count_list(args.input_filenames), read_list(String, args.input_filenames)); if (!vcc_options.only_run_clang) { - size_t len; - char* llvm_ir; - if (!read_file(vcc_options.tmp_filename, &len, &llvm_ir)) - exit(InputFileIOError); - driver_load_source_file(SrcLLVM, len, llvm_ir, mod); - free(llvm_ir); - - if (vcc_options.delete_tmp_file) - remove(vcc_options.tmp_filename); - + vcc_parse_back_into_module(&vcc_options, mod); driver_compile(&args, mod); } info_print("Done\n"); + destroy_vcc_options(vcc_options); destroy_ir_arena(arena); destroy_driver_config(&args); } diff --git a/src/driver/vcc_lib.c b/src/driver/vcc_lib.c new file mode 100644 index 000000000..9b63bc622 --- /dev/null +++ b/src/driver/vcc_lib.c @@ -0,0 +1,145 @@ +#include "vcc/driver.h" + +#include "log.h" +#include "list.h" +#include "util.h" +#include "growy.h" +#include "portability.h" + +#include +#include + +uint32_t hash_murmur(const void* data, size_t size); + +void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { + int argc = *pargc; + + for (int i = 1; i < argc; i++) { + if (argv[i] == NULL) + continue; + else if (strcmp(argv[i], "--vcc-keep-tmp-file") == 0) { + argv[i] = NULL; + options->delete_tmp_file = false; + options->tmp_filename = format_string_new("vcc_tmp.ll"); + continue; + } else if (strcmp(argv[i], "--vcc-include-path") == 0) { + argv[i] = NULL; + i++; + if (i == argc) + error("Missing subgroup size name"); + options->include_path = argv[i]; + continue; + } else if (strcmp(argv[i], "--only-run-clang") == 0) { + argv[i] = NULL; + options->only_run_clang = true; + continue; + } + } + + cli_pack_remaining_args(pargc, argv); +} + +void vcc_check_clang() { + int clang_retval = system("clang --version"); + if (clang_retval != 0) + error("clang not present in path or otherwise broken (retval=%d)", clang_retval); +} + +VccConfig vcc_init_config() { + VccConfig vcc_config = { + .only_run_clang = false, + }; + set_log_level(DEBUGVV); + + char* self_path = get_executable_location(); + char* working_dir = strip_path(self_path); + if (!vcc_config.include_path) { + vcc_config.include_path = format_string_new("%s/../share/vcc/include/", working_dir); + } + free(working_dir); + free(self_path); + return vcc_config; +} + +void destroy_vcc_options(VccConfig vcc_options) { + if (vcc_options.include_path) + free(vcc_options.include_path); + if (vcc_options.tmp_filename) + free(vcc_options.tmp_filename); +} + +void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* input_filenames) { + printf("cacaboudin %d\n", num_source_files); + printf("cacaboudin %d %d\n", input_filenames, input_filenames[0]); + Growy* g = new_growy(); + growy_append_string(g, "clang"); + char* self_path = get_executable_location(); + char* working_dir = strip_path(self_path); + growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options->include_path); + free(working_dir); + free(self_path); + + if (!vcc_options->tmp_filename) { + if (vcc_options->only_run_clang) { + error_print("Please provide an output filename.\n"); + error_die(); + } + char* tmp_alloc; + vcc_options->tmp_filename = tmp_alloc = malloc(33); + tmp_alloc[32] = '\0'; + uint32_t hash = 0; + for (size_t i = 0; i < num_source_files; i++) { + String filename = input_filenames[i]; + hash ^= hash_murmur(filename, strlen(filename)); + } + srand(hash); + for (size_t i = 0; i < 32; i++) { + tmp_alloc[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % (10 + 26 * 2)]; + } + } + growy_append_formatted(g, " -o %s", vcc_options->tmp_filename); + + for (size_t i = 0; i < num_source_files; i++) { + String filename = input_filenames[i]; + + growy_append_string(g, " \""); + growy_append_bytes(g, strlen(filename), filename); + growy_append_string(g, "\""); + } + + growy_append_bytes(g, 1, "\0"); + char* arg_string = growy_deconstruct(g); + + info_print("built command: %s\n", arg_string); + + FILE* stream = popen(arg_string, "r"); + free(arg_string); + + Growy* json_bytes = new_growy(); + while (true) { + char buf[4096]; + int read = fread(buf, 1, sizeof(buf), stream); + if (read == 0) + break; + growy_append_bytes(json_bytes, read, buf); + } + growy_append_string(json_bytes, "\0"); + char* llvm_result = growy_deconstruct(json_bytes); + int clang_returned = pclose(stream); + info_print("Clang returned %d and replied: \n%s", clang_returned, llvm_result); + free(llvm_result); + if (clang_returned) + exit(ClangInvocationFailed); +} + +void vcc_parse_back_into_module(VccConfig* vcc_options, Module* mod) { + size_t len; + char* llvm_ir; + if (!read_file(vcc_options->tmp_filename, &len, &llvm_ir)) + exit(InputFileIOError); + driver_load_source_file(SrcLLVM, len, llvm_ir, mod); + free(llvm_ir); + + if (vcc_options->delete_tmp_file) + remove(vcc_options->tmp_filename); +} \ No newline at end of file diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 7820ef882..1ec77641c 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -72,7 +72,7 @@ static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); debug_print("l2s: converting BB %s %d\n", LLVMGetBasicBlockName(bb), bb); if (get_log_level() <= DEBUG) - LLVMDumpValue(bb); + LLVMDumpValue((LLVMValueRef)bb); struct List* phis = new_list(LLVMValueRef); Nodes params = empty(a); diff --git a/zhady/common.i b/zhady/common.i new file mode 100644 index 000000000..e69de29bb From a873e2fa80f9c15af52a67b7cedc03185a1eae24 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 23:17:15 +0200 Subject: [PATCH 264/693] added vcc.i --- zhady/CMakeLists.txt | 13 +++++++++++++ zhady/common.i | 3 +++ zhady/shady.i | 1 + zhady/vcc.i | 8 ++++++++ 4 files changed, 25 insertions(+) create mode 100644 zhady/vcc.i diff --git a/zhady/CMakeLists.txt b/zhady/CMakeLists.txt index adc05273a..62aeb42e7 100644 --- a/zhady/CMakeLists.txt +++ b/zhady/CMakeLists.txt @@ -13,9 +13,22 @@ if (SWIG_FOUND AND JNI_FOUND AND Java_FOUND) set_property(TARGET zhady_shared_lib PROPERTY SWIG_COMPILE_OPTIONS -package de.unisaarland.zhady) target_link_libraries(zhady_shared_lib PUBLIC JNI::JNI api driver runtime) + if (TARGET vcc_lib) + swig_add_library(vcc_swig_c TYPE OBJECT LANGUAGE java SOURCES vcc.i OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady) + set_property(TARGET vcc_swig_c PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE) + set_property(TARGET vcc_swig_c PROPERTY SWIG_COMPILE_OPTIONS -package de.unisaarland.zhady) + target_link_libraries(vcc_swig_c PUBLIC JNI::JNI api vcc_lib) + target_link_libraries(zhady_shared_lib PRIVATE vcc_swig_c vcc_lib) + endif () + include(UseJava) get_property(zhady_jar_sources TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES) set(CMAKE_JAVA_COMPILE_FLAGS ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady/*.java) + + if (TARGET vcc_lib) + get_property(vcc_java_sources TARGET vcc_swig_c PROPERTY SWIG_SUPPORT_FILES) + list(APPEND zhady_jar_sources ${vcc_java_sources}) + endif () add_jar(zhady_jar SOURCES ${zhady_jar_sources}) install(TARGETS zhady_shared_lib EXPORT shady_export_set) diff --git a/zhady/common.i b/zhady/common.i index e69de29bb..3b5cef7ed 100644 --- a/zhady/common.i +++ b/zhady/common.i @@ -0,0 +1,3 @@ +SWIG_JAVABODY_METHODS(public, public, SWIGTYPE) +SWIG_JAVABODY_PROXY(public, public, SWIGTYPE) +SWIG_JAVABODY_TYPEWRAPPER(public, public, public, SWIGTYPE) diff --git a/zhady/shady.i b/zhady/shady.i index 0ae374ca4..e9298b623 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -1,3 +1,4 @@ +%include "common.i" %include //%apply int { _Bool }; diff --git a/zhady/vcc.i b/zhady/vcc.i new file mode 100644 index 000000000..ad84606aa --- /dev/null +++ b/zhady/vcc.i @@ -0,0 +1,8 @@ +%include common.i + +%module vcc +%{ +#include "vcc/driver.h" +%} + +%include "vcc/driver.h" From deaf4dd7412ae1160facc0d4829129aac780b696 Mon Sep 17 00:00:00 2001 From: SparkyPotato Date: Tue, 21 May 2024 17:04:51 +0100 Subject: [PATCH 265/693] remove need for empty initializer --- src/runtime/runtime_cli.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/runtime_cli.c b/src/runtime/runtime_cli.c index 27b78e771..87a951b21 100644 --- a/src/runtime/runtime_cli.c +++ b/src/runtime/runtime_cli.c @@ -8,6 +8,8 @@ RuntimeConfig default_runtime_config() { #ifndef NDEBUG .dump_spv = true, .use_validation = true, +#else + 0 #endif }; } From daac78a0f66abb8012fbecdf092925bc37f4e567 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 19 May 2024 23:16:49 +0200 Subject: [PATCH 266/693] vcc: split into library and executable --- include/vcc/driver.h | 22 ++++++ src/driver/CMakeLists.txt | 7 +- src/driver/vcc.c | 130 ++------------------------------- src/driver/vcc_lib.c | 148 ++++++++++++++++++++++++++++++++++++++ src/frontends/llvm/l2s.c | 2 +- 5 files changed, 183 insertions(+), 126 deletions(-) create mode 100644 include/vcc/driver.h create mode 100644 src/driver/vcc_lib.c diff --git a/include/vcc/driver.h b/include/vcc/driver.h new file mode 100644 index 000000000..1ea5745ff --- /dev/null +++ b/include/vcc/driver.h @@ -0,0 +1,22 @@ +#ifndef VCC_DRIVER_H +#define VCC_DRIVER_H + +#include "shady/driver.h" + +typedef struct { + bool delete_tmp_file; + bool only_run_clang; + const char* tmp_filename; + const char* include_path; +} VccConfig; + +void vcc_check_clang(); + +VccConfig vcc_init_config(); +void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv); +void destroy_vcc_options(VccConfig vcc_options); + +void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String input_filenames[]); +Module* vcc_parse_back_into_module(CompilerConfig* config, VccConfig* vcc_options, String module_name); + +#endif diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index 3c0847cbc..d8dcb32f7 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -19,9 +19,12 @@ target_link_libraries(slim PRIVATE driver) install(TARGETS slim EXPORT shady_export_set) if (TARGET shady_fe_llvm) + add_library(vcc_lib SHARED vcc_lib.c) + target_link_libraries(vcc_lib PUBLIC driver api) + add_executable(vcc vcc.c) - target_link_libraries(vcc PRIVATE driver api) - install(TARGETS vcc EXPORT shady_export_set) + target_link_libraries(vcc PRIVATE api vcc_lib) + install(TARGETS vcc_lib vcc EXPORT shady_export_set) if (WIN32) add_custom_command(TARGET vcc POST_BUILD diff --git a/src/driver/vcc.c b/src/driver/vcc.c index 5e4294891..29cd3340c 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -1,5 +1,5 @@ #include "shady/ir.h" -#include "shady/driver.h" +#include "vcc/driver.h" #include "log.h" #include "list.h" @@ -10,55 +10,11 @@ #include #include -typedef struct { - char* tmp_filename; - bool delete_tmp_file; - char* include_path; - bool only_run_clang; -} VccOptions; - -static void cli_parse_vcc_args(VccOptions* options, int* pargc, char** argv) { - int argc = *pargc; - - for (int i = 1; i < argc; i++) { - if (argv[i] == NULL) - continue; - else if (strcmp(argv[i], "--vcc-keep-tmp-file") == 0) { - argv[i] = NULL; - options->delete_tmp_file = false; - options->tmp_filename = "vcc_tmp.ll"; - continue; - } else if (strcmp(argv[i], "--vcc-include-path") == 0) { - argv[i] = NULL; - i++; - if (i == argc) - error("Missing subgroup size name"); - options->include_path = argv[i]; - continue; - } else if (strcmp(argv[i], "--only-run-clang") == 0) { - argv[i] = NULL; - options->only_run_clang = true; - continue; - } - } - - cli_pack_remaining_args(pargc, argv); -} - -uint32_t hash_murmur(const void* data, size_t size); - -int vcc_get_linked_major_llvm_version(); - int main(int argc, char** argv) { platform_specific_terminal_init_extras(); DriverConfig args = default_driver_config(); - VccOptions vcc_options = { - .tmp_filename = NULL, - .delete_tmp_file = true - }; - args.config.hacks.recover_structure = true; - + VccConfig vcc_options = vcc_init_config(); cli_parse_driver_arguments(&args, &argc, argv); cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.config, &argc, argv); @@ -73,93 +29,21 @@ int main(int argc, char** argv) { ArenaConfig aconfig = default_arena_config(&args.config.target); IrArena* arena = new_ir_arena(aconfig); - String clangname = format_string_interned(arena, "clang-%d", vcc_get_linked_major_llvm_version()); - int clang_retval = system(format_string_interned(arena, "%s --version", clangname)); - if (clang_retval != 0) - error("%s not present in path or otherwise broken (retval=%d)", clangname, clang_retval); - - size_t num_source_files = entries_count_list(args.input_filenames); - - Growy* g = new_growy(); - growy_append_string(g, clangname); - char* self_path = get_executable_location(); - char* working_dir = strip_path(self_path); - if (!vcc_options.include_path) { - vcc_options.include_path = format_string_interned(arena, "%s/../share/vcc/include/", working_dir); - } - growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options.include_path); - free(working_dir); - free(self_path); + vcc_check_clang(); if (vcc_options.only_run_clang) - growy_append_formatted(g, " -o %s", args.output_filename); - else { - if (!vcc_options.tmp_filename) { - vcc_options.tmp_filename = alloca(33); - vcc_options.tmp_filename[32] = '\0'; - uint32_t hash = 0; - for (size_t i = 0; i < num_source_files; i++) { - String filename = read_list(const char*, args.input_filenames)[i]; - hash ^= hash_murmur(filename, strlen(filename)); - } - srand(hash); - for (size_t i = 0; i < 32; i++) { - vcc_options.tmp_filename[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % (10 + 26 * 2)]; - } - } - growy_append_formatted(g, " -o %s", vcc_options.tmp_filename); - } - - for (size_t i = 0; i < num_source_files; i++) { - String filename = read_list(const char*, args.input_filenames)[i]; - - growy_append_string(g, " \""); - growy_append_bytes(g, strlen(filename), filename); - growy_append_string(g, "\""); - } - - growy_append_bytes(g, 1, "\0"); - char* arg_string = growy_deconstruct(g); - - info_print("built command: %s\n", arg_string); + vcc_options.tmp_filename = format_string_new("%s", args.output_filename); + vcc_run_clang(&vcc_options, entries_count_list(args.input_filenames), read_list(String, args.input_filenames)); - FILE* stream = popen(arg_string, "r"); - free(arg_string); - - Growy* json_bytes = new_growy(); - while (true) { - char buf[4096]; - int read = fread(buf, 1, sizeof(buf), stream); - if (read == 0) - break; - growy_append_bytes(json_bytes, read, buf); - } - growy_append_string(json_bytes, "\0"); - char* llvm_result = growy_deconstruct(json_bytes); - int clang_returned = pclose(stream); - info_print("Clang returned %d and replied: \n%s", clang_returned, llvm_result); - free(llvm_result); - if (clang_returned) - exit(ClangInvocationFailed); - - Module* mod; if (!vcc_options.only_run_clang) { - size_t len; - char* llvm_ir; - if (!read_file(vcc_options.tmp_filename, &len, &llvm_ir)) - exit(InputFileIOError); - driver_load_source_file(&args.config, SrcLLVM, len, llvm_ir, "my_module", &mod); // TODO name module after first filename, or perhaps the last one - free(llvm_ir); - - if (vcc_options.delete_tmp_file) - remove(vcc_options.tmp_filename); - + Module* mod = vcc_parse_back_into_module(&args.config, &vcc_options, "my_module"); driver_compile(&args, mod); destroy_ir_arena(get_module_arena(mod)); } info_print("Done\n"); + destroy_vcc_options(vcc_options); destroy_ir_arena(arena); destroy_driver_config(&args); } diff --git a/src/driver/vcc_lib.c b/src/driver/vcc_lib.c new file mode 100644 index 000000000..7e2856b71 --- /dev/null +++ b/src/driver/vcc_lib.c @@ -0,0 +1,148 @@ +#include "vcc/driver.h" + +#include "log.h" +#include "list.h" +#include "util.h" +#include "growy.h" +#include "portability.h" + +#include +#include + +uint32_t hash_murmur(const void* data, size_t size); + +void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { + int argc = *pargc; + + for (int i = 1; i < argc; i++) { + if (argv[i] == NULL) + continue; + else if (strcmp(argv[i], "--vcc-keep-tmp-file") == 0) { + argv[i] = NULL; + options->delete_tmp_file = false; + options->tmp_filename = format_string_new("vcc_tmp.ll"); + continue; + } else if (strcmp(argv[i], "--vcc-include-path") == 0) { + argv[i] = NULL; + i++; + if (i == argc) + error("Missing subgroup size name"); + options->include_path = argv[i]; + continue; + } else if (strcmp(argv[i], "--only-run-clang") == 0) { + argv[i] = NULL; + options->only_run_clang = true; + continue; + } + } + + cli_pack_remaining_args(pargc, argv); +} + +void vcc_check_clang() { + int clang_retval = system("clang --version"); + if (clang_retval != 0) + error("clang not present in path or otherwise broken (retval=%d)", clang_retval); +} + +VccConfig vcc_init_config() { + VccConfig vcc_config = { + .only_run_clang = false, + }; + set_log_level(DEBUGVV); + + char* self_path = get_executable_location(); + char* working_dir = strip_path(self_path); + if (!vcc_config.include_path) { + vcc_config.include_path = format_string_new("%s/../share/vcc/include/", working_dir); + } + free(working_dir); + free(self_path); + return vcc_config; +} + +void destroy_vcc_options(VccConfig vcc_options) { + if (vcc_options.include_path) + free(vcc_options.include_path); + if (vcc_options.tmp_filename) + free(vcc_options.tmp_filename); +} + +void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* input_filenames) { + printf("cacaboudin %d\n", num_source_files); + printf("cacaboudin %d %d\n", input_filenames, input_filenames[0]); + Growy* g = new_growy(); + growy_append_string(g, "clang"); + char* self_path = get_executable_location(); + char* working_dir = strip_path(self_path); + growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options->include_path); + free(working_dir); + free(self_path); + + if (!vcc_options->tmp_filename) { + if (vcc_options->only_run_clang) { + error_print("Please provide an output filename.\n"); + error_die(); + } + char* tmp_alloc; + vcc_options->tmp_filename = tmp_alloc = malloc(33); + tmp_alloc[32] = '\0'; + uint32_t hash = 0; + for (size_t i = 0; i < num_source_files; i++) { + String filename = input_filenames[i]; + hash ^= hash_murmur(filename, strlen(filename)); + } + srand(hash); + for (size_t i = 0; i < 32; i++) { + tmp_alloc[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % (10 + 26 * 2)]; + } + } + growy_append_formatted(g, " -o %s", vcc_options->tmp_filename); + + for (size_t i = 0; i < num_source_files; i++) { + String filename = input_filenames[i]; + + growy_append_string(g, " \""); + growy_append_bytes(g, strlen(filename), filename); + growy_append_string(g, "\""); + } + + growy_append_bytes(g, 1, "\0"); + char* arg_string = growy_deconstruct(g); + + info_print("built command: %s\n", arg_string); + + FILE* stream = popen(arg_string, "r"); + free(arg_string); + + Growy* json_bytes = new_growy(); + while (true) { + char buf[4096]; + int read = fread(buf, 1, sizeof(buf), stream); + if (read == 0) + break; + growy_append_bytes(json_bytes, read, buf); + } + growy_append_string(json_bytes, "\0"); + char* llvm_result = growy_deconstruct(json_bytes); + int clang_returned = pclose(stream); + info_print("Clang returned %d and replied: \n%s", clang_returned, llvm_result); + free(llvm_result); + if (clang_returned) + exit(ClangInvocationFailed); +} + +Module* vcc_parse_back_into_module(CompilerConfig* config, VccConfig* vcc_options, String module_name) { + size_t len; + char* llvm_ir; + if (!read_file(vcc_options->tmp_filename, &len, &llvm_ir)) + exit(InputFileIOError); + Module* mod; + driver_load_source_file(config, SrcLLVM, len, llvm_ir, module_name, &mod); + free(llvm_ir); + + if (vcc_options->delete_tmp_file) + remove(vcc_options->tmp_filename); + + return mod; +} \ No newline at end of file diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index c694bedad..d9e3f4cb8 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -78,7 +78,7 @@ static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); if (get_log_level() <= DEBUG) - LLVMDumpValue(bb); + LLVMDumpValue((LLVMValueRef)bb); struct List* phis = new_list(LLVMValueRef); Nodes params = empty(a); From 4f178a74909be56b8c0604ed0641e6b6a0fde5b1 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 26 May 2024 15:44:27 +0200 Subject: [PATCH 267/693] specify recursive dependency fixes mingw build --- src/frontends/slim/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontends/slim/CMakeLists.txt b/src/frontends/slim/CMakeLists.txt index e52435573..552f7c437 100644 --- a/src/frontends/slim/CMakeLists.txt +++ b/src/frontends/slim/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(slim_parser STATIC parser.c token.c) target_link_libraries(slim_parser PUBLIC common api) +target_link_libraries(slim_parser PRIVATE shady) target_include_directories(slim_parser PUBLIC $) target_include_directories(slim_parser INTERFACE "$") target_link_libraries(shady PUBLIC "$") From 2b11e9685e243b8db9b5df3329fd26370561f577 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 26 May 2024 15:44:47 +0200 Subject: [PATCH 268/693] added portable solution for get_time_nano --- samples/aobench/ao_main.c | 22 +++++----------------- src/common/portability.c | 17 +++++++++++++++++ src/common/portability.h | 2 ++ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index ef6d759cc..8571635e4 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -6,6 +6,7 @@ #include "shady/runtime.h" #include "shady/driver.h" +#include "portability.h" #include "log.h" #include "util.h" @@ -13,7 +14,6 @@ #include #include #include -#include typedef struct { CompilerConfig compiler_config; @@ -21,10 +21,6 @@ typedef struct { CommonAppArgs common_app_args; } Args; -static uint64_t timespec_to_nano(struct timespec t) { - return t.tv_sec * 1000000000 + t.tv_nsec; -} - void saveppm(const char *fname, int w, int h, TEXEL_T* img) { FILE *fp; @@ -47,9 +43,7 @@ void render_host(TEXEL_T* img, int w, int h, int nsubsamples) { Scalar* fimg = (Scalar *)malloc(sizeof(Scalar) * w * h * 3); memset((void *)fimg, 0, sizeof(Scalar) * w * h * 3); - struct timespec ts; - timespec_get(&ts, TIME_UTC); - uint64_t tsn = timespec_to_nano(ts); + uint64_t tsn = get_time_nano(); Ctx ctx = get_init_context(); init_scene(&ctx); @@ -58,9 +52,7 @@ void render_host(TEXEL_T* img, int w, int h, int nsubsamples) { render_pixel(&ctx, x, y, w, h, nsubsamples, img); } } - struct timespec tp; - timespec_get(&tp, TIME_UTC); - uint64_t tpn = timespec_to_nano(tp); + uint64_t tpn = get_time_nano(); info_print("reference rendering took %d us\n", (tpn - tsn) / 1000); } @@ -133,17 +125,13 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri // run it twice to compile everything and benefit from caches wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, NULL)); - struct timespec ts; - timespec_get(&ts, TIME_UTC); - uint64_t tsn = timespec_to_nano(ts); + uint64_t tsn = get_time_nano(); uint64_t profiled_gpu_time = 0; ExtraKernelOptions extra_kernel_options = { .profiled_gpu_time = &profiled_gpu_time }; wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, &extra_kernel_options)); - struct timespec tp; - timespec_get(&tp, TIME_UTC); - uint64_t tpn = timespec_to_nano(tp); + uint64_t tpn = get_time_nano(); info_print("device rendering took %dus (gpu time: %dus)\n", (tpn - tsn) / 1000, profiled_gpu_time / 1000); if (!import_memory) diff --git a/src/common/portability.c b/src/common/portability.c index 057a98a4c..84200bed2 100644 --- a/src/common/portability.c +++ b/src/common/portability.c @@ -28,6 +28,23 @@ void platform_specific_terminal_init_extras() { #endif } +#include +#if defined(__MINGW64__) | defined(__MINGW32__) +#include +uint64_t get_time_nano() { + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return t.tv_sec * 1000000000 + t.tv_nsec; +} +#else +#include +uint64_t get_time_nano() { + struct timespec t; + timespec_get(&t, TIME_UTC); + return t.tv_sec * 1000000000 + t.tv_nsec; +} +#endif + #ifdef WIN32 #include #elif __APPLE__ diff --git a/src/common/portability.h b/src/common/portability.h index 626d8203e..097181906 100644 --- a/src/common/portability.h +++ b/src/common/portability.h @@ -47,6 +47,8 @@ static inline void free_aligned(void* ptr) { #endif } +#include +uint64_t get_time_nano(); const char* get_executable_location(void); void platform_specific_terminal_init_extras(); From b79a7669a5edd797e19a55ae9d27233c9de56b69 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 18:31:15 +0200 Subject: [PATCH 269/693] vcc_lib: fix a bunch of memory issues with options parsing --- src/driver/vcc_lib.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/driver/vcc_lib.c b/src/driver/vcc_lib.c index 7e2856b71..3ccd0fc75 100644 --- a/src/driver/vcc_lib.c +++ b/src/driver/vcc_lib.c @@ -27,7 +27,9 @@ void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { i++; if (i == argc) error("Missing subgroup size name"); - options->include_path = argv[i]; + if (options->include_path) + free((void*) options->include_path); + options->include_path = format_string_new("%s", argv[i]); continue; } else if (strcmp(argv[i], "--only-run-clang") == 0) { argv[i] = NULL; @@ -49,35 +51,32 @@ VccConfig vcc_init_config() { VccConfig vcc_config = { .only_run_clang = false, }; - set_log_level(DEBUGVV); - char* self_path = get_executable_location(); - char* working_dir = strip_path(self_path); + String self_path = get_executable_location(); + String working_dir = strip_path(self_path); if (!vcc_config.include_path) { vcc_config.include_path = format_string_new("%s/../share/vcc/include/", working_dir); } - free(working_dir); - free(self_path); + free((void*) working_dir); + free((void*) self_path); return vcc_config; } void destroy_vcc_options(VccConfig vcc_options) { if (vcc_options.include_path) - free(vcc_options.include_path); + free((void*) vcc_options.include_path); if (vcc_options.tmp_filename) - free(vcc_options.tmp_filename); + free((void*) vcc_options.tmp_filename); } void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* input_filenames) { - printf("cacaboudin %d\n", num_source_files); - printf("cacaboudin %d %d\n", input_filenames, input_filenames[0]); Growy* g = new_growy(); growy_append_string(g, "clang"); - char* self_path = get_executable_location(); - char* working_dir = strip_path(self_path); + String self_path = get_executable_location(); + String working_dir = strip_path(self_path); growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options->include_path); - free(working_dir); - free(self_path); + free((void*) working_dir); + free((void*) self_path); if (!vcc_options->tmp_filename) { if (vcc_options->only_run_clang) { From 7ca22b7e1ab1c8ab597aea32306d82417f239e08 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 18:31:32 +0200 Subject: [PATCH 270/693] l2s: fix illegal cast on gcc 14 --- src/frontends/llvm/l2s_instr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index bcdc90cb3..d0cdf7610 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -173,13 +173,13 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, } case LLVMSwitch: { const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); - const Node* default_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, LLVMGetOperand(instr, 1)); + const Node* default_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, 1)); int n_targets = LLVMGetNumOperands(instr) / 2 - 1; LARRAY(const Node*, targets, n_targets); LARRAY(const Node*, literals, n_targets); for (size_t i = 0; i < n_targets; i++) { literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); - targets[i] = convert_jump_lazy(p, fn_ctx, fn_or_bb, LLVMGetOperand(instr, i * 2 + 3)); + targets[i] = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3)); } return (EmittedInstr) { .terminator = br_switch(a, (Switch) { From f699e2f759434c20d2b635e4c5444eab7b3f56b5 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 18:31:54 +0200 Subject: [PATCH 271/693] slim: don't create cycle if 'shady' is a shared lib --- src/frontends/slim/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/frontends/slim/CMakeLists.txt b/src/frontends/slim/CMakeLists.txt index 552f7c437..19ee4b831 100644 --- a/src/frontends/slim/CMakeLists.txt +++ b/src/frontends/slim/CMakeLists.txt @@ -1,6 +1,8 @@ add_library(slim_parser STATIC parser.c token.c) target_link_libraries(slim_parser PUBLIC common api) -target_link_libraries(slim_parser PRIVATE shady) +if (shady STREQUAL STATIC_LIBRARY) + target_link_libraries(slim_parser PRIVATE shady) +endif () target_include_directories(slim_parser PUBLIC $) target_include_directories(slim_parser INTERFACE "$") target_link_libraries(shady PUBLIC "$") From 0d3d311b40eab241ae1187cacbaf8774bd4e3ab7 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 18:32:30 +0200 Subject: [PATCH 272/693] runtime: fix a bunch of illegal implicit casts --- src/runtime/vulkan/vk_runtime_buffer.c | 10 +++++----- src/runtime/vulkan/vk_runtime_private.h | 1 + src/runtime/vulkan/vk_runtime_program.c | 16 ++++++++-------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/runtime/vulkan/vk_runtime_buffer.c b/src/runtime/vulkan/vk_runtime_buffer.c index 67f8ac644..5983254ea 100644 --- a/src/runtime/vulkan/vk_runtime_buffer.c +++ b/src/runtime/vulkan/vk_runtime_buffer.c @@ -218,7 +218,7 @@ VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { return NULL; } -static void vkr_destroy_buffer(VkrBuffer* buffer) { +void vkr_destroy_buffer(VkrBuffer* buffer) { vkDestroyBuffer(buffer->device->device, buffer->buffer, NULL); vkFreeMemory(buffer->device->device, buffer->memory, NULL); } @@ -264,7 +264,7 @@ static bool vkr_copy_to_buffer_fallback(VkrBuffer* dst, size_t buffer_offset, vo CHECK_VK(vkMapMemory(device->device, src_buf->memory, src_buf->offset, src_buf->size, 0, &mapped), goto err_post_buffer_create); memcpy(mapped, src, size); - if (!wait_completion(submit_buffer_copy(device, src_buf->buffer, src_buf->offset, dst->buffer, dst->offset + buffer_offset, size))) + if (!wait_completion((Command*) submit_buffer_copy(device, src_buf->buffer, src_buf->offset, dst->buffer, dst->offset + buffer_offset, size))) goto err_post_buffer_create; vkUnmapMemory(device->device, src_buf->memory); @@ -287,7 +287,7 @@ static bool vkr_copy_from_buffer_fallback(VkrBuffer* src, size_t buffer_offset, void* mapped; CHECK_VK(vkMapMemory(device->device, dst_buf->memory, dst_buf->offset, dst_buf->size, 0, &mapped), goto err_post_buffer_create); - if (!wait_completion(submit_buffer_copy(device, src->buffer, src->offset + buffer_offset, dst_buf->buffer, dst_buf->offset, size))) + if (!wait_completion((Command*) submit_buffer_copy(device, src->buffer, src->offset + buffer_offset, dst_buf->buffer, dst_buf->offset, size))) goto err_post_buffer_create; memcpy(dst, mapped, size); @@ -308,7 +308,7 @@ static bool vkr_copy_to_buffer_importing(VkrBuffer* dst, size_t buffer_offset, v if (!src_buf) return false; - if (!wait_completion(submit_buffer_copy(device, src_buf->buffer, src_buf->offset, dst->buffer, dst->offset + buffer_offset, size))) + if (!wait_completion((Command*) submit_buffer_copy(device, src_buf->buffer, src_buf->offset, dst->buffer, dst->offset + buffer_offset, size))) goto err_post_buffer_import; vkr_destroy_buffer(src_buf); @@ -327,7 +327,7 @@ static bool vkr_copy_from_buffer_importing(VkrBuffer* src, size_t buffer_offset, if (!dst_buf) return false; - if (!wait_completion(submit_buffer_copy(device, src->buffer, src->offset + buffer_offset, dst_buf->buffer, dst_buf->offset, size))) + if (!wait_completion((Command*) submit_buffer_copy(device, src->buffer, src->offset + buffer_offset, dst_buf->buffer, dst_buf->offset, size))) goto err_post_buffer_import; vkr_destroy_buffer(dst_buf); diff --git a/src/runtime/vulkan/vk_runtime_private.h b/src/runtime/vulkan/vk_runtime_private.h index fa6e127a3..e580d9c91 100644 --- a/src/runtime/vulkan/vk_runtime_private.h +++ b/src/runtime/vulkan/vk_runtime_private.h @@ -172,6 +172,7 @@ typedef struct VkrBuffer_ { VkrBuffer* vkr_allocate_buffer_device(VkrDevice* device, size_t size); VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size); bool vkr_can_import_host_memory(VkrDevice* device); +void vkr_destroy_buffer(VkrBuffer* buffer); typedef struct VkrCommand_ VkrCommand; diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 55d57cd1f..07ea7c68c 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -120,7 +120,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay for (size_t j = 0; j < struct_t->payload.record_type.members.count; j++) { const Type* member_t = struct_t->payload.record_type.members.nodes[j]; assert(member_t->tag == PtrType_TAG); - member_t = get_pointee_type(program->arena, member_t); + member_t = get_pointee_type(member_t->arena, member_t); TypeMemLayout layout = get_mem_layout(program->specialized_module->arena, member_t); ProgramResourceInfo* constant_res_info = arena_alloc(program->arena, sizeof(ProgramResourceInfo)); @@ -434,7 +434,7 @@ static void flush_staged_data(VkrSpecProgram* program) { for (size_t i = 0; i < program->resources.num_resources; i++) { ProgramResourceInfo* resource = program->resources.resources[i]; if (resource->staging) { - copy_to_buffer(resource->buffer, 0, resource->buffer, resource->size); + copy_to_buffer((Buffer*) resource->buffer, 0, resource->buffer, resource->size); free(resource->staging); } } @@ -447,16 +447,16 @@ static bool prepare_resources(VkrSpecProgram* program) { if (resource->host_backed_allocation) { assert(vkr_can_import_host_memory(program->device)); resource->host_ptr = alloc_aligned(resource->size, program->device->caps.properties.external_memory_host.minImportedHostPointerAlignment); - resource->buffer = import_buffer_host(program->device, resource->host_ptr, resource->size); + resource->buffer = vkr_import_buffer_host(program->device, resource->host_ptr, resource->size); } else { - resource->buffer = allocate_buffer_device(program->device, resource->size); + resource->buffer = vkr_allocate_buffer_device(program->device, resource->size); } if (resource->default_data) { - copy_to_buffer(resource->buffer, 0, resource->default_data, resource->size); + copy_to_buffer((Buffer*) resource->buffer, 0, resource->default_data, resource->size); } else { char* zeroes = calloc(1, resource->size); - copy_to_buffer(resource->buffer, 0, zeroes, resource->size); + copy_to_buffer((Buffer*) resource->buffer, 0, zeroes, resource->size); free(zeroes); } @@ -466,7 +466,7 @@ static bool prepare_resources(VkrSpecProgram* program) { dst = resource->parent->staging; } assert(dst); - *((uint64_t*) (dst + resource->offset)) = get_buffer_device_pointer(resource->buffer); + *((uint64_t*) (dst + resource->offset)) = get_buffer_device_pointer((Buffer*) resource->buffer); } } @@ -517,7 +517,7 @@ void destroy_specialized_program(VkrSpecProgram* spec) { for (size_t i = 0; i < spec->resources.num_resources; i++) { ProgramResourceInfo* resource = spec->resources.resources[i]; if (resource->buffer) - destroy_buffer(resource->buffer); + vkr_destroy_buffer(resource->buffer); if (resource->host_ptr && resource->host_backed_allocation) free_aligned(resource->host_ptr); } From 0625af70f91c9ea4732839f8ac946829b11efa56 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 18:34:22 +0200 Subject: [PATCH 273/693] rewrite: improved constructors --- src/frontends/llvm/l2s_postprocess.c | 11 +++------- src/shady/emit/spirv/emit_spv_type.c | 2 +- src/shady/passes/bind.c | 2 +- src/shady/passes/cleanup.c | 2 +- src/shady/passes/eliminate_constants.c | 2 +- src/shady/passes/import.c | 4 ++-- src/shady/passes/infer.c | 2 +- src/shady/passes/lift_indirect_targets.c | 3 ++- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_callf.c | 2 +- src/shady/passes/lower_cf_instrs.c | 2 +- src/shady/passes/lower_decay_ptrs.c | 2 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_fill.c | 2 +- src/shady/passes/lower_generic_globals.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 2 +- src/shady/passes/lower_int64.c | 2 +- src/shady/passes/lower_lea.c | 2 +- src/shady/passes/lower_mask.c | 2 +- src/shady/passes/lower_memcpy.c | 2 +- src/shady/passes/lower_memory_layout.c | 2 +- src/shady/passes/lower_nullptr.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 2 +- src/shady/passes/lower_stack.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_subgroup_vars.c | 3 +-- src/shady/passes/lower_switch_btree.c | 2 +- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/mark_leaf_functions.c | 2 +- src/shady/passes/normalize.c | 3 +-- src/shady/passes/normalize_builtins.c | 2 +- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_inline.c | 2 +- src/shady/passes/opt_mem2reg.c | 2 +- src/shady/passes/opt_restructure.c | 2 +- src/shady/passes/opt_stack.c | 2 +- src/shady/passes/reconvergence_heuristics.c | 2 +- src/shady/passes/setup_stack_frames.c | 2 +- src/shady/passes/simt2d.c | 2 +- src/shady/passes/specialize_entry_point.c | 2 +- src/shady/passes/specialize_execution_model.c | 2 +- src/shady/passes/spirv_lift_globals_ssbo.c | 2 +- src/shady/passes/spirv_map_entrypoint_args.c | 2 +- src/shady/rewrite.c | 20 +++++++++++++++---- src/shady/rewrite.h | 4 +++- 47 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 0d71c7861..fee572154 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -75,7 +75,7 @@ static Nodes remake_params(Context* ctx, Nodes old) { return nodes(a, old.count, nvars); } -static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Node* node) { +static const Node* process_node(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (node->tag) { @@ -289,7 +289,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, default: break; } - if (op_class == NcTerminator && node->tag != Let_TAG) { + if (is_terminator(node) && node->tag != Let_TAG) { Controls** found = find_value_dict(const Node, Controls*, ctx->controls, ctx->old_fn_or_bb); assert(found); Controls* controls = *found; @@ -299,20 +299,15 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, return recreate_node_identity(&ctx->rewriter, node); } -static const Node* process_node(Context* ctx, const Node* old) { - return process_op(ctx, 0, NULL, old); -} - void postprocess(Parser* p, Module* src, Module* dst) { assert(src != dst); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = p->config, .p = p, .controls = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), }; - ctx.rewriter.rewrite_op_fn = (RewriteOpFn) process_op; ctx.rewriter.config.process_params = true; ctx.rewriter.config.search_map = true; // ctx.rewriter.config.write_map = false; diff --git a/src/shady/emit/spirv/emit_spv_type.c b/src/shady/emit/spirv/emit_spv_type.c index 389132ee0..14be0bbca 100644 --- a/src/shady/emit/spirv/emit_spv_type.c +++ b/src/shady/emit/spirv/emit_spv_type.c @@ -59,7 +59,7 @@ static const Node* rewrite_normalize(Rewriter* rewriter, const Node* node) { } const Type* normalize_type(Emitter* emitter, const Type* type) { - Rewriter rewriter = create_rewriter(emitter->module, emitter->module, rewrite_normalize); + Rewriter rewriter = create_node_rewriter(emitter->module, emitter->module, rewrite_normalize); const Node* rewritten = rewrite_node(&rewriter, type); destroy_rewriter(&rewriter); return rewritten; diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 4702069f4..f20e1025d 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -338,7 +338,7 @@ Module* bind_program(SHADY_UNUSED const CompilerConfig* compiler_config, Module* Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) bind_node), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) bind_node), .local_variables = NULL, .current_function = NULL, }; diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 4877368e3..1dc2d3a19 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -167,7 +167,7 @@ bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { *m = new_module(a, get_module_name(*m)); bool todo = false; Context ctx = { .todo = &todo }; - ctx.rewriter = create_rewriter(src, *m, (RewriteNodeFn) process), + ctx.rewriter = create_node_rewriter(src, *m, (RewriteNodeFn) process), rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); return todo; diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 2b474a367..27a021fab 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -62,7 +62,7 @@ Module* eliminate_constants(SHADY_UNUSED const CompilerConfig* config, Module* s IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process) + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process) }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 5cf11ff70..79f62dd7a 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -66,7 +66,7 @@ Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) recreate_node_identity), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) recreate_node_identity), }; rewrite_module(&ctx.rewriter); @@ -76,7 +76,7 @@ Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { void link_module(Module* dst, Module* src) { Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) import_node), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) import_node), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index f1ed57cbd..2ddd96eb4 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -785,7 +785,7 @@ Module* infer_program(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), }; ctx.rewriter.config.search_map = false; ctx.rewriter.config.write_map = false; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index a500e2732..814a73878 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -241,7 +241,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { dst = new_module(a, get_module_name(src)); bool todo = false; Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .lifted = new_dict(const Node*, LiftedCont*, (HashFn) hash_node, (CmpFn) compare_node), .config = config, @@ -274,6 +274,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { dst = new_module(a2, get_module_name(src)); Rewriter r = create_importer(src, dst); rewrite_module(&r); + destroy_rewriter(&r); destroy_ir_arena(a); return dst; } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 89e0b9633..e26586003 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -175,7 +175,7 @@ Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .stack_ptr_t = int_type(a, (Int) { .is_signed = false, .width = IntTy32 }), }; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index b2cc8fcbb..906647262 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -143,7 +143,7 @@ Module* lower_callf(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) lower_callf_process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) lower_callf_process), .disable_lowering = false, }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index a1d44d606..b392f5041 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -262,7 +262,7 @@ Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .structured_join_tokens = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), }; ctx.rewriter.config.fold_quote = false; diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index 4f1b185c8..4cc19f341 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -42,7 +42,7 @@ Module* lower_decay_ptrs(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 591bdce64..7dc7a2c6d 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -99,7 +99,7 @@ Module* lower_entrypoint_args(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index eaab886e0..b441998fa 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -36,7 +36,7 @@ Module* lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index fe325bd7d..dfdc6a992 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -43,7 +43,7 @@ Module* lower_generic_globals(SHADY_UNUSED const CompilerConfig* config, Module* IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index cb41529e1..a0e49ea14 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -256,7 +256,7 @@ Module* lower_generic_ptrs(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .fns = new_dict(String, const Node*, (HashFn) hash_string, (CmpFn) compare_string), .generic_ptr_type = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false}), .config = config, diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 025703dbd..20db56856 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -88,7 +88,7 @@ Module* lower_int(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index c12b2c86a..be0055bb6 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -148,7 +148,7 @@ Module* lower_lea(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index b89e0b206..3a9b60d43 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -64,7 +64,7 @@ Module* lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* src) { assert(mask_type->tag == Int_TAG); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .zero = int_literal(a, (IntLiteral) { .width = mask_type->payload.int_type.width, .value = 0 }), .one = int_literal(a, (IntLiteral) { .width = mask_type->payload.int_type.width, .value = 1 }), }; diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 4115d9800..8565241a6 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -131,7 +131,7 @@ Module* lower_memcpy(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process) + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process) }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 856ba78a1..e540c74fc 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -57,7 +57,7 @@ Module* lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* s Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process) + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process) }; ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index ff76b72d5..fad776bab 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -54,7 +54,7 @@ Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 2210c0d3b..360147f4b 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -497,7 +497,7 @@ Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, }; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 18f3113c8..c54af1c32 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -172,7 +172,7 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 17a947736..26cdd35c3 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -154,7 +154,7 @@ Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); assert(!config->lower.emulate_subgroup_ops && "TODO"); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .fns = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node) }; diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index f47c52bbe..a69c4c6bd 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -78,10 +78,9 @@ Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, NULL), + .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process), .config = config }; - ctx.rewriter.rewrite_op_fn = (RewriteOpFn) process; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); return dst; diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index adc96115a..390e5b788 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -192,7 +192,7 @@ Module* lower_switch_btree(SHADY_UNUSED const CompilerConfig* config, Module* sr Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index cf50292e2..5aec81d10 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -430,7 +430,7 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) Node* top_dispatcher_fn = NULL; Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .disable_lowering = false, .assigned_fn_ptrs = ptrs, diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 78802fb36..606b4f0b1 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -60,7 +60,7 @@ Module* lower_vec_arr(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 606d9db9a..9840d40f5 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -175,7 +175,7 @@ Module* lower_workgroups(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .globals = calloc(sizeof(Node*), PRIMOPS_COUNT), }; diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index f7b8cc897..a057e6fdc 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -170,7 +170,7 @@ Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* s IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .fns = new_dict(const Node*, FnInfo, (HashFn) hash_node, (CmpFn) compare_node), .graph = new_callgraph(src) }; diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index 783b1aa3b..7f1dc5cd9 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -145,13 +145,12 @@ Module* normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) NULL), + .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process_op), .bb = NULL, }; ctx.rewriter.config.search_map = false; ctx.rewriter.config.write_map = false; - ctx.rewriter.rewrite_op_fn = (RewriteOpFn) process_op; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 678635896..1be5d1078 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -110,7 +110,7 @@ Module* normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* sr IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .builtins = calloc(sizeof(Node*), BuiltinsCount) }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 0c1d41bf7..e941129bf 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -283,7 +283,7 @@ bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { IrArena* a = get_module_arena(src); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .arena = new_arena(), .alloca_info = new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 4517ddc03..1fbace078 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -242,7 +242,7 @@ bool compare_node(const Node**, const Node**); void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .graph = NULL, .fun = NULL, diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 1c452353f..c813e3baf 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -711,7 +711,7 @@ Module* opt_mem2reg(const CompilerConfig* config, Module* src) { dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .bb_new_args = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), .a = new_arena(), diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 5135f0bd3..13e02f797 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -416,7 +416,7 @@ Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .tmp_alloc_stack = new_list(struct Dict*), }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/opt_stack.c b/src/shady/passes/opt_stack.c index cc019a0ca..80835702f 100644 --- a/src/shady/passes/opt_stack.c +++ b/src/shady/passes/opt_stack.c @@ -133,7 +133,7 @@ Module* opt_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .state = NULL, }; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 22381a8b3..bdba23680 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -551,7 +551,7 @@ Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .current_fn = NULL, .fwd_cfg = NULL, diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index a8eb18211..6e15c0a0b 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -65,7 +65,7 @@ Module* setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* sr IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c index ddb3052d4..f65f7923b 100644 --- a/src/shady/passes/simt2d.c +++ b/src/shady/passes/simt2d.c @@ -94,7 +94,7 @@ Module* simt2d(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .width = config->specialization.subgroup_size, .mask = NULL, }; diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 519c7d70c..430a91f69 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -114,7 +114,7 @@ Module* specialize_entry_point(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 40f489a3d..595eb2b0f 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -55,7 +55,7 @@ Module* specialize_execution_model(const CompilerConfig* config, Module* src) { assert(subgroup_size); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index 4523b5025..4d67023a8 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -59,7 +59,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; diff --git a/src/shady/passes/spirv_map_entrypoint_args.c b/src/shady/passes/spirv_map_entrypoint_args.c index 8bb23aa64..ebe9aa88b 100644 --- a/src/shady/passes/spirv_map_entrypoint_args.c +++ b/src/shady/passes/spirv_map_entrypoint_args.c @@ -67,7 +67,7 @@ Module* spirv_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Mod IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; ctx.rewriter.config.rebind_let = true; diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 99f8d2e2b..937f2a2a6 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -12,13 +12,12 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); -Rewriter create_rewriter(Module* src, Module* dst, RewriteNodeFn fn) { +Rewriter create_rewriter_base(Module* src, Module* dst) { return (Rewriter) { .src_arena = src->arena, .dst_arena = dst->arena, .src_module = src, .dst_module = dst, - .rewrite_fn = fn, .config = { .search_map = true, //.write_map = true, @@ -26,10 +25,23 @@ Rewriter create_rewriter(Module* src, Module* dst, RewriteNodeFn fn) { .fold_quote = true, }, .map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), - .decls_map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), }; } +Rewriter create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn) { + Rewriter r = create_rewriter_base(src, dst); + r.rewrite_fn = fn; + r.decls_map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + return r; +} + +Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn) { + Rewriter r = create_rewriter_base(src, dst); + r.rewrite_op_fn = fn; + r.decls_map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + return r; +} + void destroy_rewriter(Rewriter* r) { assert(r->map); destroy_dict(r->map); @@ -38,7 +50,7 @@ void destroy_rewriter(Rewriter* r) { } Rewriter create_importer(Module* src, Module* dst) { - return create_rewriter(src, dst, recreate_node_identity); + return create_node_rewriter(src, dst, recreate_node_identity); } Module* rebuild_module(Module* src) { diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index f6fd3f876..decdd27cc 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -44,7 +44,9 @@ struct Rewriter_ { struct Dict* decls_map; }; -Rewriter create_rewriter(Module* src, Module* dst, RewriteNodeFn fn); +Rewriter create_rewriter_base(Module* src, Module* dst); +Rewriter create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn); +Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn); Rewriter create_importer(Module* src, Module* dst); Module* rebuild_module(Module*); Rewriter create_substituter(Module* arena); From 8b71c398f2afa16ec4cdcad200d98a6b876de217 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 18:51:51 +0200 Subject: [PATCH 274/693] restructure: fix memory leaks --- src/shady/passes/opt_restructure.c | 75 ++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 13e02f797..173a83eab 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -37,9 +37,29 @@ struct DFSStackEntry_ { bool in_loop; }; +typedef void (*TmpAllocCleanupFn)(void*); +typedef struct { + TmpAllocCleanupFn fn; + void* payload; +} TmpAllocCleanupClosure; + +static TmpAllocCleanupClosure create_delete_dict_closure(struct Dict* d) { + return (TmpAllocCleanupClosure) { + .fn = (TmpAllocCleanupFn) destroy_dict, + .payload = d, + }; +} + +static TmpAllocCleanupClosure create_cancel_body_closure(BodyBuilder* bb) { + return (TmpAllocCleanupClosure) { + .fn = (TmpAllocCleanupFn) cancel_body, + .payload = bb, + }; +} + typedef struct { Rewriter rewriter; - struct List* tmp_alloc_stack; + struct List* cleanup_stack; jmp_buf bail; @@ -64,7 +84,7 @@ static DFSStackEntry* encountered_before(Context* ctx, const Node* bb, size_t* p static const Node* structure(Context* ctx, const Node* abs, const Node* exit_ladder); -static const Node* handle_bb_callsite(Context* ctx, BodyBuilder* bb, const Node* caller, const Node* j, const Node* exit_ladder) { +static const Node* handle_bb_callsite(Context* ctx, const Node* caller, const Node* j, const Node* exit_ladder) { assert(j->tag == Jump_TAG); IrArena* a = ctx->rewriter.dst_arena; const Node* dst = j->payload.jump.target; @@ -87,9 +107,9 @@ static const Node* handle_bb_callsite(Context* ctx, BodyBuilder* bb, const Node* entry2 = entry2->parent; } prior_encounter->loop_header = true; - return finish_body(bb, merge_continue(a, (MergeContinue) { + return merge_continue(a, (MergeContinue) { .args = rewrite_nodes(&ctx->rewriter, oargs) - })); + }); } else { Nodes oparams = get_abstraction_params(dst); assert(oparams.count == oargs.count); @@ -99,9 +119,13 @@ static const Node* handle_bb_callsite(Context* ctx, BodyBuilder* bb, const Node* // Record each step of the depth-first search on a stack so we can identify loops DFSStackEntry dfs_entry = { .parent = ctx->dfs_stack, .old = dst, .containing_control = ctx->control_stack }; ctx2.dfs_stack = &dfs_entry; - + + BodyBuilder* bb = begin_body(a); + TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); + append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); - append_list(struct Dict*, ctx->tmp_alloc_stack, tmp_processed); + TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); + append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; for (size_t i = 0; i < oargs.count; i++) { nparams[i] = param(a, rewrite_node(&ctx->rewriter, oparams.nodes[i]->type), "arg"); @@ -119,7 +143,8 @@ static const Node* handle_bb_callsite(Context* ctx, BodyBuilder* bb, const Node* assert(is_terminator(structured)); // forget we rewrote all that destroy_dict(tmp_processed); - pop_list_impl(ctx->tmp_alloc_stack); + pop_list_impl(ctx->cleanup_stack); + pop_list_impl(ctx->cleanup_stack); if (dfs_entry.loop_header) { const Node* body = case_(a, nodes(a, oargs.count, nparams), structured); @@ -261,8 +286,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad return rebuild_let(ctx, body, recreate_node_identity(&ctx->rewriter, old_instr), exit_ladder); } case Jump_TAG: { - BodyBuilder* bb = begin_body(a); - return handle_bb_callsite(ctx, bb, abs, body, exit_ladder); + return handle_bb_callsite(ctx, abs, body, exit_ladder); } // br(cond, true_bb, false_bb, args) // becomes @@ -270,12 +294,10 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case Branch_TAG: { const Node* condition = rewrite_node(&ctx->rewriter, body->payload.branch.branch_condition); - BodyBuilder* if_true_bb = begin_body(a); - const Node* true_body = handle_bb_callsite(ctx, if_true_bb, abs, body->payload.branch.true_jump, yield(a, (Yield) { .args = empty(a) })); + const Node* true_body = handle_bb_callsite(ctx, abs, body->payload.branch.true_jump, yield(a, (Yield) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); - BodyBuilder* if_false_bb = begin_body(a); - const Node* false_body = handle_bb_callsite(ctx, if_false_bb, abs, body->payload.branch.false_jump, yield(a, (Yield) { .args = empty(a) })); + const Node* false_body = handle_bb_callsite(ctx, abs, body->payload.branch.false_jump, yield(a, (Yield) { .args = empty(a) })); const Node* if_false_lam = case_(a, empty(a), false_body); const Node* instr = if_instr(a, (If) { @@ -290,14 +312,12 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case Switch_TAG: { const Node* switch_value = rewrite_node(&ctx->rewriter, body->payload.br_switch.switch_value); - BodyBuilder* default_bb = begin_body(a); - const Node* default_body = handle_bb_callsite(ctx, default_bb, abs, body->payload.br_switch.default_jump, yield(a, (Yield) { .args = empty(a) })); + const Node* default_body = handle_bb_callsite(ctx, abs, body->payload.br_switch.default_jump, yield(a, (Yield) { .args = empty(a) })); const Node* default_case = case_(a, empty(a), default_body); LARRAY(const Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { - BodyBuilder* bb = begin_body(a); - cases[i] = case_(a, empty(a), handle_bb_callsite(ctx, bb, abs, body->payload.br_switch.case_jumps.nodes[i], yield(a, (Yield) {.args = empty(a)}))); + cases[i] = case_(a, empty(a), handle_bb_callsite(ctx, abs, body->payload.br_switch.case_jumps.nodes[i], yield(a, (Yield) {.args = empty(a)}))); } const Node* instr = match_instr(a, (Match) { @@ -357,7 +377,7 @@ static const Node* process(Context* ctx, const Node* node) { if (node->tag == Function_TAG) { Node* new = recreate_decl_header_identity(&ctx->rewriter, node); - size_t alloc_stack_size_now = entries_count_list(ctx->tmp_alloc_stack); + size_t alloc_stack_size_now = entries_count_list(ctx->cleanup_stack); Context ctx2 = *ctx; ctx2.dfs_stack = NULL; @@ -374,24 +394,31 @@ static const Node* process(Context* ctx, const Node* node) { } else { ctx2.lower = true; BodyBuilder* bb = begin_body(a); + TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); + append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); const Node* ptr = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = alloca_logical_op, .type_arguments = singleton(int32_type(a)) }), (String []) {"cf_depth" })); bind_instruction(bb, prim_op(a, (PrimOp) { .op = store_op, .operands = mk_nodes(a, ptr, int32_literal(a, 0)) })); ctx2.level_ptr = ptr; ctx2.fn = new; struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); - append_list(struct Dict*, ctx->tmp_alloc_stack, tmp_processed); + TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); + append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; new->payload.fun.body = finish_body(bb, structure(&ctx2, node, unreachable(a))); is_leaf = true; + // We made it! Pop off the pending cleanup stuff and do it ourselves. + pop_list_impl(ctx->cleanup_stack); + pop_list_impl(ctx->cleanup_stack); + destroy_dict(tmp_processed); } //if (is_leaf) // new->payload.fun.annotations = append_nodes(arena, new->payload.fun.annotations, annotation(arena, (Annotation) { .name = "Leaf" })); // if we did a longjmp, we might have orphaned a few of those - while (alloc_stack_size_now < entries_count_list(ctx->tmp_alloc_stack)) { - struct Dict* orphan = pop_last_list(struct Dict*, ctx->tmp_alloc_stack); - destroy_dict(orphan); + while (alloc_stack_size_now < entries_count_list(ctx->cleanup_stack)) { + TmpAllocCleanupClosure cj = pop_last_list(TmpAllocCleanupClosure, ctx->cleanup_stack); + cj.fn(cj.payload); } new->payload.fun.annotations = filter_out_annotation(a, new->payload.fun.annotations, "MaybeLeaf"); @@ -417,10 +444,10 @@ Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .tmp_alloc_stack = new_list(struct Dict*), + .cleanup_stack = new_list(TmpAllocCleanupClosure), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_list(ctx.tmp_alloc_stack); + destroy_list(ctx.cleanup_stack); return dst; } From 8bc69c752a17626906547fc3ca75f80fc8283216 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 18:59:05 +0200 Subject: [PATCH 275/693] l2s: fix regression with br(jump(...), jump(...)) patterns --- src/frontends/llvm/l2s_postprocess.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index fee572154..8a0c7bff4 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -75,7 +75,7 @@ static Nodes remake_params(Context* ctx, Nodes old) { return nodes(a, old.count, nvars); } -static const Node* process_node(Context* ctx, const Node* node) { +static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (node->tag) { @@ -289,7 +289,8 @@ static const Node* process_node(Context* ctx, const Node* node) { default: break; } - if (is_terminator(node) && node->tag != Let_TAG) { + // This is required so we don't wrap jumps that are part of branches! + if (op_class == NcTerminator && node->tag != Let_TAG) { Controls** found = find_value_dict(const Node, Controls*, ctx->controls, ctx->old_fn_or_bb); assert(found); Controls* controls = *found; @@ -299,6 +300,11 @@ static const Node* process_node(Context* ctx, const Node* node) { return recreate_node_identity(&ctx->rewriter, node); } +static const Node* process_node(Context* ctx, const Node* old) { + return process_op(ctx, 0, NULL, old); +} + + void postprocess(Parser* p, Module* src, Module* dst) { assert(src != dst); Context ctx = { @@ -310,6 +316,7 @@ void postprocess(Parser* p, Module* src, Module* dst) { ctx.rewriter.config.process_params = true; ctx.rewriter.config.search_map = true; + ctx.rewriter.rewrite_op_fn = (RewriteOpFn) process_op; // ctx.rewriter.config.write_map = false; rewrite_module(&ctx.rewriter); From a6c3368efc22f80e9a52576cdcd39971dce7cb8f Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 19:04:52 +0200 Subject: [PATCH 276/693] vcc: default config tweaks --- include/vcc/driver.h | 4 ++-- src/driver/vcc.c | 2 +- src/driver/vcc_lib.c | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/vcc/driver.h b/include/vcc/driver.h index 1ea5745ff..d41aa3aed 100644 --- a/include/vcc/driver.h +++ b/include/vcc/driver.h @@ -10,9 +10,9 @@ typedef struct { const char* include_path; } VccConfig; -void vcc_check_clang(); +void vcc_check_clang(void); -VccConfig vcc_init_config(); +VccConfig vcc_init_config(CompilerConfig* compiler_config); void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv); void destroy_vcc_options(VccConfig vcc_options); diff --git a/src/driver/vcc.c b/src/driver/vcc.c index 29cd3340c..9a82809a9 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -14,7 +14,7 @@ int main(int argc, char** argv) { platform_specific_terminal_init_extras(); DriverConfig args = default_driver_config(); - VccConfig vcc_options = vcc_init_config(); + VccConfig vcc_options = vcc_init_config(&args.config); cli_parse_driver_arguments(&args, &argc, argv); cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.config, &argc, argv); diff --git a/src/driver/vcc_lib.c b/src/driver/vcc_lib.c index 3ccd0fc75..9ae8db86a 100644 --- a/src/driver/vcc_lib.c +++ b/src/driver/vcc_lib.c @@ -41,17 +41,20 @@ void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { cli_pack_remaining_args(pargc, argv); } -void vcc_check_clang() { +void vcc_check_clang(void) { int clang_retval = system("clang --version"); if (clang_retval != 0) error("clang not present in path or otherwise broken (retval=%d)", clang_retval); } -VccConfig vcc_init_config() { +VccConfig vcc_init_config(CompilerConfig* compiler_config) { VccConfig vcc_config = { .only_run_clang = false, }; + // magic! + compiler_config->hacks.recover_structure = true; + String self_path = get_executable_location(); String working_dir = strip_path(self_path); if (!vcc_config.include_path) { From 6759dca18bc3aa34369a0a5e46cc6dc32034c8f3 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 19:20:39 +0200 Subject: [PATCH 277/693] generator: use hex constants for C11 compliance --- src/shady/generator/generator_common.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/shady/generator/generator_common.c b/src/shady/generator/generator_common.c index 6f80789cb..20a6768c6 100644 --- a/src/shady/generator/generator_common.c +++ b/src/shady/generator/generator_common.c @@ -125,9 +125,7 @@ void generate_bit_enum(Growy* g, String enum_type_name, String enum_case_prefix, json_object* node_class = json_object_array_get_idx(cases, i); String name = json_object_get_string(json_object_object_get(node_class, "name")); String capitalized = capitalize(name); - growy_append_formatted(g, "\t%s%s = 0b1", enum_case_prefix, capitalized); - for (int c = 0; c < i; c++) - growy_append_string_literal(g, "0"); + growy_append_formatted(g, "\t%s%s = 0x%x", enum_case_prefix, capitalized, (1 << i)); growy_append_formatted(g, ",\n"); free(capitalized); } From c68e3f71f81b415d16ae69cf381a587d646d1990 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 21:18:11 +0200 Subject: [PATCH 278/693] pass on compiler warnings --- include/shady/ir.h | 2 +- samples/aobench/ao.c | 4 ++-- src/common/log.h | 3 +-- src/common/util.c | 2 ++ src/driver/cli.h | 2 +- src/frontends/llvm/l2s.c | 4 +--- src/frontends/llvm/l2s_private.h | 4 ++-- src/runtime/runtime.c | 4 ++-- src/runtime/vulkan/vk_runtime_buffer.c | 2 +- src/runtime/vulkan/vk_runtime_private.h | 2 +- src/runtime/vulkan/vk_runtime_program.c | 2 +- src/shady/analysis/looptree.h | 1 - src/shady/compile.c | 2 +- src/shady/compile.h | 2 +- src/shady/generator/generator.c | 2 +- src/shady/generator/generator_common.c | 10 +++++----- src/shady/generator_constructors.c | 5 +++-- src/shady/generator_node.c | 11 +++++++---- src/shady/generator_print.c | 5 +++-- src/shady/generator_rewrite.c | 5 +++-- src/shady/generator_type.c | 3 ++- src/shady/generator_visit.c | 5 +++-- src/shady/module.c | 4 ++-- src/shady/passes/reconvergence_heuristics.c | 2 -- src/shady/passes/specialize_entry_point.c | 4 +++- 25 files changed, 49 insertions(+), 43 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index a07be5469..cbb820626 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -55,7 +55,7 @@ Module* new_module(IrArena*, String name); IrArena* get_module_arena(const Module*); String get_module_name(const Module*); Nodes get_module_declarations(const Module*); -const Node* get_declaration(const Module*, String); +Node* get_declaration(const Module*, String); //////////////////////////////// Grammar //////////////////////////////// diff --git a/samples/aobench/ao.c b/samples/aobench/ao.c index 5d4a36860..c5e5b4b46 100644 --- a/samples/aobench/ao.c +++ b/samples/aobench/ao.c @@ -220,7 +220,7 @@ EXTERNAL_FN void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamp Scalar px = (x + (u / (Scalar)nsubsamples) - (w / 2.0f)) / (w / 2.0f); Scalar py = -(y + (v / (Scalar)nsubsamples) - (h / 2.0f)) / (h / 2.0f); - Ray ray = {}; + Ray ray = { 0 }; ray.org.x = 0.0f; ray.org.y = 0.0f; @@ -231,7 +231,7 @@ EXTERNAL_FN void render_pixel(Ctx* ctx, int x, int y, int w, int h, int nsubsamp ray.dir.z = -1.0f; vnormalize(&(ray.dir)); - Isect isect = {}; + Isect isect = { 0 }; isect.t = 1.0e+17f; isect.hit = 0; diff --git a/src/common/log.h b/src/common/log.h index d37832c49..2c05bb0a9 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -52,9 +52,8 @@ void log_module(LogLevel level, const CompilerConfig*, Module*); fprintf (stderr, __VA_ARGS__); \ fprintf (stderr, "\n"); \ error_die(); \ - SHADY_UNREACHABLE; \ } -void error_die(); +void error_die() __attribute__ ((noreturn)); #endif diff --git a/src/common/util.c b/src/common/util.c index 7cc562413..955ae0678 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -32,6 +32,7 @@ size_t apply_escape_codes(const char* src, size_t size, char* dst) { } \ ESCAPE_SEQS(ESCAPE_CASE) +#undef ESCAPE_CASE dst[j++] = c; } @@ -51,6 +52,7 @@ size_t unapply_escape_codes(const char* src, size_t size, char* dst) { } \ ESCAPE_SEQS(ESCAPE_CASE) +#undef ESCAPE_CASE dst[j++] = c; } diff --git a/src/driver/cli.h b/src/driver/cli.h index 908eb5808..207c96a57 100644 --- a/src/driver/cli.h +++ b/src/driver/cli.h @@ -12,4 +12,4 @@ if (strcmp(argv[i], "--no-"#name) == 0) { \ void cli_pack_remaining_args(int* pargc, char** argv); -#endif CLI_H +#endif diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index d9e3f4cb8..7d7446ae2 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -65,7 +65,7 @@ static const Node* write_bb_tail(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, insert_dict(LLVMValueRef, const Node*, p->map, instr, result); } } - assert(false); + SHADY_UNREACHABLE; } typedef struct { @@ -116,10 +116,8 @@ static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { } const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { - IrArena* a = get_module_arena(p->dst); const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); if (found) return *found; - // assert(false); TodoBB todo = prepare_bb(p, fn_ctx, bb); todo.nbb->payload.basic_block.body = write_bb_tail(p, fn_ctx, todo.nbb, todo.bb, todo.instr); diff --git a/src/frontends/llvm/l2s_private.h b/src/frontends/llvm/l2s_private.h index 8078cd60b..766a18f52 100644 --- a/src/frontends/llvm/l2s_private.h +++ b/src/frontends/llvm/l2s_private.h @@ -77,7 +77,7 @@ Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc); void postprocess(Parser*, Module* src, Module* dst); -static String is_llvm_intrinsic(LLVMValueRef fn) { +inline static String is_llvm_intrinsic(LLVMValueRef fn) { assert(LLVMIsAFunction(fn) || LLVMIsConstant(fn)); String name = LLVMGetValueName(fn); if (string_starts_with(name, "llvm.")) @@ -85,7 +85,7 @@ static String is_llvm_intrinsic(LLVMValueRef fn) { return NULL; } -static String is_shady_intrinsic(LLVMValueRef fn) { +inline static String is_shady_intrinsic(LLVMValueRef fn) { assert(LLVMIsAFunction(fn) || LLVMIsConstant(fn)); String name = LLVMGetValueName(fn); if (string_starts_with(name, "shady::")) diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 5d007891d..690c3df0d 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -85,10 +85,10 @@ bool can_import_host_memory(Device* device) { return device->can_import_host_mem Buffer* allocate_buffer_device(Device* device, size_t bytes) { return device->allocate_buffer(device, bytes); } Buffer* import_buffer_host(Device* device, void* ptr, size_t bytes) { return device->import_host_memory_as_buffer(device, ptr, bytes); } -void destroy_buffer(Buffer* buf) { buf->destroy(buf); }; +void destroy_buffer(Buffer* buf) { buf->destroy(buf); } void* get_buffer_host_pointer(Buffer* buf) { return buf->get_host_ptr(buf); } -uint64_t get_buffer_device_pointer(Buffer* buf) { return buf->get_device_ptr(buf); }; +uint64_t get_buffer_device_pointer(Buffer* buf) { return buf->get_device_ptr(buf); } bool copy_to_buffer(Buffer* dst, size_t buffer_offset, void* src, size_t size) { return dst->copy_into(dst, buffer_offset, src, size); diff --git a/src/runtime/vulkan/vk_runtime_buffer.c b/src/runtime/vulkan/vk_runtime_buffer.c index 5983254ea..4f9659f8d 100644 --- a/src/runtime/vulkan/vk_runtime_buffer.c +++ b/src/runtime/vulkan/vk_runtime_buffer.c @@ -32,7 +32,7 @@ static uint32_t find_suitable_memory_type(VkrDevice* device, uint32_t memory_typ } } } - assert(false && "Unable to find a suitable memory type"); + error("Unable to find a suitable memory type") } static Buffer make_base_buffer(VkrDevice*); diff --git a/src/runtime/vulkan/vk_runtime_private.h b/src/runtime/vulkan/vk_runtime_private.h index e580d9c91..1361b5caf 100644 --- a/src/runtime/vulkan/vk_runtime_private.h +++ b/src/runtime/vulkan/vk_runtime_private.h @@ -211,7 +211,7 @@ struct ProgramResourceInfo_ { size_t size; VkrBuffer* buffer; - char* default_data; + unsigned char* default_data; }; typedef struct { diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 07ea7c68c..f8d0e314d 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -510,7 +510,7 @@ void destroy_specialized_program(VkrSpecProgram* spec) { vkDestroyDescriptorSetLayout(spec->device->device, spec->set_layouts[set], NULL); vkDestroyPipelineLayout(spec->device->device, spec->layout, NULL); vkDestroyShaderModule(spec->device->device, spec->shader_module, NULL); - free(spec->parameters.arg_offset); + free( (void*) spec->parameters.arg_offset); free(spec->spirv_bytes); if (get_module_arena(spec->specialized_module) != get_module_arena(spec->key.base->module)) destroy_ir_arena(get_module_arena(spec->specialized_module)); diff --git a/src/shady/analysis/looptree.h b/src/shady/analysis/looptree.h index 50b649aa1..65bdb0c36 100644 --- a/src/shady/analysis/looptree.h +++ b/src/shady/analysis/looptree.h @@ -41,7 +41,6 @@ struct LoopTree_ { */ LTNode* looptree_lookup(LoopTree*, const Node* block); -static void destroy_lt_node(LTNode* n); void destroy_loop_tree(LoopTree* lt); LoopTree* build_loop_tree(CFG* s); diff --git a/src/shady/compile.c b/src/shady/compile.c index 9a576a55e..2f98ce91b 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -20,7 +20,7 @@ void add_scheduler_source(const CompilerConfig* config, Module* dst) { destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); } -void run_pass_impl(CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name) { +void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name) { Module* old_mod = NULL; old_mod = *pmod; *pmod = pass(config, *pmod); diff --git a/src/shady/compile.h b/src/shady/compile.h index 4672578b7..d71f08647 100644 --- a/src/shady/compile.h +++ b/src/shady/compile.h @@ -12,7 +12,7 @@ #define SHADY_RUN_VERIFY 1 #endif -void run_pass_impl(CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name); +void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name); #define RUN_PASS(pass_name) run_pass_impl(config, pmod, initial_arena, pass_name, #pass_name); diff --git a/src/shady/generator/generator.c b/src/shady/generator/generator.c index 75e542b42..ee0ec7d83 100644 --- a/src/shady/generator/generator.c +++ b/src/shady/generator/generator.c @@ -1,6 +1,6 @@ #include "generator.h" -static bool should_include_instruction(json_object* instruction) { +inline static bool should_include_instruction(json_object* instruction) { String class = json_object_get_string(json_object_object_get(instruction, "class")); if (strcmp(class, "@exclude") == 0) return false; diff --git a/src/shady/generator/generator_common.c b/src/shady/generator/generator_common.c index 20a6768c6..fb6ba9136 100644 --- a/src/shady/generator/generator_common.c +++ b/src/shady/generator/generator_common.c @@ -19,7 +19,7 @@ void generate_node_ctor(Growy* g, json_object* nodes, bool definition) { growy_append_formatted(g, "\n"); String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); - void* alloc = NULL; + const void* alloc = NULL; if (!snake_name) { alloc = snake_name = to_snake_case(name); } @@ -58,7 +58,7 @@ void generate_node_ctor(Growy* g, json_object* nodes, bool definition) { } if (alloc) - free(alloc); + free((void*) alloc); } growy_append_formatted(g, "\n"); } @@ -127,7 +127,7 @@ void generate_bit_enum(Growy* g, String enum_type_name, String enum_case_prefix, String capitalized = capitalize(name); growy_append_formatted(g, "\t%s%s = 0x%x", enum_case_prefix, capitalized, (1 << i)); growy_append_formatted(g, ",\n"); - free(capitalized); + free((void*) capitalized); } growy_append_formatted(g, "} %s;\n\n", enum_type_name); } @@ -148,7 +148,7 @@ void generate_bit_enum_classifier(Growy* g, String fn_name, String enum_type_nam case json_type_string: { String cap = capitalize(json_object_get_string(class)); growy_append_formatted(g, "\t\t\treturn %s%s;\n", enum_case_prefix, cap); - free(cap); + free((void*) cap); break; } case json_type_array: { @@ -158,7 +158,7 @@ void generate_bit_enum_classifier(Growy* g, String fn_name, String enum_type_nam growy_append_formatted(g, " | "); String cap = capitalize(json_object_get_string(json_object_array_get_idx(class, j))); growy_append_formatted(g, "%s%s", enum_case_prefix, cap); - free(cap); + free((void*) cap); } growy_append_formatted(g, ";\n"); break; diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 6b74f7b07..53140c0d2 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -11,7 +11,8 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); void* alloc = NULL; if (!snake_name) { - alloc = snake_name = to_snake_case(name); + snake_name = to_snake_case(name); + alloc = (void*) snake_name; } growy_append_formatted(g, "\tcase %s_TAG: {\n", name); json_object* ops = json_object_object_get(node, "ops"); @@ -47,7 +48,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { growy_append_formatted(g, "%s\t\t\t}\n", extra); if (list) growy_append_formatted(g, "\t\t\t}\n"); - free(cap); + free((void*) cap); growy_append_formatted(g, "\t\t}\n"); } } diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 9b424e6e6..83b934286 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -11,7 +11,8 @@ static void generate_node_names_string_array(Growy* g, json_object* nodes) { String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); void* alloc = NULL; if (!snake_name) { - alloc = snake_name = to_snake_case(name); + snake_name = to_snake_case(name); + alloc = (void*) snake_name; } assert(name); growy_append_formatted(g, "\t\"%s\",\n", snake_name); @@ -43,7 +44,8 @@ static void generate_node_payload_hash_fn(Growy* g, json_object* src, json_objec String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); void* alloc = NULL; if (!snake_name) { - alloc = snake_name = to_snake_case(name); + snake_name = to_snake_case(name); + alloc = (void*) snake_name; } json_object* ops = json_object_object_get(node, "ops"); if (ops) { @@ -81,7 +83,8 @@ static void generate_node_payload_cmp_fn(Growy* g, json_object* src, json_object String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); void* alloc = NULL; if (!snake_name) { - alloc = snake_name = to_snake_case(name); + snake_name = to_snake_case(name); + alloc = (void*) snake_name; } json_object* ops = json_object_object_get(node, "ops"); if (ops) { @@ -203,6 +206,6 @@ void generate(Growy* g, json_object* src) { json_object* generate_enum = json_object_object_get(node_class, "generate-enum"); String capitalized = capitalize(name); generate_isa_for_class(g, nodes, name, capitalized, !generate_enum || json_object_get_boolean(generate_enum)); - free(capitalized); + free((void*) capitalized); } } diff --git a/src/shady/generator_print.c b/src/shady/generator_print.c index 59b9ed842..299e310fa 100644 --- a/src/shady/generator_print.c +++ b/src/shady/generator_print.c @@ -11,7 +11,8 @@ void generate_node_print_fns(Growy* g, json_object* src) { String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); void* alloc = NULL; if (!snake_name) { - alloc = snake_name = to_snake_case(name); + snake_name = to_snake_case(name); + alloc = (void*) snake_name; } growy_append_formatted(g, "\tcase %s_TAG: {\n", name); growy_append_formatted(g, "\t\tprint(printer, \"%s \");\n", name); @@ -42,7 +43,7 @@ void generate_node_print_fns(Growy* g, json_object* src) { growy_append_formatted(g, "\t\t\tprint_node_operand(printer, node, \"%s\", Nc%s, node->payload.%s.%s, config);\n", op_name, cap_class, snake_name, op_name); growy_append_formatted(g, "\t\t}\n"); } - free(cap_class); + free((void*) cap_class); } else { String op_type = json_object_get_string(json_object_object_get(op, "type")); if (!op_type) { diff --git a/src/shady/generator_rewrite.c b/src/shady/generator_rewrite.c index a163d6044..e01b22d7e 100644 --- a/src/shady/generator_rewrite.c +++ b/src/shady/generator_rewrite.c @@ -30,7 +30,8 @@ static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); void* alloc = NULL; if (!snake_name) { - alloc = snake_name = to_snake_case(name); + snake_name = to_snake_case(name); + alloc = (void*) snake_name; } growy_append_formatted(g, "\t\tcase %s_TAG: {\n", name); json_object* ops = json_object_object_get(node, "ops"); @@ -64,7 +65,7 @@ static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { growy_append_formatted(g, "\t\t\tpayload.%s = rewrite_ops_helper(rewriter, Nc%s, \"%s\", old_payload.%s);\n", op_name, class_cap, op_name, op_name); else growy_append_formatted(g, "\t\t\tpayload.%s = rewrite_op_helper(rewriter, Nc%s, \"%s\", old_payload.%s);\n", op_name, class_cap, op_name, op_name); - free(class_cap); + free((void*) class_cap); } growy_append_formatted(g, "\t\t\treturn %s(rewriter->dst_arena, payload);\n", snake_name); } else diff --git a/src/shady/generator_type.c b/src/shady/generator_type.c index d4aaddf3a..c22ed5133 100644 --- a/src/shady/generator_type.c +++ b/src/shady/generator_type.c @@ -13,7 +13,8 @@ void generate(Growy* g, json_object* src) { String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); void* alloc = NULL; if (!snake_name) { - alloc = snake_name = to_snake_case(name); + snake_name = to_snake_case(name); + alloc = (void*) snake_name; } json_object* t = json_object_object_get(node, "type"); diff --git a/src/shady/generator_visit.c b/src/shady/generator_visit.c index 64d030af8..3db5df01a 100644 --- a/src/shady/generator_visit.c +++ b/src/shady/generator_visit.c @@ -13,7 +13,8 @@ void generate(Growy* g, json_object* src) { String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); void* alloc = NULL; if (!snake_name) { - alloc = snake_name = to_snake_case(name); + snake_name = to_snake_case(name); + alloc = (void*) snake_name; } growy_append_formatted(g, "\tcase %s_TAG: {\n", name); json_object* ops = json_object_object_get(node, "ops"); @@ -36,7 +37,7 @@ void generate(Growy* g, json_object* src) { else growy_append_formatted(g, "\t\t\tvisit_op(visitor, Nc%s, \"%s\", payload.%s);\n", class_cap, op_name, op_name); } - free(class_cap); + free((void*) class_cap); } } growy_append_formatted(g, "\t\tbreak;\n"); diff --git a/src/shady/module.c b/src/shady/module.c index 46396012f..7416d46be 100644 --- a/src/shady/module.c +++ b/src/shady/module.c @@ -36,11 +36,11 @@ void register_decl_module(Module* m, Node* node) { append_list(Node*, m->decls, node); } -const Node* get_declaration(const Module* m, String name) { +Node* get_declaration(const Module* m, String name) { Nodes existing_decls = get_module_declarations(m); for (size_t i = 0; i < existing_decls.count; i++) { if (strcmp(get_declaration_name(existing_decls.nodes[i]), name) == 0) - return existing_decls.nodes[i]; + return (Node*) existing_decls.nodes[i]; } return NULL; } diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index bdba23680..bc7168ddb 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -74,8 +74,6 @@ static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, log_string(DEBUGVV, " )\n"); append_list(const Node*, leaking, v); - - next:; } } diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 430a91f69..9d7b7b007 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -86,6 +86,8 @@ static const Node* find_entry_point(Module* m, const CompilerConfig* config) { static void specialize_arena_config(const CompilerConfig* config, Module* src, ArenaConfig* target) { const Node* old_entry_point_decl = find_entry_point(src, config); + if (!old_entry_point_decl) + error("Entry point not found") if (old_entry_point_decl->tag != Function_TAG) error("%s is not a function", config->specialization.entry_point); const Node* ep = lookup_annotation(old_entry_point_decl, "EntryPoint"); @@ -100,7 +102,7 @@ static void specialize_arena_config(const CompilerConfig* config, Module* src, A target->specializations.workgroup_size[0] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[0]), false); target->specializations.workgroup_size[1] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[1]), false); target->specializations.workgroup_size[2] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[2]), false); - assert(target->specializations.workgroup_size[0] * target->specializations.workgroup_size[1] * target->specializations.workgroup_size[2]); + assert(target->specializations.workgroup_size[0] * target->specializations.workgroup_size[1] * target->specializations.workgroup_size[2] > 0); break; } default: break; From f0ef9cd528230022128d08bc6e2b9132361a8b2a Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 26 May 2024 22:25:22 +0200 Subject: [PATCH 279/693] use stdnoreturn --- src/common/log.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/log.h b/src/common/log.h index 2c05bb0a9..7c48f41a3 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -54,6 +54,7 @@ void log_module(LogLevel level, const CompilerConfig*, Module*); error_die(); \ } -void error_die() __attribute__ ((noreturn)); +#include +noreturn void error_die(); #endif From 75f5984b29d6e25ad736ddb288730f8eec1d6ed3 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 26 May 2024 20:39:51 +0200 Subject: [PATCH 280/693] fix MinGW _again_ --- src/frontends/slim/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontends/slim/CMakeLists.txt b/src/frontends/slim/CMakeLists.txt index 19ee4b831..ff984437c 100644 --- a/src/frontends/slim/CMakeLists.txt +++ b/src/frontends/slim/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(slim_parser STATIC parser.c token.c) target_link_libraries(slim_parser PUBLIC common api) -if (shady STREQUAL STATIC_LIBRARY) +if (shady STREQUAL STATIC_LIBRARY OR MINGW) target_link_libraries(slim_parser PRIVATE shady) endif () target_include_directories(slim_parser PUBLIC $) From 85a42a5b0b871fb836a874725143058cdca928c2 Mon Sep 17 00:00:00 2001 From: gob Date: Thu, 30 May 2024 10:06:33 +0200 Subject: [PATCH 281/693] simplify check_subtype --- src/shady/type.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/shady/type.c b/src/shady/type.c index 4ca21b238..d92e82af8 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -26,6 +26,8 @@ bool is_subtype(const Type* supertype, const Type* type) { assert(supertype && type); if (supertype->tag != type->tag) return false; + if (type == supertype) + return true; switch (is_type(supertype)) { case NotAType: error("supplied not a type to is_subtype"); case QualifiedType_TAG: { @@ -41,7 +43,7 @@ bool is_subtype(const Type* supertype, const Type* type) { if (!is_subtype(supermembers->nodes[i], members->nodes[i])) return false; } - return true; + return supertype->payload.record_type.special == type->payload.record_type.special; } case JoinPointType_TAG: { const Nodes* superparams = &supertype->payload.join_point_type.yield_types; @@ -134,15 +136,10 @@ bool is_subtype(const Type* supertype, const Type* type) { } case Type_SampledImageType_TAG: return is_subtype(supertype->payload.sampled_image_type.image_type, type->payload.sampled_image_type.image_type); - case SamplerType_TAG: - case NoRet_TAG: - case Bool_TAG: - case MaskType_TAG: - return true; - case Float_TAG: - return supertype->payload.float_type.width == type->payload.float_type.width; + default: break; } - SHADY_UNREACHABLE; + // Two types are always equal (and therefore subtypes of each other) if their payload matches + return memcmp(&supertype->payload, &type->payload, sizeof(type->payload)) == 0; } void check_subtype(const Type* supertype, const Type* type) { From 9cab304344ea14408d927c615fa7e29a1bf6445e Mon Sep 17 00:00:00 2001 From: gob Date: Tue, 4 Jun 2024 09:22:20 +0200 Subject: [PATCH 282/693] name_type_safe: default to just the node name --- src/shady/type.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/shady/type.c b/src/shady/type.c index d92e82af8..50ab25d63 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -200,17 +200,7 @@ String name_type_safe(IrArena* arena, const Type* t) { case Type_Float_TAG: return format_string_arena(arena->arena, "f%s", ((String[]) {"16", "32", "64" })[t->payload.float_type.width]); case Type_Bool_TAG: return "bool"; - case Type_RecordType_TAG: - case Type_FnType_TAG: - case Type_BBType_TAG: - case Type_LamType_TAG: - case Type_PtrType_TAG: - case Type_QualifiedType_TAG: - case Type_ArrType_TAG: - case Type_PackType_TAG: - case Type_ImageType_TAG: - case Type_SamplerType_TAG: - case Type_SampledImageType_TAG: + default: break; case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; } From 2f11fa75f16a3cf6429841079c2c765b0f987928 Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 16:59:34 +0000 Subject: [PATCH 283/693] l2s: fix crash when blocks appear outside functions --- src/frontends/llvm/l2s_postprocess.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 8a0c7bff4..5cab11681 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -290,7 +290,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } // This is required so we don't wrap jumps that are part of branches! - if (op_class == NcTerminator && node->tag != Let_TAG) { + if (ctx->old_fn_or_bb && op_class == NcTerminator && node->tag != Let_TAG) { Controls** found = find_value_dict(const Node, Controls*, ctx->controls, ctx->old_fn_or_bb); assert(found); Controls* controls = *found; From beefd365610a476fec2c9f2733f7599180dea0b0 Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 17:00:17 +0000 Subject: [PATCH 284/693] added code to inline some synthetic constants early --- src/frontends/llvm/l2s.c | 2 +- src/frontends/llvm/l2s_value.c | 3 +-- src/shady/compile.c | 1 + src/shady/passes/eliminate_constants.c | 16 ++++++++++++++-- src/shady/passes/passes.h | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 7d7446ae2..3172c519c 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -224,7 +224,7 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { decl->payload.global_variable.init = convert_value(p, value); if (UNTYPED_POINTERS) { - Node* untyped_wrapper = constant(p->dst, empty(a), ptr_t, format_string_interned(a, "%s_untyped", name)); + Node* untyped_wrapper = constant(p->dst, singleton(annotation(a, (Annotation) { .name = "Inline" })), ptr_t, format_string_interned(a, "%s_untyped", name)); untyped_wrapper->payload.constant.instruction = quote_helper(a, singleton(ref_decl_helper(a, decl))); untyped_wrapper->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(ptr_t), singleton(ref_decl_helper(a, decl))); decl = untyped_wrapper; diff --git a/src/frontends/llvm/l2s_value.c b/src/frontends/llvm/l2s_value.c index 4d9a36284..bfb106207 100644 --- a/src/frontends/llvm/l2s_value.c +++ b/src/frontends/llvm/l2s_value.c @@ -78,8 +78,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { String name = LLVMGetValueName(v); if (!name || strlen(name) == 0) name = unique_name(a, "constant_expr"); - Nodes annotations = singleton(annotation(a, (Annotation) { .name = "SkipOnInfer" })); - annotations = empty(a); + Nodes annotations = singleton(annotation(a, (Annotation) { .name = "Inline" })); assert(t); Node* decl = constant(p->dst, annotations, t, name); r = ref_decl_helper(a, decl); diff --git a/src/shady/compile.c b/src/shady/compile.c index 2f98ce91b..91e050f21 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -51,6 +51,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { add_scheduler_source(config, *pmod); } + RUN_PASS(eliminate_inlineable_constants) RUN_PASS(reconvergence_heuristics) RUN_PASS(lower_cf_instrs) diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 27a021fab..c85f601cc 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -8,6 +8,7 @@ typedef struct { Rewriter rewriter; BodyBuilder* bb; + bool all; } Context; static const Node* process(Context* ctx, const Node* node) { @@ -27,6 +28,8 @@ static const Node* process(Context* ctx, const Node* node) { case Constant_TAG: if (!node->payload.constant.instruction) break; + if (!ctx->all && !lookup_annotation(node, "Inline")) + break; return NULL; case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; @@ -57,15 +60,24 @@ static const Node* process(Context* ctx, const Node* node) { return new; } -Module* eliminate_constants(SHADY_UNUSED const CompilerConfig* config, Module* src) { +static Module* eliminate_constants_(SHADY_UNUSED const CompilerConfig* config, Module* src, bool all) { ArenaConfig aconfig = get_arena_config(get_module_arena(src)); IrArena* a = new_ir_arena(aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process) + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .all = all, }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); return dst; } + +Module* eliminate_constants(const CompilerConfig* config, Module* src) { + return eliminate_constants_(config, src, true); +} + +Module* eliminate_inlineable_constants(const CompilerConfig* config, Module* src) { + return eliminate_constants_(config, src, false); +} diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 89b32ea53..f11be63dc 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -107,6 +107,8 @@ RewritePass lower_nullptr; /// Eliminates all Constant decls RewritePass eliminate_constants; +/// Ditto but for @Inline ones only +RewritePass eliminate_inlineable_constants; /// Tags all functions that don't need special handling RewritePass mark_leaf_functions; /// In addition, also inlines function calls according to heuristics From 5dd9a5198fc66eaa7b40d92efc8955d106812051 Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 17:25:17 +0000 Subject: [PATCH 285/693] fold: deal with LEAs that don't do anything --- src/shady/fold.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/shady/fold.c b/src/shady/fold.c index 39bba12a7..a0b35f65c 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -201,6 +201,18 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { src_as = get_unqualified_type(ptr->type)->payload.ptr_type.address_space; continue; } + case lea_op: { + Nodes ops = instruction.operands; + for (size_t i = 1; i < ops.count; i++) { + if (!is_zero(ops.nodes[i])) + goto outer_break; + } + distance++; + ptr = first(ops); + continue; + outer_break: + break; + } default: break; } break; From 02fcc583bee2171b1b6a2f54a37369e40974724b Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 17:33:53 +0000 Subject: [PATCH 286/693] fix annotation processing on Clang 15 --- include/shady/ir.h | 1 + src/frontends/llvm/l2s_annotations.c | 4 +- src/shady/node.c | 75 +++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index cbb820626..987d82e96 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -164,6 +164,7 @@ typedef struct { bool assume_globals_immutability; } NodeResolveConfig; NodeResolveConfig default_node_resolve_config(); +const Node* chase_ptr_to_source(const Node*, NodeResolveConfig config); const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config); /// Resolves a variable to the instruction that produces its value (if any) diff --git a/src/frontends/llvm/l2s_annotations.c b/src/frontends/llvm/l2s_annotations.c index b38debd06..5a30e9bee 100644 --- a/src/frontends/llvm/l2s_annotations.c +++ b/src/frontends/llvm/l2s_annotations.c @@ -72,7 +72,7 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { // both of those assumptions are hacky but this front-end is a hacky deal anyways. resolve_config.assume_globals_immutability = true; resolve_config.allow_incompatible_types = true; - const char* ostr = get_string_literal(a, resolve_node_to_definition(annotation_payload, resolve_config)); + const char* ostr = get_string_literal(a, chase_ptr_to_source(annotation_payload, resolve_config)); char* str = calloc(strlen(ostr) + 1, 1); memcpy(str, ostr, strlen(ostr) + 1); if (strcmp(strtok(str, "::"), "shady") == 0) { @@ -145,4 +145,4 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { free(str); //dump_node(annotation_payload); } -} \ No newline at end of file +} diff --git a/src/shady/node.c b/src/shady/node.c index 94709d4f3..500cbf047 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -79,6 +79,58 @@ const Node* get_quoted_value(const Node* instruction) { return NULL; } +static bool is_zero(const Node* node) { + const IntLiteral* lit = resolve_to_int_literal(node); + if (lit && get_int_literal_value(*lit, false) == 0) + return true; + return false; +} + +const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { + while (true) { + ptr = resolve_node_to_definition(ptr, config); + switch (ptr->tag) { + case PrimOp_TAG: { + switch (ptr->payload.prim_op.op) { + case convert_op: { + // chase generic pointers to their source + if (first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { + ptr = first(ptr->payload.prim_op.operands); + continue; + } + break; + } + case reinterpret_op: { + // chase ptr casts to their source + // TODO: figure out round-trips through integer casts? + if (first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { + ptr = first(ptr->payload.prim_op.operands); + continue; + } + break; + } + case lea_op: { + Nodes ops = ptr->payload.prim_op.operands; + for (size_t i = 1; i < ops.count; i++) { + if (!is_zero(ops.nodes[i])) + goto outer_break; + } + ptr = first(ops); + continue; + outer_break: + break; + } + default: break; + } + break; + } + default: break; + } + break; + } + return ptr; +} + const Node* resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config) { while (ptr) { ptr = resolve_node_to_definition(ptr, config); @@ -131,6 +183,15 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi node = def; continue; } + case Block_TAG: { + const Node* terminator = node->payload.block.inside->payload.case_.body; + while (terminator->tag == Let_TAG) { + terminator = terminator->payload.let.tail->payload.case_.body; + } + assert(terminator->tag == Yield_TAG); + assert(terminator->payload.yield.args.count == 1); + return resolve_node_to_definition(first(terminator->payload.yield.args), config); + } case PrimOp_TAG: { switch (node->payload.prim_op.op) { case quote_op: { @@ -183,16 +244,16 @@ const FloatLiteral* resolve_to_float_literal(const Node* node) { return NULL; } -static bool is_zero(const Node* node) { - const IntLiteral* lit = resolve_to_int_literal(node); - if (lit && get_int_literal_value(*lit, false) == 0) - return true; - return false; -} - const char* get_string_literal(IrArena* arena, const Node* node) { if (!node) return NULL; + if (node->type && get_unqualified_type(node->type)->tag == PtrType_TAG) { + NodeResolveConfig nrc = default_node_resolve_config(); + const Node* ptr = chase_ptr_to_source(node, nrc); + const Node* value = resolve_ptr_to_value(ptr, nrc); + if (value) + return get_string_literal(arena, value); + } switch (node->tag) { case Declaration_GlobalVariable_TAG: { const Node* init = node->payload.global_variable.init; From eba0123c48f06cfe680029cc2fdd9c0bf18544e8 Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 18:43:17 +0000 Subject: [PATCH 287/693] move backend declarations out of ir.h --- include/shady/be/c.h | 23 +++++++++++++++++++++++ include/shady/be/dump.h | 8 ++++++++ include/shady/be/spirv.h | 9 +++++++++ include/shady/driver.h | 3 +++ include/shady/ir.h | 21 --------------------- src/driver/driver.c | 3 +++ src/shady/emit/c/emit_c.h | 2 ++ src/shady/emit/spirv/emit_spv.h | 2 ++ 8 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 include/shady/be/c.h create mode 100644 include/shady/be/dump.h create mode 100644 include/shady/be/spirv.h diff --git a/include/shady/be/c.h b/include/shady/be/c.h new file mode 100644 index 000000000..13e1ad1a1 --- /dev/null +++ b/include/shady/be/c.h @@ -0,0 +1,23 @@ +#ifndef SHD_BE_C_H +#define SHD_BE_C_H + +#include "shady/ir.h" + +typedef enum { + CDialect_C11, + CDialect_GLSL, + CDialect_ISPC, + CDialect_CUDA, +} CDialect; + +typedef struct { + CDialect dialect; + bool explicitly_sized_types; + bool allow_compound_literals; + bool decay_unsized_arrays; +} CEmitterConfig; + +void emit_c(CompilerConfig compiler_config, CEmitterConfig emitter_config, Module*, size_t* output_size, char** output, Module** new_mod); + +#endif + diff --git a/include/shady/be/dump.h b/include/shady/be/dump.h new file mode 100644 index 000000000..350c5b1a4 --- /dev/null +++ b/include/shady/be/dump.h @@ -0,0 +1,8 @@ +#ifndef SHD_BE_DUMP_H +#define SHD_BE_DUMP_H + +void dump_cfgs(FILE* output, Module* mod); +void dump_loop_trees(FILE* output, Module* mod); + +#endif + diff --git a/include/shady/be/spirv.h b/include/shady/be/spirv.h new file mode 100644 index 000000000..9d0806363 --- /dev/null +++ b/include/shady/be/spirv.h @@ -0,0 +1,9 @@ +#ifndef SHD_BE_SPIRV_H +#define SHD_BE_SPIRV_H + +#include "shady/ir.h" + +void emit_spirv(CompilerConfig* config, Module*, size_t* output_size, char** output, Module** new_mod); + +#endif + diff --git a/include/shady/driver.h b/include/shady/driver.h index b89e96462..b63eea776 100644 --- a/include/shady/driver.h +++ b/include/shady/driver.h @@ -3,6 +3,9 @@ #include "shady/ir.h" +#include "shady/be/c.h" +#include "shady/be/spirv.h" + struct List; typedef enum { diff --git a/include/shady/ir.h b/include/shady/ir.h index 987d82e96..b4572094a 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -343,27 +343,6 @@ void link_module(Module* dst, Module* src); //////////////////////////////// Emission //////////////////////////////// -void emit_spirv(CompilerConfig* config, Module*, size_t* output_size, char** output, Module** new_mod); - -typedef enum { - CDialect_C11, - CDialect_GLSL, - CDialect_ISPC, - CDialect_CUDA, -} CDialect; - -typedef struct { - CDialect dialect; - bool explicitly_sized_types; - bool allow_compound_literals; - bool decay_unsized_arrays; -} CEmitterConfig; - -void emit_c(CompilerConfig compiler_config, CEmitterConfig emitter_config, Module*, size_t* output_size, char** output, Module** new_mod); - -void dump_cfgs(FILE* output, Module* mod); -void dump_loop_trees(FILE* output, Module* mod); - void free_output(char* output); #endif diff --git a/src/driver/driver.c b/src/driver/driver.c index 4eeba9344..057f1aa55 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -1,6 +1,9 @@ #include "shady/ir.h" #include "shady/driver.h" +#include "shady/be/c.h" +#include "shady/be/spirv.h" +#include "shady/be/dump.h" #include "shady/print.h" #include "frontends/slim/parser.h" diff --git a/src/shady/emit/c/emit_c.h b/src/shady/emit/c/emit_c.h index 2f2d031f9..a5b74ef3c 100644 --- a/src/shady/emit/c/emit_c.h +++ b/src/shady/emit/c/emit_c.h @@ -3,6 +3,8 @@ #include "shady/ir.h" #include "shady/builtins.h" +#include "shady/be/c.h" + #include "growy.h" #include "arena.h" #include "printer.h" diff --git a/src/shady/emit/spirv/emit_spv.h b/src/shady/emit/spirv/emit_spv.h index 3c0dca14f..a7afd276b 100644 --- a/src/shady/emit/spirv/emit_spv.h +++ b/src/shady/emit/spirv/emit_spv.h @@ -2,6 +2,8 @@ #define SHADY_EMIT_SPIRV_H #include "shady/ir.h" +#include "shady/be/spirv.h" + #include "spirv_builder.h" typedef SpvbFileBuilder* FileBuilder; From 397c29f1768d9c644a7d35df3e7e3db9e0207c8e Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 20:12:09 +0000 Subject: [PATCH 288/693] moved configuration structs to config.h --- include/shady/be/c.h | 3 +- include/shady/be/spirv.h | 3 +- include/shady/config.h | 123 ++++++++++ include/shady/driver.h | 7 + include/shady/grammar.h | 91 -------- include/shady/ir.h | 215 +++++++----------- samples/checkerboard/checkerboard.c | 3 +- src/driver/driver.c | 6 +- src/driver/slim.c | 3 +- src/driver/vcc.c | 2 +- src/frontends/llvm/l2s.c | 4 +- src/frontends/llvm/l2s.h | 1 + src/frontends/llvm/l2s_private.h | 3 + src/frontends/slim/parser.c | 10 +- src/frontends/slim/parser.h | 1 + src/frontends/spirv/s2s.c | 3 +- src/frontends/spirv/s2s.h | 1 + src/runtime/runtime_test.c | 3 +- src/shady/analysis/verify.h | 1 + src/shady/config.c | 3 +- src/shady/emit/c/emit_c.c | 16 +- src/shady/emit/spirv/emit_spv.c | 14 +- src/shady/ir.c | 8 +- src/shady/ir_private.h | 2 +- src/shady/passes/bind.c | 11 +- src/shady/passes/cleanup.c | 14 +- src/shady/passes/eliminate_constants.c | 7 +- src/shady/passes/import.c | 11 +- src/shady/passes/infer.c | 13 +- src/shady/passes/lift_indirect_targets.c | 21 +- src/shady/passes/lower_alloca.c | 17 +- src/shady/passes/lower_callf.c | 12 +- src/shady/passes/lower_cf_instrs.c | 13 +- src/shady/passes/lower_decay_ptrs.c | 13 +- src/shady/passes/lower_entrypoint_args.c | 15 +- src/shady/passes/lower_fill.c | 13 +- src/shady/passes/lower_generic_globals.c | 13 +- src/shady/passes/lower_generic_ptrs.c | 17 +- src/shady/passes/lower_int64.c | 13 +- src/shady/passes/lower_lea.c | 7 +- src/shady/passes/lower_mask.c | 13 +- src/shady/passes/lower_memcpy.c | 7 +- src/shady/passes/lower_memory_layout.c | 8 +- src/shady/passes/lower_nullptr.c | 15 +- src/shady/passes/lower_physical_ptrs.c | 14 +- src/shady/passes/lower_stack.c | 17 +- src/shady/passes/lower_subgroup_ops.c | 15 +- src/shady/passes/lower_subgroup_vars.c | 13 +- src/shady/passes/lower_switch_btree.c | 13 +- src/shady/passes/lower_tailcalls.c | 14 +- src/shady/passes/lower_vec_arr.c | 7 +- src/shady/passes/lower_workgroups.c | 11 +- src/shady/passes/mark_leaf_functions.c | 16 +- src/shady/passes/normalize.c | 11 +- src/shady/passes/normalize_builtins.c | 13 +- src/shady/passes/opt_demote_alloca.c | 17 +- src/shady/passes/opt_inline.c | 17 +- src/shady/passes/opt_mem2reg.c | 21 +- src/shady/passes/opt_restructure.c | 17 +- src/shady/passes/opt_stack.c | 7 +- src/shady/passes/pass.h | 11 + src/shady/passes/passes.h | 5 +- src/shady/passes/reconvergence_heuristics.c | 19 +- src/shady/passes/setup_stack_frames.c | 17 +- src/shady/passes/simt2d.c | 7 +- src/shady/passes/specialize_entry_point.c | 13 +- src/shady/passes/specialize_execution_model.c | 13 +- src/shady/passes/spirv_lift_globals_ssbo.c | 13 +- src/shady/passes/spirv_map_entrypoint_args.c | 13 +- src/shady/transform/internal_constants.h | 1 + test/test_math.c | 10 +- 71 files changed, 557 insertions(+), 567 deletions(-) create mode 100644 include/shady/config.h delete mode 100644 include/shady/grammar.h create mode 100644 src/shady/passes/pass.h diff --git a/include/shady/be/c.h b/include/shady/be/c.h index 13e1ad1a1..9e4e8d75e 100644 --- a/include/shady/be/c.h +++ b/include/shady/be/c.h @@ -17,7 +17,8 @@ typedef struct { bool decay_unsized_arrays; } CEmitterConfig; -void emit_c(CompilerConfig compiler_config, CEmitterConfig emitter_config, Module*, size_t* output_size, char** output, Module** new_mod); +typedef struct CompilerConfig_ CompilerConfig; +void emit_c(const CompilerConfig* compiler_config, CEmitterConfig emitter_config, Module*, size_t* output_size, char** output, Module** new_mod); #endif diff --git a/include/shady/be/spirv.h b/include/shady/be/spirv.h index 9d0806363..46795dc73 100644 --- a/include/shady/be/spirv.h +++ b/include/shady/be/spirv.h @@ -3,7 +3,8 @@ #include "shady/ir.h" -void emit_spirv(CompilerConfig* config, Module*, size_t* output_size, char** output, Module** new_mod); +typedef struct CompilerConfig_ CompilerConfig; +void emit_spirv(const CompilerConfig* config, Module*, size_t* output_size, char** output, Module** new_mod); #endif diff --git a/include/shady/config.h b/include/shady/config.h new file mode 100644 index 000000000..1be7692c6 --- /dev/null +++ b/include/shady/config.h @@ -0,0 +1,123 @@ +#ifndef SHD_CONFIG_H +#define SHD_CONFIG_H + +#include "shady/ir.h" + +typedef struct { + IntSizes ptr_size; + /// The base type for emulated memory + IntSizes word_size; +} PointerModel; + +typedef struct { + PointerModel memory; +} TargetConfig; + +TargetConfig default_target_config(); + +typedef struct ArenaConfig_ ArenaConfig; +struct ArenaConfig_ { + bool name_bound; + bool check_op_classes; + bool check_types; + bool allow_fold; + bool validate_builtin_types; // do @Builtins variables need to match their type in builtins.h ? + bool is_simt; + + struct { + bool physical; + bool allowed; + } address_spaces[NumAddressSpaces]; + + struct { + /// Selects which type the subgroup intrinsic primops use to manipulate masks + enum { + /// Uses the MaskType + SubgroupMaskAbstract, + /// Uses a 64-bit integer + SubgroupMaskInt64 + } subgroup_mask_representation; + + uint32_t workgroup_size[3]; + } specializations; + + PointerModel memory; + + /// 'folding' optimisations - happen in the constructors directly + struct { + bool delete_unreachable_structured_cases; + bool weaken_non_leaking_allocas; + } optimisations; +}; + +ArenaConfig default_arena_config(const TargetConfig* target); + +typedef struct CompilerConfig_ CompilerConfig; +struct CompilerConfig_ { + bool dynamic_scheduling; + uint32_t per_thread_stack_size; + + struct { + uint8_t major; + uint8_t minor; + } target_spirv_version; + + struct { + bool emulate_generic_ptrs; + bool emulate_physical_memory; + + bool emulate_subgroup_ops; + bool emulate_subgroup_ops_extended_types; + bool simt_to_explicit_simd; + bool int64; + bool decay_ptrs; + } lower; + + struct { + bool spv_shuffle_instead_of_broadcast_first; + bool force_join_point_lifting; + bool restructure_everything; + bool recover_structure; + } hacks; + + struct { + struct { + bool after_every_pass; + bool delete_unused_instructions; + } cleanup; + bool inline_everything; + } optimisations; + + struct { + bool memory_accesses; + bool stack_accesses; + bool god_function; + bool stack_size; + bool subgroup_ops; + } printf_trace; + + struct { + int max_top_iterations; + } shader_diagnostics; + + struct { + bool print_generated, print_builtin, print_internal; + } logging; + + struct { + String entry_point; + ExecutionModel execution_model; + uint32_t subgroup_size; + } specialization; + + TargetConfig target; + + struct { + struct { void* uptr; void (*fn)(void*, String, Module*); } after_pass; + } hooks; +}; + +CompilerConfig default_compiler_config(); + +#endif + diff --git a/include/shady/driver.h b/include/shady/driver.h index b63eea776..81b067a29 100644 --- a/include/shady/driver.h +++ b/include/shady/driver.h @@ -2,6 +2,7 @@ #define SHADY_CLI #include "shady/ir.h" +#include "shady/config.h" #include "shady/be/c.h" #include "shady/be/spirv.h" @@ -70,4 +71,10 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv); ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod); ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod); +typedef enum CompilationResult_ { + CompilationNoError +} CompilationResult; + +CompilationResult run_compiler_passes(CompilerConfig* config, Module** mod); + #endif diff --git a/include/shady/grammar.h b/include/shady/grammar.h deleted file mode 100644 index 1acb94015..000000000 --- a/include/shady/grammar.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef SHADY_IR_H -#error "do not include this file by itself, include shady/ir.h instead" -#endif - -typedef enum DivergenceQualifier_ { - Unknown, - Uniform, - Varying -} DivergenceQualifier; - -typedef enum { - NotSpecial, - /// for instructions with multiple yield values. Must be deconstructed by a let, cannot appear anywhere else - MultipleReturn, - /// Gets the 'Block' SPIR-V annotation, needed for UBO/SSBO variables - DecorateBlock -} RecordSpecialFlag; - -typedef enum { - IntTy8, - IntTy16, - IntTy32, - IntTy64, -} IntSizes; - -enum { - IntSizeMin = IntTy8, - IntSizeMax = IntTy64, -}; - -static inline int int_size_in_bytes(IntSizes s) { - switch (s) { - case IntTy8: return 1; - case IntTy16: return 2; - case IntTy32: return 4; - case IntTy64: return 8; - } -} - -typedef enum { - FloatTy16, - FloatTy32, - FloatTy64 -} FloatSizes; - -static inline int float_size_in_bytes(FloatSizes s) { - switch (s) { - case FloatTy16: return 2; - case FloatTy32: return 4; - case FloatTy64: return 8; - } -} - -#define EXECUTION_MODELS(EM) \ -EM(Compute, 1) \ -EM(Fragment, 0) \ -EM(Vertex, 0) \ - -typedef enum { - EmNone, -#define EM(name, _) Em##name, -EXECUTION_MODELS(EM) -#undef EM -} ExecutionModel; - -ExecutionModel execution_model_from_string(const char*); - -//////////////////////////////// Generated definitions //////////////////////////////// - -// see primops.json -#include "primops_generated.h" - -String get_primop_name(Op op); -bool has_primop_got_side_effects(Op op); - -// see grammar.json -#include "grammar_generated.h" - -extern const char* node_tags[]; -extern const bool node_type_has_payload[]; - -//////////////////////////////// Node categories //////////////////////////////// - -inline static bool is_nominal(const Node* node) { - NodeTag tag = node->tag; - if (node->tag == PrimOp_TAG && has_primop_got_side_effects(node->payload.prim_op.op)) - return true; - return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Param_TAG || tag == Variablez_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG; -} - -inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } diff --git a/include/shady/ir.h b/include/shady/ir.h index b4572094a..2cc1a93b0 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -57,65 +57,101 @@ String get_module_name(const Module*); Nodes get_module_declarations(const Module*); Node* get_declaration(const Module*, String); -//////////////////////////////// Grammar //////////////////////////////// +void link_module(Module* dst, Module* src); -// The language grammar is big enough that it deserve its own files +//////////////////////////////// Grammar //////////////////////////////// -#include "grammar.h" +// The bulk of the language grammar is defined through json files. +// We define some support enums here. + +typedef enum { + IntTy8, + IntTy16, + IntTy32, + IntTy64, +} IntSizes; + +enum { + IntSizeMin = IntTy8, + IntSizeMax = IntTy64, +}; + +static inline int int_size_in_bytes(IntSizes s) { + switch (s) { + case IntTy8: return 1; + case IntTy16: return 2; + case IntTy32: return 4; + case IntTy64: return 8; + } +} + +typedef enum { + FloatTy16, + FloatTy32, + FloatTy64 +} FloatSizes; + +static inline int float_size_in_bytes(FloatSizes s) { + switch (s) { + case FloatTy16: return 2; + case FloatTy32: return 4; + case FloatTy64: return 8; + } +} + +#define EXECUTION_MODELS(EM) \ +EM(Compute, 1) \ +EM(Fragment, 0) \ +EM(Vertex, 0) \ + +typedef enum { + EmNone, +#define EM(name, _) Em##name, +EXECUTION_MODELS(EM) +#undef EM +} ExecutionModel; + +ExecutionModel execution_model_from_string(const char*); + +typedef enum { + NotSpecial, + /// for instructions with multiple yield values. Must be deconstructed by a let, cannot appear anywhere else + MultipleReturn, + /// Gets the 'Block' SPIR-V annotation, needed for UBO/SSBO variables + DecorateBlock +} RecordSpecialFlag; + +// see primops.json +#include "primops_generated.h" + +String get_primop_name(Op op); +bool has_primop_got_side_effects(Op op); + +// see grammar.json +#include "grammar_generated.h" + +extern const char* node_tags[]; +extern const bool node_type_has_payload[]; + +//////////////////////////////// Node categories //////////////////////////////// + +inline static bool is_nominal(const Node* node) { + NodeTag tag = node->tag; + if (node->tag == PrimOp_TAG && has_primop_got_side_effects(node->payload.prim_op.op)) + return true; + return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Param_TAG || tag == Variablez_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG; +} + +inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } //////////////////////////////// IR Arena //////////////////////////////// -typedef struct { - IntSizes ptr_size; - /// The base type for emulated memory - IntSizes word_size; -} PointerModel; - -typedef struct { - PointerModel memory; -} TargetConfig; - -TargetConfig default_target_config(); +/// See config.h for definition of ArenaConfig +typedef struct ArenaConfig_ ArenaConfig; -typedef struct { - bool name_bound; - bool check_op_classes; - bool check_types; - bool allow_fold; - bool validate_builtin_types; // do @Builtins variables need to match their type in builtins.h ? - bool is_simt; - - struct { - bool physical; - bool allowed; - } address_spaces[NumAddressSpaces]; - - struct { - /// Selects which type the subgroup intrinsic primops use to manipulate masks - enum { - /// Uses the MaskType - SubgroupMaskAbstract, - /// Uses a 64-bit integer - SubgroupMaskInt64 - } subgroup_mask_representation; - - uint32_t workgroup_size[3]; - } specializations; - - PointerModel memory; - - /// 'folding' optimisations - happen in the constructors directly - struct { - bool delete_unreachable_structured_cases; - bool weaken_non_leaking_allocas; - } optimisations; -} ArenaConfig; - -ArenaConfig default_arena_config(const TargetConfig* target); - -IrArena* new_ir_arena(ArenaConfig); +IrArena* new_ir_arena(const ArenaConfig*); void destroy_ir_arena(IrArena*); -ArenaConfig get_arena_config(const IrArena*); +const ArenaConfig* get_arena_config(const IrArena*); const Node* get_node_by_id(const IrArena*, NodeId); //////////////////////////////// Getters //////////////////////////////// @@ -266,81 +302,6 @@ const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder*, const Node*, const Nodes*); const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); -//////////////////////////////// Compilation //////////////////////////////// - -typedef struct CompilerConfig_ { - bool dynamic_scheduling; - uint32_t per_thread_stack_size; - - struct { - uint8_t major; - uint8_t minor; - } target_spirv_version; - - struct { - bool emulate_generic_ptrs; - bool emulate_physical_memory; - - bool emulate_subgroup_ops; - bool emulate_subgroup_ops_extended_types; - bool simt_to_explicit_simd; - bool int64; - bool decay_ptrs; - } lower; - - struct { - bool spv_shuffle_instead_of_broadcast_first; - bool force_join_point_lifting; - bool restructure_everything; - bool recover_structure; - } hacks; - - struct { - struct { - bool after_every_pass; - bool delete_unused_instructions; - } cleanup; - bool inline_everything; - } optimisations; - - struct { - bool memory_accesses; - bool stack_accesses; - bool god_function; - bool stack_size; - bool subgroup_ops; - } printf_trace; - - struct { - int max_top_iterations; - } shader_diagnostics; - - struct { - bool print_generated, print_builtin, print_internal; - } logging; - - struct { - String entry_point; - ExecutionModel execution_model; - uint32_t subgroup_size; - } specialization; - - TargetConfig target; - - struct { - struct { void* uptr; void (*fn)(void*, String, Module*); } after_pass; - } hooks; -} CompilerConfig; - -CompilerConfig default_compiler_config(); - -typedef enum CompilationResult_ { - CompilationNoError -} CompilationResult; - -CompilationResult run_compiler_passes(CompilerConfig* config, Module** mod); -void link_module(Module* dst, Module* src); - //////////////////////////////// Emission //////////////////////////////// void free_output(char* output); diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 052fd572e..da49bd95d 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -65,7 +65,8 @@ int main(int argc, char **argv) info_print("Device-side address is: %zu\n", buf_addr); - IrArena* a = new_ir_arena(default_arena_config(&compiler_config.target)); + ArenaConfig aconfig = default_arena_config(&compiler_config.target); + IrArena* a = new_ir_arena(&aconfig); Module* m; if (driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, "checkerboard", &m) != NoError) error("Failed to load checkerboard module"); diff --git a/src/driver/driver.c b/src/driver/driver.c index 057f1aa55..47d867746 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -164,15 +164,15 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { case TgtSPV: emit_spirv(&args->config, mod, &output_size, &output_buffer, NULL); break; case TgtC: args->c_emitter_config.dialect = CDialect_C11; - emit_c(args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); + emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; case TgtGLSL: args->c_emitter_config.dialect = CDialect_GLSL; - emit_c(args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); + emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; case TgtISPC: args->c_emitter_config.dialect = CDialect_ISPC; - emit_c(args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); + emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; } debug_print("Wrote result to %s\n", args->output_filename); diff --git a/src/driver/slim.c b/src/driver/slim.c index 95d399e60..ce98f783c 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -22,7 +22,8 @@ int main(int argc, char** argv) { cli_parse_compiler_config_args(&args.config, &argc, argv); cli_parse_input_files(args.input_filenames, &argc, argv); - IrArena* arena = new_ir_arena(default_arena_config(&args.config.target)); + ArenaConfig aconfig = default_arena_config(&args.config.target); + IrArena* arena = new_ir_arena(&aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one driver_load_source_files(&args, mod); diff --git a/src/driver/vcc.c b/src/driver/vcc.c index 9a82809a9..98dae5824 100644 --- a/src/driver/vcc.c +++ b/src/driver/vcc.c @@ -27,7 +27,7 @@ int main(int argc, char** argv) { } ArenaConfig aconfig = default_arena_config(&args.config.target); - IrArena* arena = new_ir_arena(aconfig); + IrArena* arena = new_ir_arena(&aconfig); vcc_check_clang(); diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index 3172c519c..12f595cc3 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -258,7 +258,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* aconfig.check_types = false; aconfig.allow_fold = false; - IrArena* arena = new_ir_arena(aconfig); + IrArena* arena = new_ir_arena(&aconfig); Module* dirty = new_module(arena, "dirty"); Parser p = { .ctx = context, @@ -291,7 +291,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* aconfig.check_types = true; aconfig.allow_fold = true; - IrArena* arena2 = new_ir_arena(aconfig); + IrArena* arena2 = new_ir_arena(&aconfig); *dst = new_module(arena2, name); postprocess(&p, dirty, *dst); log_module(DEBUG, config, *dst); diff --git a/src/frontends/llvm/l2s.h b/src/frontends/llvm/l2s.h index bdce5d35a..4e076224a 100644 --- a/src/frontends/llvm/l2s.h +++ b/src/frontends/llvm/l2s.h @@ -4,6 +4,7 @@ #include "shady/ir.h" #include +typedef struct CompilerConfig_ CompilerConfig; bool parse_llvm_into_shady(const CompilerConfig*, size_t len, const char* data, String name, Module** dst); #endif diff --git a/src/frontends/llvm/l2s_private.h b/src/frontends/llvm/l2s_private.h index 766a18f52..f530e2c96 100644 --- a/src/frontends/llvm/l2s_private.h +++ b/src/frontends/llvm/l2s_private.h @@ -2,6 +2,9 @@ #define SHADY_L2S_PRIVATE_H #include "l2s.h" + +#include "shady/config.h" + #include "arena.h" #include "util.h" diff --git a/src/frontends/slim/parser.c b/src/frontends/slim/parser.c index 188cd71c9..aac0de88a 100644 --- a/src/frontends/slim/parser.c +++ b/src/frontends/slim/parser.c @@ -14,6 +14,12 @@ #include #include +typedef enum DivergenceQualifier_ { + Unknown, + Uniform, + Varying +} DivergenceQualifier; + static int max_precedence() { return 10; } @@ -1123,7 +1129,7 @@ Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, co aconfig.check_types = false; aconfig.validate_builtin_types = false; aconfig.allow_fold = false; - IrArena* initial_arena = new_ir_arena(aconfig); + IrArena* initial_arena = new_ir_arena(&aconfig); Module* m = new_module(initial_arena, name); parse_shady_ir(pconfig, contents, m); Module** pmod = &m; @@ -1139,4 +1145,4 @@ Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, co destroy_ir_arena(initial_arena); return *pmod; -} \ No newline at end of file +} diff --git a/src/frontends/slim/parser.h b/src/frontends/slim/parser.h index c56785f1c..2dc9d6c7a 100644 --- a/src/frontends/slim/parser.h +++ b/src/frontends/slim/parser.h @@ -36,6 +36,7 @@ INFIX_OPERATORS() InfixOperatorsCount } InfixOperators; +typedef struct CompilerConfig_ CompilerConfig; Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name); #endif diff --git a/src/frontends/spirv/s2s.c b/src/frontends/spirv/s2s.c index 81d173f47..d0da6dda6 100644 --- a/src/frontends/spirv/s2s.c +++ b/src/frontends/spirv/s2s.c @@ -1357,7 +1357,8 @@ bool compare_spvid(SpvId* pa, SpvId* pb) { } S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { - IrArena* a = new_ir_arena(default_arena_config(&config->target)); + ArenaConfig aconfig = default_arena_config(&config->target); + IrArena* a = new_ir_arena(&aconfig); *dst = new_module(a, name); SpvParser parser = { diff --git a/src/frontends/spirv/s2s.h b/src/frontends/spirv/s2s.h index a05e98265..1f76f9376 100644 --- a/src/frontends/spirv/s2s.h +++ b/src/frontends/spirv/s2s.h @@ -8,6 +8,7 @@ typedef enum { S2S_FailedParsingGeneric, } S2SError; +typedef struct CompilerConfig_ CompilerConfig; S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const char* data, String name, Module**); #endif diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 64fb9afa0..447cc944d 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -48,7 +48,8 @@ int main(int argc, char* argv[]) { Program* program; IrArena* arena = NULL; - arena = new_ir_arena(default_arena_config(&args.driver_config.config.target)); + ArenaConfig aconfig = default_arena_config(&args.driver_config.config.target); + arena = new_ir_arena(&aconfig); if (entries_count_list(args.driver_config.input_filenames) == 0) { Module* module; driver_load_source_file(&args.driver_config.config, SrcSlim, strlen(default_shader), default_shader, "runtime_test", &module); diff --git a/src/shady/analysis/verify.h b/src/shady/analysis/verify.h index 2843ba802..0a65ff4d4 100644 --- a/src/shady/analysis/verify.h +++ b/src/shady/analysis/verify.h @@ -3,6 +3,7 @@ #include "shady/ir.h" +typedef struct CompilerConfig_ CompilerConfig; void verify_module(const CompilerConfig*, Module*); #endif diff --git a/src/shady/config.c b/src/shady/config.c index 902d47652..12b8161ef 100644 --- a/src/shady/config.c +++ b/src/shady/config.c @@ -1,4 +1,5 @@ #include "shady/ir.h" +#include "shady/config.h" #define KiB * 1024 #define MiB * 1024 KiB @@ -73,4 +74,4 @@ ArenaConfig default_arena_config(const TargetConfig* target) { } return config; -} \ No newline at end of file +} diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index fac1eed3b..5877e0671 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -1,5 +1,11 @@ #include "emit_c.h" +#include "../../type.h" +#include "../../ir_private.h" +#include "../../compile.h" + +#include "../../transform/ir_gen_helpers.h" + #include "shady_cuda_prelude_src.h" #include "shady_cuda_builtins_src.h" @@ -8,12 +14,6 @@ #include "log.h" #include "util.h" -#include "../../type.h" -#include "../../ir_private.h" -#include "../../compile.h" - -#include "../../transform/ir_gen_helpers.h" - #include #include #include @@ -732,9 +732,9 @@ static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { return printer_growy_unwrap(p); } -void emit_c(CompilerConfig compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod) { +void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod) { IrArena* initial_arena = get_module_arena(mod); - mod = run_backend_specific_passes(&compiler_config, &config, mod); + mod = run_backend_specific_passes(compiler_config, &config, mod); IrArena* arena = get_module_arena(mod); Growy* type_decls_g = new_growy(); diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index 184c55cf8..eada7d065 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -1,3 +1,9 @@ +#include "shady/builtins.h" +#include "../../ir_private.h" +#include "../../analysis/cfg.h" +#include "../../type.h" +#include "../../compile.h" + #include "list.h" #include "dict.h" #include "log.h" @@ -5,12 +11,6 @@ #include "growy.h" #include "util.h" -#include "shady/builtins.h" -#include "../../ir_private.h" -#include "../../analysis/cfg.h" -#include "../../type.h" -#include "../../compile.h" - #include "emit_spv.h" #include @@ -536,7 +536,7 @@ static Module* run_backend_specific_passes(CompilerConfig* config, Module* initi return *pmod; } -void emit_spirv(CompilerConfig* config, Module* mod, size_t* output_size, char** output, Module** new_mod) { +void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, char** output, Module** new_mod) { IrArena* initial_arena = get_module_arena(mod); mod = run_backend_specific_passes(config, mod); IrArena* arena = get_module_arena(mod); diff --git a/src/shady/ir.c b/src/shady/ir.c index d0c1a4ee0..e4e5509b0 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -22,11 +22,11 @@ bool compare_string(const char** a, const char** b); KeyHash hash_node(const Node**); bool compare_node(const Node** a, const Node** b); -IrArena* new_ir_arena(ArenaConfig config) { +IrArena* new_ir_arena(const ArenaConfig* config) { IrArena* arena = malloc(sizeof(IrArena)); *arena = (IrArena) { .arena = new_arena(), - .config = config, + .config = *config, .modules = new_list(Module*), @@ -60,8 +60,8 @@ void destroy_ir_arena(IrArena* arena) { free(arena); } -ArenaConfig get_arena_config(const IrArena* a) { - return a->config; +const ArenaConfig* get_arena_config(const IrArena* a) { + return &a->config; } NodeId allocate_node_id(IrArena* arena, const Node* n) { diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index 4e20799a4..f66007d1b 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -2,9 +2,9 @@ #define SHADY_IR_PRIVATE_H #include "shady/ir.h" +#include "shady/config.h" #include "arena.h" - #include "growy.h" #include "stdlib.h" diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index f20e1025d..cdac3b022 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -1,12 +1,11 @@ -#include "passes.h" +#include "pass.h" + +#include "../ir_private.h" #include "list.h" #include "log.h" #include "portability.h" -#include "../ir_private.h" -#include "../rewrite.h" - #include #include @@ -331,10 +330,10 @@ static const Node* bind_node(Context* ctx, const Node* node) { } Module* bind_program(SHADY_UNUSED const CompilerConfig* compiler_config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); assert(!src->arena->config.name_bound); aconfig.name_bound = true; - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 1dc2d3a19..6f59d96ac 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -1,12 +1,11 @@ -#include "passes.h" +#include "pass.h" -#include "portability.h" -#include "log.h" - -#include "../rewrite.h" #include "../analysis/uses.h" #include "../ir_private.h" +#include "portability.h" +#include "log.h" + typedef struct { Rewriter rewriter; const UsesMap* map; @@ -173,8 +172,11 @@ bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { return todo; } +OptPass opt_demote_alloca; +RewritePass import; + Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); if (!aconfig.check_types) return src; bool todo; diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index c85f601cc..139b98c80 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -1,6 +1,5 @@ -#include "passes.h" +#include "pass.h" -#include "../rewrite.h" #include "portability.h" #include "log.h" #include "dict.h" @@ -61,8 +60,8 @@ static const Node* process(Context* ctx, const Node* node) { } static Module* eliminate_constants_(SHADY_UNUSED const CompilerConfig* config, Module* src, bool all) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 79f62dd7a..98c4a6cac 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -1,10 +1,9 @@ -#include "passes.h" +#include "pass.h" -#include "portability.h" -#include "log.h" #include "../ir_private.h" -#include "../rewrite.h" +#include "portability.h" +#include "log.h" typedef struct { Rewriter rewriter; @@ -62,8 +61,8 @@ const Node* import_node(Rewriter* r, const Node* node) { } Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) recreate_node_identity), diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 2ddd96eb4..059af5e21 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -1,12 +1,11 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" +#include "pass.h" #include "../type.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + #include #include @@ -777,11 +776,11 @@ static const Node* process(Context* src_ctx, const Node* node) { } Module* infer_program(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); assert(!aconfig.check_types); aconfig.check_types = true; aconfig.allow_fold = true; // TODO was moved here because a refactor, does this cause issues ? - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 814a73878..da88d7e62 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -1,13 +1,6 @@ -#include "shady/ir.h" - -#include "log.h" -#include "portability.h" -#include "list.h" -#include "dict.h" -#include "util.h" +#include "pass.h" #include "../type.h" -#include "../rewrite.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -17,6 +10,12 @@ #include "../analysis/leak.h" #include "../analysis/verify.h" +#include "log.h" +#include "portability.h" +#include "list.h" +#include "dict.h" +#include "util.h" + #include #include @@ -229,7 +228,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); IrArena* a = NULL; Module* dst; @@ -237,7 +236,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { while (true) { debugv_print("lift_indirect_target: round %d\n", round++); IrArena* oa = a; - a = new_ir_arena(aconfig); + a = new_ir_arena(&aconfig); dst = new_module(a, get_module_name(src)); bool todo = false; Context ctx = { @@ -270,7 +269,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { // this will be safe now since we won't lift any more code after this pass aconfig.optimisations.weaken_non_leaking_allocas = true; - IrArena* a2 = new_ir_arena(aconfig); + IrArena* a2 = new_ir_arena(&aconfig); dst = new_module(a2, get_module_name(src)); Rewriter r = create_importer(src, dst); rewrite_module(&r); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index e26586003..4123c8233 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -1,4 +1,9 @@ -#include "passes.h" +#include "pass.h" + +#include "../visit.h" +#include "../type.h" +#include "../ir_private.h" +#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" @@ -6,12 +11,6 @@ #include "dict.h" #include "util.h" -#include "../rewrite.h" -#include "../visit.h" -#include "../type.h" -#include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" - #include typedef struct Context_ { @@ -171,8 +170,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 906647262..4cd45b3fc 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -1,12 +1,12 @@ -#include "passes.h" +#include "pass.h" -#include "../rewrite.h" #include "../type.h" -#include "log.h" -#include "portability.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + #include typedef uint32_t FnPtr; @@ -139,8 +139,8 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { } Module* lower_callf(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) lower_callf_process), diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index b392f5041..f28e51820 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -1,13 +1,12 @@ -#include "passes.h" +#include "pass.h" + +#include "../type.h" +#include "../analysis/cfg.h" #include "log.h" #include "portability.h" #include "dict.h" -#include "../type.h" -#include "../rewrite.h" -#include "../analysis/cfg.h" - #include typedef struct Context_ { @@ -258,8 +257,8 @@ KeyHash hash_node(const Node**); bool compare_node(const Node**, const Node**); Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index 4cc19f341..e043269c2 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -1,13 +1,12 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" +#include "pass.h" #include "../ir_private.h" #include "../type.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + typedef struct { Rewriter rewriter; const CompilerConfig* config; @@ -38,8 +37,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_decay_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 7dc7a2c6d..770238414 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -1,14 +1,13 @@ -#include "passes.h" +#include "pass.h" -#include "portability.h" -#include "log.h" -#include "util.h" - -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" #include "../transform/memory_layout.h" +#include "portability.h" +#include "log.h" +#include "util.h" + typedef struct { Rewriter rewriter; const CompilerConfig* config; @@ -95,8 +94,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_entrypoint_args(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index b441998fa..18f748ffe 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -1,13 +1,12 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" +#include "pass.h" #include "../ir_private.h" #include "../type.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + typedef struct { Rewriter rewriter; } Context; @@ -32,8 +31,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index dfdc6a992..1f91cfc8f 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -1,13 +1,12 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" +#include "pass.h" #include "../ir_private.h" #include "../type.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + typedef struct { Rewriter rewriter; } Context; @@ -39,8 +38,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_generic_globals(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index a0e49ea14..905f7a240 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -1,16 +1,15 @@ -#include "passes.h" +#include "pass.h" -#include "log.h" -#include "portability.h" -#include "util.h" -#include "dict.h" - -#include "../rewrite.h" #include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" #include "../transform/memory_layout.h" +#include "log.h" +#include "portability.h" +#include "util.h" +#include "dict.h" + #include typedef struct { @@ -252,8 +251,8 @@ KeyHash hash_string(const char** string); bool compare_string(const char** a, const char** b); Module* lower_generic_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 20db56856..ba0b23271 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -1,13 +1,12 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" +#include "pass.h" #include "../ir_private.h" #include "../type.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + typedef struct { Rewriter rewriter; const CompilerConfig* config; @@ -84,8 +83,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_int(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index be0055bb6..19a5aa22a 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -1,6 +1,5 @@ -#include "passes.h" +#include "pass.h" -#include "../rewrite.h" #include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -144,8 +143,8 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_lea(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 3a9b60d43..70a25c945 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -1,13 +1,12 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" +#include "pass.h" #include "../ir_private.h" #include "../type.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + typedef struct { Rewriter rewriter; const Node* zero; @@ -55,9 +54,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); aconfig.specializations.subgroup_mask_representation = SubgroupMaskInt64; - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); const Type* mask_type = get_actual_mask_type(a); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 8565241a6..87ff8148b 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -1,8 +1,7 @@ -#include "passes.h" +#include "pass.h" #include "../transform/ir_gen_helpers.h" #include "../transform/memory_layout.h" -#include "../rewrite.h" #include "../type.h" #include "../ir_private.h" @@ -126,8 +125,8 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_memcpy(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index e540c74fc..764cef768 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -1,11 +1,11 @@ -#include "passes.h" +#include "pass.h" #include "../transform/memory_layout.h" -#include "../rewrite.h" #include "../type.h" #include "log.h" #include "portability.h" + #include typedef struct { @@ -52,8 +52,8 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index fad776bab..2a7da8b6b 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -1,14 +1,13 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" -#include "dict.h" +#include "pass.h" #include "../ir_private.h" #include "../type.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" +#include "dict.h" + typedef struct { Rewriter rewriter; struct Dict* map; @@ -50,8 +49,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 360147f4b..4a51db570 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -1,16 +1,14 @@ -#include "passes.h" - -#include "../transform/ir_gen_helpers.h" -#include "../transform/memory_layout.h" +#include "pass.h" #include "../ir_private.h" -#include "../rewrite.h" #include "../type.h" +#include "../transform/ir_gen_helpers.h" +#include "../transform/memory_layout.h" + #include "log.h" #include "portability.h" #include "util.h" - #include "list.h" #include "dict.h" @@ -488,12 +486,12 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { } Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); aconfig.address_spaces[AsPrivate].physical = false; aconfig.address_spaces[AsShared].physical = false; aconfig.address_spaces[AsSubgroup].physical = false; - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index c54af1c32..9981cf100 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -1,4 +1,9 @@ -#include "passes.h" +#include "pass.h" + +#include "../type.h" +#include "../ir_private.h" + +#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" @@ -6,12 +11,6 @@ #include "dict.h" #include "util.h" -#include "../rewrite.h" -#include "../type.h" -#include "../ir_private.h" - -#include "../transform/ir_gen_helpers.h" - #include #include @@ -167,8 +166,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 26cdd35c3..1ce129041 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -1,14 +1,13 @@ -#include "passes.h" +#include "pass.h" -#include "portability.h" -#include "log.h" -#include "dict.h" - -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" #include "../transform/memory_layout.h" +#include "portability.h" +#include "log.h" +#include "dict.h" + typedef struct { Rewriter rewriter; const CompilerConfig* config; @@ -149,8 +148,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); assert(!config->lower.emulate_subgroup_ops && "TODO"); Context ctx = { diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index a69c4c6bd..20294bece 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -1,12 +1,11 @@ -#include "passes.h" +#include "pass.h" -#include "portability.h" -#include "log.h" - -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" +#include "portability.h" +#include "log.h" + typedef struct { Rewriter rewriter; const CompilerConfig* config; @@ -74,8 +73,8 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const } Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process), diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 390e5b788..90413136d 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -1,13 +1,12 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" +#include "pass.h" #include "../ir_private.h" #include "../type.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + typedef struct { Rewriter rewriter; @@ -187,8 +186,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_switch_btree(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 5aec81d10..6b8aff932 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -1,10 +1,5 @@ -#include "passes.h" +#include "pass.h" -#include "log.h" -#include "portability.h" -#include "util.h" - -#include "../rewrite.h" #include "../type.h" #include "../ir_private.h" @@ -13,6 +8,9 @@ #include "../analysis/leak.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" +#include "util.h" #include "list.h" #include "dict.h" @@ -416,8 +414,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); struct Dict* ptrs = new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 606b4f0b1..a301a8e1a 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -1,6 +1,5 @@ -#include "passes.h" +#include "pass.h" -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" @@ -55,9 +54,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_vec_arr(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); aconfig.validate_builtin_types = false; // TODO: hacky - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 9840d40f5..358c90a50 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -1,12 +1,11 @@ -#include "passes.h" - -#include "util.h" +#include "pass.h" #include "../ir_private.h" -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" +#include "util.h" + #include #include #include @@ -171,8 +170,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_workgroups(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index a057e6fdc..d277fde29 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -1,16 +1,14 @@ -#include "passes.h" - -#include "dict.h" -#include "portability.h" -#include "log.h" - -#include "../rewrite.h" +#include "pass.h" #include "../analysis/callgraph.h" #include "../analysis/cfg.h" #include "../analysis/uses.h" #include "../analysis/leak.h" +#include "dict.h" +#include "portability.h" +#include "log.h" + typedef struct { Rewriter rewriter; CallGraph* graph; @@ -166,8 +164,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index 7f1dc5cd9..ee8aa5042 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -1,11 +1,10 @@ -#include "shady/ir.h" +#include "pass.h" + +#include "../type.h" #include "log.h" #include "portability.h" -#include "../type.h" -#include "../rewrite.h" - #include typedef struct Context_ { @@ -140,9 +139,9 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); aconfig.check_op_classes = true; - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process_op), diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 1be5d1078..82358a86c 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -1,13 +1,12 @@ -#include "passes.h" - -#include "log.h" -#include "portability.h" +#include "pass.h" #include "../ir_private.h" -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" + typedef struct { Rewriter rewriter; Node** builtins; @@ -105,9 +104,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); aconfig.validate_builtin_types = true; - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index e941129bf..cf0ef5744 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -1,12 +1,5 @@ -#include "passes.h" +#include "pass.h" -#include "log.h" -#include "portability.h" -#include "list.h" -#include "dict.h" -#include "util.h" - -#include "../rewrite.h" #include "../visit.h" #include "../type.h" #include "../ir_private.h" @@ -14,6 +7,12 @@ #include "../analysis/uses.h" #include "../analysis/leak.h" +#include "log.h" +#include "portability.h" +#include "list.h" +#include "dict.h" +#include "util.h" + #include typedef struct Context_ { @@ -226,7 +225,7 @@ static const Node* process(Context* ctx, const Node* old) { ctx->todo |= true; return quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}))); } - if (!k->non_logical_use && get_arena_config(a).optimisations.weaken_non_leaking_allocas) { + if (!k->non_logical_use && get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { ctx->todo |= true; return prim_op_helper(a, alloca_logical_op, rewrite_nodes(&ctx->rewriter, payload.type_arguments), rewrite_nodes(r, payload.operands)); } diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 1fbace078..5fc36f923 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -1,4 +1,9 @@ -#include "passes.h" +#include "pass.h" + +#include "../type.h" +#include "../ir_private.h" + +#include "../analysis/callgraph.h" #include "dict.h" #include "list.h" @@ -6,12 +11,6 @@ #include "util.h" #include "log.h" -#include "../rewrite.h" -#include "../type.h" -#include "../ir_private.h" - -#include "../analysis/callgraph.h" - typedef struct { const Node* host_fn; const Node* return_jp; @@ -258,8 +257,8 @@ void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { } Module* opt_inline(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); opt_simplify_cf(config, src, dst); return dst; diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index c813e3baf..3895d7437 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -1,9 +1,7 @@ -#include "passes.h" +#include "pass.h" -#include "portability.h" -#include "dict.h" -#include "arena.h" -#include "log.h" +#include "../visit.h" +#include "../type.h" #include "../analysis/cfg.h" #include "../analysis/uses.h" @@ -12,9 +10,10 @@ #include "../transform/ir_gen_helpers.h" -#include "../rewrite.h" -#include "../visit.h" -#include "../type.h" +#include "portability.h" +#include "dict.h" +#include "arena.h" +#include "log.h" typedef struct { AddressSpace as; @@ -701,10 +700,12 @@ static const Node* process(Context* ctx, const Node* old) { return recreate_node_identity(&ctx->rewriter, old); } +RewritePass cleanup; + Module* opt_mem2reg(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); IrArena* initial_arena = get_module_arena(src); - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = src; for (size_t round = 0; round < 5; round++) { diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 173a83eab..ee1b5b665 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -1,16 +1,15 @@ -#include "passes.h" +#include "pass.h" -#include "dict.h" -#include "list.h" -#include "portability.h" -#include "log.h" - -#include "../rewrite.h" #include "../type.h" #include #include +#include "dict.h" +#include "list.h" +#include "portability.h" +#include "log.h" + #pragma GCC diagnostic error "-Wswitch" typedef struct { @@ -438,8 +437,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/opt_stack.c b/src/shady/passes/opt_stack.c index 80835702f..6c58019f6 100644 --- a/src/shady/passes/opt_stack.c +++ b/src/shady/passes/opt_stack.c @@ -1,6 +1,5 @@ -#include "passes.h" +#include "pass.h" -#include "../rewrite.h" #include "portability.h" #include "log.h" @@ -128,8 +127,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* opt_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/pass.h b/src/shady/passes/pass.h new file mode 100644 index 000000000..9a9ad2f6f --- /dev/null +++ b/src/shady/passes/pass.h @@ -0,0 +1,11 @@ +#ifndef SHD_PASS_H +#define SHD_PASS_H + +#include "shady/config.h" +#include "rewrite.h" + +typedef Module* (RewritePass)(const CompilerConfig* config, Module* src); +typedef bool (OptPass)(const CompilerConfig* config, Module** m); + +#endif + diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index f11be63dc..192cd9556 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -1,9 +1,7 @@ #ifndef SHADY_PASSES_H #include "shady/ir.h" - -typedef Module* (RewritePass)(const CompilerConfig* config, Module* src); -typedef bool (OptPass)(const CompilerConfig* config, Module** m); +#include "pass.h" /// @name Boring, regular compiler stuff /// @{ @@ -114,7 +112,6 @@ RewritePass mark_leaf_functions; /// In addition, also inlines function calls according to heuristics RewritePass opt_inline; RewritePass opt_mem2reg; -OptPass opt_demote_alloca; /// Try to identify reconvergence points throughout the program for unstructured control flow programs RewritePass reconvergence_heuristics; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index bc7168ddb..55c3bc3fd 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -1,13 +1,6 @@ -#include "shady/ir.h" - -#include "list.h" -#include "dict.h" -#include "log.h" -#include "portability.h" -#include "util.h" +#include "pass.h" #include "../type.h" -#include "../rewrite.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -15,6 +8,12 @@ #include "../analysis/looptree.h" #include "../analysis/free_variables.h" +#include "list.h" +#include "dict.h" +#include "log.h" +#include "portability.h" +#include "util.h" + #include typedef struct Context_ { @@ -544,8 +543,8 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 6e15c0a0b..7b106e42f 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -1,16 +1,15 @@ -#include "passes.h" +#include "pass.h" -#include "log.h" -#include "portability.h" -#include "list.h" -#include "util.h" - -#include "../rewrite.h" #include "../visit.h" #include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" +#include "log.h" +#include "portability.h" +#include "list.h" +#include "util.h" + #include typedef struct Context_ { @@ -61,8 +60,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c index f65f7923b..41caee457 100644 --- a/src/shady/passes/simt2d.c +++ b/src/shady/passes/simt2d.c @@ -1,7 +1,6 @@ -#include "passes.h" +#include "pass.h" #include "../type.h" -#include "../rewrite.h" #include "portability.h" #include "log.h" @@ -88,9 +87,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* simt2d(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); aconfig.is_simt = false; - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 9d7b7b007..d0d06205c 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -1,12 +1,11 @@ -#include "passes.h" - -#include "portability.h" -#include "log.h" +#include "pass.h" #include "../ir_private.h" -#include "../rewrite.h" #include "../transform/ir_gen_helpers.h" +#include "portability.h" +#include "log.h" + #include typedef struct { @@ -110,9 +109,9 @@ static void specialize_arena_config(const CompilerConfig* config, Module* src, A } Module* specialize_entry_point(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); specialize_arena_config(config, src, &aconfig); - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 595eb2b0f..59dd54fc0 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -1,13 +1,12 @@ -#include "passes.h" - -#include "portability.h" -#include "log.h" +#include "pass.h" #include "../ir_private.h" -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" +#include "portability.h" +#include "log.h" + #include typedef struct { @@ -46,9 +45,9 @@ static void specialize_arena_config(const CompilerConfig* config, Module* m, Are } Module* specialize_execution_model(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); specialize_arena_config(config, src, &aconfig); - IrArena* a = new_ir_arena(aconfig); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); size_t subgroup_size = config->specialization.subgroup_size; diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index 4d67023a8..eb0cb9e2e 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -1,13 +1,12 @@ -#include "passes.h" +#include "pass.h" -#include "portability.h" -#include "log.h" - -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" #include "../transform/memory_layout.h" +#include "portability.h" +#include "log.h" + typedef struct { Rewriter rewriter; const CompilerConfig* config; @@ -54,8 +53,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/spirv_map_entrypoint_args.c b/src/shady/passes/spirv_map_entrypoint_args.c index ebe9aa88b..401cc0263 100644 --- a/src/shady/passes/spirv_map_entrypoint_args.c +++ b/src/shady/passes/spirv_map_entrypoint_args.c @@ -1,13 +1,12 @@ -#include "passes.h" +#include "pass.h" -#include "portability.h" -#include "log.h" - -#include "../rewrite.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" #include "../transform/memory_layout.h" +#include "portability.h" +#include "log.h" + typedef struct { Rewriter rewriter; const CompilerConfig* config; @@ -63,8 +62,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* spirv_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(aconfig); + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/transform/internal_constants.h b/src/shady/transform/internal_constants.h index bf7f61a04..607eabcbc 100644 --- a/src/shady/transform/internal_constants.h +++ b/src/shady/transform/internal_constants.h @@ -7,6 +7,7 @@ X(SUBGROUP_SIZE, uint32_type(arena), uint32_literal(arena, 64)) \ X(SUBGROUPS_PER_WG, uint32_type(arena), uint32_literal(arena, 1)) \ +typedef struct CompilerConfig_ CompilerConfig; void generate_dummy_constants(const CompilerConfig* config, Module*); #endif diff --git a/test/test_math.c b/test/test_math.c index 9db08a674..0cbc1d2f8 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -92,10 +92,10 @@ int main(int argc, char** argv) { cli_parse_common_args(&argc, argv); TargetConfig target_config = default_target_config(); - ArenaConfig acfg = default_arena_config(&target_config); - acfg.check_types = true; - acfg.allow_fold = true; - IrArena* a = new_ir_arena(acfg); + ArenaConfig aconfig = default_arena_config(&target_config); + aconfig.check_types = true; + aconfig.allow_fold = true; + IrArena* a = new_ir_arena(&aconfig); test_int_literals(a); destroy_ir_arena(a); -} \ No newline at end of file +} From 5eb9930efb0ab24c2e17d6ce441f709fdcbfead6 Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 20:38:31 +0000 Subject: [PATCH 289/693] fix gcc warnings --- src/frontends/llvm/l2s_instr.c | 4 ++-- src/frontends/llvm/l2s_postprocess.c | 6 +++--- src/shady/api/generator_grammar.c | 2 +- src/shady/emit/c/emit_c.c | 2 +- src/shady/emit/spirv/emit_spv.c | 2 +- src/shady/emit/spirv/emit_spv.h | 2 +- src/shady/generator/import_spv_defs.c | 6 +++--- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index d0cdf7610..e80bd999f 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -57,7 +57,7 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef dst) { IrArena* a = fn_or_bb->arena; - const Node* wrapper_bb = basic_block(a, fn_ctx->fn, empty(a), NULL); + Node* wrapper_bb = basic_block(a, fn_ctx->fn, empty(a), NULL); JumpTodo todo = { .wrapper = wrapper_bb, .src = fn_or_bb, @@ -65,7 +65,7 @@ static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_ }; append_list(JumpTodo, fn_ctx->jumps_todo, todo); const Node* dst2 = convert_basic_block(p, fn_ctx, dst); - insert_dict(const Node*, const Node*, p->wrappers_map, wrapper_bb, dst2); + insert_dict(Node*, const Node*, p->wrappers_map, wrapper_bb, dst2); return jump_helper(a, wrapper_bb, empty(a)); } diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontends/llvm/l2s_postprocess.c index 5cab11681..2266ecabf 100644 --- a/src/frontends/llvm/l2s_postprocess.c +++ b/src/frontends/llvm/l2s_postprocess.c @@ -100,7 +100,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, }); } case Constant_TAG: { - Node* new = recreate_node_identity(r, node); + Node* new = (Node*) recreate_node_identity(r, node); BodyBuilder* bb = begin_body(a); const Node* value = first(bind_instruction(bb, new->payload.constant.instruction)); value = first(bind_instruction(bb, prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)))); @@ -239,11 +239,11 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } Nodes nparams = remake_params(ctx, get_abstraction_params(dst)); //register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); - Node* fn = src; + Node* fn = (Node*) src; if (fn->tag == BasicBlock_TAG) fn = (Node*) fn->payload.basic_block.fn; assert(fn->tag == Function_TAG); - fn = rewrite_node(r, fn); + fn = (Node*) rewrite_node(r, fn); Node* wrapper = basic_block(a, fn, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); wrapper->payload.basic_block.body = join(a, (Join) { .args = nparams, diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 0e8250696..f36253460 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -156,7 +156,7 @@ void generate(Growy* g, json_object* src) { String capitalized = capitalize(name); generate_node_tags_for_class(g, nodes, name, capitalized); growy_append_formatted(g, "%sTag is_%s(const Node*);\n", capitalized, name); - free(capitalized); + free((void*) capitalized); } else { growy_append_formatted(g, "bool is_%s(const Node*);\n", name); } diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 5877e0671..2242f1eff 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -687,7 +687,7 @@ CType* lookup_existing_type(Emitter* emitter, const Type* node) { KeyHash hash_node(Node**); bool compare_node(Node**, Node**); -static Module* run_backend_specific_passes(CompilerConfig* config, CEmitterConfig* econfig, Module* initial_mod) { +static Module* run_backend_specific_passes(const CompilerConfig* config, CEmitterConfig* econfig, Module* initial_mod) { IrArena* initial_arena = initial_mod->arena; Module** pmod = &initial_mod; diff --git a/src/shady/emit/spirv/emit_spv.c b/src/shady/emit/spirv/emit_spv.c index eada7d065..ac26d7de4 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/shady/emit/spirv/emit_spv.c @@ -523,7 +523,7 @@ bool compare_node(Node**, Node**); KeyHash hash_string(const char** string); bool compare_string(const char** a, const char** b); -static Module* run_backend_specific_passes(CompilerConfig* config, Module* initial_mod) { +static Module* run_backend_specific_passes(const CompilerConfig* config, Module* initial_mod) { IrArena* initial_arena = initial_mod->arena; Module** pmod = &initial_mod; diff --git a/src/shady/emit/spirv/emit_spv.h b/src/shady/emit/spirv/emit_spv.h index a7afd276b..03bf4ee6c 100644 --- a/src/shady/emit/spirv/emit_spv.h +++ b/src/shady/emit/spirv/emit_spv.h @@ -13,7 +13,7 @@ typedef SpvbBasicBlockBuilder* BBBuilder; typedef struct Emitter_ { Module* module; IrArena* arena; - CompilerConfig* configuration; + const CompilerConfig* configuration; FileBuilder file_builder; SpvId void_t; struct Dict* node_ids; diff --git a/src/shady/generator/import_spv_defs.c b/src/shady/generator/import_spv_defs.c index 75908993d..3b6318008 100644 --- a/src/shady/generator/import_spv_defs.c +++ b/src/shady/generator/import_spv_defs.c @@ -188,9 +188,9 @@ json_object* import_operand(json_object* operand, json_object* instruction_filte json_object* field = json_object_new_object(); - char* field_name = sanitize_field_name(name); + const char* field_name = sanitize_field_name(name); json_object_object_add(field, "name", json_object_new_string(field_name)); - free(field_name); + free((void*) field_name); json_object* insert = json_object_object_get(filter, "overlay"); if (insert) { @@ -237,7 +237,7 @@ json_object* import_filtered_instruction(json_object* instruction, json_object* else json_object_put(ops); - free(node_name); + free((void*) node_name); return node; } From ed2ec29d3acc21fca92a1a53b527936c52564e5d Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 20:50:11 +0000 Subject: [PATCH 290/693] removed common codegen code --- include/shady/ir.h | 4 ---- src/shady/emit/CMakeLists.txt | 3 --- src/shady/emit/common.c | 5 ----- 3 files changed, 12 deletions(-) delete mode 100644 src/shady/emit/common.c diff --git a/include/shady/ir.h b/include/shady/ir.h index 2cc1a93b0..ba22ae075 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -302,8 +302,4 @@ const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder*, const Node*, const Nodes*); const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); -//////////////////////////////// Emission //////////////////////////////// - -void free_output(char* output); - #endif diff --git a/src/shady/emit/CMakeLists.txt b/src/shady/emit/CMakeLists.txt index 9be2855c0..2acd53267 100644 --- a/src/shady/emit/CMakeLists.txt +++ b/src/shady/emit/CMakeLists.txt @@ -1,6 +1,3 @@ add_subdirectory(spirv) add_subdirectory(c) -add_library(shady_emit_common OBJECT - common.c -) diff --git a/src/shady/emit/common.c b/src/shady/emit/common.c deleted file mode 100644 index 2970f51ac..000000000 --- a/src/shady/emit/common.c +++ /dev/null @@ -1,5 +0,0 @@ -#include - -void free_output(char* output) { - free(output); -} \ No newline at end of file From 79bc282196927d9df6f68307586acc59d7ecaa5f Mon Sep 17 00:00:00 2001 From: Gob Date: Wed, 5 Jun 2024 20:50:28 +0000 Subject: [PATCH 291/693] fix Vulkan runtime backend --- src/runtime/cuda/cuda_runtime_program.c | 4 +++- src/runtime/vulkan/vk_runtime_program.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 828b3b60b..909c8be5a 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -1,5 +1,7 @@ #include "cuda_runtime_private.h" +#include "shady/driver.h" + #include "log.h" #include "portability.h" #include "dict.h" @@ -162,4 +164,4 @@ bool shd_cuda_destroy_specialized_kernel(CudaKernel* kernel) { free(kernel); return true; -} \ No newline at end of file +} diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index f8d0e314d..0b3efbd5a 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -1,5 +1,7 @@ #include "vk_runtime_private.h" +#include "shady/driver.h" + #include "log.h" #include "portability.h" #include "dict.h" @@ -165,7 +167,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay } for (size_t set = 0; set < MAX_DESCRIPTOR_SETS; set++) { - layouts[set] = NULL; + layouts[set] = 0; layout_create_infos[set].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layout_create_infos[set].flags = 0; layout_create_infos[set].pNext = NULL; From 94426492b749acf9b37cacb763a1bd8aeaddd60d Mon Sep 17 00:00:00 2001 From: Gob Date: Thu, 6 Jun 2024 11:08:56 +0000 Subject: [PATCH 292/693] added basic glsl 120 support --- include/shady/be/c.h | 3 +++ src/driver/cli.c | 5 +++++ src/shady/emit/c/emit_c.c | 21 +++++++++++++++------ src/shady/emit/c/emit_c.h | 5 +++++ src/shady/emit/c/emit_c_signatures.c | 21 ++++++++++++++------- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/include/shady/be/c.h b/include/shady/be/c.h index 9e4e8d75e..e36e05fb7 100644 --- a/include/shady/be/c.h +++ b/include/shady/be/c.h @@ -15,8 +15,11 @@ typedef struct { bool explicitly_sized_types; bool allow_compound_literals; bool decay_unsized_arrays; + int glsl_version; } CEmitterConfig; +CEmitterConfig default_c_emitter_config(void); + typedef struct CompilerConfig_ CompilerConfig; void emit_c(const CompilerConfig* compiler_config, CEmitterConfig emitter_config, Module*, size_t* output_size, char** output, Module** new_mod); diff --git a/src/driver/cli.c b/src/driver/cli.c index 8bd18762c..68b9235ae 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -211,6 +211,7 @@ DriverConfig default_driver_config() { .output_filename = NULL, .cfg_output_filename = NULL, .shd_output_filename = NULL, + .c_emitter_config = default_c_emitter_config(), }; } @@ -255,6 +256,10 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { exit(MissingDumpIrArg); } args->shd_output_filename = argv[i]; + } else if (strcmp(argv[i], "--glsl-version") == 0) { + argv[i] = NULL; + i++; + args->c_emitter_config.glsl_version = strtol(argv[i], NULL, 10); } else if (strcmp(argv[i], "--target") == 0) { argv[i] = NULL; i++; diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 2242f1eff..92dc6069b 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -159,8 +159,8 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S switch (as) { case AsShared: prefix = "shared "; break; case AsInput: - case AsUInput: prefix = "in "; break; - case AsOutput: prefix = "out "; break; + case AsUInput: prefix = emitter->config.glsl_version < 130 ? "varying " : "in "; break; + case AsOutput: prefix = emitter->config.glsl_version < 130 ? "varying " : "out "; break; case AsPrivate: prefix = ""; break; case AsUniformConstant: prefix = "uniform"; break; case AsGlobal: { @@ -220,7 +220,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { bool is_long = value->payload.int_literal.width == IntTy64; bool is_signed = value->payload.int_literal.is_signed; - if (emitter->config.dialect == CDialect_GLSL) { + if (emitter->config.dialect == CDialect_GLSL && emitter->config.glsl_version >= 130) { if (!is_signed) emitted = format_string_arena(emitter->arena->arena, "%sU", emitted); if (is_long) @@ -397,7 +397,8 @@ void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const T center = format_string_arena(emitter->arena->arena, "const %s", center); break; case CDialect_GLSL: - prefix = "const "; + if (emitter->config.glsl_version >= 130) + prefix = "const "; break; } @@ -732,6 +733,12 @@ static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { return printer_growy_unwrap(p); } +CEmitterConfig default_c_emitter_config(void) { + return (CEmitterConfig) { + .glsl_version = 420, + }; +} + void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod) { IrArena* initial_arena = get_module_arena(mod); mod = run_backend_specific_passes(compiler_config, &config, mod); @@ -742,6 +749,7 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module Growy* fn_defs_g = new_growy(); Emitter emitter = { + .compiler_config = compiler_config, .config = config, .arena = arena, .type_decls = open_growy_as_printer(type_decls_g), @@ -782,7 +790,7 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module Printer* finalp = open_growy_as_printer(final); if (emitter.config.dialect == CDialect_GLSL) { - print(finalp, "#version 420\n"); + print(finalp, "#version %d\n", emitter.config.glsl_version); } print(finalp, "/* file generated by shady */\n"); @@ -807,7 +815,8 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module print(finalp, "\n#include "); break; case CDialect_GLSL: - print(finalp, "#extension GL_ARB_gpu_shader_int64: require\n"); + if (emitter.need_64b_ext) + print(finalp, "#extension GL_ARB_gpu_shader_int64: require\n"); print(finalp, "#define ubyte uint\n"); print(finalp, "#define uchar uint\n"); print(finalp, "#define ulong uint\n"); diff --git a/src/shady/emit/c/emit_c.h b/src/shady/emit/c/emit_c.h index a5b74ef3c..70013b2bb 100644 --- a/src/shady/emit/c/emit_c.h +++ b/src/shady/emit/c/emit_c.h @@ -35,7 +35,10 @@ typedef struct { typedef Strings Phis; +typedef struct CompilerConfig_ CompilerConfig; + typedef struct { + const CompilerConfig* compiler_config; CEmitterConfig config; IrArena* arena; Printer *type_decls, *fn_decls, *fn_defs; @@ -49,6 +52,8 @@ typedef struct { int total_workgroup_size; bool use_private_globals; Printer* entrypoint_prelude; + + bool need_64b_ext; } Emitter; void register_emitted(Emitter*, const Node*, CTerm); diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/shady/emit/c/emit_c_signatures.c index 74b3df8b4..f98501968 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/shady/emit/c/emit_c_signatures.c @@ -143,6 +143,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { case NoRet_TAG: case Bool_TAG: emitted = "bool"; break; case Int_TAG: { + bool sign = type->payload.int_type.is_signed; switch (emitter->config.dialect) { case CDialect_ISPC: { const char* ispc_int_types[4][2] = { @@ -151,7 +152,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { { "uint32", "int32" }, { "uint64", "int64" }, }; - emitted = ispc_int_types[type->payload.int_type.width][type->payload.int_type.is_signed]; + emitted = ispc_int_types[type->payload.int_type.width][sign]; break; } case CDialect_CUDA: @@ -168,20 +169,26 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { { "uint32_t", "int32_t" }, { "uint64_t", "int64_t" }, }; - emitted = (emitter->config.explicitly_sized_types ? c_explicit_int_sizes : c_classic_int_types)[type->payload.int_type.width][type->payload.int_type.is_signed]; + emitted = (emitter->config.explicitly_sized_types ? c_explicit_int_sizes : c_classic_int_types)[type->payload.int_type.width][sign]; break; } case CDialect_GLSL: + if (emitter->config.glsl_version <= 120) { + emitted = "int"; + break; + } switch (type->payload.int_type.width) { case IntTy8: warn_print("vanilla GLSL does not support 8-bit integers\n"); - emitted = "ubyte"; + emitted = sign ? "byte" : "ubyte"; break; case IntTy16: warn_print("vanilla GLSL does not support 16-bit integers\n"); - emitted = "ushort"; + emitted = sign ? "short" : "ushort"; break; - case IntTy32: emitted = "uint"; break; - case IntTy64: warn_print("vanilla GLSL does not support 64-bit integers\n"); - emitted = "uint64_t"; + case IntTy32: emitted = sign ? "int" : "uint"; break; + case IntTy64: + emitter->need_64b_ext = true; + warn_print("vanilla GLSL does not support 64-bit integers\n"); + emitted = sign ? "int64_t" : "uint64_t"; break; } break; From 5f4f3fdc3e653cf74328cb42123d5aca235d0cc6 Mon Sep 17 00:00:00 2001 From: Gob Date: Thu, 6 Jun 2024 11:14:51 +0000 Subject: [PATCH 293/693] added some glsl 120 polyfills --- src/driver/cli.c | 2 +- src/shady/emit/c/CMakeLists.txt | 3 + src/shady/emit/c/emit_c.c | 3 + src/shady/emit/c/emit_c_instructions.c | 18 +++- src/shady/emit/c/glsl_120_polyfills.glsl | 117 +++++++++++++++++++++++ 5 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 src/shady/emit/c/glsl_120_polyfills.glsl diff --git a/src/driver/cli.c b/src/driver/cli.c index 68b9235ae..8d0998c69 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -300,4 +300,4 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { } cli_pack_remaining_args(pargc, argv); -} \ No newline at end of file +} diff --git a/src/shady/emit/c/CMakeLists.txt b/src/shady/emit/c/CMakeLists.txt index 4896b6d2f..b976e0f0b 100644 --- a/src/shady/emit/c/CMakeLists.txt +++ b/src/shady/emit/c/CMakeLists.txt @@ -18,4 +18,7 @@ embed_file(string shady_cuda_builtins_src cuda_builtins.cu) target_link_libraries(shady_c PRIVATE "$") target_link_libraries(shady_c PRIVATE "$") +embed_file(string shady_glsl_120_polyfills_src glsl_120_polyfills.glsl) +target_link_libraries(shady_c PRIVATE "$") + target_link_libraries(shady PUBLIC "$") diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 92dc6069b..650df7d61 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -8,6 +8,7 @@ #include "shady_cuda_prelude_src.h" #include "shady_cuda_builtins_src.h" +#include "shady_glsl_120_polyfills_src.h" #include "portability.h" #include "dict.h" @@ -820,6 +821,8 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module print(finalp, "#define ubyte uint\n"); print(finalp, "#define uchar uint\n"); print(finalp, "#define ulong uint\n"); + if (emitter.config.glsl_version <= 120) + print(finalp, shady_glsl_120_polyfills_src); break; } diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index 3fe4634fc..d88c8ea46 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -70,6 +70,8 @@ typedef struct { String f_ops[3]; } ISelTableEntry; +static const ISelTableEntry isel_dummy = { IsNone }; + static const ISelTableEntry isel_table[PRIMOPS_COUNT] = { [add_op] = { IsMono, OsInfix, "+" }, [sub_op] = { IsMono, OsInfix, "-" }, @@ -120,6 +122,15 @@ static const ISelTableEntry isel_table_glsl[PRIMOPS_COUNT] = { [pow_op] = { IsMono, OsCall, "pow" }, }; +static const ISelTableEntry isel_table_glsl_120[PRIMOPS_COUNT] = { + [mod_op] = { IsMono, OsCall, "mod" }, + + [and_op] = { IsMono, OsCall, "and" }, + [ or_op] = { IsMono, OsCall, "or" }, + [xor_op] = { IsMono, OsCall, "xor" }, + [not_op] = { IsMono, OsCall, "not" }, +}; + static const ISelTableEntry isel_table_ispc[PRIMOPS_COUNT] = { [abs_op] = { IsMono, OsCall, "abs" }, @@ -195,13 +206,18 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, Printer* p, const ISe } static const ISelTableEntry* lookup_entry(Emitter* emitter, Op op) { - const ISelTableEntry* isel_entry = NULL; + const ISelTableEntry* isel_entry = &isel_dummy; + switch (emitter->config.dialect) { case CDialect_CUDA: /* TODO: do better than that */ case CDialect_C11: isel_entry = &isel_table_c[op]; break; case CDialect_GLSL: isel_entry = &isel_table_glsl[op]; break; case CDialect_ISPC: isel_entry = &isel_table_ispc[op]; break; } + + if (emitter->config.dialect == CDialect_GLSL && emitter->config.glsl_version <= 120) + isel_entry = &isel_table_glsl_120[op]; + if (isel_entry->isel_mechanism == IsNone) isel_entry = &isel_table[op]; return isel_entry; diff --git a/src/shady/emit/c/glsl_120_polyfills.glsl b/src/shady/emit/c/glsl_120_polyfills.glsl new file mode 100644 index 000000000..d794ae47e --- /dev/null +++ b/src/shady/emit/c/glsl_120_polyfills.glsl @@ -0,0 +1,117 @@ +int mod(int a, int b) { + int q = a / b; + int qb = q * b; + return a - qb; +} + +int rshift1(int word) { + return word / 2; +} + +int lshift1(int word) { + int capped = mod(word, 32768); + return capped * 2; +} + +bool extract_bit(int word, int pos) { + int shifted = word; + for (int i = 0; i < pos; i++) { + shifted = rshift1(shifted); + } + return mod(shifted, 2) == 1; +} + +const int bits[16] = int[16](0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000); + +int set_bit(int word, int pos, bool value) { + int result = 0; + for (int i = 0; i < 16; i++) { + bool set; + if (i == pos) + set = value; + else + set = extract_bit(word, i); + if (set) + result += bits[i]; + } + return result; + //if (value) { + // return mod(unset + bits[pos], 65536); + //} + //return unset; +} + +int and(int a, int b) { + int shifteda = a; + int shiftedb = b; + int result = 0; + for (int i = 0; i < 16; i++) { + bool ba = mod(shifteda, 2) == 1; + bool bb = mod(shiftedb, 2) == 1; + bool br = ba && bb; + + if (br) + result += bits[i]; + + shifteda = rshift1(shifteda); + shiftedb = rshift1(shiftedb); + } + return result; +} + +int or(int a, int b) { + int shifteda = a; + int shiftedb = b; + int result = 0; + for (int i = 0; i < 16; i++) { + bool ba = mod(shifteda, 2) == 1; + bool bb = mod(shiftedb, 2) == 1; + bool br = ba || bb; + + if (br) + result += bits[i]; + + shifteda = rshift1(shifteda); + shiftedb = rshift1(shiftedb); + } + return result; +} + +int xor(int a, int b) { + int shifteda = a; + int shiftedb = b; + int result = 0; + for (int i = 0; i < 16; i++) { + bool ba = mod(shifteda, 2) == 1; + bool bb = mod(shiftedb, 2) == 1; + bool br = ba ^^ bb; + + if (br) + result += bits[i]; + + shifteda = rshift1(shifteda); + shiftedb = rshift1(shiftedb); + } + return result; +} + +int not(int a) { + int shifteda = a; + int result = 0; + for (int i = 0; i < 16; i++) { + bool ba = mod(shifteda, 2) == 1; + bool br = !ba; + + if (br) + result += bits[i]; + + shifteda = rshift1(shifteda); + } + return result; +} + +bool and(bool a, bool b) { return a && b; } +bool or(bool a, bool b) { return a || b; } +bool xor(bool a, bool b) { return a ^^ b; } +bool not(bool a) { return !a; } + From 3bed4b8afffb53b548568932597fa5f1985bb6bc Mon Sep 17 00:00:00 2001 From: Gob Date: Thu, 6 Jun 2024 11:15:00 +0000 Subject: [PATCH 294/693] use glFragData[i] in glsl 120 --- src/shady/emit/c/emit_c.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 650df7d61..00bfe80f2 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -587,6 +587,13 @@ void emit_decl(Emitter* emitter, const Node* decl) { return; } + if (ass == AsOutput && emitter->compiler_config->specialization.execution_model == EmFragment) { + int location = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(lookup_annotation(decl, "Location"))), false); + CTerm t = term_from_cvar(format_string_interned(emitter->arena, "gl_FragData[%d]", location)); + register_emitted(emitter, decl, t); + return; + } + decl_type = decl->payload.global_variable.type; // we emit the global variable as a CVar, so we can refer to it's 'address' without explicit ptrs emit_as = term_from_cvar(name); From b0ac899bfbb4591facbb2debb758abc5ed0628ab Mon Sep 17 00:00:00 2001 From: Gob Date: Sun, 9 Jun 2024 14:38:08 +0000 Subject: [PATCH 295/693] fold: simplify lea pointer operands --- src/shady/fold.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/shady/fold.c b/src/shady/fold.c index a0b35f65c..35d67fc97 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -248,7 +248,8 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { bool rebuild = false; switch (payload.op) { case store_op: - case load_op: { + case load_op: + case lea_op: { simplify_ptr_operand(arena, bb, &payload, &rebuild, 0); break; } @@ -256,7 +257,12 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { } if (rebuild) { - return bind_last_instruction_and_wrap_in_block(bb, prim_op(arena, payload)); + const Node* r = prim_op(arena, payload); + if (r->type != node->type) { + r = gen_conversion(bb, get_unqualified_type(node->type), first(bind_instruction(bb, r))); + return yield_values_and_wrap_in_block(bb, singleton(r)); + } + return bind_last_instruction_and_wrap_in_block(bb, r); } cancel_body(bb); From facf2e1ecfcc99e2f9b5763a34a451079a9b95f0 Mon Sep 17 00:00:00 2001 From: Gob Date: Sun, 9 Jun 2024 14:38:31 +0000 Subject: [PATCH 296/693] fix memcpy to not use unsized arrays --- src/shady/passes/lower_memcpy.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 87ff8148b..e76d1ca0b 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -37,7 +37,7 @@ static const Node* process(Context* ctx, const Node* old) { assert(dst_addr_type->tag == PtrType_TAG); dst_addr_type = ptr_type(a, (PtrType) { .address_space = dst_addr_type->payload.ptr_type.address_space, - .pointed_type = arr_type(a, (ArrType) { .element_type = word_type, .size = NULL }), + .pointed_type = word_type, }); dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); @@ -46,8 +46,8 @@ static const Node* process(Context* ctx, const Node* old) { deconstruct_qualified_type(&src_addr_type); assert(src_addr_type->tag == PtrType_TAG); src_addr_type = ptr_type(a, (PtrType) { - .address_space = src_addr_type->payload.ptr_type.address_space, - .pointed_type = arr_type(a, (ArrType) { .element_type = word_type, .size = NULL }), + .address_space = src_addr_type->payload.ptr_type.address_space, + .pointed_type = word_type, }); src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); @@ -56,8 +56,8 @@ static const Node* process(Context* ctx, const Node* old) { const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memcpy_i"); BodyBuilder* loop_bb = begin_body(a); - const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, singleton(uint32_literal(a, 0)))); - gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, singleton(uint32_literal(a, 0))), loaded_word); + const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, empty(a))); + gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); bind_instruction(loop_bb, if_instr(a, (If) { .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), @@ -89,7 +89,7 @@ static const Node* process(Context* ctx, const Node* old) { assert(dst_addr_type->tag == PtrType_TAG); dst_addr_type = ptr_type(a, (PtrType) { .address_space = dst_addr_type->payload.ptr_type.address_space, - .pointed_type = arr_type(a, (ArrType) { .element_type = word_type, .size = NULL }), + .pointed_type = word_type, }); dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); @@ -98,7 +98,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memset_i"); BodyBuilder* loop_bb = begin_body(a); - gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, singleton(uint32_literal(a, 0))), src_value); + gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); bind_instruction(loop_bb, if_instr(a, (If) { .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), From f3452fcb11a700e9868bd92878554d9f7496a462 Mon Sep 17 00:00:00 2001 From: Gob Date: Sun, 9 Jun 2024 14:39:05 +0000 Subject: [PATCH 297/693] vcc: added stub matrix stuff --- vcc-std/include/shady.h | 1 + vcc-std/include/shady_mat.h | 134 ++++++++++++++++++++++++++++++++++++ vcc-std/include/shady_vec.h | 2 +- 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 vcc-std/include/shady_mat.h diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index 885ec40fe..9e594f95a 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -29,6 +29,7 @@ namespace vcc { #define private __attribute__((address_space(5))) #include "shady_vec.h" +#include "shady_mat.h" typedef __attribute__((address_space(0x1000))) struct __shady_builtin_sampler2D* sampler2D; diff --git a/vcc-std/include/shady_mat.h b/vcc-std/include/shady_mat.h new file mode 100644 index 000000000..06bdfa067 --- /dev/null +++ b/vcc-std/include/shady_mat.h @@ -0,0 +1,134 @@ +#define Mat4f mat4 +#define Vec4f vec4 +#define Vec3f vec3 + +typedef union { + struct { + // we use row-major ordering + float m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33; + }; + //Vec4f rows[4]; + float arr[16]; +} Mat4f; + +static const Mat4f identity_mat4f = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, +}; + +Mat4f transpose_mat4f(Mat4f src) { + return (Mat4f) { + src.m00, src.m10, src.m20, src.m30, + src.m01, src.m11, src.m21, src.m31, + src.m02, src.m12, src.m22, src.m32, + src.m03, src.m13, src.m23, src.m33, + }; +} + +Mat4f invert_mat4(Mat4f m) { + float a = m.m00 * m.m11 - m.m01 * m.m10; + float b = m.m00 * m.m12 - m.m02 * m.m10; + float c = m.m00 * m.m13 - m.m03 * m.m10; + float d = m.m01 * m.m12 - m.m02 * m.m11; + float e = m.m01 * m.m13 - m.m03 * m.m11; + float f = m.m02 * m.m13 - m.m03 * m.m12; + float g = m.m20 * m.m31 - m.m21 * m.m30; + float h = m.m20 * m.m32 - m.m22 * m.m30; + float i = m.m20 * m.m33 - m.m23 * m.m30; + float j = m.m21 * m.m32 - m.m22 * m.m31; + float k = m.m21 * m.m33 - m.m23 * m.m31; + float l = m.m22 * m.m33 - m.m23 * m.m32; + float det = a * l - b * k + c * j + d * i - e * h + f * g; + det = 1.0f / det; + Mat4f r; + r.m00 = ( m.m11 * l - m.m12 * k + m.m13 * j) * det; + r.m01 = (-m.m01 * l + m.m02 * k - m.m03 * j) * det; + r.m02 = ( m.m31 * f - m.m32 * e + m.m33 * d) * det; + r.m03 = (-m.m21 * f + m.m22 * e - m.m23 * d) * det; + r.m10 = (-m.m10 * l + m.m12 * i - m.m13 * h) * det; + r.m11 = ( m.m00 * l - m.m02 * i + m.m03 * h) * det; + r.m12 = (-m.m30 * f + m.m32 * c - m.m33 * b) * det; + r.m13 = ( m.m20 * f - m.m22 * c + m.m23 * b) * det; + r.m20 = ( m.m10 * k - m.m11 * i + m.m13 * g) * det; + r.m21 = (-m.m00 * k + m.m01 * i - m.m03 * g) * det; + r.m22 = ( m.m30 * e - m.m31 * c + m.m33 * a) * det; + r.m23 = (-m.m20 * e + m.m21 * c - m.m23 * a) * det; + r.m30 = (-m.m10 * j + m.m11 * h - m.m12 * g) * det; + r.m31 = ( m.m00 * j - m.m01 * h + m.m02 * g) * det; + r.m32 = (-m.m30 * d + m.m31 * b - m.m32 * a) * det; + r.m33 = ( m.m20 * d - m.m21 * b + m.m22 * a) * det; + return r; +} + +/*Mat4f perspective_mat4f(float a, float fov, float n, float f) { + float pi = M_PI; + float s = 1.0f / tanf(fov * 0.5f * (pi / 180.0f)); + return (Mat4f) { + s / a, 0, 0, 0, + 0, s, 0, 0, + 0, 0, -f / (f - n), -1.f, + 0, 0, - (f * n) / (f - n), 0 + }; +}*/ + +Mat4f translate_mat4f(Vec3f offset) { + Mat4f m = identity_mat4f; + m.m30 = offset.x; + m.m31 = offset.y; + m.m32 = offset.z; + return m; +} + +/*Mat4f rotate_axis_mat4f(unsigned int axis, float f) { + Mat4f m = { 0 }; + m.m33 = 1; + + unsigned int t = (axis + 2) % 3; + unsigned int s = (axis + 1) % 3; + + m.rows[t].arr[t] = cosf(f); + m.rows[t].arr[s] = -sinf(f); + m.rows[s].arr[t] = sinf(f); + m.rows[s].arr[s] = cosf(f); + + // leave that unchanged + m.rows[axis].arr[axis] = 1; + + return m; +}*/ + +Mat4f mul_mat4f(Mat4f l, Mat4f r) { + Mat4f dst = { 0 }; +#define a(i, j) m##i##j +#define t(bc, br, i) l.a(i, br) * r.a(bc, i) +#define e(bc, br) dst.a(bc, br) = t(bc, br, 0) + t(bc, br, 1) + t(bc, br, 2) + t(bc, br, 3); +#define row(c) e(c, 0) e(c, 1) e(c, 2) e(c, 3) +#define genmul() row(0) row(1) row(2) row(3) + genmul() + return dst; +#undef a +#undef t +#undef e +#undef row +#undef genmul +} + +Vec4f mul_mat4f_vec4f(Mat4f l, Vec4f r) { + float src[4] = { r.x, r.y, r.z, r.w }; + float dst[4]; +#define a(i, j) m##i##j +#define t(bc, br, i) l.a(i, br) * src[i] +#define e(bc, br) dst[br] = t(bc, br, 0) + t(bc, br, 1) + t(bc, br, 2) + t(bc, br, 3); +#define row(c) e(c, 0) e(c, 1) e(c, 2) e(c, 3) +#define genmul() row(0) + genmul() + return (Vec4f) { dst[0], dst[1], dst[2], dst[3] }; +} + +#if defined(__cplusplus) +#endif diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index fed12e018..b584602b0 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -138,4 +138,4 @@ typedef native_ivec2 ivec2; typedef native_uvec4 uvec4; typedef native_uvec3 uvec3; typedef native_uvec2 uvec2; -#endif \ No newline at end of file +#endif From f394cb58e1591d3dad64bf013538f1238ba5a61a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 12 Jun 2024 15:14:06 +0200 Subject: [PATCH 298/693] fix CUDA backend --- src/runtime/cuda/cuda_runtime.c | 3 ++- src/runtime/cuda/cuda_runtime_program.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index ae744c9cc..799ac063d 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -1,4 +1,5 @@ #include "cuda_runtime_private.h" +#include "shady/config.h" #include "log.h" #include "portability.h" @@ -50,7 +51,7 @@ CudaCommand* shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry cudaEventRecord(cmd->start, 0); } - ArenaConfig final_config = get_arena_config(get_module_arena(kernel->final_module)); + ArenaConfig final_config = *get_arena_config(get_module_arena(kernel->final_module)); unsigned int gx = final_config.specializations.workgroup_size[0]; unsigned int gy = final_config.specializations.workgroup_size[1]; unsigned int gz = final_config.specializations.workgroup_size[2]; diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 909c8be5a..68b075d12 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -28,7 +28,7 @@ static bool emit_cuda_c_code(CudaKernel* spec) { .decay_unsized_arrays = true, }; Module* final_mod; - emit_c(config, emitter_config, dst_mod, &spec->cuda_code_size, &spec->cuda_code, &final_mod); + emit_c(&config, emitter_config, dst_mod, &spec->cuda_code_size, &spec->cuda_code, &final_mod); spec->final_module = final_mod; if (get_log_level() <= DEBUG) From 559ff034e478595332873e4b51d932d804885407 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 12 Jun 2024 17:42:28 +0200 Subject: [PATCH 299/693] added pass to fix up logical pointers --- src/shady/CMakeLists.txt | 1 + src/shady/compile.c | 2 + src/shady/passes/lower_logical_pointers.c | 107 ++++++++++++++++++++++ src/shady/passes/passes.h | 1 + 4 files changed, 111 insertions(+) create mode 100644 src/shady/passes/lower_logical_pointers.c diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 744414f96..0b7cc5c5b 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -92,6 +92,7 @@ set(SHADY_SOURCES passes/simt2d.c passes/specialize_entry_point.c passes/specialize_execution_model.c + passes/lower_logical_pointers.c passes/lower_entrypoint_args.c passes/spirv_map_entrypoint_args.c diff --git a/src/shady/compile.c b/src/shady/compile.c index 91e050f21..ebbe20a34 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -78,6 +78,8 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { if (config->specialization.entry_point) RUN_PASS(specialize_entry_point) + RUN_PASS(lower_logical_pointers) + RUN_PASS(lower_mask) RUN_PASS(lower_memcpy) RUN_PASS(lower_subgroup_ops) diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c new file mode 100644 index 000000000..9d9851a59 --- /dev/null +++ b/src/shady/passes/lower_logical_pointers.c @@ -0,0 +1,107 @@ +#include "pass.h" + +#include "../type.h" +#include "../ir_private.h" +#include "../transform/ir_gen_helpers.h" + +#include "log.h" +#include "portability.h" +#include "shady/ir.h" + +#include + +typedef struct { + Rewriter rewriter; + const CompilerConfig* config; +} Context; + +static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node* ptr, const Type* expected_type) { + IrArena* a = ctx->rewriter.dst_arena; + while (true) { + const Type* actual_type = get_unqualified_type(ptr->type); + assert(actual_type->tag == PtrType_TAG); + actual_type = get_pointer_type_element(actual_type); + if (expected_type == actual_type) + break; + + switch (actual_type->tag) { + case RecordType_TAG: + case ArrType_TAG: + case PackType_TAG: { + ptr = gen_lea(bb, ptr, int32_literal(a, 0), singleton(int32_literal(a, 0))); + continue; + } + default: break; + } + error("Cannot fix pointer") + } + return ptr; +} + +static const Node* process(Context* ctx, const Node* old) { + const Node* found = search_processed(&ctx->rewriter, old); + if (found) return found; + + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + + switch (old->tag) { + case PtrType_TAG: { + PtrType payload = old->payload.ptr_type; + if (!get_arena_config(a)->address_spaces[payload.address_space].physical) + payload.is_reference = true; + payload.pointed_type = rewrite_node(r, payload.pointed_type); + return ptr_type(a, payload); + } + case PrimOp_TAG: { + PrimOp payload = old->payload.prim_op; + switch (payload.op) { + case reinterpret_op: { + const Node* osrc = first(payload.operands); + const Type* osrc_t = osrc->type; + deconstruct_qualified_type(&osrc_t); + if (osrc_t->tag == PtrType_TAG && !get_arena_config(a)->address_spaces[osrc_t->payload.ptr_type.address_space].physical) + return prim_op_helper(a, quote_op, empty(a), singleton(rewrite_node(r, osrc))); + break; + } + case load_op: + case store_op: + case lea_op: { + const Node* optr = first(payload.operands); + const Type* optr_t = optr->type; + deconstruct_qualified_type(&optr_t); + assert(optr_t->tag == PtrType_TAG); + const Type* expected_type = rewrite_node(r, optr_t); + payload.operands = rewrite_nodes(r, payload.operands); + payload.type_arguments = rewrite_nodes(r, payload.type_arguments); + const Node* ptr = first(payload.operands); + const Type* actual_type = get_unqualified_type(ptr->type); + BodyBuilder* bb = begin_body(a); + if (expected_type != actual_type) + payload.operands = change_node_at_index(a, payload.operands, 0, guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type))); + return bind_last_instruction_and_wrap_in_block(bb, prim_op(a, payload)); + } + default: break; + } + break; + } + default: break; + } + + return recreate_node_identity(&ctx->rewriter, old); +} + +Module* lower_logical_pointers(const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + aconfig.address_spaces[AsInput].physical = false; + aconfig.address_spaces[AsOutput].physical = false; + IrArena* a = new_ir_arena(&aconfig); + Module* dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .config = config, + }; + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + return dst; +} diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 192cd9556..c3b1b1abf 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -73,6 +73,7 @@ RewritePass lower_memcpy; /// Eliminates pointers to unsized arrays from the IR. Needs lower_lea to have ran first! RewritePass lower_decay_ptrs; RewritePass lower_generic_globals; +RewritePass lower_logical_pointers; /// @} From 17921a70a2ec2abea430a30946a756a1ac781cfa Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 12 Jun 2024 17:42:42 +0200 Subject: [PATCH 300/693] make cuda backend disable-able --- src/runtime/cuda/CMakeLists.txt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index 31592995b..7ce3fac42 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -2,12 +2,15 @@ find_package(CUDAToolkit) if (CUDAToolkit_FOUND) message("Cuda toolkit found.") - add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c cuda_runtime_program.c) - target_link_libraries(cuda_runtime PRIVATE api) - target_link_libraries(cuda_runtime PRIVATE "$") - target_link_libraries(cuda_runtime PRIVATE "$") - target_link_libraries(cuda_runtime PRIVATE CUDA::cudart CUDA::cuda_driver CUDA::nvrtc) + option(SHADY_ENABLE_CUDA_BE "Whether the CUDA backend should be enabled" ON) + if (SHADY_ENABLE_CUDA_BE) + add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c cuda_runtime_program.c) + target_link_libraries(cuda_runtime PRIVATE api) + target_link_libraries(cuda_runtime PRIVATE "$") + target_link_libraries(cuda_runtime PRIVATE "$") + target_link_libraries(cuda_runtime PRIVATE CUDA::cudart CUDA::cuda_driver CUDA::nvrtc) - target_link_libraries(runtime PRIVATE "$") - target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) + target_link_libraries(runtime PRIVATE "$") + target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) + endif() endif () \ No newline at end of file From b1ce620a800bc3294e349d8d5ca5e035435ee70c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 12 Jun 2024 17:42:53 +0200 Subject: [PATCH 301/693] don't add ArrayStride on pointer types for now --- src/shady/emit/spirv/emit_spv_type.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shady/emit/spirv/emit_spv_type.c b/src/shady/emit/spirv/emit_spv_type.c index 14be0bbca..54ecb0a29 100644 --- a/src/shady/emit/spirv/emit_spv_type.c +++ b/src/shady/emit/spirv/emit_spv_type.c @@ -224,8 +224,8 @@ SpvId emit_type(Emitter* emitter, const Type* type) { if (is_data_type(type)) { if (type->tag == PtrType_TAG && type->payload.ptr_type.address_space == AsGlobal) { - TypeMemLayout elem_mem_layout = get_mem_layout(emitter->arena, type->payload.ptr_type.pointed_type); - spvb_decorate(emitter->file_builder, new, SpvDecorationArrayStride, 1, (uint32_t[]) {elem_mem_layout.size_in_bytes}); + //TypeMemLayout elem_mem_layout = get_mem_layout(emitter->arena, type->payload.ptr_type.pointed_type); + //spvb_decorate(emitter->file_builder, new, SpvDecorationArrayStride, 1, (uint32_t[]) {elem_mem_layout.size_in_bytes}); } } From 63996b4c8c1451a99d0e8d7c411e27c8ac029be0 Mon Sep 17 00:00:00 2001 From: Gob Date: Fri, 14 Jun 2024 21:14:55 +0000 Subject: [PATCH 302/693] glsl120: deal with attribute/varying/uniform correctly-er --- src/shady/emit/c/emit_c.c | 5 +++-- src/shady/emit/c/emit_c_builtins.c | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/shady/emit/c/emit_c.c b/src/shady/emit/c/emit_c.c index 00bfe80f2..871282c3d 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/shady/emit/c/emit_c.c @@ -120,6 +120,7 @@ static bool has_forward_declarations(CDialect dialect) { static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, String decl_center, const Type* type, bool constant, String init) { String prefix = NULL; + bool is_fs = emitter->compiler_config->specialization.execution_model == EmFragment; // GLSL wants 'const' to go on the left to start the declaration, but in C const should go on the right (east const convention) switch (emitter->config.dialect) { case CDialect_C11: { @@ -160,10 +161,10 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S switch (as) { case AsShared: prefix = "shared "; break; case AsInput: - case AsUInput: prefix = emitter->config.glsl_version < 130 ? "varying " : "in "; break; + case AsUInput: prefix = emitter->config.glsl_version < 130 ? (is_fs ? "varying " : "attribute ") : "in "; break; case AsOutput: prefix = emitter->config.glsl_version < 130 ? "varying " : "out "; break; case AsPrivate: prefix = ""; break; - case AsUniformConstant: prefix = "uniform"; break; + case AsUniformConstant: prefix = "uniform "; break; case AsGlobal: { assert(constant && "Only constants are supported"); prefix = "const "; diff --git a/src/shady/emit/c/emit_c_builtins.c b/src/shady/emit/c/emit_c_builtins.c index 9e3568338..ba4e61493 100644 --- a/src/shady/emit/c/emit_c_builtins.c +++ b/src/shady/emit/c/emit_c_builtins.c @@ -15,6 +15,7 @@ static String glsl_builtins[BuiltinsCount] = { [BuiltinNumWorkgroups] = "gl_NumWorkGroups", [BuiltinWorkgroupSize] = "gl_WorkGroupSize", [BuiltinGlobalInvocationId] = "gl_GlobalInvocationID", + [BuiltinPosition] = "gl_Position", }; CTerm emit_c_builtin(Emitter* emitter, Builtin b) { From 3c782f642ad2c77e22a8b1fd62b32d4414e8c158 Mon Sep 17 00:00:00 2001 From: Gob Date: Fri, 14 Jun 2024 21:15:22 +0000 Subject: [PATCH 303/693] emit_c: LEA into pack type --- src/shady/emit/c/emit_c_instructions.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/shady/emit/c/emit_c_instructions.c index d88c8ea46..be450d95a 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/shady/emit/c/emit_c_instructions.c @@ -409,6 +409,16 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct }); break; } + case Type_PackType_TAG: { + size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); + String suffixes = "xyzw"; + acc = term_from_cvar(format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); + curr_ptr_type = ptr_type(arena, (PtrType) { + .pointed_type = pointee_type->payload.pack_type.element_type, + .address_space = curr_ptr_type->payload.ptr_type.address_space + }); + break; + } default: error("lea can't work on this"); } } From bbacf947fd399b8952bc2554b1b7095541bf6dcd Mon Sep 17 00:00:00 2001 From: Gob Date: Fri, 14 Jun 2024 21:15:44 +0000 Subject: [PATCH 304/693] fold: don't simplify reference chains --- src/shady/fold.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shady/fold.c b/src/shady/fold.c index 35d67fc97..39fd74912 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -234,6 +234,10 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { static void inline simplify_ptr_operand(IrArena* a, BodyBuilder* bb, PrimOp* payload, bool* success, int i) { const Node* old_op = payload->operands.nodes[i]; + const Type* ptr_t = old_op->type; + deconstruct_qualified_type(&ptr_t); + if (ptr_t->payload.ptr_type.is_reference) + return; const Node* new_op = resolve_ptr_source(bb, old_op); if (old_op != new_op) { payload->operands = change_node_at_index(a, payload->operands, i, new_op); From f750225bf2ed38b014c2295ac244737ed854cd27 Mon Sep 17 00:00:00 2001 From: Gob Date: Fri, 14 Jun 2024 21:15:56 +0000 Subject: [PATCH 305/693] lower_logical_pointers: cope with nominal structs --- src/shady/passes/lower_logical_pointers.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 9d9851a59..ed6df45a4 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -24,6 +24,9 @@ static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node if (expected_type == actual_type) break; + actual_type = get_maybe_nominal_type_body(actual_type); + assert(expected_type != actual_type && "todo: rework this function if we change how nominal types are handled"); + switch (actual_type->tag) { case RecordType_TAG: case ArrType_TAG: From c71809135cbd50cce2a857514a1f6e7bf7a1d7cf Mon Sep 17 00:00:00 2001 From: Gob Date: Fri, 14 Jun 2024 21:16:10 +0000 Subject: [PATCH 306/693] lower_logical_pointers: add Logical to top-level gvars --- src/shady/passes/lower_logical_pointers.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index ed6df45a4..5e7a6615d 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -88,6 +88,16 @@ static const Node* process(Context* ctx, const Node* old) { } break; } + case GlobalVariable_TAG: { + AddressSpace as = old->payload.global_variable.address_space; + if (get_arena_config(a)->address_spaces[as].physical) + break; + Nodes annotations = rewrite_nodes(r, old->payload.global_variable.annotations); + annotations = append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical" })); + Node* new = global_var(ctx->rewriter.dst_module, annotations, rewrite_node(r, old->payload.global_variable.type), old->payload.global_variable.name, as); + recreate_decl_body_identity(r, old, new); + return new; + } default: break; } From 91439db00c686ceeaef9628d3ddd54c4ebc51196 Mon Sep 17 00:00:00 2001 From: Gob Date: Fri, 14 Jun 2024 21:16:28 +0000 Subject: [PATCH 307/693] lower_logical_pointers: include UniformConstant --- src/shady/passes/lower_logical_pointers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 5e7a6615d..c8f39d20a 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -108,6 +108,7 @@ Module* lower_logical_pointers(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); aconfig.address_spaces[AsInput].physical = false; aconfig.address_spaces[AsOutput].physical = false; + aconfig.address_spaces[AsUniformConstant].physical = false; IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { From 1a9eef3e8b54918e13e2f197102440a02159d46b Mon Sep 17 00:00:00 2001 From: gob Date: Sat, 13 Jul 2024 10:04:49 +0200 Subject: [PATCH 308/693] zhady: include config.h --- zhady/shady.i | 1 + 1 file changed, 1 insertion(+) diff --git a/zhady/shady.i b/zhady/shady.i index e9298b623..56404c041 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -7,6 +7,7 @@ #include "shady/ir.h" #include "shady/runtime.h" #include "shady/driver.h" +#include "shady/config.h" %} %include "shady/ir.h" From 87a73ec555849c254b2dad6f2a8cbec776380630 Mon Sep 17 00:00:00 2001 From: gob Date: Thu, 11 Jul 2024 10:37:06 +0200 Subject: [PATCH 309/693] move src/shady/emit into src/backend --- src/CMakeLists.txt | 3 ++- src/{shady/emit => backend}/CMakeLists.txt | 0 src/{shady/emit => backend}/c/CMakeLists.txt | 4 ++-- src/{shady/emit => backend}/c/cuda_builtins.cu | 0 src/{shady/emit => backend}/c/cuda_prelude.cu | 0 src/{shady/emit => backend}/c/emit_c.c | 9 ++++----- src/{shady/emit => backend}/c/emit_c.h | 0 src/{shady/emit => backend}/c/emit_c_builtins.c | 0 src/{shady/emit => backend}/c/emit_c_instructions.c | 4 ++-- src/{shady/emit => backend}/c/emit_c_signatures.c | 4 ++-- src/{shady/emit => backend}/c/glsl_120_polyfills.glsl | 0 src/{shady/emit => backend}/spirv/CMakeLists.txt | 4 ++-- src/{shady/emit => backend}/spirv/emit_spv.c | 9 +++++---- src/{shady/emit => backend}/spirv/emit_spv.h | 0 .../emit => backend}/spirv/emit_spv_instructions.c | 6 +++--- src/{shady/emit => backend}/spirv/emit_spv_type.c | 7 +++---- src/{shady/emit => backend}/spirv/spirv_builder.c | 0 src/{shady/emit => backend}/spirv/spirv_builder.h | 0 src/driver/driver.c | 5 +++-- src/frontends/slim/CMakeLists.txt | 5 +---- src/runtime/runtime_cli.c | 4 ++-- src/shady/CMakeLists.txt | 3 +-- src/shady/analysis/cfg_dump.c | 4 ++-- src/shady/compile.c | 3 +-- src/shady/fold.c | 2 +- test/CMakeLists.txt | 2 +- test/opt/opt_oracle.c | 4 ++-- 27 files changed, 39 insertions(+), 43 deletions(-) rename src/{shady/emit => backend}/CMakeLists.txt (100%) rename src/{shady/emit => backend}/c/CMakeLists.txt (87%) rename src/{shady/emit => backend}/c/cuda_builtins.cu (100%) rename src/{shady/emit => backend}/c/cuda_prelude.cu (100%) rename src/{shady/emit => backend}/c/emit_c.c (99%) rename src/{shady/emit => backend}/c/emit_c.h (100%) rename src/{shady/emit => backend}/c/emit_c_builtins.c (100%) rename src/{shady/emit => backend}/c/emit_c_instructions.c (99%) rename src/{shady/emit => backend}/c/emit_c_signatures.c (99%) rename src/{shady/emit => backend}/c/glsl_120_polyfills.glsl (100%) rename src/{shady/emit => backend}/spirv/CMakeLists.txt (80%) rename src/{shady/emit => backend}/spirv/emit_spv.c (99%) rename src/{shady/emit => backend}/spirv/emit_spv.h (100%) rename src/{shady/emit => backend}/spirv/emit_spv_instructions.c (99%) rename src/{shady/emit => backend}/spirv/emit_spv_type.c (99%) rename src/{shady/emit => backend}/spirv/spirv_builder.c (100%) rename src/{shady/emit => backend}/spirv/spirv_builder.h (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 609a0e0ee..a2b06b35c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,5 +5,6 @@ set_target_properties(murmur3 PROPERTIES POSITION_INDEPENDENT_CODE ON) add_subdirectory(common) add_subdirectory(shady) add_subdirectory(runtime) -add_subdirectory(frontends) add_subdirectory(driver) +add_subdirectory(frontends) +add_subdirectory(backend) diff --git a/src/shady/emit/CMakeLists.txt b/src/backend/CMakeLists.txt similarity index 100% rename from src/shady/emit/CMakeLists.txt rename to src/backend/CMakeLists.txt diff --git a/src/shady/emit/c/CMakeLists.txt b/src/backend/c/CMakeLists.txt similarity index 87% rename from src/shady/emit/c/CMakeLists.txt rename to src/backend/c/CMakeLists.txt index b976e0f0b..6094feb58 100644 --- a/src/shady/emit/c/CMakeLists.txt +++ b/src/backend/c/CMakeLists.txt @@ -9,7 +9,7 @@ set_property(TARGET shady_c PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(shady_c PRIVATE $) target_link_libraries(shady_c PRIVATE "api") -target_link_libraries(shady_c INTERFACE "shady") +target_link_libraries(shady_c INTERFACE "$") target_link_libraries(shady_c PRIVATE "$") target_link_libraries(shady_c PRIVATE "$") @@ -21,4 +21,4 @@ target_link_libraries(shady_c PRIVATE "$") -target_link_libraries(shady PUBLIC "$") +target_link_libraries(driver PUBLIC "$") diff --git a/src/shady/emit/c/cuda_builtins.cu b/src/backend/c/cuda_builtins.cu similarity index 100% rename from src/shady/emit/c/cuda_builtins.cu rename to src/backend/c/cuda_builtins.cu diff --git a/src/shady/emit/c/cuda_prelude.cu b/src/backend/c/cuda_prelude.cu similarity index 100% rename from src/shady/emit/c/cuda_prelude.cu rename to src/backend/c/cuda_prelude.cu diff --git a/src/shady/emit/c/emit_c.c b/src/backend/c/emit_c.c similarity index 99% rename from src/shady/emit/c/emit_c.c rename to src/backend/c/emit_c.c index 871282c3d..dc4149f3f 100644 --- a/src/shady/emit/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -1,10 +1,9 @@ #include "emit_c.h" -#include "../../type.h" -#include "../../ir_private.h" -#include "../../compile.h" - -#include "../../transform/ir_gen_helpers.h" +#include "../shady/type.h" +#include "../shady/ir_private.h" +#include "../shady/compile.h" +#include "../shady/transform/ir_gen_helpers.h" #include "shady_cuda_prelude_src.h" #include "shady_cuda_builtins_src.h" diff --git a/src/shady/emit/c/emit_c.h b/src/backend/c/emit_c.h similarity index 100% rename from src/shady/emit/c/emit_c.h rename to src/backend/c/emit_c.h diff --git a/src/shady/emit/c/emit_c_builtins.c b/src/backend/c/emit_c_builtins.c similarity index 100% rename from src/shady/emit/c/emit_c_builtins.c rename to src/backend/c/emit_c_builtins.c diff --git a/src/shady/emit/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c similarity index 99% rename from src/shady/emit/c/emit_c_instructions.c rename to src/backend/c/emit_c_instructions.c index be450d95a..9500550a8 100644 --- a/src/shady/emit/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -5,8 +5,8 @@ #include "dict.h" #include "util.h" -#include "../../type.h" -#include "../../ir_private.h" +#include "../shady/type.h" +#include "../shady/ir_private.h" #include #include diff --git a/src/shady/emit/c/emit_c_signatures.c b/src/backend/c/emit_c_signatures.c similarity index 99% rename from src/shady/emit/c/emit_c_signatures.c rename to src/backend/c/emit_c_signatures.c index f98501968..546aef545 100644 --- a/src/shady/emit/c/emit_c_signatures.c +++ b/src/backend/c/emit_c_signatures.c @@ -4,8 +4,8 @@ #include "log.h" #include "util.h" -#include "../../type.h" -#include "../../ir_private.h" +#include "../shady/type.h" +#include "../shady/ir_private.h" #include #include diff --git a/src/shady/emit/c/glsl_120_polyfills.glsl b/src/backend/c/glsl_120_polyfills.glsl similarity index 100% rename from src/shady/emit/c/glsl_120_polyfills.glsl rename to src/backend/c/glsl_120_polyfills.glsl diff --git a/src/shady/emit/spirv/CMakeLists.txt b/src/backend/spirv/CMakeLists.txt similarity index 80% rename from src/shady/emit/spirv/CMakeLists.txt rename to src/backend/spirv/CMakeLists.txt index d3de7ace3..b1df68860 100644 --- a/src/shady/emit/spirv/CMakeLists.txt +++ b/src/backend/spirv/CMakeLists.txt @@ -9,9 +9,9 @@ set_property(TARGET shady_spirv PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(shady_spirv PRIVATE $) target_link_libraries(shady_spirv PRIVATE "api") -target_link_libraries(shady_spirv INTERFACE "shady") +target_link_libraries(shady_spirv INTERFACE "$") target_link_libraries(shady_spirv PRIVATE "$") target_link_libraries(shady_spirv PRIVATE "$") target_link_libraries(shady_spirv PRIVATE "$") -target_link_libraries(shady PUBLIC "$") +target_link_libraries(driver PUBLIC "$") diff --git a/src/shady/emit/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c similarity index 99% rename from src/shady/emit/spirv/emit_spv.c rename to src/backend/spirv/emit_spv.c index ac26d7de4..b8530806b 100644 --- a/src/shady/emit/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -1,8 +1,9 @@ #include "shady/builtins.h" -#include "../../ir_private.h" -#include "../../analysis/cfg.h" -#include "../../type.h" -#include "../../compile.h" + +#include "../shady/ir_private.h" +#include "../shady/analysis/cfg.h" +#include "../shady/type.h" +#include "../shady/compile.h" #include "list.h" #include "dict.h" diff --git a/src/shady/emit/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h similarity index 100% rename from src/shady/emit/spirv/emit_spv.h rename to src/backend/spirv/emit_spv.h diff --git a/src/shady/emit/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c similarity index 99% rename from src/shady/emit/spirv/emit_spv_instructions.c rename to src/backend/spirv/emit_spv_instructions.c index ba48e6f95..1134b2728 100644 --- a/src/shady/emit/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -3,9 +3,9 @@ #include "log.h" #include "portability.h" -#include "../../type.h" -#include "../../transform/memory_layout.h" -#include "../../transform/ir_gen_helpers.h" +#include "../shady/type.h" +#include "../shady/transform/memory_layout.h" +#include "../shady/transform/ir_gen_helpers.h" #include diff --git a/src/shady/emit/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c similarity index 99% rename from src/shady/emit/spirv/emit_spv_type.c rename to src/backend/spirv/emit_spv_type.c index 54ecb0a29..40d36ed15 100644 --- a/src/shady/emit/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -3,12 +3,11 @@ #include "portability.h" #include "log.h" - -#include "../../rewrite.h" -#include "../../transform/memory_layout.h" - #include "dict.h" +#include "../shady/rewrite.h" +#include "../shady/transform/memory_layout.h" + #include "assert.h" #pragma GCC diagnostic error "-Wswitch" diff --git a/src/shady/emit/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c similarity index 100% rename from src/shady/emit/spirv/spirv_builder.c rename to src/backend/spirv/spirv_builder.c diff --git a/src/shady/emit/spirv/spirv_builder.h b/src/backend/spirv/spirv_builder.h similarity index 100% rename from src/shady/emit/spirv/spirv_builder.h rename to src/backend/spirv/spirv_builder.h diff --git a/src/driver/driver.c b/src/driver/driver.c index 47d867746..59d448a10 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -4,9 +4,10 @@ #include "shady/be/c.h" #include "shady/be/spirv.h" #include "shady/be/dump.h" -#include "shady/print.h" -#include "frontends/slim/parser.h" +#include "print.h" + +#include "../frontends/slim/parser.h" #include "list.h" #include "util.h" diff --git a/src/frontends/slim/CMakeLists.txt b/src/frontends/slim/CMakeLists.txt index ff984437c..f81180d41 100644 --- a/src/frontends/slim/CMakeLists.txt +++ b/src/frontends/slim/CMakeLists.txt @@ -1,8 +1,5 @@ add_library(slim_parser STATIC parser.c token.c) target_link_libraries(slim_parser PUBLIC common api) -if (shady STREQUAL STATIC_LIBRARY OR MINGW) - target_link_libraries(slim_parser PRIVATE shady) -endif () +target_link_libraries(slim_parser PRIVATE shady) target_include_directories(slim_parser PUBLIC $) -target_include_directories(slim_parser INTERFACE "$") target_link_libraries(shady PUBLIC "$") diff --git a/src/runtime/runtime_cli.c b/src/runtime/runtime_cli.c index 87a951b21..a705a38b4 100644 --- a/src/runtime/runtime_cli.c +++ b/src/runtime/runtime_cli.c @@ -1,7 +1,7 @@ #include "runtime_private.h" -#include "driver/cli.h" +#include "../driver/cli.h" -#include "common/log.h" +#include "log.h" RuntimeConfig default_runtime_config() { return (RuntimeConfig) { diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 0b7cc5c5b..645a8e7bf 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -111,10 +111,9 @@ if (WIN32) endif() add_subdirectory(internal) -add_subdirectory(emit) target_link_libraries(shady PRIVATE "api") -target_link_libraries(shady INTERFACE "common") +target_link_libraries(shady PRIVATE "common") target_link_libraries(shady PRIVATE "$") target_link_libraries(shady PRIVATE "$") diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 5ebf1e5a1..1dcc4fc0e 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -1,7 +1,7 @@ #include "cfg.h" -#include "shady/ir_private.h" -#include "shady/print.h" +#include "ir_private.h" +#include "print.h" #include "list.h" #include "dict.h" diff --git a/src/shady/compile.c b/src/shady/compile.c index ebbe20a34..58e42d616 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -1,10 +1,9 @@ #include "shady/driver.h" #include "compile.h" -#include "frontends/slim/parser.h" +#include "../frontends/slim/parser.h" #include "shady_scheduler_src.h" #include "transform/internal_constants.h" -#include "portability.h" #include "ir_private.h" #include "util.h" diff --git a/src/shady/fold.c b/src/shady/fold.c index 39fd74912..a7de432cc 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -6,7 +6,7 @@ #include "portability.h" #include "rewrite.h" -#include "shady/transform/ir_gen_helpers.h" +#include "transform/ir_gen_helpers.h" #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 061fead62..f237dab73 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,5 @@ add_executable(test_math test_math.c) -target_link_libraries(test_math shady driver) +target_link_libraries(test_math driver) add_test(NAME test_math COMMAND test_math) list(APPEND BASIC_TESTS empty.slim) diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 04964c3da..ae5e186c7 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -1,8 +1,8 @@ #include "shady/ir.h" #include "shady/driver.h" -#include "shady/visit.h" -#include "shady/print.h" +#include "../shady/visit.h" +#include "../shady/print.h" #include "log.h" From 7bdc188fcb80b7483dcc88ee41c1d1f312594708 Mon Sep 17 00:00:00 2001 From: gob Date: Thu, 11 Jul 2024 10:39:06 +0200 Subject: [PATCH 310/693] drop 's' from src/frontend --- src/CMakeLists.txt | 2 +- src/driver/driver.c | 6 +++--- src/{frontends => frontend}/CMakeLists.txt | 0 src/{frontends => frontend}/llvm/CMakeLists.txt | 0 src/{frontends => frontend}/llvm/generator_l2s.c | 0 src/{frontends => frontend}/llvm/l2s.c | 0 src/{frontends => frontend}/llvm/l2s.h | 0 src/{frontends => frontend}/llvm/l2s_annotations.c | 0 src/{frontends => frontend}/llvm/l2s_instr.c | 0 src/{frontends => frontend}/llvm/l2s_meta.c | 0 src/{frontends => frontend}/llvm/l2s_postprocess.c | 0 src/{frontends => frontend}/llvm/l2s_private.h | 0 src/{frontends => frontend}/llvm/l2s_type.c | 0 src/{frontends => frontend}/llvm/l2s_value.c | 0 src/{frontends => frontend}/slim/CMakeLists.txt | 0 src/{frontends => frontend}/slim/parser.c | 0 src/{frontends => frontend}/slim/parser.h | 0 src/{frontends => frontend}/slim/token.c | 0 src/{frontends => frontend}/slim/token.h | 0 src/{frontends => frontend}/spirv/CMakeLists.txt | 0 src/{frontends => frontend}/spirv/s2s.c | 0 src/{frontends => frontend}/spirv/s2s.h | 0 src/shady/compile.c | 2 +- 23 files changed, 5 insertions(+), 5 deletions(-) rename src/{frontends => frontend}/CMakeLists.txt (100%) rename src/{frontends => frontend}/llvm/CMakeLists.txt (100%) rename src/{frontends => frontend}/llvm/generator_l2s.c (100%) rename src/{frontends => frontend}/llvm/l2s.c (100%) rename src/{frontends => frontend}/llvm/l2s.h (100%) rename src/{frontends => frontend}/llvm/l2s_annotations.c (100%) rename src/{frontends => frontend}/llvm/l2s_instr.c (100%) rename src/{frontends => frontend}/llvm/l2s_meta.c (100%) rename src/{frontends => frontend}/llvm/l2s_postprocess.c (100%) rename src/{frontends => frontend}/llvm/l2s_private.h (100%) rename src/{frontends => frontend}/llvm/l2s_type.c (100%) rename src/{frontends => frontend}/llvm/l2s_value.c (100%) rename src/{frontends => frontend}/slim/CMakeLists.txt (100%) rename src/{frontends => frontend}/slim/parser.c (100%) rename src/{frontends => frontend}/slim/parser.h (100%) rename src/{frontends => frontend}/slim/token.c (100%) rename src/{frontends => frontend}/slim/token.h (100%) rename src/{frontends => frontend}/spirv/CMakeLists.txt (100%) rename src/{frontends => frontend}/spirv/s2s.c (100%) rename src/{frontends => frontend}/spirv/s2s.h (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2b06b35c..48aae8d3e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,5 +6,5 @@ add_subdirectory(common) add_subdirectory(shady) add_subdirectory(runtime) add_subdirectory(driver) -add_subdirectory(frontends) +add_subdirectory(frontend) add_subdirectory(backend) diff --git a/src/driver/driver.c b/src/driver/driver.c index 59d448a10..24de057d5 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -7,7 +7,7 @@ #include "print.h" -#include "../frontends/slim/parser.h" +#include "../frontend/slim/parser.h" #include "list.h" #include "util.h" @@ -18,11 +18,11 @@ #include #ifdef LLVM_PARSER_PRESENT -#include "../frontends/llvm/l2s.h" +#include "../frontend/llvm/l2s.h" #endif #ifdef SPV_PARSER_PRESENT -#include "../frontends/spirv/s2s.h" +#include "../frontend/spirv/s2s.h" #endif #pragma GCC diagnostic error "-Wswitch" diff --git a/src/frontends/CMakeLists.txt b/src/frontend/CMakeLists.txt similarity index 100% rename from src/frontends/CMakeLists.txt rename to src/frontend/CMakeLists.txt diff --git a/src/frontends/llvm/CMakeLists.txt b/src/frontend/llvm/CMakeLists.txt similarity index 100% rename from src/frontends/llvm/CMakeLists.txt rename to src/frontend/llvm/CMakeLists.txt diff --git a/src/frontends/llvm/generator_l2s.c b/src/frontend/llvm/generator_l2s.c similarity index 100% rename from src/frontends/llvm/generator_l2s.c rename to src/frontend/llvm/generator_l2s.c diff --git a/src/frontends/llvm/l2s.c b/src/frontend/llvm/l2s.c similarity index 100% rename from src/frontends/llvm/l2s.c rename to src/frontend/llvm/l2s.c diff --git a/src/frontends/llvm/l2s.h b/src/frontend/llvm/l2s.h similarity index 100% rename from src/frontends/llvm/l2s.h rename to src/frontend/llvm/l2s.h diff --git a/src/frontends/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c similarity index 100% rename from src/frontends/llvm/l2s_annotations.c rename to src/frontend/llvm/l2s_annotations.c diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c similarity index 100% rename from src/frontends/llvm/l2s_instr.c rename to src/frontend/llvm/l2s_instr.c diff --git a/src/frontends/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c similarity index 100% rename from src/frontends/llvm/l2s_meta.c rename to src/frontend/llvm/l2s_meta.c diff --git a/src/frontends/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c similarity index 100% rename from src/frontends/llvm/l2s_postprocess.c rename to src/frontend/llvm/l2s_postprocess.c diff --git a/src/frontends/llvm/l2s_private.h b/src/frontend/llvm/l2s_private.h similarity index 100% rename from src/frontends/llvm/l2s_private.h rename to src/frontend/llvm/l2s_private.h diff --git a/src/frontends/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c similarity index 100% rename from src/frontends/llvm/l2s_type.c rename to src/frontend/llvm/l2s_type.c diff --git a/src/frontends/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c similarity index 100% rename from src/frontends/llvm/l2s_value.c rename to src/frontend/llvm/l2s_value.c diff --git a/src/frontends/slim/CMakeLists.txt b/src/frontend/slim/CMakeLists.txt similarity index 100% rename from src/frontends/slim/CMakeLists.txt rename to src/frontend/slim/CMakeLists.txt diff --git a/src/frontends/slim/parser.c b/src/frontend/slim/parser.c similarity index 100% rename from src/frontends/slim/parser.c rename to src/frontend/slim/parser.c diff --git a/src/frontends/slim/parser.h b/src/frontend/slim/parser.h similarity index 100% rename from src/frontends/slim/parser.h rename to src/frontend/slim/parser.h diff --git a/src/frontends/slim/token.c b/src/frontend/slim/token.c similarity index 100% rename from src/frontends/slim/token.c rename to src/frontend/slim/token.c diff --git a/src/frontends/slim/token.h b/src/frontend/slim/token.h similarity index 100% rename from src/frontends/slim/token.h rename to src/frontend/slim/token.h diff --git a/src/frontends/spirv/CMakeLists.txt b/src/frontend/spirv/CMakeLists.txt similarity index 100% rename from src/frontends/spirv/CMakeLists.txt rename to src/frontend/spirv/CMakeLists.txt diff --git a/src/frontends/spirv/s2s.c b/src/frontend/spirv/s2s.c similarity index 100% rename from src/frontends/spirv/s2s.c rename to src/frontend/spirv/s2s.c diff --git a/src/frontends/spirv/s2s.h b/src/frontend/spirv/s2s.h similarity index 100% rename from src/frontends/spirv/s2s.h rename to src/frontend/spirv/s2s.h diff --git a/src/shady/compile.c b/src/shady/compile.c index 58e42d616..0af5edeff 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -1,7 +1,7 @@ #include "shady/driver.h" #include "compile.h" -#include "../frontends/slim/parser.h" +#include "../frontend/slim/parser.h" #include "shady_scheduler_src.h" #include "transform/internal_constants.h" #include "ir_private.h" From 301054aeeb5685775c23a9e195bae47403f19e96 Mon Sep 17 00:00:00 2001 From: gob Date: Sat, 13 Jul 2024 10:42:29 +0200 Subject: [PATCH 311/693] fix backends and Vcc --- CMakeLists.txt | 1 + src/driver/CMakeLists.txt | 25 ------------------------- src/frontend/llvm/CMakeLists.txt | 3 +++ src/frontend/spirv/CMakeLists.txt | 3 +++ vcc/CMakeLists.txt | 18 ++++++++++++++++++ {src/driver => vcc}/vcc.c | 0 {src/driver => vcc}/vcc_lib.c | 0 7 files changed, 25 insertions(+), 25 deletions(-) create mode 100644 vcc/CMakeLists.txt rename {src/driver => vcc}/vcc.c (100%) rename {src/driver => vcc}/vcc_lib.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99e9358ed..e53682f91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,6 +96,7 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1) cmake_policy(SET CMP0118 NEW) add_subdirectory(src) +add_subdirectory(vcc) add_subdirectory(zhady) diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index d8dcb32f7..d37b69928 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -4,32 +4,7 @@ target_link_libraries(driver PUBLIC "shady") set_target_properties(driver PROPERTIES OUTPUT_NAME "shady_driver") install(TARGETS driver EXPORT shady_export_set) -if (TARGET shady_s2s) - target_compile_definitions(driver PUBLIC SPV_PARSER_PRESENT) - target_link_libraries(driver PUBLIC "$") -endif() - -if (TARGET shady_fe_llvm) - target_compile_definitions(driver PUBLIC LLVM_PARSER_PRESENT) - target_link_libraries(driver PUBLIC "$") -endif () - add_executable(slim slim.c) target_link_libraries(slim PRIVATE driver) install(TARGETS slim EXPORT shady_export_set) -if (TARGET shady_fe_llvm) - add_library(vcc_lib SHARED vcc_lib.c) - target_link_libraries(vcc_lib PUBLIC driver api) - - add_executable(vcc vcc.c) - target_link_libraries(vcc PRIVATE api vcc_lib) - install(TARGETS vcc_lib vcc EXPORT shady_export_set) - - if (WIN32) - add_custom_command(TARGET vcc POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy -t $ $ - COMMAND_EXPAND_LISTS - ) - endif () -endif () diff --git a/src/frontend/llvm/CMakeLists.txt b/src/frontend/llvm/CMakeLists.txt index d3b7f103e..260ef3aad 100644 --- a/src/frontend/llvm/CMakeLists.txt +++ b/src/frontend/llvm/CMakeLists.txt @@ -19,3 +19,6 @@ message(FATAL_ERROR "Failed to find LLVM-C target, but found LLVM module earlier endif() target_link_libraries(shady_fe_llvm PRIVATE api common shady) + +target_compile_definitions(driver PUBLIC LLVM_PARSER_PRESENT) +target_link_libraries(driver PUBLIC "$") diff --git a/src/frontend/spirv/CMakeLists.txt b/src/frontend/spirv/CMakeLists.txt index 7956754dc..7f905245d 100644 --- a/src/frontend/spirv/CMakeLists.txt +++ b/src/frontend/spirv/CMakeLists.txt @@ -1,3 +1,6 @@ add_library(shady_s2s STATIC s2s.c) target_link_libraries(shady_s2s PRIVATE api common) target_link_libraries(shady_s2s PRIVATE "$") + +target_compile_definitions(driver PUBLIC SPV_PARSER_PRESENT) +target_link_libraries(driver PUBLIC "$") diff --git a/vcc/CMakeLists.txt b/vcc/CMakeLists.txt new file mode 100644 index 000000000..70048d787 --- /dev/null +++ b/vcc/CMakeLists.txt @@ -0,0 +1,18 @@ +if (TARGET shady_fe_llvm) + add_library(vcc_lib STATIC vcc_lib.c) + target_link_libraries(vcc_lib PUBLIC driver api) + + add_executable(vcc vcc.c) + target_link_libraries(vcc PRIVATE api vcc_lib) + install(TARGETS vcc_lib vcc EXPORT shady_export_set) + + if (WIN32) + add_custom_command(TARGET vcc POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS + ) + endif () + message("Vcc will be built together with shady") +else() + message("LLVM front-end unavailable. Disabling Vcc") +endif () \ No newline at end of file diff --git a/src/driver/vcc.c b/vcc/vcc.c similarity index 100% rename from src/driver/vcc.c rename to vcc/vcc.c diff --git a/src/driver/vcc_lib.c b/vcc/vcc_lib.c similarity index 100% rename from src/driver/vcc_lib.c rename to vcc/vcc_lib.c From f833d6ba54ef5ffdc317b012762381a648290c4f Mon Sep 17 00:00:00 2001 From: gob Date: Sat, 13 Jul 2024 10:42:47 +0200 Subject: [PATCH 312/693] fix zhady --- include/shady/config.h | 14 ++++++++------ zhady/shady.i | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/shady/config.h b/include/shady/config.h index 1be7692c6..be7ad9aab 100644 --- a/include/shady/config.h +++ b/include/shady/config.h @@ -15,6 +15,13 @@ typedef struct { TargetConfig default_target_config(); +typedef enum { + /// Uses the MaskType + SubgroupMaskAbstract, + /// Uses a 64-bit integer + SubgroupMaskInt64 +} SubgroupMaskRepresentation; + typedef struct ArenaConfig_ ArenaConfig; struct ArenaConfig_ { bool name_bound; @@ -31,12 +38,7 @@ struct ArenaConfig_ { struct { /// Selects which type the subgroup intrinsic primops use to manipulate masks - enum { - /// Uses the MaskType - SubgroupMaskAbstract, - /// Uses a 64-bit integer - SubgroupMaskInt64 - } subgroup_mask_representation; + SubgroupMaskRepresentation subgroup_mask_representation; uint32_t workgroup_size[3]; } specializations; diff --git a/zhady/shady.i b/zhady/shady.i index 56404c041..fa155a38c 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -12,4 +12,5 @@ %include "shady/ir.h" %include "shady/driver.h" -%include "shady/runtime.h" \ No newline at end of file +%include "shady/runtime.h" +%include "shady/config.h" \ No newline at end of file From 5fc83cfdfb2fdf38ca0bb3888f7336b8debbe3a7 Mon Sep 17 00:00:00 2001 From: gob Date: Sat, 13 Jul 2024 17:40:18 +0200 Subject: [PATCH 313/693] reworked C++ vector wrapper --- test/vcc/CMakeLists.txt | 2 + test/vcc/cpp/CMakeLists.txt | 1 + test/vcc/cpp/vec_swizzle.cpp | 17 +++ vcc-std/CMakeLists.txt | 5 + vcc-std/include/shady.h | 8 ++ vcc-std/include/shady_mat.h | 105 +++++++++++--- vcc-std/include/shady_vec.h | 263 ++++++++++++++++++++++++----------- vcc-std/src/test_vec.cpp | 48 +++++++ 8 files changed, 344 insertions(+), 105 deletions(-) create mode 100644 test/vcc/cpp/CMakeLists.txt create mode 100644 test/vcc/cpp/vec_swizzle.cpp create mode 100644 vcc-std/src/test_vec.cpp diff --git a/test/vcc/CMakeLists.txt b/test/vcc/CMakeLists.txt index daabec251..a06d48bda 100644 --- a/test/vcc/CMakeLists.txt +++ b/test/vcc/CMakeLists.txt @@ -20,3 +20,5 @@ spv_outputting_test(NAME test/vcc/empty.comp.c COMPILER vcc EXTRA_ARGS ${VCC_TES spv_outputting_test(NAME test/vcc/simple.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --execution-model Fragment) spv_outputting_test(NAME test/vcc/checkerboard.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --execution-model Fragment) spv_outputting_test(NAME test/vcc/textured.frag.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --execution-model Fragment) + +add_subdirectory(cpp) diff --git a/test/vcc/cpp/CMakeLists.txt b/test/vcc/cpp/CMakeLists.txt new file mode 100644 index 000000000..69f218b47 --- /dev/null +++ b/test/vcc/cpp/CMakeLists.txt @@ -0,0 +1 @@ +spv_outputting_test(NAME test/vcc/cpp/vec_swizzle.cpp COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point test --execution-model Fragment --std=c++20) diff --git a/test/vcc/cpp/vec_swizzle.cpp b/test/vcc/cpp/vec_swizzle.cpp new file mode 100644 index 000000000..6635367e3 --- /dev/null +++ b/test/vcc/cpp/vec_swizzle.cpp @@ -0,0 +1,17 @@ +#include + +using namespace vcc; + +extern "C" { + +location(0) vec3 vertexColor; +location(0) vec4 outColor; + +fragment_shader void test() { + vec4 a; + a.xyz = vertexColor; + a.w = 1.0f; + outColor = a; +} + +} \ No newline at end of file diff --git a/vcc-std/CMakeLists.txt b/vcc-std/CMakeLists.txt index 882824b1f..335a17fb4 100644 --- a/vcc-std/CMakeLists.txt +++ b/vcc-std/CMakeLists.txt @@ -1,4 +1,9 @@ add_custom_target(copy-vcc-files ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/../share/vcc/include/) add_dependencies(shady copy-vcc-files) +enable_language(CXX) +add_executable(test_vcc_vec src/test_vec.cpp) +target_include_directories(test_vcc_vec PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/) +set_property(TARGET test_vcc_vec PROPERTY CXX_STANDARD 20) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../share/vcc/ DESTINATION share/vcc) diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index 9e594f95a..933cdfc71 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -28,9 +28,17 @@ namespace vcc { #define shared __attribute__((address_space(3))) #define private __attribute__((address_space(5))) +#if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) +} +#endif + #include "shady_vec.h" #include "shady_mat.h" +#if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) +namespace vcc { +#endif + typedef __attribute__((address_space(0x1000))) struct __shady_builtin_sampler2D* sampler2D; vec4 texture2D(const sampler2D, native_vec2) __asm__("shady::prim_op::sample_texture"); diff --git a/vcc-std/include/shady_mat.h b/vcc-std/include/shady_mat.h index 06bdfa067..0bc719804 100644 --- a/vcc-std/include/shady_mat.h +++ b/vcc-std/include/shady_mat.h @@ -1,8 +1,14 @@ -#define Mat4f mat4 -#define Vec4f vec4 -#define Vec3f vec3 +#if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) +namespace vcc { +#endif -typedef union { +typedef union mat4_ mat4; + +mat4 transpose_mat4(mat4 src); +mat4 mul_mat4(mat4 l, mat4 r); +vec4 mul_mat4_vec4f(mat4 l, vec4 r); + +union mat4_ { struct { // we use row-major ordering float m00, m01, m02, m03, @@ -10,19 +16,30 @@ typedef union { m20, m21, m22, m23, m30, m31, m32, m33; }; - //Vec4f rows[4]; + //vec4 rows[4]; float arr[16]; -} Mat4f; -static const Mat4f identity_mat4f = { + +#if defined(__cplusplus) + mat4 operator*(const mat4& other) { + return mul_mat4(*this, other); + } + + vec4 operator*(const vec4& other) { + return mul_mat4_vec4f(*this, other); + } +#endif +}; + +static const mat4 identity_mat4 = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, }; -Mat4f transpose_mat4f(Mat4f src) { - return (Mat4f) { +mat4 transpose_mat4(mat4 src) { + return (mat4) { src.m00, src.m10, src.m20, src.m30, src.m01, src.m11, src.m21, src.m31, src.m02, src.m12, src.m22, src.m32, @@ -30,7 +47,7 @@ Mat4f transpose_mat4f(Mat4f src) { }; } -Mat4f invert_mat4(Mat4f m) { +mat4 invert_mat4(mat4 m) { float a = m.m00 * m.m11 - m.m01 * m.m10; float b = m.m00 * m.m12 - m.m02 * m.m10; float c = m.m00 * m.m13 - m.m03 * m.m10; @@ -45,7 +62,7 @@ Mat4f invert_mat4(Mat4f m) { float l = m.m22 * m.m33 - m.m23 * m.m32; float det = a * l - b * k + c * j + d * i - e * h + f * g; det = 1.0f / det; - Mat4f r; + mat4 r; r.m00 = ( m.m11 * l - m.m12 * k + m.m13 * j) * det; r.m01 = (-m.m01 * l + m.m02 * k - m.m03 * j) * det; r.m02 = ( m.m31 * f - m.m32 * e + m.m33 * d) * det; @@ -65,10 +82,10 @@ Mat4f invert_mat4(Mat4f m) { return r; } -/*Mat4f perspective_mat4f(float a, float fov, float n, float f) { +/*mat4 perspective_mat4(float a, float fov, float n, float f) { float pi = M_PI; float s = 1.0f / tanf(fov * 0.5f * (pi / 180.0f)); - return (Mat4f) { + return (mat4) { s / a, 0, 0, 0, 0, s, 0, 0, 0, 0, -f / (f - n), -1.f, @@ -76,16 +93,16 @@ Mat4f invert_mat4(Mat4f m) { }; }*/ -Mat4f translate_mat4f(Vec3f offset) { - Mat4f m = identity_mat4f; +mat4 translate_mat4(vec3 offset) { + mat4 m = identity_mat4; m.m30 = offset.x; m.m31 = offset.y; m.m32 = offset.z; return m; } -/*Mat4f rotate_axis_mat4f(unsigned int axis, float f) { - Mat4f m = { 0 }; +/*mat4 rotate_axis_mat4(unsigned int axis, float f) { + mat4 m = { 0 }; m.m33 = 1; unsigned int t = (axis + 2) % 3; @@ -102,8 +119,8 @@ Mat4f translate_mat4f(Vec3f offset) { return m; }*/ -Mat4f mul_mat4f(Mat4f l, Mat4f r) { - Mat4f dst = { 0 }; +mat4 mul_mat4(mat4 l, mat4 r) { + mat4 dst = { 0 }; #define a(i, j) m##i##j #define t(bc, br, i) l.a(i, br) * r.a(bc, i) #define e(bc, br) dst.a(bc, br) = t(bc, br, 0) + t(bc, br, 1) + t(bc, br, 2) + t(bc, br, 3); @@ -118,7 +135,7 @@ Mat4f mul_mat4f(Mat4f l, Mat4f r) { #undef genmul } -Vec4f mul_mat4f_vec4f(Mat4f l, Vec4f r) { +vec4 mul_mat4_vec4f(mat4 l, vec4 r) { float src[4] = { r.x, r.y, r.z, r.w }; float dst[4]; #define a(i, j) m##i##j @@ -127,8 +144,52 @@ Vec4f mul_mat4f_vec4f(Mat4f l, Vec4f r) { #define row(c) e(c, 0) e(c, 1) e(c, 2) e(c, 3) #define genmul() row(0) genmul() - return (Vec4f) { dst[0], dst[1], dst[2], dst[3] }; + return (vec4) { dst[0], dst[1], dst[2], dst[3] }; } -#if defined(__cplusplus) +typedef union { + struct { + // we use row-major ordering + float m00, m01, m02, + m10, m11, m12, + m20, m21, m22; + }; + //vec4 rows[4]; + float arr[9]; +} Mat3f; + +static const Mat3f identity_mat3f = { + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, +}; + +Mat3f transpose_mat3f(Mat3f src) { + return (Mat3f) { + src.m00, src.m10, src.m20, + src.m01, src.m11, src.m21, + src.m02, src.m12, src.m22, + }; +} + +Mat3f mul_mat3f(Mat3f l, Mat3f r) { + Mat3f dst = { 0 }; +#define a(i, j) m##i##j +#define t(bc, br, i) l.a(i, br) * r.a(bc, i) +#define e(bc, br) dst.a(bc, br) = t(bc, br, 0) + t(bc, br, 1) + t(bc, br, 2); +#define row(c) e(c, 0) e(c, 1) e(c, 2) +#define genmul() row(0) row(1) row(2) + genmul() + return dst; +#undef a +#undef t +#undef e +#undef row +#undef genmul +} + +typedef Mat3f mat3; + +#if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) +} #endif diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index b584602b0..037bf7b47 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -1,7 +1,12 @@ +#if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) +namespace vcc { +#endif + #if defined(__cplusplus) & !defined(SHADY_CPP_NO_WRAPPER_CLASSES) #define SHADY_ENABLE_WRAPPER_CLASSES #endif +#ifdef __clang__ typedef float native_vec4 __attribute__((ext_vector_type(4))); typedef float native_vec3 __attribute__((ext_vector_type(3))); typedef float native_vec2 __attribute__((ext_vector_type(2))); @@ -13,121 +18,209 @@ typedef int native_ivec2 __attribute__((ext_vector_type(2))); typedef unsigned native_uvec4 __attribute__((ext_vector_type(4))); typedef unsigned native_uvec3 __attribute__((ext_vector_type(3))); typedef unsigned native_uvec2 __attribute__((ext_vector_type(2))); +#else +// gcc can't cope with this +typedef float native_vec4 __attribute__((vector_size(16))); +typedef float native_vec3 __attribute__((vector_size(16))); +typedef float native_vec2 __attribute__((vector_size(8))); + +typedef int native_ivec4 __attribute__((vector_size(16))); +typedef int native_ivec3 __attribute__((vector_size(16))); +typedef int native_ivec2 __attribute__((vector_size(8))); + +typedef unsigned native_uvec4 __attribute__((vector_size(16))); +typedef unsigned native_uvec3 __attribute__((vector_size(16))); +typedef unsigned native_uvec2 __attribute__((vector_size(8))); +#endif #ifdef SHADY_ENABLE_WRAPPER_CLASSES -template -struct vec4_impl { - using This = vec4_impl; - float x, y, z, w; - - vec4_impl() {} - vec4_impl(T scalar) : x(scalar), y(scalar), z(scalar), w(scalar) {} - vec4_impl(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} - vec4_impl(Native n) : x(n.x), y(n.y), z(n.z), w(n.w) {} - - operator Native() { - return (Native) { x, y, z, w }; - } - This operator +(This other) { - return This(x + other.x, y + other.y, z + other.z, w + other.w); - } - This operator -(This other) { - return This(x - other.x, y - other.y, z - other.z, w - other.w); - } - This operator *(This other) { - return This(x * other.x, y * other.y, z * other.z, w * other.w); - } - This operator /(This other) { - return This(x / other.x, y / other.y, z / other.z, w / other.w); - } - This operator *(T s) { - return This(x * s, y * s, z * s, w * s); - } - This operator /(T s) { - return This(x / s, y / s, z / s, z / s); - } +template +struct vec_native_type {}; + +template<> struct vec_native_type { using Native = native_vec4; }; +template<> struct vec_native_type { using Native = native_ivec4; }; +template<> struct vec_native_type { using Native = native_uvec4; }; +template<> struct vec_native_type { using Native = native_vec3; }; +template<> struct vec_native_type { using Native = native_ivec3; }; +template<> struct vec_native_type { using Native = native_uvec3; }; +template<> struct vec_native_type { using Native = native_vec2; }; +template<> struct vec_native_type { using Native = native_ivec2; }; +template<> struct vec_native_type { using Native = native_uvec2; }; + +template +struct Mapping { + int data[len]; }; -template -struct vec3_impl { - using This = vec3_impl; - float x, y, z; +template +static consteval bool fits(unsigned len, Mapping mapping) { + for (unsigned i = 0; i < dst_len; i++) { + if (mapping.data[i] >= len) + return false; + } + return true; +} - vec3_impl() {} - vec3_impl(T scalar) : x(scalar), y(scalar), z(scalar) {} - vec3_impl(T x, T y, T z) : x(x), y(y), z(z) {} - vec3_impl(Native n) : x(n.x), y(n.y), z(n.z) {} +template +struct vec_impl { + using This = vec_impl; + using Native = vec_native_type::Native; - operator Native() { - return (Native) { x, y, z }; - } + vec_impl() = default; + vec_impl(T s) {} - This operator +(This other) { - return This(x + other.x, y + other.y, z + other.z); - } - This operator -(This other) { - return This(x - other.x, y - other.y, z - other.z); + vec_impl(T x, T y, T z, T w) requires (len >= 4) { + this->arr[0] = x; + this->arr[1] = y; + this->arr[2] = x; + this->arr[3] = w; } - This operator *(This other) { - return This(x * other.x, y * other.y, z * other.z); + + vec_impl(T x, T y, T z) requires (len >= 3) { + this->arr[0] = x; + this->arr[1] = y; + this->arr[2] = x; } - This operator /(This other) { - return This(x / other.x, y / other.y, z / other.z); + + vec_impl(T x, T y) { + this->arr[0] = x; + this->arr[1] = y; } - This operator *(T s) { - return This(x * s, y * s, z * s); + + vec_impl(Native n) { + for (unsigned i = 0; i < len; i++) + arr[i] = n[i]; } - This operator /(T s) { - return This(x / s, y / s, z / s); + + operator Native() const { + Native n; + for (unsigned i = 0; i < len; i++) + n[i] = arr[i]; + return n; } -}; -template -struct vec2_impl { - using This = vec2_impl; - float x, y; + template mapping> // requires(fits(len, mapping)) + struct Swizzler { + using That = vec_impl; - vec2_impl() {} - vec2_impl(T scalar) : x(scalar), y(scalar) {} - vec2_impl(T x, T y) : x(x), y(y) {} - vec2_impl(Native n) : x(n.x), y(n.y) {} + operator That() const requires(dst_len > 1 && fits(len, mapping)) { + auto src = reinterpret_cast(this); + That dst; + for (int i = 0; i < dst_len; i++) + dst.arr[i] = src->arr[mapping.data[i]]; + return dst; + } - operator Native() { - return (Native) { x, y }; - } + operator T() const requires(dst_len == 1 && fits(len, mapping)) { + auto src = reinterpret_cast(this); + return *src; + } + + void operator=(const T& t) requires(dst_len == 1 && fits(len, mapping)) { + auto src = reinterpret_cast(this); + *src = t; + } + + void operator=(const That& src) requires(dst_len > 1 && fits(len, mapping)) { + auto dst = reinterpret_cast(this); + for (int i = 0; i < dst_len; i++) + dst->arr[mapping.data[i]] = src.arr[i]; + } + }; This operator +(This other) { - return This(x + other.x, y + other.y); + This result; + for (unsigned i = 0; i < len; i++) + result[i] = this->arr[i] + other.arr[i]; + return result; } This operator -(This other) { - return This(x - other.x, y - other.y); + This result; + for (unsigned i = 0; i < len; i++) + result[i] = this->arr[i] - other.arr[i]; + return result; } This operator *(This other) { - return This(x * other.x, y * other.y); + This result; + for (unsigned i = 0; i < len; i++) + result[i] = this->arr[i] * other.arr[i]; + return result; } This operator /(This other) { - return This(x / other.x, y / other.y); + This result; + for (unsigned i = 0; i < len; i++) + result[i] = this->arr[i] / other.arr[i]; + return result; } This operator *(T s) { - return This(x * s, y * s); + This result; + for (unsigned i = 0; i < len; i++) + result[i] = this->arr[i] * s; + return result; } This operator /(T s) { - return This(x / s, y / s); - } + This result; + for (unsigned i = 0; i < len; i++) + result[i] = this->arr[i] / s; + return result; + } + +#define COMPONENT_0 x +#define COMPONENT_1 y +#define COMPONENT_2 z +#define COMPONENT_3 w + +#define CONCAT_4_(a, b, c, d) a##b##c##d +#define CONCAT_4(a, b, c, d) CONCAT_4_(a, b, c, d) +#define SWIZZLER_4(a, b, c, d) Swizzler<4, { a, b, c, d }> CONCAT_4(COMPONENT_##a, COMPONENT_##b, COMPONENT_##c, COMPONENT_##d); +#define GEN_SWIZZLERS_4_D(D, C, B, A) SWIZZLER_4(A, B, C, D) +#define GEN_SWIZZLERS_4_C(C, B, A) GEN_SWIZZLERS_4_D(0, C, B, A) GEN_SWIZZLERS_4_D(1, C, B, A) GEN_SWIZZLERS_4_D(2, C, B, A) GEN_SWIZZLERS_4_D(3, C, B, A) +#define GEN_SWIZZLERS_4_B(B, A) GEN_SWIZZLERS_4_C(0, B, A) GEN_SWIZZLERS_4_C(1, B, A) GEN_SWIZZLERS_4_C(2, B, A) GEN_SWIZZLERS_4_C(3, B, A) +#define GEN_SWIZZLERS_4_A(A) GEN_SWIZZLERS_4_B(0, A) GEN_SWIZZLERS_4_B(1, A) GEN_SWIZZLERS_4_B(2, A) GEN_SWIZZLERS_4_B(3, A) +#define GEN_SWIZZLERS_4() GEN_SWIZZLERS_4_A(0) GEN_SWIZZLERS_4_A(1) GEN_SWIZZLERS_4_A(2) GEN_SWIZZLERS_4_A(3) + +#define CONCAT_3_(a, b, c) a##b##c +#define CONCAT_3(a, b, c) CONCAT_3_(a, b, c) +#define SWIZZLER_3(a, b, c) Swizzler<3, { a, b, c }> CONCAT_3(COMPONENT_##a, COMPONENT_##b, COMPONENT_##c); +#define GEN_SWIZZLERS_3_C(C, B, A) SWIZZLER_3(A, B, C) +#define GEN_SWIZZLERS_3_B(B, A) GEN_SWIZZLERS_3_C(0, B, A) GEN_SWIZZLERS_3_C(1, B, A) GEN_SWIZZLERS_3_C(2, B, A) GEN_SWIZZLERS_3_C(3, B, A) +#define GEN_SWIZZLERS_3_A(A) GEN_SWIZZLERS_3_B(0, A) GEN_SWIZZLERS_3_B(1, A) GEN_SWIZZLERS_3_B(2, A) GEN_SWIZZLERS_3_B(3, A) +#define GEN_SWIZZLERS_3() GEN_SWIZZLERS_3_A(0) GEN_SWIZZLERS_3_A(1) GEN_SWIZZLERS_3_A(2) GEN_SWIZZLERS_3_A(3) + +#define CONCAT_2_(a, b) a##b +#define CONCAT_2(a, b) CONCAT_2_(a, b) +#define SWIZZLER_2(a, b) Swizzler<2, { a, b }> CONCAT_2(COMPONENT_##a, COMPONENT_##b); +#define GEN_SWIZZLERS_2_B(B, A) SWIZZLER_2(A, B) +#define GEN_SWIZZLERS_2_A(A) GEN_SWIZZLERS_2_B(0, A) GEN_SWIZZLERS_2_B(1, A) GEN_SWIZZLERS_2_B(2, A) GEN_SWIZZLERS_2_B(3, A) +#define GEN_SWIZZLERS_2() GEN_SWIZZLERS_2_A(0) GEN_SWIZZLERS_2_A(1) GEN_SWIZZLERS_2_A(2) GEN_SWIZZLERS_2_A(3) + +#define SWIZZLER_1(a) Swizzler<1, { a }> COMPONENT_##a; +#define GEN_SWIZZLERS_1_A(A) SWIZZLER_1(A) +#define GEN_SWIZZLERS_1() GEN_SWIZZLERS_1_A(0) GEN_SWIZZLERS_1_A(1) GEN_SWIZZLERS_1_A(2) GEN_SWIZZLERS_1_A(3) + + union { + GEN_SWIZZLERS_1() + GEN_SWIZZLERS_2() + GEN_SWIZZLERS_3() + GEN_SWIZZLERS_4() + T arr[len]; + }; + + static_assert(sizeof(T) * len == sizeof(arr)); }; -typedef vec4_impl vec4; -typedef vec4_impl uvec4; -typedef vec4_impl ivec4; +typedef vec_impl vec4; +typedef vec_impl uvec4; +typedef vec_impl ivec4; -typedef vec3_impl vec3; -typedef vec3_impl uvec3; -typedef vec3_impl ivec3; +typedef vec_impl vec3; +typedef vec_impl uvec3; +typedef vec_impl ivec3; -typedef vec2_impl vec2; -typedef vec2_impl uvec2; -typedef vec2_impl ivec2; +typedef vec_impl vec2; +typedef vec_impl uvec2; +typedef vec_impl ivec2; #else typedef native_vec4 vec4; typedef native_vec3 vec3; @@ -139,3 +232,7 @@ typedef native_uvec4 uvec4; typedef native_uvec3 uvec3; typedef native_uvec2 uvec2; #endif + +#if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) +} +#endif diff --git a/vcc-std/src/test_vec.cpp b/vcc-std/src/test_vec.cpp new file mode 100644 index 000000000..26613c2bb --- /dev/null +++ b/vcc-std/src/test_vec.cpp @@ -0,0 +1,48 @@ +#define __SHADY__ + +#include +#include "shady_vec.h" + +using namespace vcc; + +void check_native_casts(const vec4& v4, const uvec4& u4, const ivec4& i4) { + native_vec4 nv4 = v4; + native_uvec4 nu4 = u4; + native_ivec4 ni4 = i4; + vec4 rv4 = nv4; +} + +void check_vector_scalar_ctors() { + vec4 x4 = vec4(0.5f); + vec4 y4 = { 0.5f }; + vec4 z4(0.5f); + vec4 w4 = 0.5f; + + vec3 x3 = vec3(0.5f); + vec3 y3 = { 0.5f }; + vec3 z3(0.5f); + vec3 w3 = 0.5f; + + vec2 x2 = vec2(0.5f); + vec2 y2 = { 0.5f }; + vec2 z2(0.5f); + vec2 w2 = 0.5f; +} + +void check_swizzle_const(const vec4& v) { + float f = v.x; + vec2 v2 = v.xy; + //float err = v2.w; +} + +void check_swizzle_mut(vec4& v) { + v.x = 0.5f; + v.xy = vec2(0.5f, 0.9f); +} + +int main(int argc, char** argv) { + { + vec4 x; + } + std::unique_ptr uptr; +} \ No newline at end of file From e335cffc3c0787e256d74bf28d209a8cfb899d90 Mon Sep 17 00:00:00 2001 From: gob Date: Sat, 13 Jul 2024 21:35:01 +0200 Subject: [PATCH 314/693] fix msvc (hopefully) --- vcc-std/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/vcc-std/CMakeLists.txt b/vcc-std/CMakeLists.txt index 335a17fb4..3dd2b83ac 100644 --- a/vcc-std/CMakeLists.txt +++ b/vcc-std/CMakeLists.txt @@ -1,9 +1,11 @@ add_custom_target(copy-vcc-files ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/../share/vcc/include/) add_dependencies(shady copy-vcc-files) -enable_language(CXX) -add_executable(test_vcc_vec src/test_vec.cpp) -target_include_directories(test_vcc_vec PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/) -set_property(TARGET test_vcc_vec PROPERTY CXX_STANDARD 20) +if (NOT MSVC) + enable_language(CXX) + add_executable(test_vcc_vec src/test_vec.cpp) + target_include_directories(test_vcc_vec PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/) + set_property(TARGET test_vcc_vec PROPERTY CXX_STANDARD 20) +endif () install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../share/vcc/ DESTINATION share/vcc) From b2299286e86f1dfd47e86917aa4dd98df559f7fe Mon Sep 17 00:00:00 2001 From: gob Date: Sat, 13 Jul 2024 21:37:09 +0200 Subject: [PATCH 315/693] make slim_parser no longer STATIC --- src/frontend/slim/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/slim/CMakeLists.txt b/src/frontend/slim/CMakeLists.txt index f81180d41..233fdedd0 100644 --- a/src/frontend/slim/CMakeLists.txt +++ b/src/frontend/slim/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(slim_parser STATIC parser.c token.c) +add_library(slim_parser parser.c token.c) target_link_libraries(slim_parser PUBLIC common api) target_link_libraries(slim_parser PRIVATE shady) target_include_directories(slim_parser PUBLIC $) From 79c45c9d50feb87ac3be5c4d64516c874f3fc675 Mon Sep 17 00:00:00 2001 From: gob Date: Sat, 13 Jul 2024 21:47:00 +0200 Subject: [PATCH 316/693] make 'shady' target internal --- src/driver/CMakeLists.txt | 4 ++-- src/frontend/slim/CMakeLists.txt | 4 ++-- src/shady/CMakeLists.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index d37b69928..16a872764 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(driver driver.c cli.c) -target_link_libraries(driver PUBLIC "api") -target_link_libraries(driver PUBLIC "shady") +target_link_libraries(driver PUBLIC "api" common) +target_link_libraries(driver PRIVATE "$") set_target_properties(driver PROPERTIES OUTPUT_NAME "shady_driver") install(TARGETS driver EXPORT shady_export_set) diff --git a/src/frontend/slim/CMakeLists.txt b/src/frontend/slim/CMakeLists.txt index 233fdedd0..6df10e398 100644 --- a/src/frontend/slim/CMakeLists.txt +++ b/src/frontend/slim/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(slim_parser parser.c token.c) +add_library(slim_parser STATIC parser.c token.c) target_link_libraries(slim_parser PUBLIC common api) target_link_libraries(slim_parser PRIVATE shady) target_include_directories(slim_parser PUBLIC $) -target_link_libraries(shady PUBLIC "$") +target_link_libraries(shady PRIVATE "$") diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 645a8e7bf..1b83487e7 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -99,7 +99,7 @@ set(SHADY_SOURCES passes/spirv_lift_globals_ssbo.c ) -add_library(shady ${SHADY_SOURCES}) +add_library(shady STATIC ${SHADY_SOURCES}) target_include_directories(shady PUBLIC $) if (WIN32) @@ -118,4 +118,4 @@ target_link_libraries(shady PRIVATE "$") target_link_libraries(shady PRIVATE "$") install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/shady DESTINATION include) -install(TARGETS shady EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) +#install(TARGETS shady EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) From 1de6b763259f91ef53d1cb05bdf79b47c831e59b Mon Sep 17 00:00:00 2001 From: gob Date: Sat, 13 Jul 2024 22:09:02 +0200 Subject: [PATCH 317/693] zhady: don't use wildcard --- zhady/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zhady/CMakeLists.txt b/zhady/CMakeLists.txt index 62aeb42e7..aef26245d 100644 --- a/zhady/CMakeLists.txt +++ b/zhady/CMakeLists.txt @@ -23,12 +23,18 @@ if (SWIG_FOUND AND JNI_FOUND AND Java_FOUND) include(UseJava) get_property(zhady_jar_sources TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES) - set(CMAKE_JAVA_COMPILE_FLAGS ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady/*.java) + get_property(zhady_jar_sources_dir TARGET zhady_shared_lib PROPERTY SWIG_SUPPORT_FILES_DIRECTORY) + #set(CMAKE_JAVA_COMPILE_FLAGS ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady/*.java) + #set(CMAKE_JAVA_COMPILE_FLAGS "-sourcepath" "${CMAKE_CURRENT_BINARY_DIR}/java_sources/") if (TARGET vcc_lib) get_property(vcc_java_sources TARGET vcc_swig_c PROPERTY SWIG_SUPPORT_FILES) list(APPEND zhady_jar_sources ${vcc_java_sources}) endif () + + # message("Zhady sources: ${zhady_jar_sources}") + # message("Zhady sources dir: ${zhady_jar_sources_dir}") + set(CMAKE_JAVA_INCLUDE_PATH ${CMAKE_CURRENT_BINARY_DIR}/java_sources/) add_jar(zhady_jar SOURCES ${zhady_jar_sources}) install(TARGETS zhady_shared_lib EXPORT shady_export_set) From 1f1a3b5d886a1b6bede6ba34fc105d4d00a284db Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Jul 2024 23:51:50 +0200 Subject: [PATCH 318/693] shady_vec.h: should build with older Clang --- vcc-std/include/shady_vec.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index 037bf7b47..39e2bc3f5 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -34,7 +34,6 @@ typedef unsigned native_uvec2 __attribute__((vector_size(8))); #endif #ifdef SHADY_ENABLE_WRAPPER_CLASSES - template struct vec_native_type {}; @@ -173,7 +172,7 @@ struct vec_impl { #define CONCAT_4_(a, b, c, d) a##b##c##d #define CONCAT_4(a, b, c, d) CONCAT_4_(a, b, c, d) -#define SWIZZLER_4(a, b, c, d) Swizzler<4, { a, b, c, d }> CONCAT_4(COMPONENT_##a, COMPONENT_##b, COMPONENT_##c, COMPONENT_##d); +#define SWIZZLER_4(a, b, c, d) Swizzler<4, Mapping<4> { a, b, c, d }> CONCAT_4(COMPONENT_##a, COMPONENT_##b, COMPONENT_##c, COMPONENT_##d); #define GEN_SWIZZLERS_4_D(D, C, B, A) SWIZZLER_4(A, B, C, D) #define GEN_SWIZZLERS_4_C(C, B, A) GEN_SWIZZLERS_4_D(0, C, B, A) GEN_SWIZZLERS_4_D(1, C, B, A) GEN_SWIZZLERS_4_D(2, C, B, A) GEN_SWIZZLERS_4_D(3, C, B, A) #define GEN_SWIZZLERS_4_B(B, A) GEN_SWIZZLERS_4_C(0, B, A) GEN_SWIZZLERS_4_C(1, B, A) GEN_SWIZZLERS_4_C(2, B, A) GEN_SWIZZLERS_4_C(3, B, A) @@ -182,7 +181,7 @@ struct vec_impl { #define CONCAT_3_(a, b, c) a##b##c #define CONCAT_3(a, b, c) CONCAT_3_(a, b, c) -#define SWIZZLER_3(a, b, c) Swizzler<3, { a, b, c }> CONCAT_3(COMPONENT_##a, COMPONENT_##b, COMPONENT_##c); +#define SWIZZLER_3(a, b, c) Swizzler<3, Mapping<3> { a, b, c }> CONCAT_3(COMPONENT_##a, COMPONENT_##b, COMPONENT_##c); #define GEN_SWIZZLERS_3_C(C, B, A) SWIZZLER_3(A, B, C) #define GEN_SWIZZLERS_3_B(B, A) GEN_SWIZZLERS_3_C(0, B, A) GEN_SWIZZLERS_3_C(1, B, A) GEN_SWIZZLERS_3_C(2, B, A) GEN_SWIZZLERS_3_C(3, B, A) #define GEN_SWIZZLERS_3_A(A) GEN_SWIZZLERS_3_B(0, A) GEN_SWIZZLERS_3_B(1, A) GEN_SWIZZLERS_3_B(2, A) GEN_SWIZZLERS_3_B(3, A) @@ -190,12 +189,12 @@ struct vec_impl { #define CONCAT_2_(a, b) a##b #define CONCAT_2(a, b) CONCAT_2_(a, b) -#define SWIZZLER_2(a, b) Swizzler<2, { a, b }> CONCAT_2(COMPONENT_##a, COMPONENT_##b); +#define SWIZZLER_2(a, b) Swizzler<2, Mapping<2> { a, b }> CONCAT_2(COMPONENT_##a, COMPONENT_##b); #define GEN_SWIZZLERS_2_B(B, A) SWIZZLER_2(A, B) #define GEN_SWIZZLERS_2_A(A) GEN_SWIZZLERS_2_B(0, A) GEN_SWIZZLERS_2_B(1, A) GEN_SWIZZLERS_2_B(2, A) GEN_SWIZZLERS_2_B(3, A) #define GEN_SWIZZLERS_2() GEN_SWIZZLERS_2_A(0) GEN_SWIZZLERS_2_A(1) GEN_SWIZZLERS_2_A(2) GEN_SWIZZLERS_2_A(3) -#define SWIZZLER_1(a) Swizzler<1, { a }> COMPONENT_##a; +#define SWIZZLER_1(a) Swizzler<1, Mapping<1> { a }> COMPONENT_##a; #define GEN_SWIZZLERS_1_A(A) SWIZZLER_1(A) #define GEN_SWIZZLERS_1() GEN_SWIZZLERS_1_A(0) GEN_SWIZZLERS_1_A(1) GEN_SWIZZLERS_1_A(2) GEN_SWIZZLERS_1_A(3) From 4331cadbfa7829e8ad1d0f8549786d822c2bb69b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 13 Jul 2024 23:54:50 +0200 Subject: [PATCH 319/693] add missing typename --- vcc-std/include/shady_vec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index 39e2bc3f5..c36d951bd 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -64,7 +64,7 @@ static consteval bool fits(unsigned len, Mapping mapping) { template struct vec_impl { using This = vec_impl; - using Native = vec_native_type::Native; + using Native = typename vec_native_type::Native; vec_impl() = default; vec_impl(T s) {} From d18ca66dd295763128bd6eb6d7c320cfcedf185e Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 14 Jul 2024 10:42:58 +0200 Subject: [PATCH 320/693] vcc-std: more vector constructors --- vcc-std/include/shady_vec.h | 25 ++++++++- vcc-std/src/test_vec.cpp | 107 ++++++++++++++++++++---------------- 2 files changed, 84 insertions(+), 48 deletions(-) diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index c36d951bd..a81950bc8 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -46,6 +46,9 @@ template<> struct vec_native_type { using Native = native_uvec3; }; template<> struct vec_native_type { using Native = native_vec2; }; template<> struct vec_native_type { using Native = native_ivec2; }; template<> struct vec_native_type { using Native = native_uvec2; }; +template<> struct vec_native_type { using Native = float; }; +template<> struct vec_native_type { using Native = int; }; +template<> struct vec_native_type { using Native = unsigned; }; template struct Mapping { @@ -67,7 +70,10 @@ struct vec_impl { using Native = typename vec_native_type::Native; vec_impl() = default; - vec_impl(T s) {} + vec_impl(T s) { + for (unsigned i = 0; i < len; i++) + arr[i] = s; + } vec_impl(T x, T y, T z, T w) requires (len >= 4) { this->arr[0] = x; @@ -76,12 +82,23 @@ struct vec_impl { this->arr[3] = w; } + vec_impl(vec_impl xy, T z, T w) requires (len >= 4) : vec_impl(xy.x, xy.y, z, w) {} + vec_impl(T x, vec_impl yz, T w) requires (len >= 4) : vec_impl(x, yz.x, yz.y, w) {} + vec_impl(T x, T y, vec_impl zw) requires (len >= 4) : vec_impl(x, y, zw.x, zw.y) {} + vec_impl(vec_impl xy, vec_impl zw) requires (len >= 4) : vec_impl(xy.x, xy.y, zw.x, zw.y) {} + + vec_impl(vec_impl xyz, T w) requires (len >= 4) : vec_impl(xyz.x, xyz.y, xyz.z, w) {} + vec_impl(T x, vec_impl yzw) requires (len >= 4) : vec_impl(x, yzw.x, yzw.y, yzw.z) {} + vec_impl(T x, T y, T z) requires (len >= 3) { this->arr[0] = x; this->arr[1] = y; this->arr[2] = x; } + vec_impl(vec_impl xy, T z) requires (len >= 3) : vec_impl(xy.x, xy.y, z) {} + vec_impl(T x, vec_impl yz) requires (len >= 3) : vec_impl(x, yz.x, yz.y) {} + vec_impl(T x, T y) { this->arr[0] = x; this->arr[1] = y; @@ -102,6 +119,7 @@ struct vec_impl { template mapping> // requires(fits(len, mapping)) struct Swizzler { using That = vec_impl; + using ThatNative = vec_native_type::Native; operator That() const requires(dst_len > 1 && fits(len, mapping)) { auto src = reinterpret_cast(this); @@ -111,6 +129,11 @@ struct vec_impl { return dst; } + operator ThatNative() const requires(dst_len > 1 && fits(len, mapping)) { + That that = *this; + return that; + } + operator T() const requires(dst_len == 1 && fits(len, mapping)) { auto src = reinterpret_cast(this); return *src; diff --git a/vcc-std/src/test_vec.cpp b/vcc-std/src/test_vec.cpp index 26613c2bb..d0b648243 100644 --- a/vcc-std/src/test_vec.cpp +++ b/vcc-std/src/test_vec.cpp @@ -1,48 +1,61 @@ -#define __SHADY__ - -#include -#include "shady_vec.h" - -using namespace vcc; - -void check_native_casts(const vec4& v4, const uvec4& u4, const ivec4& i4) { - native_vec4 nv4 = v4; - native_uvec4 nu4 = u4; - native_ivec4 ni4 = i4; - vec4 rv4 = nv4; -} - -void check_vector_scalar_ctors() { - vec4 x4 = vec4(0.5f); - vec4 y4 = { 0.5f }; - vec4 z4(0.5f); - vec4 w4 = 0.5f; - - vec3 x3 = vec3(0.5f); - vec3 y3 = { 0.5f }; - vec3 z3(0.5f); - vec3 w3 = 0.5f; - - vec2 x2 = vec2(0.5f); - vec2 y2 = { 0.5f }; - vec2 z2(0.5f); - vec2 w2 = 0.5f; -} - -void check_swizzle_const(const vec4& v) { - float f = v.x; - vec2 v2 = v.xy; - //float err = v2.w; -} - -void check_swizzle_mut(vec4& v) { - v.x = 0.5f; - v.xy = vec2(0.5f, 0.9f); -} - -int main(int argc, char** argv) { - { - vec4 x; - } - std::unique_ptr uptr; +#define __SHADY__ + +#include +#include "shady_vec.h" + +using namespace vcc; + +void check_native_casts(const vec4& v4, const uvec4& u4, const ivec4& i4) { + native_vec4 nv4 = v4; + native_uvec4 nu4 = u4; + native_ivec4 ni4 = i4; + vec4 rv4 = nv4; + native_vec3 nv3; + nv3 = v4.xyz; +} + +void check_vector_scalar_ctors() { + vec4 x4 = vec4(0.5f); + vec4 y4 = { 0.5f }; + vec4 z4(0.5f); + vec4 w4 = 0.5f; + + vec3 x3 = vec3(0.5f); + vec3 y3 = { 0.5f }; + vec3 z3(0.5f); + vec3 w3 = 0.5f; + + vec2 x2 = vec2(0.5f); + vec2 y2 = { 0.5f }; + vec2 z2(0.5f); + vec2 w2 = 0.5f; +} + +void check_swizzle_const(const vec4& v4, const uvec4& u4, const ivec4& i4) { + v4.x; + v4.xy; + v4.xyz; + v4.xyzw; + + v4.xxxx; + v4.xyww; +} + +void check_ctor_weird() { + vec4(vec2(0.5f), vec2(0.5f)); + vec4(0.5f, vec2(0.5f), 0.5f); + vec4(0.5f, vec3(0.5f)); + vec4(vec3(0.5f), 0.5f); +} + +void check_swizzle_mut(vec4& v) { + v.x = 0.5f; + v.xy = vec2(0.5f, 0.9f); +} + +int main(int argc, char** argv) { + { + vec4 x; + } + std::unique_ptr uptr; } \ No newline at end of file From 8f7d26ad74fea679456c4b613fb8d13429f6e117 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 14 Jul 2024 10:44:05 +0200 Subject: [PATCH 321/693] vcc-std: added more texture dimentionalities --- src/frontend/llvm/l2s_type.c | 35 +++++++++++++++++++++++------------ vcc-std/include/shady.h | 8 +++++++- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index 7ca93031b..87ba43acc 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -81,18 +81,29 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { } case LLVMPointerTypeKind: { unsigned int llvm_as = LLVMGetPointerAddressSpace(t); - switch (llvm_as) { - case 0x1000: return sampled_image_type(a, (SampledImageType) { .image_type = image_type(a, (ImageType) { - //.sampled_type = pack_type(a, (PackType) { .element_type = float_type(a, (Float) { .width = FloatTy32 }), .width = 4 }), - .sampled_type = float_type(a, (Float) { .width = FloatTy32 }), - .dim = 1, - .depth = 0, - .arrayed = 0, - .ms = 0, - .sampled = 1, - .imageformat = 0 - } ) }); - default: break; + if (llvm_as >= 0x1000 && llvm_as <= 0x2000) { + unsigned offset = llvm_as - 0x1000; + unsigned dim = offset & 0xF; + unsigned type_id = (offset >> 4) & 0x3; + const Type* sampled_type = NULL; + switch (type_id) { + case 0x0: sampled_type = float_type(a, (Float) {.width = FloatTy32}); break; + case 0x1: sampled_type = int32_type(a); break; + case 0x2: sampled_type = uint32_type(a); break; + default: assert(false); + } + bool arrayed = (offset >> 6) & 1; + + return sampled_image_type(a, (SampledImageType) {.image_type = image_type(a, (ImageType) { + //.sampled_type = pack_type(a, (PackType) { .element_type = float_type(a, (Float) { .width = FloatTy32 }), .width = 4 }), + .sampled_type = sampled_type, + .dim = dim, + .depth = 0, + .arrayed = arrayed, + .ms = 0, + .sampled = 1, + .imageformat = 0 + })}); } AddressSpace as = convert_llvm_address_space(llvm_as); const Type* pointee = NULL; diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index 933cdfc71..827125bc9 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -39,9 +39,15 @@ namespace vcc { namespace vcc { #endif -typedef __attribute__((address_space(0x1000))) struct __shady_builtin_sampler2D* sampler2D; +typedef __attribute__((address_space(0x1000))) struct __shady_builtin_sampler1D* sampler1D; +typedef __attribute__((address_space(0x1001))) struct __shady_builtin_sampler2D* sampler2D; +typedef __attribute__((address_space(0x1002))) struct __shady_builtin_sampler3D* sampler3D; +typedef __attribute__((address_space(0x1003))) struct __shady_builtin_sampler3D* samplerCube; +vec4 texture1D(const sampler1D, float) __asm__("shady::prim_op::sample_texture"); vec4 texture2D(const sampler2D, native_vec2) __asm__("shady::prim_op::sample_texture"); +vec4 texture3D(const sampler3D, native_vec3) __asm__("shady::prim_op::sample_texture"); +vec4 textureCube(const samplerCube, native_vec3) __asm__("shady::prim_op::sample_texture"); // builtins __attribute__((annotate("shady::builtin::FragCoord"))) From 022c4421b7b1faf725bcb33315c705c577d4d7b9 Mon Sep 17 00:00:00 2001 From: gob Date: Wed, 17 Jul 2024 14:13:51 +0200 Subject: [PATCH 322/693] vcc-std: add normalize, length, fix some intrinsics --- vcc-std/include/shady.h | 15 +++++++++++---- vcc-std/include/shady_mat.h | 16 ++++++++-------- vcc-std/include/shady_vec.h | 31 +++++++++++++++++++++++++------ 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index 827125bc9..c8b7cb033 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -44,10 +44,17 @@ typedef __attribute__((address_space(0x1001))) struct __shady_builtin_sampler2D* typedef __attribute__((address_space(0x1002))) struct __shady_builtin_sampler3D* sampler3D; typedef __attribute__((address_space(0x1003))) struct __shady_builtin_sampler3D* samplerCube; -vec4 texture1D(const sampler1D, float) __asm__("shady::prim_op::sample_texture"); -vec4 texture2D(const sampler2D, native_vec2) __asm__("shady::prim_op::sample_texture"); -vec4 texture3D(const sampler3D, native_vec3) __asm__("shady::prim_op::sample_texture"); -vec4 textureCube(const samplerCube, native_vec3) __asm__("shady::prim_op::sample_texture"); +native_vec4 texture1D(const sampler1D, float) __asm__("shady::prim_op::sample_texture"); +native_vec4 texture2D(const sampler2D, native_vec2) __asm__("shady::prim_op::sample_texture"); +native_vec4 texture3D(const sampler3D, native_vec3) __asm__("shady::prim_op::sample_texture"); +native_vec4 textureCube(const samplerCube, native_vec3) __asm__("shady::prim_op::sample_texture"); + +#if defined(__cplusplus) +native_vec4 texture(const sampler1D, float) __asm__("shady::prim_op::sample_texture"); +native_vec4 texture(const sampler2D, native_vec2) __asm__("shady::prim_op::sample_texture"); +native_vec4 texture(const sampler3D, native_vec3) __asm__("shady::prim_op::sample_texture"); +native_vec4 texture(const samplerCube, native_vec3) __asm__("shady::prim_op::sample_texture"); +#endif // builtins __attribute__((annotate("shady::builtin::FragCoord"))) diff --git a/vcc-std/include/shady_mat.h b/vcc-std/include/shady_mat.h index 0bc719804..bdaabce7d 100644 --- a/vcc-std/include/shady_mat.h +++ b/vcc-std/include/shady_mat.h @@ -4,9 +4,9 @@ namespace vcc { typedef union mat4_ mat4; -mat4 transpose_mat4(mat4 src); -mat4 mul_mat4(mat4 l, mat4 r); -vec4 mul_mat4_vec4f(mat4 l, vec4 r); +static inline mat4 transpose_mat4(mat4 src); +static inline mat4 mul_mat4(mat4 l, mat4 r); +static inline vec4 mul_mat4_vec4f(mat4 l, vec4 r); union mat4_ { struct { @@ -38,7 +38,7 @@ static const mat4 identity_mat4 = { 0, 0, 0, 1, }; -mat4 transpose_mat4(mat4 src) { +static inline mat4 transpose_mat4(mat4 src) { return (mat4) { src.m00, src.m10, src.m20, src.m30, src.m01, src.m11, src.m21, src.m31, @@ -47,7 +47,7 @@ mat4 transpose_mat4(mat4 src) { }; } -mat4 invert_mat4(mat4 m) { +static inline mat4 invert_mat4(mat4 m) { float a = m.m00 * m.m11 - m.m01 * m.m10; float b = m.m00 * m.m12 - m.m02 * m.m10; float c = m.m00 * m.m13 - m.m03 * m.m10; @@ -93,7 +93,7 @@ mat4 invert_mat4(mat4 m) { }; }*/ -mat4 translate_mat4(vec3 offset) { +static inline mat4 translate_mat4(vec3 offset) { mat4 m = identity_mat4; m.m30 = offset.x; m.m31 = offset.y; @@ -119,7 +119,7 @@ mat4 translate_mat4(vec3 offset) { return m; }*/ -mat4 mul_mat4(mat4 l, mat4 r) { +static inline mat4 mul_mat4(mat4 l, mat4 r) { mat4 dst = { 0 }; #define a(i, j) m##i##j #define t(bc, br, i) l.a(i, br) * r.a(bc, i) @@ -135,7 +135,7 @@ mat4 mul_mat4(mat4 l, mat4 r) { #undef genmul } -vec4 mul_mat4_vec4f(mat4 l, vec4 r) { +static inline vec4 mul_mat4_vec4f(mat4 l, vec4 r) { float src[4] = { r.x, r.y, r.z, r.w }; float dst[4]; #define a(i, j) m##i##j diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index a81950bc8..f22fbc3b4 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -154,37 +154,37 @@ struct vec_impl { This operator +(This other) { This result; for (unsigned i = 0; i < len; i++) - result[i] = this->arr[i] + other.arr[i]; + result.arr[i] = this->arr[i] + other.arr[i]; return result; } This operator -(This other) { This result; for (unsigned i = 0; i < len; i++) - result[i] = this->arr[i] - other.arr[i]; + result.arr[i] = this->arr[i] - other.arr[i]; return result; } This operator *(This other) { This result; for (unsigned i = 0; i < len; i++) - result[i] = this->arr[i] * other.arr[i]; + result.arr[i] = this->arr[i] * other.arr[i]; return result; } This operator /(This other) { This result; for (unsigned i = 0; i < len; i++) - result[i] = this->arr[i] / other.arr[i]; + result.arr[i] = this->arr[i] / other.arr[i]; return result; } This operator *(T s) { This result; for (unsigned i = 0; i < len; i++) - result[i] = this->arr[i] * s; + result.arr[i] = this->arr[i] * s; return result; } This operator /(T s) { This result; for (unsigned i = 0; i < len; i++) - result[i] = this->arr[i] / s; + result.arr[i] = this->arr[i] / s; return result; } @@ -243,6 +243,25 @@ typedef vec_impl ivec3; typedef vec_impl vec2; typedef vec_impl uvec2; typedef vec_impl ivec2; + +template +float lengthSquared(vec_impl vec) { + float acc = 0.0f; + for (unsigned i = 0; i < len; i++) + acc += vec.arr[i] * vec.arr[i]; + return acc; +} + +template +float length(vec_impl vec) { + return __builtin_sqrtf(lengthSquared(vec)); +} + +template +vec_impl normalize(vec_impl vec) { + return vec / length(vec); +} + #else typedef native_vec4 vec4; typedef native_vec3 vec3; From 02d042e444a18589a398cf38fbd9d9b0a4bd1c33 Mon Sep 17 00:00:00 2001 From: gob Date: Wed, 17 Jul 2024 14:14:26 +0200 Subject: [PATCH 323/693] move dump fns to dump.h --- include/shady/be/dump.h | 6 ++++++ src/shady/print.h | 7 +------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/shady/be/dump.h b/include/shady/be/dump.h index 350c5b1a4..a8f247ce0 100644 --- a/include/shady/be/dump.h +++ b/include/shady/be/dump.h @@ -1,6 +1,12 @@ #ifndef SHD_BE_DUMP_H #define SHD_BE_DUMP_H +void print_module_into_str(Module* mod, char** str_ptr, size_t* size); +void print_node_into_str(const Node* node, char** str_ptr, size_t* size); + +void dump_module(Module*); +void dump_node(const Node* node); + void dump_cfgs(FILE* output, Module* mod); void dump_loop_trees(FILE* output, Module* mod); diff --git a/src/shady/print.h b/src/shady/print.h index 66e9d85d4..d575c3449 100644 --- a/src/shady/print.h +++ b/src/shady/print.h @@ -2,6 +2,7 @@ #define SHADY_PRINT #include "shady/ir.h" +#include "shady/be/dump.h" #include "printer.h" #include @@ -22,10 +23,4 @@ void print_node_operand_list(Printer* printer, const Node* node, String op_name, void print_node_generated(Printer* printer, const Node* node, PrintConfig config); -void print_module_into_str(Module* mod, char** str_ptr, size_t* size); -void print_node_into_str(const Node* node, char** str_ptr, size_t* size); - -void dump_module(Module*); -void dump_node(const Node* node); - #endif \ No newline at end of file From 9fc1e75a279b11d480ff3bce9feb8843c857f1d9 Mon Sep 17 00:00:00 2001 From: gob Date: Wed, 17 Jul 2024 14:15:16 +0200 Subject: [PATCH 324/693] l2s: couple fixes --- src/frontend/llvm/l2s.c | 2 +- src/frontend/llvm/l2s_instr.c | 4 ++++ src/frontend/llvm/l2s_type.c | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 12f595cc3..c8e8ec797 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -276,7 +276,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* if (global_annotations) process_llvm_annotations(&p, global_annotations); - for (LLVMValueRef fn = LLVMGetFirstFunction(src); fn && fn <= LLVMGetNextFunction(fn); fn = LLVMGetLastFunction(src)) { + for (LLVMValueRef fn = LLVMGetFirstFunction(src); fn; fn = LLVMGetNextFunction(fn)) { convert_function(&p, fn); } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index e80bd999f..e0c8824f4 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -516,6 +516,10 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, // don't care return (EmittedInstr) { 0 }; } + if (string_starts_with(intrinsic, "llvm.experimental.noalias.scope.decl")) { + // don't care + return (EmittedInstr) { 0 }; + } if (string_starts_with(intrinsic, "llvm.memcpy")) { Nodes ops = convert_operands(p, num_ops, instr); num_results = 0; diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index 87ba43acc..1cd5906f0 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -66,7 +66,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { } const Node* product = record_type(a, (RecordType) { - .members = nodes(a, size, celements) + .members = nodes(a, size, celements) }); if (decl) decl->payload.nom_type.body = product; From c1ba2d4a606f3df1f8e227755881bb35e26918ae Mon Sep 17 00:00:00 2001 From: gob Date: Wed, 17 Jul 2024 14:15:31 +0200 Subject: [PATCH 325/693] zhady: add backends to the API --- zhady/shady.i | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/zhady/shady.i b/zhady/shady.i index fa155a38c..1b688b2b4 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -8,9 +8,16 @@ #include "shady/runtime.h" #include "shady/driver.h" #include "shady/config.h" +#include "shady/be/c.h" +#include "shady/be/spirv.h" +#include "shady/be/dump.h" %} %include "shady/ir.h" +%include "grammar_generated.h" %include "shady/driver.h" %include "shady/runtime.h" -%include "shady/config.h" \ No newline at end of file +%include "shady/config.h" +%include "shady/be/c.h" +%include "shady/be/spirv.h" +%include "shady/be/dump.h" \ No newline at end of file From 5e7868f3d9e098de635885b5d2388bdb64c5c257 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 17 Jul 2024 17:12:04 +0200 Subject: [PATCH 326/693] don't use address spaces because Clang bad --- src/frontend/llvm/l2s_annotations.c | 8 +++++--- src/frontend/llvm/l2s_postprocess.c | 20 ++++++++++++++++---- vcc-std/include/shady.h | 16 ++++++++-------- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 5a30e9bee..32e70a738 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -128,11 +128,13 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { .value = int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)) }) }); - } else if (strcmp(keyword, "uniform") == 0) { + } else if (strcmp(keyword, "extern") == 0) { assert(target->tag == GlobalVariable_TAG); + ((Node*) target)->payload.global_variable.init = NULL; add_annotation(p, target, (ParsedAnnotation) { - .payload = annotation(a, (Annotation) { - .name = "UniformConstant" + .payload = annotation_value(a, (AnnotationValue) { + .name = "AddressSpace", + .value = int32_literal(a, convert_llvm_address_space(strtol(strtok(NULL, "::"), NULL, 10))) }) }); } else { diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 2266ecabf..c56c3b0ed 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -272,19 +272,31 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, Nodes annotations = rewrite_nodes(r, node->payload.global_variable.annotations); const Type* type = rewrite_node(r, node->payload.global_variable.type); ParsedAnnotation* an = find_annotation(ctx->p, node); + AddressSpace old_as = as; while (an) { annotations = append_nodes(a, annotations, rewrite_node(r, an->payload)); if (strcmp(get_annotation_name(an->payload), "Builtin") == 0) old_init = NULL; - if (strcmp(get_annotation_name(an->payload), "UniformConstant") == 0) - as = AsUniformConstant; + if (strcmp(get_annotation_name(an->payload), "AddressSpace") == 0) + as = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(an->payload)), false); an = an->next; } Node* decl = global_var(ctx->rewriter.dst_module, annotations, type, get_declaration_name(node), as); - register_processed(r, node, decl); + Node* result = decl; + if (old_as != as) { + const Type* pt = ptr_type(a, (PtrType) { .address_space = old_as, .pointed_type = type }); + Node* c = constant(ctx->rewriter.dst_module, singleton(annotation(a, (Annotation) { + .name = "Inline" + })), pt, format_string_interned(a, "%s_proxy", get_declaration_name(decl))); + c->payload.constant.instruction = prim_op_helper(a, convert_op, singleton(pt), singleton( + ref_decl_helper(a, decl))); + result = c; + } + + register_processed(r, node, result); if (old_init) decl->payload.global_variable.init = rewrite_node(r, old_init); - return decl; + return result; } default: break; } diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index c8b7cb033..2c07c16ec 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -18,15 +18,15 @@ namespace vcc { #define descriptor_binding(i) __attribute__((annotate("shady::descriptor_binding::"#i))) #define local_size(x, y, z) __attribute__((annotate("shady::workgroup_size::"#x"::"#y"::"#z))) -#define input __attribute__((address_space(389))) -#define output __attribute__((address_space(390))) +#define input __attribute__((annotate("shady::extern::389"))) +#define output __attribute__((annotate("shady::extern::390"))) // maybe deprecate it ? -#define uniform_constant __attribute__((address_space(398))) -#define uniform_block __attribute__((address_space(395))) -#define push_constant __attribute__((address_space(392))) -#define global __attribute__((address_space(1))) -#define shared __attribute__((address_space(3))) -#define private __attribute__((address_space(5))) +#define uniform_constant __attribute__((annotate("shady::extern::398"))) +#define uniform_block __attribute__((annotate("shady::extern::395"))) +#define push_constant __attribute__((annotate("shady::extern::392"))) +#define global __attribute__((annotate("shady::extern::1"))) +#define shared __attribute__((annotate("shady::extern::3"))) +#define private __attribute__((annotate("shady::extern::5"))) #if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) } From 224a6e855fd9e1e232e7e022d6586836aa2b2eef Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jul 2024 09:12:49 +0200 Subject: [PATCH 327/693] make AsGeneric accesses not uniform --- src/shady/type.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shady/type.c b/src/shady/type.c index 50ab25d63..48cdb9a3b 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -168,6 +168,7 @@ size_t get_type_bitwidth(const Type* t) { bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { switch (as) { + case AsGeneric: case AsInput: case AsOutput: case AsFunction: From 9cef6825d8d957ae248840dac6668619b1d2db14 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jul 2024 09:16:36 +0200 Subject: [PATCH 328/693] fold_simplify_ptr_operand: allow uniform values to replace varying ones --- src/shady/fold.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/fold.c b/src/shady/fold.c index a7de432cc..ca338f617 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -262,7 +262,7 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { if (rebuild) { const Node* r = prim_op(arena, payload); - if (r->type != node->type) { + if (!is_subtype(node->type, r->type)) { r = gen_conversion(bb, get_unqualified_type(node->type), first(bind_instruction(bb, r))); return yield_values_and_wrap_in_block(bb, singleton(r)); } From f9d716d189ba1a688ffca68b690aa15073cb7ff1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jul 2024 09:19:50 +0200 Subject: [PATCH 329/693] use shady.h in vcc tests instead of custom defines --- test/vcc/address_spaces.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vcc/address_spaces.c b/test/vcc/address_spaces.c index 0e4dab529..f0948d141 100644 --- a/test/vcc/address_spaces.c +++ b/test/vcc/address_spaces.c @@ -1,3 +1,3 @@ -#define global __attribute__((address_space(1))) +#include global int buffer[256]; From 47276a2a3d5475366b35ab401660ab2f0748bb06 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jul 2024 09:32:48 +0200 Subject: [PATCH 330/693] shady_vec.h: check for C++20 presence --- vcc-std/include/shady_vec.h | 1 + 1 file changed, 1 insertion(+) diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index f22fbc3b4..99be65730 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -34,6 +34,7 @@ typedef unsigned native_uvec2 __attribute__((vector_size(8))); #endif #ifdef SHADY_ENABLE_WRAPPER_CLASSES +static_assert(__cplusplus >= 202002L, "C++20 is required"); template struct vec_native_type {}; From a0c5ff6735c8972f998e695ec8b7880db3e25907 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jul 2024 09:33:58 +0200 Subject: [PATCH 331/693] vcc: added C++ version of the texture test --- test/vcc/cpp/CMakeLists.txt | 1 + test/vcc/cpp/textured.frag.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/vcc/cpp/textured.frag.cpp diff --git a/test/vcc/cpp/CMakeLists.txt b/test/vcc/cpp/CMakeLists.txt index 69f218b47..515d0b6d0 100644 --- a/test/vcc/cpp/CMakeLists.txt +++ b/test/vcc/cpp/CMakeLists.txt @@ -1 +1,2 @@ spv_outputting_test(NAME test/vcc/cpp/vec_swizzle.cpp COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point test --execution-model Fragment --std=c++20) +spv_outputting_test(NAME test/vcc/cpp/textured.frag.cpp COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS} --entry-point main --execution-model Fragment --std=c++20) diff --git a/test/vcc/cpp/textured.frag.cpp b/test/vcc/cpp/textured.frag.cpp new file mode 100644 index 000000000..d8fc4a90a --- /dev/null +++ b/test/vcc/cpp/textured.frag.cpp @@ -0,0 +1,19 @@ +#include +#include + +using namespace vcc; + +descriptor_set(0) descriptor_binding(1) uniform_constant sampler2D texSampler; + +location(0) input native_vec3 fragColor; +location(1) input native_vec2 fragTexCoord; + +location(0) output native_vec4 outColor; + +extern "C" { + +fragment_shader void main() { + outColor = texture2D(texSampler, fragTexCoord) * (vec4) { fragColor.x * 2.5f, fragColor.y * 2.5f, fragColor.z * 2.5f, 1.0f }; +} + +} From ef1726721f03ed743a52f8a9011db0a69f5304b2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 18 Jul 2024 13:18:18 +0200 Subject: [PATCH 332/693] shady_vec: use a static for loop so -O0 works --- vcc-std/include/shady_vec.h | 46 +++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index 99be65730..7ad07d9dd 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -65,6 +65,16 @@ static consteval bool fits(unsigned len, Mapping mapping) { return true; } +template +constexpr void for_range(F f) +{ + if constexpr (B < E) + { + f.template operator()(); + for_range((f)); + } +} + template struct vec_impl { using This = vec_impl; @@ -72,8 +82,9 @@ struct vec_impl { vec_impl() = default; vec_impl(T s) { - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ arr[i] = s; + }); } vec_impl(T x, T y, T z, T w) requires (len >= 4) { @@ -106,14 +117,16 @@ struct vec_impl { } vec_impl(Native n) { - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ arr[i] = n[i]; + }); } operator Native() const { Native n; - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ n[i] = arr[i]; + }); return n; } @@ -125,8 +138,9 @@ struct vec_impl { operator That() const requires(dst_len > 1 && fits(len, mapping)) { auto src = reinterpret_cast(this); That dst; - for (int i = 0; i < dst_len; i++) + for_range<0, len>([&](){ dst.arr[i] = src->arr[mapping.data[i]]; + }); return dst; } @@ -147,45 +161,52 @@ struct vec_impl { void operator=(const That& src) requires(dst_len > 1 && fits(len, mapping)) { auto dst = reinterpret_cast(this); - for (int i = 0; i < dst_len; i++) + for_range<0, len>([&](){ dst->arr[mapping.data[i]] = src.arr[i]; + }); } }; This operator +(This other) { This result; - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ result.arr[i] = this->arr[i] + other.arr[i]; + }); return result; } This operator -(This other) { This result; - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ result.arr[i] = this->arr[i] - other.arr[i]; + }); return result; } This operator *(This other) { This result; - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ result.arr[i] = this->arr[i] * other.arr[i]; + }); return result; } This operator /(This other) { This result; - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ result.arr[i] = this->arr[i] / other.arr[i]; + }); return result; } This operator *(T s) { This result; - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ result.arr[i] = this->arr[i] * s; + }); return result; } This operator /(T s) { This result; - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ result.arr[i] = this->arr[i] / s; + }); return result; } @@ -248,8 +269,9 @@ typedef vec_impl ivec2; template float lengthSquared(vec_impl vec) { float acc = 0.0f; - for (unsigned i = 0; i < len; i++) + for_range<0, len>([&](){ acc += vec.arr[i] * vec.arr[i]; + }); return acc; } From 195bff9aa5f470dd7476bab0a38c0bc388655efc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 19 Jul 2024 13:52:26 +0200 Subject: [PATCH 333/693] improved vcc test --- vcc-std/CMakeLists.txt | 1 + vcc-std/src/test_vec.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/vcc-std/CMakeLists.txt b/vcc-std/CMakeLists.txt index 3dd2b83ac..a08742e2a 100644 --- a/vcc-std/CMakeLists.txt +++ b/vcc-std/CMakeLists.txt @@ -6,6 +6,7 @@ if (NOT MSVC) add_executable(test_vcc_vec src/test_vec.cpp) target_include_directories(test_vcc_vec PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/) set_property(TARGET test_vcc_vec PROPERTY CXX_STANDARD 20) + add_test(NAME test_vcc_vec COMMAND test_vcc_vec) endif () install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../share/vcc/ DESTINATION share/vcc) diff --git a/vcc-std/src/test_vec.cpp b/vcc-std/src/test_vec.cpp index d0b648243..92d39e07c 100644 --- a/vcc-std/src/test_vec.cpp +++ b/vcc-std/src/test_vec.cpp @@ -53,9 +53,13 @@ void check_swizzle_mut(vec4& v) { v.xy = vec2(0.5f, 0.9f); } +#include int main(int argc, char** argv) { - { - vec4 x; - } + vec4 v(1.0f, 0.5f, 0.0f, -1.0f); + float f; + f = v.x; printf("f = %f;\n", f); assert(f == 1.0f); + f = v.y; printf("f = %f;\n", f); assert(f == 0.5f); + f = v.z; printf("f = %f;\n", f); assert(f == 0.0f); + f = v.w; printf("f = %f;\n", f); assert(f == -1.0f); std::unique_ptr uptr; } \ No newline at end of file From 3d01cc1d8429e65c8ba5fd7605a31b23ff04a32b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 19 Jul 2024 13:52:42 +0200 Subject: [PATCH 334/693] vcc-std: bugfixes --- vcc-std/include/shady.h | 2 ++ vcc-std/include/shady_vec.h | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/vcc-std/include/shady.h b/vcc-std/include/shady.h index 2c07c16ec..8af86cc0f 100644 --- a/vcc-std/include/shady.h +++ b/vcc-std/include/shady.h @@ -28,6 +28,8 @@ namespace vcc { #define shared __attribute__((annotate("shady::extern::3"))) #define private __attribute__((annotate("shady::extern::5"))) +float sqrtf(float f) __asm__("shady::prim_op::sqrt"); + #if defined(__cplusplus) & !defined(SHADY_CPP_NO_NAMESPACE) } #endif diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index 7ad07d9dd..851db1907 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -90,7 +90,7 @@ struct vec_impl { vec_impl(T x, T y, T z, T w) requires (len >= 4) { this->arr[0] = x; this->arr[1] = y; - this->arr[2] = x; + this->arr[2] = z; this->arr[3] = w; } @@ -105,7 +105,7 @@ struct vec_impl { vec_impl(T x, T y, T z) requires (len >= 3) { this->arr[0] = x; this->arr[1] = y; - this->arr[2] = x; + this->arr[2] = z; } vec_impl(vec_impl xy, T z) requires (len >= 3) : vec_impl(xy.x, xy.y, z) {} @@ -138,7 +138,7 @@ struct vec_impl { operator That() const requires(dst_len > 1 && fits(len, mapping)) { auto src = reinterpret_cast(this); That dst; - for_range<0, len>([&](){ + for_range<0, dst_len>([&](){ dst.arr[i] = src->arr[mapping.data[i]]; }); return dst; @@ -150,18 +150,18 @@ struct vec_impl { } operator T() const requires(dst_len == 1 && fits(len, mapping)) { - auto src = reinterpret_cast(this); - return *src; + auto src = reinterpret_cast(this); + return src->arr[mapping.data[0]]; } void operator=(const T& t) requires(dst_len == 1 && fits(len, mapping)) { - auto src = reinterpret_cast(this); - *src = t; + auto src = reinterpret_cast(this); + src->arr[mapping.data[0]] = t; } void operator=(const That& src) requires(dst_len > 1 && fits(len, mapping)) { auto dst = reinterpret_cast(this); - for_range<0, len>([&](){ + for_range<0, dst_len>([&](){ dst->arr[mapping.data[i]] = src.arr[i]; }); } @@ -277,7 +277,7 @@ float lengthSquared(vec_impl vec) { template float length(vec_impl vec) { - return __builtin_sqrtf(lengthSquared(vec)); + return sqrtf(lengthSquared(vec)); } template From 0ed4a5927ec1e08a79878d0d4cd57dbce48f5eb2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jul 2024 15:25:47 +0200 Subject: [PATCH 335/693] cmake: make dependencies option()nal --- CMakeLists.txt | 5 +- samples/CMakeLists.txt | 8 ++- samples/aobench/CMakeLists.txt | 8 ++- samples/checkerboard/CMakeLists.txt | 15 +++-- src/frontend/CMakeLists.txt | 5 +- src/frontend/llvm/CMakeLists.txt | 46 ++++++++------ src/runtime/CMakeLists.txt | 20 +++--- src/runtime/cuda/CMakeLists.txt | 27 +++++---- src/runtime/vulkan/CMakeLists.txt | 9 ++- test/CMakeLists.txt | 94 +++++++++++++++-------------- vcc/CMakeLists.txt | 12 ++-- zhady/CMakeLists.txt | 12 +++- 12 files changed, 149 insertions(+), 112 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e53682f91..597cd0ec5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,10 +105,7 @@ if (BUILD_TESTING) add_subdirectory(test) endif() -set(BUILD_SAMPLES ON CACHE BOOL "Whether to build built-in demo applications") -if (BUILD_SAMPLES) - add_subdirectory(samples) -endif() +add_subdirectory(samples) include(CMakePackageConfigHelpers) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 2af9c4d93..47f50f483 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -1,4 +1,6 @@ +option(SHADY_ENABLE_SAMPLES "Demo applications and gpu programs" ON) +# TODO: this probably doesn't belong here # find math lib; based on https://stackoverflow.com/a/74867749 find_library(MATH_LIBRARY m) if (MATH_LIBRARY) @@ -8,5 +10,7 @@ else() add_library(m INTERFACE) endif() -add_subdirectory(checkerboard) -add_subdirectory(aobench) +if (SHADY_ENABLE_SAMPLES) + add_subdirectory(checkerboard) + add_subdirectory(aobench) +endif() diff --git a/samples/aobench/CMakeLists.txt b/samples/aobench/CMakeLists.txt index 77bb7f506..f8baed4ca 100644 --- a/samples/aobench/CMakeLists.txt +++ b/samples/aobench/CMakeLists.txt @@ -1,4 +1,8 @@ -if (TARGET vcc) +if (NOT TARGET vcc) + message("Vcc unavailable. Skipping aobench sample.") +elseif(NOT TARGET runtime) + message("Runtime component unavailable. Skipping aobench sample.") +else() add_executable(aobench_host ao_host.c ao_main.c) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMAND vcc ARGS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp --only-run-clang -O3 -o ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMENT ao.comp.c.ll DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ao.c) @@ -19,6 +23,4 @@ if (TARGET vcc) endif() target_link_libraries(aobench_host PRIVATE m shady runtime common) -else() - message("Vcc not enabled. Skipping aobench.") endif() diff --git a/samples/checkerboard/CMakeLists.txt b/samples/checkerboard/CMakeLists.txt index b4cfb24ca..e8d3d9010 100644 --- a/samples/checkerboard/CMakeLists.txt +++ b/samples/checkerboard/CMakeLists.txt @@ -1,7 +1,10 @@ -add_executable(checkerboard checkerboard.c) -target_link_libraries(checkerboard PRIVATE m runtime common driver) -target_include_directories(checkerboard PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -message(${CMAKE_CURRENT_BINARY_DIR}) +if(NOT TARGET runtime) + message("Runtime component unavailable. Skipping checkerboard sample.") +else() + add_executable(checkerboard checkerboard.c) + target_link_libraries(checkerboard PRIVATE m runtime common driver) + target_include_directories(checkerboard PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -embed_file(string checkerboard_kernel_src checkerboard_kernel.slim) -target_link_libraries(checkerboard PRIVATE checkerboard_kernel_src) + embed_file(string checkerboard_kernel_src checkerboard_kernel.slim) + target_link_libraries(checkerboard PRIVATE checkerboard_kernel_src) +endif() diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 21e8a6ffd..3510e80a2 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -1,6 +1,3 @@ add_subdirectory(slim) add_subdirectory(spirv) - -if(LLVM_FOUND) - add_subdirectory(llvm) -endif() +add_subdirectory(llvm) diff --git a/src/frontend/llvm/CMakeLists.txt b/src/frontend/llvm/CMakeLists.txt index 260ef3aad..9e8f1a4c0 100644 --- a/src/frontend/llvm/CMakeLists.txt +++ b/src/frontend/llvm/CMakeLists.txt @@ -1,24 +1,32 @@ -add_generated_file(FILE_NAME l2s_generated.c SOURCES generator_l2s.c) +if (NOT LLVM_FOUND) + message("LLVM not found. Skipping LLVM front-end.") +else () + option (SHADY_ENABLE_LLVM_FRONTEND "Uses LLVM-C to parse and then convert LLVM IR into Shady IR" ON) +endif () -add_library(shady_fe_llvm STATIC l2s.c l2s_type.c l2s_value.c l2s_instr.c l2s_meta.c l2s_postprocess.c l2s_annotations.c ${CMAKE_CURRENT_BINARY_DIR}/l2s_generated.c) +if (SHADY_ENABLE_LLVM_FRONTEND) + add_generated_file(FILE_NAME l2s_generated.c SOURCES generator_l2s.c) -target_include_directories(shady_fe_llvm PRIVATE ${LLVM_INCLUDE_DIRS}) -target_include_directories(shady_fe_llvm PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) # for l2s_generated.c -separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) -add_definitions(${LLVM_DEFINITIONS_LIST}) -target_compile_definitions(shady_fe_llvm PRIVATE "LLVM_VERSION_MAJOR=${LLVM_VERSION_MAJOR}") + add_library(shady_fe_llvm STATIC l2s.c l2s_type.c l2s_value.c l2s_instr.c l2s_meta.c l2s_postprocess.c l2s_annotations.c ${CMAKE_CURRENT_BINARY_DIR}/l2s_generated.c) -if (TARGET LLVM-C) - message("LLVM-C shared library target exists, major version = ${LLVM_VERSION_MAJOR}") - target_link_libraries(shady_fe_llvm PRIVATE LLVM-C) -elseif (TARGET LLVM) - message("LLVM shared library target exists, major version = ${LLVM_VERSION_MAJOR}") - target_link_libraries(shady_fe_llvm PRIVATE LLVM) -else () -message(FATAL_ERROR "Failed to find LLVM-C target, but found LLVM module earlier") -endif() + target_include_directories(shady_fe_llvm PRIVATE ${LLVM_INCLUDE_DIRS}) + target_include_directories(shady_fe_llvm PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) # for l2s_generated.c + separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) + add_definitions(${LLVM_DEFINITIONS_LIST}) + target_compile_definitions(shady_fe_llvm PRIVATE "LLVM_VERSION_MAJOR=${LLVM_VERSION_MAJOR}") + + if (TARGET LLVM-C) + message("LLVM-C shared library target exists, major version = ${LLVM_VERSION_MAJOR}") + target_link_libraries(shady_fe_llvm PRIVATE LLVM-C) + elseif (TARGET LLVM) + message("LLVM shared library target exists, major version = ${LLVM_VERSION_MAJOR}") + target_link_libraries(shady_fe_llvm PRIVATE LLVM) + else () + message(FATAL_ERROR "Failed to find LLVM-C target, but found LLVM module earlier") + endif() -target_link_libraries(shady_fe_llvm PRIVATE api common shady) + target_link_libraries(shady_fe_llvm PRIVATE api common shady) -target_compile_definitions(driver PUBLIC LLVM_PARSER_PRESENT) -target_link_libraries(driver PUBLIC "$") + target_compile_definitions(driver PUBLIC LLVM_PARSER_PRESENT) + target_link_libraries(driver PUBLIC "$") +endif () diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index 9566d87a9..4eb71e028 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -1,11 +1,15 @@ -add_library(runtime runtime.c runtime_program.c runtime_cli.c) -target_link_libraries(runtime PUBLIC driver) -set_target_properties(runtime PROPERTIES OUTPUT_NAME "shady_runtime") +option(SHADY_ENABLE_RUNTIME "Offers helpful utilities for building applications with shady. Some samples and tests depend on it." ON) -add_subdirectory(vulkan) -add_subdirectory(cuda) +if (SHADY_ENABLE_RUNTIME) + add_library(runtime runtime.c runtime_program.c runtime_cli.c) + target_link_libraries(runtime PUBLIC driver) + set_target_properties(runtime PROPERTIES OUTPUT_NAME "shady_runtime") -add_executable(runtime_test runtime_test.c) -target_link_libraries(runtime_test runtime) + add_subdirectory(vulkan) + add_subdirectory(cuda) -install(TARGETS runtime EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) + add_executable(runtime_test runtime_test.c) + target_link_libraries(runtime_test runtime) + + install(TARGETS runtime EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) +endif() diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index 7ce3fac42..b15f71e81 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -1,16 +1,19 @@ find_package(CUDAToolkit) if (CUDAToolkit_FOUND) - message("Cuda toolkit found.") - option(SHADY_ENABLE_CUDA_BE "Whether the CUDA backend should be enabled" ON) - if (SHADY_ENABLE_CUDA_BE) - add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c cuda_runtime_program.c) - target_link_libraries(cuda_runtime PRIVATE api) - target_link_libraries(cuda_runtime PRIVATE "$") - target_link_libraries(cuda_runtime PRIVATE "$") - target_link_libraries(cuda_runtime PRIVATE CUDA::cudart CUDA::cuda_driver CUDA::nvrtc) + message("CUDA toolkit found.") + option(SHADY_ENABLE_RUNTIME_CUDA "CUDA support for the 'runtime' component" ON) +else() + message("CUDA toolkit not found, CUDA runtime component cannot be built.") +endif () - target_link_libraries(runtime PRIVATE "$") - target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) - endif() -endif () \ No newline at end of file +if (SHADY_ENABLE_RUNTIME_CUDA) + add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c cuda_runtime_program.c) + target_link_libraries(cuda_runtime PRIVATE api) + target_link_libraries(cuda_runtime PRIVATE "$") + target_link_libraries(cuda_runtime PRIVATE "$") + target_link_libraries(cuda_runtime PRIVATE CUDA::cudart CUDA::cuda_driver CUDA::nvrtc) + + target_link_libraries(runtime PRIVATE "$") + target_compile_definitions(runtime PUBLIC CUDA_BACKEND_PRESENT=1) +endif() \ No newline at end of file diff --git a/src/runtime/vulkan/CMakeLists.txt b/src/runtime/vulkan/CMakeLists.txt index 25935ea7b..2eb95afc4 100644 --- a/src/runtime/vulkan/CMakeLists.txt +++ b/src/runtime/vulkan/CMakeLists.txt @@ -1,7 +1,12 @@ find_package(Vulkan) if (Vulkan_FOUND) - message("Vulkan found") + option(SHADY_ENABLE_RUNTIME_VULKAN "Vulkan support for the 'runtime' component" ON) +else() + message("Vulkan not found, runtime component cannot be built.") +endif() + +if (SHADY_ENABLE_RUNTIME_VULKAN) add_library(vk_runtime STATIC vk_runtime.c vk_runtime_device.c vk_runtime_program.c vk_runtime_dispatch.c vk_runtime_buffer.c) target_link_libraries(vk_runtime PRIVATE api) target_link_libraries(vk_runtime PRIVATE "$") @@ -10,6 +15,4 @@ if (Vulkan_FOUND) target_compile_definitions(runtime PUBLIC VK_BACKEND_PRESENT=1) target_link_libraries(runtime PRIVATE "$") -else() - message("Vulkan not found, runtime component will not be built.") endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f237dab73..97a5899ec 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,53 +1,55 @@ -add_executable(test_math test_math.c) -target_link_libraries(test_math driver) -add_test(NAME test_math COMMAND test_math) +if (BUILD_TESTING) + add_executable(test_math test_math.c) + target_link_libraries(test_math driver) + add_test(NAME test_math COMMAND test_math) -list(APPEND BASIC_TESTS empty.slim) -list(APPEND BASIC_TESTS entrypoint_args1.slim) -list(APPEND BASIC_TESTS basic_blocks1.slim) -list(APPEND BASIC_TESTS control_flow1.slim) -list(APPEND BASIC_TESTS control_flow2.slim) -list(APPEND BASIC_TESTS functions1.slim) -list(APPEND BASIC_TESTS identity.slim) -list(APPEND BASIC_TESTS memory1.slim) -list(APPEND BASIC_TESTS memory2.slim) -list(APPEND BASIC_TESTS rec_pow.slim) -list(APPEND BASIC_TESTS rec_pow2.slim) -list(APPEND BASIC_TESTS restructure1.slim) -list(APPEND BASIC_TESTS restructure2.slim) -list(APPEND BASIC_TESTS simplify_control.slim) -list(APPEND BASIC_TESTS float.slim) -list(APPEND BASIC_TESTS constant_in_use.slim) -list(APPEND BASIC_TESTS arrays.slim) -list(APPEND BASIC_TESTS fn_decl.slim) -list(APPEND BASIC_TESTS math.slim) -list(APPEND BASIC_TESTS comments.slim) -list(APPEND BASIC_TESTS generic_ptrs1.slim) -list(APPEND BASIC_TESTS generic_ptrs2.slim) -list(APPEND BASIC_TESTS subgroup_var.slim) + list(APPEND BASIC_TESTS empty.slim) + list(APPEND BASIC_TESTS entrypoint_args1.slim) + list(APPEND BASIC_TESTS basic_blocks1.slim) + list(APPEND BASIC_TESTS control_flow1.slim) + list(APPEND BASIC_TESTS control_flow2.slim) + list(APPEND BASIC_TESTS functions1.slim) + list(APPEND BASIC_TESTS identity.slim) + list(APPEND BASIC_TESTS memory1.slim) + list(APPEND BASIC_TESTS memory2.slim) + list(APPEND BASIC_TESTS rec_pow.slim) + list(APPEND BASIC_TESTS rec_pow2.slim) + list(APPEND BASIC_TESTS restructure1.slim) + list(APPEND BASIC_TESTS restructure2.slim) + list(APPEND BASIC_TESTS simplify_control.slim) + list(APPEND BASIC_TESTS float.slim) + list(APPEND BASIC_TESTS constant_in_use.slim) + list(APPEND BASIC_TESTS arrays.slim) + list(APPEND BASIC_TESTS fn_decl.slim) + list(APPEND BASIC_TESTS math.slim) + list(APPEND BASIC_TESTS comments.slim) + list(APPEND BASIC_TESTS generic_ptrs1.slim) + list(APPEND BASIC_TESTS generic_ptrs2.slim) + list(APPEND BASIC_TESTS subgroup_var.slim) -list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic1.slim) -list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic2.slim) -list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic_evil.slim) -list(APPEND BASIC_TESTS reconvergence_heuristics/loops1.slim) -list(APPEND BASIC_TESTS reconvergence_heuristics/loops2.slim) -list(APPEND BASIC_TESTS reconvergence_heuristics/multi_exit_loop.slim) -list(APPEND BASIC_TESTS reconvergence_heuristics/nested_loops.slim) + list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic1.slim) + list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic2.slim) + list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic_evil.slim) + list(APPEND BASIC_TESTS reconvergence_heuristics/loops1.slim) + list(APPEND BASIC_TESTS reconvergence_heuristics/loops2.slim) + list(APPEND BASIC_TESTS reconvergence_heuristics/multi_exit_loop.slim) + list(APPEND BASIC_TESTS reconvergence_heuristics/nested_loops.slim) -foreach(T IN LISTS BASIC_TESTS) - add_test(NAME "test/${T}" COMMAND slim ${PROJECT_SOURCE_DIR}/test/${T} -o test.spv) -endforeach() + foreach(T IN LISTS BASIC_TESTS) + add_test(NAME "test/${T}" COMMAND slim ${PROJECT_SOURCE_DIR}/test/${T} -o test.spv) + endforeach() -add_subdirectory(opt) + add_subdirectory(opt) -function(spv_outputting_test) - cmake_parse_arguments(PARSE_ARGV 0 F "" "NAME;COMPILER" "EXTRA_ARGS" ) - add_test(NAME ${F_NAME} COMMAND ${CMAKE_COMMAND} -DCOMPILER=$ -DT=${F_NAME} "-DTARGS=${F_EXTRA_ARGS}" -DSRC=${PROJECT_SOURCE_DIR} -DDST=${PROJECT_BINARY_DIR} -P ${PROJECT_SOURCE_DIR}/test/test_with_val.cmake) -endfunction() + function(spv_outputting_test) + cmake_parse_arguments(PARSE_ARGV 0 F "" "NAME;COMPILER" "EXTRA_ARGS" ) + add_test(NAME ${F_NAME} COMMAND ${CMAKE_COMMAND} -DCOMPILER=$ -DT=${F_NAME} "-DTARGS=${F_EXTRA_ARGS}" -DSRC=${PROJECT_SOURCE_DIR} -DDST=${PROJECT_BINARY_DIR} -P ${PROJECT_SOURCE_DIR}/test/test_with_val.cmake) + endfunction() -spv_outputting_test(NAME samples/fib.slim COMPILER slim EXTRA_ARGS --entry-point main) -spv_outputting_test(NAME samples/hello_world.slim COMPILER slim EXTRA_ARGS --entry-point main) + spv_outputting_test(NAME samples/fib.slim COMPILER slim EXTRA_ARGS --entry-point main) + spv_outputting_test(NAME samples/hello_world.slim COMPILER slim EXTRA_ARGS --entry-point main) -if (TARGET vcc) - add_subdirectory(vcc) -endif () + if (TARGET vcc) + add_subdirectory(vcc) + endif() +endif() diff --git a/vcc/CMakeLists.txt b/vcc/CMakeLists.txt index 70048d787..522b1da0b 100644 --- a/vcc/CMakeLists.txt +++ b/vcc/CMakeLists.txt @@ -1,4 +1,10 @@ -if (TARGET shady_fe_llvm) +if (NOT TARGET shady_fe_llvm) + message("LLVM front-end unavailable. Skipping Vcc.") +else() + option(SHADY_ENABLE_VCC "Allows compiling C and C++ code with Shady." ON) +endif() + +if (SHADY_ENABLE_VCC) add_library(vcc_lib STATIC vcc_lib.c) target_link_libraries(vcc_lib PUBLIC driver api) @@ -12,7 +18,5 @@ if (TARGET shady_fe_llvm) COMMAND_EXPAND_LISTS ) endif () - message("Vcc will be built together with shady") -else() - message("LLVM front-end unavailable. Disabling Vcc") + #message("Vcc will be built together with shady") endif () \ No newline at end of file diff --git a/zhady/CMakeLists.txt b/zhady/CMakeLists.txt index aef26245d..6ad881b34 100644 --- a/zhady/CMakeLists.txt +++ b/zhady/CMakeLists.txt @@ -2,7 +2,17 @@ find_package(SWIG) find_package(JNI) find_package(Java) -if (SWIG_FOUND AND JNI_FOUND AND Java_FOUND) +if (NOT SWIG_FOUND) + message("SWIG not found. Skipping Java bindings.") +elseif (NOT SWIG_FOUND) + message("JNI not found. Skipping Java bindings.") +elseif (NOT SWIG_FOUND) + message("Java not found. Skipping Java bindings.") +else() + option(SHADY_ENABLE_JAVA_BINDINGS "Allows using shady (and if enabled, Vcc) in JVM applications" ON) +endif() + +if (SHADY_ENABLE_JAVA_BINDINGS) message("Enabling Java bindings") add_custom_target(zhady_dir COMMAND cmake -E ${CMAKE_CURRENT_BINARY_DIR}/java_sources/de/unisaarland/zhady) From 842e34176e491e906818626de40c53dc87e547b1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 22 Jul 2024 15:26:32 +0200 Subject: [PATCH 336/693] shady_vec.h: add missing typename --- vcc-std/include/shady_vec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcc-std/include/shady_vec.h b/vcc-std/include/shady_vec.h index 851db1907..5ecd33ad8 100644 --- a/vcc-std/include/shady_vec.h +++ b/vcc-std/include/shady_vec.h @@ -133,7 +133,7 @@ struct vec_impl { template mapping> // requires(fits(len, mapping)) struct Swizzler { using That = vec_impl; - using ThatNative = vec_native_type::Native; + using ThatNative = typename vec_native_type::Native; operator That() const requires(dst_len > 1 && fits(len, mapping)) { auto src = reinterpret_cast(this); From 0162c4d867fa2ff1d305d91df7f4fe5035fabb60 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 23 Jul 2024 14:25:27 +0200 Subject: [PATCH 337/693] runtime: fix alignment warning when importing memory --- src/runtime/vulkan/vk_runtime_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/vulkan/vk_runtime_buffer.c b/src/runtime/vulkan/vk_runtime_buffer.c index 4f9659f8d..dc5e5bf34 100644 --- a/src/runtime/vulkan/vk_runtime_buffer.c +++ b/src/runtime/vulkan/vk_runtime_buffer.c @@ -176,7 +176,7 @@ VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { .sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, .pNext = NULL }; - CHECK_VK(device->extensions.EXT_external_memory_host.vkGetMemoryHostPointerPropertiesEXT(device->device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, ptr, &host_ptr_properties), goto err_post_buffer_create); + CHECK_VK(device->extensions.EXT_external_memory_host.vkGetMemoryHostPointerPropertiesEXT(device->device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, (void*) aligned_addr, &host_ptr_properties), goto err_post_buffer_create); uint32_t memory_type_index = find_suitable_memory_type(device, host_ptr_properties.memoryTypeBits, AllocHostVisible); VkPhysicalDeviceMemoryProperties device_memory_properties; vkGetPhysicalDeviceMemoryProperties(device->caps.physical_device, &device_memory_properties); From c8f0676b63b1ec03d15c7f190e8972115c109472 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 23 Jul 2024 15:43:19 +0200 Subject: [PATCH 338/693] make non-verbose debug logging more silent --- src/frontend/llvm/l2s.c | 6 ++-- src/shady/passes/cleanup.c | 2 +- src/shady/passes/opt_mem2reg.c | 56 +++++++++++++++++----------------- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index c8e8ec797..0be85afbe 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -287,14 +287,16 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* break; global = LLVMGetNextGlobal(global); } - log_module(DEBUG, config, dirty); + log_string(DEBUGVV, "Shady module parsed from LLVM:"); + log_module(DEBUGVV, config, dirty); aconfig.check_types = true; aconfig.allow_fold = true; IrArena* arena2 = new_ir_arena(&aconfig); *dst = new_module(arena2, name); postprocess(&p, dirty, *dst); - log_module(DEBUG, config, *dst); + log_string(DEBUGVV, "Shady module parsed from LLVM, after cleanup:"); + log_module(DEBUGVV, config, *dst); verify_module(config, *dst); destroy_ir_arena(arena); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 6f59d96ac..24a246ce7 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -183,7 +183,7 @@ Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { size_t r = 0; Module* m = src; do { - debug_print("Cleanup round %d\n", r); + debugv_print("Cleanup round %d\n", r); todo = false; todo |= opt_demote_alloca(config, &m); todo |= simplify(config, &m); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 3895d7437..7ad43ccee 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -185,7 +185,7 @@ static void wipe_all_leaked_pointers(KnowledgeBase* kb) { k->ptr_value = NULL; debugvv_print("mem2reg: wiping the know ptr value for "); log_node(DEBUGVV, ptr); - debug_print(".\n"); + debugvv_print(".\n"); } } } @@ -213,10 +213,10 @@ static const Node* find_or_request_known_ptr_value(Context* ctx, KnowledgeBase* while (phi_kb->dominator_kb) { phi_kb = phi_kb->dominator_kb; } - debug_print("mem2reg: It'd sure be nice to know the value of "); - log_node(DEBUG, optr); - debug_print(" at phi-like node %s.\n", get_abstraction_name_safe(phi_kb->cfnode->node)); - // log_node(DEBUG, phi_location->node); + log_string(DEBUGVV, "mem2reg: It'd sure be nice to know the value of "); + log_node(DEBUGVV, optr); + log_string(DEBUGVV, " at phi-like node %s.\n", get_abstraction_name_safe(phi_kb->cfnode->node)); + // log_node(DEBUGVV, phi_location->node); insert_set_get_key(const Node*, phi_kb->potential_additional_params, optr); } return NULL; @@ -271,7 +271,7 @@ static void mark_value_as_escaping(Context* ctx, KnowledgeBase* kb, const Node* if (k) { debugvv_print("mem2reg: marking "); log_node(DEBUGVV, value); - debug_print(" as leaking.\n"); + log_string(DEBUGVV, " as leaking.\n"); k->ptr_has_leaked = true; if (k->alias_old_address) mark_value_as_escaping(ctx, kb, k->alias_old_address); @@ -372,11 +372,11 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No // if we have knowledge on a particular ptr, the same knowledge propagates if we bitcast it! PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, first(payload.operands)); if (k) { - debug_print("mem2reg: the reinterpreted ptr "); - log_node(DEBUG, oinstruction); - debug_print(" is the same as "); - log_node(DEBUG, first(payload.operands)); - debug_print(".\n"); + log_string(DEBUGVV, "mem2reg: the reinterpreted ptr "); + log_node(DEBUGVV, oinstruction); + log_string(DEBUGVV, " is the same as "); + log_node(DEBUGVV, first(payload.operands)); + log_string(DEBUGVV, ".\n"); k = update_ptr_knowledge(kb, oinstruction, k); k->state = PSKnownAlias; k->alias_old_address = first(payload.operands); @@ -389,11 +389,11 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No if (first(payload.type_arguments)->tag == PtrType_TAG) { PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, first(payload.operands)); if (k) { - debug_print("mem2reg: the converted ptr "); - log_node(DEBUG, oinstruction); - debug_print(" is the same as "); - log_node(DEBUG, first(payload.operands)); - debug_print(".\n"); + log_string(DEBUGVV, "mem2reg: the converted ptr "); + log_node(DEBUGVV, oinstruction); + log_string(DEBUGVV, " is the same as "); + log_node(DEBUGVV, first(payload.operands)); + log_string(DEBUGVV, ".\n"); k = update_ptr_knowledge(kb, oinstruction, k); k->state = PSKnownAlias; k->alias_old_address = first(payload.operands); @@ -530,10 +530,10 @@ static void handle_bb(Context* ctx, const Node* old) { const Node* kv = get_known_value(kb_at_src, get_last_valid_ptr_knowledge(kb_at_src, ptr)); if (kv) { - log_node(DEBUG, ptr); - debug_print(" has a known value ("); - log_node(DEBUG, kv); - debug_print(") in %s ...\n", get_abstraction_name_safe(edge.src->node)); + log_node(DEBUGVV, ptr); + log_string(DEBUGVV, " has a known value ("); + log_node(DEBUGVV, kv); + log_string(DEBUGVV, ") in %s ...\n", get_abstraction_name_safe(edge.src->node)); } else goto next_potential_param; @@ -548,20 +548,20 @@ static void handle_bb(Context* ctx, const Node* old) { const Type* alloca_type_t = source->type; //deconstruct_qualified_type(&alloca_type_t); if (kv_type != source->type && !is_reinterpret_cast_legal(kv_type, alloca_type_t)) { - log_node(DEBUG, ptr); - debug_print(" has a known value in %s, but it's type ", get_abstraction_name_safe(edge.src->node)); - log_node(DEBUG, kv_type); - debug_print(" cannot be reinterpreted into the alloca type "); - log_node(DEBUG, source->type); - debug_print("\n."); + log_node(DEBUGVV, ptr); + log_string(DEBUGVV, " has a known value in %s, but it's type ", get_abstraction_name_safe(edge.src->node)); + log_node(DEBUGVV, kv_type); + log_string(DEBUGVV, " cannot be reinterpreted into the alloca type "); + log_node(DEBUGVV, source->type); + log_string(DEBUGVV, "\n."); goto next_potential_param; } uk.ptr_has_leaked |= k->ptr_has_leaked; } - log_node(DEBUG, ptr); - debug_print(" has a known value in all predecessors! Turning it into a new parameter.\n"); + log_node(DEBUGVV, ptr); + log_string(DEBUGVV, " has a known value in all predecessors! Turning it into a new parameter.\n"); // assert(!is_qualified_type_uniform(source->type)); const Node* nparam = param(a, qualified_type_helper(source->type, false), unique_name(a, "ssa_phi")); From 88c67dbbb96cccc9367c4b36e85b212932bc42f9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 24 Jul 2024 15:06:46 +0200 Subject: [PATCH 339/693] mem2reg: fix for 'forgetting' pointer aliases --- src/shady/passes/opt_mem2reg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 7ad43ccee..0e463944a 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -182,7 +182,10 @@ static void wipe_all_leaked_pointers(KnowledgeBase* kb) { PtrKnowledge* k; while (dict_iter(kb->map, &i, &ptr, &k)) { if (k->ptr_has_leaked) { - k->ptr_value = NULL; + if (k->state == PSKnownValue || k->state == PSKnownSubElement) { + k->ptr_value = NULL; + k->state = PSUnknown; + } debugvv_print("mem2reg: wiping the know ptr value for "); log_node(DEBUGVV, ptr); debugvv_print(".\n"); @@ -323,6 +326,7 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No switch (is_instruction(oinstruction)) { case NotAnInstruction: assert(is_instruction(oinstruction)); case Instruction_Call_TAG: + mark_values_as_escaping(ctx, kb, oinstruction->payload.call.args); wipe_all_leaked_pointers(kb); break; case Instruction_PrimOp_TAG: { From aade2c50f646e3b0524536dab3eafd31d792ae05 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 24 Jul 2024 15:47:57 +0200 Subject: [PATCH 340/693] fix more mem2reg issues --- src/shady/passes/opt_mem2reg.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 0e463944a..9281031ae 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -276,7 +276,9 @@ static void mark_value_as_escaping(Context* ctx, KnowledgeBase* kb, const Node* log_node(DEBUGVV, value); log_string(DEBUGVV, " as leaking.\n"); k->ptr_has_leaked = true; - if (k->alias_old_address) + // if (k->state == PSKnownValue) + // mark_value_as_escaping(ctx, kb, k->ptr_value); + if (k->state == PSKnownAlias) mark_value_as_escaping(ctx, kb, k->alias_old_address); } switch (is_value(value)) { @@ -342,9 +344,10 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No //k->source->type = qualified_type_helper(t, u); k->source->type = rewrite_node(r, first(payload.type_arguments)); + k->state = PSUnknown; // TODO: we can only enable this safely once we properly deal with control-flow - k->state = PSKnownValue; - k->ptr_value = undef(a, (Undef) { .type = rewrite_node(r, first(payload.type_arguments)) }); + // k->state = PSKnownValue; + // k->ptr_value = undef(a, (Undef) { .type = rewrite_node(r, first(payload.type_arguments)) }); return recreate_node_identity(r, oinstruction); } case load_op: { @@ -368,6 +371,8 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No k->state = PSKnownValue; k->ptr_value = rewrite_node(r, payload.operands.nodes[1]); } + mark_value_as_escaping(ctx, kb, payload.operands.nodes[1]); + wipe_all_leaked_pointers(kb); // let's take care of dead stores another time return recreate_node_identity(r, oinstruction); } From 06e1d19cbddca3e5e74135354b5fc7d47a3ab7cd Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 24 Jul 2024 15:48:32 +0200 Subject: [PATCH 341/693] allow folding away ifs entirely --- include/shady/config.h | 1 + src/shady/config.c | 1 + src/shady/fold.c | 17 +++++++++++++++++ src/shady/passes/cleanup.c | 14 ++++++++++---- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/include/shady/config.h b/include/shady/config.h index be7ad9aab..eae39cb47 100644 --- a/include/shady/config.h +++ b/include/shady/config.h @@ -47,6 +47,7 @@ struct ArenaConfig_ { /// 'folding' optimisations - happen in the constructors directly struct { + bool fold_static_control_flow; bool delete_unreachable_structured_cases; bool weaken_non_leaking_allocas; } optimisations; diff --git a/src/shady/config.c b/src/shady/config.c index 12b8161ef..bb971fbd5 100644 --- a/src/shady/config.c +++ b/src/shady/config.c @@ -61,6 +61,7 @@ ArenaConfig default_arena_config(const TargetConfig* target) { .check_op_classes = true, .optimisations = { + .fold_static_control_flow = true, .delete_unreachable_structured_cases = true, }, diff --git a/src/shady/fold.c b/src/shady/fold.c index ca338f617..eb9768e4c 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -162,6 +162,16 @@ static inline const Node* fold_simplify_math(const Node* node) { return quote_single(arena, payload.operands.nodes[0]); break; } + case eq_op: { + if (payload.operands.nodes[0] == payload.operands.nodes[1]) + return quote_single(arena, true_lit(arena)); + break; + } + case neq_op: { + if (payload.operands.nodes[0] == payload.operands.nodes[1]) + return quote_single(arena, false_lit(arena)); + break; + } default: break; } @@ -364,6 +374,13 @@ const Node* fold_node(IrArena* arena, const Node* node) { const Node* false_case = payload.if_false; if (arena->config.optimisations.delete_unreachable_structured_cases && false_case && is_unreachable_case(false_case)) return block(arena, (Block) { .inside = payload.if_true, .yield_types = add_qualifiers(arena, payload.yield_types, false) }); + if (arena->config.optimisations.fold_static_control_flow) { + if (payload.condition == true_lit(arena)) { + return block(arena, (Block) { .inside = payload.if_true, .yield_types = add_qualifiers(arena, payload.yield_types, false) }); + } else if (payload.condition == false_lit(arena) && false_case) { + return block(arena, (Block) { .inside = false_case, .yield_types = add_qualifiers(arena, payload.yield_types, false) }); + } + } break; } case Match_TAG: { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 24a246ce7..e3be64669 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -48,7 +48,7 @@ void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr); // let K in case(z) => // ... // R[a->x, b->y, c->z] -Nodes flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* bb) { +const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* bb) { assert(instruction->tag == Block_TAG); // follow the terminator of the block until we hit a yield() const Node* const lam = instruction->payload.block.inside; @@ -63,9 +63,13 @@ Nodes flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* bb) { continue; } case Terminator_Yield_TAG: { - return terminator->payload.yield.args; + return quote_helper(arena, terminator->payload.yield.args); } - // if we see anything else, give up + case Terminator_Return_TAG: + case Terminator_TailCall_TAG: { + return terminator; + } + // if we see anything else, give up default: { assert(false && "invalid block"); } @@ -117,7 +121,9 @@ const Node* process(Context* ctx, const Node* old) { // optimization: fold blocks if (instruction->tag == Block_TAG) { *ctx->todo = true; - instruction = quote_helper(a, flatten_block(a, instruction, bb)); + instruction = flatten_block(a, instruction, bb); + if (is_terminator(instruction)) + return finish_body(bb, instruction); } Nodes ovars = old->payload.let.variables; // optimization: eliminate unecessary quotes by rewriting variables into their values directly From 63066a5aeb8a4ddea84808450908c87698e1db15 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 24 Jul 2024 15:48:48 +0200 Subject: [PATCH 342/693] lower_memcpy: robustness --- src/shady/passes/lower_memcpy.c | 6 +++--- src/shady/transform/memory_layout.c | 4 ++++ src/shady/transform/memory_layout.h | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index e76d1ca0b..f3d3d42a7 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -51,8 +51,8 @@ static const Node* process(Context* ctx, const Node* old) { }); src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); - const Node* num = rewrite_node(&ctx->rewriter, old_ops.nodes[2]); - const Node* num_in_bytes = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); + const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, old_ops.nodes[2])); + const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num_in_bytes)); const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memcpy_i"); BodyBuilder* loop_bb = begin_body(a); @@ -60,7 +60,7 @@ static const Node* process(Context* ctx, const Node* old) { gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); bind_instruction(loop_bb, if_instr(a, (If) { - .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), + .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), .yield_types = empty(a), .if_true = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})), .if_false = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})) diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 44b20ade4..32fd5eba0 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -111,6 +111,10 @@ TypeMemLayout get_mem_layout(IrArena* a, const Type* type) { } } +const Node* size_t_type(IrArena* a) { + return int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); +} + const Node* size_t_literal(IrArena* a, uint64_t value) { return int_literal(a, (IntLiteral) { .width = a->config.memory.ptr_size, .is_signed = false, .value = value }); } diff --git a/src/shady/transform/memory_layout.h b/src/shady/transform/memory_layout.h index 925041e32..25aa8b703 100644 --- a/src/shady/transform/memory_layout.h +++ b/src/shady/transform/memory_layout.h @@ -19,6 +19,7 @@ TypeMemLayout get_mem_layout(IrArena*, const Type*); TypeMemLayout get_record_layout(IrArena* a, const Node* record_type, FieldLayout* fields); size_t get_record_field_offset_in_bytes(IrArena*, const Type*, size_t); +const Type* size_t_type(IrArena* a); const Node* size_t_literal(IrArena* a, uint64_t value); const Node* bytes_to_words(BodyBuilder* bb, const Node* bytes); uint64_t bytes_to_words_static(const IrArena*, uint64_t bytes); From 80b31fc4fff3a2a901145ee2e931b2649abc20a8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 25 Jul 2024 16:22:13 +0200 Subject: [PATCH 343/693] added node variants of most memory ops --- include/shady/primops.json | 44 +++++++++++++++++++ src/shady/type.c | 86 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/include/shady/primops.json b/include/shady/primops.json index 3494fd0f1..aa27d30a7 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -349,5 +349,49 @@ "name": "mask_is_thread_active", "class": "mask" } + ], + "nodes": [ + { + "name": "Load", + "class": "instruction", + "ops": [ + { "name": "ptr", "class": "value" } + ] + }, + { + "name": "Store", + "class": "instruction", + "ops": [ + { "name": "ptr", "class": "value" }, + { "name": "value", "class": "value" } + ] + }, + { + "name": "Lea", + "class": "instruction", + "ops": [ + { "name": "ptr", "class": "value" }, + { "name": "offset", "class": "value" }, + { "name": "indices", "class": "value", "list": true } + ] + }, + { + "name": "CopyBytes", + "class": "instruction", + "ops": [ + { "name": "dst", "class": "value" }, + { "name": "src", "class": "value" }, + { "name": "count", "class": "value" } + ] + }, + { + "name": "FillBytes", + "class": "instruction", + "ops": [ + { "name": "dst", "class": "value" }, + { "name": "src", "class": "value" }, + { "name": "count", "class": "value" } + ] + } ] } \ No newline at end of file diff --git a/src/shady/type.c b/src/shady/type.c index 48cdb9a3b..d871b1f8c 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1204,6 +1204,92 @@ const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { return empty_multiple_return_type(arena); } +const Type* check_type_load(IrArena* a, Load load) { + const Node* ptr_type = load.ptr->type; + bool ptr_uniform = deconstruct_qualified_type(&ptr_type); + size_t width = deconstruct_maybe_packed_type(&ptr_type); + + assert(ptr_type->tag == PtrType_TAG); + const PtrType* node_ptr_type_ = &ptr_type->payload.ptr_type; + const Type* elem_type = node_ptr_type_->pointed_type; + elem_type = maybe_packed_type_helper(elem_type, width); + return qualified_type_helper(elem_type, ptr_uniform && is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); +} + +const Type* check_type_store(IrArena* a, Store store) { + const Node* ptr_type = store.ptr->type; + bool ptr_uniform = deconstruct_qualified_type(&ptr_type); + size_t width = deconstruct_maybe_packed_type(&ptr_type); + assert(ptr_type->tag == PtrType_TAG); + const PtrType* ptr_type_payload = &ptr_type->payload.ptr_type; + const Type* elem_type = ptr_type_payload->pointed_type; + assert(elem_type); + elem_type = maybe_packed_type_helper(elem_type, width); + // we don't enforce uniform stores - but we care about storing the right thing :) + const Type* val_expected_type = qualified_type(a, (QualifiedType) { + .is_uniform = !a->config.is_simt, + .type = elem_type + }); + + assert(is_subtype(val_expected_type, store.value->type)); + return empty_multiple_return_type(a); +} + +const Type* check_type_lea(IrArena* a, Lea lea) { + const Type* base_ptr_type = lea.ptr->type; + bool uniform = deconstruct_qualified_type(&base_ptr_type); + assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); + const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; + + assert(lea.offset); + const Type* offset_type = lea.offset->type; + bool offset_uniform = deconstruct_qualified_type(&offset_type); + assert(offset_type->tag == Int_TAG && "lea expects an integer offset"); + + const IntLiteral* lit = resolve_to_int_literal(lea.offset); + bool offset_is_zero = lit && lit->value == 0; + assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); + assert(offset_is_zero || is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); + uniform &= offset_uniform; + + enter_composite(&pointee_type, &uniform, lea.indices, true); + + return qualified_type(a, (QualifiedType) { + .is_uniform = uniform, + .type = ptr_type(a, (PtrType) { + .pointed_type = pointee_type, + .address_space = base_ptr_type->payload.ptr_type.address_space, + .is_reference = base_ptr_type->payload.ptr_type.is_reference + }) + }); +} + +const Type* check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { + const Type* dst_t = copy_bytes.dst->type; + deconstruct_qualified_type(&dst_t); + assert(dst_t->tag == PtrType_TAG); + const Type* src_t = copy_bytes.src->type; + deconstruct_qualified_type(&src_t); + assert(src_t); + const Type* cnt_t = copy_bytes.count->type; + deconstruct_qualified_type(&cnt_t); + assert(cnt_t->tag == Int_TAG); + return empty_multiple_return_type(a); +} + +const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { + const Type* dst_t = fill_bytes.dst->type; + deconstruct_qualified_type(&dst_t); + assert(dst_t->tag == PtrType_TAG); + const Type* src_t = fill_bytes.count; + deconstruct_qualified_type(&src_t); + assert(src_t); + const Type* cnt_t = fill_bytes.count->type; + deconstruct_qualified_type(&cnt_t); + assert(cnt_t->tag == Int_TAG); + return empty_multiple_return_type(a); +} + const Type* check_type_let(IrArena* arena, Let let) { Nodes produced_types = unwrap_multiple_yield_types(arena, let.instruction->type); Nodes param_types = get_param_types(arena, let.tail->payload.case_.params); From 29ad099c8060459e317306273387add0362d3599 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 25 Jul 2024 16:49:07 +0200 Subject: [PATCH 344/693] removed memcpy and memset primops --- include/shady/primops.json | 10 -- src/backend/c/emit_c_instructions.c | 22 +++- src/frontend/llvm/l2s_instr.c | 4 +- src/frontend/spirv/s2s.c | 8 +- src/shady/passes/lower_memcpy.c | 182 ++++++++++++++-------------- src/shady/type.c | 30 +---- test/opt/opt_oracle.c | 6 +- 7 files changed, 115 insertions(+), 147 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index aa27d30a7..1547323a7 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -233,16 +233,6 @@ "name": "lea", "class": "memory" }, - { - "name": "memcpy", - "class": "memory", - "side-effects": true - }, - { - "name": "memset", - "class": "memory", - "side-effects": true - }, { "name": "size_of", "class": "memory_layout" diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 9500550a8..847b966d8 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -428,10 +428,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct outputs.binding[0] = NoBinding; return; } - case memcpy_op: { - print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[0])), to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])), to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[2]))); - return; - } case size_of_op: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); break; @@ -872,6 +868,7 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins switch (is_instruction(instruction)) { case NotAnInstruction: assert(false); + case Instruction_LetMut_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; case Instruction_If_TAG: emit_if (emitter, p, instruction, outputs); break; @@ -880,6 +877,21 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_Control_TAG: error("TODO") case Instruction_Block_TAG: error("Should be eliminated by the compiler") case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; - default: error("TODO"); + case Instruction_Load_TAG: + break; + case Instruction_Store_TAG: + break; + case Instruction_Lea_TAG: + break; + case Instruction_CopyBytes_TAG: { + CopyBytes payload = instruction->payload.copy_bytes; + print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, p, payload.src)), to_cvalue(emitter, c_emit_value(emitter, p, payload.count))); + return; + } + case Instruction_FillBytes_TAG:{ + FillBytes payload = instruction->payload.fill_bytes; + print(p, "\nmemset(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, p, payload.src)), to_cvalue(emitter, c_emit_value(emitter, p, payload.count))); + return; + } } } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index e0c8824f4..5ce672a2d 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -523,12 +523,12 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, if (string_starts_with(intrinsic, "llvm.memcpy")) { Nodes ops = convert_operands(p, num_ops, instr); num_results = 0; - r = prim_op_helper(a, memcpy_op, empty(a), nodes(a, 3, ops.nodes)); + r = copy_bytes(a, (CopyBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2] }); break; } else if (string_starts_with(intrinsic, "llvm.memset")) { Nodes ops = convert_operands(p, num_ops, instr); num_results = 0; - r = prim_op_helper(a, memset_op, empty(a), nodes(a, 3, ops.nodes)); + r = fill_bytes(a, (FillBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2] }); break; } else if (string_starts_with(intrinsic, "llvm.fmuladd")) { Nodes ops = convert_operands(p, num_ops, instr); diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index d0da6dda6..6c0286bdc 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1111,10 +1111,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } else { cnt = get_def_ssa_value(parser, instruction[3]); } - bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = memcpy_op, - .type_arguments = empty(parser->arena), - .operands = mk_nodes(parser->arena, dst, src, cnt) + bind_instruction_outputs_count(parser->current_block.builder, copy_bytes(parser->arena, (CopyBytes) { + .src = src, + .dst = dst, + .count = cnt, }), 0, NULL); break; } diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index f3d3d42a7..24b20670d 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -23,100 +23,94 @@ static const Node* process(Context* ctx, const Node* old) { Module* m = ctx->rewriter.dst_module; switch (old->tag) { - case PrimOp_TAG: { - switch (old->payload.prim_op.op) { - case memcpy_op: { - const Type* word_type = int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - - BodyBuilder* bb = begin_body(a); - Nodes old_ops = old->payload.prim_op.operands; - - const Node* dst_addr = rewrite_node(&ctx->rewriter, old_ops.nodes[0]); - const Type* dst_addr_type = dst_addr->type; - deconstruct_qualified_type(&dst_addr_type); - assert(dst_addr_type->tag == PtrType_TAG); - dst_addr_type = ptr_type(a, (PtrType) { - .address_space = dst_addr_type->payload.ptr_type.address_space, - .pointed_type = word_type, - }); - dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); - - const Node* src_addr = rewrite_node(&ctx->rewriter, old_ops.nodes[1]); - const Type* src_addr_type = src_addr->type; - deconstruct_qualified_type(&src_addr_type); - assert(src_addr_type->tag == PtrType_TAG); - src_addr_type = ptr_type(a, (PtrType) { - .address_space = src_addr_type->payload.ptr_type.address_space, - .pointed_type = word_type, - }); - src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); - - const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, old_ops.nodes[2])); - const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num_in_bytes)); - - const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memcpy_i"); - BodyBuilder* loop_bb = begin_body(a); - const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, empty(a))); - gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); - const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); - bind_instruction(loop_bb, if_instr(a, (If) { - .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), - .yield_types = empty(a), - .if_true = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})), - .if_false = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})) - })); - - bind_instruction(bb, loop_instr(a, (Loop) { - .yield_types = empty(a), - .body = case_(a, singleton(index), finish_body(loop_bb, unreachable(a))), - .initial_args = singleton(uint32_literal(a, 0)) - })); - return yield_values_and_wrap_in_block(bb, empty(a)); - } - case memset_op: { - Nodes old_ops = old->payload.prim_op.operands; - const Node* src_value = rewrite_node(&ctx->rewriter, old_ops.nodes[1]); - const Type* src_type = src_value->type; - deconstruct_qualified_type(&src_type); - assert(src_type->tag == Int_TAG); - const Type* word_type = src_type;// int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - - BodyBuilder* bb = begin_body(a); - - const Node* dst_addr = rewrite_node(&ctx->rewriter, old_ops.nodes[0]); - const Type* dst_addr_type = dst_addr->type; - deconstruct_qualified_type(&dst_addr_type); - assert(dst_addr_type->tag == PtrType_TAG); - dst_addr_type = ptr_type(a, (PtrType) { - .address_space = dst_addr_type->payload.ptr_type.address_space, - .pointed_type = word_type, - }); - dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); - - const Node* num = rewrite_node(&ctx->rewriter, old_ops.nodes[2]); - const Node* num_in_bytes = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); - - const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memset_i"); - BodyBuilder* loop_bb = begin_body(a); - gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); - const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); - bind_instruction(loop_bb, if_instr(a, (If) { - .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), - .yield_types = empty(a), - .if_true = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})), - .if_false = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})) - })); - - bind_instruction(bb, loop_instr(a, (Loop) { - .yield_types = empty(a), - .body = case_(a, singleton(index), finish_body(loop_bb, unreachable(a))), - .initial_args = singleton(uint32_literal(a, 0)) - })); - return yield_values_and_wrap_in_block(bb, empty(a)); - } - default: break; - } - break; + case CopyBytes_TAG: { + CopyBytes payload = old->payload.copy_bytes; + const Type* word_type = int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); + + BodyBuilder* bb = begin_body(a); + + const Node* dst_addr = rewrite_node(&ctx->rewriter, payload.dst); + const Type* dst_addr_type = dst_addr->type; + deconstruct_qualified_type(&dst_addr_type); + assert(dst_addr_type->tag == PtrType_TAG); + dst_addr_type = ptr_type(a, (PtrType) { + .address_space = dst_addr_type->payload.ptr_type.address_space, + .pointed_type = word_type, + }); + dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); + + const Node* src_addr = rewrite_node(&ctx->rewriter, payload.src); + const Type* src_addr_type = src_addr->type; + deconstruct_qualified_type(&src_addr_type); + assert(src_addr_type->tag == PtrType_TAG); + src_addr_type = ptr_type(a, (PtrType) { + .address_space = src_addr_type->payload.ptr_type.address_space, + .pointed_type = word_type, + }); + src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); + + const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, payload.count)); + const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num_in_bytes)); + + const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memcpy_i"); + BodyBuilder* loop_bb = begin_body(a); + const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, empty(a))); + gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); + const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); + bind_instruction(loop_bb, if_instr(a, (If) { + .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), + .yield_types = empty(a), + .if_true = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})), + .if_false = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})) + })); + + bind_instruction(bb, loop_instr(a, (Loop) { + .yield_types = empty(a), + .body = case_(a, singleton(index), finish_body(loop_bb, unreachable(a))), + .initial_args = singleton(uint32_literal(a, 0)) + })); + return yield_values_and_wrap_in_block(bb, empty(a)); + } + case FillBytes_TAG: { + FillBytes payload = old->payload.fill_bytes; + const Node* src_value = rewrite_node(&ctx->rewriter, payload.src); + const Type* src_type = src_value->type; + deconstruct_qualified_type(&src_type); + assert(src_type->tag == Int_TAG); + const Type* word_type = src_type;// int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); + + BodyBuilder* bb = begin_body(a); + + const Node* dst_addr = rewrite_node(&ctx->rewriter, payload.dst); + const Type* dst_addr_type = dst_addr->type; + deconstruct_qualified_type(&dst_addr_type); + assert(dst_addr_type->tag == PtrType_TAG); + dst_addr_type = ptr_type(a, (PtrType) { + .address_space = dst_addr_type->payload.ptr_type.address_space, + .pointed_type = word_type, + }); + dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); + + const Node* num = rewrite_node(&ctx->rewriter, payload.count); + const Node* num_in_bytes = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); + + const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memset_i"); + BodyBuilder* loop_bb = begin_body(a); + gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); + const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); + bind_instruction(loop_bb, if_instr(a, (If) { + .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), + .yield_types = empty(a), + .if_true = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})), + .if_false = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})) + })); + + bind_instruction(bb, loop_instr(a, (Loop) { + .yield_types = empty(a), + .body = case_(a, singleton(index), finish_body(loop_bb, unreachable(a))), + .initial_args = singleton(uint32_literal(a, 0)) + })); + return yield_values_and_wrap_in_block(bb, empty(a)); } default: break; } diff --git a/src/shady/type.c b/src/shady/type.c index d871b1f8c..5f0b5315d 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -811,34 +811,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { }) }); } - case memcpy_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 3); - const Type* dst_t = prim_op.operands.nodes[0]->type; - deconstruct_qualified_type(&dst_t); - assert(dst_t->tag == PtrType_TAG); - const Type* src_t = prim_op.operands.nodes[1]->type; - deconstruct_qualified_type(&src_t); - assert(src_t->tag == PtrType_TAG); - const Type* cnt_t = prim_op.operands.nodes[2]->type; - deconstruct_qualified_type(&cnt_t); - assert(cnt_t->tag == Int_TAG); - return empty_multiple_return_type(arena); - } - case memset_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 3); - const Type* dst_t = prim_op.operands.nodes[0]->type; - deconstruct_qualified_type(&dst_t); - assert(dst_t->tag == PtrType_TAG); - const Type* src_t = prim_op.operands.nodes[1]->type; - deconstruct_qualified_type(&src_t); - assert(src_t); - const Type* cnt_t = prim_op.operands.nodes[2]->type; - deconstruct_qualified_type(&cnt_t); - assert(cnt_t->tag == Int_TAG); - return empty_multiple_return_type(arena); - } case align_of_op: case size_of_op: { assert(prim_op.type_arguments.count == 1); @@ -1281,7 +1253,7 @@ const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { const Type* dst_t = fill_bytes.dst->type; deconstruct_qualified_type(&dst_t); assert(dst_t->tag == PtrType_TAG); - const Type* src_t = fill_bytes.count; + const Type* src_t = fill_bytes.src->type; deconstruct_qualified_type(&src_t); assert(src_t); const Type* cnt_t = fill_bytes.count->type; diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index ae5e186c7..4aa787ffc 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -20,14 +20,14 @@ static void search_for_memstuff(Visitor* v, const Node* n) { case alloca_op: case alloca_logical_op: case load_op: - case store_op: - case memcpy_op: { + case store_op: { found_memstuff = true; break; } default: break; } - } + } else if (n->tag == CopyBytes_TAG || n->tag == FillBytes_TAG) + found_memstuff = true; visit_node_operands(v, NcDeclaration, n); } From b3192f0a67de6a30b2d3f46477c1699735cdef0b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Jul 2024 09:16:53 +0200 Subject: [PATCH 345/693] removed lea_op in favor of Lea node --- include/shady/primops.json | 4 - src/backend/c/emit_c_instructions.c | 160 +++++++++++----------- src/backend/spirv/emit_spv_instructions.c | 43 +++--- src/frontend/llvm/l2s_annotations.c | 6 +- src/frontend/llvm/l2s_instr.c | 2 +- src/frontend/spirv/s2s.c | 20 +-- src/shady/fold.c | 135 ++++++++++-------- src/shady/node.c | 50 ++++--- src/shady/passes/bind.c | 5 +- src/shady/passes/infer.c | 38 ++--- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_lea.c | 61 ++++----- src/shady/passes/lower_logical_pointers.c | 16 ++- src/shady/passes/lower_physical_ptrs.c | 10 +- src/shady/passes/normalize_builtins.c | 16 +-- src/shady/passes/opt_demote_alloca.c | 12 +- src/shady/transform/ir_gen_helpers.c | 7 +- src/shady/type.c | 35 ----- 18 files changed, 297 insertions(+), 325 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index 1547323a7..4f7319e48 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -229,10 +229,6 @@ "class": "memory", "side-effects": true }, - { - "name": "lea", - "class": "memory" - }, { "name": "size_of", "class": "memory_layout" diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 847b966d8..b463ae063 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -350,83 +350,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct print(p, "\n%s = %s;", dereferenced, cvalue); return; - } case lea_op: { - CTerm acc = emit_value(emitter, p, prim_op->operands.nodes[0]); - - const Type* src_qtype = prim_op->operands.nodes[0]->type; - bool uniform = is_qualified_type_uniform(src_qtype); - const Type* curr_ptr_type = get_unqualified_type(src_qtype); - assert(curr_ptr_type->tag == PtrType_TAG); - - const IntLiteral* offset_static_value = resolve_to_int_literal(prim_op->operands.nodes[1]); - if (!offset_static_value || offset_static_value->value != 0) { - CTerm offset = emit_value(emitter, p, prim_op->operands.nodes[1]); - // we sadly need to drop to the value level (aka explicit pointer arithmetic) to do this - // this means such code is never going to be legal in GLSL - // also the cast is to account for our arrays-in-structs hack - const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); - acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &(%s)[%s])", emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); - uniform &= is_qualified_type_uniform(prim_op->operands.nodes[1]->type); - } - - //t = t->payload.ptr_type.pointed_type; - for (size_t i = 2; i < prim_op->operands.count; i++) { - const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); - const Node* selector = prim_op->operands.nodes[i]; - uniform &= is_qualified_type_uniform(selector->type); - switch (is_type(pointee_type)) { - case ArrType_TAG: { - CTerm index = emit_value(emitter, p, selector); - acc = term_from_cvar(index_into_array(emitter, pointee_type, acc, index)); - curr_ptr_type = ptr_type(arena, (PtrType) { - .pointed_type = pointee_type->payload.arr_type.element_type, - .address_space = curr_ptr_type->payload.ptr_type.address_space - }); - break; - } - case TypeDeclRef_TAG: { - pointee_type = get_nominal_type_body(pointee_type); - SHADY_FALLTHROUGH - } - case RecordType_TAG: { - // yet another ISPC bug and workaround - // ISPC cannot deal with subscripting if you've done pointer arithmetic (!) inside the expression - // so hum we just need to introduce a temporary variable to hold the pointer expression so far, and go again from there - // See https://github.com/ispc/ispc/issues/2496 - if (emitter->config.dialect == CDialect_ISPC) { - String interm = unique_name(arena, "lea_intermediary_ptr_value"); - print(p, "\n%s = %s;", emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); - acc = term_from_cvalue(interm); - } - - assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a record need to be constant"); - size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); - String field_name = get_record_field_name(pointee_type, static_index); - acc = term_from_cvar(format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); - curr_ptr_type = ptr_type(arena, (PtrType) { - .pointed_type = pointee_type->payload.record_type.members.nodes[static_index], - .address_space = curr_ptr_type->payload.ptr_type.address_space - }); - break; - } - case Type_PackType_TAG: { - size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); - String suffixes = "xyzw"; - acc = term_from_cvar(format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); - curr_ptr_type = ptr_type(arena, (PtrType) { - .pointed_type = pointee_type->payload.pack_type.element_type, - .address_space = curr_ptr_type->payload.ptr_type.address_space - }); - break; - } - default: error("lea can't work on this"); - } - } - assert(outputs.count == 1); - outputs.results[0] = acc; - outputs.binding[0] = emitter->config.dialect == CDialect_ISPC ? LetBinding : NoBinding; - outputs.binding[0] = NoBinding; - return; } case size_of_op: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); @@ -863,6 +786,86 @@ static void emit_loop(Emitter* emitter, Printer* p, const Node* loop_instr, Inst } } +static void emit_lea(Emitter* emitter, Printer* p, Lea lea, InstructionOutputs outputs) { + IrArena* arena = emitter->arena; + CTerm acc = emit_value(emitter, p, lea.ptr); + + const Type* src_qtype = lea.ptr->type->type; + bool uniform = is_qualified_type_uniform(src_qtype); + const Type* curr_ptr_type = get_unqualified_type(src_qtype); + assert(curr_ptr_type->tag == PtrType_TAG); + + const IntLiteral* offset_static_value = resolve_to_int_literal(lea.offset); + if (!offset_static_value || offset_static_value->value != 0) { + CTerm offset = emit_value(emitter, p, lea.offset); + // we sadly need to drop to the value level (aka explicit pointer arithmetic) to do this + // this means such code is never going to be legal in GLSL + // also the cast is to account for our arrays-in-structs hack + const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); + acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &(%s)[%s])", emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); + uniform &= is_qualified_type_uniform(lea.offset->type); + } + + //t = t->payload.ptr_type.pointed_type; + for (size_t i = 0; i < lea.indices.count; i++) { + const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); + const Node* selector = lea.indices.nodes[i]; + uniform &= is_qualified_type_uniform(selector->type); + switch (is_type(pointee_type)) { + case ArrType_TAG: { + CTerm index = emit_value(emitter, p, selector); + acc = term_from_cvar(index_into_array(emitter, pointee_type, acc, index)); + curr_ptr_type = ptr_type(arena, (PtrType) { + .pointed_type = pointee_type->payload.arr_type.element_type, + .address_space = curr_ptr_type->payload.ptr_type.address_space + }); + break; + } + case TypeDeclRef_TAG: { + pointee_type = get_nominal_type_body(pointee_type); + SHADY_FALLTHROUGH + } + case RecordType_TAG: { + // yet another ISPC bug and workaround + // ISPC cannot deal with subscripting if you've done pointer arithmetic (!) inside the expression + // so hum we just need to introduce a temporary variable to hold the pointer expression so far, and go again from there + // See https://github.com/ispc/ispc/issues/2496 + if (emitter->config.dialect == CDialect_ISPC) { + String interm = unique_name(arena, "lea_intermediary_ptr_value"); + print(p, "\n%s = %s;", emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); + acc = term_from_cvalue(interm); + } + + assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a record need to be constant"); + size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); + String field_name = get_record_field_name(pointee_type, static_index); + acc = term_from_cvar(format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); + curr_ptr_type = ptr_type(arena, (PtrType) { + .pointed_type = pointee_type->payload.record_type.members.nodes[static_index], + .address_space = curr_ptr_type->payload.ptr_type.address_space + }); + break; + } + case Type_PackType_TAG: { + size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); + String suffixes = "xyzw"; + acc = term_from_cvar(format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); + curr_ptr_type = ptr_type(arena, (PtrType) { + .pointed_type = pointee_type->payload.pack_type.element_type, + .address_space = curr_ptr_type->payload.ptr_type.address_space + }); + break; + } + default: error("lea can't work on this"); + } + } + assert(outputs.count == 1); + outputs.results[0] = acc; + outputs.binding[0] = emitter->config.dialect == CDialect_ISPC ? LetBinding : NoBinding; + outputs.binding[0] = NoBinding; + return; +} + void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, InstructionOutputs outputs) { assert(is_instruction(instruction)); @@ -882,7 +885,8 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_Store_TAG: break; case Instruction_Lea_TAG: - break; + emit_lea(emitter, p, instruction->payload.lea, outputs); + return; case Instruction_CopyBytes_TAG: { CopyBytes payload = instruction->payload.copy_bytes; print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, p, payload.src)), to_cvalue(emitter, c_emit_value(emitter, p, payload.count))); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 1134b2728..1c8260fe2 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -383,27 +383,6 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui results[0] = result; return; } - case lea_op: { - SpvId base = emit_value(emitter, bb_builder, first(args)); - - LARRAY(SpvId, indices, args.count - 2); - for (size_t i = 2; i < args.count; i++) - indices[i - 2] = args.nodes[i] ? emit_value(emitter, bb_builder, args.nodes[i]) : 0; - - const IntLiteral* known_offset = resolve_to_int_literal(args.nodes[1]); - if (known_offset && known_offset->value == 0) { - const Type* target_type = instr->type; - SpvId result = spvb_access_chain(bb_builder, emit_type(emitter, target_type), base, args.count - 2, indices); - assert(results_count == 1); - results[0] = result; - } else { - const Type* target_type = instr->type; - SpvId result = spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, emit_value(emitter, bb_builder, args.nodes[1]), args.count - 2, indices); - assert(results_count == 1); - results[0] = result; - } - return; - } case select_op: { SpvId cond = emit_value(emitter, bb_builder, first(args)); SpvId truv = emit_value(emitter, bb_builder, args.nodes[1]); @@ -649,6 +628,28 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Match_TAG: emit_match(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.match_instr, results_count, results); break; case Loop_TAG: emit_loop(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.loop_instr, results_count, results); break; case Comment_TAG: break; + case Lea_TAG: { + Lea payload = instruction->payload.lea; + SpvId base = emit_value(emitter, *bb_builder, payload.ptr); + + LARRAY(SpvId, indices, payload.indices.count); + for (size_t i = 0; i < payload.indices.count; i++) + indices[i] = payload.indices.nodes[i] ? emit_value(emitter, *bb_builder, payload.indices.nodes[i]) : 0; + + const IntLiteral* known_offset = resolve_to_int_literal(payload.offset); + if (known_offset && known_offset->value == 0) { + const Type* target_type = instruction->type; + SpvId result = spvb_access_chain(*bb_builder, emit_type(emitter, target_type), base, payload.indices.count, indices); + assert(results_count == 1); + results[0] = result; + } else { + const Type* target_type = instruction->type; + SpvId result = spvb_ptr_access_chain(*bb_builder, emit_type(emitter, target_type), base, emit_value(emitter, *bb_builder, payload.offset), payload.indices.count, indices); + assert(results_count == 1); + results[0] = result; + } + return; + } default: error("TODO: unhandled instruction"); } } diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 32e70a738..ec0ff5ede 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -38,11 +38,13 @@ static const Node* look_past_stuff(const Node* thing) { if (thing->tag == PrimOp_TAG) { switch (thing->payload.prim_op.op) { case reinterpret_op: - case convert_op: - case lea_op: thing = first(thing->payload.prim_op.operands); break; + case convert_op: thing = first(thing->payload.prim_op.operands); break; default: assert(false); } } + if (thing->tag == Lea_TAG) { + thing = thing->payload.lea.ptr; + } return thing; } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 5ce672a2d..86b1ae94e 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -301,7 +301,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); } ops = change_node_at_index(a, ops, 0, ptr); - r = prim_op_helper(a, lea_op, empty(a), ops); + r = lea(a, (Lea) { ops.nodes[0], ops.nodes[1], nodes(a, ops.count - 2, &ops.nodes[2])}); if (UNTYPED_POINTERS) { const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 6c0286bdc..b6e5ea1ac 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -419,6 +419,7 @@ Nodes get_args_from_phi(SpvParser* parser, SpvId block, SpvId predecessor) { } size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { + IrArena* a = parser->arena; uint32_t* instruction = parser->words + instruction_offset; SpvOp op = instruction[0] & 0xFFFF; int size = (int) ((instruction[0] >> 16u) & 0xFFFFu); @@ -997,19 +998,20 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { bool has_element = op == SpvOpInBoundsPtrAccessChain || op == SpvOpPtrAccessChain; int indices_start = has_element ? 5 : 4; int num_indices = size - indices_start; - LARRAY(const Node*, ops, 2 + num_indices); - ops[0] = get_def_ssa_value(parser, instruction[3]); + LARRAY(const Node*, indices, num_indices); + const Node* ptr = get_def_ssa_value(parser, instruction[3]); + const Node* offset = NULL; if (has_element) - ops[1] = get_def_ssa_value(parser, instruction[4]); + offset = get_def_ssa_value(parser, instruction[4]); else - ops[1] = int32_literal(parser->arena, 0); + offset = int32_literal(parser->arena, 0); for (size_t i = 0; i < num_indices; i++) - ops[2 + i] = get_def_ssa_value(parser, instruction[indices_start + i]); + indices[i] = get_def_ssa_value(parser, instruction[indices_start + i]); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = lea_op, - .type_arguments = empty(parser->arena), - .operands = nodes(parser->arena, 2 + num_indices, ops) + parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, lea(a, (Lea) { + .ptr = ptr, + .offset = offset, + .indices = nodes(a, num_indices, indices), }), 1, NULL)); break; } diff --git a/src/shady/fold.c b/src/shady/fold.c index eb9768e4c..c442d8da5 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -192,33 +192,39 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { AddressSpace src_as = t->payload.ptr_type.address_space; while (ptr->tag == Variablez_TAG) { const Node* def = get_var_def(ptr->payload.varz); - if (def->tag != PrimOp_TAG) - break; - PrimOp instruction = def->payload.prim_op; - switch (instruction.op) { - case reinterpret_op: { - distance++; - ptr = first(instruction.operands); - continue; - } - case convert_op: { - // only conversions to generic pointers are acceptable - if (first(instruction.type_arguments)->tag != PtrType_TAG) - break; - assert(!specialize_generic && "something should not be converted to generic twice!"); - specialize_generic = true; - ptr = first(instruction.operands); - src_as = get_unqualified_type(ptr->type)->payload.ptr_type.address_space; - continue; + switch (def->tag) { + case PrimOp_TAG: { + PrimOp instruction = def->payload.prim_op; + switch (instruction.op) { + case reinterpret_op: { + distance++; + ptr = first(instruction.operands); + continue; + } + case convert_op: { + // only conversions to generic pointers are acceptable + if (first(instruction.type_arguments)->tag != PtrType_TAG) + break; + assert(!specialize_generic && "something should not be converted to generic twice!"); + specialize_generic = true; + ptr = first(instruction.operands); + src_as = get_unqualified_type(ptr->type)->payload.ptr_type.address_space; + continue; + } + default: break; + } + break; } - case lea_op: { - Nodes ops = instruction.operands; - for (size_t i = 1; i < ops.count; i++) { - if (!is_zero(ops.nodes[i])) + case Lea_TAG: { + Lea payload = def->payload.lea; + if (!is_zero(payload.offset)) + goto outer_break; + for (size_t i = 0; i < payload.indices.count; i++) { + if (!is_zero(payload.indices.nodes[i])) goto outer_break; } distance++; - ptr = first(ops); + ptr = payload.ptr; continue; outer_break: break; @@ -262,8 +268,7 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { bool rebuild = false; switch (payload.op) { case store_op: - case load_op: - case lea_op: { + case load_op: { simplify_ptr_operand(arena, bb, &payload, &rebuild, 0); break; } @@ -297,32 +302,49 @@ static const Node* fold_prim_op(IrArena* arena, const Node* node) { return quote_single(arena, value); break; } - case store_op: { - if (first(payload.operands)->tag == Undef_TAG) { - return quote_helper(arena, empty(arena)); - } - break; - } - case load_op: { - if (first(payload.operands)->tag == Undef_TAG) { - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); - } - break; - } - case reinterpret_op: case convert_op: - if (first(payload.operands)->tag == Undef_TAG) { - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); - } + case reinterpret_op: { // get rid of identity casts if (payload.type_arguments.nodes[0] == get_unqualified_type(payload.operands.nodes[0]->type)) return quote_single(arena, payload.operands.nodes[0]); break; - case lea_op: - if (first(payload.operands)->tag == Undef_TAG) { - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + } + default: break; + } + return node; +} + +static const Node* fold_memory_poison(IrArena* arena, const Node* node) { + switch (node->tag) { + case PrimOp_TAG: { + PrimOp payload = node->payload.prim_op; + switch (payload.op) { + case store_op: { + if (first(payload.operands)->tag == Undef_TAG) + return quote_helper(arena, empty(arena)); + break; + } + case load_op: { + if (first(payload.operands)->tag == Undef_TAG) + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + break; + } + case reinterpret_op: + case convert_op: { + if (first(payload.operands)->tag == Undef_TAG) + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + break; + } + default: break; } break; + } + case Lea_TAG: { + Lea payload = node->payload.lea; + if (payload.ptr->tag == Undef_TAG) + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + break; + } default: break; } return node; @@ -335,9 +357,10 @@ static bool is_unreachable_case(const Node* c) { } const Node* fold_node(IrArena* arena, const Node* node) { - const Node* folded = node; + const Node* const original_node = node; + node = fold_memory_poison(arena, node); switch (node->tag) { - case PrimOp_TAG: folded = fold_prim_op(arena, node); break; + case PrimOp_TAG: node = fold_prim_op(arena, node); break; case Block_TAG: { const Node* lam = node->payload.block.inside; const Node* body = lam->payload.case_.body; @@ -357,11 +380,11 @@ const Node* fold_node(IrArena* arena, const Node* node) { only_forwards &= yield_args.nodes[i] == let_case_params.nodes[i]; } if (only_forwards) { - debugv_print("Fold: simplify "); - log_node(DEBUGV, node); - debugv_print(" into just "); - log_node(DEBUGV, instr); - debugv_print(".\n"); + log_string(DEBUGVV, "Fold: simplify "); + log_node(DEBUGVV, node); + log_string(DEBUGVV, " into just "); + log_node(DEBUGVV, instr); + log_string(DEBUGVV, ".\n"); return instr; } } @@ -420,12 +443,12 @@ const Node* fold_node(IrArena* arena, const Node* node) { } // catch bad folding rules that mess things up - if (is_value(node)) assert(is_value(folded)); - if (is_instruction(node)) assert(is_instruction(folded)); - if (is_terminator(node)) assert(is_terminator(folded)); + if (is_value(original_node)) assert(is_value(node)); + if (is_instruction(original_node)) assert(is_instruction(node)); + if (is_terminator(original_node)) assert(is_terminator(node)); if (node->type) - assert(is_subtype(node->type, folded->type)); + assert(is_subtype(original_node->type, node->type)); - return folded; + return node; } diff --git a/src/shady/node.c b/src/shady/node.c index 500cbf047..6e45f716e 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -90,6 +90,19 @@ const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { while (true) { ptr = resolve_node_to_definition(ptr, config); switch (ptr->tag) { + case Lea_TAG: { + Lea lea = ptr->payload.lea; + if (!is_zero(lea.offset)) + goto outer_break; + for (size_t i = 0; i < lea.indices.count; i++) { + if (!is_zero(lea.indices.nodes[i])) + goto outer_break; + } + ptr = lea.ptr; + continue; + outer_break: + break; + } case PrimOp_TAG: { switch (ptr->payload.prim_op.op) { case convert_op: { @@ -109,17 +122,6 @@ const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { } break; } - case lea_op: { - Nodes ops = ptr->payload.prim_op.operands; - for (size_t i = 1; i < ops.count; i++) { - if (!is_zero(ops.nodes[i])) - goto outer_break; - } - ptr = first(ops); - continue; - outer_break: - break; - } default: break; } break; @@ -269,22 +271,16 @@ const char* get_string_literal(IrArena* arena, const Node* node) { const Node* decl = node->payload.ref_decl.decl; return get_string_literal(arena, decl); } - case PrimOp_TAG: { - switch (node->payload.prim_op.op) { - case lea_op: { - Nodes ops = node->payload.prim_op.operands; - if (ops.count == 3 && is_zero(ops.nodes[1]) && is_zero(ops.nodes[2])) { - const Node* ref = first(ops); - if (ref->tag != RefDecl_TAG) - return NULL; - const Node* decl = ref->payload.ref_decl.decl; - if (decl->tag != GlobalVariable_TAG || !decl->payload.global_variable.init) - return NULL; - return get_string_literal(arena, decl->payload.global_variable.init); - } - break; - } - default: break; + case Lea_TAG: { + Lea lea = node->payload.lea; + if (lea.indices.count == 3 && is_zero(lea.offset) && is_zero(first(lea.indices))) { + const Node* ref = lea.ptr; + if (ref->tag != RefDecl_TAG) + return NULL; + const Node* decl = ref->payload.ref_decl.decl; + if (decl->tag != GlobalVariable_TAG || !decl->payload.global_variable.init) + return NULL; + return get_string_literal(arena, decl->payload.global_variable.init); } return NULL; } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index cdac3b022..aa397fe80 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -97,10 +97,7 @@ static const Node* get_node_address_safe(Context* ctx, const Node* node) { if (src_ptr == NULL) return NULL; const Node* index = rewrite_node(&ctx->rewriter, node->payload.prim_op.operands.nodes[1]); - return prim_op(a, (PrimOp) { - .op = lea_op, - .operands = nodes(a, 3, (const Node* []) {src_ptr, int32_literal(a, 0), index }) - }); + return lea(a, (Lea) { .ptr = src_ptr, .offset = int32_literal(a, 0), singleton(index) }); } else if (node->tag == PrimOp_TAG && node->payload.prim_op.op == deref_op) { return rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)); } diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 059af5e21..9d9a24c63 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -414,32 +414,6 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp goto rebuild; } - case lea_op: { - assert(old_operands.count >= 2); - assert(type_args.count <= 1); - new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); - new_operands[1] = infer(ctx, old_operands.nodes[1], NULL); - for (size_t i = 2; i < old_operands.count; i++) { - new_operands[i] = infer(ctx, old_operands.nodes[i], NULL); - } - - const Type* src_ptr = remove_uniformity_qualifier(new_operands[0]->type); - const Type* base_datatype = src_ptr; - assert(base_datatype->tag == PtrType_TAG); - assert(type_args.count == 0); - - Nodes new_ops = nodes(a, old_operands.count, new_operands); - - const Node* offset = new_operands[1]; - - const Node* result = first(bind_instruction(bb, prim_op(a, (PrimOp) { - .op = lea_op, - .type_arguments = empty(a), - .operands = new_ops - }))); - - return yield_values_and_wrap_in_block(bb, singleton(result)); - } case empty_mask_op: case subgroup_active_mask_op: case subgroup_elect_first_op: @@ -623,6 +597,18 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes case Control_TAG: return infer_control(ctx, node, expected_types); case Block_TAG: return infer_block (ctx, node, expected_types); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); + case Instruction_Lea_TAG: { + Lea payload = node->payload.lea; + const Node* ptr = infer(ctx, payload.ptr, NULL); + const Node* offset = infer(ctx, payload.offset, NULL); + Nodes indices = infer_nodes(ctx, payload.indices); + + const Type* src_ptr = remove_uniformity_qualifier(ptr->type); + const Type* base_datatype = src_ptr; + assert(base_datatype->tag == PtrType_TAG); + + return lea(ctx->rewriter.dst_arena, (Lea) { ptr, offset, indices }); + } default: error("TODO") case NotAnInstruction: error("not an instruction"); } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 4123c8233..19a62237f 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -150,7 +150,7 @@ static const Node* process(Context* ctx, const Node* node) { //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); - const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, ctx->entry_base_stack_ptr, gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->entry_stack_offset, converted_offset)))); + const Node* lea_instr = lea(a, (Lea) { ctx->entry_base_stack_ptr, gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->entry_stack_offset, converted_offset)), empty(a) }); const Node* slot = first(bind_instruction_named(bb, lea_instr, (String []) { format_string_arena(a->arena, "stack_slot_%d", found_slot->i) })); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = gen_reinterpret_cast(bb, ptr_t, slot); diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 19a5aa22a..1fbfa1b42 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -26,7 +26,7 @@ static bool is_as_emulated(SHADY_UNUSED Context* ctx, AddressSpace as) { } } -static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* pointer_type, const Node* base, const Node* offset, size_t n_indices, const Node** indices) { +static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* pointer_type, const Node* base, const Node* offset, Nodes indices) { IrArena* a = ctx->rewriter.dst_arena; const Type* emulated_ptr_t = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); assert(pointer_type->tag == PtrType_TAG); @@ -48,7 +48,7 @@ static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* p ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, physical_offset}); } - for (size_t i = 0; i < n_indices; i++) { + for (size_t i = 0; i < indices.count; i++) { assert(pointer_type->tag == PtrType_TAG); const Type* pointed_type = pointer_type->payload.ptr_type.pointed_type; switch (pointed_type->tag) { @@ -57,7 +57,7 @@ static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* p const Node* element_t_size = gen_primop_e(bb, size_of_op, singleton(element_type), empty(a)); - const Node* new_index = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, indices[i]); + const Node* new_index = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, indices.nodes[i]); const Node* physical_offset = gen_primop_ce(bb, mul_op, 2, (const Node* []) {new_index, element_t_size}); ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, physical_offset }); @@ -77,7 +77,7 @@ static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* p case RecordType_TAG: { Nodes member_types = pointed_type->payload.record_type.members; - const IntLiteral* selector_value = resolve_to_int_literal(indices[i]); + const IntLiteral* selector_value = resolve_to_int_literal(indices.nodes[i]); assert(selector_value && "selector value must be known for LEA into a record"); size_t n = selector_value->value; assert(n < member_types.count); @@ -102,39 +102,34 @@ static const Node* process(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; const Type* emulated_ptr_t = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); switch (old->tag) { - case PrimOp_TAG: { - switch (old->payload.prim_op.op) { - case lea_op: { - Nodes old_ops = old->payload.prim_op.operands; - const Node* old_base = first(old_ops); - const Type* old_base_ptr_t = old_base->type; - deconstruct_qualified_type(&old_base_ptr_t); - assert(old_base_ptr_t->tag == PtrType_TAG); - const Node* old_result_t = old->type; - deconstruct_qualified_type(&old_result_t); - bool must_lower = false; - // we have to lower generic pointers if we emulate them using ints - must_lower |= ctx->config->lower.emulate_generic_ptrs && old_base_ptr_t->payload.ptr_type.address_space == AsGeneric; - must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference && is_as_emulated(ctx, old_base_ptr_t->payload.ptr_type.address_space); - if (!must_lower) - break; - BodyBuilder* bb = begin_body(a); - Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); - const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, first(new_ops)); - const Type* new_base_t = rewrite_node(&ctx->rewriter, old_base_ptr_t); - const Node* result = lower_ptr_arithm(ctx, bb, new_base_t, cast_base, new_ops.nodes[1], new_ops.count - 2, &new_ops.nodes[2]); - const Type* new_ptr_t = rewrite_node(&ctx->rewriter, old_result_t); - const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); - return yield_values_and_wrap_in_block(bb, singleton(cast_result)); - } - default: break; - } - break; + case Lea_TAG: { + Lea lea = old->payload.lea; + const Node* old_base = lea.ptr; + const Type* old_base_ptr_t = old_base->type; + deconstruct_qualified_type(&old_base_ptr_t); + assert(old_base_ptr_t->tag == PtrType_TAG); + const Node* old_result_t = old->type; + deconstruct_qualified_type(&old_result_t); + bool must_lower = false; + // we have to lower generic pointers if we emulate them using ints + must_lower |= ctx->config->lower.emulate_generic_ptrs && old_base_ptr_t->payload.ptr_type.address_space == AsGeneric; + must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference && is_as_emulated(ctx, old_base_ptr_t->payload.ptr_type.address_space); + if (!must_lower) + break; + BodyBuilder* bb = begin_body(a); + // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); + const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, rewrite_node(r, lea.ptr)); + const Type* new_base_t = rewrite_node(&ctx->rewriter, old_base_ptr_t); + const Node* result = lower_ptr_arithm(ctx, bb, new_base_t, cast_base, rewrite_node(r, lea.offset), rewrite_nodes(r, lea.indices)); + const Type* new_ptr_t = rewrite_node(&ctx->rewriter, old_result_t); + const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); + return yield_values_and_wrap_in_block(bb, singleton(cast_result)); } default: break; } diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index c8f39d20a..c21699ccd 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -56,6 +56,19 @@ static const Node* process(Context* ctx, const Node* old) { payload.pointed_type = rewrite_node(r, payload.pointed_type); return ptr_type(a, payload); } + case Lea_TAG: { + Lea payload = old->payload.lea; + const Type* optr_t = payload.ptr->type; + deconstruct_qualified_type(&optr_t); + assert(optr_t->tag == PtrType_TAG); + const Type* expected_type = rewrite_node(r, optr_t); + const Node* ptr = rewrite_node(r, payload.ptr); + const Type* actual_type = get_unqualified_type(ptr->type); + BodyBuilder* bb = begin_body(a); + if (expected_type != actual_type) + ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); + return bind_last_instruction_and_wrap_in_block(bb, lea(a, (Lea) { ptr, rewrite_node(r, payload.offset), rewrite_nodes(r, payload.indices)})); + } case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; switch (payload.op) { @@ -68,8 +81,7 @@ static const Node* process(Context* ctx, const Node* old) { break; } case load_op: - case store_op: - case lea_op: { + case store_op: { const Node* optr = first(payload.operands); const Type* optr_t = optr->type; deconstruct_qualified_type(&optr_t); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 4a51db570..c482d35c3 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -60,7 +60,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* zero = size_t_literal(a, 0); switch (element_type->tag) { case Bool_TAG: { - const Node* logical_ptr = gen_primop_ce(bb, lea_op, 3, (const Node* []) { arr, zero, base_offset }); + const Node* logical_ptr = gen_lea(bb, arr, zero, singleton(base_offset)); const Node* value = gen_load(bb, logical_ptr); return gen_primop_ce(bb, neq_op, 2, (const Node*[]) {value, int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size })}); } @@ -82,7 +82,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { - const Node* word = gen_load(bb, gen_primop_ce(bb, lea_op, 3, (const Node* []) {arr, zero, offset})); + const Node* word = gen_load(bb, gen_lea(bb, arr, zero, singleton(base_offset))); word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded word = first(gen_primop(bb, lshift_op, empty(a), mk_nodes(a, word, shift))); // shift it acc = gen_primop_e(bb, or_op, empty(a), mk_nodes(a, acc, word)); @@ -149,7 +149,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* zero = size_t_literal(a, 0); switch (element_type->tag) { case Bool_TAG: { - const Node* logical_ptr = gen_primop_ce(bb, lea_op, 3, (const Node* []) { arr, zero, base_offset }); + const Node* logical_ptr = gen_lea(bb, arr, zero, singleton(base_offset)); const Node* zero_b = int_literal(a, (IntLiteral) { .value = 1, .width = a->config.memory.word_size }); const Node* one_b = int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size }); const Node* int_value = gen_primop_ce(bb, select_op, 3, (const Node*[]) { value, one_b, zero_b }); @@ -181,7 +181,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element /*bool needs_patch = is_last_word && word_size_in_bytes < length_in_bytes; const Node* original_word = NULL; if (needs_patch) { - original_word = gen_load(bb, gen_primop_ce(bb, lea_op, 3, (const Node* []) {arr, zero, offset})); + original_word = gen_load(bb, gen_lea(bb, arr, zero, singleton(base_offset))); error_print("TODO"); error_die(); // word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded @@ -189,7 +189,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* word = value; word = first(gen_primop(bb, rshift_logical_op, empty(a), mk_nodes(a, word, shift))); // shift it word = gen_conversion(bb, int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }), word); // widen/truncate the word we want to store - gen_store(bb, gen_primop_ce(bb, lea_op, 3, (const Node* []) {arr, zero, offset}), word); + gen_store(bb, gen_lea(bb, arr, zero, singleton(base_offset)), word); offset = first(gen_primop(bb, add_op, empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); shift = first(gen_primop(bb, add_op, empty(a), mk_nodes(a, shift, word_bitwidth))); diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 82358a86c..8b7318790 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -39,16 +39,14 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { case Variablez_TAG: { return get_req_cast(ctx, get_var_def(src->payload.varz)); } - case PrimOp_TAG: { - PrimOp prim_op = src->payload.prim_op; - if (prim_op.op == lea_op) { - const Type* src_req_cast = get_req_cast(ctx, first(prim_op.operands)); - if (src_req_cast) { - bool u = deconstruct_qualified_type(&src_req_cast); - enter_composite(&src_req_cast, &u, nodes(a, prim_op.operands.count - 2, &prim_op.operands.nodes[2]), false); - return src_req_cast; - } + case Lea_TAG: { + const Type* src_req_cast = get_req_cast(ctx, src->payload.lea.ptr); + if (src_req_cast) { + bool u = deconstruct_qualified_type(&src_req_cast); + enter_composite(&src_req_cast, &u, src->payload.lea.indices, false); + return src_req_cast; } + break; } default: break; } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index cf0ef5744..c89c92c3c 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -112,15 +112,15 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca k->leaks = true; continue; }*/ - case lea_op: { - // TODO: follow where those derived pointers are used and establish whether they leak themselves - // use slice_type to keep track of the expected type for the relevant sub-object - k->leaks = true; - continue; - } default: break; + default: break; } if (has_primop_got_side_effects(payload.op)) k->leaks = true; + } else if (use->user->tag == Lea_TAG) { + // TODO: follow where those derived pointers are used and establish whether they leak themselves + // use slice_type to keep track of the expected type for the relevant sub-object + k->leaks = true; + continue; } else if (use->user->tag == Composite_TAG) { // todo... // note: if a composite literal containing our POI (pointer-of-interest) is extracted from, folding ops simplify this to the original POI diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 1042b0149..57185e5b3 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -91,12 +91,7 @@ void gen_store(BodyBuilder* instructions, const Node* ptr, const Node* value) { } const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { - LARRAY(const Node*, ops, 2 + selectors.count); - ops[0] = base; - ops[1] = offset; - for (size_t i = 0; i < selectors.count; i++) - ops[2 + i] = selectors.nodes[i]; - return gen_primop_ce(bb, lea_op, 2 + selectors.count, ops); + return first(bind_instruction(bb, lea(bb->arena, (Lea) { base, offset, selectors }))); } const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { diff --git a/src/shady/type.c b/src/shady/type.c index 5f0b5315d..77394caab 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -776,41 +776,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { }) }); } - case lea_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count >= 2); - - const Node* base = prim_op.operands.nodes[0]; - bool uniform = is_qualified_type_uniform(base->type); - - const Type* base_ptr_type = get_unqualified_type(base->type); - assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); - const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; - - const Node* offset = prim_op.operands.nodes[1]; - assert(offset); - const Type* offset_type = offset->type; - bool offset_uniform = deconstruct_qualified_type(&offset_type); - assert(offset_type->tag == Int_TAG && "lea expects an integer offset"); - - const IntLiteral* lit = resolve_to_int_literal(offset); - bool offset_is_zero = lit && lit->value == 0; - assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); - assert(offset_is_zero || is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); - uniform &= offset_uniform; - - Nodes indices = nodes(arena, prim_op.operands.count - 2, &prim_op.operands.nodes[2]); - enter_composite(&pointee_type, &uniform, indices, true); - - return qualified_type(arena, (QualifiedType) { - .is_uniform = uniform, - .type = ptr_type(arena, (PtrType) { - .pointed_type = pointee_type, - .address_space = base_ptr_type->payload.ptr_type.address_space, - .is_reference = base_ptr_type->payload.ptr_type.is_reference - }) - }); - } case align_of_op: case size_of_op: { assert(prim_op.type_arguments.count == 1); From ed090e3ec0ba4b2749255774e69cca356ec10e2b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Jul 2024 11:26:46 +0200 Subject: [PATCH 346/693] migrated load and store to nodes --- include/shady/primops.json | 10 --- src/backend/c/emit_c_instructions.c | 49 ++++++------ src/backend/spirv/emit_spv_instructions.c | 97 ++++++++++++----------- src/frontend/llvm/l2s_instr.c | 6 +- src/frontend/spirv/s2s.c | 18 +---- src/shady/analysis/cfg.c | 8 ++ src/shady/fold.c | 96 ++++++++++++---------- src/shady/node.c | 20 ++--- src/shady/passes/bind.c | 16 +--- src/shady/passes/infer.c | 35 ++++---- src/shady/passes/lower_generic_ptrs.c | 51 ++++++------ src/shady/passes/lower_logical_pointers.c | 42 ++++++---- src/shady/passes/lower_physical_ptrs.c | 58 ++++++++------ src/shady/passes/lower_stack.c | 2 +- src/shady/passes/lower_workgroups.c | 24 +++--- src/shady/passes/normalize_builtins.c | 23 +++--- src/shady/passes/opt_demote_alloca.c | 92 ++++++++++----------- src/shady/passes/opt_mem2reg.c | 60 ++++++++------ src/shady/passes/opt_restructure.c | 13 +-- src/shady/print.c | 6 +- src/shady/transform/ir_gen_helpers.c | 10 +-- src/shady/type.c | 38 --------- test/generic_ptrs2.slim | 2 +- test/memory1.slim | 2 +- test/memory2.slim | 4 +- test/opt/opt_oracle.c | 31 +++++--- 26 files changed, 398 insertions(+), 415 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index 4f7319e48..47c9774a7 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -219,16 +219,6 @@ "class": "memory", "side-effects": true }, - { - "name": "load", - "class": "memory", - "side-effects": true - }, - { - "name": "store", - "class": "memory", - "side-effects": true - }, { "name": "size_of", "class": "memory_layout" diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index b463ae063..b8706a18c 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -329,28 +329,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct outputs.binding[0] = NoBinding; return; } - case load_op: { - CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, first(prim_op->operands))); - outputs.results[0] = term_from_cvalue(dereferenced); - outputs.binding[0] = LetBinding; - return; - } - case store_op: { - const Node* addr = first(prim_op->operands); - const Node* value = prim_op->operands.nodes[1]; - const Type* addr_type = addr->type; - bool addr_uniform = deconstruct_qualified_type(&addr_type); - bool value_uniform = is_qualified_type_uniform(value->type); - assert(addr_type->tag == PtrType_TAG); - CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, addr)); - CValue cvalue = to_cvalue(emitter, emit_value(emitter, p, value)); - // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this - if (emitter->config.dialect == CDialect_ISPC && addr_uniform && is_addr_space_uniform(arena, addr_type->payload.ptr_type.address_space) && !value_uniform) - cvalue = format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); - - print(p, "\n%s = %s;", dereferenced, cvalue); - return; - } case size_of_op: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); break; @@ -868,6 +846,7 @@ static void emit_lea(Emitter* emitter, Printer* p, Lea lea, InstructionOutputs o void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, InstructionOutputs outputs) { assert(is_instruction(instruction)); + IrArena* a = emitter->arena; switch (is_instruction(instruction)) { case NotAnInstruction: assert(false); @@ -880,10 +859,28 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_Control_TAG: error("TODO") case Instruction_Block_TAG: error("Should be eliminated by the compiler") case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; - case Instruction_Load_TAG: - break; - case Instruction_Store_TAG: - break; + case Instruction_Load_TAG: { + Load payload = instruction->payload.load; + CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, payload.ptr)); + outputs.results[0] = term_from_cvalue(dereferenced); + outputs.binding[0] = LetBinding; + return; + } + case Instruction_Store_TAG: { + Store payload = instruction->payload.store; + const Type* addr_type = payload.ptr->type; + bool addr_uniform = deconstruct_qualified_type(&addr_type); + bool value_uniform = is_qualified_type_uniform(payload.value->type); + assert(addr_type->tag == PtrType_TAG); + CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, payload.ptr)); + CValue cvalue = to_cvalue(emitter, emit_value(emitter, p, payload.value)); + // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this + if (emitter->config.dialect == CDialect_ISPC && addr_uniform && is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) + cvalue = format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); + + print(p, "\n%s = %s;", dereferenced, cvalue); + return; + } case Instruction_Lea_TAG: emit_lea(emitter, p, instruction->payload.lea, outputs); return; diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 1c8260fe2..730e32f43 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -250,7 +250,8 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { SpvId local_id; const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); - emit_primop(emitter, fn_builder, bb_builder, prim_op(emitter->arena, (PrimOp) { .op = load_op, .operands = singleton(b) }), 1, &local_id); + // TODO: very hacky indeed + emit_instruction(emitter, fn_builder, &bb_builder, NULL, load(emitter->arena, (Load) { b }), 1, &local_id); result = spvb_group_shuffle(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), scope_subgroup, emit_value(emitter, bb_builder, first(args)), local_id); spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); } else { @@ -329,50 +330,6 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui results[0] = spvb_vecshuffle(bb_builder, emit_type(emitter, result_t), a, b, args.count - 2, indices); return; } - case load_op: { - const Type* ptr_type = first(args)->type; - deconstruct_qualified_type(&ptr_type); - assert(ptr_type->tag == PtrType_TAG); - const Type* elem_type = ptr_type->payload.ptr_type.pointed_type; - - size_t operands_count = 0; - uint32_t operands[2]; - if (ptr_type->payload.ptr_type.address_space == AsGlobal) { - // TODO only do this in VK mode ? - TypeMemLayout layout = get_mem_layout(emitter->arena, elem_type); - operands[operands_count + 0] = SpvMemoryAccessAlignedMask; - operands[operands_count + 1] = (uint32_t) layout.alignment_in_bytes; - operands_count += 2; - } - - SpvId eptr = emit_value(emitter, bb_builder, first(args)); - SpvId result = spvb_load(bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); - assert(results_count == 1); - results[0] = result; - return; - } - case store_op: { - const Type* ptr_type = first(args)->type; - deconstruct_qualified_type(&ptr_type); - assert(ptr_type->tag == PtrType_TAG); - const Type* elem_type = ptr_type->payload.ptr_type.pointed_type; - - size_t operands_count = 0; - uint32_t operands[2]; - if (ptr_type->payload.ptr_type.address_space == AsGlobal) { - // TODO only do this in VK mode ? - TypeMemLayout layout = get_mem_layout(emitter->arena, elem_type); - operands[operands_count + 0] = SpvMemoryAccessAlignedMask; - operands[operands_count + 1] = (uint32_t) layout.alignment_in_bytes; - operands_count += 2; - } - - SpvId eptr = emit_value(emitter, bb_builder, first(args)); - SpvId eval = emit_value(emitter, bb_builder, args.nodes[1]); - spvb_store(bb_builder, eval, eptr, operands_count, operands); - assert(results_count == 0); - return; - } case alloca_logical_op: { const Type* elem_type = first(type_arguments); SpvId result = spvb_local_variable(fn_builder, emit_type(emitter, ptr_type(emitter->arena, (PtrType) { @@ -620,6 +577,9 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil switch (is_instruction(instruction)) { case NotAnInstruction: error(""); + case Instruction_CopyBytes_TAG: + case Instruction_FillBytes_TAG: + case Instruction_LetMut_TAG: case Instruction_Control_TAG: case Instruction_Block_TAG: error("Should be lowered elsewhere") case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; @@ -628,6 +588,52 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Match_TAG: emit_match(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.match_instr, results_count, results); break; case Loop_TAG: emit_loop(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.loop_instr, results_count, results); break; case Comment_TAG: break; + case Instruction_Load_TAG: { + Load payload = instruction->payload.load; + const Type* ptr_type = payload.ptr->type; + deconstruct_qualified_type(&ptr_type); + assert(ptr_type->tag == PtrType_TAG); + const Type* elem_type = ptr_type->payload.ptr_type.pointed_type; + + size_t operands_count = 0; + uint32_t operands[2]; + if (ptr_type->payload.ptr_type.address_space == AsGlobal) { + // TODO only do this in VK mode ? + TypeMemLayout layout = get_mem_layout(emitter->arena, elem_type); + operands[operands_count + 0] = SpvMemoryAccessAlignedMask; + operands[operands_count + 1] = (uint32_t) layout.alignment_in_bytes; + operands_count += 2; + } + + SpvId eptr = emit_value(emitter, *bb_builder, payload.ptr); + SpvId result = spvb_load(*bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); + assert(results_count == 1); + results[0] = result; + return; + } + case Instruction_Store_TAG: { + Store payload = instruction->payload.store; + const Type* ptr_type = payload.ptr->type; + deconstruct_qualified_type(&ptr_type); + assert(ptr_type->tag == PtrType_TAG); + const Type* elem_type = ptr_type->payload.ptr_type.pointed_type; + + size_t operands_count = 0; + uint32_t operands[2]; + if (ptr_type->payload.ptr_type.address_space == AsGlobal) { + // TODO only do this in VK mode ? + TypeMemLayout layout = get_mem_layout(emitter->arena, elem_type); + operands[operands_count + 0] = SpvMemoryAccessAlignedMask; + operands[operands_count + 1] = (uint32_t) layout.alignment_in_bytes; + operands_count += 2; + } + + SpvId eptr = emit_value(emitter, *bb_builder, payload.ptr); + SpvId eval = emit_value(emitter, *bb_builder, payload.value); + spvb_store(*bb_builder, eval, eptr, operands_count, operands); + assert(results_count == 0); + return; + } case Lea_TAG: { Lea payload = instruction->payload.lea; SpvId base = emit_value(emitter, *bb_builder, payload.ptr); @@ -650,6 +656,5 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil } return; } - default: error("TODO: unhandled instruction"); } } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 86b1ae94e..5f898ae1d 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -274,7 +274,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); } - r = prim_op_helper(a, load_op, empty(a), singleton(ptr)); + r = load(a, (Load) { ptr }); break; } case LLVMStore: { @@ -288,7 +288,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); } - r = prim_op_helper(a, store_op, empty(a), mk_nodes(a, ptr, ops.nodes[0])); + r = store(a, (Store) { ptr, ops.nodes[0] }); break; } case LLVMGetElementPtr: { @@ -598,7 +598,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LARRAY(const Node*, processed_ops, ops.count); for (i = 0; i < num_args; i++) { if (decoded[i].is_byval) - processed_ops[i] = first(bind_instruction_outputs_count(b, prim_op_helper(a, load_op, empty(a), singleton(ops.nodes[i])), 1, NULL)); + processed_ops[i] = first(bind_instruction_outputs_count(b, load(a, (Load) { ops.nodes[i] }), 1, NULL)); else processed_ops[i] = ops.nodes[i]; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index b6e5ea1ac..e80c3f56d 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -752,11 +752,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].node = ptr; if (size == 5) - bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = store_op, - .type_arguments = empty(parser->arena), - .operands = mk_nodes(parser->arena, ptr, get_def_ssa_value(parser, instruction[4])) - }), 1, NULL); + bind_instruction_outputs_count(parser->current_block.builder, store(parser->arena, (Store) { ptr, get_def_ssa_value(parser, instruction[4]) }), 1, NULL); } else { Nodes annotations = empty(parser->arena); SpvDeco* builtin = find_decoration(parser, result, -1, SpvDecorationBuiltIn); @@ -1079,21 +1075,13 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpLoad: { const Type* src = get_def_ssa_value(parser, instruction[3]); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = load_op, - .type_arguments = empty(parser->arena), - .operands = singleton(src) - }), 1, NULL)); + parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, load(a, (Load) { src }), 1, NULL)); break; } case SpvOpStore: { const Type* ptr = get_def_ssa_value(parser, instruction[1]); const Type* value = get_def_ssa_value(parser, instruction[2]); - bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = store_op, - .type_arguments = empty(parser->arena), - .operands = mk_nodes(parser->arena, ptr, value) - }), 0, NULL); + bind_instruction_outputs_count(parser->current_block.builder, store(a, (Store) { ptr, value }), 0, NULL); break; } case SpvOpCopyMemory: diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 9e2999abb..397cead70 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -135,12 +135,20 @@ static void add_jump_edge(CfgBuildContext* ctx, const Node* src, const Node* j) add_edge(ctx, src, target, JumpEdge); } +#pragma GCC diagnostic error "-Wswitch" + static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node* instruction, const Node* let_tail) { switch (is_instruction(instruction)) { case NotAnInstruction: error("Grammar problem"); case Instruction_Call_TAG: case Instruction_PrimOp_TAG: case Instruction_Comment_TAG: + case Instruction_LetMut_TAG: + case Instruction_Load_TAG: + case Instruction_Store_TAG: + case Instruction_Lea_TAG: + case Instruction_CopyBytes_TAG: + case Instruction_FillBytes_TAG: add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); return; case Instruction_Block_TAG: diff --git a/src/shady/fold.c b/src/shady/fold.c index c442d8da5..baa8c6283 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -248,50 +248,65 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { return original_ptr; } -static void inline simplify_ptr_operand(IrArena* a, BodyBuilder* bb, PrimOp* payload, bool* success, int i) { - const Node* old_op = payload->operands.nodes[i]; +static inline const Node* simplify_ptr_operand(IrArena* a, BodyBuilder* bb, const Node* old_op) { const Type* ptr_t = old_op->type; deconstruct_qualified_type(&ptr_t); if (ptr_t->payload.ptr_type.is_reference) - return; + return NULL; const Node* new_op = resolve_ptr_source(bb, old_op); - if (old_op != new_op) { - payload->operands = change_node_at_index(a, payload->operands, i, new_op); - *success = true; - } + return old_op != new_op ? new_op : NULL; } static inline const Node* fold_simplify_ptr_operand(const Node* node) { IrArena* arena = node->arena; - PrimOp payload = node->payload.prim_op; BodyBuilder* bb = begin_body(arena); - bool rebuild = false; - switch (payload.op) { - case store_op: - case load_op: { - simplify_ptr_operand(arena, bb, &payload, &rebuild, 0); + const Node* r = NULL; + switch (node->tag) { + case Load_TAG: { + Load payload = node->payload.load; + const Node* nptr = simplify_ptr_operand(arena, bb, payload.ptr); + if (!nptr) break; + payload.ptr = nptr; + r = load(arena, payload); break; } - default: break; + case Store_TAG: { + Store payload = node->payload.store; + const Node* nptr = simplify_ptr_operand(arena, bb, payload.ptr); + if (!nptr) break; + payload.ptr = nptr; + r = store(arena, payload); + break; + } + case Lea_TAG: { + Lea payload = node->payload.lea; + const Node* nptr = simplify_ptr_operand(arena, bb, payload.ptr); + if (!nptr) break; + payload.ptr = nptr; + r = lea(arena, payload); + break; + } + default: { + cancel_body(bb); + return node; + } } - if (rebuild) { - const Node* r = prim_op(arena, payload); - if (!is_subtype(node->type, r->type)) { - r = gen_conversion(bb, get_unqualified_type(node->type), first(bind_instruction(bb, r))); - return yield_values_and_wrap_in_block(bb, singleton(r)); - } - return bind_last_instruction_and_wrap_in_block(bb, r); + if (!r) { + cancel_body(bb); + return node; } - cancel_body(bb); - return NULL; + if (!is_subtype(node->type, r->type)) { + r = gen_conversion(bb, get_unqualified_type(node->type), first(bind_instruction(bb, r))); + return yield_values_and_wrap_in_block(bb, singleton(r)); + } + return bind_last_instruction_and_wrap_in_block(bb, r); } static const Node* fold_prim_op(IrArena* arena, const Node* node) { APPLY_FOLD(fold_constant_math) APPLY_FOLD(fold_simplify_math) - APPLY_FOLD(fold_simplify_ptr_operand) PrimOp payload = node->payload.prim_op; switch (payload.op) { @@ -316,19 +331,25 @@ static const Node* fold_prim_op(IrArena* arena, const Node* node) { static const Node* fold_memory_poison(IrArena* arena, const Node* node) { switch (node->tag) { + case Load_TAG: { + if (node->payload.load.ptr->tag == Undef_TAG) + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + break; + } + case Store_TAG: { + if (node->payload.store.ptr->tag == Undef_TAG) + return quote_helper(arena, empty(arena)); + break; + } + case Lea_TAG: { + Lea payload = node->payload.lea; + if (payload.ptr->tag == Undef_TAG) + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + break; + } case PrimOp_TAG: { PrimOp payload = node->payload.prim_op; switch (payload.op) { - case store_op: { - if (first(payload.operands)->tag == Undef_TAG) - return quote_helper(arena, empty(arena)); - break; - } - case load_op: { - if (first(payload.operands)->tag == Undef_TAG) - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); - break; - } case reinterpret_op: case convert_op: { if (first(payload.operands)->tag == Undef_TAG) @@ -339,12 +360,6 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { } break; } - case Lea_TAG: { - Lea payload = node->payload.lea; - if (payload.ptr->tag == Undef_TAG) - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); - break; - } default: break; } return node; @@ -359,6 +374,7 @@ static bool is_unreachable_case(const Node* c) { const Node* fold_node(IrArena* arena, const Node* node) { const Node* const original_node = node; node = fold_memory_poison(arena, node); + node = fold_simplify_ptr_operand(node); switch (node->tag) { case PrimOp_TAG: node = fold_prim_op(arena, node); break; case Block_TAG: { diff --git a/src/shady/node.c b/src/shady/node.c index 6e45f716e..a034d4450 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -194,22 +194,22 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi assert(terminator->payload.yield.args.count == 1); return resolve_node_to_definition(first(terminator->payload.yield.args), config); } + case Load_TAG: { + if (config.enter_loads) { + const Node* source = node->payload.load.ptr; + const Node* result = resolve_ptr_to_value(source, config); + if (!result) + break; + node = result; + continue; + } + } case PrimOp_TAG: { switch (node->payload.prim_op.op) { case quote_op: { node = first(node->payload.prim_op.operands); continue; } - case load_op: { - if (config.enter_loads) { - const Node* source = first(node->payload.prim_op.operands); - const Node* result = resolve_ptr_to_value(source, config); - if (!result) - break; - node = result; - continue; - } - } case convert_op: case reinterpret_op: { if (config.allow_incompatible_types) { diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index aa397fe80..f36e7db67 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -131,11 +131,7 @@ static const Node* desugar_let_mut(Context* ctx, BodyBuilder* bb, const Node* no .operands = nodes(a, 0, NULL) }); const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.varz.name).nodes[0]; - const Node* store = prim_op(a, (PrimOp) { - .op = store_op, - .operands = nodes(a, 2, (const Node* []) {ptr, initial_values.nodes[0] }) - }); - bind_instruction_outputs_count(bb, store, 0, NULL); + bind_instruction_outputs_count(bb, store(a, (Store) { ptr, initial_values.nodes[0] }), 0, NULL); add_binding(ctx, true, oparam->payload.varz.name, ptr); log_string(DEBUGV, "Lowered mutable variable "); @@ -204,10 +200,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { // in case the node is an l-value, we load it const Node* lhs = get_node_address_safe(ctx, node); if (lhs) { - return prim_op(a, (PrimOp) { - .op = load_op, - .operands = singleton(lhs) - }); + return load(a, (Load) { lhs }); } switch (node->tag) { @@ -308,10 +301,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { const Node* target_ptr = get_node_address(ctx, node->payload.prim_op.operands.nodes[0]); assert(target_ptr); const Node* value = rewrite_node(&ctx->rewriter, node->payload.prim_op.operands.nodes[1]); - return prim_op(a, (PrimOp) { - .op = store_op, - .operands = nodes(a, 2, (const Node* []) {target_ptr, value }) - }); + return store(a, (Store) { target_ptr, value }); } else if (node->tag == PrimOp_TAG && node->payload.prim_op.op == subscript_op) { return prim_op(a, (PrimOp) { .op = extract_op, diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 9d9a24c63..85c371ccf 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -375,25 +375,6 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp assert(is_data_type(element_type)); goto rebuild; } - case load_op: { - assert(old_operands.count == 1); - assert(type_args.count <= 1); - new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); - assert(type_args.count == 0); - goto rebuild; - } - case store_op: { - assert(old_operands.count == 2); - assert(type_args.count <= 1); - new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); - assert(type_args.count == 0); - const Type* ptr_type = get_unqualified_type(new_operands[0]->type); - assert(ptr_type->tag == PtrType_TAG); - const Type* element_t = ptr_type->payload.ptr_type.pointed_type; - assert(element_t); - new_operands[1] = infer(ctx, old_operands.nodes[1], qualified_type_helper(element_t, false)); - goto rebuild; - } case alloca_op: { assert(type_args.count == 1); assert(old_operands.count == 0); @@ -588,6 +569,7 @@ static const Node* infer_block(Context* ctx, const Node* node, const Nodes* expe } static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes* expected_types) { + IrArena* a = ctx->rewriter.dst_arena; switch (is_instruction(node)) { case PrimOp_TAG: return infer_primop(ctx, node, expected_types); case Call_TAG: return infer_indirect_call(ctx, node, expected_types); @@ -607,7 +589,20 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes const Type* base_datatype = src_ptr; assert(base_datatype->tag == PtrType_TAG); - return lea(ctx->rewriter.dst_arena, (Lea) { ptr, offset, indices }); + return lea(a, (Lea) { ptr, offset, indices }); + } + case Instruction_Load_TAG: { + return load(a, (Load) { infer(ctx, node->payload.load.ptr, NULL) }); + } + case Instruction_Store_TAG: { + Store payload = node->payload.store; + const Node* ptr = infer(ctx, payload.ptr, NULL); + const Type* ptr_type = get_unqualified_type(ptr->type); + assert(ptr_type->tag == PtrType_TAG); + const Type* element_t = ptr_type->payload.ptr_type.pointed_type; + assert(element_t); + const Node* value = infer(ctx, payload.value, qualified_type_helper(element_t, false)); + return store(a, (Store) { ptr, value }); } default: error("TODO") case NotAnInstruction: error("not an instruction"); diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 905f7a240..c17fa15e4 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -170,7 +170,8 @@ static const Node* process(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; Module* m = ctx->rewriter.dst_module; size_t max_tag = sizeof(generic_ptr_tags) / sizeof(generic_ptr_tags[0]); @@ -186,6 +187,31 @@ static const Node* process(Context* ctx, const Node* old) { return size_t_literal(a, 0); break; } + case Load_TAG: { + const Node* old_ptr = old->payload.load.ptr; + const Type* old_ptr_t = old_ptr->type; + bool u = deconstruct_qualified_type(&old_ptr_t); + u &= is_addr_space_uniform(a, old_ptr_t->payload.ptr_type.address_space); + if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { + return call(a, (Call) { + .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, u, rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), + .args = singleton(rewrite_node(&ctx->rewriter, old_ptr)), + }); + } + break; + } + case Store_TAG: { + Store payload = old->payload.store; + const Type* old_ptr_t = payload.ptr->type; + deconstruct_qualified_type(&old_ptr_t); + if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { + return call(a, (Call) { + .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, StoreFn, false, rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), + .args = mk_nodes(a, rewrite_node(r, payload.ptr), rewrite_node(r, payload.value)), + }); + } + break; + } case PrimOp_TAG: { switch (old->payload.prim_op.op) { case convert_op: { @@ -215,29 +241,6 @@ static const Node* process(Context* ctx, const Node* old) { } break; } - case load_op: { - const Type* old_ptr_t = first(old->payload.prim_op.operands)->type; - bool u = deconstruct_qualified_type(&old_ptr_t); - u &= is_addr_space_uniform(a, old_ptr_t->payload.ptr_type.address_space); - if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { - return call(a, (Call) { - .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, u, rewrite_node(&ctx->rewriter, old_ptr_t->payload.ptr_type.pointed_type))), - .args = singleton(rewrite_node(&ctx->rewriter, first(old->payload.prim_op.operands))), - }); - } - break; - } - case store_op: { - const Type* old_ptr_t = first(old->payload.prim_op.operands)->type; - deconstruct_qualified_type(&old_ptr_t); - if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { - return call(a, (Call) { - .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, StoreFn, false, rewrite_node(&ctx->rewriter, old_ptr_t->payload.ptr_type.pointed_type))), - .args = rewrite_nodes(&ctx->rewriter, old->payload.prim_op.operands), - }); - } - break; - } default: break; } } diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index c21699ccd..dc0f4f88f 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -80,26 +80,36 @@ static const Node* process(Context* ctx, const Node* old) { return prim_op_helper(a, quote_op, empty(a), singleton(rewrite_node(r, osrc))); break; } - case load_op: - case store_op: { - const Node* optr = first(payload.operands); - const Type* optr_t = optr->type; - deconstruct_qualified_type(&optr_t); - assert(optr_t->tag == PtrType_TAG); - const Type* expected_type = rewrite_node(r, optr_t); - payload.operands = rewrite_nodes(r, payload.operands); - payload.type_arguments = rewrite_nodes(r, payload.type_arguments); - const Node* ptr = first(payload.operands); - const Type* actual_type = get_unqualified_type(ptr->type); - BodyBuilder* bb = begin_body(a); - if (expected_type != actual_type) - payload.operands = change_node_at_index(a, payload.operands, 0, guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type))); - return bind_last_instruction_and_wrap_in_block(bb, prim_op(a, payload)); - } default: break; } break; } + case Load_TAG: { + Load payload = old->payload.load; + const Type* optr_t = payload.ptr->type; + deconstruct_qualified_type(&optr_t); + assert(optr_t->tag == PtrType_TAG); + const Type* expected_type = rewrite_node(r, optr_t); + const Node* ptr = rewrite_node(r, payload.ptr); + const Type* actual_type = get_unqualified_type(ptr->type); + BodyBuilder* bb = begin_body(a); + if (expected_type != actual_type) + ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); + return bind_last_instruction_and_wrap_in_block(bb, load(a, (Load) { ptr })); + } + case Store_TAG: { + Store payload = old->payload.store; + const Type* optr_t = payload.ptr->type; + deconstruct_qualified_type(&optr_t); + assert(optr_t->tag == PtrType_TAG); + const Type* expected_type = rewrite_node(r, optr_t); + const Node* ptr = rewrite_node(r, payload.ptr); + const Type* actual_type = get_unqualified_type(ptr->type); + BodyBuilder* bb = begin_body(a); + if (expected_type != actual_type) + ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); + return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { ptr, rewrite_node(r, payload.value) })); + } case GlobalVariable_TAG: { AddressSpace as = old->payload.global_variable.address_space; if (get_arena_config(a)->address_spaces[as].physical) diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index c482d35c3..5f3dad566 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -297,34 +297,41 @@ static const Node* process_node(Context* ctx, const Node* old) { IrArena* a = ctx->rewriter.dst_arena; switch (old->tag) { + case Load_TAG: { + Load payload = old->payload.load; + const Type* ptr_type = payload.ptr->type; + bool uniform_ptr = deconstruct_qualified_type(&ptr_type); + assert(ptr_type->tag == PtrType_TAG); + if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) + break; + BodyBuilder* bb = begin_body(a); + const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); + const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); + const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, false, ptr_type->payload.ptr_type.address_space); + Nodes r = bind_instruction(bb, call(a, (Call) {.callee = fn_addr_helper(a, fn), .args = singleton(pointer_as_offset)})); + return yield_values_and_wrap_in_block(bb, r); + } + case Store_TAG: { + Store payload = old->payload.store; + const Type* ptr_type = payload.ptr->type; + bool uniform_ptr = deconstruct_qualified_type(&ptr_type); + assert(ptr_type->tag == PtrType_TAG); + if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) + break; + BodyBuilder* bb = begin_body(a); + + const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); + const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); + const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, true, ptr_type->payload.ptr_type.address_space); + + const Node* value = rewrite_node(&ctx->rewriter, payload.value); + bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = mk_nodes(a, pointer_as_offset, value) })); + return yield_values_and_wrap_in_block(bb, empty(a)); + } case PrimOp_TAG: { const PrimOp* oprim_op = &old->payload.prim_op; switch (oprim_op->op) { case alloca_op: error("This needs to be lowered (see setup_stack_frames.c)") - // lowering for either kind of memory accesses is similar - case load_op: - case store_op: { - const Node* old_ptr = oprim_op->operands.nodes[0]; - const Type* ptr_type = old_ptr->type; - bool uniform_ptr = deconstruct_qualified_type(&ptr_type); - assert(ptr_type->tag == PtrType_TAG); - if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) - break; - BodyBuilder* bb = begin_body(a); - - const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); - const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, old_ptr); - const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, oprim_op->op == store_op, ptr_type->payload.ptr_type.address_space); - - if (oprim_op->op == load_op) { - Nodes r = bind_instruction(bb, call(a, (Call) {.callee = fn_addr_helper(a, fn), .args = singleton(pointer_as_offset)})); - return yield_values_and_wrap_in_block(bb, r); - } else { - const Node* value = rewrite_node(&ctx->rewriter, oprim_op->operands.nodes[1]); - bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = mk_nodes(a, pointer_as_offset, value) })); - return yield_values_and_wrap_in_block(bb, empty(a)); - } - } default: break; } break; @@ -433,13 +440,12 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, BodyBuilder* bb) { IrArena* oa = ctx->rewriter.src_arena; - IrArena* a = ctx->rewriter.dst_arena; for (size_t i = 0; i < collected.count; i++) { const Node* old_decl = collected.nodes[i]; assert(old_decl->tag == GlobalVariable_TAG); const Node* old_init = old_decl->payload.global_variable.init; if (old_init) { - const Node* old_store = prim_op_helper(oa, store_op, empty(oa), mk_nodes(oa, ref_decl_helper(oa, old_decl), old_init)); + const Node* old_store = store(oa, (Store) { ref_decl_helper(oa, old_decl), old_init }); bind_instruction(bb, rewrite_node(&ctx->rewriter, old_store)); } } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 9981cf100..c49e85010 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -68,7 +68,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { if (push) gen_store(bb, addr, value_param); else - popped_value = gen_primop_ce(bb, load_op, 1, (const Node* []) { addr }); + popped_value = gen_load(bb, addr); if (push) // for push, we increase the stack size after the store stack_size = gen_primop_ce(bb, add_op, 2, (const Node* []) { stack_size, element_size}); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 358c90a50..be82d089b 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -146,22 +146,16 @@ static const Node* process(Context* ctx, const Node* node) { } return recreate_node_identity(&ctx2.rewriter, node); } - case PrimOp_TAG: { - switch (node->payload.prim_op.op) { - case load_op: { - const Node* ptr = first(node->payload.prim_op.operands); - if (ptr->tag == RefDecl_TAG) - ptr = ptr->payload.ref_decl.decl; - if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { - BodyBuilder* bb = begin_body(a); - const Node* loaded = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); - const Node* uniformized = first(gen_primop(bb, subgroup_broadcast_first_op, empty(a), singleton(loaded))); - return yield_values_and_wrap_in_block(bb, singleton(uniformized)); - } - } - default: break; + case Load_TAG: { + const Node* ptr = node->payload.load.ptr; + if (ptr->tag == RefDecl_TAG) + ptr = ptr->payload.ref_decl.decl; + if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { + BodyBuilder* bb = begin_body(a); + const Node* loaded = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); + const Node* uniformized = first(gen_primop(bb, subgroup_broadcast_first_op, empty(a), singleton(loaded))); + return yield_values_and_wrap_in_block(bb, singleton(uniformized)); } - break; } default: break; } diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 8b7318790..a0923c5eb 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -77,21 +77,16 @@ static const Node* process(Context* ctx, const Node* node) { ctx->builtins[b] = ndecl; return ndecl; } + break; } - case PrimOp_TAG: { - Op op = node->payload.prim_op.op; - switch (op) { - case load_op: { - const Type* req_cast = get_req_cast(ctx, first(node->payload.prim_op.operands)); - if (req_cast) { - assert(is_data_type(req_cast)); - BodyBuilder* bb = begin_body(a); - const Node* r = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); - const Node* r2 = first(gen_primop(bb, reinterpret_op, singleton(req_cast), singleton(r))); - return yield_values_and_wrap_in_block(bb, singleton(r2)); - } - } - default: break; + case Load_TAG: { + const Type* req_cast = get_req_cast(ctx, node->payload.load.ptr); + if (req_cast) { + assert(is_data_type(req_cast)); + BodyBuilder* bb = begin_body(a); + const Node* r = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); + const Node* r2 = first(gen_primop(bb, reinterpret_op, singleton(req_cast), singleton(r))); + return yield_values_and_wrap_in_block(bb, singleton(r2)); } break; } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index c89c92c3c..54b2aa69c 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -63,23 +63,21 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca debugv_print(".\n"); visit_ptr_uses(vars.nodes[i], slice_type, k, map); }*/ + } else if (use->user->tag == Load_TAG) { + //if (get_pointer_type_element(ptr_type) != slice_type) + // k->reinterpreted = true; + k->read_from = true; + continue; // loads don't leak the address. + } else if (use->user->tag == Store_TAG) { + //if (get_pointer_type_element(ptr_type) != slice_type) + // k->reinterpreted = true; + // stores leak the value if it's stored + if (ptr_value == use->user->payload.store.value) + k->leaks = true; + continue; } else if (use->user->tag == PrimOp_TAG) { PrimOp payload = use->user->payload.prim_op; switch (payload.op) { - case load_op: { - //if (get_pointer_type_element(ptr_type) != slice_type) - // k->reinterpreted = true; - k->read_from = true; - continue; // loads don't leak the address. - } - case store_op: { - //if (get_pointer_type_element(ptr_type) != slice_type) - // k->reinterpreted = true; - // stores leak the value if it's stored - if (ptr_value == payload.operands.nodes[1]) - k->leaks = true; - continue; - } case reinterpret_op: { k->non_logical_use = true; continue; @@ -207,6 +205,40 @@ static const Node* process(Context* ctx, const Node* old) { // const Node* tail = case_(r->dst_arena, empty(a), nbody); return let(a, ninstruction, nvars, rewrite_node(r, otail)); } + case Load_TAG: { + Load payload = old->payload.load; + PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); + if (k.src_alloca) { + const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.ptr->type))); + if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { + if (k.src_alloca->bound == rewrite_node(r, payload.ptr)) + break; + ctx->todo |= true; + BodyBuilder* bb = begin_body(a); + const Node* data = gen_load(bb, k.src_alloca->bound); + data = gen_reinterpret_cast(bb, access_type, data); + return yield_values_and_wrap_in_block(bb, singleton(data)); + } + } + break; + } + case Store_TAG: { + Store payload = old->payload.store; + PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); + if (k.src_alloca) { + const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.ptr->type))); + if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { + if (k.src_alloca->bound == rewrite_node(r, payload.ptr)) + break; + ctx->todo |= true; + BodyBuilder* bb = begin_body(a); + const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.value)); + gen_store(bb, k.src_alloca->bound, data); + return yield_values_and_wrap_in_block(bb, empty(a)); + } + } + break; + } case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; switch (payload.op) { @@ -232,38 +264,6 @@ static const Node* process(Context* ctx, const Node* old) { } break; } - case load_op: { - PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, first(payload.operands)); - if (k.src_alloca) { - const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.operands.nodes[0]->type))); - if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { - if (k.src_alloca->bound == rewrite_node(r, first(payload.operands))) - break; - ctx->todo |= true; - BodyBuilder* bb = begin_body(a); - const Node* data = gen_load(bb, k.src_alloca->bound); - data = gen_reinterpret_cast(bb, access_type, data); - return yield_values_and_wrap_in_block(bb, singleton(data)); - } - } - break; - } - case store_op: { - PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, first(payload.operands)); - if (k.src_alloca) { - const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.operands.nodes[0]->type))); - if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { - if (k.src_alloca->bound == rewrite_node(r, first(payload.operands))) - break; - ctx->todo |= true; - BodyBuilder* bb = begin_body(a); - const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.operands.nodes[1])); - gen_store(bb, k.src_alloca->bound, data); - return yield_values_and_wrap_in_block(bb, empty(a)); - } - } - break; - } default: break; } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 9281031ae..411892dfe 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -331,6 +331,29 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No mark_values_as_escaping(ctx, kb, oinstruction->payload.call.args); wipe_all_leaked_pointers(kb); break; + case Load_TAG: { + const Node* optr = oinstruction->payload.load.ptr; + const Node* known_value = find_or_request_known_ptr_value(ctx, kb, optr); + if (known_value) + return known_value; + // const Node* other_ptr = get_known_address(&ctx->rewriter, ok); + // if (other_ptr && optr != other_ptr) { + // return prim_op_helper(a, load_op, empty(a), singleton(other_ptr)); + // } + return load(a, (Load) { rewrite_node(r, optr) }); + } + case Store_TAG: { + Store payload = oinstruction->payload.store; + PtrKnowledge* k = find_or_create_ptr_knowledge_for_updating(ctx, kb, payload.ptr, true); + if (k) { + k->state = PSKnownValue; + k->ptr_value = rewrite_node(r, payload.value); + } + mark_value_as_escaping(ctx, kb, payload.value); + wipe_all_leaked_pointers(kb); + // let's take care of dead stores another time + return recreate_node_identity(r, oinstruction); + } case Instruction_PrimOp_TAG: { PrimOp payload = oinstruction->payload.prim_op; switch (payload.op) { @@ -350,32 +373,9 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No // k->ptr_value = undef(a, (Undef) { .type = rewrite_node(r, first(payload.type_arguments)) }); return recreate_node_identity(r, oinstruction); } - case load_op: { - const Node* optr = first(payload.operands); - const Node* known_value = find_or_request_known_ptr_value(ctx, kb, optr); - if (known_value) - return known_value; - // const Node* other_ptr = get_known_address(&ctx->rewriter, ok); - // if (other_ptr && optr != other_ptr) { - // return prim_op_helper(a, load_op, empty(a), singleton(other_ptr)); - // } - return prim_op_helper(a, load_op, empty(a), singleton(rewrite_node(r, optr))); - } // case memcpy_op: { // const Node* optr = first(payload.operands); // } - case store_op: { - const Node* optr = first(payload.operands); - PtrKnowledge* k = find_or_create_ptr_knowledge_for_updating(ctx, kb, optr, true); - if (k) { - k->state = PSKnownValue; - k->ptr_value = rewrite_node(r, payload.operands.nodes[1]); - } - mark_value_as_escaping(ctx, kb, payload.operands.nodes[1]); - wipe_all_leaked_pointers(kb); - // let's take care of dead stores another time - return recreate_node_identity(r, oinstruction); - } case reinterpret_op: { const Node* rewritten = recreate_node_identity(r, oinstruction); // if we have knowledge on a particular ptr, the same knowledge propagates if we bitcast it! @@ -419,6 +419,20 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No return recreate_node_identity(r, oinstruction); } + case Instruction_Lea_TAG: { + mark_value_as_escaping(ctx, kb, oinstruction->payload.lea.ptr); + break; + } + case Instruction_CopyBytes_TAG: { + mark_value_as_escaping(ctx, kb, oinstruction->payload.copy_bytes.src); + mark_value_as_escaping(ctx, kb, oinstruction->payload.copy_bytes.dst); + break; + } + case Instruction_FillBytes_TAG: { + mark_value_as_escaping(ctx, kb, oinstruction->payload.fill_bytes.src); + mark_value_as_escaping(ctx, kb, oinstruction->payload.fill_bytes.dst); + break; + } case Instruction_Control_TAG: break; case Instruction_Block_TAG: diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index ee1b5b665..e9b7085cc 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -1,6 +1,7 @@ #include "pass.h" #include "../type.h" +#include "../transform/ir_gen_helpers.h" #include #include @@ -253,18 +254,18 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad control_ctx.control_stack = &control_entry; // Set the depth for threads entering the control body - bind_instruction(bb_outer, prim_op(a, (PrimOp) { .op = store_op, .operands = mk_nodes(a, ctx->level_ptr, int32_literal(a, control_entry.depth)) })); + gen_store(bb_outer, ctx->level_ptr, int32_literal(a, control_entry.depth)); // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() BodyBuilder* bb2 = begin_body(a); LARRAY(const Node*, phi_values, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { - phi_values[i] = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = load_op, .operands = singleton(phis[i]) }))); + phi_values[i] = gen_load(bb2, phis[i]); register_processed(&ctx->rewriter, ovars.nodes[i], phi_values[i]); } // Wrap the tail in a guarded if, to handle 'far' joins - const Node* level_value = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = load_op, .operands = singleton(ctx->level_ptr) }))); + const Node* level_value = gen_load(bb2, ctx->level_ptr); const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); const Node* true_body = structure(ctx, old_tail, yield(a, (Yield) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); @@ -334,11 +335,11 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad longjmp(ctx->bail, 1); BodyBuilder* bb = begin_body(a); - bind_instruction(bb, prim_op(a, (PrimOp) { .op = store_op, .operands = mk_nodes(a, ctx->level_ptr, int32_literal(a, control->depth - 1)) })); + gen_store(bb, ctx->level_ptr, int32_literal(a, control->depth - 1)); Nodes args = rewrite_nodes(&ctx->rewriter, body->payload.join.args); for (size_t i = 0; i < args.count; i++) { - bind_instruction(bb, prim_op(a, (PrimOp) { .op = store_op, .operands = mk_nodes(a, control->phis[i], args.nodes[i]) })); + gen_store(bb, control->phis[i], args.nodes[i]); } return finish_body(bb, exit_ladder); @@ -396,7 +397,7 @@ static const Node* process(Context* ctx, const Node* node) { TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); const Node* ptr = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = alloca_logical_op, .type_arguments = singleton(int32_type(a)) }), (String []) {"cf_depth" })); - bind_instruction(bb, prim_op(a, (PrimOp) { .op = store_op, .operands = mk_nodes(a, ptr, int32_literal(a, 0)) })); + gen_store(bb, ptr, int32_literal(a, 0)); ctx2.level_ptr = ptr; ctx2.fn = new; struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); diff --git a/src/shady/print.c b/src/shady/print.c index 8267c7660..cc90cff63 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1049,7 +1049,9 @@ void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) } void print_node_operand(Printer* p, const Node* n, String name, NodeClass op_class, const Node* op, PrintConfig config) { - print(p, " '%s': %%%zu", name, (size_t) op); + //print(p, " '%s': %%%d", name, op->id); + print(p, " '%s': ", name); + print_node(p, op, config); } void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass op_class, Nodes ops, PrintConfig config) { @@ -1063,7 +1065,7 @@ void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass o } void print_node_operand_const_Node_(Printer* p, const Node* n, String name, const Node* op, PrintConfig config) { - print(p, " '%s': %%%zu", name, (size_t) op); + print(p, " '%s': %%%d", name, op->id); } void print_node_operand_AddressSpace(Printer* p, const Node* n, String name, AddressSpace as, PrintConfig config) { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 57185e5b3..2b62d3515 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -83,11 +83,11 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { } const Node* gen_load(BodyBuilder* bb, const Node* ptr) { - return gen_primop_ce(bb, load_op, 1, (const Node* []) {ptr }); + return first(bind_instruction(bb, load(bb->arena, (Load) { ptr }))); } -void gen_store(BodyBuilder* instructions, const Node* ptr, const Node* value) { - gen_primop_c(instructions, store_op, 2, (const Node* []) { ptr, value }); +void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { + bind_instruction(bb, store(bb->arena, (Store) {ptr, value })); } const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { @@ -141,8 +141,8 @@ const Node* gen_builtin_load(Module* m, BodyBuilder* bb, Builtin b) { bool is_builtin_load_op(const Node* n, Builtin* out) { assert(is_instruction(n)); - if (n->tag == PrimOp_TAG && n->payload.prim_op.op == load_op) { - const Node* src = first(n->payload.prim_op.operands); + if (n->tag == Load_TAG) { + const Node* src = n->payload.load.ptr; if (src->tag == RefDecl_TAG) src = src->payload.ref_decl.decl; if (src->tag == GlobalVariable_TAG) { diff --git a/src/shady/type.c b/src/shady/type.c index 77394caab..6f08e7873 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -722,44 +722,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(src_type->tag == Float_TAG || src_type->tag == Int_TAG && src_type->payload.int_type.is_signed); return qualified_type_helper(maybe_packed_type_helper(src_type, width), uniform); } - case load_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 1); - - const Node* ptr = first(prim_op.operands); - const Node* ptr_type = ptr->type; - bool ptr_uniform = deconstruct_qualified_type(&ptr_type); - size_t width = deconstruct_maybe_packed_type(&ptr_type); - - assert(ptr_type->tag == PtrType_TAG); - const PtrType* node_ptr_type_ = &ptr_type->payload.ptr_type; - const Type* elem_type = node_ptr_type_->pointed_type; - elem_type = maybe_packed_type_helper(elem_type, width); - return qualified_type_helper(elem_type, ptr_uniform && is_addr_space_uniform(arena, ptr_type->payload.ptr_type.address_space)); - } - case store_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 2); - - const Node* ptr = first(prim_op.operands); - const Node* ptr_type = ptr->type; - bool ptr_uniform = deconstruct_qualified_type(&ptr_type); - size_t width = deconstruct_maybe_packed_type(&ptr_type); - assert(ptr_type->tag == PtrType_TAG); - const PtrType* ptr_type_payload = &ptr_type->payload.ptr_type; - const Type* elem_type = ptr_type_payload->pointed_type; - assert(elem_type); - elem_type = maybe_packed_type_helper(elem_type, width); - // we don't enforce uniform stores - but we care about storing the right thing :) - const Type* val_expected_type = qualified_type(arena, (QualifiedType) { - .is_uniform = !arena->config.is_simt, - .type = elem_type - }); - - const Node* val = prim_op.operands.nodes[1]; - assert(is_subtype(val_expected_type, val->type)); - return empty_multiple_return_type(arena); - } case alloca_logical_op: as = AsFunction; goto alloca_case; case alloca_op: as = AsPrivate; goto alloca_case; alloca_case: { diff --git a/test/generic_ptrs2.slim b/test/generic_ptrs2.slim index 0b2a1c62c..cb01c8beb 100644 --- a/test/generic_ptrs2.slim +++ b/test/generic_ptrs2.slim @@ -1,4 +1,4 @@ @Exported fn foo i32(varying ptr generic i32 x) { - return (load(x)); + return (*x); } \ No newline at end of file diff --git a/test/memory1.slim b/test/memory1.slim index b6f27ce4c..ea5cfb49c 100644 --- a/test/memory1.slim +++ b/test/memory1.slim @@ -9,6 +9,6 @@ fn read_from_extern i32() { @Exported fn read_from_global_ptr i32(uniform ptr global i32 global_ptr) { - val loaded = load(global_ptr); + val loaded = *global_ptr; return(loaded); } diff --git a/test/memory2.slim b/test/memory2.slim index 814b4a008..323b45925 100644 --- a/test/memory2.slim +++ b/test/memory2.slim @@ -1,7 +1,7 @@ @Exported fn alloca_load_store i32() { val a = alloca[i32](); - store(a, 9); - val i = load(a); + *a = 9; + val i = *a; return(i); } diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 4aa787ffc..7b04a40e2 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -14,20 +14,27 @@ static bool expect_memstuff = false; static bool found_memstuff = false; static void search_for_memstuff(Visitor* v, const Node* n) { - if (n->tag == PrimOp_TAG) { - PrimOp payload = n->payload.prim_op; - switch (payload.op) { - case alloca_op: - case alloca_logical_op: - case load_op: - case store_op: { - found_memstuff = true; - break; + switch (n->tag) { + case Load_TAG: + case Store_TAG: + case CopyBytes_TAG: + case FillBytes_TAG: { + found_memstuff = true; + break; + } + case PrimOp_TAG: { + PrimOp payload = n->payload.prim_op; + switch (payload.op) { + case alloca_op: + case alloca_logical_op: { + found_memstuff = true; + break; + } + default: break; } - default: break; } - } else if (n->tag == CopyBytes_TAG || n->tag == FillBytes_TAG) - found_memstuff = true; + default: break; + } visit_node_operands(v, NcDeclaration, n); } From 34ea12a3e0bb12c2b97d4d8e8dd3c451d858cba9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Jul 2024 12:14:06 +0200 Subject: [PATCH 347/693] migrated alloc primops to nodes --- include/shady/ir.h | 2 +- include/shady/primops.json | 24 +++--- src/backend/c/emit_c_instructions.c | 27 +++---- src/backend/spirv/emit_spv_instructions.c | 20 ++--- src/frontend/llvm/l2s_instr.c | 3 +- src/frontend/spirv/s2s.c | 6 +- src/shady/analysis/cfg.c | 2 + src/shady/passes/bind.c | 6 +- src/shady/passes/cleanup.c | 12 ++- src/shady/passes/infer.c | 14 ++-- src/shady/passes/lower_alloca.c | 31 ++++---- src/shady/passes/lower_physical_ptrs.c | 9 +-- src/shady/passes/lower_switch_btree.c | 2 +- src/shady/passes/opt_demote_alloca.c | 83 ++++++++++++--------- src/shady/passes/opt_mem2reg.c | 37 +++++---- src/shady/passes/opt_restructure.c | 5 +- src/shady/passes/reconvergence_heuristics.c | 6 +- src/shady/passes/simt2d.c | 29 +++---- src/shady/transform/ir_gen_helpers.c | 8 ++ src/shady/transform/ir_gen_helpers.h | 3 + src/shady/type.c | 40 ++++++---- test/opt/opt_oracle.c | 15 +--- 22 files changed, 198 insertions(+), 186 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index ba22ae075..3ee3b09ba 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -139,7 +139,7 @@ inline static bool is_nominal(const Node* node) { NodeTag tag = node->tag; if (node->tag == PrimOp_TAG && has_primop_got_side_effects(node->payload.prim_op.op)) return true; - return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Param_TAG || tag == Variablez_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG; + return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Param_TAG || tag == Variablez_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG || tag == StackAlloc_TAG || tag == LocalAlloc_TAG; } inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } diff --git a/include/shady/primops.json b/include/shady/primops.json index 47c9774a7..4f8455666 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -209,16 +209,6 @@ "class": "stack", "side-effects": true }, - { - "name": "alloca", - "class": "memory", - "side-effects": true - }, - { - "name": "alloca_logical", - "class": "memory", - "side-effects": true - }, { "name": "size_of", "class": "memory_layout" @@ -327,6 +317,20 @@ } ], "nodes": [ + { + "name": "StackAlloc", + "class": "instruction", + "ops": [ + { "name": "type", "class": "type" } + ] + }, + { + "name": "LocalAlloc", + "class": "instruction", + "ops": [ + { "name": "type", "class": "type" } + ] + }, { "name": "Load", "class": "instruction", diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index b8706a18c..0e561c26e 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -316,19 +316,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct term = term_from_cvalue(format_string_arena(arena->arena, "(%s %s %s)", src, prim_op->op == lshift_op ? "<<" : ">>", c_offset)); break; } - case alloca_op: - case alloca_logical_op: { - assert(outputs.count == 1); - String variable_name = unique_name(emitter->arena, "alloca"); - CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; - emit_variable_declaration(emitter, p, first(prim_op->type_arguments), variable_name, true, NULL); - outputs.results[0] = variable; - if (emitter->config.dialect == CDialect_ISPC) { - outputs.results[0] = ispc_varying_ptr_helper(emitter, p, get_unqualified_type(node->type), variable); - } - outputs.binding[0] = NoBinding; - return; - } case size_of_op: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); break; @@ -844,6 +831,18 @@ static void emit_lea(Emitter* emitter, Printer* p, Lea lea, InstructionOutputs o return; } +static void emit_alloca(Emitter* emitter, Printer* p, const Type* type, InstructionOutputs outputs) { + assert(outputs.count == 1); + String variable_name = unique_name(emitter->arena, "alloca"); + CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; + emit_variable_declaration(emitter, p, type, variable_name, true, NULL); + outputs.results[0] = variable; + if (emitter->config.dialect == CDialect_ISPC) { + outputs.results[0] = ispc_varying_ptr_helper(emitter, p, type, variable); + } + outputs.binding[0] = NoBinding; +} + void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, InstructionOutputs outputs) { assert(is_instruction(instruction)); IrArena* a = emitter->arena; @@ -859,6 +858,8 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_Control_TAG: error("TODO") case Instruction_Block_TAG: error("Should be eliminated by the compiler") case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; + case Instruction_StackAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.stack_alloc.type, outputs); + case Instruction_LocalAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.local_alloc.type, outputs); case Instruction_Load_TAG: { Load payload = instruction->payload.load; CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, payload.ptr)); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 730e32f43..542758050 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -330,16 +330,6 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui results[0] = spvb_vecshuffle(bb_builder, emit_type(emitter, result_t), a, b, args.count - 2, indices); return; } - case alloca_logical_op: { - const Type* elem_type = first(type_arguments); - SpvId result = spvb_local_variable(fn_builder, emit_type(emitter, ptr_type(emitter->arena, (PtrType) { - .address_space = AsFunction, - .pointed_type = elem_type - })), SpvStorageClassFunction); - assert(results_count == 1); - results[0] = result; - return; - } case select_op: { SpvId cond = emit_value(emitter, bb_builder, first(args)); SpvId truv = emit_value(emitter, bb_builder, args.nodes[1]); @@ -581,6 +571,7 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_FillBytes_TAG: case Instruction_LetMut_TAG: case Instruction_Control_TAG: + case Instruction_StackAlloc_TAG: case Instruction_Block_TAG: error("Should be lowered elsewhere") case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; case PrimOp_TAG: emit_primop(emitter, fn_builder, *bb_builder, instruction, results_count, results); break; @@ -588,6 +579,15 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Match_TAG: emit_match(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.match_instr, results_count, results); break; case Loop_TAG: emit_loop(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.loop_instr, results_count, results); break; case Comment_TAG: break; + case Instruction_LocalAlloc_TAG: { + SpvId result = spvb_local_variable(fn_builder, emit_type(emitter, ptr_type(emitter->arena, (PtrType) { + .address_space = AsFunction, + .pointed_type = instruction->payload.local_alloc.type + })), SpvStorageClassFunction); + assert(results_count == 1); + results[0] = result; + return; + } case Instruction_Load_TAG: { Load payload = instruction->payload.load; const Type* ptr_type = payload.ptr->type; diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 5f898ae1d..936454c1e 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -6,6 +6,7 @@ #include "list.h" #include "../shady/type.h" +#include "../shady/transform/ir_gen_helpers.h" #include "llvm-c/DebugInfo.h" @@ -256,7 +257,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, assert(t->tag == PtrType_TAG); const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivate }); - r = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, alloca_op, singleton(allocated_t), empty(a)), singleton(allocated_ptr_t), NULL)); + r = first(bind_instruction_explicit_result_types(b, stack_alloc(a, (StackAlloc) { allocated_t }), singleton(allocated_ptr_t), NULL)); if (UNTYPED_POINTERS) { const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivate }); r = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), singleton(untyped_ptr_t), NULL)); diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index e80c3f56d..ef3eb1408 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -742,11 +742,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { assert(is_data_type(contents_t)); if (parser->fun) { - const Node* ptr = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = alloca_op, - .type_arguments = singleton(contents_t), - .operands = empty(parser->arena) - }), 1, NULL)); + const Node* ptr = first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { contents_t }), 1, NULL)); parser->defs[result].type = Value; parser->defs[result].node = ptr; diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 397cead70..d69ceb010 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -149,6 +149,8 @@ static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node case Instruction_Lea_TAG: case Instruction_CopyBytes_TAG: case Instruction_FillBytes_TAG: + case Instruction_StackAlloc_TAG: + case Instruction_LocalAlloc_TAG: add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); return; case Instruction_Block_TAG: diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index f36e7db67..ba3de42a6 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -125,11 +125,7 @@ static const Node* desugar_let_mut(Context* ctx, BodyBuilder* bb, const Node* no const Node* oparam = old_params.nodes[i]; const Type* type_annotation = node->payload.let_mut.types.nodes[i]; assert(type_annotation); - const Node* alloca = prim_op(a, (PrimOp) { - .op = alloca_op, - .type_arguments = nodes(a, 1, (const Node* []){rewrite_node(&ctx->rewriter, type_annotation) }), - .operands = nodes(a, 0, NULL) - }); + const Node* alloca = stack_alloc(a, (StackAlloc) { rewrite_node(&ctx->rewriter, type_annotation) }); const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.varz.name).nodes[0]; bind_instruction_outputs_count(bb, store(a, (Store) { ptr, initial_values.nodes[0] }), 0, NULL); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index e3be64669..30cc0be3b 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -77,6 +77,13 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* } } +static bool has_side_effects(const Node* instr) { + bool side_effects = true; + if (instr->tag == PrimOp_TAG) + side_effects = has_primop_got_side_effects(instr->payload.prim_op.op); + return side_effects; +} + const Node* process(Context* ctx, const Node* old) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; @@ -91,9 +98,6 @@ const Node* process(Context* ctx, const Node* old) { switch (old->tag) { case Let_TAG: { Let payload = old->payload.let; - bool side_effects = true; - if (payload.instruction->tag == PrimOp_TAG) - side_effects = has_primop_got_side_effects(payload.instruction->payload.prim_op.op); bool consumed = false; Nodes vars = payload.variables; for (size_t i = 0; i < vars.count; i++) { @@ -108,7 +112,7 @@ const Node* process(Context* ctx, const Node* old) { if (consumed) break; } - if (!consumed && !side_effects && ctx->rewriter.dst_arena) { + if (!consumed && !has_side_effects(payload.instruction) && ctx->rewriter.dst_arena) { debugvv_print("Cleanup: found an unused instruction: "); log_node(DEBUGVV, payload.instruction); debugvv_print("\n"); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 85c371ccf..555590b53 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -375,14 +375,6 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp assert(is_data_type(element_type)); goto rebuild; } - case alloca_op: { - assert(type_args.count == 1); - assert(old_operands.count == 0); - const Type* element_type = type_args.nodes[0]; - assert(is_type(element_type)); - assert(is_data_type(element_type)); - goto rebuild; - } case reinterpret_op: case convert_op: { new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); @@ -604,6 +596,12 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes const Node* value = infer(ctx, payload.value, qualified_type_helper(element_t, false)); return store(a, (Store) { ptr, value }); } + case Instruction_StackAlloc_TAG: { + const Type* element_type = node->payload.stack_alloc.type; + assert(is_type(element_type)); + assert(is_data_type(element_type)); + return stack_alloc(a, (StackAlloc) { .type = infer_type(ctx, element_type) }); + } default: error("TODO") case NotAnInstruction: error("not an instruction"); } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 19a62237f..7bfc9f6bf 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -49,24 +49,21 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { return; IrArena* a = vctx->context->rewriter.dst_arena; - AddressSpace as; - if (node->tag == PrimOp_TAG) { - switch (node->payload.prim_op.op) { - case alloca_op: as = AsPrivate; break; - default: goto not_alloca; - } - - const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.prim_op.type_arguments.nodes[0]); - assert(is_data_type(element_type)); - const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, singleton(type_decl_ref_helper(a, vctx->nom_t)), singleton(int32_literal(a, entries_count_list(vctx->members)))); - append_list(const Type*, vctx->members, element_type); + switch (node->tag) { + case StackAlloc_TAG: { + const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); + assert(is_data_type(element_type)); + const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, singleton(type_decl_ref_helper(a, vctx->nom_t)), singleton(int32_literal(a, entries_count_list(vctx->members)))); + append_list(const Type*, vctx->members, element_type); - StackSlot slot = { vctx->num_slots, slot_offset, element_type, as }; - insert_dict(const Node*, StackSlot, vctx->prepared_offsets, node, slot); + StackSlot slot = { vctx->num_slots, slot_offset, element_type, AsPrivate }; + insert_dict(const Node*, StackSlot, vctx->prepared_offsets, node, slot); - vctx->num_slots++; + vctx->num_slots++; - return; + return; + } + default: break; } not_alloca: @@ -131,8 +128,8 @@ static const Node* process(Context* ctx, const Node* node) { destroy_dict(ctx2.prepared_offsets); return fun; } - case PrimOp_TAG: { - if (!ctx->disable_lowering && node->payload.prim_op.op == alloca_op) { + case StackAlloc_TAG: { + if (!ctx->disable_lowering) { StackSlot* found_slot = find_value_dict(const Node*, StackSlot, ctx->prepared_offsets, node); if (!found_slot) { error_print("lower_alloca: failed to find a stack offset for "); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 5f3dad566..2835cb1ee 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -328,14 +328,7 @@ static const Node* process_node(Context* ctx, const Node* old) { bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = mk_nodes(a, pointer_as_offset, value) })); return yield_values_and_wrap_in_block(bb, empty(a)); } - case PrimOp_TAG: { - const PrimOp* oprim_op = &old->payload.prim_op; - switch (oprim_op->op) { - case alloca_op: error("This needs to be lowered (see setup_stack_frames.c)") - default: break; - } - break; - } + case StackAlloc_TAG: error("This needs to be lowered (see setup_stack_frames.c)") case PtrType_TAG: { if (!old->payload.ptr_type.is_reference && is_as_emulated(ctx, old->payload.ptr_type.address_space)) return int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 90413136d..938597c8d 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -157,7 +157,7 @@ static const Node* process(Context* ctx, const Node* node) { } BodyBuilder* bb = begin_body(a); - const Node* run_default_case = gen_primop_e(bb, alloca_logical_op, singleton(bool_type(a)), empty(a)); + const Node* run_default_case = gen_stack_alloc(bb, bool_type(a)); gen_store(bb, run_default_case, false_lit(a)); Context ctx2 = *ctx; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 54b2aa69c..fd436584b 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -136,23 +136,26 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { assert(is_value(ptr)); if (ptr->tag == Variablez_TAG && ctx->uses) { const Node* instr = get_var_def(ptr->payload.varz); - if (instr->tag == PrimOp_TAG) { - PrimOp payload = instr->payload.prim_op; - switch (payload.op) { - case alloca_logical_op: - case alloca_op: { - k.src_alloca = *find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, instr); - return k; - } - case convert_op: - case reinterpret_op: { - ptr = first(payload.operands); - continue; + switch (instr->tag) { + case StackAlloc_TAG: + case LocalAlloc_TAG: { + k.src_alloca = *find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, instr); + return k; + } + case PrimOp_TAG: { + PrimOp payload = instr->payload.prim_op; + switch (payload.op) { + case convert_op: + case reinterpret_op: { + ptr = first(payload.operands); + continue; + } + // TODO: lea and co + default: + break; } - // TODO: lea and co - default: - break; } + default: break; } } @@ -161,6 +164,31 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { return k; } +static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_type) { + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + + AllocaInfo* k = arena_alloc(ctx->arena, sizeof(AllocaInfo)); + *k = (AllocaInfo) { .type = rewrite_node(r, old_type) }; + assert(ctx->uses); + visit_ptr_uses(old, old_type, k, ctx->uses); + insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, old, k); + debugv_print("demote_alloca: uses analysis results for "); + log_node(DEBUGV, old); + debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); + if (!k->leaks) { + if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { + ctx->todo |= true; + return quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}))); + } + if (!k->non_logical_use && get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { + ctx->todo |= true; + return local_alloc(a, (LocalAlloc) {rewrite_node(r, old_type )}); + } + } + return recreate_node_identity(r, old); +} + static const Node* process(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; @@ -242,33 +270,14 @@ static const Node* process(Context* ctx, const Node* old) { case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; switch (payload.op) { - case alloca_op: - case alloca_logical_op: { - AllocaInfo* k = arena_alloc(ctx->arena, sizeof(AllocaInfo)); - *k = (AllocaInfo) { .type = rewrite_node(r, first(payload.type_arguments)) }; - assert(ctx->uses); - visit_ptr_uses(old, first(payload.type_arguments), k, ctx->uses); - insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, old, k); - debugv_print("demote_alloca: uses analysis results for "); - log_node(DEBUGV, old); - debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); - if (!k->leaks) { - if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { - ctx->todo |= true; - return quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}))); - } - if (!k->non_logical_use && get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { - ctx->todo |= true; - return prim_op_helper(a, alloca_logical_op, rewrite_nodes(&ctx->rewriter, payload.type_arguments), rewrite_nodes(r, payload.operands)); - } - } - break; - } + default: break; } break; } + case LocalAlloc_TAG: return handle_alloc(ctx, old, old->payload.local_alloc.type); + case StackAlloc_TAG: return handle_alloc(ctx, old, old->payload.stack_alloc.type); default: break; } return recreate_node_identity(&ctx->rewriter, old); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 411892dfe..b467e0628 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -322,6 +322,25 @@ static void mark_values_as_escaping(Context* ctx, KnowledgeBase* kb, Nodes value mark_value_as_escaping(ctx, kb, values.nodes[i]); } +static const Node* handle_allocation(Context* ctx, KnowledgeBase* kb, const Node* instr, const Type* type) { + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + + PtrKnowledge* k = create_root_ptr_knowledge(kb, instr); + const Type* t = instr->type; + deconstruct_qualified_type(&t); + assert(t->tag == PtrType_TAG); + k->source->as = t->payload.ptr_type.address_space; + //k->source->type = qualified_type_helper(t, u); + k->source->type = rewrite_node(r, type); + + k->state = PSUnknown; + // TODO: we can only enable this safely once we properly deal with control-flow + // k->state = PSKnownValue; + // k->ptr_value = undef(a, (Undef) { .type = rewrite_node(r, first(payload.type_arguments)) }); + return recreate_node_identity(r, instr); +} + static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const Node* oinstruction) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; @@ -354,25 +373,11 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No // let's take care of dead stores another time return recreate_node_identity(r, oinstruction); } + case Instruction_LocalAlloc_TAG: return handle_allocation(ctx, kb, oinstruction, oinstruction->payload.local_alloc.type); + case Instruction_StackAlloc_TAG: return handle_allocation(ctx, kb, oinstruction, oinstruction->payload.stack_alloc.type); case Instruction_PrimOp_TAG: { PrimOp payload = oinstruction->payload.prim_op; switch (payload.op) { - case alloca_logical_op: - case alloca_op: { - PtrKnowledge* k = create_root_ptr_knowledge(kb, oinstruction); - const Type* t = oinstruction->type; - deconstruct_qualified_type(&t); - assert(t->tag == PtrType_TAG); - k->source->as = t->payload.ptr_type.address_space; - //k->source->type = qualified_type_helper(t, u); - k->source->type = rewrite_node(r, first(payload.type_arguments)); - - k->state = PSUnknown; - // TODO: we can only enable this safely once we properly deal with control-flow - // k->state = PSKnownValue; - // k->ptr_value = undef(a, (Undef) { .type = rewrite_node(r, first(payload.type_arguments)) }); - return recreate_node_identity(r, oinstruction); - } // case memcpy_op: { // const Node* optr = first(payload.operands); // } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index e9b7085cc..528963580 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -239,7 +239,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad for (size_t i = 0; i < yield_types.count; i++) { const Type* type = yield_types.nodes[i]; assert(is_data_type(type)); - phis[i] = first(bind_instruction_named(bb_outer, prim_op(a, (PrimOp) { .op = alloca_logical_op, .type_arguments = singleton(type) }), (String []) {"ctrl_phi" })); + phis[i] = gen_local_alloc(bb_outer, type); } // Create a new context to rewrite the body with @@ -396,7 +396,8 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); - const Node* ptr = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = alloca_logical_op, .type_arguments = singleton(int32_type(a)) }), (String []) {"cf_depth" })); + const Node* ptr = gen_local_alloc(bb, int32_type(a)); + set_variable_name(ptr, "cf_depth"); gen_store(bb, ptr, int32_literal(a, 0)); ctx2.level_ptr = ptr; ctx2.fn = new; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 55c3bc3fd..3bfcbe991 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -132,7 +132,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Nodes exit_param_types = rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); LARRAY(const Node*, exit_param_allocas_tmp, exit_param_types.count); for (size_t j = 0; j < exit_param_types.count; j++) - exit_param_allocas_tmp[j] = gen_primop_e(outer_bb, alloca_op, singleton(get_unqualified_type(exit_param_types.nodes[j])), empty(arena)); + exit_param_allocas_tmp[j] = gen_stack_alloc(outer_bb, get_unqualified_type(exit_param_types.nodes[j])); exit_param_allocas[i] = nodes(arena, exit_param_types.count, exit_param_allocas_tmp); // Search for what's required after the exit but not in scope at the loop header @@ -145,13 +145,13 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { size_t leaking_count = entries_count_list(leaking[i]); LARRAY(const Node*, exit_fwd_allocas_tmp, leaking_count); for (size_t j = 0; j < leaking_count; j++) - exit_fwd_allocas_tmp[j] = gen_primop_e(outer_bb, alloca_op, singleton(rewrite_node(rewriter, get_unqualified_type(read_list(const Node*, leaking[i])[j]->type))), empty(arena)); + exit_fwd_allocas_tmp[j] = gen_stack_alloc(outer_bb, rewrite_node(rewriter, get_unqualified_type(read_list(const Node*, leaking[i])[j]->type))); exit_fwd_allocas[i] = nodes(arena, leaking_count, exit_fwd_allocas_tmp); } const Node* exit_destination_alloca = NULL; if (exiting_nodes_count > 1) - exit_destination_alloca = gen_primop_e(outer_bb, alloca_op, singleton(int32_type(arena)), empty(arena)); + exit_destination_alloca = gen_stack_alloc(outer_bb, int32_type(arena)); Node* fn = (Node*) find_processed(rewriter, ctx->current_fn); diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c index 41caee457..ae3c5edc2 100644 --- a/src/shady/passes/simt2d.c +++ b/src/shady/passes/simt2d.c @@ -34,27 +34,22 @@ static const Node* process(Context* ctx, const Node* node) { }); goto rewrite; } + case LocalAlloc_TAG: { + BodyBuilder* bb = begin_body(a); + const Node* type = rewrite_node(&ctx->rewriter, node->payload.local_alloc.type); + LARRAY(const Node*, allocated, ctx->width); + for (size_t i = 0; i < ctx->width; i++) { + allocated[i] = first(bind_instruction_named(bb, local_alloc(a, (LocalAlloc) { type }), (String[]) {"allocated"})); + } + //return yield_values_and_wrap_in_control(bb, singleton(widen(ctx, allocated))); + const Node* result_type = maybe_packed_type_helper(ptr_type(a, (PtrType) { .address_space = AsFunction, .pointed_type = type }), ctx->width); + const Node* packed = composite_helper(a, result_type, nodes(a, ctx->width, allocated)); + return yield_values_and_wrap_in_block(bb, singleton(packed)); + } case PrimOp_TAG: { Op op = node->payload.prim_op.op; switch (op) { case quote_op: goto rewrite; - case alloca_logical_op: { - BodyBuilder* bb = begin_body(a); - const Node* type = rewrite_node(&ctx->rewriter, first(node->payload.prim_op.type_arguments)); - LARRAY(const Node*, allocated, ctx->width); - for (size_t i = 0; i < ctx->width; i++) { - allocated[i] = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { - .op = op, - .type_arguments = singleton(type), - //.type_arguments = singleton(maybe_packed_type_helper(type, ctx->width)), - .operands = empty(a) - }), (String[]) {"allocated"})); - } - //return yield_values_and_wrap_in_control(bb, singleton(widen(ctx, allocated))); - const Node* result_type = maybe_packed_type_helper(ptr_type(a, (PtrType) { .address_space = AsFunction, .pointed_type = type }), ctx->width); - const Node* packed = composite_helper(a, result_type, nodes(a, ctx->width, allocated)); - return yield_values_and_wrap_in_block(bb, singleton(packed)); - } default: break; } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 2b62d3515..0c428ae56 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -82,6 +82,14 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { return gen_primop_ce(bb, or_op, 2, (const Node* []) { lo, hi }); } +const Node* gen_stack_alloc(BodyBuilder* bb, const Type* type) { + return first(bind_instruction(bb, stack_alloc(bb->arena, (StackAlloc) { type }))); +} + +const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { + return first(bind_instruction(bb, local_alloc(bb->arena, (LocalAlloc) { type }))); +} + const Node* gen_load(BodyBuilder* bb, const Node* ptr) { return first(bind_instruction(bb, load(bb->arena, (Load) { ptr }))); } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index daeffc1ee..7c928bccb 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -18,6 +18,9 @@ const Node* gen_reinterpret_cast(BodyBuilder*, const Type* dst, const Node* src) const Node* gen_conversion(BodyBuilder*, const Type* dst, const Node* src); const Node* gen_merge_halves(BodyBuilder*, const Node* lo, const Node* hi); +const Node* gen_stack_alloc(BodyBuilder*, const Type* ptr); +const Node* gen_local_alloc(BodyBuilder*, const Type* ptr); + const Node* gen_load(BodyBuilder*, const Node* ptr); void gen_store(BodyBuilder*, const Node* ptr, const Node* value); const Node* gen_lea(BodyBuilder*, const Node* base, const Node* offset, Nodes selectors); diff --git a/src/shady/type.c b/src/shady/type.c index 6f08e7873..c02cccd07 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -722,22 +722,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(src_type->tag == Float_TAG || src_type->tag == Int_TAG && src_type->payload.int_type.is_signed); return qualified_type_helper(maybe_packed_type_helper(src_type, width), uniform); } - case alloca_logical_op: as = AsFunction; goto alloca_case; - case alloca_op: as = AsPrivate; goto alloca_case; - alloca_case: { - assert(prim_op.type_arguments.count == 1); - assert(prim_op.operands.count == 0); - const Type* elem_type = prim_op.type_arguments.nodes[0]; - assert(is_type(elem_type)); - return qualified_type(arena, (QualifiedType) { - .is_uniform = is_addr_space_uniform(arena, as), - .type = ptr_type(arena, (PtrType) { - .pointed_type = elem_type, - .address_space = as, - .is_reference = as == AsFunction - }) - }); - } case align_of_op: case size_of_op: { assert(prim_op.type_arguments.count == 1); @@ -1103,6 +1087,30 @@ const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { return empty_multiple_return_type(arena); } +const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { + assert(is_type(alloc.type)); + return qualified_type(a, (QualifiedType) { + .is_uniform = is_addr_space_uniform(a, AsPrivate), + .type = ptr_type(a, (PtrType) { + .pointed_type = alloc.type, + .address_space = AsPrivate, + .is_reference = false + }) + }); +} + +const Type* check_type_local_alloc(IrArena* a, LocalAlloc alloc) { + assert(is_type(alloc.type)); + return qualified_type(a, (QualifiedType) { + .is_uniform = is_addr_space_uniform(a, AsFunction), + .type = ptr_type(a, (PtrType) { + .pointed_type = alloc.type, + .address_space = AsFunction, + .is_reference = true + }) + }); +} + const Type* check_type_load(IrArena* a, Load load) { const Node* ptr_type = load.ptr->type; bool ptr_uniform = deconstruct_qualified_type(&ptr_type); diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 7b04a40e2..955509359 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -18,21 +18,12 @@ static void search_for_memstuff(Visitor* v, const Node* n) { case Load_TAG: case Store_TAG: case CopyBytes_TAG: - case FillBytes_TAG: { + case FillBytes_TAG: + case StackAlloc_TAG: + case LocalAlloc_TAG: { found_memstuff = true; break; } - case PrimOp_TAG: { - PrimOp payload = n->payload.prim_op; - switch (payload.op) { - case alloca_op: - case alloca_logical_op: { - found_memstuff = true; - break; - } - default: break; - } - } default: break; } From 14afc2ee0d689c8c3dfeb893febe23b73175b457 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Jul 2024 12:14:17 +0200 Subject: [PATCH 348/693] slim: added back alloca[] syntax --- src/frontend/slim/parser.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index aac0de88a..940ae8565 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -479,28 +479,36 @@ static const Node* accept_primary_expr(ctxparams) { switch (curr_token(tokenizer).tag) { case lpar_tok: { Op op = PRIMOPS_COUNT; + String callee_name = NULL; if (expr->tag == Unbound_TAG) { - String s = expr->payload.unbound.name; + callee_name = expr->payload.unbound.name; for (size_t i = 0; i < PRIMOPS_COUNT; i++) { - if (strcmp(s, get_primop_name(i)) == 0) { + if (strcmp(callee_name, get_primop_name(i)) == 0) { op = i; break; } } } + Nodes ops = expect_operands(ctx); + if (op != PRIMOPS_COUNT) { return prim_op(arena, (PrimOp) { .op = op, .type_arguments = ty_args, - .operands = expect_operands(ctx) + .operands = ops + }); + } + + if (strcmp(callee_name, "alloca") == 0) { + return stack_alloc(arena, (StackAlloc) { + .type = first(ty_args) }); } assert(ty_args.count == 0 && "Function calls do not support type arguments"); - Nodes args = expect_operands(ctx); expr = call(arena, (Call) { .callee = expr, - .args = args + .args = ops }); continue; } From e064fbc98bfa4f10255f8747fb6431077661f09a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Jul 2024 13:28:24 +0200 Subject: [PATCH 349/693] added gen_if() --- src/shady/passes/lower_memcpy.c | 18 ++++++----------- src/shady/passes/lower_switch_btree.c | 29 +++++++-------------------- src/shady/passes/lower_tailcalls.c | 25 +++-------------------- src/shady/passes/lower_workgroups.c | 7 +------ src/shady/passes/opt_restructure.c | 18 ++++------------- src/shady/transform/ir_gen_helpers.c | 4 ++++ src/shady/transform/ir_gen_helpers.h | 2 ++ 7 files changed, 27 insertions(+), 76 deletions(-) diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 24b20670d..2756e1cc9 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -57,12 +57,9 @@ static const Node* process(Context* ctx, const Node* old) { const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, empty(a))); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); - bind_instruction(loop_bb, if_instr(a, (If) { - .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), - .yield_types = empty(a), - .if_true = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})), - .if_false = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})) - })); + const Node* true_case = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); + const Node* false_case = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})); + gen_if(loop_bb, gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), empty(a), true_case, false_case); bind_instruction(bb, loop_instr(a, (Loop) { .yield_types = empty(a), @@ -98,12 +95,9 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* loop_bb = begin_body(a); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); - bind_instruction(loop_bb, if_instr(a, (If) { - .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), - .yield_types = empty(a), - .if_true = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})), - .if_false = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})) - })); + const Node* true_case = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); + const Node* false_case = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})); + gen_if(loop_bb, gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), empty(a), true_case, false_case); bind_instruction(bb, loop_instr(a, (Loop) { .yield_types = empty(a), diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 938597c8d..e562b189c 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -109,25 +109,15 @@ static const Node* generate_decision_tree(Context* ctx, TreeNode* n, uint64_t mi if (min < n->key) { BodyBuilder* bb = begin_body(a); - const Node* instr = if_instr(a, (If) { - .yield_types = ctx->yield_types, - .condition = gen_primop_e(bb, lt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), - .if_true = n->children[0] ? generate_decision_tree(ctx, n->children[0], min, n->key - 1) : generate_default_fallback_case(ctx), - .if_false = body, - }); - Nodes values = bind_instruction(bb, instr); + const Node* true_branch = n->children[0] ? generate_decision_tree(ctx, n->children[0], min, n->key - 1) : generate_default_fallback_case(ctx); + Nodes values = gen_if(bb, gen_primop_e(bb, lt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), ctx->yield_types, true_branch, body); body = case_(a, empty(a), finish_body(bb, yield(a, (Yield) {.args = values}))); } if (max > n->key) { BodyBuilder* bb = begin_body(a); - const Node* instr = if_instr(a, (If) { - .yield_types = ctx->yield_types, - .condition = gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), - .if_true = n->children[1] ? generate_decision_tree(ctx, n->children[1], n->key + 1, max) : generate_default_fallback_case(ctx), - .if_false = body, - }); - Nodes values = bind_instruction(bb, instr); + const Node* true_branch = n->children[1] ? generate_decision_tree(ctx, n->children[1], n->key + 1, max) : generate_default_fallback_case(ctx); + Nodes values = gen_if(bb, gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), ctx->yield_types, true_branch, body); body = case_(a, empty(a), finish_body(bb, yield(a, (Yield) {.args = values}))); } @@ -167,14 +157,9 @@ static const Node* process(Context* ctx, const Node* node) { Nodes matched_results = bind_instruction(bb, block(a, (Block) { .yield_types = add_qualifiers(a, ctx2.yield_types, false), .inside = generate_decision_tree(&ctx2, root, 0, UINT64_MAX) })); // Check if we need to run the default case - Nodes final_results = bind_instruction(bb, if_instr(a, (If) { - .yield_types = ctx2.yield_types, - .condition = gen_load(bb, run_default_case), - .if_true = rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), - .if_false = case_(a, empty(a), yield(a, (Yield) { - .args = matched_results, - })) - })); + Nodes final_results = gen_if(bb, gen_load(bb, run_default_case), ctx2.yield_types, rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), case_(a, empty(a), yield(a, (Yield) { + .args = matched_results, + }))); destroy_arena(arena); return yield_values_and_wrap_in_block(bb, final_results); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 6b8aff932..6b44a70c2 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -306,13 +306,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { if (ctx->config->shader_diagnostics.max_top_iterations > 0) { const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); const Node* bail_true_lam = case_(a, empty(a), break_terminator); - const Node* bail_if = if_instr(a, (If) { - .condition = bail_condition, - .if_true = bail_true_lam, - .if_false = NULL, - .yield_types = empty(a) - }); - bind_instruction(loop_body_builder, bail_if); + gen_if(loop_body_builder, bail_condition, empty(a), bail_true_lam, NULL); } struct List* literals = new_list(const Node*); @@ -326,13 +320,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { bind_instruction(zero_if_case_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: kill thread %d:%d\n" }), sid, local_id) })); } const Node* zero_if_true_lam = case_(a, empty(a), finish_body(zero_if_case_builder, break_terminator)); - const Node* zero_if_instruction = if_instr(a, (If) { - .condition = should_run, - .if_true = zero_if_true_lam, - .if_false = NULL, - .yield_types = empty(a), - }); - bind_instruction(zero_case_builder, zero_if_instruction); + gen_if(zero_case_builder, should_run, empty(a), zero_if_true_lam, NULL); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); bind_instruction(zero_case_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: thread %d:%d escaped death!\n" }), sid, local_id) })); @@ -362,15 +350,8 @@ void generate_top_level_dispatch_fn(Context* ctx) { .args = nodes(a, 0, NULL) })); const Node* if_true_lam = case_(a, empty(a), finish_body(if_builder, yield(a, (Yield) {.args = nodes(a, 0, NULL)}))); - const Node* if_instruction = if_instr(a, (If) { - .condition = should_run, - .if_true = if_true_lam, - .if_false = NULL, - .yield_types = empty(a), - }); - BodyBuilder* case_builder = begin_body(a); - bind_instruction(case_builder, if_instruction); + gen_if(case_builder, should_run, empty(a), if_true_lam, NULL); const Node* case_lam = case_(a, nodes(a, 0, NULL), finish_body(case_builder, continue_terminator)); append_list(const Node*, literals, fn_lit); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index be82d089b..c97d8b934 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -124,12 +124,7 @@ static const Node* process(Context* ctx, const Node* node) { assert(false); for (int dim = 0; dim < 3; dim++) { BodyBuilder* body_bb = begin_body(a); - bind_instruction(body_bb, if_instr(a, (If) { - .yield_types = empty(a), - .condition = gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), - .if_true = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})), - .if_false = NULL - })); + gen_if(body_bb, gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), empty(a), case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})), NULL); bind_instruction(body_bb, instr); const Node* loop = loop_instr(a, (Loop) { .yield_types = empty(a), diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 528963580..5d53aaefb 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -269,12 +269,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); const Node* true_body = structure(ctx, old_tail, yield(a, (Yield) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); - bind_instruction(bb2, if_instr(a, (If) { - .condition = guard, - .yield_types = empty(a), - .if_true = if_true_lam, - .if_false = NULL - })); + gen_if(bb2, guard, empty(a), if_true_lam, NULL); const Node* tail_lambda = case_(a, empty(a), finish_body(bb2, exit_ladder)); return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), empty(a), tail_lambda))); @@ -300,14 +295,9 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad const Node* false_body = handle_bb_callsite(ctx, abs, body->payload.branch.false_jump, yield(a, (Yield) { .args = empty(a) })); const Node* if_false_lam = case_(a, empty(a), false_body); - const Node* instr = if_instr(a, (If) { - .condition = condition, - .yield_types = empty(a), - .if_true = if_true_lam, - .if_false = if_false_lam, - }); - const Node* post_merge_lam = case_(a, empty(a), exit_ladder); - return let(a, instr, empty(a), post_merge_lam); + BodyBuilder* bb = begin_body(a); + gen_if(bb, condition, empty(a), if_true_lam, if_false_lam); + return finish_body(bb, exit_ladder); } case Switch_TAG: { const Node* switch_value = rewrite_node(&ctx->rewriter, body->payload.br_switch.switch_value); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 0c428ae56..38cbffeee 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -242,6 +242,10 @@ const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, cons return val; } +Nodes gen_if(BodyBuilder* bb, const Node* condition, Nodes yield_types, const Node* true_case, const Node* false_case) { + return bind_instruction(bb, if_instr(bb->arena, (If) { .condition = condition, .yield_types = yield_types, .if_true = true_case, .if_false = false_case })); +} + const Node* get_default_zero_value(IrArena* a, const Type* t) { switch (is_type(t)) { case NotAType: error("") diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 7c928bccb..0939b4319 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -30,6 +30,8 @@ const Node* get_builtin(Module* m, Builtin b); const Node* get_or_create_builtin(Module* m, Builtin b, String n); const Node* gen_builtin_load(Module*, BodyBuilder*, Builtin); +Nodes gen_if(BodyBuilder*, const Node*, Nodes, const Node*, const Node*); + typedef struct Rewriter_ Rewriter; const Node* find_or_process_decl(Rewriter*, const char* name); From 6691183f7c834ee7f53c8462f5d62bb4632e153c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Jul 2024 13:44:46 +0200 Subject: [PATCH 350/693] added gen_loop and gen_match --- src/shady/passes/lower_generic_ptrs.c | 16 ++-------------- src/shady/passes/lower_memcpy.c | 14 ++------------ src/shady/passes/lower_tailcalls.c | 18 +++--------------- src/shady/passes/lower_workgroups.c | 11 +++++------ src/shady/passes/opt_restructure.c | 17 ++++------------- src/shady/transform/ir_gen_helpers.c | 8 ++++++++ src/shady/transform/ir_gen_helpers.h | 3 +++ 7 files changed, 27 insertions(+), 60 deletions(-) diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index c17fa15e4..d90a9f96b 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -120,13 +120,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); - const Node* loaded_value = first(bind_instruction(bb, match_instr(a, (Match) { - .inspect = extracted_tag, - .yield_types = singleton(t), - .literals = nodes(a, max_tag, literals), - .cases = nodes(a, max_tag, cases), - .default_case = case_(a, empty(a), unreachable(a)), - }))); + const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), case_(a, empty(a), unreachable(a)))); new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value), .fn = new_fn })); break; } @@ -152,13 +146,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); - bind_instruction(bb, match_instr(a, (Match) { - .inspect = extracted_tag, - .yield_types = empty(a), - .literals = nodes(a, max_tag, literals), - .cases = nodes(a, max_tag, cases), - .default_case = case_(a, empty(a), unreachable(a)), - })); + gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), case_(a, empty(a), unreachable(a))); new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .fn = new_fn })); break; } diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 2756e1cc9..1c5c4712d 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -60,12 +60,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* true_case = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); const Node* false_case = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})); gen_if(loop_bb, gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), empty(a), true_case, false_case); - - bind_instruction(bb, loop_instr(a, (Loop) { - .yield_types = empty(a), - .body = case_(a, singleton(index), finish_body(loop_bb, unreachable(a))), - .initial_args = singleton(uint32_literal(a, 0)) - })); + gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), case_(a, singleton(index), finish_body(loop_bb, unreachable(a)))); return yield_values_and_wrap_in_block(bb, empty(a)); } case FillBytes_TAG: { @@ -98,12 +93,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* true_case = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); const Node* false_case = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})); gen_if(loop_bb, gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), empty(a), true_case, false_case); - - bind_instruction(bb, loop_instr(a, (Loop) { - .yield_types = empty(a), - .body = case_(a, singleton(index), finish_body(loop_bb, unreachable(a))), - .initial_args = singleton(uint32_literal(a, 0)) - })); + gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), case_(a, singleton(index), finish_body(loop_bb, unreachable(a)))); return yield_values_and_wrap_in_block(bb, empty(a)); } default: break; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 6b44a70c2..898e78908 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -360,28 +360,16 @@ void generate_top_level_dispatch_fn(Context* ctx) { } const Node* default_case_lam = case_(a, nodes(a, 0, NULL), unreachable(a)); - - bind_instruction(loop_body_builder, match_instr(a, (Match) { - .yield_types = nodes(a, 0, NULL), - .inspect = next_function, - .literals = nodes(a, entries_count_list(literals), read_list(const Node*, literals)), - .cases = nodes(a, entries_count_list(cases), read_list(const Node*, cases)), - .default_case = default_case_lam, - })); + gen_match(loop_body_builder, empty(a), next_function, nodes(a, entries_count_list(literals), read_list(const Node*, literals)), nodes(a, entries_count_list(cases), read_list(const Node*, cases)), default_case_lam); destroy_list(literals); destroy_list(cases); const Node* loop_inside_lam = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL), finish_body(loop_body_builder, unreachable(a))); - const Node* the_loop = loop_instr(a, (Loop) { - .yield_types = nodes(a, 0, NULL), - .initial_args = count_iterations ? singleton(int32_literal(a, 0)) : nodes(a, 0, NULL), - .body = loop_inside_lam - }); - BodyBuilder* dispatcher_body_builder = begin_body(a); - bind_instruction(dispatcher_body_builder, the_loop); + gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : nodes(a, 0, NULL), loop_inside_lam); + if (ctx->config->printf_trace.god_function) bind_instruction(dispatcher_body_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: end of top\n" })) })); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index c97d8b934..eb70dc3ff 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -126,12 +126,11 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* body_bb = begin_body(a); gen_if(body_bb, gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), empty(a), case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})), NULL); bind_instruction(body_bb, instr); - const Node* loop = loop_instr(a, (Loop) { - .yield_types = empty(a), - .initial_args = singleton(uint32_literal(a, 0)), - .body = case_(a, singleton(params[dim]), finish_body(body_bb, merge_continue(a, (MergeContinue) {.args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1))))}))) - }); - instr = loop; + + BodyBuilder* bb3 = begin_body(a); + const Node* loop_body = case_(a, singleton(params[dim]), finish_body(body_bb, merge_continue(a, (MergeContinue) {.args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1))))}))); + gen_loop(bb3, empty(a), singleton(uint32_literal(a, 0)), loop_body); + instr = yield_values_and_wrap_in_block(bb3, empty(a)); } } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 5d53aaefb..80abea036 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -148,11 +148,7 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* caller, const No if (dfs_entry.loop_header) { const Node* body = case_(a, nodes(a, oargs.count, nparams), structured); - bind_instruction(bb, loop_instr(a, (Loop) { - .body = body, - .initial_args = rewrite_nodes(&ctx->rewriter, oargs), - .yield_types = nodes(a, 0, NULL), - })); + gen_loop(bb, empty(a), rewrite_nodes(&ctx->rewriter, oargs), body); // we decide 'late' what the exit ladder should be inner_exit_ladder_bb->payload.basic_block.body = merge_break(a, (MergeBreak) { .args = empty(a) }); return finish_body(bb, exit_ladder); @@ -310,14 +306,9 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad cases[i] = case_(a, empty(a), handle_bb_callsite(ctx, abs, body->payload.br_switch.case_jumps.nodes[i], yield(a, (Yield) {.args = empty(a)}))); } - const Node* instr = match_instr(a, (Match) { - .inspect = switch_value, - .yield_types = empty(a), - .default_case = default_case, - .cases = nodes(a, body->payload.br_switch.case_jumps.count, cases), - .literals = rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), - }); - return let(a, instr, empty(a), case_(a, empty(a), exit_ladder)); + BodyBuilder* bb = begin_body(a); + gen_match(bb, empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), nodes(a, body->payload.br_switch.case_jumps.count, cases), default_case); + finish_body(bb, exit_ladder); } case Join_TAG: { ControlEntry* control = search_containing_control(ctx, body->payload.join.join_point); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 38cbffeee..d5f740cc2 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -246,6 +246,14 @@ Nodes gen_if(BodyBuilder* bb, const Node* condition, Nodes yield_types, const No return bind_instruction(bb, if_instr(bb->arena, (If) { .condition = condition, .yield_types = yield_types, .if_true = true_case, .if_false = false_case })); } +Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, const Node* default_case) { + return bind_instruction(bb, match_instr(bb->arena, (Match) { .yield_types = yield_types, .inspect = inspectee, .literals = literals, .cases = cases, .default_case = default_case })); +} + +Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Node* body) { + return bind_instruction(bb, loop_instr(bb->arena, (Loop) { .yield_types = yield_types, .initial_args = initial_args, .body = body })); +} + const Node* get_default_zero_value(IrArena* a, const Type* t) { switch (is_type(t)) { case NotAType: error("") diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 0939b4319..0d65837aa 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -32,6 +32,9 @@ const Node* gen_builtin_load(Module*, BodyBuilder*, Builtin); Nodes gen_if(BodyBuilder*, const Node*, Nodes, const Node*, const Node*); +Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, const Node*); +Nodes gen_loop(BodyBuilder*, Nodes, Nodes, const Node*); + typedef struct Rewriter_ Rewriter; const Node* find_or_process_decl(Rewriter*, const char* name); From 873d1f7d7406f35c2d4d24e5cb813ca378813ad4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 26 Jul 2024 13:48:27 +0200 Subject: [PATCH 351/693] align gen_if's signature with the others --- src/shady/passes/lower_memcpy.c | 4 ++-- src/shady/passes/lower_switch_btree.c | 8 ++++---- src/shady/passes/lower_tailcalls.c | 6 +++--- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/opt_restructure.c | 4 ++-- src/shady/transform/ir_gen_helpers.c | 2 +- src/shady/transform/ir_gen_helpers.h | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 1c5c4712d..b3c3d15fa 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -59,7 +59,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); const Node* true_case = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); const Node* false_case = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})); - gen_if(loop_bb, gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), empty(a), true_case, false_case); + gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), true_case, false_case); gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), case_(a, singleton(index), finish_body(loop_bb, unreachable(a)))); return yield_values_and_wrap_in_block(bb, empty(a)); } @@ -92,7 +92,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); const Node* true_case = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); const Node* false_case = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})); - gen_if(loop_bb, gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), empty(a), true_case, false_case); + gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), true_case, false_case); gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), case_(a, singleton(index), finish_body(loop_bb, unreachable(a)))); return yield_values_and_wrap_in_block(bb, empty(a)); } diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index e562b189c..de18efd76 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -110,14 +110,14 @@ static const Node* generate_decision_tree(Context* ctx, TreeNode* n, uint64_t mi if (min < n->key) { BodyBuilder* bb = begin_body(a); const Node* true_branch = n->children[0] ? generate_decision_tree(ctx, n->children[0], min, n->key - 1) : generate_default_fallback_case(ctx); - Nodes values = gen_if(bb, gen_primop_e(bb, lt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), ctx->yield_types, true_branch, body); + Nodes values = gen_if(bb, ctx->yield_types, gen_primop_e(bb, lt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), true_branch, body); body = case_(a, empty(a), finish_body(bb, yield(a, (Yield) {.args = values}))); } if (max > n->key) { BodyBuilder* bb = begin_body(a); const Node* true_branch = n->children[1] ? generate_decision_tree(ctx, n->children[1], n->key + 1, max) : generate_default_fallback_case(ctx); - Nodes values = gen_if(bb, gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), ctx->yield_types, true_branch, body); + Nodes values = gen_if(bb, ctx->yield_types, gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), true_branch, body); body = case_(a, empty(a), finish_body(bb, yield(a, (Yield) {.args = values}))); } @@ -157,8 +157,8 @@ static const Node* process(Context* ctx, const Node* node) { Nodes matched_results = bind_instruction(bb, block(a, (Block) { .yield_types = add_qualifiers(a, ctx2.yield_types, false), .inside = generate_decision_tree(&ctx2, root, 0, UINT64_MAX) })); // Check if we need to run the default case - Nodes final_results = gen_if(bb, gen_load(bb, run_default_case), ctx2.yield_types, rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), case_(a, empty(a), yield(a, (Yield) { - .args = matched_results, + Nodes final_results = gen_if(bb, ctx2.yield_types, gen_load(bb, run_default_case), rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), case_(a, empty(a), yield(a, (Yield) { + .args = matched_results, }))); destroy_arena(arena); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 898e78908..5ed77e2e1 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -306,7 +306,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { if (ctx->config->shader_diagnostics.max_top_iterations > 0) { const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); const Node* bail_true_lam = case_(a, empty(a), break_terminator); - gen_if(loop_body_builder, bail_condition, empty(a), bail_true_lam, NULL); + gen_if(loop_body_builder, empty(a), bail_condition, bail_true_lam, NULL); } struct List* literals = new_list(const Node*); @@ -320,7 +320,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { bind_instruction(zero_if_case_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: kill thread %d:%d\n" }), sid, local_id) })); } const Node* zero_if_true_lam = case_(a, empty(a), finish_body(zero_if_case_builder, break_terminator)); - gen_if(zero_case_builder, should_run, empty(a), zero_if_true_lam, NULL); + gen_if(zero_case_builder, empty(a), should_run, zero_if_true_lam, NULL); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); bind_instruction(zero_case_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: thread %d:%d escaped death!\n" }), sid, local_id) })); @@ -351,7 +351,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { })); const Node* if_true_lam = case_(a, empty(a), finish_body(if_builder, yield(a, (Yield) {.args = nodes(a, 0, NULL)}))); BodyBuilder* case_builder = begin_body(a); - gen_if(case_builder, should_run, empty(a), if_true_lam, NULL); + gen_if(case_builder, empty(a), should_run, if_true_lam, NULL); const Node* case_lam = case_(a, nodes(a, 0, NULL), finish_body(case_builder, continue_terminator)); append_list(const Node*, literals, fn_lit); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index eb70dc3ff..380533f93 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -124,7 +124,7 @@ static const Node* process(Context* ctx, const Node* node) { assert(false); for (int dim = 0; dim < 3; dim++) { BodyBuilder* body_bb = begin_body(a); - gen_if(body_bb, gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), empty(a), case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})), NULL); + gen_if(body_bb, empty(a), gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})), NULL); bind_instruction(body_bb, instr); BodyBuilder* bb3 = begin_body(a); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 80abea036..b151ceed8 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -265,7 +265,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); const Node* true_body = structure(ctx, old_tail, yield(a, (Yield) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); - gen_if(bb2, guard, empty(a), if_true_lam, NULL); + gen_if(bb2, empty(a), guard, if_true_lam, NULL); const Node* tail_lambda = case_(a, empty(a), finish_body(bb2, exit_ladder)); return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), empty(a), tail_lambda))); @@ -292,7 +292,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad const Node* if_false_lam = case_(a, empty(a), false_body); BodyBuilder* bb = begin_body(a); - gen_if(bb, condition, empty(a), if_true_lam, if_false_lam); + gen_if(bb, empty(a), condition, if_true_lam, if_false_lam); return finish_body(bb, exit_ladder); } case Switch_TAG: { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index d5f740cc2..c434f5da5 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -242,7 +242,7 @@ const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, cons return val; } -Nodes gen_if(BodyBuilder* bb, const Node* condition, Nodes yield_types, const Node* true_case, const Node* false_case) { +Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { return bind_instruction(bb, if_instr(bb->arena, (If) { .condition = condition, .yield_types = yield_types, .if_true = true_case, .if_false = false_case })); } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 0d65837aa..2c9a54828 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -30,7 +30,7 @@ const Node* get_builtin(Module* m, Builtin b); const Node* get_or_create_builtin(Module* m, Builtin b, String n); const Node* gen_builtin_load(Module*, BodyBuilder*, Builtin); -Nodes gen_if(BodyBuilder*, const Node*, Nodes, const Node*, const Node*); +Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, const Node*); Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, const Node*); Nodes gen_loop(BodyBuilder*, Nodes, Nodes, const Node*); From 7e718f0796b78cb5ec38586fb39aebc9fe1b363e Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 11:24:21 +0200 Subject: [PATCH 352/693] added gen_control helper --- src/frontend/llvm/l2s_postprocess.c | 6 ++--- src/shady/passes/lower_callf.c | 2 +- src/shady/passes/reconvergence_heuristics.c | 26 +++++---------------- src/shady/transform/ir_gen_helpers.c | 4 ++++ src/shady/transform/ir_gen_helpers.h | 2 ++ 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index c56c3b0ed..bc2c62357 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -8,6 +8,7 @@ #include "../shady/type.h" #include "../shady/ir_private.h" #include "../shady/analysis/cfg.h" +#include "../shady/transform/ir_gen_helpers.h" typedef struct { Rewriter rewriter; @@ -40,10 +41,7 @@ static const Node* wrap_in_controls(Context* ctx, Controls* controls, const Node const Node* dst = controls->destinations.nodes[i]; Nodes o_dst_params = get_abstraction_params(dst); BodyBuilder* bb = begin_body(a); - Nodes results = bind_instruction(bb, control(a, (Control) { - .yield_types = get_param_types(a, o_dst_params), - .inside = case_(a, singleton(token), body) - })); + Nodes results = gen_control(bb, get_param_types(a, o_dst_params), case_(a, singleton(token), body)); body = finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results)); } return body; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 4cd45b3fc..b8a6c9809 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -130,7 +130,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .target = ncallee, .args = nargs, }); - const Node* control_lam = case_(a, nodes(a, 1, (const Node* []) {jp}), control_body); + const Node* control_lam = case_(a, singleton(jp), control_body); return control(a, (Control) { .yield_types = strip_qualifiers(a, returned_types), .inside = control_lam }); } default: break; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 3bfcbe991..d0e03c898 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -272,11 +272,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { register_processed(rewriter, node, cached_entry); BodyBuilder* inner_bb = begin_body(arena); - const Node* inner_control = control(arena, (Control) { - .inside = case_(arena, singleton(join_token_continue), loop_body), - .yield_types = inner_yield_types - }); - Nodes inner_control_results = bind_instruction(inner_bb, inner_control); + Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, case_(arena, singleton(join_token_continue), loop_body)); Node* loop_outer = basic_block(arena, fn, inner_loop_params, "loop_outer"); @@ -284,15 +280,10 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .target = loop_outer, .args = inner_control_results })); - const Node* outer_control = control(arena, (Control) { - .inside = case_(arena, singleton(join_token_exit), jump(arena, (Jump) { - .target = loop_outer, - .args = nparams - })), - .yield_types = empty(arena) - }); - - bind_instruction(outer_bb, outer_control); + gen_control(outer_bb, empty(arena), case_(arena, singleton(join_token_exit), jump(arena, (Jump) { + .target = loop_outer, + .args = nparams + }))); LARRAY(const Node*, exit_numbers, exiting_nodes_count); LARRAY(const Node*, exit_jumps, exiting_nodes_count); @@ -514,17 +505,12 @@ static const Node* process_node(Context* ctx, const Node* node) { register_processed(rewriter, idom, cached); const Node* control_inner = case_(arena, singleton(join_token), inner_terminator); - const Node* control_instruction = control(arena, (Control) { - .inside = control_inner, - .yield_types = yield_types - }); - const Node* recreated_join = rewrite_node(rewriter, idom); switch (idom->tag) { case BasicBlock_TAG: { BodyBuilder* bb = begin_body(arena); - Nodes results = bind_instruction(bb, control_instruction); + Nodes results = gen_control(bb, yield_types, control_inner); return finish_body(bb, jump(arena, (Jump) { .target = recreated_join, .args = results diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index c434f5da5..1977d6020 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -254,6 +254,10 @@ Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Nod return bind_instruction(bb, loop_instr(bb->arena, (Loop) { .yield_types = yield_types, .initial_args = initial_args, .body = body })); } +Nodes gen_control(BodyBuilder* bb, Nodes yield_types, const Node* body) { + return bind_instruction(bb, control(bb->arena, (Control) { .yield_types = yield_types, .inside = body })); +} + const Node* get_default_zero_value(IrArena* a, const Type* t) { switch (is_type(t)) { case NotAType: error("") diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 2c9a54828..64eea88a4 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -35,6 +35,8 @@ Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, const Node*); Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, const Node*); Nodes gen_loop(BodyBuilder*, Nodes, Nodes, const Node*); +Nodes gen_control(BodyBuilder*, Nodes, const Node*); + typedef struct Rewriter_ Rewriter; const Node* find_or_process_decl(Rewriter*, const char* name); From 9e346c3d1afa789fad8bbc17246b07e797f990ee Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 12:00:32 +0200 Subject: [PATCH 353/693] split yield in merge_selection and block_yield --- include/shady/grammar.json | 9 +++++++- src/backend/c/emit_c.c | 5 ++-- src/backend/spirv/emit_spv.c | 5 ++-- src/frontend/llvm/l2s_postprocess.c | 4 ++-- src/frontend/slim/parser.c | 6 ++--- src/frontend/slim/token.h | 2 +- src/shady/analysis/cfg.c | 5 +++- src/shady/body_builder.c | 2 +- src/shady/fold.c | 12 +++++----- src/shady/node.c | 6 ++--- src/shady/passes/cleanup.c | 4 ++-- src/shady/passes/infer.c | 11 +++++---- src/shady/passes/lower_cf_instrs.c | 4 ++-- src/shady/passes/lower_generic_ptrs.c | 4 ++-- src/shady/passes/lower_switch_btree.c | 33 ++++++++++++--------------- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/opt_mem2reg.c | 4 +++- src/shady/passes/opt_restructure.c | 13 ++++++----- src/shady/print.c | 11 +++++++-- src/shady/type.c | 7 +++++- test/control_flow1.slim | 4 ++-- 21 files changed, 89 insertions(+), 64 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 80763c6fe..63c0e478b 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -536,7 +536,14 @@ ] }, { - "name": "Yield", + "name": "MergeSelection", + "class": "terminator", + "ops": [ + { "name": "args", "class": "value", "list": true } + ] + }, + { + "name": "BlockYield", "class": "terminator", "ops": [ { "name": "args", "class": "value", "list": true } diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index dc4149f3f..36347af0d 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -417,6 +417,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node case Jump_TAG: case Branch_TAG: case Switch_TAG: + case Terminator_BlockYield_TAG: case TailCall_TAG: error("TODO"); case Let_TAG: { const Node* instruction = get_let_instruction(terminator); @@ -487,8 +488,8 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node } break; } - case Yield_TAG: { - Nodes args = terminator->payload.yield.args; + case MergeSelection_TAG: { + Nodes args = terminator->payload.merge_selection.args; Phis phis = emitter->phis.selection; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index b8530806b..1f66a09a2 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -228,10 +228,11 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); return; } + case Terminator_BlockYield_TAG: case TailCall_TAG: case Join_TAG: error("Lower me"); - case Terminator_Yield_TAG: { - Nodes args = terminator->payload.yield.args; + case MergeSelection_TAG: { + Nodes args = terminator->payload.merge_selection.args; for (size_t i = 0; i < args.count; i++) spvb_add_phi_source(merge_targets.join_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); spvb_branch(basic_block_builder, merge_targets.join_target); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index bc2c62357..64a6f727f 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -90,8 +90,8 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, while (term->tag == Let_TAG) { term = get_abstraction_body(get_let_tail(term)); } - assert(term->tag == Yield_TAG); - yield_types = get_values_types(a, term->payload.yield.args); + assert(term->tag == BlockYield_TAG); + yield_types = get_values_types(a, term->payload.block_yield.args); return block(a, (Block) { .yield_types = yield_types, .inside = ninside, diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 940ae8565..6c401995e 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -592,7 +592,7 @@ static const Node* accept_control_flow_instruction(ctxparams, Node* fn) { const Node* condition = accept_operand(ctx); expect(condition); expect(accept_token(ctx, rpar_tok)); - const Node* merge = config.front_end ? yield(arena, (Yield) { .args = nodes(arena, 0, NULL) }) : NULL; + const Node* merge = config.front_end ? merge_selection(arena, (MergeSelection) { .args = nodes(arena, 0, NULL) }) : NULL; const Node* if_true = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, fn, merge)); @@ -830,10 +830,10 @@ static const Node* accept_terminator(ctxparams, Node* fn) { .args = args }); } - case yield_tok: { + case merge_selection_tok: { next_token(tokenizer); Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx) : nodes(arena, 0, NULL); - return yield(arena, (Yield) { + return merge_selection(arena, (MergeSelection) { .args = args }); } diff --git a/src/frontend/slim/token.h b/src/frontend/slim/token.h index 5536279aa..08dcd2e67 100644 --- a/src/frontend/slim/token.h +++ b/src/frontend/slim/token.h @@ -58,7 +58,7 @@ TOKEN(false, "false") \ TOKEN(if, "if") \ TOKEN(else, "else") \ TEXT_TOKEN(control) \ -TEXT_TOKEN(yield) \ +TEXT_TOKEN(merge_selection) \ TEXT_TOKEN(loop) \ TOKEN(continue, "continue") \ TOKEN(break, "break") \ diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index d69ceb010..cc0ddc160 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -214,11 +214,14 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_edge(ctx, node->node, (*dst)->node, StructuredLeaveBodyEdge); break; } - case Yield_TAG: + case MergeSelection_TAG: case MergeContinue_TAG: case MergeBreak_TAG: { break; // TODO i guess } + case Terminator_BlockYield_TAG: { + break; + } case TailCall_TAG: { } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 6139bcf4c..a38f0ca14 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -132,7 +132,7 @@ const Node* finish_body(BodyBuilder* bb, const Node* terminator) { const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder* bb, Nodes values, const Nodes* types) { IrArena* arena = bb->arena; assert(arena->config.check_types || types); - const Node* terminator = yield(arena, (Yield) { .args = values }); + const Node* terminator = block_yield(arena, (BlockYield) { .args = values }); const Node* lam = case_(arena, empty(arena), finish_body(bb, terminator)); return block(arena, (Block) { .yield_types = arena->config.check_types ? get_values_types(arena, values) : *types, diff --git a/src/shady/fold.c b/src/shady/fold.c index baa8c6283..c9c6915fd 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -380,17 +380,17 @@ const Node* fold_node(IrArena* arena, const Node* node) { case Block_TAG: { const Node* lam = node->payload.block.inside; const Node* body = lam->payload.case_.body; - if (body->tag == Yield_TAG) { - return quote_helper(arena, body->payload.yield.args); + if (body->tag == BlockYield_TAG) { + return quote_helper(arena, body->payload.block_yield.args); } else if (body->tag == Let_TAG) { // fold block { let x, y, z = I; yield (x, y, z); } back to I const Node* instr = get_let_instruction(body); const Node* let_case = get_let_tail(body); const Node* let_case_body = get_abstraction_body(let_case); - if (let_case_body->tag == Yield_TAG) { + if (let_case_body->tag == BlockYield_TAG) { bool only_forwards = true; Nodes let_case_params = get_abstraction_params(let_case); - Nodes yield_args = let_case_body->payload.yield.args; + Nodes yield_args = let_case_body->payload.block_yield.args; if (let_case_params.count == yield_args.count) { for (size_t i = 0; i < yield_args.count; i++) { only_forwards &= yield_args.nodes[i] == let_case_params.nodes[i]; @@ -408,7 +408,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { } break; } - case If_TAG: { + /*case If_TAG: { If payload = node->payload.if_instr; const Node* false_case = payload.if_false; if (arena->config.optimisations.delete_unreachable_structured_cases && false_case && is_unreachable_case(false_case)) @@ -421,7 +421,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { } } break; - } + }*/ case Match_TAG: { if (!arena->config.optimisations.delete_unreachable_structured_cases) break; diff --git a/src/shady/node.c b/src/shady/node.c index a034d4450..25cba0eb9 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -190,9 +190,9 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi while (terminator->tag == Let_TAG) { terminator = terminator->payload.let.tail->payload.case_.body; } - assert(terminator->tag == Yield_TAG); - assert(terminator->payload.yield.args.count == 1); - return resolve_node_to_definition(first(terminator->payload.yield.args), config); + assert(terminator->tag == BlockYield_TAG); + assert(terminator->payload.block_yield.args.count == 1); + return resolve_node_to_definition(first(terminator->payload.block_yield.args), config); } case Load_TAG: { if (config.enter_loads) { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 30cc0be3b..4743d8d2b 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -62,8 +62,8 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* terminator = get_abstraction_body(terminator->payload.let.tail); continue; } - case Terminator_Yield_TAG: { - return quote_helper(arena, terminator->payload.yield.args); + case Terminator_BlockYield_TAG: { + return quote_helper(arena, terminator->payload.block_yield.args); } case Terminator_Return_TAG: case Terminator_TailCall_TAG: { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 555590b53..2be7ffe3a 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -657,13 +657,14 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { }); } case Branch_TAG: + case Terminator_BlockYield_TAG: case Terminator_Switch_TAG: break; case Terminator_TailCall_TAG: break; - case Terminator_Yield_TAG: { + case Terminator_MergeSelection_TAG: { // TODO: block nodes should set merge types assert(ctx->merge_types && "Merge terminator found but we're not within a suitable if instruction !"); Nodes expected_types = *ctx->merge_types; - Nodes old_args = node->payload.yield.args; + Nodes old_args = node->payload.merge_selection.args; assert(expected_types.count == old_args.count); LARRAY(const Node*, new_args, old_args.count); for (size_t i = 0; i < old_args.count; i++) { @@ -671,14 +672,14 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { assert(is_value_type(e)); new_args[i] = infer(ctx, old_args.nodes[i], e); } - return yield(a, (Yield) { + return merge_selection(a, (MergeSelection) { .args = nodes(a, old_args.count, new_args) }); } case MergeContinue_TAG: { assert(ctx->continue_types && "Merge terminator found but we're not within a suitable loop instruction !"); Nodes expected_types = *ctx->continue_types; - Nodes old_args = node->payload.yield.args; + Nodes old_args = node->payload.merge_continue.args; assert(expected_types.count == old_args.count); LARRAY(const Node*, new_args, old_args.count); for (size_t i = 0; i < old_args.count; i++) { @@ -693,7 +694,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { case MergeBreak_TAG: { assert(ctx->break_types && "Merge terminator found but we're not within a suitable loop instruction !"); Nodes expected_types = *ctx->break_types; - Nodes old_args = node->payload.yield.args; + Nodes old_args = node->payload.merge_break.args; assert(expected_types.count == old_args.count); LARRAY(const Node*, new_args, old_args.count); for (size_t i = 0; i < old_args.count; i++) { diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index f28e51820..f0ea1da7e 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -151,7 +151,7 @@ static const Node* process_node(Context* ctx, const Node* node) { if (is_instruction(node)) return process_instruction(ctx, node); switch (node->tag) { - case Yield_TAG: { + case MergeSelection_TAG: { if (!cfnode) break; CFNode* dom = cfnode->idom; @@ -181,7 +181,7 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(jp); return join(a, (Join) { .join_point = jp, - .args = rewrite_nodes(&ctx->rewriter, node->payload.yield.args), + .args = rewrite_nodes(&ctx->rewriter, node->payload.merge_selection.args), }); } case MergeContinue_TAG: { diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index d90a9f96b..498c165bc 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -110,7 +110,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo BodyBuilder* case_bb = begin_body(a); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); - cases[tag] = case_(a, empty(a), finish_body(case_bb, yield(a, (Yield) { + cases[tag] = case_(a, empty(a), finish_body(case_bb, merge_selection(a, (MergeSelection) { .args = singleton(loaded_value), }))); } @@ -136,7 +136,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo BodyBuilder* case_bb = begin_body(a); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); - cases[tag] = case_(a, empty(a), finish_body(case_bb, yield(a, (Yield) { + cases[tag] = case_(a, empty(a), finish_body(case_bb, merge_selection(a, (MergeSelection) { .args = empty(a), }))); } diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index de18efd76..471b82372 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -76,24 +76,23 @@ TreeNode* insert(TreeNode* t, TreeNode* x) { return t; } -static const Node* generate_default_fallback_case(Context* ctx) { +static const Node* gen_yield(Context* ctx, bool in_if, Nodes args) { + if (in_if) + return merge_selection(ctx->rewriter.dst_arena, (MergeSelection) { args }); + return block_yield(ctx->rewriter.dst_arena, (BlockYield) { args }); +} + +static const Node* generate_default_fallback_case(Context* ctx, bool in_if) { IrArena* a = ctx->rewriter.dst_arena; BodyBuilder* bb = begin_body(a); gen_store(bb, ctx->run_default_case, true_lit(a)); LARRAY(const Node*, undefs, ctx->yield_types.count); for (size_t i = 0; i < ctx->yield_types.count; i++) undefs[i] = undef(a, (Undef) { .type = ctx->yield_types.nodes[i] }); - return case_(a, empty(a), finish_body(bb, yield(a, (Yield) {.args = nodes(a, ctx->yield_types.count, undefs)}))); -} - -static const Node* wrap_instr_in_lambda(const Node* instr) { - IrArena* a = instr->arena; - BodyBuilder* bb = begin_body(a); - Nodes values = bind_instruction(bb, instr); - return case_(a, empty(a), finish_body(bb, yield(a, (Yield) {.args = values}))); + return case_(a, empty(a), finish_body(bb, gen_yield(ctx, in_if, nodes(a, ctx->yield_types.count, undefs)))); } -static const Node* generate_decision_tree(Context* ctx, TreeNode* n, uint64_t min, uint64_t max) { +static const Node* generate_decision_tree(Context* ctx, TreeNode* n, bool in_if, uint64_t min, uint64_t max) { IrArena* a = ctx->rewriter.dst_arena; assert(n->key >= min && n->key <= max); assert(n->lam); @@ -109,16 +108,16 @@ static const Node* generate_decision_tree(Context* ctx, TreeNode* n, uint64_t mi if (min < n->key) { BodyBuilder* bb = begin_body(a); - const Node* true_branch = n->children[0] ? generate_decision_tree(ctx, n->children[0], min, n->key - 1) : generate_default_fallback_case(ctx); + const Node* true_branch = n->children[0] ? generate_decision_tree(ctx, n->children[0], true, min, n->key - 1) : generate_default_fallback_case(ctx, true); Nodes values = gen_if(bb, ctx->yield_types, gen_primop_e(bb, lt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), true_branch, body); - body = case_(a, empty(a), finish_body(bb, yield(a, (Yield) {.args = values}))); + body = case_(a, empty(a), finish_body(bb, gen_yield(ctx, in_if || max > n->key, values))); } if (max > n->key) { BodyBuilder* bb = begin_body(a); - const Node* true_branch = n->children[1] ? generate_decision_tree(ctx, n->children[1], n->key + 1, max) : generate_default_fallback_case(ctx); + const Node* true_branch = n->children[1] ? generate_decision_tree(ctx, n->children[1], true, n->key + 1, max) : generate_default_fallback_case(ctx, true); Nodes values = gen_if(bb, ctx->yield_types, gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), true_branch, body); - body = case_(a, empty(a), finish_body(bb, yield(a, (Yield) {.args = values}))); + body = case_(a, empty(a), gen_yield(ctx, in_if, values)); } return body; @@ -154,12 +153,10 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.run_default_case = run_default_case; ctx2.yield_types = yield_types; ctx2.inspectee = rewrite_node(&ctx->rewriter, node->payload.match_instr.inspect); - Nodes matched_results = bind_instruction(bb, block(a, (Block) { .yield_types = add_qualifiers(a, ctx2.yield_types, false), .inside = generate_decision_tree(&ctx2, root, 0, UINT64_MAX) })); + Nodes matched_results = bind_instruction(bb, block(a, (Block) { .yield_types = add_qualifiers(a, ctx2.yield_types, false), .inside = generate_decision_tree(&ctx2, root, false, 0, UINT64_MAX) })); // Check if we need to run the default case - Nodes final_results = gen_if(bb, ctx2.yield_types, gen_load(bb, run_default_case), rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), case_(a, empty(a), yield(a, (Yield) { - .args = matched_results, - }))); + Nodes final_results = gen_if(bb, ctx2.yield_types, gen_load(bb, run_default_case), rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), case_(a, empty(a), gen_yield(ctx, true, matched_results))); destroy_arena(arena); return yield_values_and_wrap_in_block(bb, final_results); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 5ed77e2e1..c82b02381 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -349,7 +349,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { .callee = fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), .args = nodes(a, 0, NULL) })); - const Node* if_true_lam = case_(a, empty(a), finish_body(if_builder, yield(a, (Yield) {.args = nodes(a, 0, NULL)}))); + const Node* if_true_lam = case_(a, empty(a), finish_body(if_builder, merge_selection(a, (MergeSelection) {.args = nodes(a, 0, NULL)}))); BodyBuilder* case_builder = begin_body(a); gen_if(case_builder, empty(a), should_run, if_true_lam, NULL); const Node* case_lam = case_(a, nodes(a, 0, NULL), finish_body(case_builder, continue_terminator)); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index b467e0628..6864eb3be 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -509,7 +509,9 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod break; case Terminator_MergeBreak_TAG: break; - case Terminator_Yield_TAG: + case Terminator_MergeSelection_TAG: + break; + case Terminator_BlockYield_TAG: break; case Terminator_Return_TAG: mark_values_as_escaping(ctx, kb, old->payload.fn_ret.args); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index b151ceed8..246391f05 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -263,7 +263,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad // Wrap the tail in a guarded if, to handle 'far' joins const Node* level_value = gen_load(bb2, ctx->level_ptr); const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); - const Node* true_body = structure(ctx, old_tail, yield(a, (Yield) { .args = empty(a) })); + const Node* true_body = structure(ctx, old_tail, merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); gen_if(bb2, empty(a), guard, if_true_lam, NULL); @@ -285,10 +285,10 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case Branch_TAG: { const Node* condition = rewrite_node(&ctx->rewriter, body->payload.branch.branch_condition); - const Node* true_body = handle_bb_callsite(ctx, abs, body->payload.branch.true_jump, yield(a, (Yield) { .args = empty(a) })); + const Node* true_body = handle_bb_callsite(ctx, abs, body->payload.branch.true_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); - const Node* false_body = handle_bb_callsite(ctx, abs, body->payload.branch.false_jump, yield(a, (Yield) { .args = empty(a) })); + const Node* false_body = handle_bb_callsite(ctx, abs, body->payload.branch.false_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* if_false_lam = case_(a, empty(a), false_body); BodyBuilder* bb = begin_body(a); @@ -298,12 +298,12 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case Switch_TAG: { const Node* switch_value = rewrite_node(&ctx->rewriter, body->payload.br_switch.switch_value); - const Node* default_body = handle_bb_callsite(ctx, abs, body->payload.br_switch.default_jump, yield(a, (Yield) { .args = empty(a) })); + const Node* default_body = handle_bb_callsite(ctx, abs, body->payload.br_switch.default_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* default_case = case_(a, empty(a), default_body); LARRAY(const Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { - cases[i] = case_(a, empty(a), handle_bb_callsite(ctx, abs, body->payload.br_switch.case_jumps.nodes[i], yield(a, (Yield) {.args = empty(a)}))); + cases[i] = case_(a, empty(a), handle_bb_callsite(ctx, abs, body->payload.br_switch.case_jumps.nodes[i], merge_selection(a, (MergeSelection) {.args = empty(a)}))); } BodyBuilder* bb = begin_body(a); @@ -331,9 +331,10 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case TailCall_TAG: longjmp(ctx->bail, 1); + case Terminator_BlockYield_TAG: case Terminator_MergeBreak_TAG: case Terminator_MergeContinue_TAG: - case Yield_TAG: error("Only control nodes are tolerated here.") + case Terminator_MergeSelection_TAG: error("Only control nodes are tolerated here.") } } diff --git a/src/shady/print.c b/src/shady/print.c index cc90cff63..e8b08b1fd 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -784,11 +784,18 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { break; case MergeContinue_TAG: case MergeBreak_TAG: - case Terminator_Yield_TAG: + case Terminator_MergeSelection_TAG: printf(BGREEN); printf("%s", node_tags[node->tag]); printf(RESET); - print_args_list(ctx, node->payload.yield.args); + print_args_list(ctx, node->payload.merge_selection.args); + printf(";"); + break; + case Terminator_BlockYield_TAG: + printf(BGREEN); + printf("%s", node_tags[node->tag]); + printf(RESET); + print_args_list(ctx, node->payload.block_yield.args); printf(";"); break; } diff --git a/src/shady/type.c b/src/shady/type.c index c02cccd07..fb54f5211 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1279,7 +1279,12 @@ const Type* check_type_merge_break(IrArena* arena, MergeBreak mc) { return noret_type(arena); } -const Type* check_type_yield(IrArena* arena, SHADY_UNUSED Yield payload) { +const Type* check_type_merge_selection(IrArena* arena, SHADY_UNUSED MergeSelection payload) { + // TODO check it + return noret_type(arena); +} + +const Type* check_type_block_yield(IrArena* arena, SHADY_UNUSED BlockYield payload) { // TODO check it return noret_type(arena); } diff --git a/test/control_flow1.slim b/test/control_flow1.slim index 24003e571..9d8d3f03e 100644 --- a/test/control_flow1.slim +++ b/test/control_flow1.slim @@ -1,9 +1,9 @@ @Exported fn extend varying i32(varying bool b) { val extended = if i32 (b) { - yield(1); + merge_selection(1); } else { - yield(0); + merge_selection(0); } return (extended); } From c948c526d48d0bdf9c325beaf5078a31cae47857 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 12:07:58 +0200 Subject: [PATCH 354/693] renamed Branch.condition --- include/shady/grammar.json | 2 +- src/backend/spirv/emit_spv.c | 2 +- src/frontend/llvm/l2s_instr.c | 2 +- src/frontend/slim/parser.c | 2 +- src/frontend/spirv/s2s.c | 2 +- src/shady/passes/lower_cf_instrs.c | 2 +- src/shady/passes/opt_restructure.c | 2 +- src/shady/print.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 63c0e478b..d4ede2234 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -491,7 +491,7 @@ "Branch alternatives are made out of Jump terminators" ], "ops": [ - { "name": "branch_condition", "class": "value" }, + { "name": "condition", "class": "value" }, { "name": "true_jump", "class": "jump" }, { "name": "false_jump", "class": "jump" } ] diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 1f66a09a2..f77e76d90 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -209,7 +209,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo return; } case Branch_TAG: { - SpvId condition = emit_value(emitter, basic_block_builder, terminator->payload.branch.branch_condition); + SpvId condition = emit_value(emitter, basic_block_builder, terminator->payload.branch.condition); add_branch_phis(emitter, fn_builder, basic_block_builder, terminator->payload.branch.true_jump); add_branch_phis(emitter, fn_builder, basic_block_builder, terminator->payload.branch.false_jump); spvb_branch_conditional(basic_block_builder, condition, find_reserved_id(emitter, terminator->payload.branch.true_jump->payload.jump.target), find_reserved_id(emitter, terminator->payload.branch.false_jump->payload.jump.target)); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 936454c1e..0924b040f 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -160,7 +160,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Node* condition = convert_value(p, LLVMGetCondition(instr)); return (EmittedInstr) { .terminator = branch(a, (Branch) { - .branch_condition = condition, + .condition = condition, .true_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0]), .false_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[1]), }) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 6c401995e..f9f0bc3de 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -784,7 +784,7 @@ static const Node* accept_terminator(ctxparams, Node* fn) { Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx) : nodes(arena, 0, NULL); return branch(arena, (Branch) { - .branch_condition = condition, + .condition = condition, .true_jump = true_target, .false_jump = false_target, }); diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index ef3eb1408..b0d2ced9a 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1292,7 +1292,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->current_block.finished = finish_body(bb, branch(parser->arena, (Branch) { .true_jump = jump_helper(parser->arena, get_def_block(parser, destinations[0]), get_args_from_phi(parser, destinations[0], parser->current_block.id)), .false_jump = jump_helper(parser->arena, get_def_block(parser, destinations[1]), get_args_from_phi(parser, destinations[1], parser->current_block.id)), - .branch_condition = get_def_ssa_value(parser, instruction[1]), + .condition = get_def_ssa_value(parser, instruction[1]), })); parser->current_block.builder = NULL; break; diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index f0ea1da7e..4a16b938b 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -52,7 +52,7 @@ static const Node* process_instruction(Context* ctx, const Node* old_instruction } const Node* control_body = branch(a, (Branch) { - .branch_condition = rewrite_node(&ctx->rewriter, old_instruction->payload.if_instr.condition), + .condition = rewrite_node(&ctx->rewriter, old_instruction->payload.if_instr.condition), .true_jump = jump_helper(a, true_block, empty(a)), .false_jump = jump_helper(a, flse_block, empty(a)), }); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 246391f05..2a3dfda78 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -283,7 +283,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad // becomes // let(if(cond, _ => handle_bb_callsite[true_bb, args], _ => handle_bb_callsite[false_bb, args]), _ => unreachable) case Branch_TAG: { - const Node* condition = rewrite_node(&ctx->rewriter, body->payload.branch.branch_condition); + const Node* condition = rewrite_node(&ctx->rewriter, body->payload.branch.condition); const Node* true_body = handle_bb_callsite(ctx, abs, body->payload.branch.true_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); diff --git a/src/shady/print.c b/src/shady/print.c index e8b08b1fd..210330fcd 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -739,7 +739,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf("branch "); printf(RESET); printf("("); - print_node(node->payload.branch.branch_condition); + print_node(node->payload.branch.condition); printf(", "); print_jump(ctx, node->payload.branch.true_jump); printf(", "); From 9fa0c45d0a74b2f2ec918c438ec41518ba07f52a Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 12:08:36 +0200 Subject: [PATCH 355/693] fold: port If rules to unstructured Branch --- src/shady/fold.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/shady/fold.c b/src/shady/fold.c index c9c6915fd..f1bb08485 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -371,6 +371,12 @@ static bool is_unreachable_case(const Node* c) { return b->tag == Unreachable_TAG; } +static bool is_unreachable_destination(const Node* j) { + assert(j && j->tag == Jump_TAG); + const Node* b = get_abstraction_body(j->payload.jump.target); + return b->tag == Unreachable_TAG; +} + const Node* fold_node(IrArena* arena, const Node* node) { const Node* const original_node = node; node = fold_memory_poison(arena, node); @@ -408,20 +414,21 @@ const Node* fold_node(IrArena* arena, const Node* node) { } break; } - /*case If_TAG: { - If payload = node->payload.if_instr; - const Node* false_case = payload.if_false; - if (arena->config.optimisations.delete_unreachable_structured_cases && false_case && is_unreachable_case(false_case)) - return block(arena, (Block) { .inside = payload.if_true, .yield_types = add_qualifiers(arena, payload.yield_types, false) }); + case Branch_TAG: { + Branch payload = node->payload.branch; if (arena->config.optimisations.fold_static_control_flow) { if (payload.condition == true_lit(arena)) { - return block(arena, (Block) { .inside = payload.if_true, .yield_types = add_qualifiers(arena, payload.yield_types, false) }); - } else if (payload.condition == false_lit(arena) && false_case) { - return block(arena, (Block) { .inside = false_case, .yield_types = add_qualifiers(arena, payload.yield_types, false) }); + return payload.true_jump; + } else if (payload.condition == false_lit(arena)) { + return payload.false_jump; } + } else if (arena->config.optimisations.delete_unreachable_structured_cases) { + if (is_unreachable_destination(payload.true_jump)) + return payload.false_jump; + else if (is_unreachable_destination(payload.false_jump)) + return payload.true_jump; } - break; - }*/ + } case Match_TAG: { if (!arena->config.optimisations.delete_unreachable_structured_cases) break; From 03322b7e537bbdcbd77f80d5b53efbbcb91d3cbe Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 12:31:28 +0200 Subject: [PATCH 356/693] move cf helpers to ir.h --- include/shady/ir.h | 5 +++++ src/shady/body_builder.c | 16 ++++++++++++++++ src/shady/transform/ir_gen_helpers.c | 16 ---------------- src/shady/transform/ir_gen_helpers.h | 7 ------- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 3ee3b09ba..fe7ee9077 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -287,6 +287,11 @@ BodyBuilder* begin_body(IrArena*); Nodes bind_instruction(BodyBuilder*, const Node* instruction); Nodes bind_instruction_named(BodyBuilder*, const Node* instruction, String const output_names[]); +Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, const Node*); +Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, const Node*); +Nodes gen_loop(BodyBuilder*, Nodes, Nodes, const Node*); +Nodes gen_control(BodyBuilder*, Nodes, const Node*); + /// Like append instruction, but you explicitly give it information about any yielded values /// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! Nodes bind_instruction_explicit_result_types(BodyBuilder*, const Node* initial_value, Nodes provided_types, String const output_names[]); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index a38f0ca14..d42c03923 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -158,6 +158,22 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* return bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, instruction, NULL); } +Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { + return bind_instruction_outputs_count(bb, if_instr(bb->arena, (If) { .condition = condition, .yield_types = yield_types, .if_true = true_case, .if_false = false_case }), yield_types.count, NULL); +} + +Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, const Node* default_case) { + return bind_instruction_outputs_count(bb, match_instr(bb->arena, (Match) { .yield_types = yield_types, .inspect = inspectee, .literals = literals, .cases = cases, .default_case = default_case }), yield_types.count, NULL); +} + +Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Node* body) { + return bind_instruction_outputs_count(bb, loop_instr(bb->arena, (Loop) { .yield_types = yield_types, .initial_args = initial_args, .body = body }), yield_types.count, NULL); +} + +Nodes gen_control(BodyBuilder* bb, Nodes yield_types, const Node* body) { + return bind_instruction_outputs_count(bb, control(bb->arena, (Control) { .yield_types = yield_types, .inside = body }), yield_types.count, NULL); +} + void cancel_body(BodyBuilder* bb) { destroy_list(bb->stack); free(bb); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 1977d6020..0c428ae56 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -242,22 +242,6 @@ const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, cons return val; } -Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { - return bind_instruction(bb, if_instr(bb->arena, (If) { .condition = condition, .yield_types = yield_types, .if_true = true_case, .if_false = false_case })); -} - -Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, const Node* default_case) { - return bind_instruction(bb, match_instr(bb->arena, (Match) { .yield_types = yield_types, .inspect = inspectee, .literals = literals, .cases = cases, .default_case = default_case })); -} - -Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Node* body) { - return bind_instruction(bb, loop_instr(bb->arena, (Loop) { .yield_types = yield_types, .initial_args = initial_args, .body = body })); -} - -Nodes gen_control(BodyBuilder* bb, Nodes yield_types, const Node* body) { - return bind_instruction(bb, control(bb->arena, (Control) { .yield_types = yield_types, .inside = body })); -} - const Node* get_default_zero_value(IrArena* a, const Type* t) { switch (is_type(t)) { case NotAType: error("") diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 64eea88a4..7c928bccb 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -30,13 +30,6 @@ const Node* get_builtin(Module* m, Builtin b); const Node* get_or_create_builtin(Module* m, Builtin b, String n); const Node* gen_builtin_load(Module*, BodyBuilder*, Builtin); -Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, const Node*); - -Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, const Node*); -Nodes gen_loop(BodyBuilder*, Nodes, Nodes, const Node*); - -Nodes gen_control(BodyBuilder*, Nodes, const Node*); - typedef struct Rewriter_ Rewriter; const Node* find_or_process_decl(Rewriter*, const char* name); From fc73498ca1b0690f3bffe0769678d04202e80a7d Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 12:37:58 +0200 Subject: [PATCH 357/693] removed 'fn' operand from Return node --- include/shady/grammar.json | 1 - src/frontend/llvm/l2s_instr.c | 1 - src/frontend/slim/parser.c | 1 - src/frontend/spirv/s2s.c | 1 - src/shady/passes/bind.c | 1 - src/shady/passes/infer.c | 5 +++-- src/shady/passes/lower_generic_ptrs.c | 4 ++-- src/shady/passes/lower_physical_ptrs.c | 4 ++-- src/shady/passes/lower_stack.c | 4 ++-- src/shady/passes/lower_subgroup_ops.c | 1 - src/shady/passes/lower_tailcalls.c | 8 +++----- src/shady/passes/lower_workgroups.c | 2 +- 12 files changed, 13 insertions(+), 20 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index d4ede2234..67de27fc1 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -554,7 +554,6 @@ "snake_name": "fn_ret", "class": "terminator", "ops": [ - { "name": "fn", "class": "declaration" }, { "name": "args", "class": "value", "list": true } ] }, diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 0924b040f..0f61f2ba3 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -146,7 +146,6 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, switch (opcode) { case LLVMRet: return (EmittedInstr) { .terminator = fn_ret(a, (Return) { - .fn = NULL, .args = num_ops == 0 ? empty(a) : convert_operands(p, num_ops, instr) }) }; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index f9f0bc3de..71291ab0f 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -826,7 +826,6 @@ static const Node* accept_terminator(ctxparams, Node* fn) { next_token(tokenizer); Nodes args = expect_operands(ctx); return fn_ret(arena, (Return) { - .fn = NULL, .args = args }); } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index b0d2ced9a..38eaab05e 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1306,7 +1306,6 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { args = singleton(get_def_ssa_value(parser, instruction[1])); BodyBuilder* bb = parser->current_block.builder; parser->current_block.finished = finish_body(bb, fn_ret(parser->arena, (Return) { - .fn = parser->fun, .args = args, })); parser->current_block.builder = NULL; diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index ba3de42a6..14055ca60 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -288,7 +288,6 @@ static const Node* bind_node(Context* ctx, const Node* node) { case Return_TAG: { assert(ctx->current_function); return fn_ret(a, (Return) { - .fn = ctx->current_function, .args = rewrite_nodes(&ctx->rewriter, node->payload.fn_ret.args) }); } diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 2be7ffe3a..885ee8528 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -28,6 +28,7 @@ static Nodes annotate_all_types(IrArena* a, Nodes types, bool uniform_by_default typedef struct { Rewriter rewriter; + const Node* current_fn; const Type* expected_type; const Nodes* merge_types; @@ -111,6 +112,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { Nodes nret_types = annotate_all_types(a, infer_nodes(ctx, node->payload.fun.return_types), false); Node* fun = function(ctx->rewriter.dst_module, nodes(a, node->payload.fun.params.count, nparams), string(a, node->payload.fun.name), infer_nodes(ctx, node->payload.fun.annotations), nret_types); register_processed(&ctx->rewriter, node, fun); + body_context.current_fn = fun; fun->payload.fun.body = infer(&body_context, node->payload.fun.body, NULL); return fun; } @@ -628,7 +630,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { return let(a, inferred_instruction, nvars, infer_case(ctx, node->payload.let.tail, empty(a))); } case Return_TAG: { - const Node* imported_fn = infer(ctx, node->payload.fn_ret.fn, NULL); + const Node* imported_fn = ctx->current_fn; Nodes return_types = imported_fn->payload.fun.return_types; const Nodes* old_values = &node->payload.fn_ret.args; @@ -637,7 +639,6 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { nvalues[i] = infer(ctx, old_values->nodes[i], return_types.nodes[i]); return fn_ret(a, (Return) { .args = nodes(a, old_values->count, nvalues), - .fn = NULL }); } case Jump_TAG: { diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 498c165bc..2ce8427de 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -121,7 +121,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), case_(a, empty(a), unreachable(a)))); - new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value), .fn = new_fn })); + new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value) })); break; } case StoreFn: { @@ -147,7 +147,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), case_(a, empty(a), unreachable(a))); - new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .fn = new_fn })); + new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); break; } } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 2835cb1ee..e86e3892f 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -281,11 +281,11 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { gen_serialisation(ctx, bb, element_type, base, address, value_param); - fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .fn = fun, .args = empty(a) })); + fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); } else { const Node* loaded_value = gen_deserialisation(ctx, bb, element_type, base, address); assert(loaded_value); - fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .fn = fun, .args = singleton(loaded_value) })); + fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value) })); } return fun; } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index c49e85010..54f3040cc 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -81,10 +81,10 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { } if (push) { - fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .fn = fun, .args = empty(a) })); + fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); } else { assert(popped_value); - fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .fn = fun, .args = singleton(popped_value) })); + fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(popped_value) })); } return fun; } diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 1ce129041..0f0314371 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -86,7 +86,6 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* const Node* result = generate(ctx, bb, t, param); if (result) { fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { - .fn = fn, .args = singleton(result) })); return; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index c82b02381..37cf9d0f8 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -88,7 +88,6 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { })); new_entry_pt->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { - .fn = NULL, .args = nodes(a, 0, NULL) })); } @@ -206,7 +205,7 @@ static const Node* process(Context* ctx, const Node* old) { .args = nodes(a, 1, (const Node*[]) { target }) }); bind_instruction(bb, fork_call); - return finish_body(bb, fn_ret(a, (Return) { .fn = NULL, .args = nodes(a, 0, NULL) })); + return finish_body(bb, fn_ret(a, (Return) { .args = nodes(a, 0, NULL) })); } case Join_TAG: { //if (ctx->disable_lowering) @@ -230,7 +229,7 @@ static const Node* process(Context* ctx, const Node* old) { .args = mk_nodes(a, dst, tree_node) }); bind_instruction(bb, join_call); - return finish_body(bb, fn_ret(a, (Return) { .fn = NULL, .args = nodes(a, 0, NULL) })); + return finish_body(bb, fn_ret(a, (Return) { .args = nodes(a, 0, NULL) })); } case PtrType_TAG: { const Node* pointee = old->payload.ptr_type.pointed_type; @@ -375,7 +374,6 @@ void generate_top_level_dispatch_fn(Context* ctx) { (*ctx->top_dispatcher_fn)->payload.fun.body = finish_body(dispatcher_body_builder, fn_ret(a, (Return) { .args = nodes(a, 0, NULL), - .fn = *ctx->top_dispatcher_fn, })); } @@ -390,7 +388,7 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) struct Dict* ptrs = new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); Node* init_fn = function(dst, nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" }), annotation(a, (Annotation) { .name = "Structured" })), nodes(a, 0, NULL)); - init_fn->payload.fun.body = fn_ret(a, (Return) { .fn = init_fn, .args = empty(a) }); + init_fn->payload.fun.body = fn_ret(a, (Return) { .args = empty(a) }); FnPtr next_fn_ptr = 1; diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 380533f93..1c872ce6d 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -135,7 +135,7 @@ static const Node* process(Context* ctx, const Node* node) { } bind_instruction(bb, instr); - wrapper->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .fn = wrapper, .args = empty(a) })); + wrapper->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); return wrapper; } return recreate_node_identity(&ctx2.rewriter, node); From 81fb95684e7171624d35fcf364ec553835b12b17 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 12:46:06 +0200 Subject: [PATCH 358/693] removed 'fn' operand from BasicBlock --- include/shady/grammar.json | 1 - include/shady/ir.h | 2 +- src/frontend/llvm/l2s.c | 2 +- src/frontend/llvm/l2s_instr.c | 2 +- src/frontend/llvm/l2s_postprocess.c | 7 +------ src/frontend/slim/parser.c | 2 +- src/frontend/spirv/s2s.c | 2 +- src/shady/constructors.c | 4 +--- src/shady/passes/bind.c | 4 ++-- src/shady/passes/infer.c | 3 +-- src/shady/passes/lower_cf_instrs.c | 6 +++--- src/shady/passes/normalize.c | 2 +- src/shady/passes/opt_inline.c | 8 +------- src/shady/passes/opt_mem2reg.c | 5 ++--- src/shady/passes/opt_restructure.c | 4 ++-- src/shady/passes/reconvergence_heuristics.c | 14 +++++++------- src/shady/print.c | 1 - src/shady/rewrite.c | 3 +-- 18 files changed, 27 insertions(+), 45 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 67de27fc1..82f41d8d0 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -657,7 +657,6 @@ "ops": [ { "name": "params", "class": "param", "list": true }, { "name": "body", "class": "terminator" }, - { "name": "fn", "class": "declaration" }, { "name": "name", "class": "string" } ] }, diff --git a/include/shady/ir.h b/include/shady/ir.h index fe7ee9077..7c810500b 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -275,7 +275,7 @@ Node* global_var (Module*, Nodes annotations, const Type*, String, AddressSpace Type* nominal_type(Module*, Nodes annotations, String name); // basic blocks, lambdas and their helpers -Node* basic_block(IrArena*, Node* function, Nodes params, const char* name); +Node* basic_block(IrArena*, Nodes params, const char* name); const Node* case_(IrArena* a, Nodes params, const Node* body); /// Used to build a chain of let diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 0be85afbe..03dd1a36b 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -101,7 +101,7 @@ static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { String name = LLVMGetBasicBlockName(bb); if (strlen(name) == 0) name = NULL; - Node* nbb = basic_block(a, fn_ctx->fn, params, name); + Node* nbb = basic_block(a, params, name); insert_dict(LLVMValueRef, const Node*, p->map, bb, nbb); insert_dict(const Node*, struct List*, fn_ctx->phis, nbb, phis); TodoBB todo = { diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 0f61f2ba3..82e9e7ec9 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -58,7 +58,7 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef dst) { IrArena* a = fn_or_bb->arena; - Node* wrapper_bb = basic_block(a, fn_ctx->fn, empty(a), NULL); + Node* wrapper_bb = basic_block(a, empty(a), NULL); JumpTodo todo = { .wrapper = wrapper_bb, .src = fn_or_bb, diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 64a6f727f..79e8ed01b 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -237,12 +237,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } Nodes nparams = remake_params(ctx, get_abstraction_params(dst)); //register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); - Node* fn = (Node*) src; - if (fn->tag == BasicBlock_TAG) - fn = (Node*) fn->payload.basic_block.fn; - assert(fn->tag == Function_TAG); - fn = (Node*) rewrite_node(r, fn); - Node* wrapper = basic_block(a, fn, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); + Node* wrapper = basic_block(a, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); wrapper->payload.basic_block.body = join(a, (Join) { .args = nparams, .join_point = join_token diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 71291ab0f..ef9e8c763 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -904,7 +904,7 @@ static const Node* expect_body(ctxparams, Node* fn, const Node* default_terminat Nodes parameters; expect_parameters(ctx, ¶meters, NULL); - Node* continuation = basic_block(arena, fn, parameters, name); + Node* continuation = basic_block(arena, parameters, name); continuation->payload.basic_block.body = expect_body(ctx, fn, NULL); append_list(Node*, conts, continuation); } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 38eaab05e..29d8b197b 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -895,7 +895,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].type = BB; String bb_name = get_name(parser, result); bb_name = bb_name ? bb_name : unique_name(parser->arena, "basic_block"); - Node* block = basic_block(parser->arena, parser->fun, params, bb_name); + Node* block = basic_block(parser->arena, params, bb_name); parser->defs[result].node = block; BodyBuilder* bb = begin_body(parser->arena); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 129ea1608..16729046b 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -208,12 +208,10 @@ Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, N return fn; } -Node* basic_block(IrArena* arena, Node* fn, Nodes params, const char* name) { - assert(!fn->payload.fun.module->sealed); +Node* basic_block(IrArena* arena, Nodes params, const char* name) { BasicBlock payload = { .params = params, .body = NULL, - .fn = fn, .name = name, }; diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 14055ca60..9ce6fe5a3 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -223,7 +223,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { const Node* old_bb = unbound_blocks.nodes[i]; assert(is_basic_block(old_bb)); Nodes new_bb_params = recreate_params(&ctx->rewriter, old_bb->payload.basic_block.params); - Node* new_bb = basic_block(a, (Node*) ctx->current_function, new_bb_params, old_bb->payload.basic_block.name); + Node* new_bb = basic_block(a, new_bb_params, old_bb->payload.basic_block.name); new_bbs[i] = new_bb; add_binding(ctx, false, old_bb->payload.basic_block.name, new_bb); register_processed(&ctx->rewriter, old_bb, new_bb); @@ -251,7 +251,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { case BasicBlock_TAG: { assert(is_basic_block(node)); Nodes new_bb_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); - Node* new_bb = basic_block(a, (Node*) ctx->current_function, new_bb_params, node->payload.basic_block.name); + Node* new_bb = basic_block(a, new_bb_params, node->payload.basic_block.name); Context bb_ctx = *ctx; ctx = &bb_ctx; add_binding(ctx, false, node->payload.basic_block.name, new_bb); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 885ee8528..0e353d4e4 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -335,8 +335,7 @@ static const Node* _infer_basic_block(Context* ctx, const Node* node) { register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); } - Node* fn = (Node*) infer(ctx, node->payload.basic_block.fn, NULL); - Node* bb = basic_block(a, fn, nodes(a, node->payload.basic_block.params.count, nparams), node->payload.basic_block.name); + Node* bb = basic_block(a, nodes(a, node->payload.basic_block.params.count, nparams), node->payload.basic_block.name); assert(bb); register_processed(&ctx->rewriter, node, bb); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 4a16b938b..536f69b40 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -38,11 +38,11 @@ static const Node* process_instruction(Context* ctx, const Node* old_instruction Nodes jps = singleton(jp); insert_dict(const Node*, Nodes, ctx->structured_join_tokens, old_instruction, jps); - Node* true_block = basic_block(a, ctx->current_fn, nodes(a, 0, NULL), unique_name(a, "if_true")); + Node* true_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_true")); join_context.abs = old_instruction->payload.if_instr.if_true; true_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, old_instruction->payload.if_instr.if_true->payload.case_.body); - Node* flse_block = basic_block(a, ctx->current_fn, nodes(a, 0, NULL), unique_name(a, "if_false")); + Node* flse_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_false")); if (has_false_branch) { join_context.abs = old_instruction->payload.if_instr.if_false; flse_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, old_instruction->payload.if_instr.if_false->payload.case_.body); @@ -84,7 +84,7 @@ static const Node* process_instruction(Context* ctx, const Node* old_instruction insert_dict(const Node*, Nodes, ctx->structured_join_tokens, old_instruction, jps); Nodes new_params = recreate_params(&ctx->rewriter, old_loop_body->payload.case_.params); - Node* loop_body = basic_block(a, ctx->current_fn, new_params, unique_name(a, "loop_body")); + Node* loop_body = basic_block(a, new_params, unique_name(a, "loop_body")); register_processed_list(&join_context.rewriter, old_loop_body->payload.case_.params, loop_body->payload.basic_block.params); join_context.abs = old_loop_body; diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index ee8aa5042..b32ea36cc 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -111,7 +111,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return new; } case BasicBlock_TAG: { - Node* new = basic_block(a, (Node*) rewrite_node(&ctx->rewriter, node->payload.basic_block.fn), recreate_params(&ctx->rewriter, node->payload.basic_block.params), node->payload.basic_block.name); + Node* new = basic_block(a, recreate_params(&ctx->rewriter, node->payload.basic_block.params), node->payload.basic_block.name); register_processed(&ctx->rewriter, node, new); register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new->payload.basic_block.params); BodyBuilder* bb = begin_body(a); diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 5fc36f923..aec253cd4 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -194,15 +194,9 @@ static const Node* process(Context* ctx, const Node* node) { break; } case BasicBlock_TAG: { - const Node* ofn = node->payload.basic_block.fn; - const Node* nfn; - if (ctx->inlined_call) - nfn = ctx->inlined_call->host_fn; - else - nfn = rewrite_node(r, ofn); Nodes nparams = recreate_params(r, get_abstraction_params(node)); register_processed_list(r, get_abstraction_params(node), nparams); - Node* bb = basic_block(a, (Node*) nfn, nparams, get_abstraction_name(node)); + Node* bb = basic_block(a, nparams, get_abstraction_name(node)); register_processed(r, node, bb); bb->payload.basic_block.body = rewrite_node(r, get_abstraction_body(node)); return bb; diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 6864eb3be..9d038a241 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -484,7 +484,7 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod Nodes args = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); String s = get_abstraction_name_unsafe(old_target); - Node* wrapper = basic_block(a, (Node*) rewrite_node(r, old_target->payload.basic_block.fn), recreate_params(r, get_abstraction_params(old_target)), s); + Node* wrapper = basic_block(a, recreate_params(r, get_abstraction_params(old_target)), s); TodoJump todo = { .old_jump = old, .wrapper_bb = wrapper, @@ -610,8 +610,7 @@ static void handle_bb(Context* ctx, const Node* old) { next_potential_param: continue; } - Node* fn = (Node*) rewrite_node(&ctx->rewriter, ctx->cfg->entry->node); - Node* new_bb = basic_block(a, fn, params, get_abstraction_name_unsafe(old)); + Node* new_bb = basic_block(a, params, get_abstraction_name_unsafe(old)); register_processed(&ctx->rewriter, old, new_bb); new_bb->payload.basic_block.body = finish_body(bb, nbody); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 2a3dfda78..5393489d9 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -134,7 +134,7 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* caller, const No // We use a basic block for the exit ladder because we don't know what the ladder needs to do ahead of time // opt_simplify_cf will later inline this - Node* inner_exit_ladder_bb = basic_block(a, ctx->fn, empty(a), unique_name(a, "exit_ladder_inline_me")); + Node* inner_exit_ladder_bb = basic_block(a, empty(a), unique_name(a, "exit_ladder_inline_me")); // Just jumps to the actual ladder const Node* exit_ladder_trampoline = case_(a, empty(a), jump(a, (Jump) {.target = inner_exit_ladder_bb, .args = empty(a)})); @@ -153,7 +153,7 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* caller, const No inner_exit_ladder_bb->payload.basic_block.body = merge_break(a, (MergeBreak) { .args = empty(a) }); return finish_body(bb, exit_ladder); } else { - Node* bb2 = basic_block(a, ctx->fn, nodes(a, oargs.count, nparams), NULL); + Node* bb2 = basic_block(a, nodes(a, oargs.count, nparams), NULL); bb2->payload.basic_block.body = structured; //bind_variables(bb, nodes(a, oargs.count, nparams), rewrite_nodes(&ctx->rewriter, oargs)); inner_exit_ladder_bb->payload.basic_block.body = exit_ladder; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index d0e03c898..1f124d3de 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -166,7 +166,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(const Node*, exit_wrappers, exiting_nodes_count); LARRAY(Node*, exit_helpers, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { - exit_helpers[i] = basic_block(arena, fn, empty(arena), format_string_arena(arena->arena, "exit_helper_%d", i)); + exit_helpers[i] = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_helper_%d", i)); CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); @@ -174,7 +174,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { switch (exiting_node->node->tag) { case BasicBlock_TAG: { - Node* pre_join_exit_bb = basic_block(arena, fn, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); + Node* pre_join_exit_bb = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); pre_join_exit_bb->payload.basic_block.body = jump_helper(arena, exit_helpers[i], empty(arena)); exit_wrappers[i] = pre_join_exit_bb; break; @@ -195,7 +195,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { const Node* continue_wrapper; switch (node->tag) { case BasicBlock_TAG: { - Node* pre_join_continue_bb = basic_block(arena, fn, continue_wrapper_params, "continue"); + Node* pre_join_continue_bb = basic_block(arena, continue_wrapper_params, "continue"); pre_join_continue_bb->payload.basic_block.body = continue_wrapper_body; continue_wrapper = pre_join_continue_bb; break; @@ -274,7 +274,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { BodyBuilder* inner_bb = begin_body(arena); Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, case_(arena, singleton(join_token_continue), loop_body)); - Node* loop_outer = basic_block(arena, fn, inner_loop_params, "loop_outer"); + Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); loop_outer->payload.basic_block.body = finish_body(inner_bb, jump(arena, (Jump) { .target = loop_outer, @@ -304,7 +304,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { recovered_args[j] = gen_load(exit_recover_bb, exit_param_allocas[i].nodes[j]); exit_numbers[i] = int32_literal(arena, i); - Node* exit_bb = basic_block(arena, fn, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); + Node* exit_bb = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); if (recreated_exit->tag == BasicBlock_TAG) { exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, jump(arena, (Jump) { .target = recreated_exit, @@ -337,7 +337,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { const Node* loop_container; switch (node->tag) { case BasicBlock_TAG: { - Node* bb = basic_block(arena, fn, nparams, node->payload.basic_block.name); + Node* bb = basic_block(arena, nparams, node->payload.basic_block.name); bb->payload.basic_block.body = outer_body; loop_container = bb; break; @@ -483,7 +483,7 @@ static const Node* process_node(Context* ctx, const Node* node) { .yield_types = yield_types }), true), "jp_postdom"); - Node* pre_join = basic_block(arena, fn, exit_args, format_string_arena(arena->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); + Node* pre_join = basic_block(arena, exit_args, format_string_arena(arena->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); pre_join->payload.basic_block.body = join(arena, (Join) { .join_point = join_token, .args = exit_args diff --git a/src/shady/print.c b/src/shady/print.c index 210330fcd..bbc6d8cfb 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -133,7 +133,6 @@ static void print_basic_block(PrinterCtx* ctx, const Node* bb) { printf(RESET); if (ctx->config.print_ptrs) { printf(" %zu:: ", (size_t)(void*)bb); - printf(" fn=%zu:: ", (size_t)(void*)bb->payload.basic_block.fn); } print_param_list(ctx, bb->payload.basic_block.params, NULL); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 937f2a2a6..477d61b8c 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -405,8 +405,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { case BasicBlock_TAG: { Nodes params = recreate_params(rewriter, node->payload.basic_block.params); register_processed_list(rewriter, node->payload.basic_block.params, params); - const Node* fn = rewrite_op_helper(rewriter, NcDeclaration, "fn", node->payload.basic_block.fn); - Node* bb = basic_block(arena, (Node*) fn, params, node->payload.basic_block.name); + Node* bb = basic_block(arena, params, node->payload.basic_block.name); register_processed(rewriter, node, bb); const Node* nterminator = rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.basic_block.body); bb->payload.basic_block.body = nterminator; From 60266e41e702f62f8b00eb5e2fa1a2ecd2ffdc00 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 12:49:30 +0200 Subject: [PATCH 359/693] slim: no longer thread 'fn' through parser --- src/frontend/slim/parser.c | 48 ++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index ef9e8c763..87afca422 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -80,7 +80,7 @@ static const char* accept_identifier(ctxparams) { return NULL; } -static const Node* expect_body(ctxparams, Node* fn, const Node* default_terminator); +static const Node* expect_body(ctxparams, const Node* default_terminator); static const Node* accept_value(ctxparams); static const Type* accept_unqualified_type(ctxparams); static const Node* accept_expr(ctxparams, int); @@ -582,7 +582,7 @@ static Nodes expect_operands(ctxparams) { return final; } -static const Node* accept_control_flow_instruction(ctxparams, Node* fn) { +static const Node* accept_control_flow_instruction(ctxparams) { Token current_token = curr_token(tokenizer); switch (current_token.tag) { case if_tok: { @@ -594,13 +594,13 @@ static const Node* accept_control_flow_instruction(ctxparams, Node* fn) { expect(accept_token(ctx, rpar_tok)); const Node* merge = config.front_end ? merge_selection(arena, (MergeSelection) { .args = nodes(arena, 0, NULL) }) : NULL; - const Node* if_true = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, fn, merge)); + const Node* if_true = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, merge)); // else defaults to an empty body bool has_else = accept_token(ctx, else_tok); const Node* if_false = NULL; if (has_else) { - if_false = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, fn, merge)); + if_false = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, merge)); } return if_instr(arena, (If) { .yield_types = yield_types, @@ -617,7 +617,7 @@ static const Node* accept_control_flow_instruction(ctxparams, Node* fn) { expect_parameters(ctx, ¶meters, &default_values); // by default loops continue forever const Node* default_loop_end_behaviour = config.front_end ? merge_continue(arena, (MergeContinue) { .args = nodes(arena, 0, NULL) }) : NULL; - const Node* body = case_(arena, parameters, expect_body(ctx, fn, default_loop_end_behaviour)); + const Node* body = case_(arena, parameters, expect_body(ctx, default_loop_end_behaviour)); return loop_instr(arena, (Loop) { .initial_args = default_values, @@ -635,7 +635,7 @@ static const Node* accept_control_flow_instruction(ctxparams, Node* fn) { .yield_types = yield_types, }), str); expect(accept_token(ctx, rpar_tok)); - const Node* body = case_(arena, singleton(jp), expect_body(ctx, fn, NULL)); + const Node* body = case_(arena, singleton(jp), expect_body(ctx, NULL)); return control(arena, (Control) { .inside = body, .yield_types = yield_types @@ -646,13 +646,13 @@ static const Node* accept_control_flow_instruction(ctxparams, Node* fn) { return NULL; } -static const Node* accept_instruction(ctxparams, Node* fn, bool in_list) { +static const Node* accept_instruction(ctxparams, bool in_list) { const Node* instr = accept_expr(ctx, max_precedence()); if (in_list && instr) expect(accept_token(ctx, semi_tok) && "Non-control flow instructions must be followed by a semicolon"); - if (!instr) instr = accept_control_flow_instruction(ctx, fn); + if (!instr) instr = accept_control_flow_instruction(ctx); return instr; } @@ -699,34 +699,34 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* destroy_list(tlist); } -static bool accept_non_terminator_instr(ctxparams, BodyBuilder* bb, Node* fn) { +static bool accept_non_terminator_instr(ctxparams, BodyBuilder* bb) { Strings ids; if (accept_token(ctx, val_tok)) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok)); - const Node* instruction = accept_instruction(ctx, fn, true); + const Node* instruction = accept_instruction(ctx, true); bind_instruction_outputs_count(bb, instruction, ids.count, ids.strings); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok)); - const Node* instruction = accept_instruction(ctx, fn, true); + const Node* instruction = accept_instruction(ctx, true); create_mutable_variables(bb, instruction, types, ids.strings); } else { - const Node* instr = accept_instruction(ctx, fn, true); + const Node* instr = accept_instruction(ctx, true); if (!instr) return false; bind_instruction_outputs_count(bb, instr, 0, NULL); } return true; } -static const Node* accept_case(ctxparams, Node* fn) { +static const Node* accept_case(ctxparams) { if (!accept_token(ctx, lambda_tok)) return NULL; Nodes params; expect_parameters(ctx, ¶ms, NULL); - const Node* body = expect_body(ctx, fn, NULL); + const Node* body = expect_body(ctx, NULL); return case_(arena, params, body); } @@ -749,17 +749,17 @@ static Nodes params2vars(IrArena* arena, const Node* instruction, Nodes params) return nodes(arena, params.count, vars); } -static const Node* accept_terminator(ctxparams, Node* fn) { +static const Node* accept_terminator(ctxparams) { TokenTag tag = curr_token(tokenizer).tag; switch (tag) { case let_tok: { next_token(tokenizer); - const Node* instruction = accept_instruction(ctx, fn, false); + const Node* instruction = accept_instruction(ctx, false); expect(instruction); expect(accept_token(ctx, in_tok)); switch (tag) { case let_tok: { - const Node* lam = accept_case(ctx, fn); + const Node* lam = accept_case(ctx); expect(lam); return let(arena, instruction, params2vars(arena, instruction, get_abstraction_params(lam)), get_abstraction_body(lam)); } @@ -872,17 +872,16 @@ static const Node* accept_terminator(ctxparams, Node* fn) { return NULL; } -static const Node* expect_body(ctxparams, Node* fn, const Node* default_terminator) { - assert(fn->tag == Function_TAG); +static const Node* expect_body(ctxparams, const Node* default_terminator) { expect(accept_token(ctx, lbracket_tok)); BodyBuilder* bb = begin_body(arena); while (true) { - if (!accept_non_terminator_instr(ctx, bb, fn)) + if (!accept_non_terminator_instr(ctx, bb)) break; } - const Node* terminator = accept_terminator(ctx, fn); + const Node* terminator = accept_terminator(ctx); if (terminator) expect(accept_token(ctx, semi_tok)); @@ -899,13 +898,12 @@ static const Node* expect_body(ctxparams, Node* fn, const Node* default_terminat while (true) { if (!accept_token(ctx, cont_tok)) break; - assert(fn); const char* name = accept_identifier(ctx); Nodes parameters; expect_parameters(ctx, ¶meters, NULL); Node* continuation = basic_block(arena, parameters, name); - continuation->payload.basic_block.body = expect_body(ctx, fn, NULL); + continuation->payload.basic_block.body = expect_body(ctx, NULL); append_list(Node*, conts, continuation); } @@ -986,7 +984,7 @@ static const Node* accept_const(ctxparams, Nodes annotations) { const char* id = accept_identifier(ctx); expect(id); expect(accept_token(ctx, equal_tok)); - const Node* definition = accept_instruction(ctx, NULL, false); + const Node* definition = accept_instruction(ctx, false); expect(definition); expect(accept_token(ctx, semi_tok)); @@ -1009,7 +1007,7 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { Node* fn = function(mod, parameters, name, annotations, types); if (!accept_token(ctx, semi_tok)) - fn->payload.fun.body = expect_body(ctx, fn, types.count == 0 ? fn_ret(arena, (Return) { .args = types }) : NULL); + fn->payload.fun.body = expect_body(ctx, types.count == 0 ? fn_ret(arena, (Return) { .args = types }) : NULL); const Node* declaration = fn; expect(declaration); From 54736d96712efd340f885cf02337f8bb54f816e2 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 12:59:40 +0200 Subject: [PATCH 360/693] parser: cleanup --- src/frontend/slim/parser.c | 34 ++++++++++------------------------ src/frontend/slim/token.h | 2 -- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 87afca422..d11b2dab8 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -582,7 +582,7 @@ static Nodes expect_operands(ctxparams) { return final; } -static const Node* accept_control_flow_instruction(ctxparams) { +static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { Token current_token = curr_token(tokenizer); switch (current_token.tag) { case if_tok: { @@ -646,13 +646,13 @@ static const Node* accept_control_flow_instruction(ctxparams) { return NULL; } -static const Node* accept_instruction(ctxparams, bool in_list) { +static const Node* accept_instruction(ctxparams, BodyBuilder* bb) { const Node* instr = accept_expr(ctx, max_precedence()); - if (in_list && instr) + if (instr) expect(accept_token(ctx, semi_tok) && "Non-control flow instructions must be followed by a semicolon"); - if (!instr) instr = accept_control_flow_instruction(ctx); + if (!instr) instr = accept_control_flow_instruction(ctx, bb); return instr; } @@ -699,21 +699,21 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* destroy_list(tlist); } -static bool accept_non_terminator_instr(ctxparams, BodyBuilder* bb) { +static bool accept_statement(ctxparams, BodyBuilder* bb) { Strings ids; if (accept_token(ctx, val_tok)) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok)); - const Node* instruction = accept_instruction(ctx, true); + const Node* instruction = accept_instruction(ctx, bb); bind_instruction_outputs_count(bb, instruction, ids.count, ids.strings); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok)); - const Node* instruction = accept_instruction(ctx, true); + const Node* instruction = accept_instruction(ctx, bb); create_mutable_variables(bb, instruction, types, ids.strings); } else { - const Node* instr = accept_instruction(ctx, true); + const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; bind_instruction_outputs_count(bb, instr, 0, NULL); } @@ -752,20 +752,6 @@ static Nodes params2vars(IrArena* arena, const Node* instruction, Nodes params) static const Node* accept_terminator(ctxparams) { TokenTag tag = curr_token(tokenizer).tag; switch (tag) { - case let_tok: { - next_token(tokenizer); - const Node* instruction = accept_instruction(ctx, false); - expect(instruction); - expect(accept_token(ctx, in_tok)); - switch (tag) { - case let_tok: { - const Node* lam = accept_case(ctx); - expect(lam); - return let(arena, instruction, params2vars(arena, instruction, get_abstraction_params(lam)), get_abstraction_body(lam)); - } - default: SHADY_UNREACHABLE; - } - } case jump_tok: { next_token(tokenizer); return expect_jump(ctx); @@ -877,7 +863,7 @@ static const Node* expect_body(ctxparams, const Node* default_terminator) { BodyBuilder* bb = begin_body(arena); while (true) { - if (!accept_non_terminator_instr(ctx, bb)) + if (!accept_statement(ctx, bb)) break; } @@ -984,7 +970,7 @@ static const Node* accept_const(ctxparams, Nodes annotations) { const char* id = accept_identifier(ctx); expect(id); expect(accept_token(ctx, equal_tok)); - const Node* definition = accept_instruction(ctx, false); + const Node* definition = accept_expr(ctx, max_precedence()); expect(definition); expect(accept_token(ctx, semi_tok)); diff --git a/src/frontend/slim/token.h b/src/frontend/slim/token.h index 08dcd2e67..8afa155e9 100644 --- a/src/frontend/slim/token.h +++ b/src/frontend/slim/token.h @@ -29,8 +29,6 @@ TEXT_TOKEN(generic) \ TEXT_TOKEN(logical) \ TEXT_TOKEN(var) \ TEXT_TOKEN(val) \ -TEXT_TOKEN(let) \ -TEXT_TOKEN(in) \ TEXT_TOKEN(ptr) \ TEXT_TOKEN(ref) \ TEXT_TOKEN(type) \ From c15b86e55dd2a811bdf1a1955c2807cd91e7be45 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 13:01:09 +0200 Subject: [PATCH 361/693] parser: further cleanup --- src/frontend/slim/parser.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index d11b2dab8..445b43e43 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -720,16 +720,6 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { return true; } -static const Node* accept_case(ctxparams) { - if (!accept_token(ctx, lambda_tok)) - return NULL; - - Nodes params; - expect_parameters(ctx, ¶ms, NULL); - const Node* body = expect_body(ctx, NULL); - return case_(arena, params, body); -} - static const Node* expect_jump(ctxparams) { String target = accept_identifier(ctx); expect(target); @@ -740,15 +730,6 @@ static const Node* expect_jump(ctxparams) { }); } -/// for convenience, parse variables as parameters -static Nodes params2vars(IrArena* arena, const Node* instruction, Nodes params) { - LARRAY(const Node*, vars, params.count); - for (size_t i = 0; i < params.count; i++) { - vars[i] = var(arena, params.nodes[i]->payload.param.name, instruction, i); - } - return nodes(arena, params.count, vars); -} - static const Node* accept_terminator(ctxparams) { TokenTag tag = curr_token(tokenizer).tag; switch (tag) { From 9167052cf8565e5e95b2f298995e9f356b959bcf Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 13:10:05 +0200 Subject: [PATCH 362/693] use cf builders in parser --- src/driver/driver.c | 2 +- src/frontend/slim/parser.c | 26 ++++++++------------------ src/shady/passes/bind.c | 1 + 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/driver/driver.c b/src/driver/driver.c index 24de057d5..cd653a689 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -65,7 +65,7 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang ParserConfig pconfig = { .front_end = lang == SrcSlim, }; - debugv_print("Parsing: \n%s\n", file_contents); + debugvv_print("Parsing: \n%s\n", file_contents); *mod = parse_slim_module(config, pconfig, (const char*) file_contents, name); } } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 445b43e43..8c2ca53fc 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -602,28 +602,18 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { if (has_else) { if_false = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, merge)); } - return if_instr(arena, (If) { - .yield_types = yield_types, - .condition = condition, - .if_true = if_true, - .if_false = if_false - }); + return quote_helper(arena, gen_if(bb, yield_types, condition, if_true, if_false)); } case loop_tok: { next_token(tokenizer); Nodes yield_types = accept_types(ctx, 0, NeverQualified); Nodes parameters; - Nodes default_values; - expect_parameters(ctx, ¶meters, &default_values); + Nodes initial_arguments; + expect_parameters(ctx, ¶meters, &initial_arguments); // by default loops continue forever const Node* default_loop_end_behaviour = config.front_end ? merge_continue(arena, (MergeContinue) { .args = nodes(arena, 0, NULL) }) : NULL; const Node* body = case_(arena, parameters, expect_body(ctx, default_loop_end_behaviour)); - - return loop_instr(arena, (Loop) { - .initial_args = default_values, - .yield_types = yield_types, - .body = body - }); + return quote_helper(arena, gen_loop(bb, yield_types, initial_arguments, body)); } case control_tok: { next_token(tokenizer); @@ -636,10 +626,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { }), str); expect(accept_token(ctx, rpar_tok)); const Node* body = case_(arena, singleton(jp), expect_body(ctx, NULL)); - return control(arena, (Control) { - .inside = body, - .yield_types = yield_types - }); + return quote_helper(arena, gen_control(bb, yield_types, body)); } default: break; } @@ -1107,6 +1094,9 @@ Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, co Module** pmod = &m; Module* old_mod = NULL; + debugv_print("Parsed slim module:\n"); + log_module(DEBUGV, config, *pmod); + generate_dummy_constants(config, *pmod); RUN_PASS(bind_program) diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 9ce6fe5a3..81b4e1081 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -271,6 +271,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { } Nodes ovars = node->payload.let.variables; Nodes nvars = recreate_vars(a, ovars, ninstr); + register_processed_list(r, ovars, nvars); for (size_t i = 0; i < nvars.count; i++) add_binding(ctx, false, nvars.nodes[i]->payload.varz.name, nvars.nodes[i]); return finish_body(bb, let(a, ninstr, nvars, rewrite_node(r, get_let_tail(node)))); From e6626bab4546840730f1317250c8c6723642c556 Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 13:33:25 +0200 Subject: [PATCH 363/693] always use the builder variant of cf instrs --- src/frontend/llvm/l2s_postprocess.c | 2 +- src/shady/passes/lower_callf.c | 3 ++- src/shady/passes/lower_cf_instrs.c | 18 +++++++----------- src/shady/passes/lower_tailcalls.c | 7 +++---- src/shady/passes/opt_inline.c | 6 ++---- 5 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 79e8ed01b..0af64e15c 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -216,7 +216,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { - debug_print("We need to introduce a control() block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); + debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); Controls** found = find_value_dict(const Node, Controls*, ctx->controls, dom->node); if (found) { Controls* controls = *found; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index b8a6c9809..5be61e868 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -131,7 +131,8 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .args = nargs, }); const Node* control_lam = case_(a, singleton(jp), control_body); - return control(a, (Control) { .yield_types = strip_qualifiers(a, returned_types), .inside = control_lam }); + BodyBuilder* bb = begin_body(a); + return yield_values_and_wrap_in_block(bb, gen_control(bb, strip_qualifiers(a, returned_types), control_lam)); } default: break; } diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 536f69b40..680cf788d 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -57,8 +57,8 @@ static const Node* process_instruction(Context* ctx, const Node* old_instruction .false_jump = jump_helper(a, flse_block, empty(a)), }); - const Node* control_lam = case_(a, nodes(a, 1, (const Node* []) {jp}), control_body); - return control(a, (Control) { .yield_types = yield_types, .inside = control_lam }); + BodyBuilder* bb = begin_body(a); + return yield_values_and_wrap_in_block(bb, gen_control(bb, yield_types, case_(a, singleton(jp), control_body))); } // TODO: match case Loop_TAG: { @@ -91,22 +91,18 @@ static const Node* process_instruction(Context* ctx, const Node* old_instruction const Node* inner_control_body = rewrite_node(&join_context.rewriter, old_loop_body->payload.case_.body); const Node* inner_control_lam = case_(a, nodes(a, 1, (const Node* []) {continue_point}), inner_control_body); - BodyBuilder* bb = begin_body(a); - const Node* inner_control = control(a, (Control) { - .yield_types = param_types, - .inside = inner_control_lam, - }); - Nodes args = bind_instruction(bb, inner_control); + BodyBuilder* inner_bb = begin_body(a); + Nodes args = gen_control(inner_bb, param_types, inner_control_lam); // TODO let_in_block or use a Jump ! - loop_body->payload.basic_block.body = finish_body(bb, jump(a, (Jump) { .target = loop_body, .args = args })); + loop_body->payload.basic_block.body = finish_body(inner_bb, jump(a, (Jump) { .target = loop_body, .args = args })); const Node* initial_jump = jump(a, (Jump) { .target = loop_body, .args = rewrite_nodes(&ctx->rewriter, old_instruction->payload.loop_instr.initial_args), }); - const Node* outer_body = case_(a, nodes(a, 1, (const Node* []) {break_point}), initial_jump); - return control(a, (Control) { .yield_types = yield_types, .inside = outer_body }); + BodyBuilder* outer_bb = begin_body(a); + return yield_values_and_wrap_in_block(outer_bb, gen_control(outer_bb, yield_types, case_(a, singleton(break_point), initial_jump))); } default: break; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 37cf9d0f8..46df24768 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -253,10 +253,9 @@ static const Node* process(Context* ctx, const Node* old) { const Node* new_jp = param(a, qualified_type_helper(new_jp_type, true), old_jp->payload.param.name); register_processed(&ctx->rewriter, old_jp, new_jp); const Node* new_body = case_(a, singleton(new_jp), rewrite_node(&ctx->rewriter, get_abstraction_body(old_inside))); - return control(a, (Control) { - .yield_types = rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types), - .inside = new_body, - }); + BodyBuilder* bb = begin_body(a); + Nodes nyield_types = rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types); + return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, new_body)); } break; } diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index aec253cd4..428ca89c9 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -185,10 +185,8 @@ static const Node* process(Context* ctx, const Node* node) { const Node* nbody = inline_call(ctx, ocallee, nargs, join_point); - return control(a, (Control) { - .yield_types = nyield_types, - .inside = case_(a, singleton(join_point), nbody) - }); + BodyBuilder* bb = begin_body(a); + return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, case_(a, singleton(join_point), nbody))); } } break; From 6b251c7ec43d985ab69c56e5dc1f412ba4e75e8a Mon Sep 17 00:00:00 2001 From: gob Date: Sun, 28 Jul 2024 16:22:20 +0200 Subject: [PATCH 364/693] wip: making structured constructs terminators --- include/shady/grammar.json | 11 ++++- src/backend/c/emit_c.c | 45 +++++++++++++++++ src/backend/c/emit_c_instructions.c | 27 ---------- src/backend/spirv/emit_spv.c | 46 +++++++++++++++++ src/backend/spirv/emit_spv_instructions.c | 44 ----------------- src/shady/analysis/cfg.c | 11 +++-- src/shady/body_builder.c | 59 ++++++++++++++++++++-- src/shady/ir_private.h | 1 + src/shady/node.c | 17 +++++-- src/shady/passes/cleanup.c | 5 ++ src/shady/passes/infer.c | 5 +- src/shady/passes/opt_mem2reg.c | 2 - src/shady/passes/opt_restructure.c | 2 +- src/shady/print.c | 60 ++++++++++++++++------- src/shady/rewrite.c | 17 ------- src/shady/type.c | 5 +- 16 files changed, 230 insertions(+), 127 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 82f41d8d0..06ac468e5 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -120,6 +120,12 @@ { "name": "jump", "generate-enum": false + }, + { + "name": "structured_construct", + "ops": [ + { "name": "tail", "class": "case" } + ] } ], "nodes": [ @@ -392,12 +398,13 @@ { "name": "If", "snake_name": "if_instr", - "class": "instruction", + "class": ["terminator", "structured_construct"], "ops": [ { "name": "yield_types", "class": "type", "list": true }, { "name": "condition", "class": "value" }, { "name": "if_true", "class": "case" }, - { "name": "if_false", "class": "case" } + { "name": "if_false", "class": "case" }, + { "name": "tail", "class": "case" } ] }, { diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 36347af0d..e81ea74ea 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -410,6 +410,50 @@ void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const T print(block_printer, "\n%s%s;", prefix, decl); } +static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String given_name, Strings* given_names, Nodes types, bool mut, const Nodes* init_values) { + if (given_names) + assert(given_names->count == types.count); + if (init_values) + assert(init_values->count == types.count); + LARRAY(String, names, types.count); + for (size_t i = 0; i < types.count; i++) { + String name = given_names ? given_names->strings[i] : given_name; + assert(name); + names[i] = unique_name(emitter->arena, name); + if (init_values) { + CTerm initializer = emit_value(emitter, p, init_values->nodes[i]); + emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); + } else + emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); + } + return strings(emitter->arena, types.count, names); +} + +static void emit_if(Emitter* emitter, Printer* p, If if_) { + Emitter sub_emiter = *emitter; + Strings ephis = emit_variable_declarations(emitter, p, "if_phi", NULL, if_.yield_types, true, NULL); + sub_emiter.phis.selection = ephis; + + assert(get_abstraction_params(if_.if_true).count == 0); + String true_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_true), NULL); + CValue condition = to_cvalue(emitter, emit_value(emitter, p, if_.condition)); + print(p, "\nif (%s) { %s}", condition, true_body); + free_tmp_str(true_body); + if (if_.if_false) { + assert(get_abstraction_params(if_.if_false).count == 0); + String false_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_false), NULL); + print(p, " else {%s}", false_body); + free_tmp_str(false_body); + } + + Nodes results = get_abstraction_params(if_.tail); + for (size_t i = 0; i < ephis.count; i++) { + register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + } + + emit_terminator(emitter, p, get_abstraction_body(if_.tail)); +} + static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { switch (is_terminator(terminator)) { case NotATerminator: assert(false); @@ -472,6 +516,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node break; } + case If_TAG: return emit_if(emitter, block_printer, terminator->payload.if_instr); case Terminator_Return_TAG: { Nodes args = terminator->payload.fn_ret.args; if (args.count == 0) { diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 0e561c26e..d94c9fbe7 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -648,32 +648,6 @@ static void emit_call(Emitter* emitter, Printer* p, const Node* call, Instructio free_tmp_str(params); } -static void emit_if(Emitter* emitter, Printer* p, const Node* if_instr, InstructionOutputs outputs) { - assert(if_instr->tag == If_TAG); - const If* if_ = &if_instr->payload.if_instr; - Emitter sub_emiter = *emitter; - Strings ephis = emit_variable_declarations(emitter, p, "if_phi", NULL, if_->yield_types, true, NULL); - sub_emiter.phis.selection = ephis; - - assert(get_abstraction_params(if_->if_true).count == 0); - String true_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_->if_true), NULL); - CValue condition = to_cvalue(emitter, emit_value(emitter, p, if_->condition)); - print(p, "\nif (%s) { %s}", condition, true_body); - free_tmp_str(true_body); - if (if_->if_false) { - assert(get_abstraction_params(if_->if_false).count == 0); - String false_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_->if_false), NULL); - print(p, " else {%s}", false_body); - free_tmp_str(false_body); - } - - assert(outputs.count == ephis.count); - for (size_t i = 0; i < outputs.count; i++) { - outputs.results[i] = term_from_cvalue(ephis.strings[i]); - outputs.binding[i] = NoBinding; - } -} - static void emit_match(Emitter* emitter, Printer* p, const Node* match_instr, InstructionOutputs outputs) { assert(match_instr->tag == Match_TAG); const Match* match = &match_instr->payload.match_instr; @@ -852,7 +826,6 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_LetMut_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; - case Instruction_If_TAG: emit_if (emitter, p, instruction, outputs); break; case Instruction_Match_TAG: emit_match (emitter, p, instruction, outputs); break; case Instruction_Loop_TAG: emit_loop (emitter, p, instruction, outputs); break; case Instruction_Control_TAG: error("TODO") diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index f77e76d90..bf2a5df32 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -174,6 +174,51 @@ static void add_branch_phis(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb } } +static void emit_if(Emitter* emitter, FnBuilder fn_builder, BBBuilder* pbb_builder, MergeTargets* merge_targets, If if_instr) { + Nodes yield_types = if_instr.yield_types; + Nodes results = get_abstraction_params(if_instr.tail); + SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); + + SpvId true_id = spvb_fresh_id(emitter->file_builder); + SpvId false_id = if_instr.if_false ? spvb_fresh_id(emitter->file_builder) : join_bb_id; + + spvb_selection_merge(*pbb_builder, join_bb_id, 0); + SpvId condition = emit_value(emitter, *pbb_builder, if_instr.condition); + spvb_branch_conditional(*pbb_builder, condition, true_id, false_id); + + // When 'join' is codegen'd, these will be filled with the values given to it + BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); + LARRAY(SpvbPhi*, join_phis, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) { + assert(if_instr.if_false && "Ifs with yield types need false branches !"); + SpvId phi_id = spvb_fresh_id(emitter->file_builder); + SpvId type = emit_type(emitter, yield_types.nodes[i]); + SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); + join_phis[i] = phi; + register_result(emitter, results.nodes[i], phi_id); + } + + MergeTargets merge_targets_branches = *merge_targets; + merge_targets_branches.join_target = join_bb_id; + merge_targets_branches.join_phis = join_phis; + + BBBuilder true_bb = spvb_begin_bb(fn_builder, true_id); + spvb_add_bb(fn_builder, true_bb); + assert(is_case(if_instr.if_true)); + emit_terminator(emitter, fn_builder, true_bb, merge_targets_branches, if_instr.if_true->payload.case_.body); + if (if_instr.if_false) { + BBBuilder false_bb = spvb_begin_bb(fn_builder, false_id); + spvb_add_bb(fn_builder, false_bb); + assert(is_case(if_instr.if_false)); + emit_terminator(emitter, fn_builder, false_bb, merge_targets_branches, if_instr.if_false->payload.case_.body); + } + + spvb_add_bb(fn_builder, join_bb); + *pbb_builder = join_bb; + + emit_terminator(emitter, fn_builder, *pbb_builder, *merge_targets, get_abstraction_body(if_instr.tail)); +} + void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_block_builder, MergeTargets merge_targets, const Node* terminator) { switch (is_terminator(terminator)) { case Return_TAG: { @@ -215,6 +260,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo spvb_branch_conditional(basic_block_builder, condition, find_reserved_id(emitter, terminator->payload.branch.true_jump->payload.jump.target), find_reserved_id(emitter, terminator->payload.branch.false_jump->payload.jump.target)); return; } + case If_TAG: return emit_if(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.if_instr); case Switch_TAG: { SpvId inspectee = emit_value(emitter, basic_block_builder, terminator->payload.br_switch.switch_value); LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 542758050..a61ac9f7a 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -377,49 +377,6 @@ static void emit_leaf_call(Emitter* emitter, SHADY_UNUSED FnBuilder fn_builder, } } -static void emit_if(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, If if_instr, size_t results_count, SpvId results[]) { - Nodes yield_types = if_instr.yield_types; - assert(yield_types.count == results_count); - SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); - - SpvId true_id = spvb_fresh_id(emitter->file_builder); - SpvId false_id = if_instr.if_false ? spvb_fresh_id(emitter->file_builder) : join_bb_id; - - spvb_selection_merge(*bb_builder, join_bb_id, 0); - SpvId condition = emit_value(emitter, *bb_builder, if_instr.condition); - spvb_branch_conditional(*bb_builder, condition, true_id, false_id); - - // When 'join' is codegen'd, these will be filled with the values given to it - BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); - LARRAY(SpvbPhi*, join_phis, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - assert(if_instr.if_false && "Ifs with yield types need false branches !"); - SpvId phi_id = spvb_fresh_id(emitter->file_builder); - SpvId type = emit_type(emitter, yield_types.nodes[i]); - SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); - join_phis[i] = phi; - results[i] = phi_id; - } - - MergeTargets merge_targets_branches = *merge_targets; - merge_targets_branches.join_target = join_bb_id; - merge_targets_branches.join_phis = join_phis; - - BBBuilder true_bb = spvb_begin_bb(fn_builder, true_id); - spvb_add_bb(fn_builder, true_bb); - assert(is_case(if_instr.if_true)); - emit_terminator(emitter, fn_builder, true_bb, merge_targets_branches, if_instr.if_true->payload.case_.body); - if (if_instr.if_false) { - BBBuilder false_bb = spvb_begin_bb(fn_builder, false_id); - spvb_add_bb(fn_builder, false_bb); - assert(is_case(if_instr.if_false)); - emit_terminator(emitter, fn_builder, false_bb, merge_targets_branches, if_instr.if_false->payload.case_.body); - } - - spvb_add_bb(fn_builder, join_bb); - *bb_builder = join_bb; -} - static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Match match, size_t results_count, SHADY_UNUSED SpvId results[]) { Nodes yield_types = match.yield_types; assert(yield_types.count == results_count); @@ -575,7 +532,6 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_Block_TAG: error("Should be lowered elsewhere") case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; case PrimOp_TAG: emit_primop(emitter, fn_builder, *bb_builder, instruction, results_count, results); break; - case If_TAG: emit_if(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.if_instr, results_count, results); break; case Match_TAG: emit_match(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.match_instr, results_count, results); break; case Loop_TAG: emit_loop(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.loop_instr, results_count, results); break; case Comment_TAG: break; diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index cc0ddc160..1b3142d03 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -157,11 +157,6 @@ static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node add_structural_dominance_edge(ctx, parent, instruction->payload.block.inside, StructuredEnterBodyEdge); add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); return; - case Instruction_If_TAG: - add_structural_dominance_edge(ctx, parent, instruction->payload.if_instr.if_true, StructuredEnterBodyEdge); - if(instruction->payload.if_instr.if_false) - add_structural_dominance_edge(ctx, parent, instruction->payload.if_instr.if_false, StructuredEnterBodyEdge); - break; case Instruction_Match_TAG: for (size_t i = 0; i < instruction->payload.match_instr.cases.count; i++) add_structural_dominance_edge(ctx, parent, instruction->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); @@ -214,6 +209,12 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_edge(ctx, node->node, (*dst)->node, StructuredLeaveBodyEdge); break; } + case If_TAG: + add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); + if(terminator->payload.if_instr.if_false) + add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.tail, StructuredPseudoExitEdge); + break; case MergeSelection_TAG: case MergeContinue_TAG: case MergeBreak_TAG: { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index d42c03923..db481ede0 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -9,8 +9,17 @@ #include #include +#pragma GCC diagnostic error "-Wswitch" + +typedef struct { + //struct List* stack; + Structured_constructTag tag; + union NodesUnion payload; +} BlockEntry; + typedef struct { const Node* instr; + BlockEntry structured; Nodes vars; } StackEntry; @@ -19,6 +28,7 @@ BodyBuilder* begin_body(IrArena* a) { *bb = (BodyBuilder) { .arena = a, .stack = new_list(StackEntry), + //.stack_stack = new_list(BlockEntry), }; return bb; } @@ -117,13 +127,26 @@ void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr) { append_list(StackEntry, bb->stack, entry); } -const Node* finish_body(BodyBuilder* bb, const Node* terminator) { +static const Node* build_body(BodyBuilder* bb, const Node* terminator) { + IrArena* a = bb->arena; size_t stack_size = entries_count_list(bb->stack); for (size_t i = stack_size - 1; i < stack_size; i--) { StackEntry entry = read_list(StackEntry, bb->stack)[i]; - terminator = let(bb->arena, entry.instr, entry.vars, case_(bb->arena, empty(bb->arena), terminator)); + switch (entry.structured.tag) { + case NotAStructured_construct: + terminator = let(a, entry.instr, entry.vars, case_(bb->arena, empty(bb->arena), terminator)); + break; + case Structured_construct_If_TAG: + entry.structured.payload.if_instr.tail = case_(bb->arena, entry.vars, terminator); + terminator = if_instr(a, entry.structured.payload.if_instr); + break; + } } + return terminator; +} +const Node* finish_body(BodyBuilder* bb, const Node* terminator) { + terminator = build_body(bb, terminator); destroy_list(bb->stack); free(bb); return terminator; @@ -159,7 +182,31 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* } Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { - return bind_instruction_outputs_count(bb, if_instr(bb->arena, (If) { .condition = condition, .yield_types = yield_types, .if_true = true_case, .if_false = false_case }), yield_types.count, NULL); + IrArena* a = bb->arena; + LARRAY(const Node*, tail_params, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) + tail_params[i] = param(a, yield_types.nodes[i], NULL); + + StackEntry entry = { + .structured = { + //.stack = bb->stack, + .tag = Structured_construct_If_TAG, + .payload.if_instr = { + .condition = condition, + .if_true = true_case, + .if_false = false_case, + .yield_types = yield_types, + }, + }, + .vars = nodes(a, yield_types.count, tail_params), + }; + //bb->stack = new_list(StackEntry); + append_list(StackEntry , bb->stack, entry); + + return entry.vars; + // const Node* tail = case_(a, nodes(a, yield_types.count, tail_params), block_yield(a, (BlockYield) { nodes(a, yield_types.count, tail_params) })); + // const Node* instr = if_instr(a, (If) { .condition = condition, .yield_types = yield_types, .if_true = true_case, .if_false = false_case, .tail = tail }); + // return bind_instruction_outputs_count(bb, block(a, (Block) { .yield_types = add_qualifiers(a, yield_types, false), .inside = case_(a, empty(a), instr) }),yield_types.count, NULL); } Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, const Node* default_case) { @@ -175,6 +222,12 @@ Nodes gen_control(BodyBuilder* bb, Nodes yield_types, const Node* body) { } void cancel_body(BodyBuilder* bb) { + for (size_t i = 0; i < entries_count_list(bb->stack); i++) { + StackEntry entry = read_list(StackEntry, bb->stack)[i]; + // if (entry.structured.tag != NotAStructured_construct) + // destroy_list(entry.structured.stack); + } destroy_list(bb->stack); + //destroy_list(bb->stack_stack); free(bb); } diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index f66007d1b..294d3222b 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -37,6 +37,7 @@ void destroy_module(Module* m); struct BodyBuilder_ { IrArena* arena; struct List* stack; + //struct List* stack_stack; }; NodeId allocate_node_id(IrArena*, const Node* n); diff --git a/src/shady/node.c b/src/shady/node.c index 25cba0eb9..a4b2b880e 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -187,12 +187,19 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi } case Block_TAG: { const Node* terminator = node->payload.block.inside->payload.case_.body; - while (terminator->tag == Let_TAG) { - terminator = terminator->payload.let.tail->payload.case_.body; + while (true) { + if (terminator->tag == Let_TAG) + terminator = terminator->payload.let.tail->payload.case_.body; + else if (is_structured_construct(terminator)) + terminator = get_abstraction_body(get_structured_construct_tail(terminator)); + else + break; + } + if (terminator->tag == BlockYield_TAG) { + assert(terminator->payload.block_yield.args.count == 1); + return resolve_node_to_definition(first(terminator->payload.block_yield.args), config); } - assert(terminator->tag == BlockYield_TAG); - assert(terminator->payload.block_yield.args.count == 1); - return resolve_node_to_definition(first(terminator->payload.block_yield.args), config); + return NULL; } case Load_TAG: { if (config.enter_loads) { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 4743d8d2b..d870e2a91 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -55,6 +55,11 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* assert(is_case(lam)); const Node* terminator = get_abstraction_body(lam); while (true) { + /*if (is_structured_construct(terminator)) { + //bind_variables2(bb, terminator->payload.let.variables, terminator->payload.let.instruction); + terminator = get_abstraction_body(get_structured_construct_tail(terminator)); + continue; + }*/ switch (is_terminator(terminator)) { case NotATerminator: assert(false); case Terminator_Let_TAG: { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 0e353d4e4..95877fd79 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -463,7 +463,7 @@ static const Node* infer_indirect_call(Context* ctx, const Node* node, const Nod }); } -static const Node* infer_if(Context* ctx, const Node* node, const Nodes* expected_types) { +static const Node* infer_if(Context* ctx, const Node* node) { assert(node->tag == If_TAG); IrArena* a = ctx->rewriter.dst_arena; const Node* condition = infer(ctx, node->payload.if_instr.condition, qualified_type_helper(bool_type(a), false)); @@ -484,6 +484,7 @@ static const Node* infer_if(Context* ctx, const Node* node, const Nodes* expecte .condition = condition, .if_true = true_body, .if_false = false_body, + .tail = infer_case(ctx, node->payload.if_instr.tail, expected_join_types) }); } @@ -566,7 +567,6 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes switch (is_instruction(node)) { case PrimOp_TAG: return infer_primop(ctx, node, expected_types); case Call_TAG: return infer_indirect_call(ctx, node, expected_types); - case If_TAG: return infer_if (ctx, node, expected_types); case Loop_TAG: return infer_loop (ctx, node, expected_types); case Match_TAG: error("TODO") case Control_TAG: return infer_control(ctx, node, expected_types); @@ -613,6 +613,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; switch (is_terminator(node)) { case NotATerminator: assert(false); + case If_TAG: return infer_if (ctx, node); case Let_TAG: { // const Node* otail = node->payload.let.ttail; // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 9d038a241..2fd33c7b6 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -444,8 +444,6 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No break; case Instruction_Comment_TAG: break; - case Instruction_If_TAG: - break; case Instruction_Match_TAG: break; case Instruction_Loop_TAG: diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 5393489d9..ac88e0236 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -203,7 +203,6 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad const Node* old_instr = get_let_instruction(body); switch (is_instruction(old_instr)) { case NotAnInstruction: assert(false); - case Instruction_If_TAG: case Instruction_Loop_TAG: case Instruction_Match_TAG: error("not supposed to exist in IR at this stage"); case Instruction_Block_TAG: error("Should be eliminated by the compiler"); @@ -331,6 +330,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case TailCall_TAG: longjmp(ctx->bail, 1); + case If_TAG: case Terminator_BlockYield_TAG: case Terminator_MergeBreak_TAG: case Terminator_MergeContinue_TAG: diff --git a/src/shady/print.c b/src/shady/print.c index bbc6d8cfb..5c09e8b6b 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -562,24 +562,6 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf(")"); print_args_list(ctx, node->payload.call.args); break; - } case If_TAG: { - printf(GREEN); - printf("if"); - printf(RESET); - print_yield_types(ctx, node->payload.if_instr.yield_types); - printf("("); - print_node(node->payload.if_instr.condition); - printf(") "); - if (ctx->config.in_cfg) - break; - print_case_body(ctx, node->payload.if_instr.if_true); - if (node->payload.if_instr.if_false) { - printf(GREEN); - printf(" else "); - printf(RESET); - print_case_body(ctx, node->payload.if_instr.if_false); - } - break; } case Loop_TAG: { printf(GREEN); printf("loop"); @@ -656,6 +638,26 @@ static void print_jump(PrinterCtx* ctx, const Node* node) { print_args_list(ctx, node->payload.jump.args); } +static void print_structured_construct_results(PrinterCtx* ctx, const Node* tail_case) { + Nodes params = get_abstraction_params(tail_case); + if (params.count > 0) { + printf(GREEN); + printf("val"); + printf(RESET); + for (size_t i = 0; i < params.count; i++) { + // TODO: fix let mut + if (tail_case->arena->config.check_types) { + printf(" "); + print_node(params.nodes[i]->type); + } + printf(" "); + print_node(params.nodes[i]); + printf(RESET); + } + printf(" = "); + } +} + static void print_terminator(PrinterCtx* ctx, const Node* node) { TerminatorTag tag = is_terminator(node); switch (tag) { @@ -710,6 +712,28 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(";"); } break; + } + case If_TAG: { + print_structured_construct_results(ctx, node->payload.if_instr.tail); + printf(GREEN); + printf("if"); + printf(RESET); + print_yield_types(ctx, node->payload.if_instr.yield_types); + printf("("); + print_node(node->payload.if_instr.condition); + printf(") "); + if (ctx->config.in_cfg) + break; + print_case_body(ctx, node->payload.if_instr.if_true); + if (node->payload.if_instr.if_false) { + printf(GREEN); + printf(" else "); + printf(RESET); + print_case_body(ctx, node->payload.if_instr.if_false); + } + printf("\n"); + print_abs_body(ctx, node->payload.if_instr.tail); + break; } case Return_TAG: printf(BGREEN); printf("return"); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 477d61b8c..f077a22af 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -328,23 +328,6 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) } } -/*const Node* rebind_let(Rewriter* rewriter, const Node* ninstruction, const Node* olam) { - assert(olam->tag == Case_TAG); - Nodes oparams = olam->payload.case_.params; - Nodes ntypes = unwrap_multiple_yield_types(rewriter->dst_arena, ninstruction->type); - assert(ntypes.count == oparams.count); - LARRAY(const Node*, new_params, oparams.count); - for (size_t i = 0; i < oparams.count; i++) { - new_params[i] = var(rewriter->dst_arena, ntypes.nodes[i], oparams.nodes[i]->payload.var.name); - register_processed(rewriter, oparams.nodes[i], new_params[i]); - } - const Node* nbody = rewrite_node(rewriter, olam->payload.case_.body); - const Node* tail = case_(rewriter->dst_arena, nodes(rewriter->dst_arena, oparams.count, new_params), nbody); - return tail; -}*/ - -void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr); - const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { if (node == NULL) return NULL; diff --git a/src/shady/type.c b/src/shady/type.c index fb54f5211..5a1bff4b6 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1013,6 +1013,7 @@ static void ensure_types_are_value_types(const Nodes* yield_types) { } const Type* check_type_if_instr(IrArena* arena, If if_instr) { + assert(if_instr.tail && is_abstraction(if_instr.tail)); ensure_types_are_data_types(&if_instr.yield_types); if (get_unqualified_type(if_instr.condition->type) != bool_type(arena)) error("condition of an if should be bool"); @@ -1020,7 +1021,9 @@ const Type* check_type_if_instr(IrArena* arena, If if_instr) { if (if_instr.yield_types.count > 0) assert(if_instr.if_false); - return wrap_multiple_yield_types(arena, add_qualifiers(arena, if_instr.yield_types, false)); + check_arguments_types_against_parameters_helper(get_param_types(arena, get_abstraction_params(if_instr.tail)), add_qualifiers(arena, if_instr.yield_types, false)); + //return wrap_multiple_yield_types(arena, add_qualifiers(arena, if_instr.yield_types, false)); + return noret_type(arena); } const Type* check_type_loop_instr(IrArena* arena, Loop loop_instr) { From cd18c873a5ce216d4e4eacad687c6e2e5dddcd50 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 28 Jul 2024 18:58:49 +0200 Subject: [PATCH 365/693] fixed terminator-if bugs --- src/shady/fold.c | 1 + src/shady/passes/cleanup.c | 16 +++-- src/shady/passes/lower_cf_instrs.c | 84 +++++++++++++++------------ src/shady/passes/lower_switch_btree.c | 2 +- 4 files changed, 61 insertions(+), 42 deletions(-) diff --git a/src/shady/fold.c b/src/shady/fold.c index f1bb08485..d52a8b9e3 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -428,6 +428,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { else if (is_unreachable_destination(payload.false_jump)) return payload.true_jump; } + break; } case Match_TAG: { if (!arena->config.optimisations.delete_unreachable_structured_cases) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index d870e2a91..75a90482a 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -55,11 +55,17 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* assert(is_case(lam)); const Node* terminator = get_abstraction_body(lam); while (true) { - /*if (is_structured_construct(terminator)) { - //bind_variables2(bb, terminator->payload.let.variables, terminator->payload.let.instruction); - terminator = get_abstraction_body(get_structured_construct_tail(terminator)); - continue; - }*/ + switch (is_structured_construct(terminator)) { + case NotAStructured_construct: break; + case Structured_construct_If_TAG: { + If payload = terminator->payload.if_instr; + Nodes results = gen_if(bb, payload.yield_types, payload.condition, payload.if_true, payload.if_false); + bind_variables(bb, get_abstraction_params(payload.tail), results); + terminator = get_abstraction_body(get_structured_construct_tail(terminator)); + continue; + } + } + switch (is_terminator(terminator)) { case NotATerminator: assert(false); case Terminator_Let_TAG: { diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 680cf788d..aa50c8fe6 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -25,41 +25,6 @@ static const Node* process_instruction(Context* ctx, const Node* old_instruction IrArena* a = ctx->rewriter.dst_arena; switch (old_instruction->tag) { - case If_TAG: { - bool has_false_branch = old_instruction->payload.if_instr.if_false; - Nodes yield_types = rewrite_nodes(&ctx->rewriter, old_instruction->payload.if_instr.yield_types); - - const Type* jp_type = qualified_type(a, (QualifiedType) { - .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), - .is_uniform = false, - }); - const Node* jp = param(a, jp_type, "if_join"); - Context join_context = *ctx; - Nodes jps = singleton(jp); - insert_dict(const Node*, Nodes, ctx->structured_join_tokens, old_instruction, jps); - - Node* true_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_true")); - join_context.abs = old_instruction->payload.if_instr.if_true; - true_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, old_instruction->payload.if_instr.if_true->payload.case_.body); - - Node* flse_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_false")); - if (has_false_branch) { - join_context.abs = old_instruction->payload.if_instr.if_false; - flse_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, old_instruction->payload.if_instr.if_false->payload.case_.body); - } else { - assert(yield_types.count == 0); - flse_block->payload.basic_block.body = join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL) }); - } - - const Node* control_body = branch(a, (Branch) { - .condition = rewrite_node(&ctx->rewriter, old_instruction->payload.if_instr.condition), - .true_jump = jump_helper(a, true_block, empty(a)), - .false_jump = jump_helper(a, flse_block, empty(a)), - }); - - BodyBuilder* bb = begin_body(a); - return yield_values_and_wrap_in_block(bb, gen_control(bb, yield_types, case_(a, singleton(jp), control_body))); - } // TODO: match case Loop_TAG: { const Node* old_loop_body = old_instruction->payload.loop_instr.body; @@ -116,7 +81,8 @@ static const Node* process_node(Context* ctx, const Node* node) { if (already_done) return already_done; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; Context sub_ctx = *ctx; if (node->tag == Function_TAG) { @@ -147,6 +113,49 @@ static const Node* process_node(Context* ctx, const Node* node) { if (is_instruction(node)) return process_instruction(ctx, node); switch (node->tag) { + case If_TAG: { + bool has_false_branch = node->payload.if_instr.if_false; + Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.if_instr.yield_types); + + const Type* jp_type = qualified_type(a, (QualifiedType) { + .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), + .is_uniform = false, + }); + const Node* jp = param(a, jp_type, "if_join"); + Context join_context = *ctx; + Nodes jps = singleton(jp); + insert_dict(const Node*, Nodes, ctx->structured_join_tokens, node, jps); + + Node* true_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_true")); + join_context.abs = node->payload.if_instr.if_true; + true_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, node->payload.if_instr.if_true->payload.case_.body); + + Node* flse_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_false")); + if (has_false_branch) { + join_context.abs = node->payload.if_instr.if_false; + flse_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, node->payload.if_instr.if_false->payload.case_.body); + } else { + assert(yield_types.count == 0); + flse_block->payload.basic_block.body = join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL) }); + } + + const Node* control_body = branch(a, (Branch) { + .condition = rewrite_node(r, node->payload.if_instr.condition), + .true_jump = jump_helper(a, true_block, empty(a)), + .false_jump = jump_helper(a, flse_block, empty(a)), + }); + + BodyBuilder* bb = begin_body(a); + Nodes results = gen_control(bb, yield_types, case_(a, singleton(jp), control_body)); + + const Node* otail = node->payload.if_instr.tail; + Node* join = basic_block(a, recreate_params(r, get_abstraction_params(otail)), NULL); + register_processed_list(r, get_abstraction_params(otail), get_abstraction_params(join)); + set_abstraction_body(join, rewrite_node(r, get_abstraction_body(otail))); + return finish_body(bb, jump_helper(a, join, results)); + // return control(a) + //return yield_values_and_wrap_in_block(bb, ); + } case MergeSelection_TAG: { if (!cfnode) break; @@ -160,6 +169,9 @@ static const Node* process_node(Context* ctx, const Node* node) { selection_instr = instr; break; } + } else if(body->tag == If_TAG) { + selection_instr = body; + break; } dom = dom->idom; } diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 471b82372..9aec55bff 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -117,7 +117,7 @@ static const Node* generate_decision_tree(Context* ctx, TreeNode* n, bool in_if, BodyBuilder* bb = begin_body(a); const Node* true_branch = n->children[1] ? generate_decision_tree(ctx, n->children[1], true, n->key + 1, max) : generate_default_fallback_case(ctx, true); Nodes values = gen_if(bb, ctx->yield_types, gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), true_branch, body); - body = case_(a, empty(a), gen_yield(ctx, in_if, values)); + body = case_(a, empty(a), finish_body(bb, gen_yield(ctx, in_if, values))); } return body; From a0f303c5bec91054bfe0c0481757d91b96ab545a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 29 Jul 2024 09:24:20 +0200 Subject: [PATCH 366/693] fixed mac build --- vcc-std/src/test_vec.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/vcc-std/src/test_vec.cpp b/vcc-std/src/test_vec.cpp index 92d39e07c..9ba6ba556 100644 --- a/vcc-std/src/test_vec.cpp +++ b/vcc-std/src/test_vec.cpp @@ -54,6 +54,7 @@ void check_swizzle_mut(vec4& v) { } #include +#include int main(int argc, char** argv) { vec4 v(1.0f, 0.5f, 0.0f, -1.0f); float f; From 83f24b7ec501c55de217ba7224bacdde3e0a19b9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 29 Jul 2024 10:02:31 +0200 Subject: [PATCH 367/693] converted Match to a terminator too --- include/shady/grammar.json | 5 +- src/backend/c/emit_c.c | 44 +++++++++++++++ src/backend/c/emit_c_instructions.c | 45 --------------- src/backend/spirv/emit_spv.c | 64 +++++++++++++++++++++ src/backend/spirv/emit_spv_instructions.c | 62 -------------------- src/shady/analysis/cfg.c | 13 +++-- src/shady/body_builder.c | 35 +++++++++--- src/shady/fold.c | 1 + src/shady/passes/infer.c | 2 +- src/shady/passes/lower_switch_btree.c | 7 ++- src/shady/passes/opt_mem2reg.c | 2 - src/shady/passes/opt_restructure.c | 2 +- src/shady/print.c | 69 ++++++++++++----------- 13 files changed, 189 insertions(+), 162 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 06ac468e5..9459ec4e0 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -410,13 +410,14 @@ { "name": "Match", "snake_name": "match_instr", - "class": "instruction", + "class": ["terminator", "structured_construct"], "ops": [ { "name": "yield_types", "class": "type", "list": true }, { "name": "inspect", "class": "value" }, { "name": "literals", "class": "value", "list": true }, { "name": "cases", "class": "case", "list": true }, - { "name": "default_case", "class": "case" } + { "name": "default_case", "class": "case" }, + { "name": "tail", "class": "case" } ] }, { diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index e81ea74ea..6c1c4c80f 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -454,6 +454,49 @@ static void emit_if(Emitter* emitter, Printer* p, If if_) { emit_terminator(emitter, p, get_abstraction_body(if_.tail)); } +static void emit_match(Emitter* emitter, Printer* p, Match match) { + Emitter sub_emiter = *emitter; + Strings ephis = emit_variable_declarations(emitter, p, "match_phi", NULL, match.yield_types, true, NULL); + sub_emiter.phis.selection = ephis; + + // Of course, the sensible thing to do here would be to emit a switch statement. + // ... + // Except that doesn't work, because C/GLSL have a baffling design wart: the `break` statement is overloaded, + // meaning that if you enter a switch statement, which should be orthogonal to loops, you can't actually break + // out of the outer loop anymore. Brilliant. So we do this terrible if-chain instead. + // + // We could do GOTO for C, but at the cost of arguably even more noise in the output, and two different codepaths. + // I don't think it's quite worth it, just like it's not worth doing some data-flow based solution either. + + CValue inspectee = to_cvalue(emitter, emit_value(emitter, p, match.inspect)); + bool first = true; + LARRAY(CValue, literals, match.cases.count); + for (size_t i = 0; i < match.cases.count; i++) { + literals[i] = to_cvalue(emitter, emit_value(emitter, p, match.literals.nodes[i])); + } + for (size_t i = 0; i < match.cases.count; i++) { + String case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match.cases.nodes[i]), NULL); + print(p, "\n"); + if (!first) + print(p, "else "); + print(p, "if (%s == %s) { %s}", inspectee, literals[i], case_body); + free_tmp_str(case_body); + first = false; + } + if (match.default_case) { + String default_case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match.default_case), NULL); + print(p, "\nelse { %s}", default_case_body); + free_tmp_str(default_case_body); + } + + Nodes results = get_abstraction_params(match.tail); + for (size_t i = 0; i < ephis.count; i++) { + register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + } + + emit_terminator(emitter, p, get_abstraction_body(match.tail)); +} + static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { switch (is_terminator(terminator)) { case NotATerminator: assert(false); @@ -517,6 +560,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node break; } case If_TAG: return emit_if(emitter, block_printer, terminator->payload.if_instr); + case Match_TAG: return emit_match(emitter, block_printer, terminator->payload.match_instr); case Terminator_Return_TAG: { Nodes args = terminator->payload.fn_ret.args; if (args.count == 0) { diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index d94c9fbe7..0678d3a81 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -648,50 +648,6 @@ static void emit_call(Emitter* emitter, Printer* p, const Node* call, Instructio free_tmp_str(params); } -static void emit_match(Emitter* emitter, Printer* p, const Node* match_instr, InstructionOutputs outputs) { - assert(match_instr->tag == Match_TAG); - const Match* match = &match_instr->payload.match_instr; - Emitter sub_emiter = *emitter; - Strings ephis = emit_variable_declarations(emitter, p, "match_phi", NULL, match->yield_types, true, NULL); - sub_emiter.phis.selection = ephis; - - // Of course, the sensible thing to do here would be to emit a switch statement. - // ... - // Except that doesn't work, because C/GLSL have a baffling design wart: the `break` statement is overloaded, - // meaning that if you enter a switch statement, which should be orthogonal to loops, you can't actually break - // out of the outer loop anymore. Brilliant. So we do this terrible if-chain instead. - // - // We could do GOTO for C, but at the cost of arguably even more noise in the output, and two different codepaths. - // I don't think it's quite worth it, just like it's not worth doing some data-flow based solution either. - - CValue inspectee = to_cvalue(emitter, emit_value(emitter, p, match->inspect)); - bool first = true; - LARRAY(CValue, literals, match->cases.count); - for (size_t i = 0; i < match->cases.count; i++) { - literals[i] = to_cvalue(emitter, emit_value(emitter, p, match->literals.nodes[i])); - } - for (size_t i = 0; i < match->cases.count; i++) { - String case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match->cases.nodes[i]), NULL); - print(p, "\n"); - if (!first) - print(p, "else "); - print(p, "if (%s == %s) { %s}", inspectee, literals[i], case_body); - free_tmp_str(case_body); - first = false; - } - if (match->default_case) { - String default_case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match->default_case), NULL); - print(p, "\nelse { %s}", default_case_body); - free_tmp_str(default_case_body); - } - - assert(outputs.count == ephis.count); - for (size_t i = 0; i < outputs.count; i++) { - outputs.results[i] = term_from_cvalue(ephis.strings[i]); - outputs.binding[i] = NoBinding; - } -} - static void emit_loop(Emitter* emitter, Printer* p, const Node* loop_instr, InstructionOutputs outputs) { assert(loop_instr->tag == Loop_TAG); const Loop* loop = &loop_instr->payload.loop_instr; @@ -826,7 +782,6 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_LetMut_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; - case Instruction_Match_TAG: emit_match (emitter, p, instruction, outputs); break; case Instruction_Loop_TAG: emit_loop (emitter, p, instruction, outputs); break; case Instruction_Control_TAG: error("TODO") case Instruction_Block_TAG: error("Should be eliminated by the compiler") diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index bf2a5df32..415b7cb20 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -219,6 +219,69 @@ static void emit_if(Emitter* emitter, FnBuilder fn_builder, BBBuilder* pbb_build emit_terminator(emitter, fn_builder, *pbb_builder, *merge_targets, get_abstraction_body(if_instr.tail)); } +static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Match match) { + Nodes yield_types = match.yield_types; + Nodes results = get_abstraction_params(match.tail); + SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); + + assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); + SpvId inspectee = emit_value(emitter, *bb_builder, match.inspect); + + SpvId default_id = spvb_fresh_id(emitter->file_builder); + + const Type* inspectee_t = match.inspect->type; + deconstruct_qualified_type(&inspectee_t); + assert(inspectee_t->tag == Int_TAG); + size_t literal_width = inspectee_t->payload.int_type.width == IntTy64 ? 2 : 1; + size_t literal_case_entry_size = literal_width + 1; + LARRAY(uint32_t, literals_and_cases, match.cases.count * literal_case_entry_size); + for (size_t i = 0; i < match.cases.count; i++) { + uint64_t value = (uint64_t) get_int_literal_value(*resolve_to_int_literal(match.literals.nodes[i]), false); + if (inspectee_t->payload.int_type.width == IntTy64) { + literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) (value & 0xFFFFFFFF); + literals_and_cases[i * literal_case_entry_size + 1] = (SpvId) (uint32_t) (value >> 32); + } else { + literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) value; + } + literals_and_cases[i * literal_case_entry_size + literal_width] = spvb_fresh_id(emitter->file_builder); + } + + spvb_selection_merge(*bb_builder, join_bb_id, 0); + spvb_switch(*bb_builder, inspectee, default_id, match.cases.count * literal_case_entry_size, literals_and_cases); + + // When 'join' is codegen'd, these will be filled with the values given to it + BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); + LARRAY(SpvbPhi*, join_phis, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) { + SpvId phi_id = spvb_fresh_id(emitter->file_builder); + SpvId type = emit_type(emitter, yield_types.nodes[i]); + SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); + join_phis[i] = phi; + register_result(emitter, results.nodes[i], phi_id); + } + + MergeTargets merge_targets_branches = *merge_targets; + merge_targets_branches.join_target = join_bb_id; + merge_targets_branches.join_phis = join_phis; + + for (size_t i = 0; i < match.cases.count; i++) { + BBBuilder case_bb = spvb_begin_bb(fn_builder, literals_and_cases[i * literal_case_entry_size + literal_width]); + const Node* case_body = match.cases.nodes[i]; + assert(is_case(case_body)); + spvb_add_bb(fn_builder, case_bb); + emit_terminator(emitter, fn_builder, case_bb, merge_targets_branches, case_body->payload.case_.body); + } + BBBuilder default_bb = spvb_begin_bb(fn_builder, default_id); + assert(is_case(match.default_case)); + spvb_add_bb(fn_builder, default_bb); + emit_terminator(emitter, fn_builder, default_bb, merge_targets_branches, match.default_case->payload.case_.body); + + spvb_add_bb(fn_builder, join_bb); + *bb_builder = join_bb; + + emit_terminator(emitter, fn_builder, *bb_builder, *merge_targets, get_abstraction_body(match.tail)); +} + void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_block_builder, MergeTargets merge_targets, const Node* terminator) { switch (is_terminator(terminator)) { case Return_TAG: { @@ -261,6 +324,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo return; } case If_TAG: return emit_if(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.if_instr); + case Match_TAG: return emit_match(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.match_instr); case Switch_TAG: { SpvId inspectee = emit_value(emitter, basic_block_builder, terminator->payload.br_switch.switch_value); LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index a61ac9f7a..4b3762fbc 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -377,67 +377,6 @@ static void emit_leaf_call(Emitter* emitter, SHADY_UNUSED FnBuilder fn_builder, } } -static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Match match, size_t results_count, SHADY_UNUSED SpvId results[]) { - Nodes yield_types = match.yield_types; - assert(yield_types.count == results_count); - SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); - - assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); - SpvId inspectee = emit_value(emitter, *bb_builder, match.inspect); - - SpvId default_id = spvb_fresh_id(emitter->file_builder); - - const Type* inspectee_t = match.inspect->type; - deconstruct_qualified_type(&inspectee_t); - assert(inspectee_t->tag == Int_TAG); - size_t literal_width = inspectee_t->payload.int_type.width == IntTy64 ? 2 : 1; - size_t literal_case_entry_size = literal_width + 1; - LARRAY(uint32_t, literals_and_cases, match.cases.count * literal_case_entry_size); - for (size_t i = 0; i < match.cases.count; i++) { - uint64_t value = (uint64_t) get_int_literal_value(*resolve_to_int_literal(match.literals.nodes[i]), false); - if (inspectee_t->payload.int_type.width == IntTy64) { - literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) (value & 0xFFFFFFFF); - literals_and_cases[i * literal_case_entry_size + 1] = (SpvId) (uint32_t) (value >> 32); - } else { - literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) value; - } - literals_and_cases[i * literal_case_entry_size + literal_width] = spvb_fresh_id(emitter->file_builder); - } - - spvb_selection_merge(*bb_builder, join_bb_id, 0); - spvb_switch(*bb_builder, inspectee, default_id, match.cases.count * literal_case_entry_size, literals_and_cases); - - // When 'join' is codegen'd, these will be filled with the values given to it - BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); - LARRAY(SpvbPhi*, join_phis, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - SpvId phi_id = spvb_fresh_id(emitter->file_builder); - SpvId type = emit_type(emitter, yield_types.nodes[i]); - SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); - join_phis[i] = phi; - results[i] = phi_id; - } - - MergeTargets merge_targets_branches = *merge_targets; - merge_targets_branches.join_target = join_bb_id; - merge_targets_branches.join_phis = join_phis; - - for (size_t i = 0; i < match.cases.count; i++) { - BBBuilder case_bb = spvb_begin_bb(fn_builder, literals_and_cases[i * literal_case_entry_size + literal_width]); - const Node* case_body = match.cases.nodes[i]; - assert(is_case(case_body)); - spvb_add_bb(fn_builder, case_bb); - emit_terminator(emitter, fn_builder, case_bb, merge_targets_branches, case_body->payload.case_.body); - } - BBBuilder default_bb = spvb_begin_bb(fn_builder, default_id); - assert(is_case(match.default_case)); - spvb_add_bb(fn_builder, default_bb); - emit_terminator(emitter, fn_builder, default_bb, merge_targets_branches, match.default_case->payload.case_.body); - - spvb_add_bb(fn_builder, join_bb); - *bb_builder = join_bb; -} - static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Loop loop_instr, size_t results_count, SpvId results[]) { Nodes yield_types = loop_instr.yield_types; assert(yield_types.count == results_count); @@ -532,7 +471,6 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_Block_TAG: error("Should be lowered elsewhere") case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; case PrimOp_TAG: emit_primop(emitter, fn_builder, *bb_builder, instruction, results_count, results); break; - case Match_TAG: emit_match(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.match_instr, results_count, results); break; case Loop_TAG: emit_loop(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.loop_instr, results_count, results); break; case Comment_TAG: break; case Instruction_LocalAlloc_TAG: { diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 1b3142d03..8061ea8db 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -157,11 +157,6 @@ static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node add_structural_dominance_edge(ctx, parent, instruction->payload.block.inside, StructuredEnterBodyEdge); add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); return; - case Instruction_Match_TAG: - for (size_t i = 0; i < instruction->payload.match_instr.cases.count; i++) - add_structural_dominance_edge(ctx, parent, instruction->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, parent, instruction->payload.match_instr.default_case, StructuredEnterBodyEdge); - break; case Instruction_Loop_TAG: add_structural_dominance_edge(ctx, parent, instruction->payload.loop_instr.body, StructuredEnterBodyEdge); break; @@ -213,7 +208,13 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); if(terminator->payload.if_instr.if_false) add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.tail, StructuredPseudoExitEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + break; + case Match_TAG: + for (size_t i = 0; i < terminator->payload.match_instr.cases.count; i++) + add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); break; case MergeSelection_TAG: case MergeContinue_TAG: diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index db481ede0..16364c5ae 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -140,6 +140,10 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { entry.structured.payload.if_instr.tail = case_(bb->arena, entry.vars, terminator); terminator = if_instr(a, entry.structured.payload.if_instr); break; + case Structured_construct_Match_TAG: + entry.structured.payload.match_instr.tail = case_(bb->arena, entry.vars, terminator); + terminator = match_instr(a, entry.structured.payload.match_instr); + break; } } return terminator; @@ -183,13 +187,13 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { IrArena* a = bb->arena; + Nodes qyield_types = add_qualifiers(a, yield_types, false); LARRAY(const Node*, tail_params, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) - tail_params[i] = param(a, yield_types.nodes[i], NULL); + tail_params[i] = param(a, qyield_types.nodes[i], NULL); StackEntry entry = { .structured = { - //.stack = bb->stack, .tag = Structured_construct_If_TAG, .payload.if_instr = { .condition = condition, @@ -200,17 +204,32 @@ Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const No }, .vars = nodes(a, yield_types.count, tail_params), }; - //bb->stack = new_list(StackEntry); append_list(StackEntry , bb->stack, entry); - return entry.vars; - // const Node* tail = case_(a, nodes(a, yield_types.count, tail_params), block_yield(a, (BlockYield) { nodes(a, yield_types.count, tail_params) })); - // const Node* instr = if_instr(a, (If) { .condition = condition, .yield_types = yield_types, .if_true = true_case, .if_false = false_case, .tail = tail }); - // return bind_instruction_outputs_count(bb, block(a, (Block) { .yield_types = add_qualifiers(a, yield_types, false), .inside = case_(a, empty(a), instr) }),yield_types.count, NULL); } Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, const Node* default_case) { - return bind_instruction_outputs_count(bb, match_instr(bb->arena, (Match) { .yield_types = yield_types, .inspect = inspectee, .literals = literals, .cases = cases, .default_case = default_case }), yield_types.count, NULL); + IrArena* a = bb->arena; + Nodes qyield_types = add_qualifiers(a, yield_types, false); + LARRAY(const Node*, tail_params, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) + tail_params[i] = param(a, qyield_types.nodes[i], NULL); + + StackEntry entry = { + .structured = { + .tag = Structured_construct_Match_TAG, + .payload.match_instr = { + .yield_types = yield_types, + .inspect = inspectee, + .literals = literals, + .cases = cases, + .default_case = default_case + }, + }, + .vars = nodes(a, yield_types.count, tail_params), + }; + append_list(StackEntry , bb->stack, entry); + return entry.vars; } Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Node* body) { diff --git a/src/shady/fold.c b/src/shady/fold.c index d52a8b9e3..9f564a825 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -461,6 +461,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { .default_case = payload.default_case, .literals = nodes(arena, new_cases_count, literals), .cases = nodes(arena, new_cases_count, cases), + .tail = payload.tail, }); } default: break; diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 95877fd79..7096e6ecf 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -568,7 +568,6 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes case PrimOp_TAG: return infer_primop(ctx, node, expected_types); case Call_TAG: return infer_indirect_call(ctx, node, expected_types); case Loop_TAG: return infer_loop (ctx, node, expected_types); - case Match_TAG: error("TODO") case Control_TAG: return infer_control(ctx, node, expected_types); case Block_TAG: return infer_block (ctx, node, expected_types); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); @@ -614,6 +613,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { switch (is_terminator(node)) { case NotATerminator: assert(false); case If_TAG: return infer_if (ctx, node); + case Match_TAG: error("TODO") case Let_TAG: { // const Node* otail = node->payload.let.ttail; // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 9aec55bff..8cabee782 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -124,7 +124,8 @@ static const Node* generate_decision_tree(Context* ctx, TreeNode* n, bool in_if, } static const Node* process(Context* ctx, const Node* node) { - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { case Match_TAG: { @@ -157,9 +158,11 @@ static const Node* process(Context* ctx, const Node* node) { // Check if we need to run the default case Nodes final_results = gen_if(bb, ctx2.yield_types, gen_load(bb, run_default_case), rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), case_(a, empty(a), gen_yield(ctx, true, matched_results))); + register_processed_list(r, get_abstraction_params(get_structured_construct_tail(node)), final_results); destroy_arena(arena); - return yield_values_and_wrap_in_block(bb, final_results); + return finish_body(bb, rewrite_node(r, get_abstraction_body(get_structured_construct_tail(node)))); + // return yield_values_and_wrap_in_block(bb, final_results); } default: break; } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 2fd33c7b6..8f212c4c0 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -444,8 +444,6 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No break; case Instruction_Comment_TAG: break; - case Instruction_Match_TAG: - break; case Instruction_Loop_TAG: mark_values_as_escaping(ctx, kb, oinstruction->payload.loop_instr.initial_args); // assert(false && "unsupported"); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index ac88e0236..9cb624a07 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -204,7 +204,6 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad switch (is_instruction(old_instr)) { case NotAnInstruction: assert(false); case Instruction_Loop_TAG: - case Instruction_Match_TAG: error("not supposed to exist in IR at this stage"); case Instruction_Block_TAG: error("Should be eliminated by the compiler"); case Instruction_Call_TAG: { const Node* callee = old_instr->payload.call.callee; @@ -331,6 +330,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case TailCall_TAG: longjmp(ctx->bail, 1); case If_TAG: + case Match_TAG: error("not supposed to exist in IR at this stage"); case Terminator_BlockYield_TAG: case Terminator_MergeBreak_TAG: case Terminator_MergeContinue_TAG: diff --git a/src/shady/print.c b/src/shady/print.c index 5c09e8b6b..2f9f3a1ca 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -574,39 +574,6 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { print_param_list(ctx, body->payload.case_.params, &node->payload.loop_instr.initial_args); print_case_body(ctx, body); break; - } case Match_TAG: { - printf(GREEN); - printf("match"); - printf(RESET); - print_yield_types(ctx, node->payload.match_instr.yield_types); - printf("("); - print_node(node->payload.match_instr.inspect); - printf(")"); - if (ctx->config.in_cfg) - break; - printf(" {"); - indent(ctx->printer); - for (size_t i = 0; i < node->payload.match_instr.literals.count; i++) { - printf("\n"); - printf(GREEN); - printf("case"); - printf(RESET); - printf(" "); - print_node(node->payload.match_instr.literals.nodes[i]); - printf(": "); - print_case_body(ctx, node->payload.match_instr.cases.nodes[i]); - } - - printf("\n"); - printf(GREEN); - printf("default"); - printf(RESET); - printf(": "); - print_case_body(ctx, node->payload.match_instr.default_case); - - deindent(ctx->printer); - printf("\n}"); - break; } case Control_TAG: { printf(BGREEN); if (ctx->uses) { @@ -734,6 +701,42 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf("\n"); print_abs_body(ctx, node->payload.if_instr.tail); break; + } case Match_TAG: { + print_structured_construct_results(ctx, node->payload.match_instr.tail); + printf(GREEN); + printf("match"); + printf(RESET); + print_yield_types(ctx, node->payload.match_instr.yield_types); + printf("("); + print_node(node->payload.match_instr.inspect); + printf(")"); + if (ctx->config.in_cfg) + break; + printf(" {"); + indent(ctx->printer); + for (size_t i = 0; i < node->payload.match_instr.literals.count; i++) { + printf("\n"); + printf(GREEN); + printf("case"); + printf(RESET); + printf(" "); + print_node(node->payload.match_instr.literals.nodes[i]); + printf(": "); + print_case_body(ctx, node->payload.match_instr.cases.nodes[i]); + } + + printf("\n"); + printf(GREEN); + printf("default"); + printf(RESET); + printf(": "); + print_case_body(ctx, node->payload.match_instr.default_case); + + deindent(ctx->printer); + printf("\n}"); + printf("\n"); + print_abs_body(ctx, node->payload.match_instr.tail); + break; } case Return_TAG: printf(BGREEN); printf("return"); From e836142747644c9bd3715403eecff84b5b6763dd Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 09:30:03 +0200 Subject: [PATCH 368/693] convert Loop to a terminator --- include/shady/grammar.json | 5 +- src/backend/c/emit_c.c | 32 ++++++ src/backend/c/emit_c_instructions.c | 34 ------ src/backend/spirv/emit_spv.c | 86 ++++++++++++++- src/backend/spirv/emit_spv_instructions.c | 82 --------------- src/shady/analysis/cfg.c | 7 +- src/shady/body_builder.c | 24 ++++- src/shady/passes/cleanup.c | 16 +++ src/shady/passes/infer.c | 5 +- src/shady/passes/lower_cf_instrs.c | 121 +++++++++++----------- src/shady/passes/opt_mem2reg.c | 8 +- src/shady/passes/opt_restructure.c | 4 +- src/shady/print.c | 31 +++--- src/shady/type.c | 12 +-- 14 files changed, 253 insertions(+), 214 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 9459ec4e0..82cb2834d 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -423,11 +423,12 @@ { "name": "Loop", "snake_name": "loop_instr", - "class": "instruction", + "class": ["terminator", "structured_construct"], "ops": [ { "name": "yield_types", "class": "type", "list": true }, { "name": "body", "class": "case" }, - { "name": "initial_args", "class": "value", "list": true } + { "name": "initial_args", "class": "value", "list": true }, + { "name": "tail", "class": "case" } ] }, { diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 6c1c4c80f..369e37bf9 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -497,6 +497,37 @@ static void emit_match(Emitter* emitter, Printer* p, Match match) { emit_terminator(emitter, p, get_abstraction_body(match.tail)); } +static void emit_loop(Emitter* emitter, Printer* p, Loop loop) { + Emitter sub_emiter = *emitter; + Nodes params = get_abstraction_params(loop.body); + Nodes variables = params; + LARRAY(String, arr, variables.count); + for (size_t i = 0; i < variables.count; i++) { + arr[i] = get_value_name_unsafe(variables.nodes[i]); + if (!arr[i]) + arr[i] = unique_name(emitter->arena, "phi"); + } + Strings param_names = strings(emitter->arena, variables.count, arr); + Strings eparams = emit_variable_declarations(emitter, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop.initial_args); + for (size_t i = 0; i < params.count; i++) + register_emitted(&sub_emiter, params.nodes[i], term_from_cvalue(eparams.strings[i])); + + sub_emiter.phis.loop_continue = eparams; + Strings ephis = emit_variable_declarations(emitter, p, "loop_break_phi", NULL, loop.yield_types, true, NULL); + sub_emiter.phis.loop_break = ephis; + + String body = emit_lambda_body(&sub_emiter, get_abstraction_body(loop.body), NULL); + print(p, "\nwhile(true) { %s}", body); + free_tmp_str(body); + + Nodes results = get_abstraction_params(loop.tail); + for (size_t i = 0; i < ephis.count; i++) { + register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + } + + emit_terminator(emitter, p, get_abstraction_body(loop.tail)); +} + static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { switch (is_terminator(terminator)) { case NotATerminator: assert(false); @@ -561,6 +592,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node } case If_TAG: return emit_if(emitter, block_printer, terminator->payload.if_instr); case Match_TAG: return emit_match(emitter, block_printer, terminator->payload.match_instr); + case Loop_TAG: return emit_loop(emitter, block_printer, terminator->payload.loop_instr); case Terminator_Return_TAG: { Nodes args = terminator->payload.fn_ret.args; if (args.count == 0) { diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 0678d3a81..7d10a1f6e 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -648,39 +648,6 @@ static void emit_call(Emitter* emitter, Printer* p, const Node* call, Instructio free_tmp_str(params); } -static void emit_loop(Emitter* emitter, Printer* p, const Node* loop_instr, InstructionOutputs outputs) { - assert(loop_instr->tag == Loop_TAG); - const Loop* loop = &loop_instr->payload.loop_instr; - - Emitter sub_emiter = *emitter; - Nodes params = get_abstraction_params(loop->body); - Nodes variables = params; - LARRAY(String, arr, variables.count); - for (size_t i = 0; i < variables.count; i++) { - arr[i] = get_value_name_unsafe(variables.nodes[i]); - if (!arr[i]) - arr[i] = unique_name(emitter->arena, "phi"); - } - Strings param_names = strings(emitter->arena, variables.count, arr); - Strings eparams = emit_variable_declarations(emitter, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop_instr->payload.loop_instr.initial_args); - for (size_t i = 0; i < params.count; i++) - register_emitted(&sub_emiter, params.nodes[i], term_from_cvalue(eparams.strings[i])); - - sub_emiter.phis.loop_continue = eparams; - Strings ephis = emit_variable_declarations(emitter, p, "loop_break_phi", NULL, loop->yield_types, true, NULL); - sub_emiter.phis.loop_break = ephis; - - String body = emit_lambda_body(&sub_emiter, get_abstraction_body(loop->body), NULL); - print(p, "\nwhile(true) { %s}", body); - free_tmp_str(body); - - assert(outputs.count == ephis.count); - for (size_t i = 0; i < outputs.count; i++) { - outputs.results[i] = term_from_cvalue(ephis.strings[i]); - outputs.binding[i] = NoBinding; - } -} - static void emit_lea(Emitter* emitter, Printer* p, Lea lea, InstructionOutputs outputs) { IrArena* arena = emitter->arena; CTerm acc = emit_value(emitter, p, lea.ptr); @@ -782,7 +749,6 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_LetMut_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; - case Instruction_Loop_TAG: emit_loop (emitter, p, instruction, outputs); break; case Instruction_Control_TAG: error("TODO") case Instruction_Block_TAG: error("Should be eliminated by the compiler") case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 415b7cb20..275c98e82 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -221,7 +221,6 @@ static void emit_if(Emitter* emitter, FnBuilder fn_builder, BBBuilder* pbb_build static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Match match) { Nodes yield_types = match.yield_types; - Nodes results = get_abstraction_params(match.tail); SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); @@ -252,6 +251,7 @@ static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_bui // When 'join' is codegen'd, these will be filled with the values given to it BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); LARRAY(SpvbPhi*, join_phis, yield_types.count); + Nodes results = get_abstraction_params(match.tail); for (size_t i = 0; i < yield_types.count; i++) { SpvId phi_id = spvb_fresh_id(emitter->file_builder); SpvId type = emit_type(emitter, yield_types.nodes[i]); @@ -282,6 +282,89 @@ static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_bui emit_terminator(emitter, fn_builder, *bb_builder, *merge_targets, get_abstraction_body(match.tail)); } +static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Loop loop_instr) { + Nodes yield_types = loop_instr.yield_types; + + const Node* body = loop_instr.body; + assert(is_case(body)); + Nodes body_params = body->payload.case_.params; + + // First we create all the basic blocks we'll need + SpvId header_id = spvb_fresh_id(emitter->file_builder); + BBBuilder header_builder = spvb_begin_bb(fn_builder, header_id); + spvb_name(emitter->file_builder, header_id, "loop_header"); + + SpvId body_id = spvb_fresh_id(emitter->file_builder); + BBBuilder body_builder = spvb_begin_bb(fn_builder, body_id); + spvb_name(emitter->file_builder, body_id, "loop_body"); + + SpvId continue_id = spvb_fresh_id(emitter->file_builder); + BBBuilder continue_builder = spvb_begin_bb(fn_builder, continue_id); + spvb_name(emitter->file_builder, continue_id, "loop_continue"); + + SpvId next_id = spvb_fresh_id(emitter->file_builder); + BBBuilder next = spvb_begin_bb(fn_builder, next_id); + spvb_name(emitter->file_builder, next_id, "loop_next"); + + // Wire up the phi nodes for loop exit + LARRAY(SpvbPhi*, loop_break_phis, yield_types.count); + Nodes results = get_abstraction_params(loop_instr.tail); + for (size_t i = 0; i < yield_types.count; i++) { + SpvId yielded_type = emit_type(emitter, get_unqualified_type(yield_types.nodes[i])); + + SpvId break_phi_id = spvb_fresh_id(emitter->file_builder); + SpvbPhi* phi = spvb_add_phi(next, yielded_type, break_phi_id); + loop_break_phis[i] = phi; + register_result(emitter, results.nodes[i], break_phi_id); + } + + // Wire up the phi nodes for the loop contents + LARRAY(SpvbPhi*, loop_continue_phis, body_params.count); + for (size_t i = 0; i < body_params.count; i++) { + SpvId loop_param_type = emit_type(emitter, get_unqualified_type(body_params.nodes[i]->type)); + + SpvId continue_phi_id = spvb_fresh_id(emitter->file_builder); + SpvbPhi* continue_phi = spvb_add_phi(continue_builder, loop_param_type, continue_phi_id); + loop_continue_phis[i] = continue_phi; + + // To get the actual loop parameter, we make a second phi for the nodes that go into the header + // We already know the two edges into the header so we immediately add the Phi sources for it. + SpvId loop_param_id = spvb_fresh_id(emitter->file_builder); + SpvbPhi* loop_param_phi = spvb_add_phi(header_builder, loop_param_type, loop_param_id); + SpvId param_initial_value = emit_value(emitter, *bb_builder, loop_instr.initial_args.nodes[i]); + spvb_add_phi_source(loop_param_phi, get_block_builder_id(*bb_builder), param_initial_value); + spvb_add_phi_source(loop_param_phi, get_block_builder_id(continue_builder), continue_phi_id); + register_result(emitter, body_params.nodes[i], loop_param_id); + } + + // The current block goes to the header (it can't be the header itself !) + spvb_branch(*bb_builder, header_id); + spvb_add_bb(fn_builder, header_builder); + + // the header block receives the loop merge annotation + spvb_loop_merge(header_builder, next_id, continue_id, 0, 0, NULL); + spvb_branch(header_builder, body_id); + spvb_add_bb(fn_builder, body_builder); + + // Emission of the body requires extra info for the break/continue merge terminators + MergeTargets merge_targets_branches = *merge_targets; + merge_targets_branches.continue_target = continue_id; + merge_targets_branches.continue_phis = loop_continue_phis; + merge_targets_branches.break_target = next_id; + merge_targets_branches.break_phis = loop_break_phis; + emit_terminator(emitter, fn_builder, body_builder, merge_targets_branches, body->payload.case_.body); + + // the continue block just jumps back into the header + spvb_branch(continue_builder, header_id); + spvb_add_bb(fn_builder, continue_builder); + + // We start the next block + spvb_add_bb(fn_builder, next); + *bb_builder = next; + + emit_terminator(emitter, fn_builder, *bb_builder, *merge_targets, get_abstraction_body(loop_instr.tail)); +} + void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_block_builder, MergeTargets merge_targets, const Node* terminator) { switch (is_terminator(terminator)) { case Return_TAG: { @@ -325,6 +408,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo } case If_TAG: return emit_if(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.if_instr); case Match_TAG: return emit_match(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.match_instr); + case Loop_TAG: return emit_loop(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.loop_instr); case Switch_TAG: { SpvId inspectee = emit_value(emitter, basic_block_builder, terminator->payload.br_switch.switch_value); LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 4b3762fbc..1fc5d1a95 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -377,87 +377,6 @@ static void emit_leaf_call(Emitter* emitter, SHADY_UNUSED FnBuilder fn_builder, } } -static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Loop loop_instr, size_t results_count, SpvId results[]) { - Nodes yield_types = loop_instr.yield_types; - assert(yield_types.count == results_count); - - const Node* body = loop_instr.body; - assert(is_case(body)); - Nodes body_params = body->payload.case_.params; - - // First we create all the basic blocks we'll need - SpvId header_id = spvb_fresh_id(emitter->file_builder); - BBBuilder header_builder = spvb_begin_bb(fn_builder, header_id); - spvb_name(emitter->file_builder, header_id, "loop_header"); - - SpvId body_id = spvb_fresh_id(emitter->file_builder); - BBBuilder body_builder = spvb_begin_bb(fn_builder, body_id); - spvb_name(emitter->file_builder, body_id, "loop_body"); - - SpvId continue_id = spvb_fresh_id(emitter->file_builder); - BBBuilder continue_builder = spvb_begin_bb(fn_builder, continue_id); - spvb_name(emitter->file_builder, continue_id, "loop_continue"); - - SpvId next_id = spvb_fresh_id(emitter->file_builder); - BBBuilder next = spvb_begin_bb(fn_builder, next_id); - spvb_name(emitter->file_builder, next_id, "loop_next"); - - // Wire up the phi nodes for loop exit - LARRAY(SpvbPhi*, loop_break_phis, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - SpvId yielded_type = emit_type(emitter, get_unqualified_type(yield_types.nodes[i])); - - SpvId break_phi_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* phi = spvb_add_phi(next, yielded_type, break_phi_id); - loop_break_phis[i] = phi; - results[i] = break_phi_id; - } - - // Wire up the phi nodes for the loop contents - LARRAY(SpvbPhi*, loop_continue_phis, body_params.count); - for (size_t i = 0; i < body_params.count; i++) { - SpvId loop_param_type = emit_type(emitter, get_unqualified_type(body_params.nodes[i]->type)); - - SpvId continue_phi_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* continue_phi = spvb_add_phi(continue_builder, loop_param_type, continue_phi_id); - loop_continue_phis[i] = continue_phi; - - // To get the actual loop parameter, we make a second phi for the nodes that go into the header - // We already know the two edges into the header so we immediately add the Phi sources for it. - SpvId loop_param_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* loop_param_phi = spvb_add_phi(header_builder, loop_param_type, loop_param_id); - SpvId param_initial_value = emit_value(emitter, *bb_builder, loop_instr.initial_args.nodes[i]); - spvb_add_phi_source(loop_param_phi, get_block_builder_id(*bb_builder), param_initial_value); - spvb_add_phi_source(loop_param_phi, get_block_builder_id(continue_builder), continue_phi_id); - register_result(emitter, body_params.nodes[i], loop_param_id); - } - - // The current block goes to the header (it can't be the header itself !) - spvb_branch(*bb_builder, header_id); - spvb_add_bb(fn_builder, header_builder); - - // the header block receives the loop merge annotation - spvb_loop_merge(header_builder, next_id, continue_id, 0, 0, NULL); - spvb_branch(header_builder, body_id); - spvb_add_bb(fn_builder, body_builder); - - // Emission of the body requires extra info for the break/continue merge terminators - MergeTargets merge_targets_branches = *merge_targets; - merge_targets_branches.continue_target = continue_id; - merge_targets_branches.continue_phis = loop_continue_phis; - merge_targets_branches.break_target = next_id; - merge_targets_branches.break_phis = loop_break_phis; - emit_terminator(emitter, fn_builder, body_builder, merge_targets_branches, body->payload.case_.body); - - // the continue block just jumps back into the header - spvb_branch(continue_builder, header_id); - spvb_add_bb(fn_builder, continue_builder); - - // We start the next block - spvb_add_bb(fn_builder, next); - *bb_builder = next; -} - void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, const Node* instruction, size_t results_count, SpvId results[]) { assert(is_instruction(instruction)); @@ -471,7 +390,6 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_Block_TAG: error("Should be lowered elsewhere") case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; case PrimOp_TAG: emit_primop(emitter, fn_builder, *bb_builder, instruction, results_count, results); break; - case Loop_TAG: emit_loop(emitter, fn_builder, bb_builder, merge_targets, instruction->payload.loop_instr, results_count, results); break; case Comment_TAG: break; case Instruction_LocalAlloc_TAG: { SpvId result = spvb_local_variable(fn_builder, emit_type(emitter, ptr_type(emitter->arena, (PtrType) { diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 8061ea8db..856fd1f4c 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -157,9 +157,6 @@ static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node add_structural_dominance_edge(ctx, parent, instruction->payload.block.inside, StructuredEnterBodyEdge); add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); return; - case Instruction_Loop_TAG: - add_structural_dominance_edge(ctx, parent, instruction->payload.loop_instr.body, StructuredEnterBodyEdge); - break; case Instruction_Control_TAG: add_structural_dominance_edge(ctx, parent, instruction->payload.control.inside, StructuredEnterBodyEdge); const Node* param = first(get_abstraction_params(instruction->payload.control.inside)); @@ -216,6 +213,10 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); break; + case Loop_TAG: + add_structural_dominance_edge(ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + break; case MergeSelection_TAG: case MergeContinue_TAG: case MergeBreak_TAG: { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 16364c5ae..4a897f17a 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -144,6 +144,10 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { entry.structured.payload.match_instr.tail = case_(bb->arena, entry.vars, terminator); terminator = match_instr(a, entry.structured.payload.match_instr); break; + case Structured_construct_Loop_TAG: + entry.structured.payload.loop_instr.tail = case_(bb->arena, entry.vars, terminator); + terminator = loop_instr(a, entry.structured.payload.loop_instr); + break; } } return terminator; @@ -233,7 +237,25 @@ Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes } Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Node* body) { - return bind_instruction_outputs_count(bb, loop_instr(bb->arena, (Loop) { .yield_types = yield_types, .initial_args = initial_args, .body = body }), yield_types.count, NULL); + IrArena* a = bb->arena; + Nodes qyield_types = add_qualifiers(a, yield_types, false); + LARRAY(const Node*, tail_params, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) + tail_params[i] = param(a, qyield_types.nodes[i], NULL); + + StackEntry entry = { + .structured = { + .tag = Structured_construct_Loop_TAG, + .payload.loop_instr = { + .yield_types = yield_types, + .initial_args = initial_args, + .body = body + }, + }, + .vars = nodes(a, yield_types.count, tail_params), + }; + append_list(StackEntry , bb->stack, entry); + return entry.vars; } Nodes gen_control(BodyBuilder* bb, Nodes yield_types, const Node* body) { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 75a90482a..7ddfbcea5 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -6,6 +6,8 @@ #include "portability.h" #include "log.h" +#pragma GCC diagnostic error "-Wswitch" + typedef struct { Rewriter rewriter; const UsesMap* map; @@ -64,6 +66,20 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* terminator = get_abstraction_body(get_structured_construct_tail(terminator)); continue; } + case Structured_construct_Match_TAG: { + Match payload = terminator->payload.match_instr; + Nodes results = gen_match(bb, payload.yield_types, payload.inspect, payload.literals, payload.cases, payload.default_case); + bind_variables(bb, get_abstraction_params(payload.tail), results); + terminator = get_abstraction_body(get_structured_construct_tail(terminator)); + continue; + } + case Structured_construct_Loop_TAG: { + Loop payload = terminator->payload.loop_instr; + Nodes results = gen_loop(bb, payload.yield_types, payload.initial_args, payload.body); + bind_variables(bb, get_abstraction_params(payload.tail), results); + terminator = get_abstraction_body(get_structured_construct_tail(terminator)); + continue; + } } switch (is_terminator(terminator)) { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 7096e6ecf..2823960d0 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -488,7 +488,7 @@ static const Node* infer_if(Context* ctx, const Node* node) { }); } -static const Node* infer_loop(Context* ctx, const Node* node, const Nodes* expected_types) { +static const Node* infer_loop(Context* ctx, const Node* node) { assert(node->tag == Loop_TAG); IrArena* a = ctx->rewriter.dst_arena; Context loop_body_ctx = *ctx; @@ -518,6 +518,7 @@ static const Node* infer_loop(Context* ctx, const Node* node, const Nodes* expec .yield_types = loop_yield_types, .initial_args = nodes(a, old_params.count, new_initial_args), .body = nbody, + .tail = infer_case(ctx, node->payload.loop_instr.tail, qual_yield_types) }); } @@ -567,7 +568,6 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes switch (is_instruction(node)) { case PrimOp_TAG: return infer_primop(ctx, node, expected_types); case Call_TAG: return infer_indirect_call(ctx, node, expected_types); - case Loop_TAG: return infer_loop (ctx, node, expected_types); case Control_TAG: return infer_control(ctx, node, expected_types); case Block_TAG: return infer_block (ctx, node, expected_types); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); @@ -614,6 +614,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { case NotATerminator: assert(false); case If_TAG: return infer_if (ctx, node); case Match_TAG: error("TODO") + case Loop_TAG: return infer_loop (ctx, node); case Let_TAG: { // const Node* otail = node->payload.let.ttail; // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index aa50c8fe6..08a8ec1e1 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -25,50 +25,6 @@ static const Node* process_instruction(Context* ctx, const Node* old_instruction IrArena* a = ctx->rewriter.dst_arena; switch (old_instruction->tag) { - // TODO: match - case Loop_TAG: { - const Node* old_loop_body = old_instruction->payload.loop_instr.body; - assert(is_case(old_loop_body)); - - Nodes yield_types = rewrite_nodes(&ctx->rewriter, old_instruction->payload.loop_instr.yield_types); - Nodes param_types = rewrite_nodes(&ctx->rewriter, get_param_types(a, old_loop_body->payload.case_.params)); - param_types = strip_qualifiers(a, param_types); - - const Type* break_jp_type = qualified_type(a, (QualifiedType) { - .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), - .is_uniform = false, - }); - const Type* continue_jp_type = qualified_type(a, (QualifiedType) { - .type = join_point_type(a, (JoinPointType) { .yield_types = param_types }), - .is_uniform = false, - }); - const Node* break_point = param(a, break_jp_type, "loop_break_point"); - const Node* continue_point = param(a, continue_jp_type, "loop_continue_point"); - Context join_context = *ctx; - Nodes jps = mk_nodes(a, break_point, continue_point); - insert_dict(const Node*, Nodes, ctx->structured_join_tokens, old_instruction, jps); - - Nodes new_params = recreate_params(&ctx->rewriter, old_loop_body->payload.case_.params); - Node* loop_body = basic_block(a, new_params, unique_name(a, "loop_body")); - register_processed_list(&join_context.rewriter, old_loop_body->payload.case_.params, loop_body->payload.basic_block.params); - - join_context.abs = old_loop_body; - const Node* inner_control_body = rewrite_node(&join_context.rewriter, old_loop_body->payload.case_.body); - const Node* inner_control_lam = case_(a, nodes(a, 1, (const Node* []) {continue_point}), inner_control_body); - - BodyBuilder* inner_bb = begin_body(a); - Nodes args = gen_control(inner_bb, param_types, inner_control_lam); - - // TODO let_in_block or use a Jump ! - loop_body->payload.basic_block.body = finish_body(inner_bb, jump(a, (Jump) { .target = loop_body, .args = args })); - - const Node* initial_jump = jump(a, (Jump) { - .target = loop_body, - .args = rewrite_nodes(&ctx->rewriter, old_instruction->payload.loop_instr.initial_args), - }); - BodyBuilder* outer_bb = begin_body(a); - return yield_values_and_wrap_in_block(outer_bb, gen_control(outer_bb, yield_types, case_(a, singleton(break_point), initial_jump))); - } default: break; } @@ -156,6 +112,57 @@ static const Node* process_node(Context* ctx, const Node* node) { // return control(a) //return yield_values_and_wrap_in_block(bb, ); } + // TODO: match + case Loop_TAG: { + const Node* old_loop_body = node->payload.loop_instr.body; + assert(is_case(old_loop_body)); + + Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.yield_types); + Nodes param_types = rewrite_nodes(&ctx->rewriter, get_param_types(a, old_loop_body->payload.case_.params)); + param_types = strip_qualifiers(a, param_types); + + const Type* break_jp_type = qualified_type(a, (QualifiedType) { + .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), + .is_uniform = false, + }); + const Type* continue_jp_type = qualified_type(a, (QualifiedType) { + .type = join_point_type(a, (JoinPointType) { .yield_types = param_types }), + .is_uniform = false, + }); + const Node* break_point = param(a, break_jp_type, "loop_break_point"); + const Node* continue_point = param(a, continue_jp_type, "loop_continue_point"); + Context join_context = *ctx; + Nodes jps = mk_nodes(a, break_point, continue_point); + insert_dict(const Node*, Nodes, ctx->structured_join_tokens, node, jps); + + Nodes new_params = recreate_params(&ctx->rewriter, old_loop_body->payload.case_.params); + Node* loop_body = basic_block(a, new_params, unique_name(a, "loop_body")); + register_processed_list(&join_context.rewriter, old_loop_body->payload.case_.params, loop_body->payload.basic_block.params); + + join_context.abs = old_loop_body; + const Node* inner_control_body = rewrite_node(&join_context.rewriter, old_loop_body->payload.case_.body); + const Node* inner_control_lam = case_(a, nodes(a, 1, (const Node* []) {continue_point}), inner_control_body); + + BodyBuilder* inner_bb = begin_body(a); + Nodes args = gen_control(inner_bb, param_types, inner_control_lam); + + // TODO let_in_block or use a Jump ! + loop_body->payload.basic_block.body = finish_body(inner_bb, jump(a, (Jump) { .target = loop_body, .args = args })); + + const Node* initial_jump = jump(a, (Jump) { + .target = loop_body, + .args = rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.initial_args), + }); + BodyBuilder* outer_bb = begin_body(a); + + Nodes results = gen_control(outer_bb, yield_types, case_(a, singleton(break_point), initial_jump)); + + const Node* otail = get_structured_construct_tail(node); + Node* join = basic_block(a, recreate_params(r, get_abstraction_params(otail)), NULL); + register_processed_list(r, get_abstraction_params(otail), get_abstraction_params(join)); + set_abstraction_body(join, rewrite_node(r, get_abstraction_body(otail))); + return finish_body(outer_bb, jump_helper(a, join, results)); + } case MergeSelection_TAG: { if (!cfnode) break; @@ -163,13 +170,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* selection_instr = NULL; while (dom) { const Node* body = get_abstraction_body(dom->node); - if (body->tag == Let_TAG) { - const Node* instr = get_let_instruction(body); - if (instr->tag == If_TAG || instr->tag == Match_TAG) { - selection_instr = instr; - break; - } - } else if(body->tag == If_TAG) { + if(body->tag == If_TAG || body->tag == Match_TAG) { selection_instr = body; break; } @@ -198,12 +199,9 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* selection_instr = NULL; while (dom) { const Node* body = get_abstraction_body(dom->node); - if (body->tag == Let_TAG) { - const Node* instr = get_let_instruction(body); - if (instr->tag == Loop_TAG) { - selection_instr = instr; - break; - } + if (body->tag == Loop_TAG) { + selection_instr = body; + break; } dom = dom->idom; } @@ -230,12 +228,9 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* selection_instr = NULL; while (dom) { const Node* body = get_abstraction_body(dom->node); - if (body->tag == Let_TAG) { - const Node* instr = get_let_instruction(body); - if (instr->tag == Loop_TAG) { - selection_instr = instr; - break; - } + if (body->tag == Loop_TAG) { + selection_instr = body; + break; } dom = dom->idom; } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 8f212c4c0..e55cd786e 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -444,10 +444,6 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No break; case Instruction_Comment_TAG: break; - case Instruction_Loop_TAG: - mark_values_as_escaping(ctx, kb, oinstruction->payload.loop_instr.initial_args); - // assert(false && "unsupported"); - break; } return recreate_node_identity(r, oinstruction); @@ -501,6 +497,10 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod // TODO: local joins are fine mark_values_as_escaping(ctx, kb, old->payload.join.args); break; + case Terminator_Loop_TAG: + mark_values_as_escaping(ctx, kb, old->payload.loop_instr.initial_args); + // assert(false && "unsupported"); + break; case Terminator_MergeContinue_TAG: break; case Terminator_MergeBreak_TAG: diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 9cb624a07..a9630d015 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -203,7 +203,6 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad const Node* old_instr = get_let_instruction(body); switch (is_instruction(old_instr)) { case NotAnInstruction: assert(false); - case Instruction_Loop_TAG: case Instruction_Block_TAG: error("Should be eliminated by the compiler"); case Instruction_Call_TAG: { const Node* callee = old_instr->payload.call.callee; @@ -330,7 +329,8 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case TailCall_TAG: longjmp(ctx->bail, 1); case If_TAG: - case Match_TAG: error("not supposed to exist in IR at this stage"); + case Match_TAG: + case Loop_TAG: error("not supposed to exist in IR at this stage"); case Terminator_BlockYield_TAG: case Terminator_MergeBreak_TAG: case Terminator_MergeContinue_TAG: diff --git a/src/shady/print.c b/src/shady/print.c index 2f9f3a1ca..1fe677060 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -562,18 +562,6 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf(")"); print_args_list(ctx, node->payload.call.args); break; - } case Loop_TAG: { - printf(GREEN); - printf("loop"); - printf(RESET); - print_yield_types(ctx, node->payload.loop_instr.yield_types); - if (ctx->config.in_cfg) - break; - const Node* body = node->payload.loop_instr.body; - assert(is_case(body)); - print_param_list(ctx, body->payload.case_.params, &node->payload.loop_instr.initial_args); - print_case_body(ctx, body); - break; } case Control_TAG: { printf(BGREEN); if (ctx->uses) { @@ -681,7 +669,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { break; } case If_TAG: { - print_structured_construct_results(ctx, node->payload.if_instr.tail); + print_structured_construct_results(ctx, get_structured_construct_tail(node)); printf(GREEN); printf("if"); printf(RESET); @@ -702,7 +690,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { print_abs_body(ctx, node->payload.if_instr.tail); break; } case Match_TAG: { - print_structured_construct_results(ctx, node->payload.match_instr.tail); + print_structured_construct_results(ctx, get_structured_construct_tail(node)); printf(GREEN); printf("match"); printf(RESET); @@ -737,6 +725,21 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf("\n"); print_abs_body(ctx, node->payload.match_instr.tail); break; + } case Loop_TAG: { + print_structured_construct_results(ctx, get_structured_construct_tail(node)); + printf(GREEN); + printf("loop"); + printf(RESET); + print_yield_types(ctx, node->payload.loop_instr.yield_types); + if (ctx->config.in_cfg) + break; + const Node* body = node->payload.loop_instr.body; + assert(is_case(body)); + print_param_list(ctx, body->payload.case_.params, &node->payload.loop_instr.initial_args); + print_case_body(ctx, body); + printf("\n"); + print_abs_body(ctx, node->payload.loop_instr.tail); + break; } case Return_TAG: printf(BGREEN); printf("return"); diff --git a/src/shady/type.c b/src/shady/type.c index 5a1bff4b6..971e5fcb5 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1026,18 +1026,18 @@ const Type* check_type_if_instr(IrArena* arena, If if_instr) { return noret_type(arena); } -const Type* check_type_loop_instr(IrArena* arena, Loop loop_instr) { - ensure_types_are_data_types(&loop_instr.yield_types); +const Type* check_type_match_instr(IrArena* arena, Match match_instr) { + ensure_types_are_data_types(&match_instr.yield_types); // TODO check param against initial_args // TODO check the contained Merge instrs - return wrap_multiple_yield_types(arena, add_qualifiers(arena, loop_instr.yield_types, false)); + return noret_type(arena); } -const Type* check_type_match_instr(IrArena* arena, Match match_instr) { - ensure_types_are_data_types(&match_instr.yield_types); +const Type* check_type_loop_instr(IrArena* arena, Loop loop_instr) { + ensure_types_are_data_types(&loop_instr.yield_types); // TODO check param against initial_args // TODO check the contained Merge instrs - return wrap_multiple_yield_types(arena, add_qualifiers(arena, match_instr.yield_types, false)); + return noret_type(arena); } const Type* check_type_control(IrArena* arena, Control control) { From 737a4d3eb7665899e9a788cbefab8d69510d4a35 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 11:05:38 +0200 Subject: [PATCH 369/693] made Control a structured construct too --- include/shady/grammar.json | 5 +- src/backend/c/emit_c.c | 1 + src/backend/c/emit_c_instructions.c | 1 - src/backend/spirv/emit_spv.c | 1 + src/backend/spirv/emit_spv_instructions.c | 1 - src/shady/analysis/cfg.c | 14 +-- src/shady/body_builder.c | 23 ++++- src/shady/passes/cleanup.c | 7 ++ src/shady/passes/infer.c | 9 +- src/shady/passes/lift_indirect_targets.c | 39 ++++----- src/shady/passes/lower_tailcalls.c | 6 +- src/shady/passes/opt_mem2reg.c | 8 +- src/shady/passes/opt_restructure.c | 100 +++++++++++----------- src/shady/print.c | 37 ++++---- src/shady/type.c | 2 +- 15 files changed, 146 insertions(+), 108 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 82cb2834d..fb0a481c6 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -433,10 +433,11 @@ }, { "name": "Control", - "class": "instruction", + "class": ["terminator", "structured_construct"], "ops": [ { "name": "yield_types", "class": "type", "list": true }, - { "name": "inside", "class": "case" } + { "name": "inside", "class": "case" }, + { "name": "tail", "class": "case" } ] }, { diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 369e37bf9..709b4fa2b 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -593,6 +593,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node case If_TAG: return emit_if(emitter, block_printer, terminator->payload.if_instr); case Match_TAG: return emit_match(emitter, block_printer, terminator->payload.match_instr); case Loop_TAG: return emit_loop(emitter, block_printer, terminator->payload.loop_instr); + case Control_TAG: error("TODO") case Terminator_Return_TAG: { Nodes args = terminator->payload.fn_ret.args; if (args.count == 0) { diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 7d10a1f6e..7d886e8af 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -749,7 +749,6 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_LetMut_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; - case Instruction_Control_TAG: error("TODO") case Instruction_Block_TAG: error("Should be eliminated by the compiler") case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; case Instruction_StackAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.stack_alloc.type, outputs); diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 275c98e82..7e5824c08 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -422,6 +422,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); return; } + case Terminator_Control_TAG: case Terminator_BlockYield_TAG: case TailCall_TAG: case Join_TAG: error("Lower me"); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 1fc5d1a95..f0856fc99 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -385,7 +385,6 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_CopyBytes_TAG: case Instruction_FillBytes_TAG: case Instruction_LetMut_TAG: - case Instruction_Control_TAG: case Instruction_StackAlloc_TAG: case Instruction_Block_TAG: error("Should be lowered elsewhere") case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 856fd1f4c..6cee27ad1 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -154,15 +154,10 @@ static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); return; case Instruction_Block_TAG: + //error("no puppet you're the puppet") add_structural_dominance_edge(ctx, parent, instruction->payload.block.inside, StructuredEnterBodyEdge); add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); return; - case Instruction_Control_TAG: - add_structural_dominance_edge(ctx, parent, instruction->payload.control.inside, StructuredEnterBodyEdge); - const Node* param = first(get_abstraction_params(instruction->payload.control.inside)); - CFNode* let_tail_cfnode = get_or_enqueue(ctx, let_tail); - insert_dict(const Node*, CFNode*, ctx->join_point_values, param, let_tail_cfnode); - break; } add_structural_dominance_edge(ctx, parent, let_tail, StructuredPseudoExitEdge); } @@ -217,6 +212,13 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_structural_dominance_edge(ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); break; + case Control_TAG: + add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); + const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); + CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); + insert_dict(const Node*, CFNode*, ctx->join_point_values, param, let_tail_cfnode); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + break; case MergeSelection_TAG: case MergeContinue_TAG: case MergeBreak_TAG: { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 4a897f17a..8b66bd325 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -148,6 +148,10 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { entry.structured.payload.loop_instr.tail = case_(bb->arena, entry.vars, terminator); terminator = loop_instr(a, entry.structured.payload.loop_instr); break; + case Structured_construct_Control_TAG: + entry.structured.payload.control.tail = case_(bb->arena, entry.vars, terminator); + terminator = control(a, entry.structured.payload.control); + break; } } return terminator; @@ -259,7 +263,24 @@ Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Nod } Nodes gen_control(BodyBuilder* bb, Nodes yield_types, const Node* body) { - return bind_instruction_outputs_count(bb, control(bb->arena, (Control) { .yield_types = yield_types, .inside = body }), yield_types.count, NULL); + IrArena* a = bb->arena; + Nodes qyield_types = add_qualifiers(a, yield_types, false); + LARRAY(const Node*, tail_params, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) + tail_params[i] = param(a, qyield_types.nodes[i], NULL); + + StackEntry entry = { + .structured = { + .tag = Structured_construct_Control_TAG, + .payload.control = { + .yield_types = yield_types, + .inside = body + }, + }, + .vars = nodes(a, yield_types.count, tail_params), + }; + append_list(StackEntry , bb->stack, entry); + return entry.vars; } void cancel_body(BodyBuilder* bb) { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 7ddfbcea5..07a070244 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -80,6 +80,13 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* terminator = get_abstraction_body(get_structured_construct_tail(terminator)); continue; } + case Structured_construct_Control_TAG: { + Control payload = terminator->payload.control; + Nodes results = gen_control(bb, payload.yield_types, payload.inside); + bind_variables(bb, get_abstraction_params(payload.tail), results); + terminator = get_abstraction_body(get_structured_construct_tail(terminator)); + continue; + } } switch (is_terminator(terminator)) { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 2823960d0..98e66d6c9 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -522,7 +522,7 @@ static const Node* infer_loop(Context* ctx, const Node* node) { }); } -static const Node* infer_control(Context* ctx, const Node* node, const Nodes* expected_types) { +static const Node* infer_control(Context* ctx, const Node* node) { assert(node->tag == Control_TAG); IrArena* a = ctx->rewriter.dst_arena; @@ -533,7 +533,7 @@ static const Node* infer_control(Context* ctx, const Node* node, const Nodes* ex Context joinable_ctx = *ctx; const Type* jpt = join_point_type(a, (JoinPointType) { - .yield_types = yield_types + .yield_types = yield_types }); jpt = qualified_type(a, (QualifiedType) { .is_uniform = true, .type = jpt }); const Node* jp = param(a, jpt, ojp->payload.param.name); @@ -543,7 +543,8 @@ static const Node* infer_control(Context* ctx, const Node* node, const Nodes* ex return control(a, (Control) { .yield_types = yield_types, - .inside = nlam + .inside = nlam, + .tail = infer_case(ctx, get_structured_construct_tail(node), add_qualifiers(a, yield_types, false)) }); } @@ -568,7 +569,6 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes switch (is_instruction(node)) { case PrimOp_TAG: return infer_primop(ctx, node, expected_types); case Call_TAG: return infer_indirect_call(ctx, node, expected_types); - case Control_TAG: return infer_control(ctx, node, expected_types); case Block_TAG: return infer_block (ctx, node, expected_types); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); case Instruction_Lea_TAG: { @@ -615,6 +615,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { case If_TAG: return infer_if (ctx, node); case Match_TAG: error("TODO") case Loop_TAG: return infer_loop (ctx, node); + case Control_TAG: return infer_control(ctx, node); case Let_TAG: { // const Node* otail = node->payload.let.ttail; // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index da88d7e62..ece59dce5 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -198,27 +198,24 @@ static const Node* process_node(Context* ctx, const Node* node) { return recreate_node_identity(&ctx->rewriter, node); switch (node->tag) { - case Let_TAG: { - const Node* oinstruction = get_let_instruction(node); - if (oinstruction->tag == Control_TAG) { - const Node* oinside = oinstruction->payload.control.inside; - assert(is_case(oinside)); - if (!is_control_static(ctx->uses, oinstruction) || ctx->config->hacks.force_join_point_lifting) { - *ctx->todo = true; - - const Node* otail = get_let_tail(node); - BodyBuilder* bb = begin_body(a); - LiftedCont* lifted_tail = lambda_lift(ctx, otail, node->payload.let.variables); - const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); - const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); - - const Node* jp = gen_primop_e(bb, create_joint_point_op, rewrite_nodes(&ctx->rewriter, oinstruction->payload.control.yield_types), mk_nodes(a, tail_ptr, sp)); - // dumbass hack - jp = gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(jp)); - - register_processed(r, first(get_abstraction_params(oinside)), jp); - return finish_body(bb, rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); - } + case Control_TAG: { + const Node* oinside = node->payload.control.inside; + assert(is_case(oinside)); + if (!is_control_static(ctx->uses, node) || ctx->config->hacks.force_join_point_lifting) { + *ctx->todo = true; + + const Node* otail = get_structured_construct_tail(node); + BodyBuilder* bb = begin_body(a); + LiftedCont* lifted_tail = lambda_lift(ctx, otail, node->payload.let.variables); + const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); + const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); + + const Node* jp = gen_primop_e(bb, create_joint_point_op, rewrite_nodes(&ctx->rewriter, node->payload.control.yield_types), mk_nodes(a, tail_ptr, sp)); + // dumbass hack + jp = gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(jp)); + + register_processed(r, first(get_abstraction_params(oinside)), jp); + return finish_body(bb, rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); } break; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 46df24768..678438cb7 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -96,7 +96,8 @@ static const Node* process(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (old->tag) { case Function_TAG: { Context ctx2 = *ctx; @@ -255,7 +256,8 @@ static const Node* process(Context* ctx, const Node* old) { const Node* new_body = case_(a, singleton(new_jp), rewrite_node(&ctx->rewriter, get_abstraction_body(old_inside))); BodyBuilder* bb = begin_body(a); Nodes nyield_types = rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types); - return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, new_body)); + return control(a, (Control) { .yield_types = nyield_types, .inside = new_body, .tail = rewrite_node(r, get_structured_construct_tail(old))}); + //return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, new_body)); } break; } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index e55cd786e..8519c5599 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -438,8 +438,6 @@ static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const No mark_value_as_escaping(ctx, kb, oinstruction->payload.fill_bytes.dst); break; } - case Instruction_Control_TAG: - break; case Instruction_Block_TAG: break; case Instruction_Comment_TAG: @@ -497,10 +495,16 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod // TODO: local joins are fine mark_values_as_escaping(ctx, kb, old->payload.join.args); break; + case Terminator_If_TAG: + break; + case Terminator_Match_TAG: + break; case Terminator_Loop_TAG: mark_values_as_escaping(ctx, kb, old->payload.loop_instr.initial_args); // assert(false && "unsupported"); break; + case Control_TAG: + break; case Terminator_MergeContinue_TAG: break; case Terminator_MergeBreak_TAG: diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index a9630d015..c14789d96 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -217,56 +217,6 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad assert(false); // actually that should not come up. longjmp(ctx->bail, 1); } - // let(control(body), tail) - // var phi = undef; level = N+1; structurize[body, if (level == N+1, _ => tail(load(phi))); structured_exit_terminator] - case Instruction_Control_TAG: { - const Node* old_control_body = old_instr->payload.control.inside; - assert(old_control_body->tag == Case_TAG); - Nodes old_control_params = get_abstraction_params(old_control_body); - assert(old_control_params.count == 1); - - // Create N temporary variables to hold the join point arguments - BodyBuilder* bb_outer = begin_body(a); - Nodes yield_types = rewrite_nodes(&ctx->rewriter, old_instr->payload.control.yield_types); - LARRAY(const Node*, phis, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - const Type* type = yield_types.nodes[i]; - assert(is_data_type(type)); - phis[i] = gen_local_alloc(bb_outer, type); - } - - // Create a new context to rewrite the body with - // TODO: Bail if we try to re-enter the same control construct - Context control_ctx = *ctx; - ControlEntry control_entry = { - .parent = ctx->control_stack, - .old_token = first(old_control_params), - .phis = phis, - .depth = ctx->control_stack ? ctx->control_stack->depth + 1 : 1, - }; - control_ctx.control_stack = &control_entry; - - // Set the depth for threads entering the control body - gen_store(bb_outer, ctx->level_ptr, int32_literal(a, control_entry.depth)); - - // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() - BodyBuilder* bb2 = begin_body(a); - LARRAY(const Node*, phi_values, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - phi_values[i] = gen_load(bb2, phis[i]); - register_processed(&ctx->rewriter, ovars.nodes[i], phi_values[i]); - } - - // Wrap the tail in a guarded if, to handle 'far' joins - const Node* level_value = gen_load(bb2, ctx->level_ptr); - const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); - const Node* true_body = structure(ctx, old_tail, merge_selection(a, (MergeSelection) { .args = empty(a) })); - const Node* if_true_lam = case_(a, empty(a), true_body); - gen_if(bb2, empty(a), guard, if_true_lam, NULL); - - const Node* tail_lambda = case_(a, empty(a), finish_body(bb2, exit_ladder)); - return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), empty(a), tail_lambda))); - } default: { break; } @@ -307,6 +257,56 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad gen_match(bb, empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), nodes(a, body->payload.br_switch.case_jumps.count, cases), default_case); finish_body(bb, exit_ladder); } + // let(control(body), tail) + // var phi = undef; level = N+1; structurize[body, if (level == N+1, _ => tail(load(phi))); structured_exit_terminator] + case Control_TAG: { + const Node* old_control_body = body->payload.control.inside; + assert(old_control_body->tag == Case_TAG); + Nodes old_control_params = get_abstraction_params(old_control_body); + assert(old_control_params.count == 1); + + // Create N temporary variables to hold the join point arguments + BodyBuilder* bb_outer = begin_body(a); + Nodes yield_types = rewrite_nodes(&ctx->rewriter, body->payload.control.yield_types); + LARRAY(const Node*, phis, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) { + const Type* type = yield_types.nodes[i]; + assert(is_data_type(type)); + phis[i] = gen_local_alloc(bb_outer, type); + } + + // Create a new context to rewrite the body with + // TODO: Bail if we try to re-enter the same control construct + Context control_ctx = *ctx; + ControlEntry control_entry = { + .parent = ctx->control_stack, + .old_token = first(old_control_params), + .phis = phis, + .depth = ctx->control_stack ? ctx->control_stack->depth + 1 : 1, + }; + control_ctx.control_stack = &control_entry; + + // Set the depth for threads entering the control body + gen_store(bb_outer, ctx->level_ptr, int32_literal(a, control_entry.depth)); + + // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() + BodyBuilder* bb2 = begin_body(a); + LARRAY(const Node*, phi_values, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) { + phi_values[i] = gen_load(bb2, phis[i]); + register_processed(&ctx->rewriter, get_abstraction_params(get_structured_construct_tail(body)).nodes[i], phi_values[i]); + } + + // Wrap the tail in a guarded if, to handle 'far' joins + const Node* level_value = gen_load(bb2, ctx->level_ptr); + const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); + const Node* true_body = structure(ctx, get_structured_construct_tail(body), merge_selection(a, (MergeSelection) { .args = empty(a) })); + const Node* if_true_lam = case_(a, empty(a), true_body); + gen_if(bb2, empty(a), guard, if_true_lam, NULL); + + const Node* tail_lambda = case_(a, empty(a), finish_body(bb2, exit_ladder)); + return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), empty(a), tail_lambda))); + } case Join_TAG: { ControlEntry* control = search_containing_control(ctx, body->payload.join.join_point); if (!control) diff --git a/src/shady/print.c b/src/shady/print.c index 1fe677060..bb451ebcd 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -562,20 +562,6 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf(")"); print_args_list(ctx, node->payload.call.args); break; - } case Control_TAG: { - printf(BGREEN); - if (ctx->uses) { - if (is_control_static(ctx->uses, node)) - printf("static "); - } - printf("control"); - printf(RESET); - print_yield_types(ctx, node->payload.control.yield_types); - if (ctx->config.in_cfg) - break; - print_param_list(ctx, node->payload.control.inside->payload.case_.params, NULL); - print_case_body(ctx, node->payload.control.inside); - break; } case Block_TAG: { printf(BGREEN); printf("block"); @@ -687,7 +673,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { print_case_body(ctx, node->payload.if_instr.if_false); } printf("\n"); - print_abs_body(ctx, node->payload.if_instr.tail); + print_abs_body(ctx, get_structured_construct_tail(node)); break; } case Match_TAG: { print_structured_construct_results(ctx, get_structured_construct_tail(node)); @@ -723,7 +709,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { deindent(ctx->printer); printf("\n}"); printf("\n"); - print_abs_body(ctx, node->payload.match_instr.tail); + print_abs_body(ctx, get_structured_construct_tail(node)); break; } case Loop_TAG: { print_structured_construct_results(ctx, get_structured_construct_tail(node)); @@ -738,7 +724,24 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { print_param_list(ctx, body->payload.case_.params, &node->payload.loop_instr.initial_args); print_case_body(ctx, body); printf("\n"); - print_abs_body(ctx, node->payload.loop_instr.tail); + print_abs_body(ctx, get_structured_construct_tail(node)); + break; + } case Control_TAG: { + print_structured_construct_results(ctx, get_structured_construct_tail(node)); + printf(BGREEN); + if (ctx->uses) { + if (is_control_static(ctx->uses, node)) + printf("static "); + } + printf("control"); + printf(RESET); + print_yield_types(ctx, node->payload.control.yield_types); + if (ctx->config.in_cfg) + break; + print_param_list(ctx, node->payload.control.inside->payload.case_.params, NULL); + print_case_body(ctx, node->payload.control.inside); + printf("\n"); + print_abs_body(ctx, get_structured_construct_tail(node)); break; } case Return_TAG: printf(BGREEN); diff --git a/src/shady/type.c b/src/shady/type.c index 971e5fcb5..500cb0723 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1056,7 +1056,7 @@ const Type* check_type_control(IrArena* arena, Control control) { assert(is_subtype(control.yield_types.nodes[i], join_point_yield_types.nodes[i])); } - return wrap_multiple_yield_types(arena, add_qualifiers(arena, join_point_yield_types, false)); + return noret_type(arena); } const Type* check_type_block(IrArena* arena, Block payload) { From a1d2ad03a4c837da7102171d5692fc627f8d68be Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 11:12:04 +0200 Subject: [PATCH 370/693] body_builder: simplify generation of structured constructs --- src/shady/body_builder.c | 98 ++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 64 deletions(-) diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 8b66bd325..a7a572e3b 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -193,7 +193,7 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* return bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, instruction, NULL); } -Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { +static Nodes gen_structured_construct(BodyBuilder* bb, Nodes yield_types, Structured_constructTag tag, union NodesUnion payload) { IrArena* a = bb->arena; Nodes qyield_types = add_qualifiers(a, yield_types, false); LARRAY(const Node*, tail_params, yield_types.count); @@ -202,13 +202,8 @@ Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const No StackEntry entry = { .structured = { - .tag = Structured_construct_If_TAG, - .payload.if_instr = { - .condition = condition, - .if_true = true_case, - .if_false = false_case, - .yield_types = yield_types, - }, + .tag = tag, + .payload = payload, }, .vars = nodes(a, yield_types.count, tail_params), }; @@ -216,71 +211,46 @@ Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const No return entry.vars; } -Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, const Node* default_case) { - IrArena* a = bb->arena; - Nodes qyield_types = add_qualifiers(a, yield_types, false); - LARRAY(const Node*, tail_params, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) - tail_params[i] = param(a, qyield_types.nodes[i], NULL); +Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { + return gen_structured_construct(bb, yield_types, Structured_construct_If_TAG, (union NodesUnion) { + .if_instr = { + .condition = condition, + .if_true = true_case, + .if_false = false_case, + .yield_types = yield_types, + } + }); +} - StackEntry entry = { - .structured = { - .tag = Structured_construct_Match_TAG, - .payload.match_instr = { - .yield_types = yield_types, - .inspect = inspectee, - .literals = literals, - .cases = cases, - .default_case = default_case - }, - }, - .vars = nodes(a, yield_types.count, tail_params), - }; - append_list(StackEntry , bb->stack, entry); - return entry.vars; +Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, const Node* default_case) { + return gen_structured_construct(bb, yield_types, Structured_construct_Match_TAG, (union NodesUnion) { + .match_instr = { + .yield_types = yield_types, + .inspect = inspectee, + .literals = literals, + .cases = cases, + .default_case = default_case + } + }); } Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Node* body) { - IrArena* a = bb->arena; - Nodes qyield_types = add_qualifiers(a, yield_types, false); - LARRAY(const Node*, tail_params, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) - tail_params[i] = param(a, qyield_types.nodes[i], NULL); - - StackEntry entry = { - .structured = { - .tag = Structured_construct_Loop_TAG, - .payload.loop_instr = { - .yield_types = yield_types, - .initial_args = initial_args, - .body = body - }, + return gen_structured_construct(bb, yield_types, Structured_construct_Loop_TAG, (union NodesUnion) { + .loop_instr = { + .yield_types = yield_types, + .initial_args = initial_args, + .body = body }, - .vars = nodes(a, yield_types.count, tail_params), - }; - append_list(StackEntry , bb->stack, entry); - return entry.vars; + }); } Nodes gen_control(BodyBuilder* bb, Nodes yield_types, const Node* body) { - IrArena* a = bb->arena; - Nodes qyield_types = add_qualifiers(a, yield_types, false); - LARRAY(const Node*, tail_params, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) - tail_params[i] = param(a, qyield_types.nodes[i], NULL); - - StackEntry entry = { - .structured = { - .tag = Structured_construct_Control_TAG, - .payload.control = { - .yield_types = yield_types, - .inside = body - }, + return gen_structured_construct(bb, yield_types, Structured_construct_Control_TAG, (union NodesUnion) { + .control = { + .yield_types = yield_types, + .inside = body }, - .vars = nodes(a, yield_types.count, tail_params), - }; - append_list(StackEntry , bb->stack, entry); - return entry.vars; + }); } void cancel_body(BodyBuilder* bb) { From 5c8e6b64eaa79d1c437975a687977ff85e1c1ae2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 11:31:03 +0200 Subject: [PATCH 371/693] c: fix segfault in emit_lea --- src/backend/c/emit_c_instructions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 7d886e8af..b44d9b221 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -652,7 +652,7 @@ static void emit_lea(Emitter* emitter, Printer* p, Lea lea, InstructionOutputs o IrArena* arena = emitter->arena; CTerm acc = emit_value(emitter, p, lea.ptr); - const Type* src_qtype = lea.ptr->type->type; + const Type* src_qtype = lea.ptr->type; bool uniform = is_qualified_type_uniform(src_qtype); const Type* curr_ptr_type = get_unqualified_type(src_qtype); assert(curr_ptr_type->tag == PtrType_TAG); From 3f0575fcb89dd6aafaa646483d20be511ea79c25 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 11:32:26 +0200 Subject: [PATCH 372/693] clean up how body_builder deals with structured constructs --- include/shady/ir.h | 2 -- src/shady/body_builder.c | 41 +++++++++------------ src/shady/passes/cleanup.c | 45 +++++++----------------- src/shady/passes/lift_indirect_targets.c | 2 +- 4 files changed, 31 insertions(+), 59 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 7c810500b..7b65dbe8b 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -298,8 +298,6 @@ Nodes bind_instruction_explicit_result_types(BodyBuilder*, const Node* initial_v Nodes create_mutable_variables(BodyBuilder*, const Node* initial_value, Nodes provided_types, String const output_names[]); Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count, String const output_names[]); -void bind_variables(BodyBuilder*, Nodes vars, Nodes values); - const Node* finish_body(BodyBuilder*, const Node* terminator); void cancel_body(BodyBuilder*); const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder*, Nodes, const Nodes*); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index a7a572e3b..a6856daba 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -12,13 +12,11 @@ #pragma GCC diagnostic error "-Wswitch" typedef struct { - //struct List* stack; Structured_constructTag tag; union NodesUnion payload; } BlockEntry; typedef struct { - const Node* instr; BlockEntry structured; Nodes vars; } StackEntry; @@ -28,7 +26,6 @@ BodyBuilder* begin_body(IrArena* a) { *bb = (BodyBuilder) { .arena = a, .stack = new_list(StackEntry), - //.stack_stack = new_list(BlockEntry), }; return bb; } @@ -79,8 +76,11 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp } Nodes params = create_output_variables(bb->arena, instruction, outputs_count, provided_types, output_names); StackEntry entry = { - .instr = instruction, - .vars = params, + .vars = empty(bb->arena), + .structured.payload.let = { + .instruction = instruction, + .variables = params, + } }; append_list(StackEntry, bb->stack, entry); return params; @@ -111,22 +111,6 @@ Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, s return bind_internal(bb, instruction, outputs_count, NULL, output_names); } -void bind_variables(BodyBuilder* bb, Nodes vars, Nodes values) { - StackEntry entry = { - .instr = quote_helper(bb->arena, values), - .vars = vars, - }; - append_list(StackEntry, bb->stack, entry); -} - -void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr) { - StackEntry entry = { - .instr = instr, - .vars = vars, - }; - append_list(StackEntry, bb->stack, entry); -} - static const Node* build_body(BodyBuilder* bb, const Node* terminator) { IrArena* a = bb->arena; size_t stack_size = entries_count_list(bb->stack); @@ -134,7 +118,8 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { StackEntry entry = read_list(StackEntry, bb->stack)[i]; switch (entry.structured.tag) { case NotAStructured_construct: - terminator = let(a, entry.instr, entry.vars, case_(bb->arena, empty(bb->arena), terminator)); + entry.structured.payload.let.tail = case_(bb->arena, entry.vars, terminator); + terminator = let(a, entry.structured.payload.let.instruction, entry.structured.payload.let.variables, entry.structured.payload.let.tail); break; case Structured_construct_If_TAG: entry.structured.payload.if_instr.tail = case_(bb->arena, entry.vars, terminator); @@ -193,24 +178,32 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* return bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, instruction, NULL); } -static Nodes gen_structured_construct(BodyBuilder* bb, Nodes yield_types, Structured_constructTag tag, union NodesUnion payload) { +static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { IrArena* a = bb->arena; + Nodes qyield_types = add_qualifiers(a, yield_types, false); LARRAY(const Node*, tail_params, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) tail_params[i] = param(a, qyield_types.nodes[i], NULL); + return nodes(a, yield_types.count, tail_params); +} +Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constructTag tag, union NodesUnion payload) { StackEntry entry = { .structured = { .tag = tag, .payload = payload, }, - .vars = nodes(a, yield_types.count, tail_params), + .vars = params, }; append_list(StackEntry , bb->stack, entry); return entry.vars; } +static Nodes gen_structured_construct(BodyBuilder* bb, Nodes yield_types, Structured_constructTag tag, union NodesUnion payload) { + return add_structured_construct(bb, gen_variables(bb, yield_types), tag, payload); +} + Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { return gen_structured_construct(bb, yield_types, Structured_construct_If_TAG, (union NodesUnion) { .if_instr = { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 07a070244..be3312b32 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -30,7 +30,12 @@ static size_t count_calls(const UsesMap* map, const Node* bb) { return count; } -void bind_variables2(BodyBuilder* bb, Nodes vars, const Node* instr); +Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constructTag tag, union NodesUnion payload); + +static void reset_params(Nodes params) { + for (size_t i = 0; i < params.count; i++) + ((Node*) params.nodes[i])->payload.param.abs = NULL; +} // eliminates blocks by "lifting" their contents out and replacing yield with the tail of the outer let // In other words, we turn these patterns: @@ -57,42 +62,18 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* assert(is_case(lam)); const Node* terminator = get_abstraction_body(lam); while (true) { - switch (is_structured_construct(terminator)) { - case NotAStructured_construct: break; - case Structured_construct_If_TAG: { - If payload = terminator->payload.if_instr; - Nodes results = gen_if(bb, payload.yield_types, payload.condition, payload.if_true, payload.if_false); - bind_variables(bb, get_abstraction_params(payload.tail), results); - terminator = get_abstraction_body(get_structured_construct_tail(terminator)); - continue; - } - case Structured_construct_Match_TAG: { - Match payload = terminator->payload.match_instr; - Nodes results = gen_match(bb, payload.yield_types, payload.inspect, payload.literals, payload.cases, payload.default_case); - bind_variables(bb, get_abstraction_params(payload.tail), results); - terminator = get_abstraction_body(get_structured_construct_tail(terminator)); - continue; - } - case Structured_construct_Loop_TAG: { - Loop payload = terminator->payload.loop_instr; - Nodes results = gen_loop(bb, payload.yield_types, payload.initial_args, payload.body); - bind_variables(bb, get_abstraction_params(payload.tail), results); - terminator = get_abstraction_body(get_structured_construct_tail(terminator)); - continue; - } - case Structured_construct_Control_TAG: { - Control payload = terminator->payload.control; - Nodes results = gen_control(bb, payload.yield_types, payload.inside); - bind_variables(bb, get_abstraction_params(payload.tail), results); - terminator = get_abstraction_body(get_structured_construct_tail(terminator)); - continue; - } + if (is_structured_construct(terminator)) { + Nodes params = get_abstraction_params(get_structured_construct_tail(terminator)); + reset_params(params); + add_structured_construct(bb, params, (Structured_constructTag) terminator->tag, terminator->payload); + terminator = get_abstraction_body(get_structured_construct_tail(terminator)); + continue; } switch (is_terminator(terminator)) { case NotATerminator: assert(false); case Terminator_Let_TAG: { - bind_variables2(bb, terminator->payload.let.variables, terminator->payload.let.instruction); + add_structured_construct(bb, empty(arena), (Structured_constructTag) NotAStructured_construct, terminator->payload); terminator = get_abstraction_body(terminator->payload.let.tail); continue; } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index ece59dce5..70d1e7115 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -206,7 +206,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* otail = get_structured_construct_tail(node); BodyBuilder* bb = begin_body(a); - LiftedCont* lifted_tail = lambda_lift(ctx, otail, node->payload.let.variables); + LiftedCont* lifted_tail = lambda_lift(ctx, otail, get_abstraction_params(otail)); const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); From ab9a91223b75bb22576d6f90107e588905997b9f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 12:30:30 +0200 Subject: [PATCH 373/693] body_builder: don't pass in types by pointer --- include/shady/ir.h | 4 ++-- src/frontend/llvm/l2s_value.c | 3 +-- src/shady/body_builder.c | 13 ++++++------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 7b65dbe8b..1a2e97315 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -300,9 +300,9 @@ Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, si const Node* finish_body(BodyBuilder*, const Node* terminator); void cancel_body(BodyBuilder*); -const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder*, Nodes, const Nodes*); +const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder*, Nodes, const Nodes); const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); -const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder*, const Node*, const Nodes*); +const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder*, const Node*, const Nodes); const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); #endif diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index bfb106207..cc7db227f 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -85,8 +85,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { insert_dict(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = begin_body(a); EmittedInstr emitted = convert_instruction(p, NULL, NULL, bb, v); - Nodes types = singleton(t); - decl->payload.constant.instruction = bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, emitted.instruction, &types); + decl->payload.constant.instruction = bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, emitted.instruction, singleton(t)); return r; } case LLVMConstantDataArrayValueKind: { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index a6856daba..6f7ff8f16 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -149,33 +149,32 @@ const Node* finish_body(BodyBuilder* bb, const Node* terminator) { return terminator; } -const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder* bb, Nodes values, const Nodes* types) { +const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder* bb, Nodes values, const Nodes types) { IrArena* arena = bb->arena; - assert(arena->config.check_types || types); const Node* terminator = block_yield(arena, (BlockYield) { .args = values }); const Node* lam = case_(arena, empty(arena), finish_body(bb, terminator)); return block(arena, (Block) { - .yield_types = arena->config.check_types ? get_values_types(arena, values) : *types, + .yield_types = types, .inside = lam, }); } const Node* yield_values_and_wrap_in_block(BodyBuilder* bb, Nodes values) { - return yield_values_and_wrap_in_block_explicit_return_types(bb, values, NULL); + return yield_values_and_wrap_in_block_explicit_return_types(bb, values, get_values_types(bb->arena, values)); } -const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder* bb, const Node* instruction, const Nodes* types) { +const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder* bb, const Node* instruction, const Nodes types) { size_t stack_size = entries_count_list(bb->stack); if (stack_size == 0) { cancel_body(bb); return instruction; } - Nodes bound = bind_internal(bb, instruction, types ? types->count : SIZE_MAX, types ? types->nodes : NULL, NULL); + Nodes bound = bind_internal(bb, instruction, types.count, types.nodes, NULL); return yield_values_and_wrap_in_block_explicit_return_types(bb, bound, types); } const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* instruction) { - return bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, instruction, NULL); + return bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type)); } static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { From 55e005ccb762394105bd7fbf8256efc1e0c7e692 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 13:06:49 +0200 Subject: [PATCH 374/693] make stack ops into nodes --- include/shady/primops.json | 58 +++++++-------- src/backend/c/emit_c_instructions.c | 10 +-- src/backend/spirv/emit_spv_instructions.c | 5 ++ src/shady/analysis/cfg.c | 5 ++ src/shady/passes/cleanup.c | 2 +- src/shady/passes/infer.c | 23 +++--- src/shady/passes/lift_indirect_targets.c | 18 ++--- src/shady/passes/lower_alloca.c | 18 ++--- src/shady/passes/lower_stack.c | 88 ++++++++++++----------- src/shady/passes/lower_tailcalls.c | 6 +- src/shady/passes/opt_stack.c | 45 +++++------- src/shady/passes/setup_stack_frames.c | 12 ++-- src/shady/transform/ir_gen_helpers.c | 16 ++++- src/shady/transform/ir_gen_helpers.h | 3 + src/shady/type.c | 61 ++++++---------- 15 files changed, 181 insertions(+), 189 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index 4f8455666..bc564888a 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -15,12 +15,6 @@ { "name": "math" }, - { - "name": "stack" - }, - { - "name": "memory" - }, { "name": "memory_layout" }, @@ -186,29 +180,6 @@ "name": "cos", "class": "math" }, - { - "name": "push_stack", - "class": "stack", - "side-effects": true - }, - { - "name": "pop_stack", - "class": "stack", - "side-effects": true - }, - { - "name": "get_stack_size", - "class": "stack" - }, - { - "name": "get_stack_base", - "class": "stack" - }, - { - "name": "set_stack_size", - "class": "stack", - "side-effects": true - }, { "name": "size_of", "class": "memory_layout" @@ -372,6 +343,35 @@ { "name": "src", "class": "value" }, { "name": "count", "class": "value" } ] + }, + { + "name": "PushStack", + "class": "instruction", + "ops": [ + { "name": "value", "class": "value" } + ] + }, + { + "name": "PopStack", + "class": "instruction", + "ops": [ + { "name": "type", "class": "type" } + ] + }, + { + "name": "GetStackSize", + "class": "instruction" + }, + { + "name": "SetStackSize", + "class": "instruction", + "ops": [ + { "name": "value", "class": "value" } + ] + }, + { + "name": "GetStackBaseAddr", + "class": "instruction" } ] } \ No newline at end of file diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index b44d9b221..52c3e133c 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -525,11 +525,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct term = term_from_cvalue(dst); break; } - case get_stack_base_op: - case push_stack_op: - case pop_stack_op: - case get_stack_size_op: - case set_stack_size_op: error("Stack operations need to be lowered."); case default_join_point_op: case create_joint_point_op: error("lowered in lower_tailcalls.c"); case subgroup_elect_first_op: { @@ -746,6 +741,11 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins switch (is_instruction(instruction)) { case NotAnInstruction: assert(false); + case Instruction_PushStack_TAG: + case Instruction_PopStack_TAG: + case Instruction_GetStackSize_TAG: + case Instruction_SetStackSize_TAG: + case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); case Instruction_LetMut_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index f0856fc99..d81ece4e3 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -382,6 +382,11 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil switch (is_instruction(instruction)) { case NotAnInstruction: error(""); + case Instruction_PushStack_TAG: + case Instruction_PopStack_TAG: + case Instruction_GetStackSize_TAG: + case Instruction_SetStackSize_TAG: + case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); case Instruction_CopyBytes_TAG: case Instruction_FillBytes_TAG: case Instruction_LetMut_TAG: diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 6cee27ad1..97156fd1c 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -151,6 +151,11 @@ static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node case Instruction_FillBytes_TAG: case Instruction_StackAlloc_TAG: case Instruction_LocalAlloc_TAG: + case Instruction_PushStack_TAG: + case Instruction_PopStack_TAG: + case Instruction_GetStackSize_TAG: + case Instruction_SetStackSize_TAG: + case Instruction_GetStackBaseAddr_TAG: add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); return; case Instruction_Block_TAG: diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index be3312b32..8689e111e 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -145,7 +145,7 @@ const Node* process(Context* ctx, const Node* old) { return finish_body(bb, instruction); } Nodes ovars = old->payload.let.variables; - // optimization: eliminate unecessary quotes by rewriting variables into their values directly + // optimization: eliminate unnecessary quotes by rewriting variables into their values directly if (instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { *ctx->todo = true; register_processed_list(r, ovars, instruction->payload.prim_op.operands); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 98e66d6c9..56e366f08 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -361,21 +361,6 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp LARRAY(const Node*, new_operands, old_operands.count); Nodes input_types = empty(a); switch (node->payload.prim_op.op) { - case push_stack_op: { - assert(old_operands.count == 1); - assert(type_args.count == 1); - const Type* element_type = type_args.nodes[0]; - assert(is_data_type(element_type)); - new_operands[0] = infer(ctx, old_operands.nodes[0], qualified_type_helper(element_type, false)); - goto rebuild; - } - case pop_stack_op: { - assert(old_operands.count == 0); - assert(type_args.count == 1); - const Type* element_type = type_args.nodes[0]; - assert(is_data_type(element_type)); - goto rebuild; - } case reinterpret_op: case convert_op: { new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); @@ -567,6 +552,14 @@ static const Node* infer_block(Context* ctx, const Node* node, const Nodes* expe static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes* expected_types) { IrArena* a = ctx->rewriter.dst_arena; switch (is_instruction(node)) { + case Instruction_PushStack_TAG: { + return push_stack(a, (PushStack) { infer_value(ctx, node->payload.push_stack.value, NULL) }); + } + case Instruction_PopStack_TAG: { + const Type* element_type = node->payload.pop_stack.type; + assert(is_data_type(element_type)); + return pop_stack(a, (PopStack) { element_type }); + } case PrimOp_TAG: return infer_primop(ctx, node, expected_types); case Call_TAG: return infer_indirect_call(ctx, node, expected_types); case Block_TAG: return infer_block (ctx, node, expected_types); diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 70d1e7115..0e2429929 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -54,15 +54,10 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, struct L const Type* t = nvar->type; deconstruct_qualified_type(&t); assert(t->tag != PtrType_TAG || !t->payload.ptr_type.is_reference && "References cannot be spilled"); - const Node* save_instruction = prim_op(a, (PrimOp) { - .op = push_stack_op, - .type_arguments = singleton(get_unqualified_type(nvar->type)), - .operands = singleton(nvar), - }); - bind_instruction(builder, save_instruction); + gen_push_value_stack(builder, nvar); } - const Node* sp = gen_primop_ce(builder, get_stack_size_op, 0, NULL); + const Node* sp = gen_get_stack_size(builder); return sp; } @@ -137,7 +132,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable // Recover that stuff inside the new body BodyBuilder* bb = begin_body(a); - gen_primop(bb, set_stack_size_op, empty(a), singleton(payload)); + gen_set_stack_size(bb, payload); for (size_t i = recover_context_size - 1; i < recover_context_size; i--) { const Node* ovar = read_list(const Node*, recover_context)[i]; // assert(ovar->tag == Variable_TAG); @@ -145,10 +140,9 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable const Type* value_type = rewrite_node(&ctx->rewriter, ovar->type); String param_name = get_value_name_unsafe(ovar); - const Node* recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { - .op = pop_stack_op, - .type_arguments = singleton(get_unqualified_type(value_type)) - }), ¶m_name)); + const Node* recovered_value = gen_pop_value_stack(bb, get_unqualified_type(value_type)); + if (param_name) + set_variable_name(recovered_value, param_name); if (is_qualified_type_uniform(ovar->type)) recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }), ¶m_name)); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 7bfc9f6bf..08dcce63e 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -19,8 +19,8 @@ typedef struct Context_ { const CompilerConfig* config; struct Dict* prepared_offsets; - const Node* entry_base_stack_ptr; - const Node* entry_stack_offset; + const Node* base_stack_addr_on_entry; + const Node* stack_size_on_entry; size_t num_slots; const Node* frame_size; @@ -94,9 +94,9 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); ctx2.prepared_offsets = new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); - ctx2.entry_base_stack_ptr = gen_primop_ce(bb, get_stack_base_op, 0, NULL); - String tmp_name = "stack_ptr_before_alloca"; - ctx2.entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_size_op } ), (String []) { tmp_name })); + ctx2.base_stack_addr_on_entry = gen_get_stack_base_addr(bb); + ctx2.stack_size_on_entry = gen_get_stack_size(bb); + set_variable_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); Node* nom_t = nominal_type(m, empty(a), format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); VContext vctx = { @@ -140,21 +140,21 @@ static const Node* process(Context* ctx, const Node* node) { } BodyBuilder* bb = begin_body(a); - if (!ctx->entry_stack_offset) { + if (!ctx->stack_size_on_entry) { //String tmp_name = format_string_arena(a->arena, "stack_ptr_before_alloca_%s", get_abstraction_name(fun)); assert(false); } //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); - const Node* lea_instr = lea(a, (Lea) { ctx->entry_base_stack_ptr, gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->entry_stack_offset, converted_offset)), empty(a) }); + const Node* lea_instr = lea(a, (Lea) {ctx->base_stack_addr_on_entry, gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)), empty(a) }); const Node* slot = first(bind_instruction_named(bb, lea_instr, (String []) { format_string_arena(a->arena, "stack_slot_%d", found_slot->i) })); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = gen_reinterpret_cast(bb, ptr_t, slot); //bool last = found_slot->i == ctx->num_slots - 1; //if (last) { - const Node* updated_stack_ptr = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->entry_stack_offset, ctx->frame_size)); - gen_primop(bb, set_stack_size_op, empty(a), singleton(updated_stack_ptr)); + const Node* updated_stack_ptr = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, ctx->frame_size)); + gen_set_stack_size(bb, updated_stack_ptr); //} return yield_values_and_wrap_in_block(bb, singleton(slot)); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 54f3040cc..db20aeef7 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -110,53 +110,59 @@ static const Node* process_node(Context* ctx, const Node* old) { return new; } - if (old->tag == PrimOp_TAG) { - const PrimOp* oprim_op = &old->payload.prim_op; - switch (oprim_op->op) { - case get_stack_size_op: { - assert(ctx->stack); - BodyBuilder* bb = begin_body(a); - const Node* sp = gen_load(bb, ctx->stack_pointer); - return yield_values_and_wrap_in_block(bb, singleton(sp)); - } - case set_stack_size_op: { - assert(ctx->stack); - BodyBuilder* bb = begin_body(a); - const Node* val = rewrite_node(&ctx->rewriter, oprim_op->operands.nodes[0]); - gen_store(bb, ctx->stack_pointer, val); - return yield_values_and_wrap_in_block(bb, empty(a)); - } - case get_stack_base_op: { - assert(ctx->stack); - BodyBuilder* bb = begin_body(a); - const Node* stack_pointer = ctx->stack_pointer; - const Node* stack_size = gen_load(bb, stack_pointer); - const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); - if (ctx->config->printf_trace.stack_size) { - bind_instruction(bb, prim_op(a, (PrimOp) {.op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) {.string = "trace: stack_size=%d\n"}), stack_size)})); - } - return yield_values_and_wrap_in_block(bb, singleton(stack_base_ptr)); + switch (old->tag) { + case GetStackSize_TAG: { + assert(ctx->stack); + BodyBuilder* bb = begin_body(a); + const Node* sp = gen_load(bb, ctx->stack_pointer); + return yield_values_and_wrap_in_block(bb, singleton(sp)); + } + case SetStackSize_TAG: { + assert(ctx->stack); + BodyBuilder* bb = begin_body(a); + const Node* val = rewrite_node(&ctx->rewriter, old->payload.set_stack_size.value); + gen_store(bb, ctx->stack_pointer, val); + return yield_values_and_wrap_in_block(bb, empty(a)); + } + case GetStackBaseAddr_TAG: { + assert(ctx->stack); + BodyBuilder* bb = begin_body(a); + const Node* stack_pointer = ctx->stack_pointer; + const Node* stack_size = gen_load(bb, stack_pointer); + const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); + if (ctx->config->printf_trace.stack_size) { + bind_instruction(bb, prim_op(a, (PrimOp) {.op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) {.string = "trace: stack_size=%d\n"}), stack_size)})); } - case push_stack_op: - case pop_stack_op: { - assert(ctx->stack); - BodyBuilder* bb = begin_body(a); - const Type* element_type = rewrite_node(&ctx->rewriter, first(oprim_op->type_arguments)); + return yield_values_and_wrap_in_block(bb, singleton(stack_base_ptr)); + } + case PushStack_TAG:{ + assert(ctx->stack); + BodyBuilder* bb = begin_body(a); + const Type* element_type = rewrite_node(&ctx->rewriter, get_unqualified_type(old->payload.push_stack.value->type)); - bool push = oprim_op->op == push_stack_op; + bool push = true; - const Node* fn = gen_fn(ctx, element_type, push); - Nodes args = push ? singleton(rewrite_node(&ctx->rewriter, first(oprim_op->operands))) : empty(a); - Nodes results = bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = args})); + const Node* fn = gen_fn(ctx, element_type, push); + Nodes args = singleton(rewrite_node(&ctx->rewriter, old->payload.push_stack.value)); + Nodes results = bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = args})); - if (push) - return yield_values_and_wrap_in_block(bb, empty(a)); + return yield_values_and_wrap_in_block(bb, empty(a)); + } + case PopStack_TAG: { + assert(ctx->stack); + BodyBuilder* bb = begin_body(a); + const Type* element_type = rewrite_node(&ctx->rewriter, old->payload.pop_stack.type); - assert(results.count == 1); - return yield_values_and_wrap_in_block(bb, results); - } - default: break; + bool push = false; + + const Node* fn = gen_fn(ctx, element_type, push); + Nodes args = empty(a); + Nodes results = bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = args})); + + assert(results.count == 1); + return yield_values_and_wrap_in_block(bb, results); } + default: break; } return recreate_node_identity(&ctx->rewriter, old); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 678438cb7..7fcd4bf02 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -144,10 +144,12 @@ static const Node* process(Context* ctx, const Node* old) { for (size_t i = 0; i < old->payload.fun.params.count; i++) { const Node* old_param = old->payload.fun.params.nodes[i]; const Type* new_param_type = rewrite_node(&ctx->rewriter, get_unqualified_type(old_param->type)); - const Node* popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = pop_stack_op, .type_arguments = singleton(new_param_type), .operands = empty(a) }), &old_param->payload.param.name)); + const Node* popped = gen_pop_value_stack(bb, new_param_type); + if (old_param->payload.param.name) + set_variable_name((Node*) popped, old_param->payload.param.name); // TODO use the uniform stack instead ? or no ? if (is_qualified_type_uniform(old_param->type)) - popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_broadcast_first_op, .type_arguments = empty(a), .operands =singleton(popped) }), &old_param->payload.param.name)); + popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_broadcast_first_op, .type_arguments = empty(a), .operands = singleton(popped) }), &old_param->payload.param.name)); register_processed(&ctx->rewriter, old_param, popped); } fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body)); diff --git a/src/shady/passes/opt_stack.c b/src/shady/passes/opt_stack.c index 6c58019f6..6fc2531ec 100644 --- a/src/shady/passes/opt_stack.c +++ b/src/shady/passes/opt_stack.c @@ -43,36 +43,25 @@ static const Node* process(Context* ctx, const Node* node) { const Node* old_instruction = node->payload.let.instruction; const Node* ntail = NULL; switch (is_instruction(old_instruction)) { - case PrimOp_TAG: { - switch (old_instruction->payload.prim_op.op) { - case push_stack_op: { - const Node* value = rewrite_node(&ctx->rewriter, first(old_instruction->payload.prim_op.operands)); - entry = (StackState) { - .prev = ctx->state, - .type = VALUE, - .value = value, - .leaks = false, - }; - child_ctx.state = &entry; - is_push = true; - break; - } - case pop_stack_op: { - if (ctx->state) { - child_ctx.state = ctx->state->prev; - is_pop = true; - } - break; - } - default: break; + case Instruction_PushStack_TAG: { + const Node* value = rewrite_node(&ctx->rewriter, old_instruction->payload.push_stack.value); + entry = (StackState) { + .prev = ctx->state, + .type = VALUE, + .value = value, + .leaks = false, + }; + child_ctx.state = &entry; + is_push = true; + break; + } + case Instruction_PopStack_TAG: { + if (ctx->state) { + child_ctx.state = ctx->state->prev; + is_pop = true; } break; } - // We sadly don't handle those yet: - case Match_TAG: - case Control_TAG: - case Loop_TAG: - case If_TAG: case Instruction_Block_TAG: // Leaf calls and indirect calls are not analysed and so they are considered to leak the state // we also need to forget our information about the current state @@ -81,7 +70,7 @@ static const Node* process(Context* ctx, const Node* node) { child_ctx.state = NULL; break; } - case Instruction_Comment_TAG: break; + default: break; case NotAnInstruction: assert(false); } diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 7b106e42f..b3d6041bc 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -17,7 +17,7 @@ typedef struct Context_ { bool disable_lowering; const CompilerConfig* config; - const Node* entry_stack_offset; + const Node* stack_size_on_entry; } Context; static const Node* process(Context* ctx, const Node* node) { @@ -34,7 +34,8 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); if (!ctx2.disable_lowering) { - ctx2.entry_stack_offset = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = get_stack_size_op } ), (String []) {format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun)) })); + ctx2.stack_size_on_entry = gen_get_stack_size(bb); + set_variable_name((Node*) ctx2.stack_size_on_entry, format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun))); } if (node->payload.fun.body) fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); @@ -45,12 +46,9 @@ static const Node* process(Context* ctx, const Node* node) { case Return_TAG: { BodyBuilder* bb = begin_body(a); if (!ctx->disable_lowering) { - assert(ctx->entry_stack_offset); + assert(ctx->stack_size_on_entry); // Restore SP before calling exit - bind_instruction(bb, prim_op(a, (PrimOp) { - .op = set_stack_size_op, - .operands = nodes(a, 1, (const Node* []) {ctx->entry_stack_offset }) - })); + gen_set_stack_size(bb, ctx->stack_size_on_entry); } return finish_body(bb, recreate_node_identity(r, node)); } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 0c428ae56..3c2b70f52 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -40,7 +40,7 @@ const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { } void gen_push_value_stack(BodyBuilder* bb, const Node* value) { - gen_primop(bb, push_stack_op, singleton(get_unqualified_type(value->type)), singleton(value)); + bind_instruction(bb, push_stack(bb->arena, (PushStack) { value })); } void gen_push_values_stack(BodyBuilder* bb, Nodes values) { @@ -51,10 +51,22 @@ void gen_push_values_stack(BodyBuilder* bb, Nodes values) { } const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { - const Node* instruction = prim_op(bb->arena, (PrimOp) { .op = pop_stack_op, .type_arguments = nodes(bb->arena, 1, (const Node*[]) { type }) }); + const Node* instruction = pop_stack(bb->arena, (PopStack) { .type = type }); return first(bind_instruction(bb, instruction)); } +const Node* gen_get_stack_base_addr(BodyBuilder* bb) { + return first(bind_instruction(bb, get_stack_base_addr(bb->arena))); +} + +const Node* gen_get_stack_size(BodyBuilder* bb) { + return first(bind_instruction(bb, get_stack_size(bb->arena))); +} + +void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { + bind_instruction(bb, set_stack_size(bb->arena, (SetStackSize) { new_size })); +} + const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); return first(bind_instruction(bb, prim_op(bb->arena, (PrimOp) { .op = reinterpret_op, .operands = singleton(src), .type_arguments = singleton(dst)}))); diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 7c928bccb..38583ed3c 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -7,6 +7,9 @@ void gen_push_value_stack(BodyBuilder* bb, const Node* value); void gen_push_values_stack(BodyBuilder* bb, Nodes values); const Node* gen_pop_value_stack(BodyBuilder*, const Type* type); +const Node* gen_get_stack_base_addr(BodyBuilder*); +const Node* gen_get_stack_size(BodyBuilder*); +void gen_set_stack_size(BodyBuilder*, const Node* new_size); Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); Nodes gen_primop(BodyBuilder*, Op, Nodes, Nodes); diff --git a/src/shady/type.c b/src/shady/type.c index 500cb0723..a71111021 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -905,44 +905,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); return qualified_type(arena, (QualifiedType) { .type = join_point_type(arena, (JoinPointType) { .yield_types = empty(arena) }), .is_uniform = true }); } - // Stack stuff - case get_stack_size_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 0); - return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = uint32_type(arena) }); - } - case get_stack_base_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 0); - const Node* ptr = ptr_type(arena, (PtrType) { .pointed_type = uint8_type(arena), .address_space = AsPrivate}); - return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = ptr }); - } - case set_stack_size_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 1); - assert(get_unqualified_type(prim_op.operands.nodes[0]->type) == uint32_type(arena)); - return empty_multiple_return_type(arena); - } - case push_stack_op: { - assert(prim_op.type_arguments.count == 1); - assert(prim_op.operands.count == 1); - const Type* element_type = first(prim_op.type_arguments); - assert(is_data_type(element_type)); - const Type* qual_element_type = qualified_type(arena, (QualifiedType) { - .is_uniform = false, - .type = element_type - }); - // the operand has to be a subtype of the annotated type - assert(is_subtype(qual_element_type, first(prim_op.operands)->type)); - return empty_multiple_return_type(arena); - } - case pop_stack_op:{ - assert(prim_op.operands.count == 0); - assert(prim_op.type_arguments.count == 1); - const Type* element_type = prim_op.type_arguments.nodes[0]; - assert(is_data_type(element_type)); - return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = element_type}); - } // Debugging ops case debug_printf_op: { assert(prim_op.type_arguments.count == 0); @@ -1200,6 +1162,29 @@ const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { return empty_multiple_return_type(a); } +const Type* check_type_push_stack(IrArena* a, PushStack payload) { + assert(payload.value); + return empty_multiple_return_type(a); +} + +const Type* check_type_pop_stack(IrArena* a, PopStack payload) { + return qualified_type_helper(payload.type, false); +} + +const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { + assert(get_unqualified_type(payload.value->type) == uint32_type(a)); + return empty_multiple_return_type(a); +} + +const Type* check_type_get_stack_size(IrArena* a) { + return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = uint32_type(a) }); +} + +const Type* check_type_get_stack_base_addr(IrArena* a) { + const Node* ptr = ptr_type(a, (PtrType) { .pointed_type = uint8_type(a), .address_space = AsPrivate}); + return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = ptr }); +} + const Type* check_type_let(IrArena* arena, Let let) { Nodes produced_types = unwrap_multiple_yield_types(arena, let.instruction->type); Nodes param_types = get_param_types(arena, let.tail->payload.case_.params); From 3728f542deeea6d413f891dc2669e36255769294 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 13:34:05 +0200 Subject: [PATCH 375/693] made 'nominality' a node property --- include/shady/grammar.json | 8 ++++++++ include/shady/ir.h | 7 +------ include/shady/primops.json | 15 +++++++++++++-- src/shady/generator_node.c | 17 +++++++++++++++++ 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index fb0a481c6..e235ae877 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -254,6 +254,7 @@ "name": "Param", "class": ["value", "param"], "constructor": "custom", + "nominal": true, "ops": [ { "name": "type", "class": "type" }, { "name": "name", "class": "string" }, @@ -266,6 +267,7 @@ "snake_name": "varz", "class": ["value", "variable"], "constructor": "custom", + "nominal": true, "ops": [ { "name": "name", "class": "string" }, { "name": "instruction", "class": "instruction" }, @@ -576,6 +578,7 @@ "snake_name": "fun", "class": "declaration", "constructor": "custom", + "nominal": true, "ops": [ { "name": "module", "type": "Module*", "ignore": true }, { "name": "name", "class": "string" }, @@ -590,6 +593,7 @@ "class": "declaration", "constructor": "custom", "description": "Constants are used to express possibly complicated compile-time expressions", + "nominal": true, "ops": [ { "name": "module", "type": "Module*", "ignore": true }, { "name": "name", "class": "string" }, @@ -602,6 +606,7 @@ "name": "GlobalVariable", "class": "declaration", "constructor": "custom", + "nominal": true, "ops": [ { "name": "module", "type": "Module*", "ignore": true }, { "name": "name", "class": "string" }, @@ -616,6 +621,7 @@ "snake_name": "nom_type", "class": "declaration", "constructor": "custom", + "nominal": true, "type": false, "ops": [ { "name": "module", "type": "Module*", "ignore": true }, @@ -664,6 +670,7 @@ "constructor": "custom", "description": "A named abstraction that lives inside a function and can be jumped to", "class": "basic_block", + "nominal": true, "ops": [ { "name": "params", "class": "param", "list": true }, { "name": "body", "class": "terminator" }, @@ -675,6 +682,7 @@ "snake_name": "case_", "constructor": "custom", "class": "case", + "nominal": true, "description": [ "An unnamed abstraction that lives inside a function, and can be used as part of various control-flow constructs" ], diff --git a/include/shady/ir.h b/include/shady/ir.h index 1a2e97315..485d2acd4 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -135,12 +135,7 @@ extern const bool node_type_has_payload[]; //////////////////////////////// Node categories //////////////////////////////// -inline static bool is_nominal(const Node* node) { - NodeTag tag = node->tag; - if (node->tag == PrimOp_TAG && has_primop_got_side_effects(node->payload.prim_op.op)) - return true; - return tag == Function_TAG || tag == BasicBlock_TAG || tag == Constant_TAG || tag == Param_TAG || tag == Variablez_TAG || tag == GlobalVariable_TAG || tag == NominalType_TAG || tag == Case_TAG || tag == StackAlloc_TAG || tag == LocalAlloc_TAG; -} +bool is_nominal(const Node* node); inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } diff --git a/include/shady/primops.json b/include/shady/primops.json index bc564888a..a772425a9 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -291,6 +291,7 @@ { "name": "StackAlloc", "class": "instruction", + "nominal": true, "ops": [ { "name": "type", "class": "type" } ] @@ -298,6 +299,7 @@ { "name": "LocalAlloc", "class": "instruction", + "nominal": true, "ops": [ { "name": "type", "class": "type" } ] @@ -305,6 +307,7 @@ { "name": "Load", "class": "instruction", + "nominal": true, "ops": [ { "name": "ptr", "class": "value" } ] @@ -312,6 +315,7 @@ { "name": "Store", "class": "instruction", + "nominal": true, "ops": [ { "name": "ptr", "class": "value" }, { "name": "value", "class": "value" } @@ -329,6 +333,7 @@ { "name": "CopyBytes", "class": "instruction", + "nominal": true, "ops": [ { "name": "dst", "class": "value" }, { "name": "src", "class": "value" }, @@ -338,6 +343,7 @@ { "name": "FillBytes", "class": "instruction", + "nominal": true, "ops": [ { "name": "dst", "class": "value" }, { "name": "src", "class": "value" }, @@ -347,6 +353,7 @@ { "name": "PushStack", "class": "instruction", + "nominal": true, "ops": [ { "name": "value", "class": "value" } ] @@ -354,24 +361,28 @@ { "name": "PopStack", "class": "instruction", + "nominal": true, "ops": [ { "name": "type", "class": "type" } ] }, { "name": "GetStackSize", - "class": "instruction" + "class": "instruction", + "nominal": true }, { "name": "SetStackSize", "class": "instruction", + "nominal": true, "ops": [ { "name": "value", "class": "value" } ] }, { "name": "GetStackBaseAddr", - "class": "instruction" + "class": "instruction", + "nominal": true } ] } \ No newline at end of file diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 83b934286..e40537899 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -112,6 +112,22 @@ static void generate_node_payload_cmp_fn(Growy* g, json_object* src, json_object growy_append_formatted(g, "}\n"); } +static void generate_node_is_nominal(Growy* g, json_object* nodes) { + growy_append_formatted(g, "bool is_nominal(const Node* node) {\n"); + growy_append_formatted(g, "\tswitch (node->tag) { \n"); + assert(json_object_get_type(nodes) == json_type_array); + for (size_t i = 0; i < json_object_array_length(nodes); i++) { + json_object* node = json_object_array_get_idx(nodes, i); + String name = json_object_get_string(json_object_object_get(node, "name")); + if (json_object_get_boolean(json_object_object_get(node, "nominal"))) { + growy_append_formatted(g, "\t\tcase %s_TAG: return true;\n", name); + } + } + growy_append_formatted(g, "\t\tdefault: return false;\n"); + growy_append_formatted(g, "\t}\n"); + growy_append_formatted(g, "}\n"); +} + static void generate_isa_for_class(Growy* g, json_object* nodes, String class, String capitalized_class, bool use_enum) { assert(json_object_get_type(nodes) == json_type_array); if (use_enum) @@ -190,6 +206,7 @@ void generate(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); generate_address_space_name_fn(g, json_object_object_get(src, "address-spaces")); generate_node_names_string_array(g, nodes); + generate_node_is_nominal(g, nodes); generate_node_has_payload_array(g, nodes); generate_node_payload_hash_fn(g, src, nodes); generate_node_payload_cmp_fn(g, src, nodes); From 3c8a9a91fa58a3ff155d797e84afa73fae881443 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 13:57:02 +0200 Subject: [PATCH 376/693] cfg: remove handling of Block --- src/shady/analysis/cfg.c | 32 +------------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 97156fd1c..c5322eae7 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -137,36 +137,6 @@ static void add_jump_edge(CfgBuildContext* ctx, const Node* src, const Node* j) #pragma GCC diagnostic error "-Wswitch" -static void process_instruction(CfgBuildContext* ctx, CFNode* parent, const Node* instruction, const Node* let_tail) { - switch (is_instruction(instruction)) { - case NotAnInstruction: error("Grammar problem"); - case Instruction_Call_TAG: - case Instruction_PrimOp_TAG: - case Instruction_Comment_TAG: - case Instruction_LetMut_TAG: - case Instruction_Load_TAG: - case Instruction_Store_TAG: - case Instruction_Lea_TAG: - case Instruction_CopyBytes_TAG: - case Instruction_FillBytes_TAG: - case Instruction_StackAlloc_TAG: - case Instruction_LocalAlloc_TAG: - case Instruction_PushStack_TAG: - case Instruction_PopStack_TAG: - case Instruction_GetStackSize_TAG: - case Instruction_SetStackSize_TAG: - case Instruction_GetStackBaseAddr_TAG: - add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); - return; - case Instruction_Block_TAG: - //error("no puppet you're the puppet") - add_structural_dominance_edge(ctx, parent, instruction->payload.block.inside, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, parent, let_tail, LetTailEdge); - return; - } - add_structural_dominance_edge(ctx, parent, let_tail, StructuredPseudoExitEdge); -} - static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { const Node* const abs = node->node; assert(is_abstraction(abs)); @@ -177,7 +147,7 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { switch (is_terminator(terminator)) { case Let_TAG: { const Node* target = get_let_tail(terminator); - process_instruction(ctx, node, get_let_instruction(terminator), target); + add_structural_dominance_edge(ctx, node, target, LetTailEdge); break; } case Jump_TAG: { From e469c6c96b22f9542b4f8980322e5e963e620aec Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 14:38:36 +0200 Subject: [PATCH 377/693] converted debug_printf primop --- include/shady/primops.json | 13 ++++-- src/backend/c/emit_c_instructions.c | 51 +++++++++++------------ src/backend/spirv/emit_spv_instructions.c | 10 ++++- src/frontend/llvm/l2s_instr.c | 16 +++++++ src/frontend/llvm/l2s_postprocess.c | 9 ---- src/frontend/slim/parser.c | 5 +++ src/shady/passes/infer.c | 10 +---- src/shady/passes/lower_physical_ptrs.c | 4 +- src/shady/passes/lower_stack.c | 6 +-- src/shady/passes/lower_tailcalls.c | 12 +++--- src/shady/transform/ir_gen_helpers.c | 4 ++ src/shady/transform/ir_gen_helpers.h | 1 + src/shady/type.c | 10 ++--- 13 files changed, 83 insertions(+), 68 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index a772425a9..d659cbb52 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -260,10 +260,6 @@ { "name": "shuffle" }, - { - "name": "debug_printf", - "side-effects": true - }, { "name": "sample_texture", "side-effects": true @@ -383,6 +379,15 @@ "name": "GetStackBaseAddr", "class": "instruction", "nominal": true + }, + { + "name": "DebugPrintf", + "class": "instruction", + "nominal": true, + "ops": [ + { "name": "string", "class": "string" }, + { "name": "args", "class": "value", "list": true } + ] } ] } \ No newline at end of file diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 52c3e133c..5661a8443 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -555,33 +555,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct } case empty_mask_op: case mask_is_thread_active_op: error("lower_me"); - case debug_printf_op: { - String args_list = ""; - for (size_t i = 0; i < prim_op->operands.count; i++) { - CValue str = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[i])); - - if (emitter->config.dialect == CDialect_ISPC && i > 0) - str = format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); - - if (i > 0) - args_list = format_string_arena(emitter->arena->arena, "%s, %s", args_list, str); - else - args_list = str; - } - switch (emitter->config.dialect) { - case CDialect_ISPC: - print(p, "\nforeach_active(printf_thread_index) { print(%s); }", args_list); - break; - case CDialect_CUDA: - case CDialect_C11: - print(p, "\nprintf(%s);", args_list); - break; - case CDialect_GLSL: warn_print("printf is not supported in GLSL"); - break; - } - - return; - } default: break; case PRIMOPS_COUNT: assert(false); break; } @@ -788,5 +761,29 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins print(p, "\nmemset(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, p, payload.src)), to_cvalue(emitter, c_emit_value(emitter, p, payload.count))); return; } + case Instruction_DebugPrintf_TAG: { + String args_list = format_string_interned(emitter->arena, "\"%s\"", instruction->payload.debug_printf.string); + for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) { + CValue str = to_cvalue(emitter, emit_value(emitter, p, instruction->payload.debug_printf.args.nodes[i])); + + if (emitter->config.dialect == CDialect_ISPC && i > 0) + str = format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); + + args_list = format_string_arena(emitter->arena->arena, "%s, %s", args_list, str); + } + switch (emitter->config.dialect) { + case CDialect_ISPC: + print(p, "\nforeach_active(printf_thread_index) { print(%s); }", args_list); + break; + case CDialect_CUDA: + case CDialect_C11: + print(p, "\nprintf(%s);", args_list); + break; + case CDialect_GLSL: warn_print("printf is not supported in GLSL"); + break; + } + + return; + } } } diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index d81ece4e3..900ecc21b 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -130,8 +130,6 @@ static const IselTableEntry isel_table[] = { [pow_op] = { Plain, Monomorphic, Same, .extended_set = "GLSL.std.450", .op = (SpvOp) GLSLstd450Pow }, [fma_op] = { Plain, Monomorphic, Same, .extended_set = "GLSL.std.450", .op = (SpvOp) GLSLstd450Fma }, - [debug_printf_op] = {Plain, Monomorphic, Void, .extended_set = "NonSemantic.DebugPrintf", .op = (SpvOp) NonSemanticDebugPrintfDebugPrintf}, - [sample_texture_op] = {Plain, Monomorphic, TyOperand, .op = SpvOpImageSampleImplicitLod }, [subgroup_assume_uniform_op] = {Plain, Monomorphic, Same, .op = ISEL_IDENTITY }, @@ -472,5 +470,13 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil } return; } + case Instruction_DebugPrintf_TAG: { + SpvId set_id = get_extended_instruction_set(emitter, "NonSemantic.DebugPrintf"); + LARRAY(SpvId, args, instruction->payload.debug_printf.args.count + 1); + args[0] = emit_value(emitter, *bb_builder, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); + for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) + args[i + 1] = emit_value(emitter, *bb_builder, instruction->payload.debug_printf.args.nodes[i]); + spvb_ext_instruction(*bb_builder, emit_type(emitter, instruction->type), set_id, (SpvOp) NonSemanticDebugPrintfDebugPrintf, instruction->payload.debug_printf.args.count + 1, args); + } } } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 82e9e7ec9..1919ea949 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -605,6 +605,22 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, r = prim_op_helper(a, op, empty(a), nodes(a, num_args, processed_ops)); free(str); goto finish; + } else if (strcmp(keyword, "instruction") == 0) { + char* instructionname = strtok(NULL, "::"); + Nodes ops = convert_operands(p, num_args, instr); + if (strcmp(instructionname, "DebugPrintf") == 0) { + if (ops.count == 0) + error("DebugPrintf called without arguments"); + size_t whocares; + r = debug_printf(a, (DebugPrintf) { + .string = LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), + .args = nodes(a, ops.count - 1, &ops.nodes[1]) + }); + goto finish; + } + + error_print("Unrecognised shady instruction '%s'\n", instructionname); + error_die(); } else { error_print("Unrecognised shady intrinsic '%s'\n", keyword); error_die(); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 0af64e15c..144b13a90 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -108,15 +108,6 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, case PrimOp_TAG: { Nodes old_operands = node->payload.prim_op.operands; switch (node->payload.prim_op.op) { - case debug_printf_op: { - Nodes new_operands = rewrite_nodes(r, old_operands); - String lit = get_string_literal(a, old_operands.nodes[0]); - assert(lit && "debug_printf requires a string literal"); - new_operands = change_node_at_index(a, new_operands, 0, string_lit_helper(a, lit)); - // for (size_t i = 1; i < old_operands.count; i++) - // new_operands[i] = infer(ctx, old_operands.nodes[i], NULL); - return prim_op_helper(a, debug_printf_op, empty(a), new_operands); - } default: break; } break; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 8c2ca53fc..7565d0bf1 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -503,6 +503,11 @@ static const Node* accept_primary_expr(ctxparams) { return stack_alloc(arena, (StackAlloc) { .type = first(ty_args) }); + } else if (strcmp(callee_name, "debug_printf") == 0) { + return debug_printf(arena, (DebugPrintf) { + .string = get_string_literal(arena, first(ops)), + .args = nodes(arena, ops.count - 1, &ops.nodes[1]) + }); } assert(ty_args.count == 0 && "Function calls do not support type arguments"); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 56e366f08..e8da83fd0 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -388,14 +388,6 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp input_types = mk_nodes(a, qualified_type_helper(mask_type(a), false), qualified_type_helper(uint32_type(a), false)); break; } - case debug_printf_op: { - String lit = get_string_literal(a, old_operands.nodes[0]); - assert(lit && "debug_printf requires a string literal"); - new_operands[0] = string_lit_helper(a, lit); - for (size_t i = 1; i < old_operands.count; i++) - new_operands[i] = infer(ctx, old_operands.nodes[i], NULL); - goto rebuild; - } default: { for (size_t i = 0; i < old_operands.count; i++) { new_operands[i] = old_operands.nodes[i] ? infer(ctx, old_operands.nodes[i], NULL) : NULL; @@ -595,7 +587,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes assert(is_data_type(element_type)); return stack_alloc(a, (StackAlloc) { .type = infer_type(ctx, element_type) }); } - default: error("TODO") + default: return recreate_node_identity(&ctx->rewriter, node); case NotAnInstruction: error("not an instruction"); } SHADY_UNREACHABLE; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index e86e3892f..d371e8998 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -96,7 +96,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* widened = acc; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, uint32_type(a), acc); - bind_instruction(bb, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = template }), widened, base_offset) })); + gen_debug_printf(bb, template, mk_nodes(a, widened, base_offset)); } acc = gen_reinterpret_cast(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = element_type->payload.int_type.is_signed }), acc);\ return acc; @@ -200,7 +200,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* widened = value; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, uint32_type(a), value); - bind_instruction(bb, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = template }), widened, base_offset) })); + gen_debug_printf(bb, template, mk_nodes(a, widened, base_offset)); } return; } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index db20aeef7..7817b4162 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -76,8 +76,8 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { // store updated stack size gen_store(bb, stack_pointer, stack_size); if (ctx->config->printf_trace.stack_size) { - bind_instruction(bb, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = name })) })); - bind_instruction(bb, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "stack size after: %d\n" }), stack_size) })); + gen_debug_printf(bb, name, empty(a)); + gen_debug_printf(bb, "stack size after: %d\n", singleton(stack_size)); } if (push) { @@ -131,7 +131,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* stack_size = gen_load(bb, stack_pointer); const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { - bind_instruction(bb, prim_op(a, (PrimOp) {.op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) {.string = "trace: stack_size=%d\n"}), stack_size)})); + gen_debug_printf(bb, "trace: stack_size=%d\n", singleton(stack_size)); } return yield_values_and_wrap_in_block(bb, singleton(stack_base_ptr)); } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 7fcd4bf02..e1ddc1852 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -291,9 +291,9 @@ void generate_top_level_dispatch_fn(Context* ctx) { if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); if (count_iterations) - bind_instruction(loop_body_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: top loop, thread:%d:%d iteration=%d next_fn=%d next_mask=%lx\n" }), sid, local_id, iterations_count_param, next_function, next_mask) })); + gen_debug_printf(loop_body_builder, "trace: top loop, thread:%d:%d iteration=%d next_fn=%d next_mask=%lx\n", mk_nodes(a, sid, local_id, iterations_count_param, next_function, next_mask)); else - bind_instruction(loop_body_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: top loop, thread:%d:%d next_fn=%d next_mask=%lx\n" }), sid, local_id, next_function, next_mask) })); + gen_debug_printf(loop_body_builder, "trace: top loop, thread:%d:%d next_fn=%d next_mask=%lx\n", mk_nodes(a, sid, local_id, next_function, next_mask)); } const Node* iteration_count_plus_one = NULL; @@ -319,13 +319,13 @@ void generate_top_level_dispatch_fn(Context* ctx) { BodyBuilder* zero_if_case_builder = begin_body(a); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); - bind_instruction(zero_if_case_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: kill thread %d:%d\n" }), sid, local_id) })); + gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } const Node* zero_if_true_lam = case_(a, empty(a), finish_body(zero_if_case_builder, break_terminator)); gen_if(zero_case_builder, empty(a), should_run, zero_if_true_lam, NULL); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); - bind_instruction(zero_case_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: thread %d:%d escaped death!\n" }), sid, local_id) })); + gen_debug_printf(zero_case_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } const Node* zero_case_lam = case_(a, nodes(a, 0, NULL), finish_body(zero_case_builder, continue_terminator)); @@ -345,7 +345,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { BodyBuilder* if_builder = begin_body(a); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); - bind_instruction(if_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: thread %d:%d will run fn %ul with mask = %lx\n" }), sid, local_id, fn_lit, next_mask) })); + gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %ul with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } bind_instruction(if_builder, call(a, (Call) { .callee = fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), @@ -373,7 +373,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : nodes(a, 0, NULL), loop_inside_lam); if (ctx->config->printf_trace.god_function) - bind_instruction(dispatcher_body_builder, prim_op(a, (PrimOp) { .op = debug_printf_op, .operands = mk_nodes(a, string_lit(a, (StringLiteral) { .string = "trace: end of top\n" })) })); + gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", empty(a)); (*ctx->top_dispatcher_fn)->payload.fun.body = finish_body(dispatcher_body_builder, fn_ret(a, (Return) { .args = nodes(a, 0, NULL), diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 3c2b70f52..91729605c 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -126,6 +126,10 @@ void gen_comment(BodyBuilder* bb, String str) { bind_instruction(bb, comment(bb->arena, (Comment) { .string = str })); } +void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { + bind_instruction(bb, debug_printf(bb->arena, (DebugPrintf) { pattern, args })); +} + const Node* get_builtin(Module* m, Builtin b) { Nodes decls = get_module_declarations(m); for (size_t i = 0; i < decls.count; i++) { diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 38583ed3c..080271f52 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -29,6 +29,7 @@ void gen_store(BodyBuilder*, const Node* ptr, const Node* value); const Node* gen_lea(BodyBuilder*, const Node* base, const Node* offset, Nodes selectors); const Node* gen_extract(BodyBuilder*, const Node* base, Nodes selectors); void gen_comment(BodyBuilder*, String str); +void gen_debug_printf(BodyBuilder*, String pattern, Nodes args); const Node* get_builtin(Module* m, Builtin b); const Node* get_or_create_builtin(Module* m, Builtin b, String n); const Node* gen_builtin_load(Module*, BodyBuilder*, Builtin); diff --git a/src/shady/type.c b/src/shady/type.c index a71111021..292c1697a 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -905,12 +905,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); return qualified_type(arena, (QualifiedType) { .type = join_point_type(arena, (JoinPointType) { .yield_types = empty(arena) }), .is_uniform = true }); } - // Debugging ops - case debug_printf_op: { - assert(prim_op.type_arguments.count == 0); - // TODO ? - return empty_multiple_return_type(arena); - } case sample_texture_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); @@ -1185,6 +1179,10 @@ const Type* check_type_get_stack_base_addr(IrArena* a) { return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = ptr }); } +const Type* check_type_debug_printf(IrArena* a, DebugPrintf payload) { + return empty_multiple_return_type(a); +} + const Type* check_type_let(IrArena* arena, Let let) { Nodes produced_types = unwrap_multiple_yield_types(arena, let.instruction->type); Nodes param_types = get_param_types(arena, let.tail->payload.case_.params); From 15cd8ca385237172bc1a136567a7a77717451764 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 14:41:46 +0200 Subject: [PATCH 378/693] renamed set_value_name --- include/shady/ir.h | 2 +- src/frontend/llvm/l2s_instr.c | 2 +- src/shady/node.c | 6 +++--- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/opt_restructure.c | 2 +- src/shady/passes/setup_stack_frames.c | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 485d2acd4..047eb5fb9 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -154,7 +154,7 @@ const Node* get_node_by_id(const IrArena*, NodeId); /// Get the name out of a global variable, function or constant String get_value_name_safe(const Node*); String get_value_name_unsafe(const Node*); -void set_variable_name(Node* var, String); +void set_value_name(Node* var, String name); const Node* get_quoted_value(const Node* instruction); const IntLiteral* resolve_to_int_literal(const Node* node); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 1919ea949..868fb9152 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -501,7 +501,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Node* name_node = meta->payload.composite.contents.nodes[2]; String name = get_string_literal(target->arena, name_node); assert(name); - set_variable_name((Node*) target, name); + set_value_name((Node*) target, name); return (EmittedInstr) { 0 }; } if (strcmp(intrinsic, "llvm.dbg.label") == 0) { diff --git a/src/shady/node.c b/src/shady/node.c index a4b2b880e..90e29bcc0 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -26,9 +26,9 @@ String get_value_name_safe(const Node* v) { //return node_tags[v->tag]; } -void set_variable_name(Node* var, String name) { - assert(var->tag == Variablez_TAG); - var->payload.varz.name = string(var->arena, name); +void set_value_name(Node* var, String name) { + if (var->tag == Variablez_TAG) + var->payload.varz.name = string(var->arena, name); } int64_t get_int_literal_value(IntLiteral literal, bool sign_extend) { diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 0e2429929..31897e40f 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -142,7 +142,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable String param_name = get_value_name_unsafe(ovar); const Node* recovered_value = gen_pop_value_stack(bb, get_unqualified_type(value_type)); if (param_name) - set_variable_name(recovered_value, param_name); + set_value_name(recovered_value, param_name); if (is_qualified_type_uniform(ovar->type)) recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }), ¶m_name)); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 08dcce63e..476b25f9c 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -96,7 +96,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.prepared_offsets = new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); ctx2.base_stack_addr_on_entry = gen_get_stack_base_addr(bb); ctx2.stack_size_on_entry = gen_get_stack_size(bb); - set_variable_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); + set_value_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); Node* nom_t = nominal_type(m, empty(a), format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); VContext vctx = { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index e1ddc1852..aeb4bec45 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -146,7 +146,7 @@ static const Node* process(Context* ctx, const Node* old) { const Type* new_param_type = rewrite_node(&ctx->rewriter, get_unqualified_type(old_param->type)); const Node* popped = gen_pop_value_stack(bb, new_param_type); if (old_param->payload.param.name) - set_variable_name((Node*) popped, old_param->payload.param.name); + set_value_name((Node*) popped, old_param->payload.param.name); // TODO use the uniform stack instead ? or no ? if (is_qualified_type_uniform(old_param->type)) popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_broadcast_first_op, .type_arguments = empty(a), .operands = singleton(popped) }), &old_param->payload.param.name)); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index c14789d96..fbcb06b4c 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -379,7 +379,7 @@ static const Node* process(Context* ctx, const Node* node) { TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); const Node* ptr = gen_local_alloc(bb, int32_type(a)); - set_variable_name(ptr, "cf_depth"); + set_value_name(ptr, "cf_depth"); gen_store(bb, ptr, int32_literal(a, 0)); ctx2.level_ptr = ptr; ctx2.fn = new; diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index b3d6041bc..b2200849d 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -35,7 +35,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body(a); if (!ctx2.disable_lowering) { ctx2.stack_size_on_entry = gen_get_stack_size(bb); - set_variable_name((Node*) ctx2.stack_size_on_entry, format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun))); + set_value_name((Node*) ctx2.stack_size_on_entry, format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun))); } if (node->payload.fun.body) fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); From 4daf65339cecc1d9694579cec84069b8ccce727b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 14:47:49 +0200 Subject: [PATCH 379/693] made relevant primop instructions values too --- include/shady/grammar.json | 9 --------- include/shady/primops.json | 23 ++++++++++++++++------- src/backend/c/emit_c.c | 4 ++++ src/backend/spirv/emit_spv.c | 4 ++++ src/shady/passes/infer.c | 2 +- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index e235ae877..872e28b87 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -388,15 +388,6 @@ { "name": "args", "class": "value", "list": true } ] }, - { - "name": "PrimOp", - "class": "instruction", - "ops": [ - { "name": "op", "type": "Op" }, - { "name": "type_arguments", "class": "type", "list": true }, - { "name": "operands", "class": "value", "list": true } - ] - }, { "name": "If", "snake_name": "if_instr", diff --git a/include/shady/primops.json b/include/shady/primops.json index d659cbb52..81c6f0975 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -284,9 +284,18 @@ } ], "nodes": [ + { + "name": "PrimOp", + "class": ["instruction", "value"], + "ops": [ + { "name": "op", "type": "Op" }, + { "name": "type_arguments", "class": "type", "list": true }, + { "name": "operands", "class": "value", "list": true } + ] + }, { "name": "StackAlloc", - "class": "instruction", + "class": ["instruction", "value"], "nominal": true, "ops": [ { "name": "type", "class": "type" } @@ -294,7 +303,7 @@ }, { "name": "LocalAlloc", - "class": "instruction", + "class": ["instruction", "value"], "nominal": true, "ops": [ { "name": "type", "class": "type" } @@ -302,7 +311,7 @@ }, { "name": "Load", - "class": "instruction", + "class": ["instruction", "value"], "nominal": true, "ops": [ { "name": "ptr", "class": "value" } @@ -319,7 +328,7 @@ }, { "name": "Lea", - "class": "instruction", + "class": ["instruction", "value"], "ops": [ { "name": "ptr", "class": "value" }, { "name": "offset", "class": "value" }, @@ -356,7 +365,7 @@ }, { "name": "PopStack", - "class": "instruction", + "class": ["instruction", "value"], "nominal": true, "ops": [ { "name": "type", "class": "type" } @@ -364,7 +373,7 @@ }, { "name": "GetStackSize", - "class": "instruction", + "class": ["instruction", "value"], "nominal": true }, { @@ -377,7 +386,7 @@ }, { "name": "GetStackBaseAddr", - "class": "instruction", + "class": ["instruction", "value"], "nominal": true }, { diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 709b4fa2b..2bc78b9b1 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -213,6 +213,10 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { case Value_UntypedNumber_TAG: error("lower me"); case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); case Variablez_TAG: error("tried to emit a variable: all variables should be register by their binding let !"); + default: { + assert(!is_instruction(value)); + error("Unhandled value for code generation: %s", node_tags[value->tag]); + } case Value_IntLiteral_TAG: { if (value->payload.int_literal.is_signed) emitted = format_string_arena(emitter->arena->arena, "%" PRIi64, value->payload.int_literal.value); diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 7e5824c08..f4781aa9f 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -44,6 +44,10 @@ SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { case Value_ConstrainedValue_TAG: case Value_UntypedNumber_TAG: case Value_FnAddr_TAG: error("Should be lowered away earlier!"); + default: { + assert(!is_instruction(node)); + error("Unhandled value for code generation: %s", node_tags[node->tag]); + } case IntLiteral_TAG: { new = spvb_fresh_id(emitter->file_builder); SpvId ty = emit_type(emitter, node->type); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index e8da83fd0..5843eeb37 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -285,7 +285,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec const Node* value = infer(ctx, node->payload.fill.value, qualified_type(a, (QualifiedType) { .is_uniform = uniform, .type = element_t })); return fill(a, (Fill) { .type = composite_t, .value = value }); } - case Value_NullPtr_TAG: break; + default: break; } return recreate_node_identity(&ctx->rewriter, node); } From 4b4cb4df627e1692dab84703ebc90a3381244aca Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 17:39:22 +0200 Subject: [PATCH 380/693] removed Variables --- include/shady/grammar.json | 26 +---- include/shady/ir.h | 12 +- src/backend/c/emit_c.c | 11 +- src/backend/c/emit_c_instructions.c | 2 +- src/backend/spirv/emit_spv.c | 12 +- src/backend/spirv/emit_spv_instructions.c | 2 +- src/frontend/llvm/l2s_instr.c | 3 - src/frontend/slim/parser.c | 7 +- src/shady/analysis/free_variables.c | 12 +- src/shady/body_builder.c | 71 ++++-------- src/shady/constructors.c | 37 ++----- src/shady/fold.c | 4 +- src/shady/generator_print.c | 9 +- src/shady/node.c | 21 +--- src/shady/passes/bind.c | 60 +++++----- src/shady/passes/cleanup.c | 19 +--- src/shady/passes/infer.c | 32 +++--- src/shady/passes/lower_alloca.c | 3 - src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/normalize.c | 44 ++++++-- src/shady/passes/normalize_builtins.c | 3 - src/shady/passes/opt_demote_alloca.c | 90 ++++++--------- src/shady/passes/opt_mem2reg.c | 20 +--- src/shady/passes/opt_restructure.c | 12 +- src/shady/passes/opt_stack.c | 5 +- src/shady/print.c | 127 ++++++++++++++++------ src/shady/rewrite.c | 33 +----- src/shady/transform/ir_gen_helpers.c | 4 + src/shady/transform/ir_gen_helpers.h | 2 + src/shady/type.c | 6 - src/shady/type_helpers.c | 9 +- 31 files changed, 308 insertions(+), 392 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 872e28b87..aab04ce93 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -88,10 +88,6 @@ "name": "param", "generate-enum": false }, - { - "name": "variable", - "generate-enum": false - }, { "name": "instruction" }, @@ -262,18 +258,6 @@ { "name": "pindex", "type": "unsigned", "ignore": true } ] }, - { - "name": "Variablez", - "snake_name": "varz", - "class": ["value", "variable"], - "constructor": "custom", - "nominal": true, - "ops": [ - { "name": "name", "class": "string" }, - { "name": "instruction", "class": "instruction" }, - { "name": "iindex", "type": "unsigned" } - ] - }, { "name": "ConstrainedValue", "snake_name": "constrained", @@ -435,7 +419,7 @@ }, { "name": "Block", - "class": "instruction", + "class": ["instruction", "value"], "description": "Used as a helper to insert multiple instructions in place of one", "ops": [ { "name": "yield_types", "class": "type", "list": true }, @@ -455,19 +439,19 @@ "constructor": "custom", "ops": [ { "name": "instruction", "class": "instruction" }, - { "name": "variables", "class": "variable", "list": true }, { "name": "tail", "class": "case" } ] }, { - "name": "LetMut", + "name": "BindIdentifiers", "class": "instruction", "constructor": "custom", "front-end-only": true, "ops": [ { "name": "instruction", "class": "instruction" }, - { "name": "variables", "class": "param", "list": true }, - { "name": "types", "class": "type", "list": true } + { "name": "mutable", "type": "bool" }, + { "name": "names", "class": "string", "list": true }, + { "name": "types", "type": "Nodes*" } ] }, { diff --git a/include/shady/ir.h b/include/shady/ir.h index 047eb5fb9..2394e61c8 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -154,7 +154,7 @@ const Node* get_node_by_id(const IrArena*, NodeId); /// Get the name out of a global variable, function or constant String get_value_name_safe(const Node*); String get_value_name_unsafe(const Node*); -void set_value_name(Node* var, String name); +void set_value_name(const Node* var, String name); const Node* get_quoted_value(const Node* instruction); const IntLiteral* resolve_to_int_literal(const Node* node); @@ -189,6 +189,9 @@ void set_abstraction_body (Node* abs, const Node* body); const Node* get_let_instruction(const Node* let); const Node* get_let_tail(const Node* let); +const Node* extract_helper(const Node* composite, const Node* index); +const Node* extract_multiple_ret_types_helper(const Node* composite, int index); + typedef struct { bool enter_loads; bool allow_incompatible_types; @@ -198,8 +201,6 @@ NodeResolveConfig default_node_resolve_config(); const Node* chase_ptr_to_source(const Node*, NodeResolveConfig config); const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config); -/// Resolves a variable to the instruction that produces its value (if any) -const Node* get_var_def(Variablez var); const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config); //////////////////////////////// Constructors //////////////////////////////// @@ -258,9 +259,7 @@ const Node* quote_helper(IrArena*, Nodes values); const Node* prim_op_helper(IrArena*, Op, Nodes, Nodes); // terminators -const Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i); -const Node* let(IrArena*, const Node* instruction, Nodes vars, const Node* tail); -const Node* let_mut(IrArena*, const Node* instruction, Nodes variables, Nodes types); +const Node* let(IrArena*, const Node* instruction, const Node* tail); const Node* jump_helper(IrArena* a, const Node* dst, Nodes args); // decl ctors @@ -290,7 +289,6 @@ Nodes gen_control(BodyBuilder*, Nodes, const Node*); /// Like append instruction, but you explicitly give it information about any yielded values /// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! Nodes bind_instruction_explicit_result_types(BodyBuilder*, const Node* initial_value, Nodes provided_types, String const output_names[]); -Nodes create_mutable_variables(BodyBuilder*, const Node* initial_value, Nodes provided_types, String const output_names[]); Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count, String const output_names[]); const Node* finish_body(BodyBuilder*, const Node* terminator); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 2bc78b9b1..01a129268 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -212,7 +212,6 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { case Value_ConstrainedValue_TAG: case Value_UntypedNumber_TAG: error("lower me"); case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); - case Variablez_TAG: error("tried to emit a variable: all variables should be register by their binding let !"); default: { assert(!is_instruction(value)); error("Unhandled value for code generation: %s", node_tags[value->tag]); @@ -559,18 +558,18 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node const Node* tail = get_let_tail(terminator); assert(tail->tag == Case_TAG); - Nodes vars = terminator->payload.let.variables; - assert(vars.count == yield_types.count); + // Nodes vars = terminator->payload.let.variables; + // assert(vars.count == yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { bool has_result = results[i].value || results[i].var; switch (bindings[i]) { case NoBinding: { assert(has_result && "unbound results can't be empty"); - register_emitted(emitter, vars.nodes[i], results[i]); + register_emitted(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); break; } case LetBinding: { - String variable_name = get_value_name_unsafe(vars.nodes[i]); + String variable_name = get_value_name_unsafe(extract_multiple_ret_types_helper(instruction, i)); if (!variable_name) variable_name = ""; @@ -584,7 +583,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node else emit_variable_declaration(emitter, block_printer, t, bind_to, false, NULL); - register_emitted(emitter, vars.nodes[i], term_from_cvalue(bind_to)); + register_emitted(emitter, extract_multiple_ret_types_helper(instruction, i), term_from_cvalue(bind_to)); break; } default: assert(false); diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 5661a8443..e4d4c2cb6 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -719,7 +719,7 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_GetStackSize_TAG: case Instruction_SetStackSize_TAG: case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); - case Instruction_LetMut_TAG: error("front-end only!"); + case Instruction_BindIdentifiers_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; case Instruction_Block_TAG: error("Should be eliminated by the compiler") diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index f4781aa9f..6c013a3f2 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -40,7 +40,6 @@ SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { switch (is_value(node)) { case NotAValue: error(""); case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); - case Variablez_TAG: error("tried to emit a variable: all variables should be register by their binding let !"); case Value_ConstrainedValue_TAG: case Value_UntypedNumber_TAG: case Value_FnAddr_TAG: error("Should be lowered away earlier!"); @@ -388,13 +387,14 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo } case Let_TAG: { const Node* tail = get_let_tail(terminator); - Nodes vars = terminator->payload.let.variables; - LARRAY(SpvId, results, vars.count); - emit_instruction(emitter, fn_builder, &basic_block_builder, &merge_targets, get_let_instruction(terminator), vars.count, results); + const Node* instruction = terminator->payload.let.instruction; + Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction); + LARRAY(SpvId, results, types.count); + emit_instruction(emitter, fn_builder, &basic_block_builder, &merge_targets, instruction, types.count, results); assert(tail->tag == Case_TAG); - for (size_t i = 0; i < vars.count; i++) - register_result(emitter, vars.nodes[i], results[i]); + for (size_t i = 0; i < types.count; i++) + register_result(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); emit_terminator(emitter, fn_builder, basic_block_builder, merge_targets, tail->payload.case_.body); return; } diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 900ecc21b..e2552fe7e 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -387,7 +387,7 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); case Instruction_CopyBytes_TAG: case Instruction_FillBytes_TAG: - case Instruction_LetMut_TAG: + case Instruction_BindIdentifiers_TAG: case Instruction_StackAlloc_TAG: case Instruction_Block_TAG: error("Should be lowered elsewhere") case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 868fb9152..a63409db3 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -489,9 +489,6 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, assert(LLVMIsAFunction(callee)); if (strcmp(intrinsic, "llvm.dbg.declare") == 0) { const Node* target = convert_value(p, LLVMGetOperand(instr, 0)); - if (target->tag != Variablez_TAG) - return (EmittedInstr) { 0 }; - assert(target->tag == Variablez_TAG); const Node* meta = convert_value(p, LLVMGetOperand(instr, 1)); assert(meta->tag == RefDecl_TAG); meta = meta->payload.ref_decl.decl; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 7565d0bf1..5f4e834ed 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -691,19 +691,22 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* destroy_list(tlist); } +Nodes parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names); +Nodes parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names); + static bool accept_statement(ctxparams, BodyBuilder* bb) { Strings ids; if (accept_token(ctx, val_tok)) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok)); const Node* instruction = accept_instruction(ctx, bb); - bind_instruction_outputs_count(bb, instruction, ids.count, ids.strings); + parser_create_immutable_variables(bb, instruction, ids); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok)); const Node* instruction = accept_instruction(ctx, bb); - create_mutable_variables(bb, instruction, types, ids.strings); + parser_create_mutable_variables(bb, instruction, types, ids); } else { const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index d57bfe840..9c07a78d8 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -84,16 +84,6 @@ static void dump_free_variables(Context* ctx, CFNode* cfnode, int depth) { static void search_op_for_free_variables(Context* visitor, NodeClass class, String op_name, const Node* node) { assert(node); switch (node->tag) { - case Let_TAG: { - Nodes variables = node->payload.let.variables; - for (size_t j = 0; j < variables.count; j++) { - const Node* var = variables.nodes[j]; - bool r = insert_set_get_result(const Node*, visitor->bound, var); - assert(r); - } - break; - } - case Variablez_TAG: case Param_TAG: { //const Node** found = find_key_dict(const Node*, visitor->bound, node); //if (!found) @@ -105,7 +95,7 @@ static void search_op_for_free_variables(Context* visitor, NodeClass class, Stri case BasicBlock_TAG: assert(false); default: break; } - visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK | NcVariable, node); + visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK, node); } static CFNodeVariables* create_node_variables(CFNode* cfnode) { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 6f7ff8f16..981e1250f 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -2,6 +2,7 @@ #include "log.h" #include "portability.h" #include "type.h" +#include "transform/ir_gen_helpers.h" #include "list.h" #include "dict.h" @@ -30,80 +31,52 @@ BodyBuilder* begin_body(IrArena* a) { return bb; } -const Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i); - -static Nodes create_output_variables(IrArena* a, const Node* value, size_t outputs_count, const Node** output_types, String const output_names[]) { - Nodes types; - if (a->config.check_types) { - types = unwrap_multiple_yield_types(a, value->type); - // outputs count has to match or not be given - assert(outputs_count == types.count || outputs_count == SIZE_MAX); - if (output_types) { - // Check that the types we got are subtypes of what we care about - for (size_t i = 0; i < types.count; i++) - assert(is_subtype(output_types[i], types.nodes[i])); - types = nodes(a, outputs_count, output_types); - } - outputs_count = types.count; - } else { - assert(outputs_count != SIZE_MAX); - if (output_types) { - types = nodes(a, outputs_count, output_types); - } else { - LARRAY(const Type*, nulls, outputs_count); - for (size_t i = 0; i < outputs_count; i++) - nulls[i] = NULL; - types = nodes(a, outputs_count, nulls); - } - } - - LARRAY(Node*, vars, types.count); - for (size_t i = 0; i < types.count; i++) { - String var_name = output_names ? output_names[i] : NULL; - vars[i] = (Node*) var(a, var_name, value, i); - } - - // for (size_t i = 0; i < outputs_count; i++) { - // vars[i]->payload.var.instruction = value; - // vars[i]->payload.var.output = i; - // } - return nodes(a, outputs_count, (const Node**) vars); -} - static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count, const Node** provided_types, String const output_names[]) { if (bb->arena->config.check_types) { assert(is_instruction(instruction)); } - Nodes params = create_output_variables(bb->arena, instruction, outputs_count, provided_types, output_names); StackEntry entry = { .vars = empty(bb->arena), .structured.payload.let = { .instruction = instruction, - .variables = params, } }; append_list(StackEntry, bb->stack, entry); - return params; + if (outputs_count > 1) { + LARRAY(const Node*, extracted, outputs_count); + for (size_t i = 0; i < outputs_count; i++) + extracted[i] = gen_extract_single(bb, instruction, int32_literal(bb->arena, i)); + return nodes(bb->arena, outputs_count, extracted); + } else if (outputs_count == 1) + return singleton(instruction); + else + return empty(bb->arena); } Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { assert(bb->arena->config.check_types); - return bind_internal(bb, instruction, SIZE_MAX, NULL, NULL); + return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count, NULL, NULL); } Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String const output_names[]) { assert(bb->arena->config.check_types); assert(output_names); - return bind_internal(bb, instruction, SIZE_MAX, NULL, output_names); + return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count, NULL, output_names); } Nodes bind_instruction_explicit_result_types(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[]) { return bind_internal(bb, instruction, provided_types.count, provided_types.nodes, output_names); } -Nodes create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[]) { - Nodes mutable_vars = create_output_variables(bb->arena, instruction, provided_types.count, provided_types.nodes, output_names); - const Node* let_mut_instr = let_mut(bb->arena, instruction, mutable_vars, provided_types); +const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes* types); + +Nodes parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names) { + const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, true, output_names, &provided_types); + return bind_internal(bb, let_mut_instr, 0, NULL, NULL); +} + +Nodes parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names) { + const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, false, output_names, NULL); return bind_internal(bb, let_mut_instr, 0, NULL, NULL); } @@ -119,7 +92,7 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { switch (entry.structured.tag) { case NotAStructured_construct: entry.structured.payload.let.tail = case_(bb->arena, entry.vars, terminator); - terminator = let(a, entry.structured.payload.let.instruction, entry.structured.payload.let.variables, entry.structured.payload.let.tail); + terminator = let(a, entry.structured.payload.let.instruction, entry.structured.payload.let.tail); break; case Structured_construct_If_TAG: entry.structured.payload.if_instr.tail = case_(bb->arena, entry.vars, terminator); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 16729046b..6e4a59df2 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -74,10 +74,9 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { #include "constructors_generated.c" -const Node* let(IrArena* arena, const Node* instruction, Nodes vars, const Node* tail) { +const Node* let(IrArena* arena, const Node* instruction, const Node* tail) { Let payload = { .instruction = instruction, - .variables = vars, .tail = tail, }; @@ -94,24 +93,6 @@ const Node* let(IrArena* arena, const Node* instruction, Nodes vars, const Node* return create_node_helper(arena, node, NULL); } -const Node* var(IrArena* arena, const char* name, const Node* instruction, size_t i) { - Variablez variable = { - .name = string(arena, name), - .instruction = instruction, - .iindex = i, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .type = arena->config.check_types ? check_type_varz(arena, variable) : NULL, - .tag = Variablez_TAG, - .payload.varz = variable - }; - return create_node_helper(arena, node, NULL); -} - Node* param(IrArena* arena, const Type* type, const char* name) { Param param = { .type = type, @@ -129,10 +110,11 @@ Node* param(IrArena* arena, const Type* type, const char* name) { return create_node_helper(arena, node, NULL); } -const Node* let_mut(IrArena* arena, const Node* instruction, Nodes variables, Nodes types) { - LetMut payload = { +const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes* types) { + BindIdentifiers payload = { .instruction = instruction, - .variables = variables, + .mutable = mut, + .names = names, .types = types, }; @@ -141,8 +123,8 @@ const Node* let_mut(IrArena* arena, const Node* instruction, Nodes variables, No node = (Node) { .arena = arena, .type = NULL, - .tag = LetMut_TAG, - .payload.let_mut = payload + .tag = BindIdentifiers_TAG, + .payload.bind_identifiers = payload }; return create_node_helper(arena, node, NULL); } @@ -432,3 +414,8 @@ const Node* fp_literal_helper(IrArena* a, FloatSizes size, double value) { } } } + +const Node* extract_helper(const Node* composite, const Node* index) { + IrArena* a = composite->arena; + return prim_op_helper(a, extract_op, empty(a), mk_nodes(a, composite, index)); +} diff --git a/src/shady/fold.c b/src/shady/fold.c index 9f564a825..715d82be3 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -190,8 +190,8 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { int distance = 0; bool specialize_generic = false; AddressSpace src_as = t->payload.ptr_type.address_space; - while (ptr->tag == Variablez_TAG) { - const Node* def = get_var_def(ptr->payload.varz); + while (true) { + const Node* def = ptr; switch (def->tag) { case PrimOp_TAG: { PrimOp instruction = def->payload.prim_op; diff --git a/src/shady/generator_print.c b/src/shady/generator_print.c index 299e310fa..0d3bb60e4 100644 --- a/src/shady/generator_print.c +++ b/src/shady/generator_print.c @@ -15,7 +15,10 @@ void generate_node_print_fns(Growy* g, json_object* src) { alloc = (void*) snake_name; } growy_append_formatted(g, "\tcase %s_TAG: {\n", name); - growy_append_formatted(g, "\t\tprint(printer, \"%s \");\n", name); + growy_append_formatted(g, "\t\tprint(printer, GREEN);\n"); + growy_append_formatted(g, "\t\tprint(printer, \"%s\");\n", name); + growy_append_formatted(g, "\t\tprint(printer, RESET);\n"); + growy_append_formatted(g, "\t\tprint(printer, \"(\");\n"); json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); @@ -61,8 +64,12 @@ void generate_node_print_fns(Growy* g, json_object* src) { growy_append_formatted(g, "\t\tprint_node_operand_%s(printer, node, \"%s\", node->payload.%s.%s, config);\n", s, op_name, snake_name, op_name); free(s); } + + if (j + 1 < json_object_array_length(ops)) + growy_append_formatted(g, "\t\tprint(printer, \", \");\n"); } } + growy_append_formatted(g, "\t\tprint(printer, \")\");\n"); growy_append_formatted(g, "\t\tbreak;\n"); growy_append_formatted(g, "\t}\n", name); if (alloc) diff --git a/src/shady/node.c b/src/shady/node.c index 90e29bcc0..a6607c033 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -12,8 +12,6 @@ String get_value_name_unsafe(const Node* v) { assert(v && is_value(v)); if (v->tag == Param_TAG) return v->payload.param.name; - if (v->tag == Variablez_TAG) - return v->payload.varz.name; return NULL; } @@ -26,9 +24,10 @@ String get_value_name_safe(const Node* v) { //return node_tags[v->tag]; } -void set_value_name(Node* var, String name) { - if (var->tag == Variablez_TAG) - var->payload.varz.name = string(var->arena, name); +void set_value_name(const Node* var, String name) { + // TODO: annotations + // if (var->tag == Variablez_TAG) + // var->payload.varz.name = string(var->arena, name); } int64_t get_int_literal_value(IntLiteral literal, bool sign_extend) { @@ -165,10 +164,6 @@ NodeResolveConfig default_node_resolve_config() { }; } -const Node* get_var_def(Variablez var) { - return var.instruction; -} - const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config) { while (node) { switch (node->tag) { @@ -178,13 +173,6 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi case RefDecl_TAG: node = node->payload.ref_decl.decl; continue; - case Variablez_TAG: { - const Node* def = get_var_def(node->payload.varz); - if (!def) - break; - node = def; - continue; - } case Block_TAG: { const Node* terminator = node->payload.block.inside->payload.case_.body; while (true) { @@ -373,7 +361,6 @@ Nodes get_abstraction_params(const Node* abs) { const Node* get_let_instruction(const Node* let) { switch (let->tag) { case Let_TAG: return let->payload.let.instruction; - case LetMut_TAG: return let->payload.let_mut.instruction; default: assert(false); } } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 81b4e1081..348398948 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -69,6 +69,7 @@ static Resolved resolve_using_name(Context* ctx, const char* name) { } static void add_binding(Context* ctx, bool is_var, String name, const Node* node) { + assert(name); NamedBindEntry* entry = arena_alloc(ctx->rewriter.dst_arena->arena, sizeof(NamedBindEntry)); *entry = (NamedBindEntry) { .name = string(ctx->rewriter.dst_arena, name), @@ -114,25 +115,28 @@ static const Node* get_node_address(Context* ctx, const Node* node) { return got; } -static const Node* desugar_let_mut(Context* ctx, BodyBuilder* bb, const Node* node) { - assert(node->tag == LetMut_TAG); +static const Node* desugar_bind_identifiers(Context* ctx, BodyBuilder* bb, const Node* node) { + assert(node->tag == BindIdentifiers_TAG); IrArena* a = ctx->rewriter.dst_arena; - const Node* ninstruction = rewrite_node(&ctx->rewriter, node->payload.let_mut.instruction); - - Nodes old_params = node->payload.let_mut.variables; - Nodes initial_values = bind_instruction_outputs_count(bb, ninstruction, old_params.count, NULL); - for (size_t i = 0; i < old_params.count; i++) { - const Node* oparam = old_params.nodes[i]; - const Type* type_annotation = node->payload.let_mut.types.nodes[i]; - assert(type_annotation); - const Node* alloca = stack_alloc(a, (StackAlloc) { rewrite_node(&ctx->rewriter, type_annotation) }); - const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, &oparam->payload.varz.name).nodes[0]; - bind_instruction_outputs_count(bb, store(a, (Store) { ptr, initial_values.nodes[0] }), 0, NULL); - - add_binding(ctx, true, oparam->payload.varz.name, ptr); - log_string(DEBUGV, "Lowered mutable variable "); - log_node(DEBUGV, oparam); - log_string(DEBUGV, ".\n;"); + const Node* ninstruction = rewrite_node(&ctx->rewriter, node->payload.bind_identifiers.instruction); + + Strings names = node->payload.bind_identifiers.names; + Nodes results = bind_instruction_outputs_count(bb, ninstruction, names.count, NULL); + for (size_t i = 0; i < names.count; i++) { + String name = names.strings[i]; + if (node->payload.bind_identifiers.mutable) { + const Type* type_annotation = node->payload.bind_identifiers.types->nodes[i]; + assert(type_annotation); + const Node* alloca = stack_alloc(a, (StackAlloc) {rewrite_node(&ctx->rewriter, type_annotation)}); + const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, NULL).nodes[0]; + set_value_name(ptr, names.strings[i]); + bind_instruction_outputs_count(bb, store(a, (Store) {ptr, results.nodes[0]}), 0, NULL); + + add_binding(ctx, true, name, ptr); + log_string(DEBUGV, "Bound mutable variable '%s'\n", name); + } else { + add_binding(ctx, false, name, results.nodes[i]); + } } Nodes e = empty(a); @@ -207,7 +211,6 @@ static const Node* bind_node(Context* ctx, const Node* node) { assert(is_declaration(node)); return rewrite_decl(ctx, node); } - case Variablez_TAG: case Param_TAG: error("the binders should be handled such that this node is never reached"); case Unbound_TAG: { Resolved entry = resolve_using_name(ctx, node->payload.unbound.name); @@ -261,31 +264,26 @@ static const Node* bind_node(Context* ctx, const Node* node) { return new_bb; } case Let_TAG: { - const Node* oinstruction = get_let_instruction(node); + const Node* oinstruction = node->payload.let.instruction; const Node* ninstr; BodyBuilder* bb = begin_body(a); - if (oinstruction->tag == LetMut_TAG) { - ninstr = desugar_let_mut(ctx, bb, oinstruction); + if (oinstruction->tag == BindIdentifiers_TAG) { + ninstr = desugar_bind_identifiers(ctx, bb, oinstruction); } else { ninstr = rewrite_node(r, oinstruction); } - Nodes ovars = node->payload.let.variables; - Nodes nvars = recreate_vars(a, ovars, ninstr); - register_processed_list(r, ovars, nvars); - for (size_t i = 0; i < nvars.count; i++) - add_binding(ctx, false, nvars.nodes[i]->payload.varz.name, nvars.nodes[i]); - return finish_body(bb, let(a, ninstr, nvars, rewrite_node(r, get_let_tail(node)))); + return finish_body(bb, let(a, ninstr, rewrite_node(r, get_let_tail(node)))); } case Case_TAG: { Nodes old_params = node->payload.case_.params; Nodes new_params = recreate_params(&ctx->rewriter, old_params); - for (size_t i = 0; i < new_params.count; i++) - add_binding(ctx, false, old_params.nodes[i]->payload.param.name, new_params.nodes[i]); + // for (size_t i = 0; i < new_params.count; i++) + // add_binding(ctx, false, old_params.nodes[i]->payload.param.name, new_params.nodes[i]); register_processed_list(&ctx->rewriter, old_params, new_params); const Node* new_body = rewrite_node(&ctx->rewriter, node->payload.case_.body); return case_(a, new_params, new_body); } - case LetMut_TAG: assert(false); + case BindIdentifiers_TAG: assert(false); case Return_TAG: { assert(ctx->current_function); return fn_ret(a, (Return) { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 8689e111e..952f70316 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -2,6 +2,7 @@ #include "../analysis/uses.h" #include "../ir_private.h" +#include "../type.h" #include "portability.h" #include "log.h" @@ -114,9 +115,9 @@ const Node* process(Context* ctx, const Node* old) { case Let_TAG: { Let payload = old->payload.let; bool consumed = false; - Nodes vars = payload.variables; - for (size_t i = 0; i < vars.count; i++) { - const Use* use = get_first_use(ctx->map, vars.nodes[i]); + Nodes result_types = unwrap_multiple_yield_types(a, payload.instruction->type); + for (size_t i = 0; i < result_types.count; i++) { + const Use* use = get_first_use(ctx->map, extract_multiple_ret_types_helper(payload.instruction, i)); assert(use); for (;use; use = use->next_use) { if (use->user == old) @@ -144,17 +145,7 @@ const Node* process(Context* ctx, const Node* old) { if (is_terminator(instruction)) return finish_body(bb, instruction); } - Nodes ovars = old->payload.let.variables; - // optimization: eliminate unnecessary quotes by rewriting variables into their values directly - if (instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { - *ctx->todo = true; - register_processed_list(r, ovars, instruction->payload.prim_op.operands); - return finish_body(bb, get_abstraction_body(rewrite_node(r, old->payload.let.tail))); - } - // rewrite variables now - Nodes nvars = recreate_vars(a, ovars, instruction); - register_processed_list(r, ovars, nvars); - const Node* nlet = let(a, instruction, nvars, rewrite_node(r, old->payload.let.tail)); + const Node* nlet = let(a, instruction, rewrite_node(r, old->payload.let.tail)); return finish_body(bb, nlet); } case BasicBlock_TAG: { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 5843eeb37..c186df63f 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -122,11 +122,11 @@ static const Node* infer_decl(Context* ctx, const Node* node) { const Node* instruction = NULL; if (imported_hint) { assert(is_data_type(imported_hint)); - Nodes s = singleton(qualified_type_helper(imported_hint, true)); + const Node* s = qualified_type_helper(imported_hint, true); if (oconstant->instruction) - instruction = infer_instruction(ctx, oconstant->instruction, &s); + instruction = infer(ctx, oconstant->instruction, s); } else if (oconstant->instruction) { - instruction = infer_instruction(ctx, oconstant->instruction, NULL); + instruction = infer(ctx, oconstant->instruction, NULL); } if (instruction) imported_hint = get_unqualified_type(instruction->type); @@ -173,7 +173,6 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec switch (is_value(node)) { case NotAValue: error(""); case Param_TAG: - case Variablez_TAG: return find_processed(&ctx->rewriter, node); case Value_ConstrainedValue_TAG: { const Type* type = infer(ctx, node->payload.constrained.type, NULL); bool expect_uniform = false; @@ -545,7 +544,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes IrArena* a = ctx->rewriter.dst_arena; switch (is_instruction(node)) { case Instruction_PushStack_TAG: { - return push_stack(a, (PushStack) { infer_value(ctx, node->payload.push_stack.value, NULL) }); + return push_stack(a, (PushStack) { infer(ctx, node->payload.push_stack.value, NULL) }); } case Instruction_PopStack_TAG: { const Type* element_type = node->payload.pop_stack.type; @@ -604,17 +603,13 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { case Let_TAG: { // const Node* otail = node->payload.let.ttail; // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); - const Node* inferred_instruction = infer_instruction(ctx, node->payload.let.instruction, NULL); + const Node* inferred_instruction = infer(ctx, node->payload.let.instruction, NULL); Nodes inferred_yield_types = unwrap_multiple_yield_types(a, inferred_instruction->type); LARRAY(const Node*, vars, inferred_yield_types.count); for (size_t i = 0; i < inferred_yield_types.count; i++) { assert(is_value_type(inferred_yield_types.nodes[i])); } - // const Node* inferred_tail = infer_case(ctx, otail, inferred_yield_types); - Nodes ovars = node->payload.let.variables; - Nodes nvars = recreate_vars(a, ovars, inferred_instruction); - register_processed_list(&ctx->rewriter, ovars, nvars); - return let(a, inferred_instruction, nvars, infer_case(ctx, node->payload.let.tail, empty(a))); + return let(a, inferred_instruction, infer_case(ctx, node->payload.let.tail, empty(a))); } case Return_TAG: { const Node* imported_fn = ctx->current_fn; @@ -708,6 +703,8 @@ static const Node* process(Context* src_ctx, const Node* node) { Context ctx = *src_ctx; ctx.expected_type = NULL; + IrArena* a = ctx.rewriter.dst_arena; + const Node* found = search_processed(&src_ctx->rewriter, node); if (found) { //if (expect) @@ -718,13 +715,16 @@ static const Node* process(Context* src_ctx, const Node* node) { if (is_type(node)) { assert(expected_type == NULL); return infer_type(&ctx, node); + } else if (is_instruction(node)) { + if (expected_type) { + Nodes expected_types = unwrap_multiple_yield_types(a, expected_type); + return infer_instruction(&ctx, node, &expected_types); + } + return infer_instruction(&ctx, node, NULL); } else if (is_value(node)) { const Node* value = infer_value(&ctx, node, expected_type); assert(is_value_type(value->type)); return value; - } else if (is_instruction(node)) { - assert(false); - //return infer_instruction(&ctx, node, expected_type); } else if (is_terminator(node)) { assert(expected_type == NULL); return infer_terminator(&ctx, node); @@ -754,8 +754,8 @@ Module* infer_program(SHADY_UNUSED const CompilerConfig* config, Module* src) { Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), }; - ctx.rewriter.config.search_map = false; - ctx.rewriter.config.write_map = false; + //ctx.rewriter.config.search_map = false; + //ctx.rewriter.config.write_map = false; ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 476b25f9c..181f45e25 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -45,9 +45,6 @@ typedef struct { } StackSlot; static void search_operand_for_alloca(VContext* vctx, const Node* node) { - if (node->tag == Variablez_TAG) - return; - IrArena* a = vctx->context->rewriter.dst_arena; switch (node->tag) { case StackAlloc_TAG: { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index aeb4bec45..e4a068228 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -115,7 +115,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* nbody = rewrite_node(&ctx2.rewriter, old->payload.fun.body); if (entry_point_annotation) { const Node* lam = case_(a, empty(a), nbody); - nbody = let(a, call(a, (Call) { .callee = fn_addr_helper(a, ctx2.init_fn), .args = empty(a)}), empty(a), lam); + nbody = let(a, call(a, (Call) { .callee = fn_addr_helper(a, ctx2.init_fn), .args = empty(a)}), lam); } fun->payload.fun.body = nbody; } diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index b32ea36cc..fb8d6daa0 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -4,12 +4,17 @@ #include "log.h" #include "portability.h" +#include "dict.h" #include +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + typedef struct Context_ { Rewriter rewriter; BodyBuilder* bb; + struct Dict* bound; } Context; static const Node* process_node(Context* ctx, const Node* node); @@ -19,8 +24,11 @@ static const Node* force_to_be_value(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; if (is_instruction(node)) { - const Node* let_bound; - let_bound = process_node(ctx, node); + const Node** found = find_value_dict(const Node*, const Node*, ctx->bound, node); + if (found) + return *found; + const Node* let_bound = process_node(ctx, node); + insert_dict_and_get_result(const Node*, const Node*, ctx->bound, node, let_bound); return first(bind_instruction_outputs_count(ctx->bb, let_bound, 1, NULL)); } @@ -33,7 +41,6 @@ static const Node* force_to_be_value(Context* ctx, const Node* node) { case Function_TAG: { return fn_addr_helper(a, process_node(ctx, node)); } - case Variablez_TAG: case Param_TAG: return find_processed(&ctx->rewriter, node); default: break; @@ -47,13 +54,14 @@ static const Node* force_to_be_value(Context* ctx, const Node* node) { static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED String op_name, const Node* node) { if (node == NULL) return NULL; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (op_class) { case NcType: { switch (node->tag) { case NominalType_TAG: { return type_decl_ref(ctx->rewriter.dst_arena, (TypeDeclRef) { - .decl = process_node(ctx, node), + .decl = process_node(ctx, node), }); } default: break; @@ -68,8 +76,11 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str case NcParam: break; case NcInstruction: { - if (is_instruction(node)) - return process_node(ctx, node); + if (is_instruction(node)) { + const Node* new = process_node(ctx, node); + register_processed(r, node, new); + return new; + } const Node* val = force_to_be_value(ctx, node); return quote_helper(a, singleton(val)); } @@ -85,6 +96,8 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str break; case NcJump: break; + case NcStructured_construct: + break; } return process_node(ctx, node); } @@ -96,7 +109,8 @@ static const Node* process_node(Context* ctx, const Node* node) { if (already_done) return already_done; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; // add a builder to each abstraction... switch (node->tag) { @@ -106,8 +120,9 @@ static const Node* process_node(Context* ctx, const Node* node) { Context ctx2 = *ctx; ctx2.bb = bb; ctx2.rewriter.rewrite_fn = (RewriteNodeFn) process_node; - + ctx2.bound = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node); new->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); + destroy_dict(ctx2.bound); return new; } case BasicBlock_TAG: { @@ -132,6 +147,14 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* new_body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.case_.body)); return case_(a, new_params, new_body); } + case Let_TAG: { + const Node* new = recreate_node_identity(r, node); + const Node* oinstr = get_let_instruction(node); + const Node* ninstr = get_let_instruction(new); + insert_dict_and_get_result(const Node*, const Node*, ctx->bound, oinstr, ninstr); + register_processed(r, node, new); + return new; + } default: break; } @@ -146,9 +169,10 @@ Module* normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { Context ctx = { .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process_op), .bb = NULL, + .bound = NULL, }; - ctx.rewriter.config.search_map = false; + ctx.rewriter.config.search_map = true; ctx.rewriter.config.write_map = false; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index a0923c5eb..e99a5adcb 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -36,9 +36,6 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { break; } case RefDecl_TAG: return get_req_cast(ctx, src->payload.ref_decl.decl); - case Variablez_TAG: { - return get_req_cast(ctx, get_var_def(src->payload.varz)); - } case Lea_TAG: { const Type* src_req_cast = get_req_cast(ctx, src->payload.lea.ptr); if (src_req_cast) { diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index fd436584b..82a33a235 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -31,7 +31,7 @@ typedef struct { bool leaks; bool read_from; bool non_logical_use; - const Node* bound; + const Node* new; } AllocaInfo; typedef struct { @@ -47,14 +47,6 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca for (;use; use = use->next_use) { if (is_abstraction(use->user) && use->operand_class == NcParam) continue; - if (use->operand_class == NcVariable) - continue; - if (use->user->tag == Variablez_TAG) { - debugv_print("demote_alloca leak analysis: following let-bound variable: "); - log_node(DEBUGV, use->user); - debugv_print(".\n"); - visit_ptr_uses(use->user, slice_type, k, map); - } else if (use->user->tag == Let_TAG && use->operand_class == NcInstruction) { /*Nodes vars = use->user->payload.let.variables; for (size_t i = 0; i < vars.count; i++) { @@ -134,29 +126,27 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { PtrSourceKnowledge k = { 0 }; while (ptr) { assert(is_value(ptr)); - if (ptr->tag == Variablez_TAG && ctx->uses) { - const Node* instr = get_var_def(ptr->payload.varz); - switch (instr->tag) { - case StackAlloc_TAG: - case LocalAlloc_TAG: { - k.src_alloca = *find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, instr); - return k; - } - case PrimOp_TAG: { - PrimOp payload = instr->payload.prim_op; - switch (payload.op) { - case convert_op: - case reinterpret_op: { - ptr = first(payload.operands); - continue; - } - // TODO: lea and co - default: - break; + const Node* instr = ptr; + switch (instr->tag) { + case StackAlloc_TAG: + case LocalAlloc_TAG: { + k.src_alloca = *find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, instr); + return k; + } + case PrimOp_TAG: { + PrimOp payload = instr->payload.prim_op; + switch (payload.op) { + case convert_op: + case reinterpret_op: { + ptr = first(payload.operands); + continue; } + // TODO: lea and co + default: + break; } - default: break; } + default: break; } ptr = NULL; @@ -179,14 +169,20 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t if (!k->leaks) { if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { ctx->todo |= true; - return quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}))); + const Node* new = quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}))); + k->new = new; + return new; } if (!k->non_logical_use && get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { ctx->todo |= true; - return local_alloc(a, (LocalAlloc) {rewrite_node(r, old_type )}); + const Node* new = local_alloc(a, (LocalAlloc) {rewrite_node(r, old_type )}); + k->new = new; + return new; } } - return recreate_node_identity(r, old); + const Node* new = recreate_node_identity(r, old); + k->new = new; + return new; } static const Node* process(Context* ctx, const Node* old) { @@ -211,39 +207,17 @@ static const Node* process(Context* ctx, const Node* old) { fun_ctx.uses = NULL; return recreate_node_identity(&fun_ctx.rewriter, old); } - case Let_TAG: { - const Node* oinstruction = get_let_instruction(old); - Nodes ovars = old->payload.let.variables; - const Node* otail = get_let_tail(old); - const Node* ninstruction = rewrite_node(r, oinstruction); - AllocaInfo** found_info = find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, oinstruction); - AllocaInfo* info = NULL; - if (found_info) { - const Node* ovar = first(ovars); - info = *found_info; - insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, ovar, info); - } - Nodes ntypes = unwrap_multiple_yield_types(r->dst_arena, ninstruction->type); - assert(ntypes.count == ovars.count); - Nodes nvars = recreate_vars(a, ovars, ninstruction); - register_processed_list(r, ovars, nvars); - if (info) - info->bound = first(nvars); - // const Node* nbody = rewrite_node(r, otail->payload.case_.body); - // const Node* tail = case_(r->dst_arena, empty(a), nbody); - return let(a, ninstruction, nvars, rewrite_node(r, otail)); - } case Load_TAG: { Load payload = old->payload.load; PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.ptr->type))); if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { - if (k.src_alloca->bound == rewrite_node(r, payload.ptr)) + if (k.src_alloca->new == rewrite_node(r, payload.ptr)) break; ctx->todo |= true; BodyBuilder* bb = begin_body(a); - const Node* data = gen_load(bb, k.src_alloca->bound); + const Node* data = gen_load(bb, k.src_alloca->new); data = gen_reinterpret_cast(bb, access_type, data); return yield_values_and_wrap_in_block(bb, singleton(data)); } @@ -256,12 +230,12 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca) { const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.ptr->type))); if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { - if (k.src_alloca->bound == rewrite_node(r, payload.ptr)) + if (k.src_alloca->new == rewrite_node(r, payload.ptr)) break; ctx->todo |= true; BodyBuilder* bb = begin_body(a); const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.value)); - gen_store(bb, k.src_alloca->bound, data); + gen_store(bb, k.src_alloca->new, data); return yield_values_and_wrap_in_block(bb, empty(a)); } } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 8519c5599..8aa3618e9 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -284,8 +284,6 @@ static void mark_value_as_escaping(Context* ctx, KnowledgeBase* kb, const Node* switch (is_value(value)) { case NotAValue: assert(false); case Value_Param_TAG: - case Value_Variablez_TAG: - break; case Value_ConstrainedValue_TAG: break; case Value_UntypedNumber_TAG: @@ -452,22 +450,8 @@ static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Nod Rewriter* r = &ctx->rewriter; switch (is_terminator(old)) { case NotATerminator: assert(false); - case Let_TAG: { - const Node* oinstruction = get_let_instruction(old); - const Node* ninstruction = rewrite_node(r, oinstruction); - PtrKnowledge** found = find_value_dict(const Node*, PtrKnowledge*, kb->map, oinstruction); - Nodes ovars = old->payload.let.variables; - if (found) { // copy any knownledge about an instruction to the bound variable - assert(ovars.count == 1); - PtrKnowledge* k = *found; - const Node* first_param = first(ovars); - insert_dict(const Node*, PtrKnowledge*, kb->map, first_param, k); - } - - Nodes nvars = recreate_vars(a, ovars, ninstruction); - register_processed_list(r, ovars, nvars); - return let(a, ninstruction, nvars, rewrite_node(r, get_let_tail(old))); - } + case Let_TAG: + break; case Jump_TAG: { const Node* old_target = old->payload.jump.target; // rewrite_node(&ctx->rewriter, old_target); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index fbcb06b4c..08901bfa0 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -139,7 +139,7 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* caller, const No // Just jumps to the actual ladder const Node* exit_ladder_trampoline = case_(a, empty(a), jump(a, (Jump) {.target = inner_exit_ladder_bb, .args = empty(a)})); - const Node* structured = structure(&ctx2, dst, let(a, quote_helper(a, empty(a)), empty(a), exit_ladder_trampoline)); + const Node* structured = structure(&ctx2, dst, let(a, quote_helper(a, empty(a)), exit_ladder_trampoline)); assert(is_terminator(structured)); // forget we rewrote all that destroy_dict(tmp_processed); @@ -180,12 +180,8 @@ static const Node* rebuild_let(Context* ctx, const Node* old_let, const Node* ne Nodes otail_params = get_abstraction_params(old_tail); assert(otail_params.count == 0); - Nodes ovars = old_let->payload.let.variables; - Nodes nvars = recreate_vars(a, ovars, new_instruction); - register_processed_list(&ctx->rewriter, ovars, nvars); - const Node* structured_lam = case_(a, empty(a), structure(ctx, old_tail, exit_ladder)); - return let(a, new_instruction, nvars, structured_lam); + return let(a, new_instruction, structured_lam); } static const Node* structure(Context* ctx, const Node* abs, const Node* exit_ladder) { @@ -197,8 +193,6 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case NotATerminator: case Let_TAG: { const Node* old_tail = get_let_tail(body); - Nodes ovars = body->payload.let.variables; - //Nodes otail_params = get_abstraction_params(old_tail); const Node* old_instr = get_let_instruction(body); switch (is_instruction(old_instr)) { @@ -305,7 +299,7 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad gen_if(bb2, empty(a), guard, if_true_lam, NULL); const Node* tail_lambda = case_(a, empty(a), finish_body(bb2, exit_ladder)); - return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), empty(a), tail_lambda))); + return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), tail_lambda))); } case Join_TAG: { ControlEntry* control = search_containing_control(ctx, body->payload.join.join_point); diff --git a/src/shady/passes/opt_stack.c b/src/shady/passes/opt_stack.c index 6fc2531ec..7b712df1b 100644 --- a/src/shady/passes/opt_stack.c +++ b/src/shady/passes/opt_stack.c @@ -89,10 +89,7 @@ static const Node* process(Context* ctx, const Node* node) { ninstruction = recreate_node_identity(&ctx->rewriter, old_instruction); } assert(ninstruction); - Nodes ovars = node->payload.let.variables; - Nodes nvars = recreate_vars(a, ovars, ninstruction); - register_processed_list(&ctx->rewriter, ovars, nvars); - return let(a, ninstruction, nvars, ntail); + return let(a, ninstruction, ntail); } // Unreachable is assumed to never happen, so it doesn't observe the stack state case NotATerminator: break; diff --git a/src/shady/print.c b/src/shady/print.c index bb451ebcd..4f870ed46 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -34,7 +34,7 @@ struct PrinterCtx_ { #define GREEN COLOR("\033[0;32m") #define YELLOW COLOR("\033[0;33m") #define BLUE COLOR("\033[0;34m") -#define MANGENTA COLOR("\033[0;35m") +#define MAGENTA COLOR("\033[0;35m") #define CYAN COLOR("\033[0;36m") #define WHITE COLOR("\033[0;37m") @@ -406,7 +406,6 @@ static void print_value(PrinterCtx* ctx, const Node* node) { print_node(node->payload.constrained.value); break; } - case Value_Variablez_TAG: case Value_Param_TAG: if (ctx->uses) { // if ((*find_value_dict(const Node*, Uses*, ctx->uses->map, node))->escapes_defining_block) @@ -540,7 +539,7 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { switch (is_instruction(node)) { case NotAnInstruction: assert(false); break; case Instruction_Comment_TAG: { - printf(GREY); + printf(MAGENTA); printf("/* %s */", node->payload.comment.string); printf(RESET); break; @@ -605,36 +604,54 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { case NotATerminator: assert(false); case Let_TAG: { const Node* instruction = get_let_instruction(node); - bool mut = false; - if (instruction->tag == LetMut_TAG) - mut = true; + const BindIdentifiers* binders = NULL; + if (instruction->tag == BindIdentifiers_TAG) + binders = &instruction->payload.bind_identifiers; const Node* tail = get_let_tail(node); if (!ctx->config.reparseable) { - // if the let tail is a case, we apply some syntactic sugar - Nodes variables = node->payload.let.variables; - if (mut || variables.count > 0) { + Nodes result_types = instruction->type ? unwrap_multiple_yield_types(node->arena, instruction->type) : empty(node->arena); + if (binders) { + //printf("%%%d = ", instruction->id); printf(GREEN); - if (mut) + if (binders && binders->mutable) printf("var"); else printf("val"); printf(RESET); - if (mut) { - variables = instruction->payload.let_mut.variables; - instruction = instruction->payload.let_mut.instruction; - } - for (size_t i = 0; i < variables.count; i++) { - // TODO: fix let mut - if (node->arena->config.check_types && (mut || !ctx->config.reparseable)) { + } + + if (binders) { + Strings names = binders->names; + instruction = binders->instruction; + for (size_t i = 0; i < names.count; i++) { + if (binders->types) { printf(" "); - print_node(variables.nodes[i]->type); + print_node(binders->types->nodes[i]); } printf(" "); - print_node(variables.nodes[i]); + printf("%s", names.strings[i]); printf(RESET); } + printf(" = %%%d = ", instruction->id); + } else { + if (result_types.count > 1) { + printf("["); + for (size_t i = 0; i < result_types.count; i++) { + if (node->arena->config.check_types && !ctx->config.reparseable) { + printf(" "); + print_node(result_types.nodes[i]); + } + printf("%s", get_value_name_safe(extract_multiple_ret_types_helper(instruction, i))); + printf(RESET); + if (i + 1 < result_types.count) + printf(", "); + } + printf("]"); + } + printf("%%%zu", instruction->id); printf(" = "); } + print_node(instruction); if (!ctx->config.in_cfg) { printf(";\n"); @@ -1087,16 +1104,37 @@ void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) } } +#define COLOR(x) (config.color ? (x) : "") + +static void print_operand_name_helper(Printer* p, PrintConfig config, String name) { + print(p, GREY); + print(p, "%s", name); + print(p, RESET); + print(p, ": ", name); +} + +static void print_operand_helper(Printer* p, PrintConfig config, NodeClass nc, const Node* op) { + if (is_instruction(op) && op->arena->config.check_types) + print(p, "%%%d", op->id); + else { + if (!op->arena->config.check_types) + print(p, "%%%d", op->id); + print_node(p, op, config); + } +} + void print_node_operand(Printer* p, const Node* n, String name, NodeClass op_class, const Node* op, PrintConfig config) { - //print(p, " '%s': %%%d", name, op->id); - print(p, " '%s': ", name); - print_node(p, op, config); + print_operand_name_helper(p, config, name); + print_operand_helper(p, config, op_class, op); + // print(p, " '%s': ", name); + // print_node(p, op, config); } void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass op_class, Nodes ops, PrintConfig config) { - print(p, " '%s': [", name); + print_operand_name_helper(p, config, name); + print(p, "["); for (size_t i = 0; i < ops.count; i++) { - print(p, "%%%zu", (size_t) ops.nodes[i]); + print_operand_helper(p, config, op_class, ops.nodes[i]); if (i + 1 < ops.count) print(p, ", "); } @@ -1104,19 +1142,31 @@ void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass o } void print_node_operand_const_Node_(Printer* p, const Node* n, String name, const Node* op, PrintConfig config) { - print(p, " '%s': %%%d", name, op->id); + print_operand_name_helper(p, config, name); + print_operand_helper(p, config, 0, op); +} + +void print_node_operand_Nodes_(Printer* p, const Node* n, String name, Nodes* op, PrintConfig config) { + if (op) { + print_node_operand_list(p, n, name, 0, *op, config); + } else { + print_operand_name_helper(p, config, name); + print(p, "null"); + } } void print_node_operand_AddressSpace(Printer* p, const Node* n, String name, AddressSpace as, PrintConfig config) { - print(p, " '%s': %s", name, get_address_space_name(as)); + print_operand_name_helper(p, config, name); + print(p, "%s", get_address_space_name(as)); } void print_node_operand_Op(Printer* p, const Node* n, String name, Op op, PrintConfig config) { - print(p, " '%s': %s", name, get_primop_name(op)); + print_operand_name_helper(p, config, name); + print(p, "%s", get_primop_name(op)); } void print_node_operand_RecordSpecialFlag(Printer* p, const Node* n, String name, RecordSpecialFlag flags, PrintConfig config) { - print(p, " '%s': ", name); + print_operand_name_helper(p, config, name); if (flags & MultipleReturn) print(p, "MultipleReturn"); if (flags & DecorateBlock) @@ -1124,15 +1174,17 @@ void print_node_operand_RecordSpecialFlag(Printer* p, const Node* n, String name } void print_node_operand_uint32_t(Printer* p, const Node* n, String name, uint32_t i, PrintConfig config) { - print(p, " '%s': %u", name, i); + print_operand_name_helper(p, config, name); + print(p, "%u", i); } void print_node_operand_uint64_t(Printer* p, const Node* n, String name, uint64_t i, PrintConfig config) { - print(p, " '%s': %zu", name, i); + print_operand_name_helper(p, config, name); + print(p, "%zu", i); } void print_node_operand_IntSizes(Printer* p, const Node* n, String name, IntSizes s, PrintConfig config) { - print(p, " '%s': ", name); + print_operand_name_helper(p, config, name); switch (s) { case IntTy8: print(p, "8"); break; case IntTy16: print(p, "16"); break; @@ -1142,7 +1194,7 @@ void print_node_operand_IntSizes(Printer* p, const Node* n, String name, IntSize } void print_node_operand_FloatSizes(Printer* p, const Node* n, String name, FloatSizes s, PrintConfig config) { - print(p, " '%s': ", name); + print_operand_name_helper(p, config, name); switch (s) { case FloatTy16: print(p, "16"); break; case FloatTy32: print(p, "32"); break; @@ -1151,11 +1203,13 @@ void print_node_operand_FloatSizes(Printer* p, const Node* n, String name, Float } void print_node_operand_String(Printer* p, const Node* n, String name, String s, PrintConfig config) { - print(p, " '%s': \"%s\"", name, s); + print_operand_name_helper(p, config, name); + print(p, "\"%s\"", s); } void print_node_operand_Strings(Printer* p, const Node* n, String name, Strings ops, PrintConfig config) { - print(p, " '%s': [", name); + print_operand_name_helper(p, config, name); + print(p, "["); for (size_t i = 0; i < ops.count; i++) { print(p, "\"%s\"", (size_t) ops.strings[i]); if (i + 1 < ops.count) @@ -1165,7 +1219,7 @@ void print_node_operand_Strings(Printer* p, const Node* n, String name, Strings } void print_node_operand_bool(Printer* p, const Node* n, String name, bool b, PrintConfig config) { - print(p, " '%s': ", name); + print_operand_name_helper(p, config, name); if (b) print(p, "true"); else @@ -1173,7 +1227,8 @@ void print_node_operand_bool(Printer* p, const Node* n, String name, bool b, Pri } void print_node_operand_unsigned(Printer* p, const Node* n, String name, unsigned u, PrintConfig config) { - print(p, " '%s': %u", name, u); + print_operand_name_helper(p, config, name); + print(p, "%u", u); } #include "print_generated.c" diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index f077a22af..d1729a038 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -20,7 +20,7 @@ Rewriter create_rewriter_base(Module* src, Module* dst) { .dst_module = dst, .config = { .search_map = true, - //.write_map = true, + .write_map = true, .rebind_let = false, .fold_quote = true, }, @@ -37,6 +37,7 @@ Rewriter create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn) { Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn) { Rewriter r = create_rewriter_base(src, dst); + r.config.write_map = false; r.rewrite_op_fn = fn; r.decls_map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); return r; @@ -251,15 +252,6 @@ Nodes recreate_params(Rewriter* rewriter, Nodes oparams) { return nodes(rewriter->dst_arena, oparams.count, nparams); } -Nodes recreate_vars(IrArena* arena, Nodes ovars, const Node* instruction) { - LARRAY(const Node*, nvars_arr, ovars.count); - for (size_t i = 0; i < ovars.count; i++) { - nvars_arr[i] = var(arena, ovars.nodes[i]->payload.varz.name, instruction, i); - } - Nodes nvars = nodes(arena, ovars.count, nvars_arr); - return nvars; -} - Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { Node* new = NULL; switch (is_declaration(old)) { @@ -352,31 +344,12 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { log_node(ERROR, node); log_string(ERROR, ", params should be rewritten by the abstraction rewrite logic"); error_die(); - case Variablez_TAG: - log_string(ERROR, "Can't rewrite: "); - log_node(ERROR, node); - log_string(ERROR, ", variables should be rewritten by the binding let"); - error_die(); case Let_TAG: { BodyBuilder* bb = begin_body(arena); const Node* instruction = rewrite_op_helper(rewriter, NcInstruction, "instruction", node->payload.let.instruction); - // optimization: fold blocks - // if (instruction->tag == Block_TAG) { - // instruction = quote_helper(arena, flatten_block(arena, instruction, bb)); - // } - Nodes ovars = node->payload.let.variables; - // optimization: eliminate unecessary quotes by rewriting variables into their values directly - // if (instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) { - // register_processed_list(rewriter, ovars, instruction->payload.prim_op.operands); - // return finish_body(bb, get_abstraction_body(rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail))); - // } - // rewrite variables now - Nodes nvars = recreate_vars(arena, ovars, instruction); - register_processed_list(rewriter, ovars, nvars); - const Node* nlet = let(arena, instruction, nvars, rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail)); + const Node* nlet = let(arena, instruction, rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail)); return finish_body(bb, nlet); } - case LetMut_TAG: error("De-sugar this by hand") case Case_TAG: { Nodes params = recreate_params(rewriter, node->payload.case_.params); register_processed_list(rewriter, node->payload.case_.params, params); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 91729605c..f5b22cb91 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -102,6 +102,10 @@ const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { return first(bind_instruction(bb, local_alloc(bb->arena, (LocalAlloc) { type }))); } +const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Node* index) { + return first(bind_instruction(bb, extract_helper(composite, index))); +} + const Node* gen_load(BodyBuilder* bb, const Node* ptr) { return first(bind_instruction(bb, load(bb->arena, (Load) { ptr }))); } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 080271f52..ff9b2fe47 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -24,6 +24,8 @@ const Node* gen_merge_halves(BodyBuilder*, const Node* lo, const Node* hi); const Node* gen_stack_alloc(BodyBuilder*, const Type* ptr); const Node* gen_local_alloc(BodyBuilder*, const Type* ptr); +const Node* gen_extract_single(BodyBuilder*, const Node* composite, const Node* index); + const Node* gen_load(BodyBuilder*, const Node* ptr); void gen_store(BodyBuilder*, const Node* ptr, const Node* value); const Node* gen_lea(BodyBuilder*, const Node* base, const Node* offset, Nodes selectors); diff --git a/src/shady/type.c b/src/shady/type.c index 292c1697a..ef3bd3313 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -411,12 +411,6 @@ const Type* check_type_param(IrArena* arena, Param variable) { return variable.type; } -const Type* check_type_varz(IrArena* arena, Variablez variable) { - Nodes types = unwrap_multiple_yield_types(arena, variable.instruction->type); - assert(variable.iindex < types.count); - return types.nodes[variable.iindex]; -} - const Type* check_type_untyped_number(IrArena* arena, UntypedNumber untyped) { error("should never happen"); } diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index bdcf28bed..8551a81f1 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -26,7 +26,7 @@ Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type) { // fallthrough default: assert(is_value_type(type)); - return nodes(arena, 1, (const Node* []) { type }); + return singleton(type); } } @@ -301,3 +301,10 @@ const Node* get_fill_type_size(const Type* composite_t) { default: error("fill values need to be either array or pack types") } } + +const Node* extract_multiple_ret_types_helper(const Node* composite, int index) { + Nodes types = unwrap_multiple_yield_types(composite->arena, composite->type); + if (types.count > 1) + return extract_helper(composite, int32_literal(composite->arena, index)); + return composite; +} From f9d02ebf1d9f5858bb0d00e697981cd557c9c88e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 17:53:37 +0200 Subject: [PATCH 381/693] cull some old irrelevant builder fns --- include/shady/ir.h | 5 ++--- src/frontend/llvm/l2s.c | 2 +- src/frontend/llvm/l2s_instr.c | 16 ++++++++-------- src/frontend/slim/parser.c | 2 +- src/frontend/spirv/s2s.c | 32 ++++++++++++++++---------------- src/shady/body_builder.c | 20 ++++++++------------ src/shady/passes/bind.c | 6 +++--- src/shady/passes/normalize.c | 2 +- 8 files changed, 40 insertions(+), 45 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 2394e61c8..667cc071a 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -286,10 +286,9 @@ Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, const Node*); Nodes gen_loop(BodyBuilder*, Nodes, Nodes, const Node*); Nodes gen_control(BodyBuilder*, Nodes, const Node*); -/// Like append instruction, but you explicitly give it information about any yielded values +/// Like append bind_instruction, but you explicitly give it information about any yielded values /// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! -Nodes bind_instruction_explicit_result_types(BodyBuilder*, const Node* initial_value, Nodes provided_types, String const output_names[]); -Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count, String const output_names[]); +Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count); const Node* finish_body(BodyBuilder*, const Node* terminator); void cancel_body(BodyBuilder*); diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 03dd1a36b..973fbdf90 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -59,7 +59,7 @@ static const Node* write_bb_tail(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, if (!emitted.instruction) continue; String names[] = { LLVMGetValueName(instr) }; - Nodes results = bind_instruction_explicit_result_types(b, emitted.instruction, emitted.result_types, names); + Nodes results = bind_instruction_outputs_count(b, emitted.instruction, emitted.result_types.count); if (emitted.result_types.count == 1) { const Node* result = first(results); insert_dict(LLVMValueRef, const Node*, p->map, instr, result); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index a63409db3..ee623a3de 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -38,7 +38,7 @@ static Nodes reinterpret_operands(BodyBuilder* b, Nodes ops, const Type* dst_t) IrArena* a = dst_t->arena; LARRAY(const Node*, nops, ops.count); for (size_t i = 0; i < ops.count; i++) - nops[i] = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(dst_t), singleton(ops.nodes[i])), singleton(dst_t), NULL)); + nops[i] = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(dst_t), singleton(ops.nodes[i])), 1)); return nodes(a, ops.count, nops); } @@ -120,7 +120,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* t = convert_type(p, LLVMTypeOf(instr)); -#define BIND_PREV_R(t) bind_instruction_explicit_result_types(b, r, singleton(t), NULL) +#define BIND_PREV_R(t) bind_instruction_outputs_count(b, r, 1) //if (LLVMIsATerminatorInst(instr)) { if (LLVMIsAInstruction(instr)) { @@ -256,10 +256,10 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, assert(t->tag == PtrType_TAG); const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivate }); - r = first(bind_instruction_explicit_result_types(b, stack_alloc(a, (StackAlloc) { allocated_t }), singleton(allocated_ptr_t), NULL)); + r = first(bind_instruction_outputs_count(b, stack_alloc(a, (StackAlloc) { allocated_t }), 1)); if (UNTYPED_POINTERS) { const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivate }); - r = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), singleton(untyped_ptr_t), NULL)); + r = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), 1)); } r = prim_op_helper(a, convert_op, singleton(t), singleton(r)); break; @@ -272,7 +272,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* element_t = t; const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); + ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } r = load(a, (Load) { ptr }); break; @@ -286,7 +286,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* element_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 1))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); + ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } r = store(a, (Store) { ptr, ops.nodes[0] }); break; @@ -298,7 +298,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = first(bind_instruction_explicit_result_types(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), singleton(typed_ptr), NULL)); + ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } ops = change_node_at_index(a, ops, 0, ptr); r = lea(a, (Lea) { ops.nodes[0], ops.nodes[1], nodes(a, ops.count - 2, &ops.nodes[2])}); @@ -595,7 +595,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LARRAY(const Node*, processed_ops, ops.count); for (i = 0; i < num_args; i++) { if (decoded[i].is_byval) - processed_ops[i] = first(bind_instruction_outputs_count(b, load(a, (Load) { ops.nodes[i] }), 1, NULL)); + processed_ops[i] = first(bind_instruction_outputs_count(b, load(a, (Load) { ops.nodes[i] }), 1)); else processed_ops[i] = ops.nodes[i]; } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 5f4e834ed..be347ec2c 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -710,7 +710,7 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { } else { const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; - bind_instruction_outputs_count(bb, instr, 0, NULL); + bind_instruction_outputs_count(bb, instr, 0); } return true; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 29d8b197b..e43086b8f 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -462,7 +462,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = shd_op.op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, num_ops, ops) - }), results_count, NULL); + }), results_count); if (has_result) { parser->defs[result].type = Value; parser->defs[result].node = first(results); @@ -742,13 +742,13 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { assert(is_data_type(contents_t)); if (parser->fun) { - const Node* ptr = first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { contents_t }), 1, NULL)); + const Node* ptr = first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { contents_t }), 1)); parser->defs[result].type = Value; parser->defs[result].node = ptr; if (size == 5) - bind_instruction_outputs_count(parser->current_block.builder, store(parser->arena, (Store) { ptr, get_def_ssa_value(parser, instruction[4]) }), 1, NULL); + bind_instruction_outputs_count(parser->current_block.builder, store(parser->arena, (Store) { ptr, get_def_ssa_value(parser, instruction[4]) }), 1); } else { Nodes annotations = empty(parser->arena); SpvDeco* builtin = find_decoration(parser, result, -1, SpvDecorationBuiltIn); @@ -967,7 +967,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = convert_op, .type_arguments = singleton(dst_t), .operands = singleton(src) - }), 1, NULL)); + }), 1)); break; } case SpvOpConvertPtrToU: @@ -980,7 +980,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = reinterpret_op, .type_arguments = singleton(dst_t), .operands = singleton(src) - }), 1, NULL)); + }), 1)); break; } case SpvOpInBoundsPtrAccessChain: @@ -1004,7 +1004,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .ptr = ptr, .offset = offset, .indices = nodes(a, num_indices, indices), - }), 1, NULL)); + }), 1)); break; } case SpvOpCompositeExtract: { @@ -1018,7 +1018,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = extract_op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, 1 + num_indices, ops) - }), 1, NULL)); + }), 1)); break; } case SpvOpCompositeInsert: { @@ -1033,7 +1033,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = insert_op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, 2 + num_indices, ops) - }), 1, NULL)); + }), 1)); break; } case SpvOpVectorShuffle: { @@ -1058,7 +1058,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = extract_op, .type_arguments = empty(parser->arena), .operands = mk_nodes(parser->arena, src, int32_literal(parser->arena, index)) - }), 1, NULL)); + }), 1)); } parser->defs[result].type = Value; @@ -1071,13 +1071,13 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpLoad: { const Type* src = get_def_ssa_value(parser, instruction[3]); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, load(a, (Load) { src }), 1, NULL)); + parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, load(a, (Load) { src }), 1)); break; } case SpvOpStore: { const Type* ptr = get_def_ssa_value(parser, instruction[1]); const Type* value = get_def_ssa_value(parser, instruction[2]); - bind_instruction_outputs_count(parser->current_block.builder, store(a, (Store) { ptr, value }), 0, NULL); + bind_instruction_outputs_count(parser->current_block.builder, store(a, (Store) { ptr, value }), 0); break; } case SpvOpCopyMemory: @@ -1093,7 +1093,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = size_of_op, .type_arguments = singleton(elem_t), .operands = empty(parser->arena) - }), 1, NULL)); + }), 1)); } else { cnt = get_def_ssa_value(parser, instruction[3]); } @@ -1101,7 +1101,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .src = src, .dst = dst, .count = cnt, - }), 0, NULL); + }), 0); break; } case SpvOpSelectionMerge: @@ -1143,7 +1143,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .op = op, .type_arguments = empty(parser->arena), .operands = nodes(parser->arena, num_args, args) - }), rslts_count, NULL); + }), rslts_count); if (rslts_count == 1) parser->defs[result].node = first(rslts); @@ -1154,7 +1154,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { Nodes rslts = bind_instruction_outputs_count(parser->current_block.builder, call(parser->arena, (Call) { .callee = fn_addr_helper(parser->arena, callee), .args = nodes(parser->arena, num_args, args) - }), rslts_count, NULL); + }), rslts_count); if (rslts_count == 1) parser->defs[result].node = first(rslts); @@ -1274,7 +1274,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, instr, 1, NULL)); + parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, instr, 1)); break; } case SpvOpBranch: { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 981e1250f..8e316a4a8 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -31,7 +31,7 @@ BodyBuilder* begin_body(IrArena* a) { return bb; } -static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count, const Node** provided_types, String const output_names[]) { +static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { if (bb->arena->config.check_types) { assert(is_instruction(instruction)); } @@ -55,33 +55,29 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { assert(bb->arena->config.check_types); - return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count, NULL, NULL); + return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count); } Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String const output_names[]) { assert(bb->arena->config.check_types); assert(output_names); - return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count, NULL, output_names); -} - -Nodes bind_instruction_explicit_result_types(BodyBuilder* bb, const Node* instruction, Nodes provided_types, String const output_names[]) { - return bind_internal(bb, instruction, provided_types.count, provided_types.nodes, output_names); + return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count); } const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes* types); Nodes parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names) { const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, true, output_names, &provided_types); - return bind_internal(bb, let_mut_instr, 0, NULL, NULL); + return bind_internal(bb, let_mut_instr, 0); } Nodes parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names) { const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, false, output_names, NULL); - return bind_internal(bb, let_mut_instr, 0, NULL, NULL); + return bind_internal(bb, let_mut_instr, 0); } -Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count, String const output_names[]) { - return bind_internal(bb, instruction, outputs_count, NULL, output_names); +Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { + return bind_internal(bb, instruction, outputs_count); } static const Node* build_body(BodyBuilder* bb, const Node* terminator) { @@ -142,7 +138,7 @@ const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBu cancel_body(bb); return instruction; } - Nodes bound = bind_internal(bb, instruction, types.count, types.nodes, NULL); + Nodes bound = bind_internal(bb, instruction, types.count); return yield_values_and_wrap_in_block_explicit_return_types(bb, bound, types); } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 348398948..afc9133e4 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -121,16 +121,16 @@ static const Node* desugar_bind_identifiers(Context* ctx, BodyBuilder* bb, const const Node* ninstruction = rewrite_node(&ctx->rewriter, node->payload.bind_identifiers.instruction); Strings names = node->payload.bind_identifiers.names; - Nodes results = bind_instruction_outputs_count(bb, ninstruction, names.count, NULL); + Nodes results = bind_instruction_outputs_count(bb, ninstruction, names.count); for (size_t i = 0; i < names.count; i++) { String name = names.strings[i]; if (node->payload.bind_identifiers.mutable) { const Type* type_annotation = node->payload.bind_identifiers.types->nodes[i]; assert(type_annotation); const Node* alloca = stack_alloc(a, (StackAlloc) {rewrite_node(&ctx->rewriter, type_annotation)}); - const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1, NULL).nodes[0]; + const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; set_value_name(ptr, names.strings[i]); - bind_instruction_outputs_count(bb, store(a, (Store) {ptr, results.nodes[0]}), 0, NULL); + bind_instruction_outputs_count(bb, store(a, (Store) {ptr, results.nodes[0]}), 0); add_binding(ctx, true, name, ptr); log_string(DEBUGV, "Bound mutable variable '%s'\n", name); diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index fb8d6daa0..0516c85c3 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -29,7 +29,7 @@ static const Node* force_to_be_value(Context* ctx, const Node* node) { return *found; const Node* let_bound = process_node(ctx, node); insert_dict_and_get_result(const Node*, const Node*, ctx->bound, node, let_bound); - return first(bind_instruction_outputs_count(ctx->bb, let_bound, 1, NULL)); + return first(bind_instruction_outputs_count(ctx->bb, let_bound, 1)); } switch (node->tag) { From 1d622d2d2be40830f4a1c4f0628433de4f646aa2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 17:54:16 +0200 Subject: [PATCH 382/693] fixed opt_inline --- src/shady/passes/opt_inline.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 428ca89c9..b5eb2b2b6 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -222,10 +222,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - const Node* new = recreate_node_identity(&ctx->rewriter, node); - if (node->tag == Case_TAG) - register_processed(&ctx->rewriter, node, new); - return new; + return recreate_node_identity(&ctx->rewriter, node); } KeyHash hash_node(const Node**); From 80245f6d504840ca05beea619b2814617d81f0ee Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 17:54:22 +0200 Subject: [PATCH 383/693] allow destroying unused loads --- src/shady/passes/cleanup.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 952f70316..28f4e7447 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -97,6 +97,10 @@ static bool has_side_effects(const Node* instr) { bool side_effects = true; if (instr->tag == PrimOp_TAG) side_effects = has_primop_got_side_effects(instr->payload.prim_op.op); + switch (instr->tag) { + case Load_TAG: return false; + default: break; + } return side_effects; } From 64f5372ac365a7c0cdbc2e66ac6ef4032de7b0f3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 31 Jul 2024 18:12:59 +0200 Subject: [PATCH 384/693] sort of getting there, kinda --- src/shady/body_builder.c | 2 ++ src/shady/passes/cleanup.c | 12 ++++++++++-- src/shady/passes/lower_stack.c | 5 +++-- src/shady/passes/opt_restructure.c | 21 +++++++++------------ src/shady/print.c | 5 +++-- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 8e316a4a8..b5ce11371 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -35,6 +35,8 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp if (bb->arena->config.check_types) { assert(is_instruction(instruction)); } + if (bb->arena->config.allow_fold && instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) + return instruction->payload.prim_op.operands; StackEntry entry = { .vars = empty(bb->arena), .structured.payload.let = { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 28f4e7447..256920086 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -105,8 +105,8 @@ static bool has_side_effects(const Node* instr) { } const Node* process(Context* ctx, const Node* old) { - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; if (old->tag == Function_TAG || old->tag == Constant_TAG) { Context c = *ctx; c.map = create_uses_map(old, NcType | NcDeclaration); @@ -141,7 +141,15 @@ const Node* process(Context* ctx, const Node* old) { } BodyBuilder* bb = begin_body(a); - const Node* instruction = rewrite_node(r, old->payload.let.instruction); + const Node* oinstruction = old->payload.let.instruction; + if (oinstruction->tag == PrimOp_TAG && oinstruction->payload.prim_op.op == quote_op) { + Nodes args = oinstruction->payload.prim_op.operands; + if (args.count == 1) { + register_processed(r, oinstruction, first(rewrite_nodes(r, args))); + return finish_body(bb, rewrite_node(r, get_abstraction_body(old->payload.let.tail))); + } + } + const Node* instruction = rewrite_node(r, oinstruction); // optimization: fold blocks if (instruction->tag == Block_TAG) { *ctx->todo = true; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 7817b4162..ee4a14101 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -93,7 +93,8 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; if (old->tag == Function_TAG && strcmp(get_abstraction_name(old), "generated_init") == 0) { Node* new = recreate_decl_header_identity(&ctx->rewriter, old); @@ -120,7 +121,7 @@ static const Node* process_node(Context* ctx, const Node* old) { case SetStackSize_TAG: { assert(ctx->stack); BodyBuilder* bb = begin_body(a); - const Node* val = rewrite_node(&ctx->rewriter, old->payload.set_stack_size.value); + const Node* val = rewrite_node(r, old->payload.set_stack_size.value); gen_store(bb, ctx->stack_pointer, val); return yield_values_and_wrap_in_block(bb, empty(a)); } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 08901bfa0..288e09013 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -174,18 +174,9 @@ static ControlEntry* search_containing_control(Context* ctx, const Node* old_tok return entry; } -static const Node* rebuild_let(Context* ctx, const Node* old_let, const Node* new_instruction, const Node* exit_ladder) { - IrArena* a = ctx->rewriter.dst_arena; - const Node* old_tail = get_let_tail(old_let); - Nodes otail_params = get_abstraction_params(old_tail); - assert(otail_params.count == 0); - - const Node* structured_lam = case_(a, empty(a), structure(ctx, old_tail, exit_ladder)); - return let(a, new_instruction, structured_lam); -} - static const Node* structure(Context* ctx, const Node* abs, const Node* exit_ladder) { - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; const Node* body = get_abstraction_body(abs); assert(body); @@ -215,7 +206,13 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad break; } } - return rebuild_let(ctx, body, recreate_node_identity(&ctx->rewriter, old_instr), exit_ladder); + const Node* new_instruction = recreate_node_identity(&ctx->rewriter, old_instr); + register_processed(r, old_instr, new_instruction); + Nodes otail_params = get_abstraction_params(old_tail); + assert(otail_params.count == 0); + + const Node* structured_lam = case_(a, empty(a), structure(ctx, old_tail, exit_ladder)); + return let(a, new_instruction, structured_lam); } case Jump_TAG: { return handle_bb_callsite(ctx, abs, body, exit_ladder); diff --git a/src/shady/print.c b/src/shady/print.c index 4f870ed46..b06f12ce5 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1114,11 +1114,12 @@ static void print_operand_name_helper(Printer* p, PrintConfig config, String nam } static void print_operand_helper(Printer* p, PrintConfig config, NodeClass nc, const Node* op) { + // print(p, "%%%d ", op->id); + // print_node(p, op, config); + if (is_instruction(op) && op->arena->config.check_types) print(p, "%%%d", op->id); else { - if (!op->arena->config.check_types) - print(p, "%%%d", op->id); print_node(p, op, config); } } From 1b6d9176c91e9ae66499b7520310ebee5a33d831 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 09:28:52 +0200 Subject: [PATCH 385/693] fix binding --- include/shady/grammar.json | 2 +- src/shady/body_builder.c | 6 +++--- src/shady/constructors.c | 2 +- src/shady/passes/bind.c | 10 +++++++--- src/shady/print.c | 4 ++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index aab04ce93..a16818aa4 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -451,7 +451,7 @@ { "name": "instruction", "class": "instruction" }, { "name": "mutable", "type": "bool" }, { "name": "names", "class": "string", "list": true }, - { "name": "types", "type": "Nodes*" } + { "name": "types", "class": "type", "list": true } ] }, { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index b5ce11371..5c5e53f3b 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -66,15 +66,15 @@ Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String co return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count); } -const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes* types); +const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes types); Nodes parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names) { - const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, true, output_names, &provided_types); + const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, true, output_names, provided_types); return bind_internal(bb, let_mut_instr, 0); } Nodes parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names) { - const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, false, output_names, NULL); + const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, false, output_names, empty(bb->arena)); return bind_internal(bb, let_mut_instr, 0); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 6e4a59df2..c7d42d085 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -110,7 +110,7 @@ Node* param(IrArena* arena, const Type* type, const char* name) { return create_node_helper(arena, node, NULL); } -const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes* types) { +const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes types) { BindIdentifiers payload = { .instruction = instruction, .mutable = mut, diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index afc9133e4..0bc561cfa 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -125,7 +125,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, BodyBuilder* bb, const for (size_t i = 0; i < names.count; i++) { String name = names.strings[i]; if (node->payload.bind_identifiers.mutable) { - const Type* type_annotation = node->payload.bind_identifiers.types->nodes[i]; + const Type* type_annotation = node->payload.bind_identifiers.types.nodes[i]; assert(type_annotation); const Node* alloca = stack_alloc(a, (StackAlloc) {rewrite_node(&ctx->rewriter, type_annotation)}); const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; @@ -135,6 +135,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, BodyBuilder* bb, const add_binding(ctx, true, name, ptr); log_string(DEBUGV, "Bound mutable variable '%s'\n", name); } else { + log_string(DEBUGV, "Bound immutable variable '%s'\n", name); add_binding(ctx, false, name, results.nodes[i]); } } @@ -277,8 +278,11 @@ static const Node* bind_node(Context* ctx, const Node* node) { case Case_TAG: { Nodes old_params = node->payload.case_.params; Nodes new_params = recreate_params(&ctx->rewriter, old_params); - // for (size_t i = 0; i < new_params.count; i++) - // add_binding(ctx, false, old_params.nodes[i]->payload.param.name, new_params.nodes[i]); + for (size_t i = 0; i < new_params.count; i++) { + String name = old_params.nodes[i]->payload.param.name; + if (name) + add_binding(ctx, false, name, new_params.nodes[i]); + } register_processed_list(&ctx->rewriter, old_params, new_params); const Node* new_body = rewrite_node(&ctx->rewriter, node->payload.case_.body); return case_(a, new_params, new_body); diff --git a/src/shady/print.c b/src/shady/print.c index b06f12ce5..8f9a28098 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -624,9 +624,9 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { Strings names = binders->names; instruction = binders->instruction; for (size_t i = 0; i < names.count; i++) { - if (binders->types) { + if (binders->mutable) { printf(" "); - print_node(binders->types->nodes[i]); + print_node(binders->types.nodes[i]); } printf(" "); printf("%s", names.strings[i]); From 5f5ff849b79573efd45c43e26919c02c3a1b4d1d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 14:29:11 +0200 Subject: [PATCH 386/693] logging improvements --- src/common/log.c | 2 +- src/common/log.h | 10 +++++----- src/driver/slim.c | 12 ++++++++---- src/frontend/llvm/l2s.c | 2 +- src/shady/compile.c | 2 +- src/shady/print.c | 21 +++++++++++++-------- src/shady/rewrite.c | 11 +++++++++++ src/shady/rewrite.h | 2 ++ 8 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/common/log.c b/src/common/log.c index 66e27dbf6..5cdcffbd3 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -16,7 +16,7 @@ void set_log_level(LogLevel l) { void log_string(LogLevel level, const char* format, ...) { va_list args; va_start(args, format); - if (level >= shady_log_level) + if (level <= shady_log_level) vfprintf(stderr, format, args); va_end(args); } diff --git a/src/common/log.h b/src/common/log.h index 7c48f41a3..74f131abf 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -7,12 +7,12 @@ typedef struct Node_ Node; typedef struct Module_ Module; typedef enum LogLevel_ { - DEBUGVV, - DEBUGV, - DEBUG, - INFO, + ERROR, WARN, - ERROR + INFO, + DEBUG, + DEBUGV, + DEBUGVV, } LogLevel; LogLevel get_log_level(); diff --git a/src/driver/slim.c b/src/driver/slim.c index ce98f783c..99954698d 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -26,10 +26,14 @@ int main(int argc, char** argv) { IrArena* arena = new_ir_arena(&aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one - driver_load_source_files(&args, mod); - - driver_compile(&args, mod); - info_print("Done\n"); + ShadyErrorCodes err = driver_load_source_files(&args, mod); + if (err) + exit(err); + + err = driver_compile(&args, mod); + if (err) + exit(err); + info_print("Compilation successful\n"); destroy_ir_arena(arena); destroy_driver_config(&args); diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 973fbdf90..008ccca3b 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -77,7 +77,7 @@ typedef struct { static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); - if (get_log_level() <= DEBUG) + if (get_log_level() >= DEBUG) LLVMDumpValue((LLVMValueRef)bb); struct List* phis = new_list(LLVMValueRef); diff --git a/src/shady/compile.c b/src/shady/compile.c index 0af5edeff..70ef5fb0c 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -24,6 +24,7 @@ void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial old_mod = *pmod; *pmod = pass(config, *pmod); (*pmod)->sealed = true; + debugvv_print("After pass %s: \n", pass_name); if (SHADY_RUN_VERIFY) verify_module(config, *pmod); if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) @@ -31,7 +32,6 @@ void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial old_mod = *pmod; if (config->optimisations.cleanup.after_every_pass) *pmod = cleanup(config, *pmod); - debugvv_print("After pass %s: \n", pass_name); log_module(DEBUGVV, config, *pmod); if (SHADY_RUN_VERIFY) verify_module(config, *pmod); diff --git a/src/shady/print.c b/src/shady/print.c index 8f9a28098..058a9a3e2 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1083,8 +1083,10 @@ void dump_module(Module* mod) { } void log_node(LogLevel level, const Node* node) { - if (level >= get_log_level()) { + if (level <= get_log_level()) { Printer* p = open_file_as_printer(stderr); + if (node) + print(p, "%%%d = ", node->id); print_node(p, node, (PrintConfig) { .color = true }); destroy_printer(p); } @@ -1097,7 +1099,7 @@ void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) config.print_builtin = compiler_cfg->logging.print_builtin; config.print_internal = compiler_cfg->logging.print_internal; } - if (level >= get_log_level()) { + if (level <= get_log_level()) { Printer* p = open_file_as_printer(stderr); print_module(p, mod, config); destroy_printer(p); @@ -1114,13 +1116,16 @@ static void print_operand_name_helper(Printer* p, PrintConfig config, String nam } static void print_operand_helper(Printer* p, PrintConfig config, NodeClass nc, const Node* op) { - // print(p, "%%%d ", op->id); - // print_node(p, op, config); - - if (is_instruction(op) && op->arena->config.check_types) - print(p, "%%%d", op->id); - else { + if (get_log_level() >= DEBUGV && false) { + if (op && (is_value(op) || is_instruction(op))) + print(p, "%%%d ", op->id); print_node(p, op, config); + } else { + if (op && is_instruction(op) && op->arena->config.check_types) + print(p, "%%%d", op->id); + else { + print_node(p, op, config); + } } } diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index d1729a038..60309280c 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -370,3 +370,14 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { } assert(false); } + +void dump_rewriter_map(Rewriter* r) { + size_t i = 0; + const Node* src, *dst; + while (dict_iter(r->map, &i, &src, &dst)) { + log_node(ERROR, src); + log_string(ERROR, " -> "); + log_node(ERROR, dst); + log_string(ERROR, "\n"); + } +} \ No newline at end of file diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index decdd27cc..e6b673cb4 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -78,4 +78,6 @@ void register_processed(Rewriter*, const Node*, const Node*); void register_processed_list(Rewriter*, Nodes, Nodes); void clear_processed_non_decls(Rewriter*); +void dump_rewriter_map(Rewriter*); + #endif From c6622f5deaa870d01df035efc742ae239ec164b5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 14:29:40 +0200 Subject: [PATCH 387/693] printer improvements --- src/shady/print.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/shady/print.c b/src/shady/print.c index 058a9a3e2..e63fbe662 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -48,9 +48,12 @@ struct PrinterCtx_ { #define BWHITE COLOR("\033[0;97m") #define printf(...) print(ctx->printer, __VA_ARGS__) -#define print_node(n) print_node_impl(ctx, n) +#define print_node2(n) print_node_impl(ctx, n) +#define print_node(n) print_operand_helper(ctx->printer, ctx->config, 0, n) +#define print_operand(nc, n) print_operand_helper(ctx->printer, ctx->config, nc, n) static void print_node_impl(PrinterCtx* ctx, const Node* node); +static void print_operand_helper(Printer* p, PrintConfig config, NodeClass nc, const Node* op); #pragma GCC diagnostic error "-Wswitch" @@ -160,7 +163,7 @@ static void print_abs_body(PrinterCtx* ctx, const Node* block) { assert(!ctx->fn || is_function(ctx->fn)); assert(is_abstraction(block)); - print_node(get_abstraction_body(block)); + print_node2(get_abstraction_body(block)); // TODO: it's likely cleaner to instead print things according to the dominator tree in the first place. if (ctx->cfg != NULL) { @@ -618,7 +621,11 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { else printf("val"); printf(RESET); - } + }/* else { + printf(GREEN); + printf("let "); + printf(RESET); + }*/ if (binders) { Strings names = binders->names; @@ -632,7 +639,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf("%s", names.strings[i]); printf(RESET); } - printf(" = %%%d = ", instruction->id); + printf(" = "); } else { if (result_types.count > 1) { printf("["); @@ -647,12 +654,13 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(", "); } printf("]"); + printf(" = "); + } else { + printf("%%%d = ", instruction->id); } - printf("%%%zu", instruction->id); - printf(" = "); } - print_node(instruction); + print_node_impl(ctx, instruction); if (!ctx->config.in_cfg) { printf(";\n"); print_abs_body(ctx, tail); @@ -666,7 +674,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(GREEN); printf(" in "); printf(RESET); - print_node(tail); + print_node2(tail); printf(";"); } break; @@ -970,7 +978,7 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { printf("`%s`", node->payload.unbound.name); printf(RESET); } else if (node->tag == UnboundBBs_TAG) { - print_node(node->payload.unbound_bbs.body); + print_node2(node->payload.unbound_bbs.body); for (size_t i = 0; i < node->payload.unbound_bbs.children_blocks.count; i++) print_basic_block(ctx, node->payload.unbound_bbs.children_blocks.nodes[i]); } else switch (node->tag) { @@ -1054,6 +1062,8 @@ void print_node(Printer* printer, const Node* node, PrintConfig config) { void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { Growy* g = new_growy(); Printer* p = open_growy_as_printer(g); + if (node) + print(p, "%%%d ", node->id); print_node(p, node, (PrintConfig) { .reparseable = true }); destroy_printer(p); *size = growy_size(g); @@ -1071,6 +1081,8 @@ void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { void dump_node(const Node* node) { Printer* p = open_file_as_printer(stdout); + if (node) + print(p, "%%%d ", node->id); print_node(p, node, (PrintConfig) { .color = true }); printf("\n"); } From 39d94816978500063c8dbfc8dcf6762d199712d6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 14:30:10 +0200 Subject: [PATCH 388/693] fixed Let in spirv --- src/backend/spirv/emit_spv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 6c013a3f2..c3fa7f043 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -388,7 +388,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo case Let_TAG: { const Node* tail = get_let_tail(terminator); const Node* instruction = terminator->payload.let.instruction; - Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction); + Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction->type); LARRAY(SpvId, results, types.count); emit_instruction(emitter, fn_builder, &basic_block_builder, &merge_targets, instruction, types.count, results); assert(tail->tag == Case_TAG); From 067cb0665a2b3ca58a64c3b44b094e9856e4bdca Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 14:30:37 +0200 Subject: [PATCH 389/693] added verifier pass for dealing with unbound instructions --- src/shady/analysis/verify.c | 68 +++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 739b377a7..e7bb36ffb 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -100,7 +100,69 @@ static void verify_nominal_node(const Node* fn, const Node* n) { } } -static void verify_bodies(Module* mod) { +typedef struct ScheduleContext_ { + Visitor visitor; + struct Dict* bound; + struct ScheduleContext_* parent; + CompilerConfig* config; + Module* mod; +} ScheduleContext; + +static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { + if (is_instruction(node)) { + ScheduleContext* search = ctx; + while (search) { + if (find_key_dict(const Node*, search->bound, node)) + break; + search = search->parent; + } + if (!search) { + log_string(ERROR, "Scheduling problem: "); + log_node(ERROR, node); + log_string(ERROR, "was encountered before we say it be bound by a let!\n"); + log_module(ERROR, ctx->config, ctx->mod); + error_die(); + } + } + visit_node_operands(&ctx->visitor, NcTerminator | NcDeclaration, node); +} + +static void verify_schedule_node(ScheduleContext* parent, CompilerConfig* config, Module* mod, CFNode* node) { + ScheduleContext new = { + .visitor = { + .visit_node_fn = (VisitNodeFn) verify_schedule_visitor + }, + .bound = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .parent = parent, + .config = config, + .mod = mod, + }; + struct List* dominated = node->dominates; + size_t len = entries_count_list(dominated); + + const Node* terminator = get_abstraction_body(node->node); + while (terminator) { + if (terminator->tag != Let_TAG) + break; + const Node* instr = get_let_instruction(terminator); + insert_set_get_key(const Node*, new.bound, instr); + visit_node_operands(&new.visitor, NcTerminator | NcDeclaration, instr); + terminator = get_abstraction_body(get_let_tail(terminator)); + } + + for (size_t i = 0; i < len; i++) { + verify_schedule_node(&new, config, mod, read_list(CFNode*, dominated)[i]); + } + + destroy_dict(new.bound); +} + +static void verify_schedule(const CompilerConfig* config, Module* mod, CFG* cfg) { + compute_domtree(cfg); + verify_schedule_node(NULL, config, mod, cfg->entry); +} + +static void verify_bodies(const CompilerConfig* config, Module* mod) { struct List* cfgs = build_cfgs(mod); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; @@ -112,6 +174,8 @@ static void verify_bodies(Module* mod) { } } + verify_schedule(config, mod, cfg); + destroy_cfg(cfg); } destroy_list(cfgs); @@ -129,6 +193,6 @@ void verify_module(const CompilerConfig* config, Module* mod) { // TODO add a normalized flag to the IR and check grammar is adhered to strictly if (get_module_arena(mod)->config.check_types) { verify_scoping(config, mod); - verify_bodies(mod); + verify_bodies(config, mod); } } From 407baf4d4ddc6ec78ba972fa2b0f14231cb9ad96 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 14:31:13 +0200 Subject: [PATCH 390/693] various misc changes to rewriting --- include/shady/grammar.json | 8 +++++++- src/shady/passes/cleanup.c | 13 ++++++++++--- src/shady/passes/infer.c | 1 + src/shady/passes/lower_subgroup_vars.c | 8 ++++++-- src/shady/passes/normalize.c | 14 +++++++++----- src/shady/passes/reconvergence_heuristics.c | 14 ++++++-------- src/shady/rewrite.c | 19 +++++++++++++++++-- src/shady/type.c | 2 ++ 8 files changed, 58 insertions(+), 21 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index a16818aa4..386e25a90 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -366,7 +366,8 @@ }, { "name": "Call", - "class": "instruction", + "class": ["instruction", "value"], + "nominal": true, "ops": [ { "name": "callee", "class": "value" }, { "name": "args", "class": "value", "list": true } @@ -511,6 +512,7 @@ { "name": "MergeContinue", "class": "terminator", + "nominal": true, "ops": [ { "name": "args", "class": "value", "list": true } ] @@ -518,6 +520,7 @@ { "name": "MergeBreak", "class": "terminator", + "nominal": true, "ops": [ { "name": "args", "class": "value", "list": true } ] @@ -525,6 +528,7 @@ { "name": "MergeSelection", "class": "terminator", + "nominal": true, "ops": [ { "name": "args", "class": "value", "list": true } ] @@ -532,6 +536,7 @@ { "name": "BlockYield", "class": "terminator", + "nominal": true, "ops": [ { "name": "args", "class": "value", "list": true } ] @@ -540,6 +545,7 @@ "name": "Return", "snake_name": "fn_ret", "class": "terminator", + "nominal": true, "ops": [ { "name": "args", "class": "value", "list": true } ] diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 256920086..45cabf88b 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -147,15 +147,22 @@ const Node* process(Context* ctx, const Node* old) { if (args.count == 1) { register_processed(r, oinstruction, first(rewrite_nodes(r, args))); return finish_body(bb, rewrite_node(r, get_abstraction_body(old->payload.let.tail))); + } else { + register_processed(r, oinstruction, tuple_helper(a, rewrite_nodes(r, args))); + return finish_body(bb, rewrite_node(r, get_abstraction_body(old->payload.let.tail))); } } - const Node* instruction = rewrite_node(r, oinstruction); + const Node* instruction; // optimization: fold blocks - if (instruction->tag == Block_TAG) { + if (oinstruction->tag == Block_TAG) { *ctx->todo = true; - instruction = flatten_block(a, instruction, bb); + instruction = flatten_block(a, recreate_node_identity(r, oinstruction), bb); + register_processed(r, oinstruction, instruction); if (is_terminator(instruction)) return finish_body(bb, instruction); + } else { + instruction = rewrite_node(r, oinstruction); + register_processed(r, oinstruction, instruction); } const Node* nlet = let(a, instruction, rewrite_node(r, old->payload.let.tail)); return finish_body(bb, nlet); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index c186df63f..e7ba48339 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -604,6 +604,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { // const Node* otail = node->payload.let.ttail; // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); const Node* inferred_instruction = infer(ctx, node->payload.let.instruction, NULL); + register_processed(&ctx->rewriter, node->payload.let.instruction, inferred_instruction); Nodes inferred_yield_types = unwrap_multiple_yield_types(a, inferred_instruction->type); LARRAY(const Node*, vars, inferred_yield_types.count); for (size_t i = 0; i < inferred_yield_types.count; i++) { diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 20294bece..bbf57f3e0 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -17,7 +17,8 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const const Node* found = search_processed(&ctx->rewriter, node); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { case PtrType_TAG: { @@ -69,7 +70,10 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const c.b = b; return finish_body(b, recreate_node_identity(&c.rewriter, node)); } - return recreate_node_identity(&ctx->rewriter, node); + const Node* new = recreate_node_identity(&ctx->rewriter, node); + if (class == NcInstruction) + register_processed(r, node, new); + return new; } Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index 0516c85c3..3efdd6eee 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -78,7 +78,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str case NcInstruction: { if (is_instruction(node)) { const Node* new = process_node(ctx, node); - register_processed(r, node, new); + //register_processed(r, node, new); return new; } const Node* val = force_to_be_value(ctx, node); @@ -148,11 +148,15 @@ static const Node* process_node(Context* ctx, const Node* node) { return case_(a, new_params, new_body); } case Let_TAG: { - const Node* new = recreate_node_identity(r, node); const Node* oinstr = get_let_instruction(node); - const Node* ninstr = get_let_instruction(new); + const Node* found = search_processed(r, oinstr); + if (found) + return rewrite_node(r, get_abstraction_body(get_let_tail(node))); + const Node* ninstr = rewrite_node(r, oinstr); insert_dict_and_get_result(const Node*, const Node*, ctx->bound, oinstr, ninstr); - register_processed(r, node, new); + register_processed(r, oinstr, ninstr); + const Node* new = recreate_node_identity(r, node); + //register_processed(r, node, new); return new; } default: break; @@ -172,7 +176,7 @@ Module* normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { .bound = NULL, }; - ctx.rewriter.config.search_map = true; + ctx.rewriter.config.search_map = false; ctx.rewriter.config.write_map = false; rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 1f124d3de..41ee13004 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -153,14 +153,12 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (exiting_nodes_count > 1) exit_destination_alloca = gen_stack_alloc(outer_bb, int32_type(arena)); - Node* fn = (Node*) find_processed(rewriter, ctx->current_fn); - const Node* join_token_exit = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { - .yield_types = empty(arena) + .yield_types = empty(arena) }), true), "jp_exit"); const Node* join_token_continue = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { - .yield_types = inner_yield_types + .yield_types = inner_yield_types }), true), "jp_continue"); LARRAY(const Node*, exit_wrappers, exiting_nodes_count); @@ -277,12 +275,12 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); loop_outer->payload.basic_block.body = finish_body(inner_bb, jump(arena, (Jump) { - .target = loop_outer, - .args = inner_control_results + .target = loop_outer, + .args = inner_control_results })); gen_control(outer_bb, empty(arena), case_(arena, singleton(join_token_exit), jump(arena, (Jump) { - .target = loop_outer, - .args = nparams + .target = loop_outer, + .args = nparams }))); LARRAY(const Node*, exit_numbers, exiting_nodes_count); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 60309280c..6d959a6f6 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -70,6 +70,14 @@ Rewriter create_children_rewriter(Rewriter* parent) { return r; } +static bool should_memoize(const Node* node) { + if (is_declaration(node)) + return false; + if (node->tag == BasicBlock_TAG) + return false; + return true; +} + const Node* rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNodeFn fn) { assert(rewriter->rewrite_fn); if (!node) @@ -84,7 +92,7 @@ const Node* rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNo const Node* rewritten = fn(rewriter, node); if (is_declaration(node)) return rewritten; - if (rewriter->config.write_map) { + if (rewriter->config.write_map && should_memoize(node)) { register_processed(rewriter, node, rewritten); } return rewritten; @@ -121,7 +129,7 @@ const Node* rewrite_op_with_fn(Rewriter* rewriter, NodeClass class, String op_na const Node* rewritten = fn(rewriter, class, op_name, node); if (is_declaration(node)) return rewritten; - if (rewriter->config.write_map) { + if (rewriter->config.write_map && should_memoize(node)) { register_processed(rewriter, node, rewritten); } return rewritten; @@ -193,6 +201,12 @@ void register_processed(Rewriter* ctx, const Node* old, const Node* new) { #ifndef NDEBUG const Node* found = search_processed_(ctx, old, false); if (found) { + // this can happen and is typically harmless + // ie: when rewriting a jump into a loop, the outer jump cannot be finished until the loop body is rebuilt + // and therefore the back-edge jump inside the loop will be rebuilt while the outer one isn't done. + // as long as there is no conflict, this is correct, but this might hide perf hazards if we fail to cache things + if (found == new) + return; error_print("Trying to replace "); log_node(ERROR, old); error_print(" with "); @@ -347,6 +361,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { case Let_TAG: { BodyBuilder* bb = begin_body(arena); const Node* instruction = rewrite_op_helper(rewriter, NcInstruction, "instruction", node->payload.let.instruction); + //register_processed(rewriter, node->payload.let.instruction, instruction); const Node* nlet = let(arena, instruction, rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail)); return finish_body(bb, nlet); } diff --git a/src/shady/type.c b/src/shady/type.c index ef3bd3313..e3116e812 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1006,6 +1006,8 @@ const Type* check_type_control(IrArena* arena, Control control) { assert(is_subtype(control.yield_types.nodes[i], join_point_yield_types.nodes[i])); } + assert(get_abstraction_params(control.tail).count == control.yield_types.count); + return noret_type(arena); } From 19f7e4710efa6f7d2e82930ffcc7a59a7b6dbc3d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 14:46:10 +0200 Subject: [PATCH 391/693] free_variables: find unbound instructions --- src/shady/analysis/free_variables.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index 9c07a78d8..d77149cea 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -84,17 +84,19 @@ static void dump_free_variables(Context* ctx, CFNode* cfnode, int depth) { static void search_op_for_free_variables(Context* visitor, NodeClass class, String op_name, const Node* node) { assert(node); switch (node->tag) { - case Param_TAG: { - //const Node** found = find_key_dict(const Node*, visitor->bound, node); - //if (!found) - insert_set_get_result(const Node*, visitor->live, node); - return; + case Let_TAG: { + const Node* instr = get_let_instruction(node); + bool r = insert_set_get_result(const Node*, visitor->bound, instr); + assert(r); + break; } case Function_TAG: case Case_TAG: case BasicBlock_TAG: assert(false); default: break; } + if (node->tag == Param_TAG || is_instruction(node)) + insert_set_get_result(const Node*, visitor->live, node); visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK, node); } From c62d8401e244e0939b93f405b1d0dc4536514833 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 14:46:26 +0200 Subject: [PATCH 392/693] diagnostics improvements --- src/shady/analysis/verify.c | 19 +++++++++++++------ src/shady/passes/cleanup.c | 4 ++++ src/shady/print.c | 4 ++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index e7bb36ffb..0daddf190 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -48,13 +48,19 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { CFG* cfg = read_list(CFG*, cfgs)[i]; struct Dict* map = compute_cfg_variables_map(cfg, CfgVariablesAnalysisFlagFreeSet); CFNodeVariables* entry_vars = *find_value_dict(CFNode*, CFNodeVariables*, map, cfg->entry); - size_t j = 0; - const Node* leaking; - while (dict_iter(entry_vars->free_set, &j, &leaking, NULL)) { - log_node(ERROR, leaking); - error_print("\n"); - } if (entries_count_dict(entry_vars->free_set) > 0) { + log_string(ERROR, "Leaking variables in "); + log_node(ERROR, cfg->entry->node); + log_string(ERROR, ":\n"); + + size_t j = 0; + const Node* leaking; + while (dict_iter(entry_vars->free_set, &j, &leaking, NULL)) { + log_node(ERROR, leaking); + error_print("\n"); + } + + log_string(ERROR, "Problematic module:\n"); log_module(ERROR, config, mod); error_die(); } @@ -120,6 +126,7 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { log_string(ERROR, "Scheduling problem: "); log_node(ERROR, node); log_string(ERROR, "was encountered before we say it be bound by a let!\n"); + log_string(ERROR, "Problematic module:\n"); log_module(ERROR, ctx->config, ctx->mod); error_die(); } diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 45cabf88b..49467e035 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -219,8 +219,12 @@ Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { Module* m = src; do { debugv_print("Cleanup round %d\n", r); + if (getenv("SHADY_DUMP_CLEAN_ROUNDS")) + log_module(DEBUGVV, config, m); todo = false; todo |= opt_demote_alloca(config, &m); + if (getenv("SHADY_DUMP_CLEAN_ROUNDS")) + log_module(DEBUGVV, config, m); todo |= simplify(config, &m); r++; } while (todo); diff --git a/src/shady/print.c b/src/shady/print.c index e63fbe662..bf7e61ee4 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -952,10 +952,10 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { if (is_type(node)) print_type(ctx, node); - else if (is_value(node)) - print_value(ctx, node); else if (is_instruction(node)) print_instruction(ctx, node); + else if (is_value(node)) + print_value(ctx, node); else if (is_terminator(node)) print_terminator(ctx, node); else if (node->tag == Case_TAG) { From b8be505bab51c84611d6f295dc36a769b834d4c4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 1 Aug 2024 15:49:32 +0200 Subject: [PATCH 393/693] removed case from let's tail --- include/shady/grammar.json | 2 +- include/shady/ir.h | 2 +- src/backend/c/emit_c.c | 5 +- src/backend/spirv/emit_spv.c | 4 +- src/frontend/llvm/l2s_postprocess.c | 2 +- src/shady/analysis/cfg.c | 132 +++++++++++++++------------- src/shady/analysis/cfg_dump.c | 11 +-- src/shady/analysis/free_variables.c | 2 +- src/shady/analysis/verify.c | 4 +- src/shady/body_builder.c | 3 +- src/shady/constructors.c | 6 +- src/shady/fold.c | 5 +- src/shady/node.c | 10 +-- src/shady/passes/bind.c | 2 +- src/shady/passes/cleanup.c | 10 +-- src/shady/passes/infer.c | 2 +- src/shady/passes/lower_cf_instrs.c | 6 +- src/shady/passes/lower_tailcalls.c | 3 +- src/shady/passes/normalize.c | 14 +-- src/shady/passes/opt_restructure.c | 35 +++----- src/shady/passes/opt_stack.c | 2 +- src/shady/print.c | 7 +- src/shady/rewrite.c | 2 +- src/shady/type.c | 2 - 24 files changed, 128 insertions(+), 145 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 386e25a90..41902bfd5 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -440,7 +440,7 @@ "constructor": "custom", "ops": [ { "name": "instruction", "class": "instruction" }, - { "name": "tail", "class": "case" } + { "name": "in", "class": "terminator" } ] }, { diff --git a/include/shady/ir.h b/include/shady/ir.h index 667cc071a..b981a1b65 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -187,7 +187,7 @@ Nodes get_abstraction_params(const Node* abs); void set_abstraction_body (Node* abs, const Node* body); const Node* get_let_instruction(const Node* let); -const Node* get_let_tail(const Node* let); +const Node* get_let_chain_end(const Node* terminator); const Node* extract_helper(const Node* composite, const Node* index); const Node* extract_multiple_ret_types_helper(const Node* composite, int index); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 01a129268..cbeba4fab 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -555,9 +555,6 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node }; emit_instruction(emitter, block_printer, instruction, ioutputs); - const Node* tail = get_let_tail(terminator); - assert(tail->tag == Case_TAG); - // Nodes vars = terminator->payload.let.variables; // assert(vars.count == yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { @@ -589,7 +586,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node default: assert(false); } } - emit_terminator(emitter, block_printer, tail->payload.case_.body); + emit_terminator(emitter, block_printer, terminator->payload.let.in); break; } diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index c3fa7f043..74a429f13 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -386,16 +386,14 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo } } case Let_TAG: { - const Node* tail = get_let_tail(terminator); const Node* instruction = terminator->payload.let.instruction; Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction->type); LARRAY(SpvId, results, types.count); emit_instruction(emitter, fn_builder, &basic_block_builder, &merge_targets, instruction, types.count, results); - assert(tail->tag == Case_TAG); for (size_t i = 0; i < types.count; i++) register_result(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); - emit_terminator(emitter, fn_builder, basic_block_builder, merge_targets, tail->payload.case_.body); + emit_terminator(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.let.in); return; } case Jump_TAG: { diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 144b13a90..5978a6118 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -88,7 +88,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Node* ninside = rewrite_node(r, node->payload.block.inside); const Node* term = get_abstraction_body(ninside); while (term->tag == Let_TAG) { - term = get_abstraction_body(get_let_tail(term)); + term = term->payload.let.in; } assert(term->tag == BlockYield_TAG); yield_types = get_values_types(a, term->payload.block_yield.args); diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index c5322eae7..e63768c6b 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -144,70 +144,76 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { const Node* terminator = get_abstraction_body(abs); if (!terminator) return; - switch (is_terminator(terminator)) { - case Let_TAG: { - const Node* target = get_let_tail(terminator); - add_structural_dominance_edge(ctx, node, target, LetTailEdge); - break; - } - case Jump_TAG: { - add_jump_edge(ctx, abs, terminator); - break; - } - case Branch_TAG: { - add_jump_edge(ctx, abs, terminator->payload.branch.true_jump); - add_jump_edge(ctx, abs, terminator->payload.branch.false_jump); - break; - } - case Switch_TAG: { - for (size_t i = 0; i < terminator->payload.br_switch.case_jumps.count; i++) - add_jump_edge(ctx, abs, terminator->payload.br_switch.case_jumps.nodes[i]); - add_jump_edge(ctx, abs, terminator->payload.br_switch.default_jump); - break; - } - case Join_TAG: { - CFNode** dst = find_value_dict(const Node*, CFNode*, ctx->join_point_values, terminator->payload.join.join_point); - if (dst) - add_edge(ctx, node->node, (*dst)->node, StructuredLeaveBodyEdge); - break; - } - case If_TAG: - add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); - if(terminator->payload.if_instr.if_false) - add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); - break; - case Match_TAG: - for (size_t i = 0; i < terminator->payload.match_instr.cases.count; i++) - add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); - break; - case Loop_TAG: - add_structural_dominance_edge(ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); - break; - case Control_TAG: - add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); - const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); - CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); - insert_dict(const Node*, CFNode*, ctx->join_point_values, param, let_tail_cfnode); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); - break; - case MergeSelection_TAG: - case MergeContinue_TAG: - case MergeBreak_TAG: { - break; // TODO i guess - } - case Terminator_BlockYield_TAG: { - break; - } - case TailCall_TAG: { - + while (true) { + switch (is_terminator(terminator)) { + case Let_TAG: { + terminator = terminator->payload.let.in; + continue; + // const Node* target = get_let_tail(terminator); + // add_structural_dominance_edge(ctx, node, target, LetTailEdge); + // break; + } + case Jump_TAG: { + add_jump_edge(ctx, abs, terminator); + return; + } + case Branch_TAG: { + add_jump_edge(ctx, abs, terminator->payload.branch.true_jump); + add_jump_edge(ctx, abs, terminator->payload.branch.false_jump); + return; + } + case Switch_TAG: { + for (size_t i = 0; i < terminator->payload.br_switch.case_jumps.count; i++) + add_jump_edge(ctx, abs, terminator->payload.br_switch.case_jumps.nodes[i]); + add_jump_edge(ctx, abs, terminator->payload.br_switch.default_jump); + return; + } + case Join_TAG: { + CFNode** dst = find_value_dict(const Node*, CFNode*, ctx->join_point_values, terminator->payload.join.join_point); + if (dst) + add_edge(ctx, node->node, (*dst)->node, StructuredLeaveBodyEdge); + return; + } + case If_TAG: + add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); + if (terminator->payload.if_instr.if_false) + add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + return; + case Match_TAG: + for (size_t i = 0; i < terminator->payload.match_instr.cases.count; i++) + add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + return; + case Loop_TAG: + add_structural_dominance_edge(ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + return; + case Control_TAG: + add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); + const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); + CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); + insert_dict(const Node*, CFNode*, ctx->join_point_values, param, let_tail_cfnode); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + return; + case MergeSelection_TAG: + case MergeContinue_TAG: + case MergeBreak_TAG: { + return; // TODO i guess + } + case Terminator_BlockYield_TAG: { + return; + } + case TailCall_TAG: + case Return_TAG: + case Unreachable_TAG: + return; + case NotATerminator: + if (terminator->arena->config.check_types) {error("Grammar problem"); } + return; } - case Return_TAG: - case Unreachable_TAG: break; - case NotATerminator: if (terminator->arena->config.check_types) { error("Grammar problem"); } break; + SHADY_UNREACHABLE; } } diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 1dcc4fc0e..181331c05 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -30,8 +30,8 @@ static void print_node_helper(Printer* p, const Node* n) { Printer* tmp_p = open_growy_as_printer(tmp_g); PrintConfig config = { - .color = false, - .in_cfg = true, + .color = false, + .in_cfg = true, }; print_node(tmp_p, n, config); @@ -76,13 +76,8 @@ static void dump_cf_node(FILE* output, const CFNode* n) { print_node_helper(p, body); print(p, "\\l"); - const Node* abs = body->payload.let.tail; - print(p, "%%%d: ", abs->id); - let_chain_end = read_list(CFEdge, let_chain_end->succ_edges)[0].dst; - assert(let_chain_end->node == abs); - assert(is_case(abs)); - body = get_abstraction_body(abs); + body = body->payload.let.in; } print_node_helper(p, body); diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index d77149cea..ebc50ea0b 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -87,7 +87,7 @@ static void search_op_for_free_variables(Context* visitor, NodeClass class, Stri case Let_TAG: { const Node* instr = get_let_instruction(node); bool r = insert_set_get_result(const Node*, visitor->bound, instr); - assert(r); + //assert(r); break; } case Function_TAG: diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 0daddf190..6f49ae229 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -125,7 +125,7 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { if (!search) { log_string(ERROR, "Scheduling problem: "); log_node(ERROR, node); - log_string(ERROR, "was encountered before we say it be bound by a let!\n"); + log_string(ERROR, "was encountered before we saw it be bound by a let!\n"); log_string(ERROR, "Problematic module:\n"); log_module(ERROR, ctx->config, ctx->mod); error_die(); @@ -154,7 +154,7 @@ static void verify_schedule_node(ScheduleContext* parent, CompilerConfig* config const Node* instr = get_let_instruction(terminator); insert_set_get_key(const Node*, new.bound, instr); visit_node_operands(&new.visitor, NcTerminator | NcDeclaration, instr); - terminator = get_abstraction_body(get_let_tail(terminator)); + terminator = terminator->payload.let.in; } for (size_t i = 0; i < len; i++) { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 5c5e53f3b..e97cfe53a 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -89,8 +89,7 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { StackEntry entry = read_list(StackEntry, bb->stack)[i]; switch (entry.structured.tag) { case NotAStructured_construct: - entry.structured.payload.let.tail = case_(bb->arena, entry.vars, terminator); - terminator = let(a, entry.structured.payload.let.instruction, entry.structured.payload.let.tail); + terminator = let(a, entry.structured.payload.let.instruction, terminator); break; case Structured_construct_If_TAG: entry.structured.payload.if_instr.tail = case_(bb->arena, entry.vars, terminator); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index c7d42d085..d5f2aeabc 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -74,14 +74,12 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { #include "constructors_generated.c" -const Node* let(IrArena* arena, const Node* instruction, const Node* tail) { +const Node* let(IrArena* arena, const Node* instruction, const Node* in) { Let payload = { .instruction = instruction, - .tail = tail, + .in = in, }; - assert(is_case(tail) && get_abstraction_params(tail).count == 0); - Node node; memset((void*) &node, 0, sizeof(Node)); node = (Node) { diff --git a/src/shady/fold.c b/src/shady/fold.c index 715d82be3..8be281a18 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -391,11 +391,10 @@ const Node* fold_node(IrArena* arena, const Node* node) { } else if (body->tag == Let_TAG) { // fold block { let x, y, z = I; yield (x, y, z); } back to I const Node* instr = get_let_instruction(body); - const Node* let_case = get_let_tail(body); - const Node* let_case_body = get_abstraction_body(let_case); + const Node* let_case_body = body->payload.let.in; if (let_case_body->tag == BlockYield_TAG) { bool only_forwards = true; - Nodes let_case_params = get_abstraction_params(let_case); + Nodes let_case_params = empty(arena); Nodes yield_args = let_case_body->payload.block_yield.args; if (let_case_params.count == yield_args.count) { for (size_t i = 0; i < yield_args.count; i++) { diff --git a/src/shady/node.c b/src/shady/node.c index a6607c033..f11e66b5e 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -177,7 +177,7 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi const Node* terminator = node->payload.block.inside->payload.case_.body; while (true) { if (terminator->tag == Let_TAG) - terminator = terminator->payload.let.tail->payload.case_.body; + terminator = terminator->payload.let.in; else if (is_structured_construct(terminator)) terminator = get_abstraction_body(get_structured_construct_tail(terminator)); else @@ -365,11 +365,11 @@ const Node* get_let_instruction(const Node* let) { } } -const Node* get_let_tail(const Node* let) { - switch (let->tag) { - case Let_TAG: return let->payload.let.tail; - default: assert(false); +const Node* get_let_chain_end(const Node* terminator) { + while (terminator->tag == Let_TAG) { + terminator = terminator->payload.let.in; } + return terminator; } KeyHash hash_node_payload(const Node* node); diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 0bc561cfa..39d047dd0 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -273,7 +273,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { } else { ninstr = rewrite_node(r, oinstruction); } - return finish_body(bb, let(a, ninstr, rewrite_node(r, get_let_tail(node)))); + return finish_body(bb, let(a, ninstr, rewrite_node(r, node->payload.let.in))); } case Case_TAG: { Nodes old_params = node->payload.case_.params; diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 49467e035..ca88e079d 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -75,7 +75,7 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* case NotATerminator: assert(false); case Terminator_Let_TAG: { add_structured_construct(bb, empty(arena), (Structured_constructTag) NotAStructured_construct, terminator->payload); - terminator = get_abstraction_body(terminator->payload.let.tail); + terminator = terminator->payload.let.in; continue; } case Terminator_BlockYield_TAG: { @@ -137,7 +137,7 @@ const Node* process(Context* ctx, const Node* old) { log_node(DEBUGVV, payload.instruction); debugvv_print("\n"); *ctx->todo = true; - return rewrite_node(&ctx->rewriter, get_abstraction_body(payload.tail)); + return rewrite_node(&ctx->rewriter, payload.in); } BodyBuilder* bb = begin_body(a); @@ -146,10 +146,10 @@ const Node* process(Context* ctx, const Node* old) { Nodes args = oinstruction->payload.prim_op.operands; if (args.count == 1) { register_processed(r, oinstruction, first(rewrite_nodes(r, args))); - return finish_body(bb, rewrite_node(r, get_abstraction_body(old->payload.let.tail))); + return finish_body(bb, rewrite_node(r, old->payload.let.in)); } else { register_processed(r, oinstruction, tuple_helper(a, rewrite_nodes(r, args))); - return finish_body(bb, rewrite_node(r, get_abstraction_body(old->payload.let.tail))); + return finish_body(bb, rewrite_node(r, old->payload.let.in)); } } const Node* instruction; @@ -164,7 +164,7 @@ const Node* process(Context* ctx, const Node* old) { instruction = rewrite_node(r, oinstruction); register_processed(r, oinstruction, instruction); } - const Node* nlet = let(a, instruction, rewrite_node(r, old->payload.let.tail)); + const Node* nlet = let(a, instruction, rewrite_node(r, old->payload.let.in)); return finish_body(bb, nlet); } case BasicBlock_TAG: { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index e7ba48339..aa812d903 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -610,7 +610,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { for (size_t i = 0; i < inferred_yield_types.count; i++) { assert(is_value_type(inferred_yield_types.nodes[i])); } - return let(a, inferred_instruction, infer_case(ctx, node->payload.let.tail, empty(a))); + return let(a, inferred_instruction, infer(ctx, node->payload.let.in, NULL)); } case Return_TAG: { const Node* imported_fn = ctx->current_fn; diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 08a8ec1e1..fbe19fa7a 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -169,7 +169,7 @@ static const Node* process_node(Context* ctx, const Node* node) { CFNode* dom = cfnode->idom; const Node* selection_instr = NULL; while (dom) { - const Node* body = get_abstraction_body(dom->node); + const Node* body = get_let_chain_end(get_abstraction_body(dom->node)); if(body->tag == If_TAG || body->tag == Match_TAG) { selection_instr = body; break; @@ -198,7 +198,7 @@ static const Node* process_node(Context* ctx, const Node* node) { CFNode* dom = cfnode->idom; const Node* selection_instr = NULL; while (dom) { - const Node* body = get_abstraction_body(dom->node); + const Node* body = get_let_chain_end(get_abstraction_body(dom->node)); if (body->tag == Loop_TAG) { selection_instr = body; break; @@ -227,7 +227,7 @@ static const Node* process_node(Context* ctx, const Node* node) { CFNode* dom = cfnode->idom; const Node* selection_instr = NULL; while (dom) { - const Node* body = get_abstraction_body(dom->node); + const Node* body = get_let_chain_end(get_abstraction_body(dom->node)); if (body->tag == Loop_TAG) { selection_instr = body; break; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index e4a068228..8a6979904 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -114,8 +114,7 @@ static const Node* process(Context* ctx, const Node* old) { if (old->payload.fun.body) { const Node* nbody = rewrite_node(&ctx2.rewriter, old->payload.fun.body); if (entry_point_annotation) { - const Node* lam = case_(a, empty(a), nbody); - nbody = let(a, call(a, (Call) { .callee = fn_addr_helper(a, ctx2.init_fn), .args = empty(a)}), lam); + nbody = let(a, call(a, (Call) { .callee = fn_addr_helper(a, ctx2.init_fn), .args = empty(a)}), nbody); } fun->payload.fun.body = nbody; } diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index 3efdd6eee..c1669da50 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -149,15 +149,19 @@ static const Node* process_node(Context* ctx, const Node* node) { } case Let_TAG: { const Node* oinstr = get_let_instruction(node); - const Node* found = search_processed(r, oinstr); + //const Node* found = search_processed(r, oinstr); + const Node** found = find_value_dict(const Node*, const Node*, ctx->bound, node); if (found) - return rewrite_node(r, get_abstraction_body(get_let_tail(node))); - const Node* ninstr = rewrite_node(r, oinstr); + return rewrite_node(r, node->payload.let.in); + const Node* ninstr = rewrite_op(r, NcInstruction, "instruction", oinstr); insert_dict_and_get_result(const Node*, const Node*, ctx->bound, oinstr, ninstr); register_processed(r, oinstr, ninstr); - const Node* new = recreate_node_identity(r, node); + bind_instruction_outputs_count(ctx->bb, ninstr, 0); + return rewrite_node(r, node->payload.let.in); + + //const Node* new = recreate_node_identity(r, node); //register_processed(r, node, new); - return new; + //return new; } default: break; } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 288e09013..568d41e28 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -84,7 +84,7 @@ static DFSStackEntry* encountered_before(Context* ctx, const Node* bb, size_t* p static const Node* structure(Context* ctx, const Node* abs, const Node* exit_ladder); -static const Node* handle_bb_callsite(Context* ctx, const Node* caller, const Node* j, const Node* exit_ladder) { +static const Node* handle_bb_callsite(Context* ctx, const Node* j, const Node* exit_ladder) { assert(j->tag == Jump_TAG); IrArena* a = ctx->rewriter.dst_arena; const Node* dst = j->payload.jump.target; @@ -137,9 +137,7 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* caller, const No Node* inner_exit_ladder_bb = basic_block(a, empty(a), unique_name(a, "exit_ladder_inline_me")); // Just jumps to the actual ladder - const Node* exit_ladder_trampoline = case_(a, empty(a), jump(a, (Jump) {.target = inner_exit_ladder_bb, .args = empty(a)})); - - const Node* structured = structure(&ctx2, dst, let(a, quote_helper(a, empty(a)), exit_ladder_trampoline)); + const Node* structured = structure(&ctx2, get_abstraction_body(dst), let(a, quote_helper(a, empty(a)), jump(a, (Jump) {.target = inner_exit_ladder_bb, .args = empty(a)}))); assert(is_terminator(structured)); // forget we rewrote all that destroy_dict(tmp_processed); @@ -174,17 +172,14 @@ static ControlEntry* search_containing_control(Context* ctx, const Node* old_tok return entry; } -static const Node* structure(Context* ctx, const Node* abs, const Node* exit_ladder) { +static const Node* structure(Context* ctx, const Node* body, const Node* exit_ladder) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; - const Node* body = get_abstraction_body(abs); - assert(body); + assert(body && is_terminator(body)); switch (is_terminator(body)) { case NotATerminator: case Let_TAG: { - const Node* old_tail = get_let_tail(body); - const Node* old_instr = get_let_instruction(body); switch (is_instruction(old_instr)) { case NotAnInstruction: assert(false); @@ -208,14 +203,11 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad } const Node* new_instruction = recreate_node_identity(&ctx->rewriter, old_instr); register_processed(r, old_instr, new_instruction); - Nodes otail_params = get_abstraction_params(old_tail); - assert(otail_params.count == 0); - const Node* structured_lam = case_(a, empty(a), structure(ctx, old_tail, exit_ladder)); - return let(a, new_instruction, structured_lam); + return let(a, new_instruction, structure(ctx, body->payload.let.in, exit_ladder)); } case Jump_TAG: { - return handle_bb_callsite(ctx, abs, body, exit_ladder); + return handle_bb_callsite(ctx, body, exit_ladder); } // br(cond, true_bb, false_bb, args) // becomes @@ -223,10 +215,10 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case Branch_TAG: { const Node* condition = rewrite_node(&ctx->rewriter, body->payload.branch.condition); - const Node* true_body = handle_bb_callsite(ctx, abs, body->payload.branch.true_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); + const Node* true_body = handle_bb_callsite(ctx, body->payload.branch.true_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); - const Node* false_body = handle_bb_callsite(ctx, abs, body->payload.branch.false_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); + const Node* false_body = handle_bb_callsite(ctx, body->payload.branch.false_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* if_false_lam = case_(a, empty(a), false_body); BodyBuilder* bb = begin_body(a); @@ -236,12 +228,12 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad case Switch_TAG: { const Node* switch_value = rewrite_node(&ctx->rewriter, body->payload.br_switch.switch_value); - const Node* default_body = handle_bb_callsite(ctx, abs, body->payload.br_switch.default_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); + const Node* default_body = handle_bb_callsite(ctx, body->payload.br_switch.default_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* default_case = case_(a, empty(a), default_body); LARRAY(const Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { - cases[i] = case_(a, empty(a), handle_bb_callsite(ctx, abs, body->payload.br_switch.case_jumps.nodes[i], merge_selection(a, (MergeSelection) {.args = empty(a)}))); + cases[i] = case_(a, empty(a), handle_bb_callsite(ctx, body->payload.br_switch.case_jumps.nodes[i], merge_selection(a, (MergeSelection) {.args = empty(a)}))); } BodyBuilder* bb = begin_body(a); @@ -291,12 +283,11 @@ static const Node* structure(Context* ctx, const Node* abs, const Node* exit_lad // Wrap the tail in a guarded if, to handle 'far' joins const Node* level_value = gen_load(bb2, ctx->level_ptr); const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); - const Node* true_body = structure(ctx, get_structured_construct_tail(body), merge_selection(a, (MergeSelection) { .args = empty(a) })); + const Node* true_body = structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), merge_selection(a, (MergeSelection) { .args = empty(a) })); const Node* if_true_lam = case_(a, empty(a), true_body); gen_if(bb2, empty(a), guard, if_true_lam, NULL); - const Node* tail_lambda = case_(a, empty(a), finish_body(bb2, exit_ladder)); - return finish_body(bb_outer, structure(&control_ctx, old_control_body, let(a, quote_helper(a, empty(a)), tail_lambda))); + return finish_body(bb_outer, structure(&control_ctx, get_abstraction_body(old_control_body), let(a, quote_helper(a, empty(a)), finish_body(bb2, exit_ladder)))); } case Join_TAG: { ControlEntry* control = search_containing_control(ctx, body->payload.join.join_point); @@ -378,7 +369,7 @@ static const Node* process(Context* ctx, const Node* node) { TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; - new->payload.fun.body = finish_body(bb, structure(&ctx2, node, unreachable(a))); + new->payload.fun.body = finish_body(bb, structure(&ctx2, get_abstraction_body(node), unreachable(a))); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. pop_list_impl(ctx->cleanup_stack); diff --git a/src/shady/passes/opt_stack.c b/src/shady/passes/opt_stack.c index 7b712df1b..932276017 100644 --- a/src/shady/passes/opt_stack.c +++ b/src/shady/passes/opt_stack.c @@ -74,7 +74,7 @@ static const Node* process(Context* ctx, const Node* node) { case NotAnInstruction: assert(false); } - ntail = rewrite_node(&child_ctx.rewriter, node->payload.let.tail); + ntail = rewrite_node(&child_ctx.rewriter, node->payload.let.in); const Node* ninstruction = NULL; if (is_push && !child_ctx.state->leaks) { diff --git a/src/shady/print.c b/src/shady/print.c index bf7e61ee4..6555367f7 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -610,7 +610,6 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { const BindIdentifiers* binders = NULL; if (instruction->tag == BindIdentifiers_TAG) binders = &instruction->payload.bind_identifiers; - const Node* tail = get_let_tail(node); if (!ctx->config.reparseable) { Nodes result_types = instruction->type ? unwrap_multiple_yield_types(node->arena, instruction->type) : empty(node->arena); if (binders) { @@ -663,7 +662,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { print_node_impl(ctx, instruction); if (!ctx->config.in_cfg) { printf(";\n"); - print_abs_body(ctx, tail); + print_node2(node->payload.let.in); } } else { printf(GREEN); @@ -674,7 +673,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(GREEN); printf(" in "); printf(RESET); - print_node2(tail); + print_node2(node->payload.let.in); printf(";"); } break; @@ -1128,7 +1127,7 @@ static void print_operand_name_helper(Printer* p, PrintConfig config, String nam } static void print_operand_helper(Printer* p, PrintConfig config, NodeClass nc, const Node* op) { - if (get_log_level() >= DEBUGV && false) { + if (getenv("SHADY_SUPER_VERBOSE_NODE_DEBUG")) { if (op && (is_value(op) || is_instruction(op))) print(p, "%%%d ", op->id); print_node(p, op, config); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 6d959a6f6..1faa999e5 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -362,7 +362,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { BodyBuilder* bb = begin_body(arena); const Node* instruction = rewrite_op_helper(rewriter, NcInstruction, "instruction", node->payload.let.instruction); //register_processed(rewriter, node->payload.let.instruction, instruction); - const Node* nlet = let(arena, instruction, rewrite_op_helper(rewriter, NcCase, "tail", node->payload.let.tail)); + const Node* nlet = let(arena, instruction, rewrite_op_helper(rewriter, NcTerminator, "in", node->payload.let.in)); return finish_body(bb, nlet); } case Case_TAG: { diff --git a/src/shady/type.c b/src/shady/type.c index e3116e812..5fbbb4ee6 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1181,8 +1181,6 @@ const Type* check_type_debug_printf(IrArena* a, DebugPrintf payload) { const Type* check_type_let(IrArena* arena, Let let) { Nodes produced_types = unwrap_multiple_yield_types(arena, let.instruction->type); - Nodes param_types = get_param_types(arena, let.tail->payload.case_.params); - assert(param_types.count == 0); // check_arguments_types_against_parameters_helper(param_types, produced_types); return noret_type(arena); } From e172136c77d497563a9d84305fda45a89df174de Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 11:34:17 +0200 Subject: [PATCH 394/693] move print.h to public include folder --- include/shady/be/dump.h | 3 --- {src => include}/shady/print.h | 3 +++ src/driver/driver.c | 4 +--- src/shady/analysis/cfg_dump.c | 2 +- src/shady/print.c | 3 ++- test/opt/opt_oracle.c | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) rename {src => include}/shady/print.h (84%) diff --git a/include/shady/be/dump.h b/include/shady/be/dump.h index a8f247ce0..de0b5e561 100644 --- a/include/shady/be/dump.h +++ b/include/shady/be/dump.h @@ -1,9 +1,6 @@ #ifndef SHD_BE_DUMP_H #define SHD_BE_DUMP_H -void print_module_into_str(Module* mod, char** str_ptr, size_t* size); -void print_node_into_str(const Node* node, char** str_ptr, size_t* size); - void dump_module(Module*); void dump_node(const Node* node); diff --git a/src/shady/print.h b/include/shady/print.h similarity index 84% rename from src/shady/print.h rename to include/shady/print.h index d575c3449..069778983 100644 --- a/src/shady/print.h +++ b/include/shady/print.h @@ -16,6 +16,9 @@ typedef struct { bool in_cfg; } PrintConfig; +void print_module_into_str(Module* mod, char** str_ptr, size_t* size); +void print_node_into_str(const Node* node, char** str_ptr, size_t* size); + void print_module(Printer* printer, Module* mod, PrintConfig config); void print_node(Printer* printer, const Node* node, PrintConfig config); void print_node_operand(Printer* printer, const Node* node, String op_name, NodeClass op_class, const Node* op, PrintConfig config); diff --git a/src/driver/driver.c b/src/driver/driver.c index cd653a689..a1ca54ef5 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -1,12 +1,10 @@ #include "shady/ir.h" #include "shady/driver.h" - +#include "shady/print.h" #include "shady/be/c.h" #include "shady/be/spirv.h" #include "shady/be/dump.h" -#include "print.h" - #include "../frontend/slim/parser.h" #include "list.h" diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 181331c05..18e69c941 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -1,7 +1,7 @@ #include "cfg.h" #include "ir_private.h" -#include "print.h" +#include "shady/print.h" #include "list.h" #include "dict.h" diff --git a/src/shady/print.c b/src/shady/print.c index 6555367f7..2f55cde65 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1,4 +1,5 @@ -#include "print.h" +#include "shady/print.h" + #include "ir_private.h" #include "analysis/cfg.h" #include "analysis/uses.h" diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 955509359..893aa9994 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -1,8 +1,8 @@ #include "shady/ir.h" #include "shady/driver.h" +#include "shady/print.h" #include "../shady/visit.h" -#include "../shady/print.h" #include "log.h" From a9d188a2d860e49392c88eb66b19b07b9ee311ec Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 11:37:55 +0200 Subject: [PATCH 395/693] print: move internal stuff out of public API --- include/shady/print.h | 4 ---- src/shady/print.c | 7 ++++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/shady/print.h b/include/shady/print.h index 069778983..643ec90d0 100644 --- a/include/shady/print.h +++ b/include/shady/print.h @@ -21,9 +21,5 @@ void print_node_into_str(const Node* node, char** str_ptr, size_t* size); void print_module(Printer* printer, Module* mod, PrintConfig config); void print_node(Printer* printer, const Node* node, PrintConfig config); -void print_node_operand(Printer* printer, const Node* node, String op_name, NodeClass op_class, const Node* op, PrintConfig config); -void print_node_operand_list(Printer* printer, const Node* node, String op_name, NodeClass op_class, Nodes ops, PrintConfig config); - -void print_node_generated(Printer* printer, const Node* node, PrintConfig config); #endif \ No newline at end of file diff --git a/src/shady/print.c b/src/shady/print.c index 2f55cde65..bf54fb13c 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -21,11 +21,11 @@ typedef struct PrinterCtx_ PrinterCtx; struct PrinterCtx_ { Printer* printer; + PrintConfig config; const Node* fn; CFG* cfg; const UsesMap* uses; long int min_rpo; - PrintConfig config; }; #define COLOR(x) (ctx->config.color ? (x) : "") @@ -56,6 +56,11 @@ struct PrinterCtx_ { static void print_node_impl(PrinterCtx* ctx, const Node* node); static void print_operand_helper(Printer* p, PrintConfig config, NodeClass nc, const Node* op); +void print_node_operand(Printer* printer, const Node* node, String op_name, NodeClass op_class, const Node* op, PrintConfig config); +void print_node_operand_list(Printer* printer, const Node* node, String op_name, NodeClass op_class, Nodes ops, PrintConfig config); + +void print_node_generated(Printer* printer, const Node* node, PrintConfig config); + #pragma GCC diagnostic error "-Wswitch" static void print_param_list(PrinterCtx* ctx, Nodes params, const Nodes* defaults) { From 752eee1529722c4ed538d09d1d953afbeb270eac Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 11:38:41 +0200 Subject: [PATCH 396/693] print: make config the second parameter instead of the last --- include/shady/print.h | 6 ++-- src/shady/analysis/cfg_dump.c | 4 +-- src/shady/print.c | 66 +++++++++++++++++------------------ 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/include/shady/print.h b/include/shady/print.h index 643ec90d0..72262b19f 100644 --- a/include/shady/print.h +++ b/include/shady/print.h @@ -14,12 +14,12 @@ typedef struct { bool color; bool reparseable; bool in_cfg; -} PrintConfig; +} NodePrintConfig; void print_module_into_str(Module* mod, char** str_ptr, size_t* size); void print_node_into_str(const Node* node, char** str_ptr, size_t* size); -void print_module(Printer* printer, Module* mod, PrintConfig config); -void print_node(Printer* printer, const Node* node, PrintConfig config); +void print_module(Printer* printer, NodePrintConfig config, Module* mod); +void print_node(Printer* printer, NodePrintConfig config, const Node* node); #endif \ No newline at end of file diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 18e69c941..acd8133b4 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -29,12 +29,12 @@ static void print_node_helper(Printer* p, const Node* n) { Growy* tmp_g = new_growy(); Printer* tmp_p = open_growy_as_printer(tmp_g); - PrintConfig config = { + NodePrintConfig config = { .color = false, .in_cfg = true, }; - print_node(tmp_p, n, config); + print_node(tmp_p, config, n); String label = printer_growy_unwrap(tmp_p); char* escaped_label = calloc(strlen(label) * 2, 1); diff --git a/src/shady/print.c b/src/shady/print.c index bf54fb13c..9d10299df 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -21,7 +21,7 @@ typedef struct PrinterCtx_ PrinterCtx; struct PrinterCtx_ { Printer* printer; - PrintConfig config; + NodePrintConfig config; const Node* fn; CFG* cfg; const UsesMap* uses; @@ -54,12 +54,12 @@ struct PrinterCtx_ { #define print_operand(nc, n) print_operand_helper(ctx->printer, ctx->config, nc, n) static void print_node_impl(PrinterCtx* ctx, const Node* node); -static void print_operand_helper(Printer* p, PrintConfig config, NodeClass nc, const Node* op); +static void print_operand_helper(Printer* p, NodePrintConfig config, NodeClass nc, const Node* op); -void print_node_operand(Printer* printer, const Node* node, String op_name, NodeClass op_class, const Node* op, PrintConfig config); -void print_node_operand_list(Printer* printer, const Node* node, String op_name, NodeClass op_class, Nodes ops, PrintConfig config); +void print_node_operand(Printer* printer, const Node* node, String op_name, NodeClass op_class, const Node* op, NodePrintConfig config); +void print_node_operand_list(Printer* printer, const Node* node, String op_name, NodeClass op_class, Nodes ops, NodePrintConfig config); -void print_node_generated(Printer* printer, const Node* node, PrintConfig config); +void print_node_generated(Printer* printer, const Node* node, NodePrintConfig config); #pragma GCC diagnostic error "-Wswitch" @@ -1046,7 +1046,7 @@ static void print_mod_impl(PrinterCtx* ctx, Module* mod) { #undef print_node #undef printf -void print_module(Printer* printer, Module* mod, PrintConfig config) { +void print_module(Printer* printer, NodePrintConfig config, Module* mod) { PrinterCtx ctx = { .printer = printer, .config = config, @@ -1055,7 +1055,7 @@ void print_module(Printer* printer, Module* mod, PrintConfig config) { flush(ctx.printer); } -void print_node(Printer* printer, const Node* node, PrintConfig config) { +void print_node(Printer* printer, NodePrintConfig config, const Node* node) { PrinterCtx ctx = { .printer = printer, .config = config, @@ -1069,7 +1069,7 @@ void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { Printer* p = open_growy_as_printer(g); if (node) print(p, "%%%d ", node->id); - print_node(p, node, (PrintConfig) { .reparseable = true }); + print_node(p, (NodePrintConfig) {.reparseable = true}, node); destroy_printer(p); *size = growy_size(g); *str_ptr = growy_deconstruct(g); @@ -1078,7 +1078,7 @@ void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { Growy* g = new_growy(); Printer* p = open_growy_as_printer(g); - print_module(p, mod, (PrintConfig) { .reparseable = true, }); + print_module(p, (NodePrintConfig) {.reparseable = true,}, mod); destroy_printer(p); *size = growy_size(g); *str_ptr = growy_deconstruct(g); @@ -1088,13 +1088,13 @@ void dump_node(const Node* node) { Printer* p = open_file_as_printer(stdout); if (node) print(p, "%%%d ", node->id); - print_node(p, node, (PrintConfig) { .color = true }); + print_node(p, (NodePrintConfig) {.color = true}, node); printf("\n"); } void dump_module(Module* mod) { Printer* p = open_file_as_printer(stdout); - print_module(p, mod, (PrintConfig) { .color = true }); + print_module(p, (NodePrintConfig) {.color = true}, mod); destroy_printer(p); printf("\n"); } @@ -1104,13 +1104,13 @@ void log_node(LogLevel level, const Node* node) { Printer* p = open_file_as_printer(stderr); if (node) print(p, "%%%d = ", node->id); - print_node(p, node, (PrintConfig) { .color = true }); + print_node(p, (NodePrintConfig) {.color = true}, node); destroy_printer(p); } } void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) { - PrintConfig config = { .color = true }; + NodePrintConfig config = { .color = true }; if (compiler_cfg) { config.print_generated = compiler_cfg->logging.print_generated; config.print_builtin = compiler_cfg->logging.print_builtin; @@ -1118,42 +1118,42 @@ void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) } if (level <= get_log_level()) { Printer* p = open_file_as_printer(stderr); - print_module(p, mod, config); + print_module(p, config, mod); destroy_printer(p); } } #define COLOR(x) (config.color ? (x) : "") -static void print_operand_name_helper(Printer* p, PrintConfig config, String name) { +static void print_operand_name_helper(Printer* p, NodePrintConfig config, String name) { print(p, GREY); print(p, "%s", name); print(p, RESET); print(p, ": ", name); } -static void print_operand_helper(Printer* p, PrintConfig config, NodeClass nc, const Node* op) { +static void print_operand_helper(Printer* p, NodePrintConfig config, NodeClass nc, const Node* op) { if (getenv("SHADY_SUPER_VERBOSE_NODE_DEBUG")) { if (op && (is_value(op) || is_instruction(op))) print(p, "%%%d ", op->id); - print_node(p, op, config); + print_node(p, config, op); } else { if (op && is_instruction(op) && op->arena->config.check_types) print(p, "%%%d", op->id); else { - print_node(p, op, config); + print_node(p, config, op); } } } -void print_node_operand(Printer* p, const Node* n, String name, NodeClass op_class, const Node* op, PrintConfig config) { +void print_node_operand(Printer* p, const Node* n, String name, NodeClass op_class, const Node* op, NodePrintConfig config) { print_operand_name_helper(p, config, name); print_operand_helper(p, config, op_class, op); // print(p, " '%s': ", name); // print_node(p, op, config); } -void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass op_class, Nodes ops, PrintConfig config) { +void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass op_class, Nodes ops, NodePrintConfig config) { print_operand_name_helper(p, config, name); print(p, "["); for (size_t i = 0; i < ops.count; i++) { @@ -1164,12 +1164,12 @@ void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass o print(p, "]"); } -void print_node_operand_const_Node_(Printer* p, const Node* n, String name, const Node* op, PrintConfig config) { +void print_node_operand_const_Node_(Printer* p, const Node* n, String name, const Node* op, NodePrintConfig config) { print_operand_name_helper(p, config, name); print_operand_helper(p, config, 0, op); } -void print_node_operand_Nodes_(Printer* p, const Node* n, String name, Nodes* op, PrintConfig config) { +void print_node_operand_Nodes_(Printer* p, const Node* n, String name, Nodes* op, NodePrintConfig config) { if (op) { print_node_operand_list(p, n, name, 0, *op, config); } else { @@ -1178,17 +1178,17 @@ void print_node_operand_Nodes_(Printer* p, const Node* n, String name, Nodes* op } } -void print_node_operand_AddressSpace(Printer* p, const Node* n, String name, AddressSpace as, PrintConfig config) { +void print_node_operand_AddressSpace(Printer* p, const Node* n, String name, AddressSpace as, NodePrintConfig config) { print_operand_name_helper(p, config, name); print(p, "%s", get_address_space_name(as)); } -void print_node_operand_Op(Printer* p, const Node* n, String name, Op op, PrintConfig config) { +void print_node_operand_Op(Printer* p, const Node* n, String name, Op op, NodePrintConfig config) { print_operand_name_helper(p, config, name); print(p, "%s", get_primop_name(op)); } -void print_node_operand_RecordSpecialFlag(Printer* p, const Node* n, String name, RecordSpecialFlag flags, PrintConfig config) { +void print_node_operand_RecordSpecialFlag(Printer* p, const Node* n, String name, RecordSpecialFlag flags, NodePrintConfig config) { print_operand_name_helper(p, config, name); if (flags & MultipleReturn) print(p, "MultipleReturn"); @@ -1196,17 +1196,17 @@ void print_node_operand_RecordSpecialFlag(Printer* p, const Node* n, String name print(p, "DecorateBlock"); } -void print_node_operand_uint32_t(Printer* p, const Node* n, String name, uint32_t i, PrintConfig config) { +void print_node_operand_uint32_t(Printer* p, const Node* n, String name, uint32_t i, NodePrintConfig config) { print_operand_name_helper(p, config, name); print(p, "%u", i); } -void print_node_operand_uint64_t(Printer* p, const Node* n, String name, uint64_t i, PrintConfig config) { +void print_node_operand_uint64_t(Printer* p, const Node* n, String name, uint64_t i, NodePrintConfig config) { print_operand_name_helper(p, config, name); print(p, "%zu", i); } -void print_node_operand_IntSizes(Printer* p, const Node* n, String name, IntSizes s, PrintConfig config) { +void print_node_operand_IntSizes(Printer* p, const Node* n, String name, IntSizes s, NodePrintConfig config) { print_operand_name_helper(p, config, name); switch (s) { case IntTy8: print(p, "8"); break; @@ -1216,7 +1216,7 @@ void print_node_operand_IntSizes(Printer* p, const Node* n, String name, IntSize } } -void print_node_operand_FloatSizes(Printer* p, const Node* n, String name, FloatSizes s, PrintConfig config) { +void print_node_operand_FloatSizes(Printer* p, const Node* n, String name, FloatSizes s, NodePrintConfig config) { print_operand_name_helper(p, config, name); switch (s) { case FloatTy16: print(p, "16"); break; @@ -1225,12 +1225,12 @@ void print_node_operand_FloatSizes(Printer* p, const Node* n, String name, Float } } -void print_node_operand_String(Printer* p, const Node* n, String name, String s, PrintConfig config) { +void print_node_operand_String(Printer* p, const Node* n, String name, String s, NodePrintConfig config) { print_operand_name_helper(p, config, name); print(p, "\"%s\"", s); } -void print_node_operand_Strings(Printer* p, const Node* n, String name, Strings ops, PrintConfig config) { +void print_node_operand_Strings(Printer* p, const Node* n, String name, Strings ops, NodePrintConfig config) { print_operand_name_helper(p, config, name); print(p, "["); for (size_t i = 0; i < ops.count; i++) { @@ -1241,7 +1241,7 @@ void print_node_operand_Strings(Printer* p, const Node* n, String name, Strings print(p, "]"); } -void print_node_operand_bool(Printer* p, const Node* n, String name, bool b, PrintConfig config) { +void print_node_operand_bool(Printer* p, const Node* n, String name, bool b, NodePrintConfig config) { print_operand_name_helper(p, config, name); if (b) print(p, "true"); @@ -1249,7 +1249,7 @@ void print_node_operand_bool(Printer* p, const Node* n, String name, bool b, Pri print(p, "false"); } -void print_node_operand_unsigned(Printer* p, const Node* n, String name, unsigned u, PrintConfig config) { +void print_node_operand_unsigned(Printer* p, const Node* n, String name, unsigned u, NodePrintConfig config) { print_operand_name_helper(p, config, name); print(p, "%u", u); } From 4be0c2b4ae6aaed45d0f8cbeb88b856143aa130b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 11:59:56 +0200 Subject: [PATCH 397/693] print: use PrintCtx in the geneated stuff too! --- src/shady/generator_print.c | 20 +-- src/shady/print.c | 326 ++++++++++++++++++------------------ 2 files changed, 173 insertions(+), 173 deletions(-) diff --git a/src/shady/generator_print.c b/src/shady/generator_print.c index 0d3bb60e4..2bf9bd8a1 100644 --- a/src/shady/generator_print.c +++ b/src/shady/generator_print.c @@ -2,7 +2,7 @@ void generate_node_print_fns(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); - growy_append_formatted(g, "void print_node_generated(Printer* printer, const Node* node, PrintConfig config) {\n"); + growy_append_formatted(g, "void print_node_generated(PrinterCtx* ctx, const Node* node) {\n"); growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { @@ -15,10 +15,10 @@ void generate_node_print_fns(Growy* g, json_object* src) { alloc = (void*) snake_name; } growy_append_formatted(g, "\tcase %s_TAG: {\n", name); - growy_append_formatted(g, "\t\tprint(printer, GREEN);\n"); - growy_append_formatted(g, "\t\tprint(printer, \"%s\");\n", name); - growy_append_formatted(g, "\t\tprint(printer, RESET);\n"); - growy_append_formatted(g, "\t\tprint(printer, \"(\");\n"); + growy_append_formatted(g, "\t\tprint(ctx->printer, GREEN);\n"); + growy_append_formatted(g, "\t\tprint(ctx->printer, \"%s\");\n", name); + growy_append_formatted(g, "\t\tprint(ctx->printer, RESET);\n"); + growy_append_formatted(g, "\t\tprint(ctx->printer, \"(\");\n"); json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); @@ -35,7 +35,7 @@ void generate_node_print_fns(Growy* g, json_object* src) { String cap_class = capitalize(op_class); if (is_list) { growy_append_formatted(g, "\t\t{\n"); - growy_append_formatted(g, "\t\t\tprint_node_operand_list(printer, node, \"%s\", Nc%s, node->payload.%s.%s, config);\n", op_name, cap_class, snake_name, op_name); + growy_append_formatted(g, "\t\t\tprint_node_operand_list(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); // growy_append_formatted(g, "\t\t\tsize_t count = node->payload.%s.%s.count;\n", snake_name, op_name); // growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < count; i++) {\n"); // growy_append_formatted(g, "\t\t\t\tprint_node_operand(printer, node, \"%s\", Nc%s, i, node->payload.%s.%s.nodes[i], config);\n", op_name, cap_class, snake_name, op_name); @@ -43,7 +43,7 @@ void generate_node_print_fns(Growy* g, json_object* src) { growy_append_formatted(g, "\t\t}\n"); } else { growy_append_formatted(g, "\t\t{\n"); - growy_append_formatted(g, "\t\t\tprint_node_operand(printer, node, \"%s\", Nc%s, node->payload.%s.%s, config);\n", op_name, cap_class, snake_name, op_name); + growy_append_formatted(g, "\t\t\tprint_node_operand(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); growy_append_formatted(g, "\t\t}\n"); } free((void*) cap_class); @@ -61,15 +61,15 @@ void generate_node_print_fns(Growy* g, json_object* src) { if (!isalnum(s[k])) s[k] = '_'; } - growy_append_formatted(g, "\t\tprint_node_operand_%s(printer, node, \"%s\", node->payload.%s.%s, config);\n", s, op_name, snake_name, op_name); + growy_append_formatted(g, "\t\tprint_node_operand_%s(ctx, node, \"%s\", node->payload.%s.%s);\n", s, op_name, snake_name, op_name); free(s); } if (j + 1 < json_object_array_length(ops)) - growy_append_formatted(g, "\t\tprint(printer, \", \");\n"); + growy_append_formatted(g, "\t\tprint(ctx->printer, \", \");\n"); } } - growy_append_formatted(g, "\t\tprint(printer, \")\");\n"); + growy_append_formatted(g, "\t\tprint(ctx->printer, \")\");\n"); growy_append_formatted(g, "\t\tbreak;\n"); growy_append_formatted(g, "\t}\n", name); if (alloc) diff --git a/src/shady/print.c b/src/shady/print.c index 9d10299df..f34a8ac9e 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -28,6 +28,86 @@ struct PrinterCtx_ { long int min_rpo; }; +static void print_node_impl(PrinterCtx* ctx, const Node* node); +static void print_mod_impl(PrinterCtx* ctx, Module* mod); + +void print_module(Printer* printer, NodePrintConfig config, Module* mod) { + PrinterCtx ctx = { + .printer = printer, + .config = config, + }; + print_mod_impl(&ctx, mod); + flush(ctx.printer); +} + +void print_node(Printer* printer, NodePrintConfig config, const Node* node) { + PrinterCtx ctx = { + .printer = printer, + .config = config, + }; + print_node_impl(&ctx, node); + flush(ctx.printer); +} + +void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { + Growy* g = new_growy(); + Printer* p = open_growy_as_printer(g); + if (node) + print(p, "%%%d ", node->id); + print_node(p, (NodePrintConfig) {.reparseable = true}, node); + destroy_printer(p); + *size = growy_size(g); + *str_ptr = growy_deconstruct(g); +} + +void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { + Growy* g = new_growy(); + Printer* p = open_growy_as_printer(g); + print_module(p, (NodePrintConfig) {.reparseable = true,}, mod); + destroy_printer(p); + *size = growy_size(g); + *str_ptr = growy_deconstruct(g); +} + +void dump_node(const Node* node) { + Printer* p = open_file_as_printer(stdout); + if (node) + print(p, "%%%d ", node->id); + print_node(p, (NodePrintConfig) {.color = true}, node); + printf("\n"); +} + +void dump_module(Module* mod) { + Printer* p = open_file_as_printer(stdout); + print_module(p, (NodePrintConfig) {.color = true}, mod); + destroy_printer(p); + printf("\n"); +} + +void log_node(LogLevel level, const Node* node) { + if (level <= get_log_level()) { + Printer* p = open_file_as_printer(stderr); + if (node) + print(p, "%%%d = ", node->id); + print_node(p, (NodePrintConfig) {.color = true}, node); + destroy_printer(p); + } +} + +void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) { + NodePrintConfig config = { .color = true }; + if (compiler_cfg) { + config.print_generated = compiler_cfg->logging.print_generated; + config.print_builtin = compiler_cfg->logging.print_builtin; + config.print_internal = compiler_cfg->logging.print_internal; + } + if (level <= get_log_level()) { + Printer* p = open_file_as_printer(stderr); + print_module(p, config, mod); + destroy_printer(p); + } +} + #define COLOR(x) (ctx->config.color ? (x) : "") #define RESET COLOR("\033[0m") @@ -49,17 +129,16 @@ struct PrinterCtx_ { #define BWHITE COLOR("\033[0;97m") #define printf(...) print(ctx->printer, __VA_ARGS__) -#define print_node2(n) print_node_impl(ctx, n) -#define print_node(n) print_operand_helper(ctx->printer, ctx->config, 0, n) -#define print_operand(nc, n) print_operand_helper(ctx->printer, ctx->config, nc, n) +#define print_node(n) print_operand_helper(ctx, 0, n) +#define print_operand(nc, n) print_operand_helper(ctx, nc, n) static void print_node_impl(PrinterCtx* ctx, const Node* node); -static void print_operand_helper(Printer* p, NodePrintConfig config, NodeClass nc, const Node* op); +static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op); -void print_node_operand(Printer* printer, const Node* node, String op_name, NodeClass op_class, const Node* op, NodePrintConfig config); -void print_node_operand_list(Printer* printer, const Node* node, String op_name, NodeClass op_class, Nodes ops, NodePrintConfig config); +void print_node_operand(PrinterCtx* ctx, const Node* node, String op_name, NodeClass op_class, const Node* op); +void print_node_operand_list(PrinterCtx* ctx, const Node* node, String op_name, NodeClass op_class, Nodes ops); -void print_node_generated(Printer* printer, const Node* node, NodePrintConfig config); +void print_node_generated(PrinterCtx* ctx, const Node* node); #pragma GCC diagnostic error "-Wswitch" @@ -169,7 +248,7 @@ static void print_abs_body(PrinterCtx* ctx, const Node* block) { assert(!ctx->fn || is_function(ctx->fn)); assert(is_abstraction(block)); - print_node2(get_abstraction_body(block)); + print_node(get_abstraction_body(block)); // TODO: it's likely cleaner to instead print things according to the dominator tree in the first place. if (ctx->cfg != NULL) { @@ -379,7 +458,7 @@ static void print_type(PrinterCtx* ctx, const Node* node) { break; } default: - print_node_generated(ctx->printer, node, ctx->config); + print_node_generated(ctx, node); break; } printf(RESET); @@ -539,7 +618,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { printf(RESET); break; default: - print_node_generated(ctx->printer, node, ctx->config); + print_node_generated(ctx, node); break; } } @@ -577,7 +656,7 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { print_case_body(ctx, node->payload.block.inside); break; } - default: print_node_generated(ctx->printer, node, ctx->config); + default: print_node_generated(ctx, node); } } @@ -668,7 +747,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { print_node_impl(ctx, instruction); if (!ctx->config.in_cfg) { printf(";\n"); - print_node2(node->payload.let.in); + print_node(node->payload.let.in); } } else { printf(GREEN); @@ -679,7 +758,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(GREEN); printf(" in "); printf(RESET); - print_node2(node->payload.let.in); + print_node(node->payload.let.in); printf(";"); } break; @@ -983,7 +1062,7 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { printf("`%s`", node->payload.unbound.name); printf(RESET); } else if (node->tag == UnboundBBs_TAG) { - print_node2(node->payload.unbound_bbs.body); + print_node(node->payload.unbound_bbs.body); for (size_t i = 0; i < node->payload.unbound_bbs.children_blocks.count; i++) print_basic_block(ctx, node->payload.unbound_bbs.children_blocks.nodes[i]); } else switch (node->tag) { @@ -1030,7 +1109,7 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { break; } default: - print_node_generated(ctx->printer, node, ctx->config); + print_node_generated(ctx, node); break; } } @@ -1046,212 +1125,133 @@ static void print_mod_impl(PrinterCtx* ctx, Module* mod) { #undef print_node #undef printf -void print_module(Printer* printer, NodePrintConfig config, Module* mod) { - PrinterCtx ctx = { - .printer = printer, - .config = config, - }; - print_mod_impl(&ctx, mod); - flush(ctx.printer); -} - -void print_node(Printer* printer, NodePrintConfig config, const Node* node) { - PrinterCtx ctx = { - .printer = printer, - .config = config, - }; - print_node_impl(&ctx, node); - flush(ctx.printer); -} - -void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { - Growy* g = new_growy(); - Printer* p = open_growy_as_printer(g); - if (node) - print(p, "%%%d ", node->id); - print_node(p, (NodePrintConfig) {.reparseable = true}, node); - destroy_printer(p); - *size = growy_size(g); - *str_ptr = growy_deconstruct(g); -} - -void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { - Growy* g = new_growy(); - Printer* p = open_growy_as_printer(g); - print_module(p, (NodePrintConfig) {.reparseable = true,}, mod); - destroy_printer(p); - *size = growy_size(g); - *str_ptr = growy_deconstruct(g); -} - -void dump_node(const Node* node) { - Printer* p = open_file_as_printer(stdout); - if (node) - print(p, "%%%d ", node->id); - print_node(p, (NodePrintConfig) {.color = true}, node); - printf("\n"); -} - -void dump_module(Module* mod) { - Printer* p = open_file_as_printer(stdout); - print_module(p, (NodePrintConfig) {.color = true}, mod); - destroy_printer(p); - printf("\n"); -} - -void log_node(LogLevel level, const Node* node) { - if (level <= get_log_level()) { - Printer* p = open_file_as_printer(stderr); - if (node) - print(p, "%%%d = ", node->id); - print_node(p, (NodePrintConfig) {.color = true}, node); - destroy_printer(p); - } -} - -void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) { - NodePrintConfig config = { .color = true }; - if (compiler_cfg) { - config.print_generated = compiler_cfg->logging.print_generated; - config.print_builtin = compiler_cfg->logging.print_builtin; - config.print_internal = compiler_cfg->logging.print_internal; - } - if (level <= get_log_level()) { - Printer* p = open_file_as_printer(stderr); - print_module(p, config, mod); - destroy_printer(p); - } -} - -#define COLOR(x) (config.color ? (x) : "") - -static void print_operand_name_helper(Printer* p, NodePrintConfig config, String name) { - print(p, GREY); - print(p, "%s", name); - print(p, RESET); - print(p, ": ", name); +static void print_operand_name_helper(PrinterCtx* ctx, String name) { + print(ctx->printer, GREY); + print(ctx->printer, "%s", name); + print(ctx->printer, RESET); + print(ctx->printer, ": ", name); } -static void print_operand_helper(Printer* p, NodePrintConfig config, NodeClass nc, const Node* op) { +static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op) { if (getenv("SHADY_SUPER_VERBOSE_NODE_DEBUG")) { if (op && (is_value(op) || is_instruction(op))) - print(p, "%%%d ", op->id); - print_node(p, config, op); + print(ctx->printer, "%%%d ", op->id); + print_node_impl(ctx, op); } else { if (op && is_instruction(op) && op->arena->config.check_types) - print(p, "%%%d", op->id); + print(ctx->printer, "%%%d", op->id); else { - print_node(p, config, op); + print_node_impl(ctx, op); } } } -void print_node_operand(Printer* p, const Node* n, String name, NodeClass op_class, const Node* op, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print_operand_helper(p, config, op_class, op); +void print_node_operand(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, const Node* op) { + print_operand_name_helper(ctx, name); + print_operand_helper(ctx, op_class, op); // print(p, " '%s': ", name); // print_node(p, op, config); } -void print_node_operand_list(Printer* p, const Node* n, String name, NodeClass op_class, Nodes ops, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print(p, "["); +void print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, Nodes ops) { + print_operand_name_helper(ctx, name); + print(ctx->printer, "["); for (size_t i = 0; i < ops.count; i++) { - print_operand_helper(p, config, op_class, ops.nodes[i]); + print_operand_helper(ctx, op_class, ops.nodes[i]); if (i + 1 < ops.count) - print(p, ", "); + print(ctx->printer, ", "); } - print(p, "]"); + print(ctx->printer, "]"); } -void print_node_operand_const_Node_(Printer* p, const Node* n, String name, const Node* op, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print_operand_helper(p, config, 0, op); +void print_node_operand_const_Node_(PrinterCtx* ctx, const Node* n, String name, const Node* op) { + print_operand_name_helper(ctx, name); + print_operand_helper(ctx, 0, op); } -void print_node_operand_Nodes_(Printer* p, const Node* n, String name, Nodes* op, NodePrintConfig config) { +void print_node_operand_Nodes_(PrinterCtx* ctx, const Node* n, String name, Nodes* op) { if (op) { - print_node_operand_list(p, n, name, 0, *op, config); + print_node_operand_list(ctx, n, name, 0, *op); } else { - print_operand_name_helper(p, config, name); - print(p, "null"); + print_operand_name_helper(ctx, name); + print(ctx->printer, "null"); } } -void print_node_operand_AddressSpace(Printer* p, const Node* n, String name, AddressSpace as, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print(p, "%s", get_address_space_name(as)); +void print_node_operand_AddressSpace(PrinterCtx* ctx, const Node* n, String name, AddressSpace as) { + print_operand_name_helper(ctx, name); + print(ctx->printer, "%s", get_address_space_name(as)); } -void print_node_operand_Op(Printer* p, const Node* n, String name, Op op, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print(p, "%s", get_primop_name(op)); +void print_node_operand_Op(PrinterCtx* ctx, const Node* n, String name, Op op) { + print_operand_name_helper(ctx, name); + print(ctx->printer, "%s", get_primop_name(op)); } -void print_node_operand_RecordSpecialFlag(Printer* p, const Node* n, String name, RecordSpecialFlag flags, NodePrintConfig config) { - print_operand_name_helper(p, config, name); +void print_node_operand_RecordSpecialFlag(PrinterCtx* ctx, const Node* n, String name, RecordSpecialFlag flags) { + print_operand_name_helper(ctx, name); if (flags & MultipleReturn) - print(p, "MultipleReturn"); + print(ctx->printer, "MultipleReturn"); if (flags & DecorateBlock) - print(p, "DecorateBlock"); + print(ctx->printer, "DecorateBlock"); } -void print_node_operand_uint32_t(Printer* p, const Node* n, String name, uint32_t i, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print(p, "%u", i); +void print_node_operand_uint32_t(PrinterCtx* ctx, const Node* n, String name, uint32_t i) { + print_operand_name_helper(ctx, name); + print(ctx->printer, "%u", i); } -void print_node_operand_uint64_t(Printer* p, const Node* n, String name, uint64_t i, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print(p, "%zu", i); +void print_node_operand_uint64_t(PrinterCtx* ctx, const Node* n, String name, uint64_t i) { + print_operand_name_helper(ctx, name); + print(ctx->printer, "%zu", i); } -void print_node_operand_IntSizes(Printer* p, const Node* n, String name, IntSizes s, NodePrintConfig config) { - print_operand_name_helper(p, config, name); +void print_node_operand_IntSizes(PrinterCtx* ctx, const Node* n, String name, IntSizes s) { + print_operand_name_helper(ctx, name); switch (s) { - case IntTy8: print(p, "8"); break; - case IntTy16: print(p, "16"); break; - case IntTy32: print(p, "32"); break; - case IntTy64: print(p, "64"); break; + case IntTy8: print(ctx->printer, "8"); break; + case IntTy16: print(ctx->printer, "16"); break; + case IntTy32: print(ctx->printer, "32"); break; + case IntTy64: print(ctx->printer, "64"); break; } } -void print_node_operand_FloatSizes(Printer* p, const Node* n, String name, FloatSizes s, NodePrintConfig config) { - print_operand_name_helper(p, config, name); +void print_node_operand_FloatSizes(PrinterCtx* ctx, const Node* n, String name, FloatSizes s) { + print_operand_name_helper(ctx, name); switch (s) { - case FloatTy16: print(p, "16"); break; - case FloatTy32: print(p, "32"); break; - case FloatTy64: print(p, "64"); break; + case FloatTy16: print(ctx->printer, "16"); break; + case FloatTy32: print(ctx->printer, "32"); break; + case FloatTy64: print(ctx->printer, "64"); break; } } -void print_node_operand_String(Printer* p, const Node* n, String name, String s, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print(p, "\"%s\"", s); +void print_node_operand_String(PrinterCtx* ctx, const Node* n, String name, String s ){ + print_operand_name_helper(ctx, name); + print(ctx->printer, "\"%s\"", s); } -void print_node_operand_Strings(Printer* p, const Node* n, String name, Strings ops, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print(p, "["); +void print_node_operand_Strings(PrinterCtx* ctx, const Node* n, String name, Strings ops) { + print_operand_name_helper(ctx, name); + print(ctx->printer, "["); for (size_t i = 0; i < ops.count; i++) { - print(p, "\"%s\"", (size_t) ops.strings[i]); + print(ctx->printer, "\"%s\"", (size_t) ops.strings[i]); if (i + 1 < ops.count) - print(p, ", "); + print(ctx->printer, ", "); } - print(p, "]"); + print(ctx->printer, "]"); } -void print_node_operand_bool(Printer* p, const Node* n, String name, bool b, NodePrintConfig config) { - print_operand_name_helper(p, config, name); +void print_node_operand_bool(PrinterCtx* ctx, const Node* n, String name, bool b) { + print_operand_name_helper(ctx, name); if (b) - print(p, "true"); + print(ctx->printer, "true"); else - print(p, "false"); + print(ctx->printer, "false"); } -void print_node_operand_unsigned(Printer* p, const Node* n, String name, unsigned u, NodePrintConfig config) { - print_operand_name_helper(p, config, name); - print(p, "%u", u); +void print_node_operand_unsigned(PrinterCtx* ctx, const Node* n, String name, unsigned u) { + print_operand_name_helper(ctx, name); + print(ctx->printer, "%u", u); } #include "print_generated.c" From b5ca6a2e674ec68b4e6f8b0b3afce84736c5c2ef Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 12:12:02 +0200 Subject: [PATCH 398/693] added compound instructions --- include/shady/grammar.json | 9 ++++++++ src/backend/c/emit_c_instructions.c | 25 +++++++++++++++++++++++ src/backend/spirv/emit_spv_instructions.c | 17 +++++++++++++++ src/shady/type.c | 4 ++++ 4 files changed, 55 insertions(+) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 41902bfd5..d8388daa3 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -427,6 +427,15 @@ { "name": "inside", "class": "case" } ] }, + { + "name": "CompoundInstruction", + "class": ["instruction", "value"], + "description": "Used as a helper to insert multiple instructions in place of one", + "ops": [ + { "name": "instructions", "class": "instruction", "list": true }, + { "name": "results", "class": "value", "list": "true" } + ] + }, { "name": "Comment", "class": "instruction", diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index e4d4c2cb6..d4a56c61a 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -722,6 +722,31 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_BindIdentifiers_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; + case Instruction_CompoundInstruction_TAG: { + Nodes instructions = instruction->payload.compound_instruction.instructions; + for (size_t i = 0; i < instructions.count; i++) { + const Node* instruction2 = instructions.nodes[i]; + + // we declare N local variables in order to store the result of the instruction + Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, instruction2->type); + + LARRAY(CTerm, results, yield_types.count); + LARRAY(InstrResultBinding, bindings, yield_types.count); + InstructionOutputs ioutputs = { + .count = yield_types.count, + .results = results, + .binding = bindings, + }; + + emit_instruction(emitter, p, instruction2, ioutputs); + } + Nodes results2 = instruction->payload.compound_instruction.results; + for (size_t i = 0; i < results2.count; i++) { + outputs.results[0] = emit_value(emitter, p, results2.nodes[i]); + outputs.binding[0] = NoBinding; + } + return; + } case Instruction_Block_TAG: error("Should be eliminated by the compiler") case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; case Instruction_StackAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.stack_alloc.type, outputs); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index e2552fe7e..7aef906f1 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -393,6 +393,23 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; case PrimOp_TAG: emit_primop(emitter, fn_builder, *bb_builder, instruction, results_count, results); break; case Comment_TAG: break; + case Instruction_CompoundInstruction_TAG: { + Nodes instructions = instruction->payload.compound_instruction.instructions; + for (size_t i = 0; i < instructions.count; i++) { + const Node* instruction2 = instructions.nodes[i]; + + // we declare N local variables in order to store the result of the instruction + Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, instruction2->type); + + LARRAY(SpvId, results2, yield_types.count); + emit_instruction(emitter, fn_builder, bb_builder, merge_targets, instruction2, yield_types.count, results2); + } + Nodes results2 = instruction->payload.compound_instruction.results; + for (size_t i = 0; i < results2.count; i++) { + results[0] = emit_value(emitter, *bb_builder, results2.nodes[i]); + } + return; + } case Instruction_LocalAlloc_TAG: { SpvId result = spvb_local_variable(fn_builder, emit_type(emitter, ptr_type(emitter->arena, (PtrType) { .address_space = AsFunction, diff --git a/src/shady/type.c b/src/shady/type.c index 5fbbb4ee6..ab805a8a9 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1185,6 +1185,10 @@ const Type* check_type_let(IrArena* arena, Let let) { return noret_type(arena); } +const Type* check_type_compound_instruction(IrArena* arena, CompoundInstruction payload) { + return wrap_multiple_yield_types(arena, get_values_types(arena, payload.results)); +} + const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { Nodes args = tail_call.args; for (size_t i = 0; i < args.count; i++) { From ab43398590c4c70921cb392c9a627133a67821d4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 12:55:08 +0200 Subject: [PATCH 399/693] use compound instructions for constants --- include/shady/ir.h | 5 ++++ src/frontend/llvm/l2s_postprocess.c | 2 +- src/frontend/llvm/l2s_value.c | 2 +- src/shady/body_builder.c | 36 ++++++++++++++++++++++++++ src/shady/node.c | 5 ++++ src/shady/passes/eliminate_constants.c | 2 +- src/shady/passes/lower_nullptr.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 4 +-- src/shady/print.c | 15 ++++++++++- 9 files changed, 66 insertions(+), 7 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index b981a1b65..c1e9c4719 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -297,4 +297,9 @@ const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder*, const Node*, const Nodes); const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); +const Node* yield_values_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder*, Nodes, const Nodes); +const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder*, Nodes); +const Node* bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder*, const Node*, const Nodes); +const Node* bind_last_instruction_and_wrap_in_compound_instruction(BodyBuilder*, const Node*); + #endif diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 5978a6118..f95198dcc 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -102,7 +102,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, BodyBuilder* bb = begin_body(a); const Node* value = first(bind_instruction(bb, new->payload.constant.instruction)); value = first(bind_instruction(bb, prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)))); - new->payload.constant.instruction = yield_values_and_wrap_in_block(bb, singleton(value)); + new->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(value)); return new; } case PrimOp_TAG: { diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index cc7db227f..49c2beb17 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -85,7 +85,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { insert_dict(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = begin_body(a); EmittedInstr emitted = convert_instruction(p, NULL, NULL, bb, v); - decl->payload.constant.instruction = bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, emitted.instruction, singleton(t)); + decl->payload.constant.instruction = bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(bb, emitted.instruction, singleton(t)); return r; } case LLVMConstantDataArrayValueKind: { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index e97cfe53a..bc52a0602 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -147,6 +147,42 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* return bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type)); } +static Nodes finish_with_instruction_list(BodyBuilder* bb) { + IrArena* a = bb->arena; + size_t count = entries_count_list(bb->stack); + LARRAY(const Node*, list, count); + for (size_t i = 0; i < count; i++) { + StackEntry entry = read_list(StackEntry, bb->stack)[i]; + if (entry.structured.tag != NotAStructured_construct) { + error("When using a BodyBuilder to create compound instructions, control flow is not allowed.") + } + list[i] = entry.structured.payload.let.instruction; + } + + destroy_list(bb->stack); + free(bb); + return nodes(a, count, list); +} + +const Node* yield_values_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder* bb, Nodes values, const Nodes types) { + IrArena* arena = bb->arena; + return compound_instruction(arena, (CompoundInstruction) { .instructions = finish_with_instruction_list(bb), .results = values }); +} + +const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { + return yield_values_and_wrap_in_compound_instruction_explicit_return_types(bb, values, get_values_types(bb->arena, values)); +} + +const Node* bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder* bb, const Node* instruction, const Nodes types) { + IrArena* arena = bb->arena; + Nodes values = bind_instruction_outputs_count(bb, instruction, types.count); + return compound_instruction(arena, (CompoundInstruction) { .instructions = finish_with_instruction_list(bb), .results = values }); +} + +const Node* bind_last_instruction_and_wrap_in_compound_instruction(BodyBuilder* bb, const Node* instruction) { + return bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type)); +} + static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { IrArena* a = bb->arena; diff --git a/src/shady/node.c b/src/shady/node.c index f11e66b5e..5d40b4811 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -189,6 +189,11 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi } return NULL; } + case CompoundInstruction_TAG: { + if (node->payload.compound_instruction.results.count == 1) + return resolve_node_to_definition(first(node->payload.compound_instruction.results), config); + return NULL; + } case Load_TAG: { if (config.enter_loads) { const Node* source = node->payload.load.ptr; diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 139b98c80..26e68ceef 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -33,7 +33,7 @@ static const Node* process(Context* ctx, const Node* node) { case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; if (decl->tag == Constant_TAG && decl->payload.constant.instruction) { - const Node* value = get_quoted_value(decl->payload.constant.instruction); + const Node* value = resolve_node_to_definition(decl->payload.constant.instruction, (NodeResolveConfig) { 0 }); if (value) return rewrite_node(&ctx->rewriter, value); c.rewriter.map = clone_dict(c.rewriter.map); diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 2a7da8b6b..24fd1d7cb 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -24,7 +24,7 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { Node* decl = constant(ctx->rewriter.dst_module, singleton(annotation(a, (Annotation) { .name = "Generated", })), t, format_string_interned(a, "nullptr_%s", name_type_safe(a, t))); - decl->payload.constant.instruction = yield_values_and_wrap_in_block(bb, singleton(nul)); + decl->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(nul)); const Node* ref = ref_decl_helper(a, decl); insert_dict(const Type*, const Node*, ctx->map, t, ref); return ref; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index d371e8998..523a773cb 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -416,7 +416,7 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect BodyBuilder* bb = begin_body(a); const Node* offset = gen_primop_e(bb, offset_of_op, singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), singleton(size_t_literal(a, i))); // const Node* offset_in_words = bytes_to_words(bb, offset); - new_address->payload.constant.instruction = yield_values_and_wrap_in_block(bb, singleton(offset)); + new_address->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(offset)); register_processed(&ctx->rewriter, decl, new_address); } @@ -472,7 +472,7 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { const Node* size_in_words = bytes_to_words(bb, size_of); Node* constant_decl = constant(m, annotations, ptr_size_type, format_string_interned(a, "memory_%s_size", as_name)); - constant_decl->payload.constant.instruction = yield_values_and_wrap_in_block(bb, singleton(size_in_words)); + constant_decl->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(size_in_words)); const Type* words_array_type = arr_type(a, (ArrType) { .element_type = word_type, diff --git a/src/shady/print.c b/src/shady/print.c index f34a8ac9e..2fad1e20c 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -655,6 +655,19 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf(RESET); print_case_body(ctx, node->payload.block.inside); break; + } case CompoundInstruction_TAG: { + printf("{\n"); + indent(ctx->printer); + Nodes instructions = node->payload.compound_instruction.instructions; + for (size_t i = 0; i < instructions.count; i++) { + print_instruction(ctx, instructions.nodes[i]); + printf(";\n"); + } + printf("}\n"); + deindent(ctx->printer); + printf("yields "); + print_args_list(ctx, node->payload.compound_instruction.results); + break; } default: print_node_generated(ctx, node); } @@ -990,7 +1003,7 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { if (get_quoted_value(cnst->instruction)) print_node(get_quoted_value(cnst->instruction)); else - print_node(cnst->instruction); + print_node_impl(ctx, cnst->instruction); } printf(";\n"); break; From f83bf8c18903e70ad41e79eb6a15d498c9577505 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 14:35:35 +0200 Subject: [PATCH 400/693] removed quote_op --- include/shady/grammar.json | 1 + include/shady/ir.h | 6 +-- include/shady/primops.json | 3 -- src/backend/c/emit_c.c | 2 +- src/backend/c/emit_c_instructions.c | 8 --- src/backend/spirv/emit_spv.c | 2 +- src/frontend/llvm/l2s.c | 2 +- src/frontend/slim/parser.c | 8 +-- src/shady/body_builder.c | 24 ++++----- src/shady/constructors.c | 52 ++++++++++++++----- src/shady/fold.c | 8 +-- src/shady/node.c | 10 ---- src/shady/passes/bind.c | 3 +- src/shady/passes/cleanup.c | 12 +---- src/shady/passes/lower_logical_pointers.c | 2 +- src/shady/passes/lower_mask.c | 2 +- src/shady/passes/lower_memory_layout.c | 6 +-- src/shady/passes/normalize.c | 2 +- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_restructure.c | 4 +- src/shady/passes/opt_stack.c | 4 +- src/shady/passes/simt2d.c | 1 - src/shady/passes/specialize_entry_point.c | 4 +- src/shady/passes/specialize_execution_model.c | 2 +- src/shady/print.c | 5 +- src/shady/rewrite.c | 3 ++ src/shady/transform/internal_constants.c | 2 +- src/shady/type.c | 6 +-- 28 files changed, 88 insertions(+), 98 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index d8388daa3..2adfd1659 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -431,6 +431,7 @@ "name": "CompoundInstruction", "class": ["instruction", "value"], "description": "Used as a helper to insert multiple instructions in place of one", + "constructor": "custom", "ops": [ { "name": "instructions", "class": "instruction", "list": true }, { "name": "results", "class": "value", "list": "true" } diff --git a/include/shady/ir.h b/include/shady/ir.h index c1e9c4719..08aa97312 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -156,7 +156,6 @@ String get_value_name_safe(const Node*); String get_value_name_unsafe(const Node*); void set_value_name(const Node* var, String name); -const Node* get_quoted_value(const Node* instruction); const IntLiteral* resolve_to_int_literal(const Node* node); int64_t get_int_literal_value(IntLiteral, bool sign_extend); const FloatLiteral* resolve_to_float_literal(const Node* node); @@ -189,6 +188,7 @@ void set_abstraction_body (Node* abs, const Node* body); const Node* get_let_instruction(const Node* let); const Node* get_let_chain_end(const Node* terminator); +const Node* maybe_tuple_helper(IrArena* a, Nodes values); const Node* extract_helper(const Node* composite, const Node* index); const Node* extract_multiple_ret_types_helper(const Node* composite, int index); @@ -253,10 +253,8 @@ const Node* string_lit_helper(IrArena* a, String s); const Node* annotation_value_helper(IrArena* a, String n, const Node* v); // instructions -/// Turns a value into an 'instruction' (the enclosing let will be folded away later) -/// Useful for local rewrites -const Node* quote_helper(IrArena*, Nodes values); const Node* prim_op_helper(IrArena*, Op, Nodes, Nodes); +const Node* compound_instruction(IrArena* arena, Nodes instructions, Nodes results); // terminators const Node* let(IrArena*, const Node* instruction, const Node* tail); diff --git a/include/shady/primops.json b/include/shady/primops.json index 81c6f0975..c33156b91 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -236,9 +236,6 @@ "class": "ast", "side-effects": true }, - { - "name": "quote" - }, { "name": "select" }, diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index cbeba4fab..5c91b8366 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -777,7 +777,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { emit_as = term_from_cvalue(name); register_emitted(emitter, decl, emit_as); - const Node* init_value = get_quoted_value(decl->payload.constant.instruction); + const Node* init_value = resolve_node_to_definition(decl->payload.constant.instruction, (NodeResolveConfig) { 0 }); assert(init_value && "TODO: support some measure of constant expressions"); String init = to_cvalue(emitter, emit_value(emitter, NULL, init_value)); emit_global_variable_definition(emitter, AsGlobal, decl_center, decl->type, true, init); diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index d4a56c61a..618bddf49 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -243,14 +243,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case deref_op: case assign_op: case subscript_op: assert(false); - case quote_op: { - assert(outputs.count == 1); - for (size_t i = 0; i < prim_op->operands.count; i++) { - outputs.results[i] = emit_value(emitter, p, prim_op->operands.nodes[i]); - outputs.binding[i] = NoBinding; - } - break; - } case add_carry_op: case sub_borrow_op: case mul_extended_op: diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 74a429f13..ff0bf4054 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -127,7 +127,7 @@ SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { break; } case Constant_TAG: { - const Node* init_value = get_quoted_value(decl->payload.constant.instruction); + const Node* init_value = resolve_node_to_definition(decl->payload.constant.instruction, (NodeResolveConfig) { 0 }); if (!init_value && bb_builder) { SpvId r; emit_instruction(emitter, NULL, &bb_builder, NULL, decl->payload.constant.instruction, 1, &r); diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 008ccca3b..a8138341c 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -225,7 +225,7 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { if (UNTYPED_POINTERS) { Node* untyped_wrapper = constant(p->dst, singleton(annotation(a, (Annotation) { .name = "Inline" })), ptr_t, format_string_interned(a, "%s_untyped", name)); - untyped_wrapper->payload.constant.instruction = quote_helper(a, singleton(ref_decl_helper(a, decl))); + untyped_wrapper->payload.constant.instruction = ref_decl_helper(a, decl); untyped_wrapper->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(ptr_t), singleton(ref_decl_helper(a, decl))); decl = untyped_wrapper; } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index be347ec2c..37b629c71 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -187,7 +187,7 @@ static const Node* accept_value(ctxparams) { case lpar_tok: { next_token(tokenizer); if (accept_token(ctx, rpar_tok)) { - return quote_helper(arena, empty(arena)); + return tuple_helper(arena, empty(arena)); } const Node* atom = config.front_end ? accept_expr(ctx, max_precedence()) : accept_value(ctx); expect(atom); @@ -607,7 +607,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { if (has_else) { if_false = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, merge)); } - return quote_helper(arena, gen_if(bb, yield_types, condition, if_true, if_false)); + return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, if_true, if_false)); } case loop_tok: { next_token(tokenizer); @@ -618,7 +618,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { // by default loops continue forever const Node* default_loop_end_behaviour = config.front_end ? merge_continue(arena, (MergeContinue) { .args = nodes(arena, 0, NULL) }) : NULL; const Node* body = case_(arena, parameters, expect_body(ctx, default_loop_end_behaviour)); - return quote_helper(arena, gen_loop(bb, yield_types, initial_arguments, body)); + return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, body)); } case control_tok: { next_token(tokenizer); @@ -631,7 +631,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { }), str); expect(accept_token(ctx, rpar_tok)); const Node* body = case_(arena, singleton(jp), expect_body(ctx, NULL)); - return quote_helper(arena, gen_control(bb, yield_types, body)); + return maybe_tuple_helper(arena, gen_control(bb, yield_types, body)); } default: break; } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index bc52a0602..49a86f56a 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -33,17 +33,17 @@ BodyBuilder* begin_body(IrArena* a) { static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { if (bb->arena->config.check_types) { - assert(is_instruction(instruction)); + assert(is_instruction(instruction) || is_value(instruction)); + } + if (is_instruction(instruction)) { + StackEntry entry = { + .vars = empty(bb->arena), + .structured.payload.let = { + .instruction = instruction, + } + }; + append_list(StackEntry, bb->stack, entry); } - if (bb->arena->config.allow_fold && instruction->tag == PrimOp_TAG && instruction->payload.prim_op.op == quote_op) - return instruction->payload.prim_op.operands; - StackEntry entry = { - .vars = empty(bb->arena), - .structured.payload.let = { - .instruction = instruction, - } - }; - append_list(StackEntry, bb->stack, entry); if (outputs_count > 1) { LARRAY(const Node*, extracted, outputs_count); for (size_t i = 0; i < outputs_count; i++) @@ -166,7 +166,7 @@ static Nodes finish_with_instruction_list(BodyBuilder* bb) { const Node* yield_values_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder* bb, Nodes values, const Nodes types) { IrArena* arena = bb->arena; - return compound_instruction(arena, (CompoundInstruction) { .instructions = finish_with_instruction_list(bb), .results = values }); + return compound_instruction(arena, finish_with_instruction_list(bb), values); } const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { @@ -176,7 +176,7 @@ const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes const Node* bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder* bb, const Node* instruction, const Nodes types) { IrArena* arena = bb->arena; Nodes values = bind_instruction_outputs_count(bb, instruction, types.count); - return compound_instruction(arena, (CompoundInstruction) { .instructions = finish_with_instruction_list(bb), .results = values }); + return compound_instruction(arena, finish_with_instruction_list(bb), values); } const Node* bind_last_instruction_and_wrap_in_compound_instruction(BodyBuilder* bb, const Node* instruction) { diff --git a/src/shady/constructors.c b/src/shady/constructors.c index d5f2aeabc..a503ff6d0 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -75,6 +75,10 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { #include "constructors_generated.c" const Node* let(IrArena* arena, const Node* instruction, const Node* in) { + // This is like a folding opt, but earlier, simplifies things by allowing to rewrite an instruction into a value + if (!is_instruction(instruction) && is_value(instruction)) + return in; + Let payload = { .instruction = instruction, .in = in, @@ -91,6 +95,32 @@ const Node* let(IrArena* arena, const Node* instruction, const Node* in) { return create_node_helper(arena, node, NULL); } +const Node* compound_instruction(IrArena* arena, Nodes instructions, Nodes results) { + LARRAY(const Node*, ninstructions, instructions.count); + size_t count = 0; + for (size_t i = 0; i < instructions.count; i++) { + const Node* instr = instructions.nodes[i]; + if (is_instruction(instr)) + ninstructions[count++] = instr; + } + instructions = nodes(arena, count, ninstructions); + + CompoundInstruction payload = { + .instructions = instructions, + .results = results, + }; + + Node node; + memset((void*) &node, 0, sizeof(Node)); + node = (Node) { + .arena = arena, + .type = arena->config.check_types ? check_type_compound_instruction(arena, payload) : NULL, + .tag = CompoundInstruction_TAG, + .payload.compound_instruction = payload + }; + return create_node_helper(arena, node, NULL); +} + Node* param(IrArena* arena, const Type* type, const char* name) { Param param = { .type = type, @@ -323,17 +353,6 @@ Type* nominal_type(Module* mod, Nodes annotations, String name) { return decl; } -const Node* quote_helper(IrArena* a, Nodes values) { - for (size_t i = 0; i < values.count; i++) - assert(is_value(values.nodes[i])); - - return prim_op(a, (PrimOp) { - .op = quote_op, - .type_arguments = nodes(a, 0, NULL), - .operands = values - }); -} - const Node* prim_op_helper(IrArena* a, Op op, Nodes types, Nodes operands) { return prim_op(a, (PrimOp) { .op = op, @@ -350,9 +369,10 @@ const Node* jump_helper(IrArena* a, const Node* dst, Nodes args) { } const Node* unit_type(IrArena* arena) { - return record_type(arena, (RecordType) { + /*return record_type(arena, (RecordType) { .members = empty(arena), - }); + });*/ + return empty_multiple_return_type(arena); } const Node* empty_multiple_return_type(IrArena* arena) { @@ -417,3 +437,9 @@ const Node* extract_helper(const Node* composite, const Node* index) { IrArena* a = composite->arena; return prim_op_helper(a, extract_op, empty(a), mk_nodes(a, composite, index)); } + +const Node* maybe_tuple_helper(IrArena* a, Nodes values) { + if (values.count == 1) + return first(values); + return tuple_helper(a, values); +} diff --git a/src/shady/fold.c b/src/shady/fold.c index 8be281a18..01a5424f1 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -12,7 +12,7 @@ #include static const Node* quote_single(IrArena* a, const Node* value) { - return quote_helper(a, singleton(value)); + return value; } static bool is_zero(const Node* node) { @@ -338,7 +338,7 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { } case Store_TAG: { if (node->payload.store.ptr->tag == Undef_TAG) - return quote_helper(arena, empty(arena)); + return tuple_helper(arena, empty(arena)); break; } case Lea_TAG: { @@ -387,7 +387,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { const Node* lam = node->payload.block.inside; const Node* body = lam->payload.case_.body; if (body->tag == BlockYield_TAG) { - return quote_helper(arena, body->payload.block_yield.args); + return maybe_tuple_helper(arena, body->payload.block_yield.args); } else if (body->tag == Let_TAG) { // fold block { let x, y, z = I; yield (x, y, z); } back to I const Node* instr = get_let_instruction(body); @@ -468,7 +468,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { // catch bad folding rules that mess things up if (is_value(original_node)) assert(is_value(node)); - if (is_instruction(original_node)) assert(is_instruction(node)); + if (is_instruction(original_node)) assert(is_instruction(node) || is_value(node)); if (is_terminator(original_node)) assert(is_terminator(node)); if (node->type) diff --git a/src/shady/node.c b/src/shady/node.c index 5d40b4811..f9637fd39 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -72,12 +72,6 @@ double get_float_literal_value(FloatLiteral literal) { return r; } -const Node* get_quoted_value(const Node* instruction) { - if (instruction->payload.prim_op.op == quote_op) - return first(instruction->payload.prim_op.operands); - return NULL; -} - static bool is_zero(const Node* node) { const IntLiteral* lit = resolve_to_int_literal(node); if (lit && get_int_literal_value(*lit, false) == 0) @@ -206,10 +200,6 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi } case PrimOp_TAG: { switch (node->payload.prim_op.op) { - case quote_op: { - node = first(node->payload.prim_op.operands); - continue; - } case convert_op: case reinterpret_op: { if (config.allow_incompatible_types) { diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 39d047dd0..8a0751fe3 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -140,8 +140,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, BodyBuilder* bb, const } } - Nodes e = empty(a); - return prim_op_helper(a, quote_op, empty(a), empty(a)); + return tuple_helper(a, empty(a)); } static const Node* rewrite_decl(Context* ctx, const Node* decl) { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index ca88e079d..dd9888462 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -79,7 +79,7 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* continue; } case Terminator_BlockYield_TAG: { - return quote_helper(arena, terminator->payload.block_yield.args); + return maybe_tuple_helper(arena, terminator->payload.block_yield.args); } case Terminator_Return_TAG: case Terminator_TailCall_TAG: { @@ -142,16 +142,6 @@ const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body(a); const Node* oinstruction = old->payload.let.instruction; - if (oinstruction->tag == PrimOp_TAG && oinstruction->payload.prim_op.op == quote_op) { - Nodes args = oinstruction->payload.prim_op.operands; - if (args.count == 1) { - register_processed(r, oinstruction, first(rewrite_nodes(r, args))); - return finish_body(bb, rewrite_node(r, old->payload.let.in)); - } else { - register_processed(r, oinstruction, tuple_helper(a, rewrite_nodes(r, args))); - return finish_body(bb, rewrite_node(r, old->payload.let.in)); - } - } const Node* instruction; // optimization: fold blocks if (oinstruction->tag == Block_TAG) { diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index dc0f4f88f..215b6e6b4 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -77,7 +77,7 @@ static const Node* process(Context* ctx, const Node* old) { const Type* osrc_t = osrc->type; deconstruct_qualified_type(&osrc_t); if (osrc_t->tag == PtrType_TAG && !get_arena_config(a)->address_spaces[osrc_t->payload.ptr_type.address_space].physical) - return prim_op_helper(a, quote_op, empty(a), singleton(rewrite_node(r, osrc))); + return rewrite_node(r, osrc); break; } default: break; diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 70a25c945..2a0a1d85e 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -25,7 +25,7 @@ static const Node* process(Context* ctx, const Node* node) { Op op = node->payload.prim_op.op; Nodes old_nodes = node->payload.prim_op.operands; switch(op) { - case empty_mask_op: return quote_helper(a, singleton(ctx->zero)); + case empty_mask_op: return ctx->zero; case subgroup_active_mask_op: // this is just ballot(true) return prim_op(a, (PrimOp) { .op = subgroup_ballot_op, .type_arguments = empty(a), .operands = singleton(true_lit(ctx->rewriter.dst_arena)) }); // extract the relevant bit diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 764cef768..f45a0a036 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -24,12 +24,12 @@ static const Node* process(Context* ctx, const Node* old) { case size_of_op: { const Type* t = rewrite_node(&ctx->rewriter, first(old->payload.prim_op.type_arguments)); TypeMemLayout layout = get_mem_layout(a, t); - return quote_helper(a, singleton(int_literal(a, (IntLiteral) {.width = a->config.memory.ptr_size, .is_signed = false, .value = layout.size_in_bytes}))); + return int_literal(a, (IntLiteral) {.width = a->config.memory.ptr_size, .is_signed = false, .value = layout.size_in_bytes}); } case align_of_op: { const Type* t = rewrite_node(&ctx->rewriter, first(old->payload.prim_op.type_arguments)); TypeMemLayout layout = get_mem_layout(a, t); - return quote_helper(a, singleton(int_literal(a, (IntLiteral) {.width = a->config.memory.ptr_size, .is_signed = false, .value = layout.alignment_in_bytes}))); + return int_literal(a, (IntLiteral) {.width = a->config.memory.ptr_size, .is_signed = false, .value = layout.alignment_in_bytes}); } case offset_of_op: { const Type* t = rewrite_node(&ctx->rewriter, first(old->payload.prim_op.type_arguments)); @@ -39,7 +39,7 @@ static const Node* process(Context* ctx, const Node* old) { t = get_maybe_nominal_type_body(t); uint64_t offset_in_bytes = (uint64_t) get_record_field_offset_in_bytes(a, t, literal->value); const Node* offset_literal = int_literal(a, (IntLiteral) { .width = a->config.memory.ptr_size, .is_signed = false, .value = offset_in_bytes }); - return quote_helper(a, singleton(offset_literal)); + return offset_literal; } default: break; } diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index c1669da50..0644a7715 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -82,7 +82,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str return new; } const Node* val = force_to_be_value(ctx, node); - return quote_helper(a, singleton(val)); + return val; } case NcTerminator: break; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 82a33a235..a017e8996 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -169,7 +169,7 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t if (!k->leaks) { if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { ctx->todo |= true; - const Node* new = quote_helper(a, singleton(undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}))); + const Node* new = undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}); k->new = new; return new; } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 568d41e28..4a89fc5ad 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -137,7 +137,7 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* j, const Node* e Node* inner_exit_ladder_bb = basic_block(a, empty(a), unique_name(a, "exit_ladder_inline_me")); // Just jumps to the actual ladder - const Node* structured = structure(&ctx2, get_abstraction_body(dst), let(a, quote_helper(a, empty(a)), jump(a, (Jump) {.target = inner_exit_ladder_bb, .args = empty(a)}))); + const Node* structured = structure(&ctx2, get_abstraction_body(dst), jump(a, (Jump) {.target = inner_exit_ladder_bb, .args = empty(a)})); assert(is_terminator(structured)); // forget we rewrote all that destroy_dict(tmp_processed); @@ -287,7 +287,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit_la const Node* if_true_lam = case_(a, empty(a), true_body); gen_if(bb2, empty(a), guard, if_true_lam, NULL); - return finish_body(bb_outer, structure(&control_ctx, get_abstraction_body(old_control_body), let(a, quote_helper(a, empty(a)), finish_body(bb2, exit_ladder)))); + return finish_body(bb_outer, structure(&control_ctx, get_abstraction_body(old_control_body), finish_body(bb2, exit_ladder))); } case Join_TAG: { ControlEntry* control = search_containing_control(ctx, body->payload.join.join_point); diff --git a/src/shady/passes/opt_stack.c b/src/shady/passes/opt_stack.c index 932276017..ea08412d0 100644 --- a/src/shady/passes/opt_stack.c +++ b/src/shady/passes/opt_stack.c @@ -79,11 +79,11 @@ static const Node* process(Context* ctx, const Node* node) { const Node* ninstruction = NULL; if (is_push && !child_ctx.state->leaks) { // replace stack pushes with no-ops - ninstruction = quote_helper(a, empty(a)); + ninstruction = maybe_tuple_helper(a, empty(a)); } else if (is_pop) { assert(ctx->state->type == VALUE); const Node* value = ctx->state->value; - ninstruction = quote_helper(a, singleton(value)); + ninstruction = value; } else { // if the stack state is observed, or this was an unrelated instruction, leave it alone ninstruction = recreate_node_identity(&ctx->rewriter, old_instruction); diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c index ae3c5edc2..6ec45b35b 100644 --- a/src/shady/passes/simt2d.c +++ b/src/shady/passes/simt2d.c @@ -49,7 +49,6 @@ static const Node* process(Context* ctx, const Node* node) { case PrimOp_TAG: { Op op = node->payload.prim_op.op; switch (op) { - case quote_op: goto rewrite; default: break; } diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index d0d06205c..20a7e709d 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -30,7 +30,7 @@ static const Node* process(Context* ctx, const Node* node) { wg_size[0] = a->config.specializations.workgroup_size[0]; wg_size[1] = a->config.specializations.workgroup_size[1]; wg_size[2] = a->config.specializations.workgroup_size[2]; - return quote_helper(a, singleton(composite_helper(a, t, mk_nodes(a, uint32_literal(a, wg_size[0]), uint32_literal(a, wg_size[1]), uint32_literal(a, wg_size[2]) )))); + return composite_helper(a, t, mk_nodes(a, uint32_literal(a, wg_size[0]), uint32_literal(a, wg_size[1]), uint32_literal(a, wg_size[2]) )); } break; } @@ -59,7 +59,7 @@ static const Node* process(Context* ctx, const Node* node) { uint32_t subgroups_per_wg = (wg_size[0] * wg_size[1] * wg_size[2]) / ctx->config->specialization.subgroup_size; if (subgroups_per_wg == 0) subgroups_per_wg = 1; // uh-oh - ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, subgroups_per_wg))); + ncnst->payload.constant.instruction = uint32_literal(a, subgroups_per_wg); } return ncnst; } diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 59dd54fc0..3ee495c14 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -24,7 +24,7 @@ static const Node* process(Context* ctx, const Node* node) { case Constant_TAG: { Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { - ncnst->payload.constant.instruction = quote_helper(a, singleton(uint32_literal(a, ctx->config->specialization.subgroup_size))); + ncnst->payload.constant.instruction = uint32_literal(a, ctx->config->specialization.subgroup_size); } return ncnst; } diff --git a/src/shady/print.c b/src/shady/print.c index 2fad1e20c..413dcb879 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1000,10 +1000,7 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { printf(RESET); if (cnst->instruction) { printf(" = "); - if (get_quoted_value(cnst->instruction)) - print_node(get_quoted_value(cnst->instruction)); - else - print_node_impl(ctx, cnst->instruction); + print_node_impl(ctx, cnst->instruction); } printf(";\n"); break; diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 1faa999e5..ae20b21a7 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -353,6 +353,9 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { recreate_decl_body_identity(rewriter, node, new); return new; } + case CompoundInstruction_TAG: { + return compound_instruction(arena, rewrite_ops_helper(rewriter, NcInstruction, "instructions", node->payload.compound_instruction.instructions), rewrite_ops_helper(rewriter, NcValue, "results", node->payload.compound_instruction.results)); + } case Param_TAG: log_string(ERROR, "Can't rewrite: "); log_node(ERROR, node); diff --git a/src/shady/transform/internal_constants.c b/src/shady/transform/internal_constants.c index 78f61c164..811e3cd78 100644 --- a/src/shady/transform/internal_constants.c +++ b/src/shady/transform/internal_constants.c @@ -9,7 +9,7 @@ void generate_dummy_constants(SHADY_UNUSED const CompilerConfig* config, Module* IrArena* arena = get_module_arena(mod); #define X(constant_name, T, placeholder) \ Node* constant_name##_var = constant(mod, singleton(annotation(arena, (Annotation) { .name = "RetainAfterSpecialization" })), T, #constant_name); \ - constant_name##_var->payload.constant.instruction = quote_helper(arena, singleton(placeholder)); + constant_name##_var->payload.constant.instruction = placeholder; INTERNAL_CONSTANTS(X) #undef X } diff --git a/src/shady/type.c b/src/shady/type.c index ab805a8a9..00d76fcd6 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -449,6 +449,8 @@ const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { } const Type* check_type_composite(IrArena* arena, Composite composite) { + if (composite.contents.count == 0) + return unit_type(arena); assert(is_data_type(composite.type)); Nodes expected_member_types = get_composite_type_element_types(composite.type); bool is_uniform = true; @@ -529,10 +531,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case assign_op: case addrof_op: case subscript_op: error("These ops are only allowed in untyped IR before desugaring. They don't type to anything."); - case quote_op: { - assert(prim_op.type_arguments.count == 0); - return wrap_multiple_yield_types(arena, get_values_types(arena, prim_op.operands)); - } case neg_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); From cbc840318a5d478188832a7de75ab477bdaaab0e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 14:40:21 +0200 Subject: [PATCH 401/693] fix restructure pass --- src/shady/passes/opt_restructure.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 4a89fc5ad..9f8ce81b6 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -201,9 +201,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit_la break; } } - const Node* new_instruction = recreate_node_identity(&ctx->rewriter, old_instr); - register_processed(r, old_instr, new_instruction); - + const Node* new_instruction = rewrite_node(&ctx->rewriter, old_instr); return let(a, new_instruction, structure(ctx, body->payload.let.in, exit_ladder)); } case Jump_TAG: { From 1f8ba147d257f873949f88d596fd7d5f496d6f95 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 2 Aug 2024 15:21:19 +0200 Subject: [PATCH 402/693] added nullability checks to the grammar --- include/shady/grammar.json | 16 ++++++++-------- src/shady/generator_constructors.c | 7 +++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 2adfd1659..ea958bc32 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -227,7 +227,7 @@ "class": "type", "ops": [ { "name": "element_type", "class": "type" }, - { "name": "size", "class": "value" } + { "name": "size", "class": "value", "nullable": true } ] }, { @@ -326,7 +326,7 @@ "Re-ordering values does not count as a computation here !" ], "ops": [ - { "name": "type", "class": "type" }, + { "name": "type", "class": "type", "nullable": true }, { "name": "contents", "class": "value", "list": true } ] }, @@ -381,7 +381,7 @@ { "name": "yield_types", "class": "type", "list": true }, { "name": "condition", "class": "value" }, { "name": "if_true", "class": "case" }, - { "name": "if_false", "class": "case" }, + { "name": "if_false", "class": "case", "nullable": true }, { "name": "tail", "class": "case" } ] }, @@ -575,7 +575,7 @@ { "name": "name", "class": "string" }, { "name": "annotations", "class": "annotation", "list": true }, { "name": "params", "class": "param", "list": true }, - { "name": "body", "class": "terminator" }, + { "name": "body", "class": "terminator", "nullable": true }, { "name": "return_types", "class": "type", "list": true } ] }, @@ -590,7 +590,7 @@ { "name": "name", "class": "string" }, { "name": "annotations", "class": "annotation", "list": true }, { "name": "type_hint", "class": "type" }, - { "name": "instruction", "class": "instruction" } + { "name": "instruction", "class": "instruction", "nullable": true } ] }, { @@ -604,7 +604,7 @@ { "name": "annotations", "class": "annotation", "list": true }, { "name": "type", "class": "type" }, { "name": "address_space", "type": "AddressSpace"}, - { "name": "init", "class": "value", "ignore": true } + { "name": "init", "class": "value", "nullable": true } ] }, { @@ -618,7 +618,7 @@ { "name": "module", "type": "Module*", "ignore": true }, { "name": "name", "class": "string" }, { "name": "annotations", "class": "annotation", "list": true }, - { "name": "body", "class": "type" } + { "name": "body", "class": "type", "nullable": true } ] }, { @@ -664,7 +664,7 @@ "nominal": true, "ops": [ { "name": "params", "class": "param", "list": true }, - { "name": "body", "class": "terminator" }, + { "name": "body", "class": "terminator", "nullable": true }, { "name": "name", "class": "string" } ] }, diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 53140c0d2..f182c0a4f 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -42,6 +42,13 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { } if (!list) growy_append_formatted(g, "\t\t\tconst Node* op = node->payload.%s.%s;\n", snake_name, op_name); + + if (!(json_object_get_boolean(json_object_object_get(op, "nullable")) || json_object_get_boolean(json_object_object_get(op, "ignore")))) { + growy_append_formatted(g, "%s\t\t\tif (!op) {\n", extra); + growy_append_formatted(g, "%s\t\t\t\terror(\"operand '%s' of node '%s' cannot be null\");\n", extra, op_name, name); + growy_append_formatted(g, "%s\t\t\t}\n", extra); + } + growy_append_formatted(g, "%s\t\t\tif (arena->config.check_op_classes && op != NULL && !is_%s(op)) {\n", extra, class); growy_append_formatted(g, "%s\t\t\t\terror_print(\"Invalid '%s' operand for node '%s', expected a %s\");\n", extra, op_name, name, class); growy_append_formatted(g, "%s\t\t\t\terror_die();\n", extra); From dcdf7a24232bc94ec1d9b6a1da486c2cc665e23b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 10:21:32 +0200 Subject: [PATCH 403/693] made cases mutable --- include/shady/grammar.json | 2 +- include/shady/ir.h | 10 ++--- src/frontend/llvm/l2s_postprocess.c | 4 +- src/frontend/slim/parser.c | 20 ++++++---- src/shady/body_builder.c | 41 ++++++++++++------- src/shady/constructors.c | 9 ++--- src/shady/passes/bind.c | 4 +- src/shady/passes/infer.c | 16 ++++---- src/shady/passes/lower_callf.c | 5 ++- src/shady/passes/lower_cf_instrs.c | 13 ++++-- src/shady/passes/lower_generic_ptrs.c | 28 ++++++++----- src/shady/passes/lower_memcpy.c | 20 +++++++--- src/shady/passes/lower_switch_btree.c | 16 ++++++-- src/shady/passes/lower_tailcalls.c | 32 +++++++++------ src/shady/passes/lower_workgroups.c | 7 +++- src/shady/passes/normalize.c | 4 +- src/shady/passes/opt_inline.c | 4 +- src/shady/passes/opt_restructure.c | 30 +++++++------- src/shady/passes/reconvergence_heuristics.c | 44 ++++++++++++--------- src/shady/rewrite.c | 5 ++- 20 files changed, 195 insertions(+), 119 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index ea958bc32..5a38af372 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -679,7 +679,7 @@ ], "ops": [ { "name": "params", "class": "param", "list": true }, - { "name": "body", "class": "terminator" }, + { "name": "body", "class": "terminator", "nullable": true }, { "name": "structured_construct", "type": "const Node*", "ignored": true } ] }, diff --git a/include/shady/ir.h b/include/shady/ir.h index 08aa97312..80f102e42 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -268,7 +268,7 @@ Type* nominal_type(Module*, Nodes annotations, String name); // basic blocks, lambdas and their helpers Node* basic_block(IrArena*, Nodes params, const char* name); -const Node* case_(IrArena* a, Nodes params, const Node* body); +Node* case_(IrArena* a, Nodes params); /// Used to build a chain of let typedef struct BodyBuilder_ BodyBuilder; @@ -279,10 +279,10 @@ BodyBuilder* begin_body(IrArena*); Nodes bind_instruction(BodyBuilder*, const Node* instruction); Nodes bind_instruction_named(BodyBuilder*, const Node* instruction, String const output_names[]); -Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, const Node*); -Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, const Node*); -Nodes gen_loop(BodyBuilder*, Nodes, Nodes, const Node*); -Nodes gen_control(BodyBuilder*, Nodes, const Node*); +Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, Node*); +Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, Node*); +Nodes gen_loop(BodyBuilder*, Nodes, Nodes, Node*); +Nodes gen_control(BodyBuilder*, Nodes, Node*); /// Like append bind_instruction, but you explicitly give it information about any yielded values /// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index f95198dcc..54b600b89 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -40,8 +40,10 @@ static const Node* wrap_in_controls(Context* ctx, Controls* controls, const Node const Node* token = controls->tokens.nodes[i]; const Node* dst = controls->destinations.nodes[i]; Nodes o_dst_params = get_abstraction_params(dst); + Node* control_case = case_(a, singleton(token)); + set_abstraction_body(control_case, body); BodyBuilder* bb = begin_body(a); - Nodes results = gen_control(bb, get_param_types(a, o_dst_params), case_(a, singleton(token), body)); + Nodes results = gen_control(bb, get_param_types(a, o_dst_params), control_case); body = finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results)); } return body; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 37b629c71..5956b3df7 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -599,15 +599,17 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { expect(accept_token(ctx, rpar_tok)); const Node* merge = config.front_end ? merge_selection(arena, (MergeSelection) { .args = nodes(arena, 0, NULL) }) : NULL; - const Node* if_true = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, merge)); + Node* true_case = case_(arena, nodes(arena, 0, NULL)); + set_abstraction_body(true_case, expect_body(ctx, merge)); // else defaults to an empty body bool has_else = accept_token(ctx, else_tok); - const Node* if_false = NULL; + Node* false_case = NULL; if (has_else) { - if_false = case_(arena, nodes(arena, 0, NULL), expect_body(ctx, merge)); + false_case = case_(arena, nodes(arena, 0, NULL)); + set_abstraction_body(false_case, expect_body(ctx, merge)); } - return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, if_true, if_false)); + return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, true_case, false_case)); } case loop_tok: { next_token(tokenizer); @@ -617,8 +619,9 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { expect_parameters(ctx, ¶meters, &initial_arguments); // by default loops continue forever const Node* default_loop_end_behaviour = config.front_end ? merge_continue(arena, (MergeContinue) { .args = nodes(arena, 0, NULL) }) : NULL; - const Node* body = case_(arena, parameters, expect_body(ctx, default_loop_end_behaviour)); - return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, body)); + Node* loop_case = case_(arena, parameters); + set_abstraction_body(loop_case, expect_body(ctx, default_loop_end_behaviour)); + return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, loop_case)); } case control_tok: { next_token(tokenizer); @@ -630,8 +633,9 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { .yield_types = yield_types, }), str); expect(accept_token(ctx, rpar_tok)); - const Node* body = case_(arena, singleton(jp), expect_body(ctx, NULL)); - return maybe_tuple_helper(arena, gen_control(bb, yield_types, body)); + Node* control_case = case_(arena, singleton(jp)); + set_abstraction_body(control_case, expect_body(ctx, NULL)); + return maybe_tuple_helper(arena, gen_control(bb, yield_types, control_case)); } default: break; } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 49a86f56a..0fe33848b 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -91,22 +91,34 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { case NotAStructured_construct: terminator = let(a, entry.structured.payload.let.instruction, terminator); break; - case Structured_construct_If_TAG: - entry.structured.payload.if_instr.tail = case_(bb->arena, entry.vars, terminator); + case Structured_construct_If_TAG: { + Node* tail = case_(bb->arena, entry.vars); + set_abstraction_body(tail, terminator); + entry.structured.payload.if_instr.tail = tail; terminator = if_instr(a, entry.structured.payload.if_instr); break; - case Structured_construct_Match_TAG: - entry.structured.payload.match_instr.tail = case_(bb->arena, entry.vars, terminator); + } + case Structured_construct_Match_TAG: { + Node* tail = case_(bb->arena, entry.vars); + set_abstraction_body(tail, terminator); + entry.structured.payload.match_instr.tail = tail; terminator = match_instr(a, entry.structured.payload.match_instr); break; - case Structured_construct_Loop_TAG: - entry.structured.payload.loop_instr.tail = case_(bb->arena, entry.vars, terminator); + } + case Structured_construct_Loop_TAG: { + Node* tail = case_(bb->arena, entry.vars); + set_abstraction_body(tail, terminator); + entry.structured.payload.loop_instr.tail = tail; terminator = loop_instr(a, entry.structured.payload.loop_instr); break; - case Structured_construct_Control_TAG: - entry.structured.payload.control.tail = case_(bb->arena, entry.vars, terminator); + } + case Structured_construct_Control_TAG: { + Node* tail = case_(bb->arena, entry.vars); + set_abstraction_body(tail, terminator); + entry.structured.payload.control.tail = tail; terminator = control(a, entry.structured.payload.control); break; + } } } return terminator; @@ -122,10 +134,11 @@ const Node* finish_body(BodyBuilder* bb, const Node* terminator) { const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder* bb, Nodes values, const Nodes types) { IrArena* arena = bb->arena; const Node* terminator = block_yield(arena, (BlockYield) { .args = values }); - const Node* lam = case_(arena, empty(arena), finish_body(bb, terminator)); + const Node* block_case = case_(arena, empty(arena)); + set_abstraction_body(block_case, finish_body(bb, terminator)); return block(arena, (Block) { .yield_types = types, - .inside = lam, + .inside = block_case, }); } @@ -209,7 +222,7 @@ static Nodes gen_structured_construct(BodyBuilder* bb, Nodes yield_types, Struct return add_structured_construct(bb, gen_variables(bb, yield_types), tag, payload); } -Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, const Node* false_case) { +Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, Node* false_case) { return gen_structured_construct(bb, yield_types, Structured_construct_If_TAG, (union NodesUnion) { .if_instr = { .condition = condition, @@ -220,7 +233,7 @@ Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const No }); } -Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, const Node* default_case) { +Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, Node* default_case) { return gen_structured_construct(bb, yield_types, Structured_construct_Match_TAG, (union NodesUnion) { .match_instr = { .yield_types = yield_types, @@ -232,7 +245,7 @@ Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes }); } -Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Node* body) { +Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, Node* body) { return gen_structured_construct(bb, yield_types, Structured_construct_Loop_TAG, (union NodesUnion) { .loop_instr = { .yield_types = yield_types, @@ -242,7 +255,7 @@ Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, const Nod }); } -Nodes gen_control(BodyBuilder* bb, Nodes yield_types, const Node* body) { +Nodes gen_control(BodyBuilder* bb, Nodes yield_types, Node* body) { return gen_structured_construct(bb, yield_types, Structured_construct_Control_TAG, (union NodesUnion) { .control = { .yield_types = yield_types, diff --git a/src/shady/constructors.c b/src/shady/constructors.c index a503ff6d0..f097abd5e 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -247,10 +247,9 @@ Node* basic_block(IrArena* arena, Nodes params, const char* name) { return bb; } -const Node* case_(IrArena* a, Nodes params, const Node* body) { +Node* case_(IrArena* a, Nodes params) { Case payload = { .params = params, - .body = body, }; Node node; @@ -263,19 +262,19 @@ const Node* case_(IrArena* a, Nodes params, const Node* body) { }; bool fresh; - const Node* lam = create_node_helper(a, node, &fresh); + Node* ncase = create_node_helper(a, node, &fresh); if (fresh || true) { for (size_t i = 0; i < params.count; i++) { Node* param = (Node*) params.nodes[i]; assert(param->tag == Param_TAG); assert(!param->payload.param.abs); - param->payload.param.abs = lam; + param->payload.param.abs = ncase; param->payload.param.pindex = i; } } - return lam; + return ncase; } Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 8a0751fe3..0f0595c6f 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -284,7 +284,9 @@ static const Node* bind_node(Context* ctx, const Node* node) { } register_processed_list(&ctx->rewriter, old_params, new_params); const Node* new_body = rewrite_node(&ctx->rewriter, node->payload.case_.body); - return case_(a, new_params, new_body); + Node* new_case = case_(a, new_params); + set_abstraction_body(new_case, new_body); + return new_case; } case BindIdentifiers_TAG: assert(false); case Return_TAG: { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index aa812d903..31d3513f7 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -314,8 +314,9 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg } } - const Node* new_body = infer(&body_context, node->payload.case_.body, NULL); - return case_(a, nodes(a, inferred_arg_type.count, nparams), new_body); + Node* new_case = case_(a, nodes(a, inferred_arg_type.count, nparams)); + set_abstraction_body(new_case, infer(&body_context, node->payload.case_.body, NULL)); + return new_case; } static const Node* _infer_basic_block(Context* ctx, const Node* node) { @@ -515,11 +516,12 @@ static const Node* infer_control(Context* ctx, const Node* node) { const Node* jp = param(a, jpt, ojp->payload.param.name); register_processed(&joinable_ctx.rewriter, ojp, jp); - const Node* nlam = case_(a, singleton(jp), infer(&joinable_ctx, get_abstraction_body(olam), NULL)); + Node* new_case = case_(a, singleton(jp)); + set_abstraction_body(new_case, infer(&joinable_ctx, get_abstraction_body(olam), NULL)); return control(a, (Control) { .yield_types = yield_types, - .inside = nlam, + .inside = new_case, .tail = infer_case(ctx, get_structured_construct_tail(node), add_qualifiers(a, yield_types, false)) }); } @@ -531,12 +533,12 @@ static const Node* infer_block(Context* ctx, const Node* node, const Nodes* expe Context block_inside_ctx = *ctx; Nodes nyield_types = infer_nodes(ctx, node->payload.block.yield_types); block_inside_ctx.merge_types = &nyield_types; - const Node* olam = node->payload.block.inside; - const Node* nlam = case_(a, empty(a), infer(&block_inside_ctx, get_abstraction_body(olam), NULL)); + Node* new_case = case_(a, empty(a)); + set_abstraction_body(new_case, infer(&block_inside_ctx, get_abstraction_body(node->payload.block.inside), NULL)); return block(a, (Block) { .yield_types = nyield_types, - .inside = nlam + .inside = new_case }); } diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 5be61e868..5dedcd2a2 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -130,9 +130,10 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .target = ncallee, .args = nargs, }); - const Node* control_lam = case_(a, singleton(jp), control_body); + const Node* control_case = case_(a, singleton(jp)); + set_abstraction_body(control_case, control_body); BodyBuilder* bb = begin_body(a); - return yield_values_and_wrap_in_block(bb, gen_control(bb, strip_qualifiers(a, returned_types), control_lam)); + return yield_values_and_wrap_in_block(bb, gen_control(bb, strip_qualifiers(a, returned_types), control_case)); } default: break; } diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index fbe19fa7a..eeecb1848 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -102,7 +102,9 @@ static const Node* process_node(Context* ctx, const Node* node) { }); BodyBuilder* bb = begin_body(a); - Nodes results = gen_control(bb, yield_types, case_(a, singleton(jp), control_body)); + Node* control_case = case_(a, singleton(jp)); + set_abstraction_body(control_case, control_body); + Nodes results = gen_control(bb, yield_types, control_case); const Node* otail = node->payload.if_instr.tail; Node* join = basic_block(a, recreate_params(r, get_abstraction_params(otail)), NULL); @@ -141,10 +143,11 @@ static const Node* process_node(Context* ctx, const Node* node) { join_context.abs = old_loop_body; const Node* inner_control_body = rewrite_node(&join_context.rewriter, old_loop_body->payload.case_.body); - const Node* inner_control_lam = case_(a, nodes(a, 1, (const Node* []) {continue_point}), inner_control_body); + Node* inner_control_case = case_(a, singleton(continue_point)); + set_abstraction_body(inner_control_case, inner_control_body); BodyBuilder* inner_bb = begin_body(a); - Nodes args = gen_control(inner_bb, param_types, inner_control_lam); + Nodes args = gen_control(inner_bb, param_types, inner_control_case); // TODO let_in_block or use a Jump ! loop_body->payload.basic_block.body = finish_body(inner_bb, jump(a, (Jump) { .target = loop_body, .args = args })); @@ -155,7 +158,9 @@ static const Node* process_node(Context* ctx, const Node* node) { }); BodyBuilder* outer_bb = begin_body(a); - Nodes results = gen_control(outer_bb, yield_types, case_(a, singleton(break_point), initial_jump)); + Node* outer_control_case = case_(a, singleton(break_point)); + Nodes results = gen_control(outer_bb, yield_types, outer_control_case); + set_abstraction_body(outer_control_case, initial_jump); const Node* otail = get_structured_construct_tail(node); Node* join = basic_block(a, recreate_params(r, get_abstraction_params(otail)), NULL); diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 2ce8427de..b7f3ccda0 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -100,18 +100,20 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo switch (which) { case LoadFn: { LARRAY(const Node*, literals, max_tag); - LARRAY(const Node*, cases, max_tag); + LARRAY(Node*, cases, max_tag); for (size_t tag = 0; tag < max_tag; tag++) { literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { - cases[tag] = case_(a, empty(a), unreachable(a)); + cases[tag] = case_(a, empty(a)); + set_abstraction_body(cases[tag], unreachable(a)); continue; } BodyBuilder* case_bb = begin_body(a); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); - cases[tag] = case_(a, empty(a), finish_body(case_bb, merge_selection(a, (MergeSelection) { - .args = singleton(loaded_value), + cases[tag] = case_(a, empty(a)); + set_abstraction_body(cases[tag], finish_body(case_bb, merge_selection(a, (MergeSelection) { + .args = singleton(loaded_value), }))); } @@ -120,24 +122,28 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); - const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), case_(a, empty(a), unreachable(a)))); + Node* default_case = case_(a, empty(a)); + set_abstraction_body(default_case, unreachable(a)); + const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), default_case)); new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value) })); break; } case StoreFn: { LARRAY(const Node*, literals, max_tag); - LARRAY(const Node*, cases, max_tag); + LARRAY(Node*, cases, max_tag); for (size_t tag = 0; tag < max_tag; tag++) { literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { - cases[tag] = case_(a, empty(a), unreachable(a)); + cases[tag] = case_(a, empty(a)); + set_abstraction_body(cases[tag], unreachable(a)); continue; } BodyBuilder* case_bb = begin_body(a); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); - cases[tag] = case_(a, empty(a), finish_body(case_bb, merge_selection(a, (MergeSelection) { - .args = empty(a), + cases[tag] = case_(a, empty(a)); + set_abstraction_body(cases[tag], finish_body(case_bb, merge_selection(a, (MergeSelection) { + .args = empty(a), }))); } @@ -146,7 +152,9 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); - gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), case_(a, empty(a), unreachable(a))); + Node* default_case = case_(a, empty(a)); + set_abstraction_body(default_case, unreachable(a)); + gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), default_case); new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); break; } diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index b3c3d15fa..49f1197eb 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -57,10 +57,14 @@ static const Node* process(Context* ctx, const Node* old) { const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, empty(a))); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); - const Node* true_case = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); - const Node* false_case = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})); + Node* true_case = case_(a, empty(a)); + set_abstraction_body(true_case, merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); + Node* false_case = case_(a, empty(a)); + set_abstraction_body(false_case, merge_break(a, (MergeBreak) {.args = empty(a)})); gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), true_case, false_case); - gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), case_(a, singleton(index), finish_body(loop_bb, unreachable(a)))); + Node* loop_case = case_(a, singleton(index)); + set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a))); + gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), loop_case); return yield_values_and_wrap_in_block(bb, empty(a)); } case FillBytes_TAG: { @@ -90,10 +94,14 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* loop_bb = begin_body(a); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); - const Node* true_case = case_(a, empty(a), merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); - const Node* false_case = case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})); + Node* true_case = case_(a, empty(a)); + set_abstraction_body(true_case, merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); + Node* false_case = case_(a, empty(a)); + set_abstraction_body(false_case, merge_break(a, (MergeBreak) {.args = empty(a)})); gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), true_case, false_case); - gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), case_(a, singleton(index), finish_body(loop_bb, unreachable(a)))); + Node* loop_case = case_(a, singleton(index)); + set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a))); + gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), loop_case); return yield_values_and_wrap_in_block(bb, empty(a)); } default: break; diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 8cabee782..83cfbf1d5 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -89,7 +89,9 @@ static const Node* generate_default_fallback_case(Context* ctx, bool in_if) { LARRAY(const Node*, undefs, ctx->yield_types.count); for (size_t i = 0; i < ctx->yield_types.count; i++) undefs[i] = undef(a, (Undef) { .type = ctx->yield_types.nodes[i] }); - return case_(a, empty(a), finish_body(bb, gen_yield(ctx, in_if, nodes(a, ctx->yield_types.count, undefs)))); + Node* c = case_(a, empty(a)); + set_abstraction_body(c, finish_body(bb, gen_yield(ctx, in_if, nodes(a, ctx->yield_types.count, undefs)))); + return c; } static const Node* generate_decision_tree(Context* ctx, TreeNode* n, bool in_if, uint64_t min, uint64_t max) { @@ -110,14 +112,18 @@ static const Node* generate_decision_tree(Context* ctx, TreeNode* n, bool in_if, BodyBuilder* bb = begin_body(a); const Node* true_branch = n->children[0] ? generate_decision_tree(ctx, n->children[0], true, min, n->key - 1) : generate_default_fallback_case(ctx, true); Nodes values = gen_if(bb, ctx->yield_types, gen_primop_e(bb, lt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), true_branch, body); - body = case_(a, empty(a), finish_body(bb, gen_yield(ctx, in_if || max > n->key, values))); + Node* c = case_(a, empty(a)); + set_abstraction_body(c, finish_body(bb, gen_yield(ctx, in_if || max > n->key, values))); + body = c; } if (max > n->key) { BodyBuilder* bb = begin_body(a); const Node* true_branch = n->children[1] ? generate_decision_tree(ctx, n->children[1], true, n->key + 1, max) : generate_default_fallback_case(ctx, true); Nodes values = gen_if(bb, ctx->yield_types, gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, ctx->inspectee, pivot)), true_branch, body); - body = case_(a, empty(a), finish_body(bb, gen_yield(ctx, in_if, values))); + Node* c = case_(a, empty(a)); + set_abstraction_body(c, finish_body(bb, gen_yield(ctx, in_if, values))); + body = c; } return body; @@ -157,7 +163,9 @@ static const Node* process(Context* ctx, const Node* node) { Nodes matched_results = bind_instruction(bb, block(a, (Block) { .yield_types = add_qualifiers(a, ctx2.yield_types, false), .inside = generate_decision_tree(&ctx2, root, false, 0, UINT64_MAX) })); // Check if we need to run the default case - Nodes final_results = gen_if(bb, ctx2.yield_types, gen_load(bb, run_default_case), rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), case_(a, empty(a), gen_yield(ctx, true, matched_results))); + Node* yield_case = case_(a, empty(a)); + set_abstraction_body(yield_case, gen_yield(ctx, true, matched_results)); + Nodes final_results = gen_if(bb, ctx2.yield_types, gen_load(bb, run_default_case), rewrite_node(&ctx->rewriter, node->payload.match_instr.default_case), yield_case); register_processed_list(r, get_abstraction_params(get_structured_construct_tail(node)), final_results); destroy_arena(arena); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 8a6979904..5ec950d2c 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -254,10 +254,11 @@ static const Node* process(Context* ctx, const Node* old) { }); const Node* new_jp = param(a, qualified_type_helper(new_jp_type, true), old_jp->payload.param.name); register_processed(&ctx->rewriter, old_jp, new_jp); - const Node* new_body = case_(a, singleton(new_jp), rewrite_node(&ctx->rewriter, get_abstraction_body(old_inside))); + const Node* new_control_case = case_(a, singleton(new_jp)); + set_abstraction_body(new_control_case, rewrite_node(&ctx->rewriter, get_abstraction_body(old_inside))); BodyBuilder* bb = begin_body(a); Nodes nyield_types = rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types); - return control(a, (Control) { .yield_types = nyield_types, .inside = new_body, .tail = rewrite_node(r, get_structured_construct_tail(old))}); + return control(a, (Control) { .yield_types = nyield_types, .inside = new_control_case, .tail = rewrite_node(r, get_structured_construct_tail(old))}); //return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, new_body)); } break; @@ -306,8 +307,9 @@ void generate_top_level_dispatch_fn(Context* ctx) { if (ctx->config->shader_diagnostics.max_top_iterations > 0) { const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); - const Node* bail_true_lam = case_(a, empty(a), break_terminator); - gen_if(loop_body_builder, empty(a), bail_condition, bail_true_lam, NULL); + Node* true_case = case_(a, empty(a)); + set_abstraction_body(true_case, break_terminator); + gen_if(loop_body_builder, empty(a), bail_condition, true_case, NULL); } struct List* literals = new_list(const Node*); @@ -320,14 +322,16 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } - const Node* zero_if_true_lam = case_(a, empty(a), finish_body(zero_if_case_builder, break_terminator)); + Node* zero_if_true_lam = case_(a, empty(a)); + set_abstraction_body(zero_if_true_lam, finish_body(zero_if_case_builder, break_terminator)); gen_if(zero_case_builder, empty(a), should_run, zero_if_true_lam, NULL); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_case_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } - const Node* zero_case_lam = case_(a, nodes(a, 0, NULL), finish_body(zero_case_builder, continue_terminator)); + Node* zero_case_lam = case_(a, nodes(a, 0, NULL)); + set_abstraction_body(zero_case_lam, finish_body(zero_case_builder, continue_terminator)); const Node* zero_lit = uint64_literal(a, 0); append_list(const Node*, literals, zero_lit); append_list(const Node*, cases, zero_case_lam); @@ -350,26 +354,30 @@ void generate_top_level_dispatch_fn(Context* ctx) { .callee = fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), .args = nodes(a, 0, NULL) })); - const Node* if_true_lam = case_(a, empty(a), finish_body(if_builder, merge_selection(a, (MergeSelection) {.args = nodes(a, 0, NULL)}))); + Node* if_true_lam = case_(a, empty(a)); + set_abstraction_body(if_true_lam, finish_body(if_builder, merge_selection(a, (MergeSelection) {.args = nodes(a, 0, NULL)}))); BodyBuilder* case_builder = begin_body(a); gen_if(case_builder, empty(a), should_run, if_true_lam, NULL); - const Node* case_lam = case_(a, nodes(a, 0, NULL), finish_body(case_builder, continue_terminator)); + Node* case_lam = case_(a, nodes(a, 0, NULL)); + set_abstraction_body(case_lam, finish_body(case_builder, continue_terminator)); append_list(const Node*, literals, fn_lit); append_list(const Node*, cases, case_lam); } } - const Node* default_case_lam = case_(a, nodes(a, 0, NULL), unreachable(a)); - gen_match(loop_body_builder, empty(a), next_function, nodes(a, entries_count_list(literals), read_list(const Node*, literals)), nodes(a, entries_count_list(cases), read_list(const Node*, cases)), default_case_lam); + Node* default_case = case_(a, nodes(a, 0, NULL)); + set_abstraction_body(default_case, unreachable(a)); + gen_match(loop_body_builder, empty(a), next_function, nodes(a, entries_count_list(literals), read_list(const Node*, literals)), nodes(a, entries_count_list(cases), read_list(const Node*, cases)), default_case); destroy_list(literals); destroy_list(cases); - const Node* loop_inside_lam = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL), finish_body(loop_body_builder, unreachable(a))); + Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL)); + set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, unreachable(a))); BodyBuilder* dispatcher_body_builder = begin_body(a); - gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : nodes(a, 0, NULL), loop_inside_lam); + gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : nodes(a, 0, NULL), loop_inside_case); if (ctx->config->printf_trace.god_function) gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", empty(a)); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 1c872ce6d..54d8f0f37 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -124,11 +124,14 @@ static const Node* process(Context* ctx, const Node* node) { assert(false); for (int dim = 0; dim < 3; dim++) { BodyBuilder* body_bb = begin_body(a); - gen_if(body_bb, empty(a), gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), case_(a, empty(a), merge_break(a, (MergeBreak) {.args = empty(a)})), NULL); + Node* out_of_bounds_case = case_(a, empty(a)); + set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) {.args = empty(a)})); + gen_if(body_bb, empty(a), gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), out_of_bounds_case, NULL); bind_instruction(body_bb, instr); BodyBuilder* bb3 = begin_body(a); - const Node* loop_body = case_(a, singleton(params[dim]), finish_body(body_bb, merge_continue(a, (MergeContinue) {.args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1))))}))); + Node* loop_body = case_(a, singleton(params[dim])); + set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) {.args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1))))}))); gen_loop(bb3, empty(a), singleton(uint32_literal(a, 0)), loop_body); instr = yield_values_and_wrap_in_block(bb3, empty(a)); } diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index 0644a7715..ed33edaf1 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -145,7 +145,9 @@ static const Node* process_node(Context* ctx, const Node* node) { ctx2.rewriter.rewrite_fn = (RewriteNodeFn) process_node; const Node* new_body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.case_.body)); - return case_(a, new_params, new_body); + Node* new_case = case_(a, new_params); + set_abstraction_body(new_case, new_body); + return new_case; } case Let_TAG: { const Node* oinstr = get_let_instruction(node); diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index b5eb2b2b6..7ddbe2c8c 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -184,9 +184,11 @@ static const Node* process(Context* ctx, const Node* node) { const Node* join_point = param(a, qualified_type_helper(jp_type, true), format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); const Node* nbody = inline_call(ctx, ocallee, nargs, join_point); + Node* control_case = case_(a, singleton(join_point)); + set_abstraction_body(control_case, nbody); BodyBuilder* bb = begin_body(a); - return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, case_(a, singleton(join_point), nbody))); + return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, control_case)); } } break; diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 9f8ce81b6..39d35a500 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -145,8 +145,9 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* j, const Node* e pop_list_impl(ctx->cleanup_stack); if (dfs_entry.loop_header) { - const Node* body = case_(a, nodes(a, oargs.count, nparams), structured); - gen_loop(bb, empty(a), rewrite_nodes(&ctx->rewriter, oargs), body); + Node* loop_case = case_(a, nodes(a, oargs.count, nparams)); + set_abstraction_body(loop_case, structured); + gen_loop(bb, empty(a), rewrite_nodes(&ctx->rewriter, oargs), loop_case); // we decide 'late' what the exit ladder should be inner_exit_ladder_bb->payload.basic_block.body = merge_break(a, (MergeBreak) { .args = empty(a) }); return finish_body(bb, exit_ladder); @@ -213,25 +214,26 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit_la case Branch_TAG: { const Node* condition = rewrite_node(&ctx->rewriter, body->payload.branch.condition); - const Node* true_body = handle_bb_callsite(ctx, body->payload.branch.true_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); - const Node* if_true_lam = case_(a, empty(a), true_body); + Node* true_case = case_(a, empty(a)); + set_abstraction_body(true_case, handle_bb_callsite(ctx, body->payload.branch.true_jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); - const Node* false_body = handle_bb_callsite(ctx, body->payload.branch.false_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); - const Node* if_false_lam = case_(a, empty(a), false_body); + Node* false_case = case_(a, empty(a)); + set_abstraction_body(false_case, handle_bb_callsite(ctx, body->payload.branch.false_jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); BodyBuilder* bb = begin_body(a); - gen_if(bb, empty(a), condition, if_true_lam, if_false_lam); + gen_if(bb, empty(a), condition, true_case, false_case); return finish_body(bb, exit_ladder); } case Switch_TAG: { const Node* switch_value = rewrite_node(&ctx->rewriter, body->payload.br_switch.switch_value); - const Node* default_body = handle_bb_callsite(ctx, body->payload.br_switch.default_jump, merge_selection(a, (MergeSelection) { .args = empty(a) })); - const Node* default_case = case_(a, empty(a), default_body); + Node* default_case = case_(a, empty(a)); + set_abstraction_body(default_case, handle_bb_callsite(ctx, body->payload.br_switch.default_jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); - LARRAY(const Node*, cases, body->payload.br_switch.case_jumps.count); + LARRAY(Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { - cases[i] = case_(a, empty(a), handle_bb_callsite(ctx, body->payload.br_switch.case_jumps.nodes[i], merge_selection(a, (MergeSelection) {.args = empty(a)}))); + cases[i] = case_(a, empty(a)); + set_abstraction_body(cases[i], handle_bb_callsite(ctx, body->payload.br_switch.case_jumps.nodes[i], merge_selection(a, (MergeSelection) {.args = empty(a)}))); } BodyBuilder* bb = begin_body(a); @@ -281,9 +283,9 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit_la // Wrap the tail in a guarded if, to handle 'far' joins const Node* level_value = gen_load(bb2, ctx->level_ptr); const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); - const Node* true_body = structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), merge_selection(a, (MergeSelection) { .args = empty(a) })); - const Node* if_true_lam = case_(a, empty(a), true_body); - gen_if(bb2, empty(a), guard, if_true_lam, NULL); + const Node* true_case = case_(a, empty(a)); + set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), merge_selection(a, (MergeSelection) { .args = empty(a) }))); + gen_if(bb2, empty(a), guard, true_case, NULL); return finish_body(bb_outer, structure(&control_ctx, get_abstraction_body(old_control_body), finish_body(bb2, exit_ladder))); } diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 41ee13004..7117c1582 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -161,7 +161,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .yield_types = inner_yield_types }), true), "jp_continue"); - LARRAY(const Node*, exit_wrappers, exiting_nodes_count); + LARRAY(Node*, exit_wrappers, exiting_nodes_count); LARRAY(Node*, exit_helpers, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { exit_helpers[i] = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_helper_%d", i)); @@ -178,7 +178,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { break; } case Case_TAG: - exit_wrappers[i] = case_(arena, exit_wrapper_params, jump_helper(arena, exit_helpers[i], empty(arena))); + exit_wrappers[i] = case_(arena, exit_wrapper_params); + set_abstraction_body(exit_wrappers[i], jump_helper(arena, exit_helpers[i], empty(arena))); break; default: assert(false); @@ -190,16 +191,16 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .join_point = join_token_continue, .args = continue_wrapper_params }); - const Node* continue_wrapper; + Node* continue_wrapper; switch (node->tag) { case BasicBlock_TAG: { - Node* pre_join_continue_bb = basic_block(arena, continue_wrapper_params, "continue"); - pre_join_continue_bb->payload.basic_block.body = continue_wrapper_body; - continue_wrapper = pre_join_continue_bb; + continue_wrapper = basic_block(arena, continue_wrapper_params, "continue"); + set_abstraction_body(continue_wrapper, continue_wrapper_body); break; } case Case_TAG: - continue_wrapper = case_(arena, continue_wrapper_params, continue_wrapper_body); + continue_wrapper = case_(arena, continue_wrapper_params); + set_abstraction_body(continue_wrapper, continue_wrapper_body); break; default: assert(false); @@ -270,7 +271,9 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { register_processed(rewriter, node, cached_entry); BodyBuilder* inner_bb = begin_body(arena); - Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, case_(arena, singleton(join_token_continue), loop_body)); + Node* inner_control_case = case_(arena, singleton(join_token_continue)); + set_abstraction_body(inner_control_case, loop_body); + Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); @@ -278,10 +281,12 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .target = loop_outer, .args = inner_control_results })); - gen_control(outer_bb, empty(arena), case_(arena, singleton(join_token_exit), jump(arena, (Jump) { + Node* outer_control_case = case_(arena, singleton(join_token_exit)); + set_abstraction_body(outer_control_case, jump(arena, (Jump) { .target = loop_outer, .args = nparams - }))); + })); + gen_control(outer_bb, empty(arena), outer_control_case); LARRAY(const Node*, exit_numbers, exiting_nodes_count); LARRAY(const Node*, exit_jumps, exiting_nodes_count); @@ -332,16 +337,16 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { })); } - const Node* loop_container; + Node* loop_container; switch (node->tag) { case BasicBlock_TAG: { - Node* bb = basic_block(arena, nparams, node->payload.basic_block.name); - bb->payload.basic_block.body = outer_body; - loop_container = bb; + loop_container = basic_block(arena, nparams, node->payload.basic_block.name); + set_abstraction_body(loop_container, outer_body); break; } case Case_TAG: - loop_container = case_(arena, nparams, outer_body); + loop_container = case_(arena, nparams); + set_abstraction_body(loop_container, outer_body); break; default: assert(false); @@ -502,15 +507,16 @@ static const Node* process_node(Context* ctx, const Node* node) { if (cached) register_processed(rewriter, idom, cached); - const Node* control_inner = case_(arena, singleton(join_token), inner_terminator); - const Node* recreated_join = rewrite_node(rewriter, idom); + Node* control_case = case_(arena, singleton(join_token)); + set_abstraction_body(control_case, inner_terminator); + const Node* join_target = rewrite_node(rewriter, idom); switch (idom->tag) { case BasicBlock_TAG: { BodyBuilder* bb = begin_body(arena); - Nodes results = gen_control(bb, yield_types, control_inner); + Nodes results = gen_control(bb, yield_types, control_case); return finish_body(bb, jump(arena, (Jump) { - .target = recreated_join, + .target = join_target, .args = results })); } diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index ae20b21a7..be9e01187 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -372,9 +372,10 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { Nodes params = recreate_params(rewriter, node->payload.case_.params); register_processed_list(rewriter, node->payload.case_.params, params); const Node* nterminator = rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.case_.body); - const Node* nlam = case_(rewriter->dst_arena, params, nterminator); + Node* ncase = case_(rewriter->dst_arena, params); + set_abstraction_body(ncase, nterminator); // register_processed(rewriter, node, nlam); - return nlam; + return ncase; } case BasicBlock_TAG: { Nodes params = recreate_params(rewriter, node->payload.basic_block.params); From 1671338b930590bc86359a719da41eb816aa3c1e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 11:47:25 +0200 Subject: [PATCH 404/693] spv: simplify emit_instruction signature --- src/backend/spirv/emit_spv.c | 4 +-- src/backend/spirv/emit_spv.h | 2 +- src/backend/spirv/emit_spv_instructions.c | 36 +++++++++++------------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index ff0bf4054..129cf5daf 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -130,7 +130,7 @@ SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { const Node* init_value = resolve_node_to_definition(decl->payload.constant.instruction, (NodeResolveConfig) { 0 }); if (!init_value && bb_builder) { SpvId r; - emit_instruction(emitter, NULL, &bb_builder, NULL, decl->payload.constant.instruction, 1, &r); + emit_instruction(emitter, NULL, bb_builder, decl->payload.constant.instruction, 1, &r); return r; } assert(init_value && "TODO: support some measure of constant expressions"); @@ -389,7 +389,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo const Node* instruction = terminator->payload.let.instruction; Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction->type); LARRAY(SpvId, results, types.count); - emit_instruction(emitter, fn_builder, &basic_block_builder, &merge_targets, instruction, types.count, results); + emit_instruction(emitter, fn_builder, basic_block_builder, instruction, types.count, results); for (size_t i = 0; i < types.count; i++) register_result(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index 03bf4ee6c..9f6b7dbac 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -41,7 +41,7 @@ typedef struct { SpvId emit_decl(Emitter*, const Node*); SpvId emit_type(Emitter*, const Type*); SpvId emit_value(Emitter*, BBBuilder, const Node*); -void emit_instruction(Emitter*, FnBuilder, BBBuilder*, MergeTargets*, const Node* instruction, size_t results_count, SpvId results[]); +void emit_instruction(Emitter*, FnBuilder, BBBuilder, const Node* instruction, size_t results_count, SpvId results[]); void emit_terminator(Emitter*, FnBuilder, BBBuilder, MergeTargets, const Node* terminator); SpvId find_reserved_id(Emitter* emitter, const Node* node); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 7aef906f1..4857f90d5 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -249,7 +249,7 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui SpvId local_id; const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); // TODO: very hacky indeed - emit_instruction(emitter, fn_builder, &bb_builder, NULL, load(emitter->arena, (Load) { b }), 1, &local_id); + emit_instruction(emitter, fn_builder, bb_builder, load(emitter->arena, (Load) { b }), 1, &local_id); result = spvb_group_shuffle(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), scope_subgroup, emit_value(emitter, bb_builder, first(args)), local_id); spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); } else { @@ -375,7 +375,7 @@ static void emit_leaf_call(Emitter* emitter, SHADY_UNUSED FnBuilder fn_builder, } } -void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, const Node* instruction, size_t results_count, SpvId results[]) { +void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, const Node* instruction, size_t results_count, SpvId results[]) { assert(is_instruction(instruction)); switch (is_instruction(instruction)) { @@ -390,8 +390,8 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_BindIdentifiers_TAG: case Instruction_StackAlloc_TAG: case Instruction_Block_TAG: error("Should be lowered elsewhere") - case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, *bb_builder, instruction->payload.call, results_count, results); break; - case PrimOp_TAG: emit_primop(emitter, fn_builder, *bb_builder, instruction, results_count, results); break; + case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call, results_count, results); break; + case PrimOp_TAG: emit_primop(emitter, fn_builder, bb_builder, instruction, results_count, results); break; case Comment_TAG: break; case Instruction_CompoundInstruction_TAG: { Nodes instructions = instruction->payload.compound_instruction.instructions; @@ -402,11 +402,11 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, instruction2->type); LARRAY(SpvId, results2, yield_types.count); - emit_instruction(emitter, fn_builder, bb_builder, merge_targets, instruction2, yield_types.count, results2); + emit_instruction(emitter, fn_builder, bb_builder, instruction2, yield_types.count, results2); } Nodes results2 = instruction->payload.compound_instruction.results; for (size_t i = 0; i < results2.count; i++) { - results[0] = emit_value(emitter, *bb_builder, results2.nodes[i]); + results[0] = emit_value(emitter, bb_builder, results2.nodes[i]); } return; } @@ -436,8 +436,8 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil operands_count += 2; } - SpvId eptr = emit_value(emitter, *bb_builder, payload.ptr); - SpvId result = spvb_load(*bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); + SpvId eptr = emit_value(emitter, bb_builder, payload.ptr); + SpvId result = spvb_load(bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); assert(results_count == 1); results[0] = result; return; @@ -459,29 +459,29 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil operands_count += 2; } - SpvId eptr = emit_value(emitter, *bb_builder, payload.ptr); - SpvId eval = emit_value(emitter, *bb_builder, payload.value); - spvb_store(*bb_builder, eval, eptr, operands_count, operands); + SpvId eptr = emit_value(emitter, bb_builder, payload.ptr); + SpvId eval = emit_value(emitter, bb_builder, payload.value); + spvb_store(bb_builder, eval, eptr, operands_count, operands); assert(results_count == 0); return; } case Lea_TAG: { Lea payload = instruction->payload.lea; - SpvId base = emit_value(emitter, *bb_builder, payload.ptr); + SpvId base = emit_value(emitter, bb_builder, payload.ptr); LARRAY(SpvId, indices, payload.indices.count); for (size_t i = 0; i < payload.indices.count; i++) - indices[i] = payload.indices.nodes[i] ? emit_value(emitter, *bb_builder, payload.indices.nodes[i]) : 0; + indices[i] = payload.indices.nodes[i] ? emit_value(emitter, bb_builder, payload.indices.nodes[i]) : 0; const IntLiteral* known_offset = resolve_to_int_literal(payload.offset); if (known_offset && known_offset->value == 0) { const Type* target_type = instruction->type; - SpvId result = spvb_access_chain(*bb_builder, emit_type(emitter, target_type), base, payload.indices.count, indices); + SpvId result = spvb_access_chain(bb_builder, emit_type(emitter, target_type), base, payload.indices.count, indices); assert(results_count == 1); results[0] = result; } else { const Type* target_type = instruction->type; - SpvId result = spvb_ptr_access_chain(*bb_builder, emit_type(emitter, target_type), base, emit_value(emitter, *bb_builder, payload.offset), payload.indices.count, indices); + SpvId result = spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, emit_value(emitter, bb_builder, payload.offset), payload.indices.count, indices); assert(results_count == 1); results[0] = result; } @@ -490,10 +490,10 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil case Instruction_DebugPrintf_TAG: { SpvId set_id = get_extended_instruction_set(emitter, "NonSemantic.DebugPrintf"); LARRAY(SpvId, args, instruction->payload.debug_printf.args.count + 1); - args[0] = emit_value(emitter, *bb_builder, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); + args[0] = emit_value(emitter, bb_builder, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) - args[i + 1] = emit_value(emitter, *bb_builder, instruction->payload.debug_printf.args.nodes[i]); - spvb_ext_instruction(*bb_builder, emit_type(emitter, instruction->type), set_id, (SpvOp) NonSemanticDebugPrintfDebugPrintf, instruction->payload.debug_printf.args.count + 1, args); + args[i + 1] = emit_value(emitter, bb_builder, instruction->payload.debug_printf.args.nodes[i]); + spvb_ext_instruction(bb_builder, emit_type(emitter, instruction->type), set_id, (SpvOp) NonSemanticDebugPrintfDebugPrintf, instruction->payload.debug_printf.args.count + 1, args); } } } From a43deff4b79e810a346ec2f4283fdd0a1c208680 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 12:27:52 +0200 Subject: [PATCH 405/693] disable mem2reg --- src/shady/passes/opt_mem2reg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 8aa3618e9..16e81c787 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -716,6 +716,8 @@ static const Node* process(Context* ctx, const Node* old) { RewritePass cleanup; Module* opt_mem2reg(const CompilerConfig* config, Module* src) { + return src; + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); IrArena* initial_arena = get_module_arena(src); IrArena* a = new_ir_arena(&aconfig); From aa0cf5120508b343906aee932dbf685cdb0776f0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 12:28:22 +0200 Subject: [PATCH 406/693] use basic blocks for structural exits --- include/shady/grammar.json | 10 +++++----- src/backend/spirv/emit_spv.c | 2 ++ src/shady/analysis/cfg.c | 13 +++++-------- src/shady/analysis/cfg.h | 2 +- src/shady/analysis/cfg_dump.c | 2 +- src/shady/body_builder.c | 8 ++++---- src/shady/passes/bind.c | 6 ++++-- src/shady/passes/cleanup.c | 2 ++ src/shady/passes/infer.c | 8 +++++--- src/shady/passes/opt_mem2reg.c | 2 +- 10 files changed, 30 insertions(+), 25 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 5a38af372..58d3b8aea 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -120,7 +120,7 @@ { "name": "structured_construct", "ops": [ - { "name": "tail", "class": "case" } + { "name": "tail", "class": "basic_block" } ] } ], @@ -382,7 +382,7 @@ { "name": "condition", "class": "value" }, { "name": "if_true", "class": "case" }, { "name": "if_false", "class": "case", "nullable": true }, - { "name": "tail", "class": "case" } + { "name": "tail", "class": "basic_block" } ] }, { @@ -395,7 +395,7 @@ { "name": "literals", "class": "value", "list": true }, { "name": "cases", "class": "case", "list": true }, { "name": "default_case", "class": "case" }, - { "name": "tail", "class": "case" } + { "name": "tail", "class": "basic_block" } ] }, { @@ -406,7 +406,7 @@ { "name": "yield_types", "class": "type", "list": true }, { "name": "body", "class": "case" }, { "name": "initial_args", "class": "value", "list": true }, - { "name": "tail", "class": "case" } + { "name": "tail", "class": "basic_block" } ] }, { @@ -415,7 +415,7 @@ "ops": [ { "name": "yield_types", "class": "type", "list": true }, { "name": "inside", "class": "case" }, - { "name": "tail", "class": "case" } + { "name": "tail", "class": "basic_block" } ] }, { diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 129cf5daf..2fd96549b 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -533,6 +533,8 @@ static void emit_function(Emitter* emitter, const Node* node) { assert(cfnode == cfg->entry); if (is_case(cfnode->node)) continue; + if (entries_count_list(cfnode->pred_edges) == 1 && read_list(CFEdge, cfnode->pred_edges)[0].type == StructuredTailEdge) + continue; emit_basic_block(emitter, fn_builder, cfg, cfnode); } diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index e63768c6b..d24d4bbfc 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -100,13 +100,10 @@ static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { return false; } -static bool is_structural_edge(CFEdgeType edge_type) { return edge_type != JumpEdge; } - /// Adds an edge to somewhere inside a basic block static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFEdgeType type) { assert(is_abstraction(src) && is_abstraction(dst)); assert(!is_function(dst)); - assert(is_structural_edge(type) == (bool) is_case(dst)); if (ctx->lt && !in_loop(ctx->lt, ctx->entry, dst)) return; if (ctx->lt && dst == ctx->entry) { @@ -178,24 +175,24 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); if (terminator->payload.if_instr.if_false) add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; case Match_TAG: for (size_t i = 0; i < terminator->payload.match_instr.cases.count; i++) add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; case Loop_TAG: add_structural_dominance_edge(ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; case Control_TAG: add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); insert_dict(const Node*, CFNode*, ctx->join_point_values, param, let_tail_cfnode); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredPseudoExitEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; case MergeSelection_TAG: case MergeContinue_TAG: @@ -297,7 +294,7 @@ static void validate_cfg(CFG* cfg) { case StructuredEnterBodyEdge: structured_body_uses += 1; break; - case StructuredPseudoExitEdge: + case StructuredTailEdge: structured_body_uses += 1; case StructuredLeaveBodyEdge: break; diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index eb9cac35e..c63ff781b 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -14,7 +14,7 @@ typedef enum { /// tail of the enclosing let, which would make it look like dead code. /// This edge type accounts for that risk, they can be ignored where more precise info is available /// (see is_control_static for example) - StructuredPseudoExitEdge, + StructuredTailEdge, } CFEdgeType; typedef struct { diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index acd8133b4..4bb2f6f4d 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -127,7 +127,7 @@ static void dump_cfg(FILE* output, CFG* cfg) { case LetTailEdge: edge_color = "green"; break; case StructuredEnterBodyEdge: edge_color = "blue"; break; case StructuredLeaveBodyEdge: edge_color = "red"; break; - case StructuredPseudoExitEdge: edge_color = "darkred"; break; + case StructuredTailEdge: edge_color = "darkred"; break; default: break; } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 0fe33848b..d766346db 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -92,28 +92,28 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { terminator = let(a, entry.structured.payload.let.instruction, terminator); break; case Structured_construct_If_TAG: { - Node* tail = case_(bb->arena, entry.vars); + Node* tail = basic_block(bb->arena, entry.vars, NULL); set_abstraction_body(tail, terminator); entry.structured.payload.if_instr.tail = tail; terminator = if_instr(a, entry.structured.payload.if_instr); break; } case Structured_construct_Match_TAG: { - Node* tail = case_(bb->arena, entry.vars); + Node* tail = basic_block(bb->arena, entry.vars, NULL); set_abstraction_body(tail, terminator); entry.structured.payload.match_instr.tail = tail; terminator = match_instr(a, entry.structured.payload.match_instr); break; } case Structured_construct_Loop_TAG: { - Node* tail = case_(bb->arena, entry.vars); + Node* tail = basic_block(bb->arena, entry.vars, NULL); set_abstraction_body(tail, terminator); entry.structured.payload.loop_instr.tail = tail; terminator = loop_instr(a, entry.structured.payload.loop_instr); break; } case Structured_construct_Control_TAG: { - Node* tail = case_(bb->arena, entry.vars); + Node* tail = basic_block(bb->arena, entry.vars, NULL); set_abstraction_body(tail, terminator); entry.structured.payload.control.tail = tail; terminator = control(a, entry.structured.payload.control); diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 0f0595c6f..ba2e77488 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -254,10 +254,12 @@ static const Node* bind_node(Context* ctx, const Node* node) { case BasicBlock_TAG: { assert(is_basic_block(node)); Nodes new_bb_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); - Node* new_bb = basic_block(a, new_bb_params, node->payload.basic_block.name); + String name = node->payload.basic_block.name; + Node* new_bb = basic_block(a, new_bb_params, name); Context bb_ctx = *ctx; ctx = &bb_ctx; - add_binding(ctx, false, node->payload.basic_block.name, new_bb); + if (name) + add_binding(ctx, false, name, new_bb); register_processed(&ctx->rewriter, node, new_bb); register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new_bb_params); new_bb->payload.basic_block.body = rewrite_node(&ctx->rewriter, node->payload.basic_block.body); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index dd9888462..833136913 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -27,6 +27,8 @@ static size_t count_calls(const UsesMap* map, const Node* bb) { count++; } } + if (is_structured_construct(use->user) && use->operand_class == NcBasic_block) + count+=2; } return count; } diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 31d3513f7..1227e163a 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -461,7 +461,8 @@ static const Node* infer_if(Context* ctx, const Node* node) { .condition = condition, .if_true = true_body, .if_false = false_body, - .tail = infer_case(ctx, node->payload.if_instr.tail, expected_join_types) + //.tail = infer_case(ctx, node->payload.if_instr.tail, expected_join_types) + .tail = infer(ctx, node->payload.if_instr.tail, NULL) }); } @@ -495,7 +496,8 @@ static const Node* infer_loop(Context* ctx, const Node* node) { .yield_types = loop_yield_types, .initial_args = nodes(a, old_params.count, new_initial_args), .body = nbody, - .tail = infer_case(ctx, node->payload.loop_instr.tail, qual_yield_types) + //.tail = infer_case(ctx, node->payload.loop_instr.tail, qual_yield_types) + .tail = infer(ctx, node->payload.loop_instr.tail, NULL) }); } @@ -522,7 +524,7 @@ static const Node* infer_control(Context* ctx, const Node* node) { return control(a, (Control) { .yield_types = yield_types, .inside = new_case, - .tail = infer_case(ctx, get_structured_construct_tail(node), add_qualifiers(a, yield_types, false)) + .tail = infer(ctx, get_structured_construct_tail(node), NULL /*add_qualifiers(a, yield_types, false)*/) }); } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 16e81c787..242a35380 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -535,7 +535,7 @@ static void handle_bb(Context* ctx, const Node* old) { // check if all the edges have a value for this! for (size_t j = 0; j < entries_count_list(cfnode->pred_edges); j++) { CFEdge edge = read_list(CFEdge, cfnode->pred_edges)[j]; - if (edge.type == StructuredPseudoExitEdge) + if (edge.type == StructuredTailEdge) continue; // these are not real edges... KnowledgeBase* kb_at_src = get_kb(ctx, edge.src->node); if (!kb_at_src) { From 6b54ecff044ea6bb4437433d3afc30bcb8179945 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 17:12:55 +0200 Subject: [PATCH 407/693] removed Case node --- include/shady/grammar.json | 32 ++------- include/shady/ir.h | 6 +- src/backend/spirv/emit_spv.c | 35 ++++------ src/shady/analysis/callgraph.c | 3 +- src/shady/analysis/cfg.c | 63 +++++++++++------ src/shady/analysis/cfg.h | 3 +- src/shady/analysis/cfg_dump.c | 77 ++++++++------------- src/shady/analysis/free_variables.c | 1 - src/shady/analysis/leak.c | 15 +++- src/shady/analysis/leak.h | 2 + src/shady/constructors.c | 49 ------------- src/shady/fold.c | 4 +- src/shady/node.c | 14 ++-- src/shady/passes/bind.c | 25 +++---- src/shady/passes/cleanup.c | 8 +-- src/shady/passes/infer.c | 21 +++--- src/shady/passes/lift_indirect_targets.c | 3 +- src/shady/passes/lower_cf_instrs.c | 15 ++-- src/shady/passes/mark_leaf_functions.c | 16 ++--- src/shady/passes/normalize.c | 17 +---- src/shady/passes/opt_mem2reg.c | 2 +- src/shady/passes/opt_restructure.c | 1 - src/shady/passes/reconvergence_heuristics.c | 16 ----- src/shady/print.c | 19 +---- src/shady/rewrite.c | 9 --- src/shady/type.c | 10 +-- src/shady/visit.h | 2 +- 27 files changed, 161 insertions(+), 307 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 58d3b8aea..ae58715f5 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -101,9 +101,6 @@ { "name": "name", "class": "string" } ] }, - { - "name": "case" - }, { "name": "basic_block" }, @@ -380,8 +377,8 @@ "ops": [ { "name": "yield_types", "class": "type", "list": true }, { "name": "condition", "class": "value" }, - { "name": "if_true", "class": "case" }, - { "name": "if_false", "class": "case", "nullable": true }, + { "name": "if_true", "class": "basic_block" }, + { "name": "if_false", "class": "basic_block", "nullable": true }, { "name": "tail", "class": "basic_block" } ] }, @@ -393,8 +390,8 @@ { "name": "yield_types", "class": "type", "list": true }, { "name": "inspect", "class": "value" }, { "name": "literals", "class": "value", "list": true }, - { "name": "cases", "class": "case", "list": true }, - { "name": "default_case", "class": "case" }, + { "name": "cases", "class": "basic_block", "list": true }, + { "name": "default_case", "class": "basic_block" }, { "name": "tail", "class": "basic_block" } ] }, @@ -404,7 +401,7 @@ "class": ["terminator", "structured_construct"], "ops": [ { "name": "yield_types", "class": "type", "list": true }, - { "name": "body", "class": "case" }, + { "name": "body", "class": "basic_block" }, { "name": "initial_args", "class": "value", "list": true }, { "name": "tail", "class": "basic_block" } ] @@ -414,7 +411,7 @@ "class": ["terminator", "structured_construct"], "ops": [ { "name": "yield_types", "class": "type", "list": true }, - { "name": "inside", "class": "case" }, + { "name": "inside", "class": "basic_block" }, { "name": "tail", "class": "basic_block" } ] }, @@ -424,7 +421,7 @@ "description": "Used as a helper to insert multiple instructions in place of one", "ops": [ { "name": "yield_types", "class": "type", "list": true }, - { "name": "inside", "class": "case" } + { "name": "inside", "class": "basic_block" } ] }, { @@ -668,21 +665,6 @@ { "name": "name", "class": "string" } ] }, - { - "name": "Case", - "snake_name": "case_", - "constructor": "custom", - "class": "case", - "nominal": true, - "description": [ - "An unnamed abstraction that lives inside a function, and can be used as part of various control-flow constructs" - ], - "ops": [ - { "name": "params", "class": "param", "list": true }, - { "name": "body", "class": "terminator", "nullable": true }, - { "name": "structured_construct", "type": "const Node*", "ignored": true } - ] - }, { "name": "Unbound", "description": "Unbound identifier, obtained by parsing a file", diff --git a/include/shady/ir.h b/include/shady/ir.h index 80f102e42..320c39ed5 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -266,9 +266,11 @@ Node* constant (Module*, Nodes annotations, const Type*, const char* name); Node* global_var (Module*, Nodes annotations, const Type*, String, AddressSpace); Type* nominal_type(Module*, Nodes annotations, String name); -// basic blocks, lambdas and their helpers +// basic blocks Node* basic_block(IrArena*, Nodes params, const char* name); -Node* case_(IrArena* a, Nodes params); +static inline Node* case_(IrArena* a, Nodes params) { + return basic_block(a, params, NULL); +} /// Used to build a chain of let typedef struct BodyBuilder_ BodyBuilder; diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 2fd96549b..79162052b 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -207,13 +207,11 @@ static void emit_if(Emitter* emitter, FnBuilder fn_builder, BBBuilder* pbb_build BBBuilder true_bb = spvb_begin_bb(fn_builder, true_id); spvb_add_bb(fn_builder, true_bb); - assert(is_case(if_instr.if_true)); - emit_terminator(emitter, fn_builder, true_bb, merge_targets_branches, if_instr.if_true->payload.case_.body); + emit_terminator(emitter, fn_builder, true_bb, merge_targets_branches, get_abstraction_body(if_instr.if_true)); if (if_instr.if_false) { BBBuilder false_bb = spvb_begin_bb(fn_builder, false_id); spvb_add_bb(fn_builder, false_bb); - assert(is_case(if_instr.if_false)); - emit_terminator(emitter, fn_builder, false_bb, merge_targets_branches, if_instr.if_false->payload.case_.body); + emit_terminator(emitter, fn_builder, false_bb, merge_targets_branches, get_abstraction_body(if_instr.if_false)); } spvb_add_bb(fn_builder, join_bb); @@ -269,15 +267,13 @@ static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_bui for (size_t i = 0; i < match.cases.count; i++) { BBBuilder case_bb = spvb_begin_bb(fn_builder, literals_and_cases[i * literal_case_entry_size + literal_width]); - const Node* case_body = match.cases.nodes[i]; - assert(is_case(case_body)); + const Node* case_ = match.cases.nodes[i]; spvb_add_bb(fn_builder, case_bb); - emit_terminator(emitter, fn_builder, case_bb, merge_targets_branches, case_body->payload.case_.body); + emit_terminator(emitter, fn_builder, case_bb, merge_targets_branches, get_abstraction_body(case_)); } BBBuilder default_bb = spvb_begin_bb(fn_builder, default_id); - assert(is_case(match.default_case)); spvb_add_bb(fn_builder, default_bb); - emit_terminator(emitter, fn_builder, default_bb, merge_targets_branches, match.default_case->payload.case_.body); + emit_terminator(emitter, fn_builder, default_bb, merge_targets_branches, get_abstraction_body(match.default_case)); spvb_add_bb(fn_builder, join_bb); *bb_builder = join_bb; @@ -288,9 +284,8 @@ static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_bui static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Loop loop_instr) { Nodes yield_types = loop_instr.yield_types; - const Node* body = loop_instr.body; - assert(is_case(body)); - Nodes body_params = body->payload.case_.params; + const Node* loop_inside = loop_instr.body; + Nodes loop_params = get_abstraction_params(loop_inside); // First we create all the basic blocks we'll need SpvId header_id = spvb_fresh_id(emitter->file_builder); @@ -322,9 +317,9 @@ static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil } // Wire up the phi nodes for the loop contents - LARRAY(SpvbPhi*, loop_continue_phis, body_params.count); - for (size_t i = 0; i < body_params.count; i++) { - SpvId loop_param_type = emit_type(emitter, get_unqualified_type(body_params.nodes[i]->type)); + LARRAY(SpvbPhi*, loop_continue_phis, loop_params.count); + for (size_t i = 0; i < loop_params.count; i++) { + SpvId loop_param_type = emit_type(emitter, get_unqualified_type(loop_params.nodes[i]->type)); SpvId continue_phi_id = spvb_fresh_id(emitter->file_builder); SpvbPhi* continue_phi = spvb_add_phi(continue_builder, loop_param_type, continue_phi_id); @@ -337,7 +332,7 @@ static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil SpvId param_initial_value = emit_value(emitter, *bb_builder, loop_instr.initial_args.nodes[i]); spvb_add_phi_source(loop_param_phi, get_block_builder_id(*bb_builder), param_initial_value); spvb_add_phi_source(loop_param_phi, get_block_builder_id(continue_builder), continue_phi_id); - register_result(emitter, body_params.nodes[i], loop_param_id); + register_result(emitter, loop_params.nodes[i], loop_param_id); } // The current block goes to the header (it can't be the header itself !) @@ -355,7 +350,7 @@ static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_buil merge_targets_branches.continue_phis = loop_continue_phis; merge_targets_branches.break_target = next_id; merge_targets_branches.break_phis = loop_break_phis; - emit_terminator(emitter, fn_builder, body_builder, merge_targets_branches, body->payload.case_.body); + emit_terminator(emitter, fn_builder, body_builder, merge_targets_branches, get_abstraction_body(loop_inside)); // the continue block just jumps back into the header spvb_branch(continue_builder, header_id); @@ -507,7 +502,7 @@ static void emit_function(Emitter* emitter, const Node* node) { CFNode* cfnode = read_list(CFNode*, cfg->contents)[i]; assert(cfnode); const Node* bb = cfnode->node; - if (is_case(bb)) + if (is_cfnode_structural_target(cfnode)) continue; assert(is_basic_block(bb) || bb == node); SpvId bb_id = spvb_fresh_id(emitter->file_builder); @@ -531,9 +526,7 @@ static void emit_function(Emitter* emitter, const Node* node) { CFNode* cfnode = cfg->rpo[i]; if (i == 0) assert(cfnode == cfg->entry); - if (is_case(cfnode->node)) - continue; - if (entries_count_list(cfnode->pred_edges) == 1 && read_list(CFEdge, cfnode->pred_edges)[0].type == StructuredTailEdge) + if (is_cfnode_structural_target(cfnode)) continue; emit_basic_block(emitter, fn_builder, cfg, cfnode); } diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index 78bcee923..d4e29636e 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -65,8 +65,7 @@ static void search_for_callsites(CGVisitor* visitor, const Node* node) { // analyze_fn(visitor->graph, node)->is_address_captured = true; break; } - case BasicBlock_TAG: - case Case_TAG: { + case BasicBlock_TAG: { const Node* old_abs = visitor->abs; visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK, node); visitor->abs = old_abs; diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index d24d4bbfc..fc1d8ea0d 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -12,6 +12,8 @@ #include #include +#pragma GCC diagnostic error "-Wswitch" + struct List* build_cfgs(Module* mod) { struct List* cfgs = new_list(CFG*); @@ -280,29 +282,42 @@ static void flip_cfg(CFG* cfg) { static void validate_cfg(CFG* cfg) { for (size_t i = 0; i < cfg->size; i++) { CFNode* node = read_list(CFNode*, cfg->contents)[i]; - if (is_case(node->node)) { - size_t structured_body_uses = 0; - for (size_t j = 0; j < entries_count_list(node->pred_edges); j++) { - CFEdge edge = read_list(CFEdge, node->pred_edges)[j]; - switch (edge.type) { - case JumpEdge: - error_print("Error: cases cannot be jumped to directly."); - error_die(); - case LetTailEdge: - structured_body_uses += 1; - break; - case StructuredEnterBodyEdge: - structured_body_uses += 1; - break; - case StructuredTailEdge: - structured_body_uses += 1; - case StructuredLeaveBodyEdge: - break; - } + size_t structured_body_uses = 0; + size_t num_jumps = 0; + size_t num_exits = 0; + bool is_tail = false; + for (size_t j = 0; j < entries_count_list(node->pred_edges); j++) { + CFEdge edge = read_list(CFEdge, node->pred_edges)[j]; + switch (edge.type) { + case JumpEdge: + num_jumps++; + break; + case StructuredEnterBodyEdge: + structured_body_uses += 1; + break; + case StructuredTailEdge: + structured_body_uses += 1; + is_tail = true; + break; + case StructuredLeaveBodyEdge: + num_exits += 1; + break; } - if (structured_body_uses != 1 && node != cfg->entry /* this exception exists since we might build CFGs rooted in cases */) { - error_print("reachable cases must be used be as bodies exactly once (actual uses: %zu)", structured_body_uses); - error_die(); + } + if (node != cfg->entry /* this exception exists since we might build CFGs rooted in cases */) { + if (structured_body_uses > 0) { + if (structured_body_uses > 1) { + error_print("Basic block %s is used as a structural target more than once (structured_body_uses: %zu)", get_abstraction_name_safe(node->node), structured_body_uses); + error_die(); + } + if (num_jumps > 0) { + error_print("Basic block %s is used as structural target, but is also jumped into (num_jumps: %zu)", get_abstraction_name_safe(node->node), num_jumps); + error_die(); + } + if (!is_tail && num_exits > 0) { + error_print("Basic block %s is not a merge target yet is used as once (num_exits: %zu)", get_abstraction_name_safe(node->node), num_exits); + error_die(); + } } } } @@ -407,6 +422,10 @@ void compute_rpo(CFG* cfg) { // debug_print("\n"); } +bool is_cfnode_structural_target(CFNode* cfn) { + return entries_count_list(cfn->pred_edges) == 1 && read_list(CFEdge, cfn->pred_edges)[0].type != JumpEdge; +} + CFNode* least_common_ancestor(CFNode* i, CFNode* j) { assert(i && j); while (i->rpo_index != j->rpo_index) { diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index c63ff781b..134adadc3 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -7,7 +7,6 @@ typedef struct CFNode_ CFNode; typedef enum { JumpEdge, - LetTailEdge, StructuredEnterBodyEdge, StructuredLeaveBodyEdge, /// Join points might leak, and as a consequence, there might be no static edge to the @@ -99,6 +98,8 @@ CFNode* cfg_lookup(CFG* cfg, const Node* abs); void compute_rpo(CFG*); void compute_domtree(CFG*); +bool is_cfnode_structural_target(CFNode*); + CFNode* least_common_ancestor(CFNode* i, CFNode* j); void destroy_cfg(CFG* cfg); diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 4bb2f6f4d..aefff4df0 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -13,18 +13,6 @@ static int extra_uniqueness = 0; -static CFNode* get_let_pred(const CFNode* n) { - if (entries_count_list(n->pred_edges) == 1) { - CFEdge pred = read_list(CFEdge, n->pred_edges)[0]; - assert(pred.dst == n); - if (pred.type == LetTailEdge && entries_count_list(pred.src->succ_edges) == 1) { - assert(is_case(n->node)); - return pred.src; - } - } - return NULL; -} - static void print_node_helper(Printer* p, const Node* n) { Growy* tmp_g = new_growy(); Printer* tmp_p = open_growy_as_printer(tmp_g); @@ -50,33 +38,22 @@ static void dump_cf_node(FILE* output, const CFNode* n) { const Node* body = get_abstraction_body(bb); if (!body) return; - if (get_let_pred(n)) - return; String color = "black"; - if (is_case(bb)) - color = "green"; - else if (is_basic_block(bb)) + if (is_basic_block(bb)) color = "blue"; Growy* g = new_growy(); Printer* p = open_growy_as_printer(g); - String abs_name = get_abstraction_name_unsafe(bb); - if (!abs_name) - abs_name = format_string_interned(bb->arena, "%%%d", bb->id); + String abs_name = get_abstraction_name_safe(bb); print(p, "%s: \n%s: ", abs_name, abs_name); - const CFNode* let_chain_end = n; while (body->tag == Let_TAG) { - if (entries_count_list(let_chain_end->succ_edges) != 1 || read_list(CFEdge, let_chain_end->succ_edges)[0].type != LetTailEdge) - break; - print_node_helper(p, body); print(p, "\\l"); - let_chain_end = read_list(CFEdge, let_chain_end->succ_edges)[0].dst; body = body->payload.let.in; } @@ -87,19 +64,19 @@ static void dump_cf_node(FILE* output, const CFNode* n) { fprintf(output, "bb_%zu [nojustify=true, label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); free((void*) label); - for (size_t i = 0; i < entries_count_list(n->dominates); i++) { - CFNode* d = read_list(CFNode*, n->dominates)[i]; - if (!find_key_dict(const Node*, n->structurally_dominates, d->node)) - dump_cf_node(output, d); - } + //for (size_t i = 0; i < entries_count_list(n->dominates); i++) { + // CFNode* d = read_list(CFNode*, n->dominates)[i]; + // if (!find_key_dict(const Node*, n->structurally_dominates, d->node)) + // dump_cf_node(output, d); + //} } static void dump_cfg(FILE* output, CFG* cfg) { extra_uniqueness++; const Node* entry = cfg->entry->node; - fprintf(output, "subgraph cluster_%s {\n", get_abstraction_name(entry)); - fprintf(output, "label = \"%s\";\n", get_abstraction_name(entry)); + fprintf(output, "subgraph cluster_%s {\n", get_abstraction_name_safe(entry)); + fprintf(output, "label = \"%s\";\n", get_abstraction_name_safe(entry)); for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { const CFNode* n = read_list(const CFNode*, cfg->contents)[i]; dump_cf_node(output, n); @@ -107,24 +84,12 @@ static void dump_cfg(FILE* output, CFG* cfg) { for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { const CFNode* bb_node = read_list(const CFNode*, cfg->contents)[i]; const CFNode* src_node = bb_node; - while (true) { - const CFNode* let_parent = get_let_pred(src_node); - if (let_parent) - src_node = let_parent; - else - break; - } for (size_t j = 0; j < entries_count_list(bb_node->succ_edges); j++) { CFEdge edge = read_list(CFEdge, bb_node->succ_edges)[j]; const CFNode* target_node = edge.dst; - - if (edge.type == LetTailEdge && get_let_pred(target_node) == bb_node) - continue; - String edge_color = "black"; switch (edge.type) { - case LetTailEdge: edge_color = "green"; break; case StructuredEnterBodyEdge: edge_color = "blue"; break; case StructuredLeaveBodyEdge: edge_color = "red"; break; case StructuredTailEdge: edge_color = "darkred"; break; @@ -137,6 +102,24 @@ static void dump_cfg(FILE* output, CFG* cfg) { fprintf(output, "}\n"); } +void dump_existing_cfg_auto(CFG* cfg) { + FILE* f = fopen("cfg.dot", "wb"); + fprintf(f, "digraph G {\n"); + dump_cfg(f, cfg); + fprintf(f, "}\n"); + fclose(f); +} + +void dump_cfg_auto(const Node* fn) { + FILE* f = fopen("cfg.dot", "wb"); + fprintf(f, "digraph G {\n"); + CFG* cfg = build_fn_cfg(fn); + dump_cfg(f, cfg); + destroy_cfg(cfg); + fprintf(f, "}\n"); + fclose(f); +} + void dump_cfgs(FILE* output, Module* mod) { if (output == NULL) output = stderr; @@ -152,14 +135,14 @@ void dump_cfgs(FILE* output, Module* mod) { fprintf(output, "}\n"); } -void dump_cfg_auto(Module* mod) { +void dump_cfgs_auto(Module* mod) { FILE* f = fopen("cfg.dot", "wb"); dump_cfgs(f, mod); fclose(f); } static void dump_domtree_cfnode(Printer* p, CFNode* idom) { - String name = get_abstraction_name_unsafe(idom->node); + String name = get_abstraction_name_safe(idom->node); if (name) print(p, "bb_%zu [label=\"%s\", shape=box];\n", (size_t) idom, name); else @@ -173,7 +156,7 @@ static void dump_domtree_cfnode(Printer* p, CFNode* idom) { } void dump_domtree_cfg(Printer* p, CFG* s) { - print(p, "subgraph cluster_%s {\n", get_abstraction_name(s->entry->node)); + print(p, "subgraph cluster_%s {\n", get_abstraction_name_safe(s->entry->node)); dump_domtree_cfnode(p, s->entry); print(p, "}\n"); } diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index ebc50ea0b..179079d5b 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -91,7 +91,6 @@ static void search_op_for_free_variables(Context* visitor, NodeClass class, Stri break; } case Function_TAG: - case Case_TAG: case BasicBlock_TAG: assert(false); default: break; } diff --git a/src/shady/analysis/leak.c b/src/shady/analysis/leak.c index 9391e1068..179b0e007 100644 --- a/src/shady/analysis/leak.c +++ b/src/shady/analysis/leak.c @@ -23,7 +23,6 @@ void visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, Visit bool is_control_static(const UsesMap* map, const Node* control) { assert(control->tag == Control_TAG); const Node* inside = control->payload.control.inside; - assert(is_case(inside)); const Node* jp = first(get_abstraction_params(inside)); bool found_binding_abs = false; @@ -42,3 +41,17 @@ bool is_control_static(const UsesMap* map, const Node* control) { assert(found_binding_abs); return true; } + +const Node* get_control_for_jp(const UsesMap* map, const Node* jp) { + assert(is_param(jp)); + const Node* abs = jp->payload.param.abs; + assert(is_abstraction(abs)); + + const Use* use = get_first_use(map, abs); + for (;use; use = use->next_use) { + if (use->user->tag == Control_TAG && use->operand_class == NcBasic_block && strcmp(use->operand_name, "inside") == 0) + return use->user; + } + + return NULL; +} diff --git a/src/shady/analysis/leak.h b/src/shady/analysis/leak.h index bc32c163e..24b860207 100644 --- a/src/shady/analysis/leak.h +++ b/src/shady/analysis/leak.h @@ -10,5 +10,7 @@ typedef void (VisitEnclosingAbsCallback)(void*, const Use*); void visit_enclosing_abstractions(UsesMap*, const Node*, void* uptr, VisitEnclosingAbsCallback fn); bool is_control_static(const UsesMap*, const Node* control); +/// Returns the Control node that defines the join point, or NULL if it's defined by something else +const Node* get_control_for_jp(const UsesMap*, const Node* jp); #endif diff --git a/src/shady/constructors.c b/src/shady/constructors.c index f097abd5e..7971187ac 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -13,23 +13,6 @@ Strings import_strings(IrArena*, Strings); bool compare_nodes(Nodes* a, Nodes* b); -typedef struct { Visitor visitor; const Node* parent; } VisitorPCV; - -static void post_construction_validation_visit_op(VisitorPCV* v, NodeClass class, SHADY_UNUSED String op_name, const Node* node) { - if (class == NcCase) - ((Node*) node)->payload.case_.structured_construct = v->parent; -} - -static void post_construction_validation(IrArena* arena, Node* node) { - VisitorPCV v = { - .visitor = { - .visit_op_fn = (VisitOpFn) post_construction_validation_visit_op - }, - .parent = node, - }; - visit_node_operands(&v.visitor, 0, node); -} - static void pre_construction_validation(IrArena* arena, Node* node); static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { @@ -54,7 +37,6 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { if (folded != ptr) { // The folding process simplified the node, we store a mapping to that simplified node and bail out ! insert_set_get_result(Node*, arena->node_set, folded); - post_construction_validation(arena, folded); return folded; } } @@ -68,7 +50,6 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { alloc->id = allocate_node_id(arena, alloc); insert_set_get_result(const Node*, arena->node_set, alloc); - post_construction_validation(arena, alloc); return alloc; } @@ -247,36 +228,6 @@ Node* basic_block(IrArena* arena, Nodes params, const char* name) { return bb; } -Node* case_(IrArena* a, Nodes params) { - Case payload = { - .params = params, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = a, - .type = a->config.check_types ? check_type_case_(a, payload) : NULL, - .tag = Case_TAG, - .payload.case_ = payload - }; - - bool fresh; - Node* ncase = create_node_helper(a, node, &fresh); - - if (fresh || true) { - for (size_t i = 0; i < params.count; i++) { - Node* param = (Node*) params.nodes[i]; - assert(param->tag == Param_TAG); - assert(!param->payload.param.abs); - param->payload.param.abs = ncase; - param->payload.param.pindex = i; - } - } - - return ncase; -} - Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { IrArena* arena = mod->arena; Constant cnst = { diff --git a/src/shady/fold.c b/src/shady/fold.c index 01a5424f1..21b985900 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -366,7 +366,7 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { } static bool is_unreachable_case(const Node* c) { - assert(c && c->tag == Case_TAG); + assert(c && c->tag == BasicBlock_TAG); const Node* b = get_abstraction_body(c); return b->tag == Unreachable_TAG; } @@ -385,7 +385,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { case PrimOp_TAG: node = fold_prim_op(arena, node); break; case Block_TAG: { const Node* lam = node->payload.block.inside; - const Node* body = lam->payload.case_.body; + const Node* body = get_abstraction_body(lam); if (body->tag == BlockYield_TAG) { return maybe_tuple_helper(arena, body->payload.block_yield.args); } else if (body->tag == Let_TAG) { diff --git a/src/shady/node.c b/src/shady/node.c index f9637fd39..6a7e66564 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -168,7 +168,7 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi node = node->payload.ref_decl.decl; continue; case Block_TAG: { - const Node* terminator = node->payload.block.inside->payload.case_.body; + const Node* terminator = get_abstraction_body(node->payload.block.inside); while (true) { if (terminator->tag == Let_TAG) terminator = terminator->payload.let.in; @@ -272,7 +272,7 @@ const char* get_string_literal(IrArena* arena, const Node* node) { return NULL; return get_string_literal(arena, decl->payload.global_variable.init); } - return NULL; + break; } case StringLiteral_TAG: return node->payload.string_lit.string; case Composite_TAG: { @@ -286,13 +286,14 @@ const char* get_string_literal(IrArena* arena, const Node* node) { assert(chars[contents.count - 1] == 0); return string(arena, chars); } - default: return NULL; // error("This is not a string literal and it doesn't look like one either"); + default: break; } + return NULL; } bool is_abstraction(const Node* node) { NodeTag tag = node->tag; - return tag == Function_TAG || tag == BasicBlock_TAG || tag == Case_TAG; + return tag == Function_TAG || tag == BasicBlock_TAG; } String get_abstraction_name(const Node* abs) { @@ -300,7 +301,6 @@ String get_abstraction_name(const Node* abs) { switch (abs->tag) { case Function_TAG: return abs->payload.fun.name; case BasicBlock_TAG: return abs->payload.basic_block.name; - case Case_TAG: return "case"; default: assert(false); } } @@ -310,7 +310,6 @@ String get_abstraction_name_unsafe(const Node* abs) { switch (abs->tag) { case Function_TAG: return abs->payload.fun.name; case BasicBlock_TAG: return abs->payload.basic_block.name; - case Case_TAG: return NULL; default: assert(false); } } @@ -327,7 +326,6 @@ const Node* get_abstraction_body(const Node* abs) { switch (abs->tag) { case Function_TAG: return abs->payload.fun.body; case BasicBlock_TAG: return abs->payload.basic_block.body; - case Case_TAG: return abs->payload.case_.body; default: assert(false); } } @@ -338,7 +336,6 @@ void set_abstraction_body(Node* abs, const Node* body) { switch (abs->tag) { case Function_TAG: abs->payload.fun.body = body; break; case BasicBlock_TAG: abs->payload.basic_block.body = body; break; - case Case_TAG: abs->payload.case_.body = body; break; default: assert(false); } } @@ -348,7 +345,6 @@ Nodes get_abstraction_params(const Node* abs) { switch (abs->tag) { case Function_TAG: return abs->payload.fun.params; case BasicBlock_TAG: return abs->payload.basic_block.params; - case Case_TAG: return abs->payload.case_.params; default: assert(false); } } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index ba2e77488..05597efc4 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -253,15 +253,20 @@ static const Node* bind_node(Context* ctx, const Node* node) { } case BasicBlock_TAG: { assert(is_basic_block(node)); - Nodes new_bb_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); + Nodes new_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); String name = node->payload.basic_block.name; - Node* new_bb = basic_block(a, new_bb_params, name); + Node* new_bb = basic_block(a, new_params, name); Context bb_ctx = *ctx; ctx = &bb_ctx; if (name) add_binding(ctx, false, name, new_bb); + for (size_t i = 0; i < new_params.count; i++) { + String param_name = new_params.nodes[i]->payload.param.name; + if (param_name) + add_binding(ctx, false, param_name, new_params.nodes[i]); + } register_processed(&ctx->rewriter, node, new_bb); - register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new_bb_params); + register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new_params); new_bb->payload.basic_block.body = rewrite_node(&ctx->rewriter, node->payload.basic_block.body); return new_bb; } @@ -276,20 +281,6 @@ static const Node* bind_node(Context* ctx, const Node* node) { } return finish_body(bb, let(a, ninstr, rewrite_node(r, node->payload.let.in))); } - case Case_TAG: { - Nodes old_params = node->payload.case_.params; - Nodes new_params = recreate_params(&ctx->rewriter, old_params); - for (size_t i = 0; i < new_params.count; i++) { - String name = old_params.nodes[i]->payload.param.name; - if (name) - add_binding(ctx, false, name, new_params.nodes[i]); - } - register_processed_list(&ctx->rewriter, old_params, new_params); - const Node* new_body = rewrite_node(&ctx->rewriter, node->payload.case_.body); - Node* new_case = case_(a, new_params); - set_abstraction_body(new_case, new_body); - return new_case; - } case BindIdentifiers_TAG: assert(false); case Return_TAG: { assert(ctx->current_function); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 833136913..690f6aac8 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -26,9 +26,8 @@ static size_t count_calls(const UsesMap* map, const Node* bb) { return SIZE_MAX; // you can never inline conditional jumps count++; } - } - if (is_structured_construct(use->user) && use->operand_class == NcBasic_block) - count+=2; + } else if (use->operand_class == NcBasic_block) + return SIZE_MAX; // you can never inline basic blocks used for other purposes } return count; } @@ -62,7 +61,6 @@ const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* assert(instruction->tag == Block_TAG); // follow the terminator of the block until we hit a yield() const Node* const lam = instruction->payload.block.inside; - assert(is_case(lam)); const Node* terminator = get_abstraction_body(lam); while (true) { if (is_structured_construct(terminator)) { @@ -162,7 +160,7 @@ const Node* process(Context* ctx, const Node* old) { case BasicBlock_TAG: { size_t uses = count_calls(ctx->map, old); if (uses <= 1) { - log_string(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name(old), uses); + log_string(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name_safe(old), uses); return NULL; } break; diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 1227e163a..0195b3bd2 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -291,17 +291,16 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg_type) { IrArena* a = ctx->rewriter.dst_arena; - assert(is_case(node)); - assert(inferred_arg_type.count == node->payload.case_.params.count || node->payload.case_.params.count == 0); + assert(inferred_arg_type.count == node->payload.basic_block.params.count || node->payload.basic_block.params.count == 0); Context body_context = *ctx; LARRAY(const Node*, nparams, inferred_arg_type.count); for (size_t i = 0; i < inferred_arg_type.count; i++) { - if (node->payload.case_.params.count == 0) { + if (node->payload.basic_block.params.count == 0) { // syntax sugar: make up a parameter if there was none nparams[i] = param(a, inferred_arg_type.nodes[i], unique_name(a, "_")); } else { - const Param* old_param = &node->payload.case_.params.nodes[i]->payload.param; + const Param* old_param = &node->payload.basic_block.params.nodes[i]->payload.param; // for the param type: use the inferred one if none is already provided // if one is provided, check the inferred argument type is a subtype of the param type const Type* param_type = old_param->type ? infer_type(ctx, old_param->type) : NULL; @@ -310,12 +309,12 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg param_type = inferred_arg_type.nodes[i]; assert(is_subtype(param_type, inferred_arg_type.nodes[i])); nparams[i] = param(a, param_type, old_param->name); - register_processed(&body_context.rewriter, node->payload.case_.params.nodes[i], nparams[i]); + register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); } } - Node* new_case = case_(a, nodes(a, inferred_arg_type.count, nparams)); - set_abstraction_body(new_case, infer(&body_context, node->payload.case_.body, NULL)); + Node* new_case = basic_block(a, nodes(a, inferred_arg_type.count, nparams), get_abstraction_name_unsafe(node)); + set_abstraction_body(new_case, infer(&body_context, node->payload.basic_block.body, NULL)); return new_case; } @@ -518,7 +517,7 @@ static const Node* infer_control(Context* ctx, const Node* node) { const Node* jp = param(a, jpt, ojp->payload.param.name); register_processed(&joinable_ctx.rewriter, ojp, jp); - Node* new_case = case_(a, singleton(jp)); + Node* new_case = basic_block(a, singleton(jp), NULL); set_abstraction_body(new_case, infer(&joinable_ctx, get_abstraction_body(olam), NULL)); return control(a, (Control) { @@ -535,7 +534,7 @@ static const Node* infer_block(Context* ctx, const Node* node, const Nodes* expe Context block_inside_ctx = *ctx; Nodes nyield_types = infer_nodes(ctx, node->payload.block.yield_types); block_inside_ctx.merge_types = &nyield_types; - Node* new_case = case_(a, empty(a)); + Node* new_case = basic_block(a, empty(a), NULL); set_abstraction_body(new_case, infer(&block_inside_ctx, get_abstraction_body(node->payload.block.inside), NULL)); return block(a, (Block) { @@ -738,10 +737,6 @@ static const Node* process(Context* src_ctx, const Node* node) { } else if (is_annotation(node)) { assert(expected_type == NULL); return infer_annotation(&ctx, node); - } else if (is_case(node)) { - assert(false); - //assert(expected_types != NULL); - //return infer_case(&ctx, node, expected_types); } else if (is_basic_block(node)) { return _infer_basic_block(&ctx, node); } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 31897e40f..d11b75b1b 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -73,7 +73,7 @@ static void add_to_recover_context(struct List* recover_context, struct Dict* se } static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariables) { - assert(is_basic_block(liftee) || is_case(liftee)); + assert(is_basic_block(liftee)); LiftedCont** found = find_value_dict(const Node*, LiftedCont*, ctx->lifted, liftee); if (found) return *found; @@ -194,7 +194,6 @@ static const Node* process_node(Context* ctx, const Node* node) { switch (node->tag) { case Control_TAG: { const Node* oinside = node->payload.control.inside; - assert(is_case(oinside)); if (!is_control_static(ctx->uses, node) || ctx->config->hacks.force_join_point_lifting) { *ctx->todo = true; diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index eeecb1848..763728f3e 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -84,12 +84,12 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* true_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_true")); join_context.abs = node->payload.if_instr.if_true; - true_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, node->payload.if_instr.if_true->payload.case_.body); + true_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, get_abstraction_body(node->payload.if_instr.if_true)); Node* flse_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_false")); if (has_false_branch) { join_context.abs = node->payload.if_instr.if_false; - flse_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, node->payload.if_instr.if_false->payload.case_.body); + flse_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, get_abstraction_body(node->payload.if_instr.if_false)); } else { assert(yield_types.count == 0); flse_block->payload.basic_block.body = join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL) }); @@ -102,7 +102,7 @@ static const Node* process_node(Context* ctx, const Node* node) { }); BodyBuilder* bb = begin_body(a); - Node* control_case = case_(a, singleton(jp)); + Node* control_case = basic_block(a, singleton(jp), NULL); set_abstraction_body(control_case, control_body); Nodes results = gen_control(bb, yield_types, control_case); @@ -117,10 +117,9 @@ static const Node* process_node(Context* ctx, const Node* node) { // TODO: match case Loop_TAG: { const Node* old_loop_body = node->payload.loop_instr.body; - assert(is_case(old_loop_body)); Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.yield_types); - Nodes param_types = rewrite_nodes(&ctx->rewriter, get_param_types(a, old_loop_body->payload.case_.params)); + Nodes param_types = rewrite_nodes(&ctx->rewriter, get_param_types(a, get_abstraction_params(old_loop_body))); param_types = strip_qualifiers(a, param_types); const Type* break_jp_type = qualified_type(a, (QualifiedType) { @@ -137,12 +136,12 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes jps = mk_nodes(a, break_point, continue_point); insert_dict(const Node*, Nodes, ctx->structured_join_tokens, node, jps); - Nodes new_params = recreate_params(&ctx->rewriter, old_loop_body->payload.case_.params); + Nodes new_params = recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_body)); Node* loop_body = basic_block(a, new_params, unique_name(a, "loop_body")); - register_processed_list(&join_context.rewriter, old_loop_body->payload.case_.params, loop_body->payload.basic_block.params); + register_processed_list(&join_context.rewriter, get_abstraction_params(old_loop_body), loop_body->payload.basic_block.params); join_context.abs = old_loop_body; - const Node* inner_control_body = rewrite_node(&join_context.rewriter, old_loop_body->payload.case_.body); + const Node* inner_control_body = rewrite_node(&join_context.rewriter, get_abstraction_body(old_loop_body)); Node* inner_control_case = case_(a, singleton(continue_point)); set_abstraction_body(inner_control_case, inner_control_body); diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index d277fde29..90c6ab9f3 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -127,7 +127,7 @@ static const Node* process(Context* ctx, const Node* node) { case Control_TAG: { if (!is_control_static(ctx->uses, node)) { debugv_print("Function %s can't be a leaf function because the join point ", get_abstraction_name(ctx->cfg->entry->node)); - log_node(DEBUGV, first(node->payload.control.inside->payload.case_.params)); + log_node(DEBUGV, first(get_abstraction_params(node->payload.control.inside))); debugv_print("escapes its control block, preventing restructuring.\n"); ctx->is_leaf = false; } @@ -135,22 +135,14 @@ static const Node* process(Context* ctx, const Node* node) { } case Join_TAG: { const Node* old_jp = node->payload.join.join_point; - // is it associated with a control node ? if (old_jp->tag == Param_TAG) { - const Node* abs = old_jp->payload.param.abs; - assert(abs); - if (abs->tag == Case_TAG) { - const Node* structured = abs->payload.case_.structured_construct; - assert(structured); - // this join point is defined by a control - we can be a leaf :) - if (structured->tag == Control_TAG) - break; - } + const Node* control = get_control_for_jp(ctx->uses, old_jp); + if (control && is_control_static(ctx->uses, control)) + break; } debugv_print("Function %s can't be a leaf function because it joins with ", get_abstraction_name(ctx->cfg->entry->node)); log_node(DEBUGV, old_jp); debugv_print("which is not bound by a control node within that function.\n"); - // we join with some random join point; we can't be a leaf :( ctx->is_leaf = false; break; } diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index ed33edaf1..e84ae0feb 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -88,8 +88,6 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str break; case NcDeclaration: break; - case NcCase: - break; case NcBasic_block: break; case NcAnnotation: @@ -133,22 +131,9 @@ static const Node* process_node(Context* ctx, const Node* node) { Context ctx2 = *ctx; ctx2.bb = bb; ctx2.rewriter.rewrite_fn = (RewriteNodeFn) process_node; - new->payload.basic_block.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.basic_block.body)); + set_abstraction_body(new, finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.basic_block.body))); return new; } - case Case_TAG: { - Nodes new_params = recreate_params(&ctx->rewriter, node->payload.case_.params); - register_processed_list(&ctx->rewriter, node->payload.case_.params, new_params); - BodyBuilder* bb = begin_body(a); - Context ctx2 = *ctx; - ctx2.bb = bb; - ctx2.rewriter.rewrite_fn = (RewriteNodeFn) process_node; - - const Node* new_body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.case_.body)); - Node* new_case = case_(a, new_params); - set_abstraction_body(new_case, new_body); - return new_case; - } case Let_TAG: { const Node* oinstr = get_let_instruction(node); //const Node* found = search_processed(r, oinstr); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 242a35380..5bd918e3f 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -162,7 +162,7 @@ static KnowledgeBase* create_kb(Context* ctx, const Node* old) { if (entries_count_list(cf_node->pred_edges) == 1) { CFEdge edge = read_list(CFEdge, cf_node->pred_edges)[0]; assert(edge.dst == cf_node); - if (edge.type == LetTailEdge || edge.type == JumpEdge) { + if (edge.type == JumpEdge) { CFNode* dominator = edge.src; const KnowledgeBase* parent_kb = get_kb(ctx, dominator->node); assert(parent_kb); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 39d35a500..0b3c0016c 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -244,7 +244,6 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit_la // var phi = undef; level = N+1; structurize[body, if (level == N+1, _ => tail(load(phi))); structured_exit_terminator] case Control_TAG: { const Node* old_control_body = body->payload.control.inside; - assert(old_control_body->tag == Case_TAG); Nodes old_control_params = get_abstraction_params(old_control_body); assert(old_control_params.count == 1); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 7117c1582..b5c903f02 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -177,10 +177,6 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { exit_wrappers[i] = pre_join_exit_bb; break; } - case Case_TAG: - exit_wrappers[i] = case_(arena, exit_wrapper_params); - set_abstraction_body(exit_wrappers[i], jump_helper(arena, exit_helpers[i], empty(arena))); - break; default: assert(false); } @@ -198,10 +194,6 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { set_abstraction_body(continue_wrapper, continue_wrapper_body); break; } - case Case_TAG: - continue_wrapper = case_(arena, continue_wrapper_params); - set_abstraction_body(continue_wrapper, continue_wrapper_body); - break; default: assert(false); } @@ -344,10 +336,6 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { set_abstraction_body(loop_container, outer_body); break; } - case Case_TAG: - loop_container = case_(arena, nparams); - set_abstraction_body(loop_container, outer_body); - break; default: assert(false); } @@ -392,7 +380,6 @@ static const Node* process_node(Context* ctx, const Node* node) { rewriter = &ctx->rewriter; break; } - case Case_TAG: case BasicBlock_TAG: if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) break; @@ -520,9 +507,6 @@ static const Node* process_node(Context* ctx, const Node* node) { .args = results })); } - case Case_TAG: - error("todo"); - // return let(arena, control_instruction, recreated_join); default: assert(false); } diff --git a/src/shady/print.c b/src/shady/print.c index 413dcb879..1905469cc 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -263,7 +263,6 @@ static void print_abs_body(PrinterCtx* ctx, const Node* block) { } static void print_case_body(PrinterCtx* ctx, const Node* case_) { - assert(is_case(case_)); printf(" {"); indent(ctx->printer); printf("\n"); @@ -842,8 +841,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { if (ctx->config.in_cfg) break; const Node* body = node->payload.loop_instr.body; - assert(is_case(body)); - print_param_list(ctx, body->payload.case_.params, &node->payload.loop_instr.initial_args); + print_param_list(ctx, get_abstraction_params(body), &node->payload.loop_instr.initial_args); print_case_body(ctx, body); printf("\n"); print_abs_body(ctx, get_structured_construct_tail(node)); @@ -860,7 +858,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { print_yield_types(ctx, node->payload.control.yield_types); if (ctx->config.in_cfg) break; - print_param_list(ctx, node->payload.control.inside->payload.case_.params, NULL); + print_param_list(ctx, get_abstraction_params(node->payload.control.inside), NULL); print_case_body(ctx, node->payload.control.inside); printf("\n"); print_abs_body(ctx, get_structured_construct_tail(node)); @@ -1052,18 +1050,7 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { print_value(ctx, node); else if (is_terminator(node)) print_terminator(ctx, node); - else if (node->tag == Case_TAG) { - printf(BYELLOW); - printf("case_ "); - printf(RESET); - print_param_list(ctx, node->payload.case_.params, NULL); - indent(ctx->printer); - printf(" {\n"); - print_abs_body(ctx, node); - // printf(";"); - deindent(ctx->printer); - printf("\n}"); - } else if (is_declaration(node)) { + else if (is_declaration(node)) { printf(BYELLOW); printf("%s", get_declaration_name(node)); printf(RESET); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index be9e01187..3ce114864 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -368,15 +368,6 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { const Node* nlet = let(arena, instruction, rewrite_op_helper(rewriter, NcTerminator, "in", node->payload.let.in)); return finish_body(bb, nlet); } - case Case_TAG: { - Nodes params = recreate_params(rewriter, node->payload.case_.params); - register_processed_list(rewriter, node->payload.case_.params, params); - const Node* nterminator = rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.case_.body); - Node* ncase = case_(rewriter->dst_arena, params); - set_abstraction_body(ncase, nterminator); - // register_processed(rewriter, node, nlam); - return ncase; - } case BasicBlock_TAG: { Nodes params = recreate_params(rewriter, node->payload.basic_block.params); register_processed_list(rewriter, node->payload.basic_block.params, params); diff --git a/src/shady/type.c b/src/shady/type.c index 00d76fcd6..a5b520db0 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -991,8 +991,7 @@ const Type* check_type_loop_instr(IrArena* arena, Loop loop_instr) { const Type* check_type_control(IrArena* arena, Control control) { ensure_types_are_data_types(&control.yield_types); // TODO check it then ! - assert(is_case(control.inside)); - const Node* join_point = first(control.inside->payload.case_.params); + const Node* join_point = first(get_abstraction_params(control.inside)); const Type* join_point_type = join_point->type; deconstruct_qualified_type(&join_point_type); @@ -1011,8 +1010,7 @@ const Type* check_type_control(IrArena* arena, Control control) { const Type* check_type_block(IrArena* arena, Block payload) { ensure_types_are_value_types(&payload.yield_types); - assert(is_case(payload.inside)); - assert(payload.inside->payload.case_.params.count == 0); + assert(get_abstraction_params(payload.inside).count == 0); /*const Node* lam = payload.inside; const Node* yield_instr = NULL; @@ -1288,10 +1286,6 @@ const Type* check_type_basic_block(IrArena* arena, BasicBlock bb) { return bb_type(arena, (BBType) { .param_types = get_param_types(arena, (&bb)->params) }); } -const Type* check_type_case_(IrArena* arena, Case lam) { - return lam_type(arena, (LamType) { .param_types = get_param_types(arena, (&lam)->params) }); -} - const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_variable) { assert(is_type(global_variable.type)); diff --git a/src/shady/visit.h b/src/shady/visit.h index 789c94dc4..0d943d4bf 100644 --- a/src/shady/visit.h +++ b/src/shady/visit.h @@ -24,6 +24,6 @@ void visit_ops(Visitor* visitor, NodeClass, String, Nodes nodes); // visits the abstractions in the function, _except_ for the entry block (ie the function itself) void visit_function_rpo(Visitor* visitor, const Node* function); // use this in visit_node_operands to avoid visiting nodes in non-rpo order -#define IGNORE_ABSTRACTIONS_MASK NcBasic_block | NcCase | NcDeclaration +#define IGNORE_ABSTRACTIONS_MASK NcBasic_block | NcDeclaration #endif From 881e90f14253a6efd4663688264661d16cd82f1d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 18:28:09 +0200 Subject: [PATCH 408/693] parser: reorganize --- src/frontend/slim/parser.c | 170 +++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 81 deletions(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 5956b3df7..fbaf0c431 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -81,10 +81,11 @@ static const char* accept_identifier(ctxparams) { } static const Node* expect_body(ctxparams, const Node* default_terminator); -static const Node* accept_value(ctxparams); +static const Node* accept_value(ctxparams, BodyBuilder*); static const Type* accept_unqualified_type(ctxparams); -static const Node* accept_expr(ctxparams, int); -static Nodes expect_operands(ctxparams); +static const Node* accept_expr(ctxparams, BodyBuilder*, int); +static Nodes expect_operands(ctxparams, BodyBuilder*); +static const Node* expect_operand(ctxparams, BodyBuilder*); static const Type* accept_numerical_type(ctxparams) { if (accept_token(ctx, i8_tok)) { @@ -153,7 +154,7 @@ static const Node* accept_numerical_literal(ctxparams) { return n; } -static const Node* accept_value(ctxparams) { +static const Node* accept_value(ctxparams, BodyBuilder* bb) { Token tok = curr_token(tokenizer); size_t size = tok.end - tok.start; @@ -189,8 +190,7 @@ static const Node* accept_value(ctxparams) { if (accept_token(ctx, rpar_tok)) { return tuple_helper(arena, empty(arena)); } - const Node* atom = config.front_end ? accept_expr(ctx, max_precedence()) : accept_value(ctx); - expect(atom); + const Node* atom = expect_operand(ctx, bb); if (curr_token(tokenizer).tag == rpar_tok) { next_token(tokenizer); } else { @@ -199,8 +199,7 @@ static const Node* accept_value(ctxparams) { while (!accept_token(ctx, rpar_tok)) { expect(accept_token(ctx, comma_tok)); - const Node* element = config.front_end ? accept_expr(ctx, max_precedence()) : accept_value(ctx); - expect(elements); + const Node* element = expect_operand(ctx, bb); append_list(const Node*, elements, element); } @@ -214,7 +213,7 @@ static const Node* accept_value(ctxparams) { next_token(tokenizer); const Type* elem_type = accept_unqualified_type(ctx); expect(elem_type); - Nodes elems = expect_operands(ctx); + Nodes elems = expect_operands(ctx, bb); return composite_helper(arena, elem_type, elems); } default: return NULL; @@ -272,7 +271,7 @@ static const Type* accept_unqualified_type(ctxparams) { expect(elem_type); const Node* size = NULL; if(accept_token(ctx, semi_tok)) { - size = accept_value(ctx); + size = accept_value(ctx, NULL); expect(size); } expect(accept_token(ctx, rsbracket_tok)); @@ -355,11 +354,17 @@ static const Type* accept_qualified_type(ctxparams) { return qualified_type(arena, (QualifiedType) { .is_uniform = qualifier == Uniform, .type = unqualified }); } -static const Node* accept_operand(ctxparams) { - return config.front_end ? accept_expr(ctx, max_precedence()) : accept_value(ctx); +static const Node* accept_operand(ctxparams, BodyBuilder* bb) { + return config.front_end ? accept_expr(ctx, bb, max_precedence()) : accept_value(ctx, bb); } -static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_values) { +static const Node* expect_operand(ctxparams, BodyBuilder* bb) { + const Node* operand = accept_operand(ctx, bb); + expect(operand); + return operand; +} + +static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_values, BodyBuilder* bb) { expect(accept_token(ctx, lpar_tok)); struct List* params = new_list(Node*); struct List* default_vals = default_values ? new_list(Node*) : NULL; @@ -379,7 +384,7 @@ static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_value if (default_values) { expect(accept_token(ctx, equal_tok)); - const Node* default_val = accept_operand(ctx); + const Node* default_val = accept_operand(ctx, bb); append_list(const Node*, default_vals, default_val); } @@ -422,9 +427,9 @@ static Nodes accept_types(ctxparams, TokenTag separator, Qualified qualified) { return types2; } -static const Node* accept_primary_expr(ctxparams) { +static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { if (accept_token(ctx, minus_tok)) { - const Node* expr = accept_primary_expr(ctx); + const Node* expr = accept_primary_expr(ctx, bb); expect(expr); if (expr->tag == IntLiteral_TAG) { return int_literal(arena, (IntLiteral) { @@ -438,21 +443,21 @@ static const Node* accept_primary_expr(ctxparams) { }); } } else if (accept_token(ctx, unary_excl_tok)) { - const Node* expr = accept_primary_expr(ctx); + const Node* expr = accept_primary_expr(ctx, bb); expect(expr); return prim_op(arena, (PrimOp) { .op = not_op, .operands = singleton(expr), }); } else if (accept_token(ctx, star_tok)) { - const Node* expr = accept_primary_expr(ctx); + const Node* expr = accept_primary_expr(ctx, bb); expect(expr); return prim_op(arena, (PrimOp) { .op = deref_op, .operands = singleton(expr), }); } else if (accept_token(ctx, infix_and_tok)) { - const Node* expr = accept_primary_expr(ctx); + const Node* expr = accept_primary_expr(ctx, bb); expect(expr); return prim_op(arena, (PrimOp) { .op = addrof_op, @@ -460,8 +465,32 @@ static const Node* accept_primary_expr(ctxparams) { }); } - const Node* expr = accept_value(ctx); + return accept_value(ctx, bb); +} + +static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) { + const Node* expr = accept_primary_expr(ctx, bb); while (expr) { + InfixOperators infix; + if (is_infix_operator(curr_token(tokenizer).tag, &infix)) { + int precedence = get_precedence(infix); + if (precedence > outer_precedence) break; + next_token(tokenizer); + + const Node* rhs = accept_expr(ctx, bb, precedence - 1); + expect(rhs); + Op primop_op; + if (is_primop_op(infix, &primop_op)) { + expr = prim_op(arena, (PrimOp) { + .op = primop_op, + .operands = nodes(arena, 2, (const Node* []) {expr, rhs}) + }); + } else switch (infix) { + default: error("unknown infix operator") + } + continue; + } + Nodes ty_args = nodes(arena, 0, NULL); bool parse_ty_args = false; if (accept_token(ctx, lsbracket_tok)) { @@ -478,6 +507,8 @@ static const Node* accept_primary_expr(ctxparams) { } switch (curr_token(tokenizer).tag) { case lpar_tok: { + Nodes ops = expect_operands(ctx, bb); + Op op = PRIMOPS_COUNT; String callee_name = NULL; if (expr->tag == Unbound_TAG) { @@ -489,25 +520,27 @@ static const Node* accept_primary_expr(ctxparams) { } } } - Nodes ops = expect_operands(ctx); if (op != PRIMOPS_COUNT) { - return prim_op(arena, (PrimOp) { + expr = prim_op(arena, (PrimOp) { .op = op, .type_arguments = ty_args, .operands = ops }); + continue; } if (strcmp(callee_name, "alloca") == 0) { - return stack_alloc(arena, (StackAlloc) { + expr = stack_alloc(arena, (StackAlloc) { .type = first(ty_args) }); + continue; } else if (strcmp(callee_name, "debug_printf") == 0) { - return debug_printf(arena, (DebugPrintf) { + expr = debug_printf(arena, (DebugPrintf) { .string = get_string_literal(arena, first(ops)), .args = nodes(arena, ops.count - 1, &ops.nodes[1]) }); + continue; } assert(ty_args.count == 0 && "Function calls do not support type arguments"); @@ -522,39 +555,13 @@ static const Node* accept_primary_expr(ctxparams) { expect(false && "expected function call arguments"); break; } - break; - } - return expr; -} -static const Node* accept_expr(ctxparams, int outer_precedence) { - const Node* expr = accept_primary_expr(ctx); - while (expr) { - InfixOperators infix; - if (is_infix_operator(curr_token(tokenizer).tag, &infix)) { - int precedence = get_precedence(infix); - if (precedence > outer_precedence) break; - next_token(tokenizer); - - const Node* rhs = accept_expr(ctx, precedence - 1); - expect(rhs); - Op primop_op; - if (is_primop_op(infix, &primop_op)) { - expr = prim_op(arena, (PrimOp) { - .op = primop_op, - .operands = nodes(arena, 2, (const Node* []) {expr, rhs}) - }); - } else switch (infix) { - default: error("unknown infix operator") - } - continue; - } break; } return expr; } -static Nodes expect_operands(ctxparams) { +static Nodes expect_operands(ctxparams, BodyBuilder* bb) { if (!accept_token(ctx, lpar_tok)) error("Expected left parenthesis") @@ -562,7 +569,7 @@ static Nodes expect_operands(ctxparams) { bool expect = false; while (true) { - const Node* val = accept_operand(ctx); + const Node* val = accept_operand(ctx, bb); if (!val) { if (expect) error("expected value but got none") @@ -594,7 +601,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { next_token(tokenizer); Nodes yield_types = accept_types(ctx, 0, NeverQualified); expect(accept_token(ctx, lpar_tok)); - const Node* condition = accept_operand(ctx); + const Node* condition = accept_operand(ctx, bb); expect(condition); expect(accept_token(ctx, rpar_tok)); const Node* merge = config.front_end ? merge_selection(arena, (MergeSelection) { .args = nodes(arena, 0, NULL) }) : NULL; @@ -616,7 +623,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { Nodes yield_types = accept_types(ctx, 0, NeverQualified); Nodes parameters; Nodes initial_arguments; - expect_parameters(ctx, ¶meters, &initial_arguments); + expect_parameters(ctx, ¶meters, &initial_arguments, bb); // by default loops continue forever const Node* default_loop_end_behaviour = config.front_end ? merge_continue(arena, (MergeContinue) { .args = nodes(arena, 0, NULL) }) : NULL; Node* loop_case = case_(arena, parameters); @@ -643,7 +650,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { } static const Node* accept_instruction(ctxparams, BodyBuilder* bb) { - const Node* instr = accept_expr(ctx, max_precedence()); + const Node* instr = accept_expr(ctx, bb, max_precedence()); if (instr) expect(accept_token(ctx, semi_tok) && "Non-control flow instructions must be followed by a semicolon"); @@ -719,36 +726,36 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { return true; } -static const Node* expect_jump(ctxparams) { +static const Node* expect_jump(ctxparams, BodyBuilder* bb) { String target = accept_identifier(ctx); expect(target); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx) : nodes(arena, 0, NULL); + Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return jump(arena, (Jump) { .target = unbound(arena, (Unbound) { .name = target }), .args = args }); } -static const Node* accept_terminator(ctxparams) { +static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { TokenTag tag = curr_token(tokenizer).tag; switch (tag) { case jump_tok: { next_token(tokenizer); - return expect_jump(ctx); + return expect_jump(ctx, bb); } case branch_tok: { next_token(tokenizer); expect(accept_token(ctx, lpar_tok)); - const Node* condition = accept_value(ctx); + const Node* condition = accept_value(ctx, bb); expect(condition); expect(accept_token(ctx, comma_tok)); - const Node* true_target = expect_jump(ctx); + const Node* true_target = expect_jump(ctx, bb); expect(accept_token(ctx, comma_tok)); - const Node* false_target = expect_jump(ctx); + const Node* false_target = expect_jump(ctx, bb); expect(accept_token(ctx, rpar_tok)); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx) : nodes(arena, 0, NULL); + Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return branch(arena, (Branch) { .condition = condition, .true_jump = true_target, @@ -759,7 +766,7 @@ static const Node* accept_terminator(ctxparams) { next_token(tokenizer); expect(accept_token(ctx, lpar_tok)); - const Node* inspectee = accept_value(ctx); + const Node* inspectee = accept_value(ctx, bb); expect(inspectee); expect(accept_token(ctx, comma_tok)); Nodes values = empty(arena); @@ -767,14 +774,14 @@ static const Node* accept_terminator(ctxparams) { const Node* default_jump; while (true) { if (accept_token(ctx, default_tok)) { - default_jump = expect_jump(ctx); + default_jump = expect_jump(ctx, bb); break; } expect(accept_token(ctx, case_tok)); - const Node* value = accept_value(ctx); + const Node* value = accept_value(ctx, bb); expect(value); expect(accept_token(ctx, comma_tok) && 1); - const Node* j = expect_jump(ctx); + const Node* j = expect_jump(ctx, bb); expect(accept_token(ctx, comma_tok) && true); values = append_nodes(arena, values, value); cases = append_nodes(arena, cases, j); @@ -790,28 +797,28 @@ static const Node* accept_terminator(ctxparams) { } case return_tok: { next_token(tokenizer); - Nodes args = expect_operands(ctx); + Nodes args = expect_operands(ctx, bb); return fn_ret(arena, (Return) { .args = args }); } case merge_selection_tok: { next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx) : nodes(arena, 0, NULL); + Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return merge_selection(arena, (MergeSelection) { .args = args }); } case continue_tok: { next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx) : nodes(arena, 0, NULL); + Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return merge_continue(arena, (MergeContinue) { .args = args }); } case break_tok: { next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx) : nodes(arena, 0, NULL); + Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return merge_break(arena, (MergeBreak) { .args = args }); @@ -819,9 +826,9 @@ static const Node* accept_terminator(ctxparams) { case join_tok: { next_token(tokenizer); expect(accept_token(ctx, lpar_tok)); - const Node* jp = accept_operand(ctx); + const Node* jp = accept_operand(ctx, bb); expect(accept_token(ctx, rpar_tok)); - Nodes args = expect_operands(ctx); + Nodes args = expect_operands(ctx, bb); return join(arena, (Join) { .join_point = jp, .args = args @@ -847,7 +854,7 @@ static const Node* expect_body(ctxparams, const Node* default_terminator) { break; } - const Node* terminator = accept_terminator(ctx); + const Node* terminator = accept_terminator(ctx, bb); if (terminator) expect(accept_token(ctx, semi_tok)); @@ -867,7 +874,7 @@ static const Node* expect_body(ctxparams, const Node* default_terminator) { const char* name = accept_identifier(ctx); Nodes parameters; - expect_parameters(ctx, ¶meters, NULL); + expect_parameters(ctx, ¶meters, NULL, bb); Node* continuation = basic_block(arena, parameters, name); continuation->payload.basic_block.body = expect_body(ctx, NULL); append_list(Node*, conts, continuation); @@ -890,7 +897,7 @@ static Nodes accept_annotations(ctxparams) { const char* id = accept_identifier(ctx); const Node* annot = NULL; if (accept_token(ctx, lpar_tok)) { - const Node* first_value = accept_value(ctx); + const Node* first_value = accept_value(ctx, NULL); if (!first_value) { expect(accept_token(ctx, rpar_tok)); goto no_params; @@ -904,7 +911,7 @@ static Nodes accept_annotations(ctxparams) { struct List* values = new_list(const Node*); append_list(const Node*, values, first_value); while (true) { - const Node* next_value = accept_value(ctx); + const Node* next_value = accept_value(ctx, NULL); expect(next_value); append_list(const Node*, values, next_value); if (accept_token(ctx, comma_tok)) @@ -950,13 +957,14 @@ static const Node* accept_const(ctxparams, Nodes annotations) { const char* id = accept_identifier(ctx); expect(id); expect(accept_token(ctx, equal_tok)); - const Node* definition = accept_expr(ctx, max_precedence()); + BodyBuilder* bb = begin_body(arena); + const Node* definition = accept_expr(ctx, bb, max_precedence()); expect(definition); expect(accept_token(ctx, semi_tok)); Node* cnst = constant(mod, annotations, type, id); - cnst->payload.constant.instruction = definition; + cnst->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(definition)); return cnst; } @@ -969,7 +977,7 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { Nodes types = accept_types(ctx, comma_tok, MaybeQualified); expect(curr_token(tokenizer).tag == lpar_tok); Nodes parameters; - expect_parameters(ctx, ¶meters, NULL); + expect_parameters(ctx, ¶meters, NULL, NULL); Node* fn = function(mod, parameters, name, annotations, types); if (!accept_token(ctx, semi_tok)) @@ -1032,7 +1040,7 @@ static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { const Node* initial_value = NULL; if (accept_token(ctx, equal_tok)) { - initial_value = accept_value(ctx); + initial_value = accept_value(ctx, NULL); expect(initial_value); } From ac6f7bb0d210590f69e08e9ba407a28e9b3cf035 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 18:44:24 +0200 Subject: [PATCH 409/693] fix parser crash --- include/shady/ir.h | 1 - src/shady/api/generator_type.c | 67 ++++++++++++++++++++++++++++++++++ src/shady/body_builder.c | 6 +-- 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 src/shady/api/generator_type.c diff --git a/include/shady/ir.h b/include/shady/ir.h index 320c39ed5..647bd8abb 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -297,7 +297,6 @@ const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder*, const Node*, const Nodes); const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); -const Node* yield_values_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder*, Nodes, const Nodes); const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder*, Nodes); const Node* bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder*, const Node*, const Nodes); const Node* bind_last_instruction_and_wrap_in_compound_instruction(BodyBuilder*, const Node*); diff --git a/src/shady/api/generator_type.c b/src/shady/api/generator_type.c new file mode 100644 index 000000000..4e19a6684 --- /dev/null +++ b/src/shady/api/generator_type.c @@ -0,0 +1,67 @@ +#include "generator.h" + +void generate(Growy* g, json_object* src) { + generate_header(g, src); + + json_object* nodes = json_object_object_get(src, "nodes"); + for (size_t i = 0; i < json_object_array_length(nodes); i++) { + json_object* node = json_object_array_get_idx(nodes, i); + + String name = json_object_get_string(json_object_object_get(node, "name")); + assert(name); + + String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); + void* alloc = NULL; + if (!snake_name) { + snake_name = to_snake_case(name); + alloc = (void*) snake_name; + } + + json_object* t = json_object_object_get(node, "type"); + if (!t || json_object_get_boolean(t)) { + json_object* ops = json_object_object_get(node, "ops"); + if (ops) + growy_append_formatted(g, "const Type* check_type_%s(IrArena*, %s);\n", snake_name, name); + else + growy_append_formatted(g, "const Type* check_type_%s(IrArena*);\n", snake_name); + } + + if (alloc) + free(alloc); + } + + growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node);\n"); + + growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node) {\n"); + growy_append_formatted(g, "\tswitch(node->tag) {\n"); + for (size_t i = 0; i < json_object_array_length(nodes); i++) { + json_object* node = json_object_array_get_idx(nodes, i); + + String name = json_object_get_string(json_object_object_get(node, "name")); + assert(name); + + String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); + void* alloc = NULL; + if (!snake_name) { + snake_name = to_snake_case(name); + alloc = (void*) snake_name; + } + + growy_append_formatted(g, "\t\tcase %s_TAG: ", name); + + json_object* t = json_object_object_get(node, "type"); + if (!t || json_object_get_boolean(t)) { + json_object* ops = json_object_object_get(node, "ops"); + if (ops) + growy_append_formatted(g, "return check_type_%s(a, node->payload.%s);\n", snake_name, snake_name); + else + growy_append_formatted(g, "return check_type_%s(a);\n", snake_name); + } + + if (alloc) + free(alloc); + } + growy_append_formatted(g, "\t\tdefault: return NULL;\n"); + growy_append_formatted(g, "\t}\n"); + growy_append_formatted(g, "}\n"); +} diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index d766346db..a9fa0ddb2 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -177,15 +177,11 @@ static Nodes finish_with_instruction_list(BodyBuilder* bb) { return nodes(a, count, list); } -const Node* yield_values_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder* bb, Nodes values, const Nodes types) { +const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { IrArena* arena = bb->arena; return compound_instruction(arena, finish_with_instruction_list(bb), values); } -const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { - return yield_values_and_wrap_in_compound_instruction_explicit_return_types(bb, values, get_values_types(bb->arena, values)); -} - const Node* bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder* bb, const Node* instruction, const Nodes types) { IrArena* arena = bb->arena; Nodes values = bind_instruction_outputs_count(bb, instruction, types.count); From 6b27a82c3415edb393b7d9c9120d8918f058039f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 18:52:49 +0200 Subject: [PATCH 410/693] run check_type after validation operands --- include/shady/grammar.json | 1 + src/shady/CMakeLists.txt | 2 +- src/shady/api/CMakeLists.txt | 5 ++++ src/shady/api/generator_type.c | 33 -------------------------- src/shady/constructors.c | 11 ++++----- src/shady/generator/generator_common.c | 11 +-------- src/shady/generator_type.c | 11 +++++++-- src/shady/type.c | 2 ++ 8 files changed, 23 insertions(+), 53 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index ae58715f5..552812080 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -455,6 +455,7 @@ "class": "instruction", "constructor": "custom", "front-end-only": true, + "type": false, "ops": [ { "name": "instruction", "class": "instruction" }, { "name": "mutable", "type": "bool" }, diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 1b83487e7..71d78fc3e 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(api) get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) -add_generated_file(FILE_NAME type_generated.h TARGET_NAME type_generated SOURCES generator_type.c) +add_generated_file(FILE_NAME type_generated.c TARGET_NAME type_generated SOURCES generator_type.c) add_generated_file(FILE_NAME node_generated.c TARGET_NAME node_generated SOURCES generator_node.c) add_generated_file(FILE_NAME primops_generated.c TARGET_NAME primops_generated SOURCES generator_primops.c) add_generated_file(FILE_NAME constructors_generated.c TARGET_NAME constructors_generated SOURCES generator_constructors.c) diff --git a/src/shady/api/CMakeLists.txt b/src/shady/api/CMakeLists.txt index e7a10cbff..943011410 100644 --- a/src/shady/api/CMakeLists.txt +++ b/src/shady/api/CMakeLists.txt @@ -11,4 +11,9 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grammar_generated.h DESTINATION includ add_generated_file(FILE_NAME primops_generated.h TARGET_NAME generate-primops-headers SOURCES generator_primops.c) add_dependencies(api INTERFACE generate-primops-headers) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/primops_generated.h DESTINATION include) + +add_generated_file(FILE_NAME type_generated.h TARGET_NAME generate-type-headers SOURCES generator_type.c) +add_dependencies(api INTERFACE generate-type-headers) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/type_generated.h DESTINATION include) + install(TARGETS api EXPORT shady_export_set) diff --git a/src/shady/api/generator_type.c b/src/shady/api/generator_type.c index 4e19a6684..cb812e00b 100644 --- a/src/shady/api/generator_type.c +++ b/src/shady/api/generator_type.c @@ -31,37 +31,4 @@ void generate(Growy* g, json_object* src) { } growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node);\n"); - - growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node) {\n"); - growy_append_formatted(g, "\tswitch(node->tag) {\n"); - for (size_t i = 0; i < json_object_array_length(nodes); i++) { - json_object* node = json_object_array_get_idx(nodes, i); - - String name = json_object_get_string(json_object_object_get(node, "name")); - assert(name); - - String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); - void* alloc = NULL; - if (!snake_name) { - snake_name = to_snake_case(name); - alloc = (void*) snake_name; - } - - growy_append_formatted(g, "\t\tcase %s_TAG: ", name); - - json_object* t = json_object_object_get(node, "type"); - if (!t || json_object_get_boolean(t)) { - json_object* ops = json_object_object_get(node, "ops"); - if (ops) - growy_append_formatted(g, "return check_type_%s(a, node->payload.%s);\n", snake_name, snake_name); - else - growy_append_formatted(g, "return check_type_%s(a);\n", snake_name); - } - - if (alloc) - free(alloc); - } - growy_append_formatted(g, "\t\tdefault: return NULL;\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n"); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 7971187ac..21b6ecdac 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -15,8 +15,12 @@ bool compare_nodes(Nodes* a, Nodes* b); static void pre_construction_validation(IrArena* arena, Node* node); +const Type* check_type_generated(IrArena* a, const Node* node); + static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { pre_construction_validation(arena, &node); + if (arena->config.check_types) + node.type = check_type_generated(arena, &node); if (pfresh) *pfresh = false; @@ -69,7 +73,6 @@ const Node* let(IrArena* arena, const Node* instruction, const Node* in) { memset((void*) &node, 0, sizeof(Node)); node = (Node) { .arena = arena, - .type = arena->config.check_types ? check_type_let(arena, payload) : NULL, .tag = Let_TAG, .payload.let = payload }; @@ -95,7 +98,6 @@ const Node* compound_instruction(IrArena* arena, Nodes instructions, Nodes resul memset((void*) &node, 0, sizeof(Node)); node = (Node) { .arena = arena, - .type = arena->config.check_types ? check_type_compound_instruction(arena, payload) : NULL, .tag = CompoundInstruction_TAG, .payload.compound_instruction = payload }; @@ -112,7 +114,6 @@ Node* param(IrArena* arena, const Type* type, const char* name) { memset((void*) &node, 0, sizeof(Node)); node = (Node) { .arena = arena, - .type = arena->config.check_types ? check_type_param(arena, param) : NULL, .tag = Param_TAG, .payload.param = param }; @@ -181,7 +182,6 @@ Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, N memset((void*) &node, 0, sizeof(Node)); node = (Node) { .arena = arena, - .type = arena->config.check_types ? check_type_fun(arena, payload) : NULL, .tag = Function_TAG, .payload.fun = payload }; @@ -210,7 +210,6 @@ Node* basic_block(IrArena* arena, Nodes params, const char* name) { memset((void*) &node, 0, sizeof(Node)); node = (Node) { .arena = arena, - .type = arena->config.check_types ? check_type_basic_block(arena, payload) : NULL, .tag = BasicBlock_TAG, .payload.basic_block = payload }; @@ -240,7 +239,6 @@ Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { memset((void*) &node, 0, sizeof(Node)); node = (Node) { .arena = arena, - .type = arena->config.check_types ? check_type_constant(arena, cnst) : NULL, .tag = Constant_TAG, .payload.constant = cnst }; @@ -272,7 +270,6 @@ Node* global_var(Module* mod, Nodes annotations, const Type* type, const char* n memset((void*) &node, 0, sizeof(Node)); node = (Node) { .arena = arena, - .type = arena->config.check_types ? check_type_global_variable(arena, gvar) : NULL, .tag = GlobalVariable_TAG, .payload.global_variable = gvar }; diff --git a/src/shady/generator/generator_common.c b/src/shady/generator/generator_common.c index fb6ba9136..a7b24d510 100644 --- a/src/shady/generator/generator_common.c +++ b/src/shady/generator/generator_common.c @@ -40,16 +40,7 @@ void generate_node_ctor(Growy* g, json_object* nodes, bool definition) { growy_append_formatted(g, "\t\t.tag = %s_TAG,\n", name); if (ops) growy_append_formatted(g, "\t\t.payload.%s = payload,\n", snake_name); - json_object* t = json_object_object_get(node, "type"); - if (!t || json_object_get_boolean(t)) { - growy_append_formatted(g, "\t\t.type = arena->config.check_types ? "); - if (ops) - growy_append_formatted(g, "check_type_%s(arena, payload)", snake_name); - else - growy_append_formatted(g, "check_type_%s(arena)", snake_name); - growy_append_formatted(g, ": NULL,\n"); - } else - growy_append_formatted(g, "\t\t.type = NULL,\n"); + growy_append_formatted(g, "\t\t.type = NULL,\n"); growy_append_formatted(g, "\t};\n"); growy_append_formatted(g, "\treturn create_node_helper(arena, node, NULL);\n"); growy_append_formatted(g, "}\n"); diff --git a/src/shady/generator_type.c b/src/shady/generator_type.c index c22ed5133..096fa6ae9 100644 --- a/src/shady/generator_type.c +++ b/src/shady/generator_type.c @@ -4,6 +4,9 @@ void generate(Growy* g, json_object* src) { generate_header(g, src); json_object* nodes = json_object_object_get(src, "nodes"); + + growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node) {\n"); + growy_append_formatted(g, "\tswitch(node->tag) {\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -19,14 +22,18 @@ void generate(Growy* g, json_object* src) { json_object* t = json_object_object_get(node, "type"); if (!t || json_object_get_boolean(t)) { + growy_append_formatted(g, "\t\tcase %s_TAG: ", name); json_object* ops = json_object_object_get(node, "ops"); if (ops) - growy_append_formatted(g, "const Type* check_type_%s(IrArena*, %s);\n", snake_name, name); + growy_append_formatted(g, "return check_type_%s(a, node->payload.%s);\n", snake_name, snake_name); else - growy_append_formatted(g, "const Type* check_type_%s(IrArena*);\n", snake_name); + growy_append_formatted(g, "return check_type_%s(a);\n", snake_name); } if (alloc) free(alloc); } + growy_append_formatted(g, "\t\tdefault: return NULL;\n"); + growy_append_formatted(g, "\t}\n"); + growy_append_formatted(g, "}\n"); } diff --git a/src/shady/type.c b/src/shady/type.c index a5b520db0..e55d754b0 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1318,4 +1318,6 @@ const Type* check_type_constant(IrArena* arena, Constant cnst) { return cnst.type_hint; } +#include "type_generated.c" + #pragma GCC diagnostic pop From 0f2ea32f6f3ef89c293b1826e0e76229bfa99e48 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 3 Aug 2024 19:42:08 +0200 Subject: [PATCH 411/693] trying to get rid of the normalize pass... --- include/shady/ir.h | 2 + src/frontend/slim/parser.c | 135 ++++++++++++++++++----------------- src/shady/body_builder.c | 24 ++++--- src/shady/passes/bind.c | 2 +- src/shady/passes/normalize.c | 64 +++-------------- 5 files changed, 94 insertions(+), 133 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 647bd8abb..2be44ba35 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -281,6 +281,8 @@ BodyBuilder* begin_body(IrArena*); Nodes bind_instruction(BodyBuilder*, const Node* instruction); Nodes bind_instruction_named(BodyBuilder*, const Node* instruction, String const output_names[]); +Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count); + Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, Node*); Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, Node*); Nodes gen_loop(BodyBuilder*, Nodes, Nodes, Node*); diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index fbaf0c431..b6e22ab0a 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -87,6 +87,10 @@ static const Node* accept_expr(ctxparams, BodyBuilder*, int); static Nodes expect_operands(ctxparams, BodyBuilder*); static const Node* expect_operand(ctxparams, BodyBuilder*); +static const Node* bind_instruction_single(BodyBuilder* bb, const Node* instr) { + return first(bind_instruction_outputs_count(bb, instr, 1)); +} + static const Type* accept_numerical_type(ctxparams) { if (accept_token(ctx, i8_tok)) { return int8_type(arena); @@ -154,6 +158,22 @@ static const Node* accept_numerical_literal(ctxparams) { return n; } +static Nodes accept_type_arguments(ctxparams) { + Nodes ty_args = empty(arena); + if (accept_token(ctx, lsbracket_tok)) { + while (true) { + const Type* t = accept_unqualified_type(ctx); + expect(t); + ty_args = append_nodes(arena, ty_args, t); + if (accept_token(ctx, comma_tok)) + continue; + if (accept_token(ctx, rsbracket_tok)) + break; + } + } + return ty_args; +} + static const Node* accept_value(ctxparams, BodyBuilder* bb) { Token tok = curr_token(tokenizer); size_t size = tok.end - tok.start; @@ -166,6 +186,37 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { case identifier_tok: { const char* id = string_sized(arena, (int) size, &contents[tok.start]); next_token(tokenizer); + + Op op = PRIMOPS_COUNT; + for (size_t i = 0; i < PRIMOPS_COUNT; i++) { + if (strcmp(id, get_primop_name(i)) == 0) { + op = i; + break; + } + } + + if (op != PRIMOPS_COUNT) { + if (!bb) + error("can't have primops here"); + return bind_instruction_single(bb, prim_op(arena, (PrimOp) { + .op = op, + .type_arguments = accept_type_arguments(ctx), + .operands = expect_operands(ctx, bb) + })); + } else if (strcmp(id, "alloca") == 0) { + return bind_instruction_single(bb, stack_alloc(arena, (StackAlloc) { + .type = first(accept_type_arguments(ctx)) + })); + } else if (strcmp(id, "debug_printf") == 0) { + Nodes ops = expect_operands(ctx, bb); + return bind_instruction_single(bb, debug_printf(arena, (DebugPrintf) { + .string = get_string_literal(arena, first(ops)), + .args = nodes(arena, ops.count - 1, &ops.nodes[1]) + })); + } + + if (bb) + return bind_instruction_single(bb, unbound(arena, (Unbound) { .name = id })); return unbound(arena, (Unbound) { .name = id }); } case hex_lit_tok: @@ -428,6 +479,7 @@ static Nodes accept_types(ctxparams, TokenTag separator, Qualified qualified) { } static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { + assert(bb); if (accept_token(ctx, minus_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr); @@ -437,38 +489,39 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { .value = -get_int_literal_value(*resolve_to_int_literal(expr), true) }); } else { - return prim_op(arena, (PrimOp) { + return bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = neg_op, .operands = nodes(arena, 1, (const Node* []) {expr}) - }); + })); } } else if (accept_token(ctx, unary_excl_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr); - return prim_op(arena, (PrimOp) { + return bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = not_op, .operands = singleton(expr), - }); + })); } else if (accept_token(ctx, star_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr); - return prim_op(arena, (PrimOp) { + return bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = deref_op, .operands = singleton(expr), - }); + })); } else if (accept_token(ctx, infix_and_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr); - return prim_op(arena, (PrimOp) { + return bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = addrof_op, .operands = singleton(expr), - }); + })); } return accept_value(ctx, bb); } static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) { + assert(bb); const Node* expr = accept_primary_expr(ctx, bb); while (expr) { InfixOperators infix; @@ -481,78 +534,26 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) expect(rhs); Op primop_op; if (is_primop_op(infix, &primop_op)) { - expr = prim_op(arena, (PrimOp) { + expr = bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = primop_op, .operands = nodes(arena, 2, (const Node* []) {expr, rhs}) - }); + })); } else switch (infix) { default: error("unknown infix operator") } continue; } - Nodes ty_args = nodes(arena, 0, NULL); - bool parse_ty_args = false; - if (accept_token(ctx, lsbracket_tok)) { - parse_ty_args = true; - while (true) { - const Type* t = accept_unqualified_type(ctx); - expect(t); - ty_args = append_nodes(arena, ty_args, t); - if (accept_token(ctx, comma_tok)) - continue; - if (accept_token(ctx, rsbracket_tok)) - break; - } - } switch (curr_token(tokenizer).tag) { case lpar_tok: { Nodes ops = expect_operands(ctx, bb); - - Op op = PRIMOPS_COUNT; - String callee_name = NULL; - if (expr->tag == Unbound_TAG) { - callee_name = expr->payload.unbound.name; - for (size_t i = 0; i < PRIMOPS_COUNT; i++) { - if (strcmp(callee_name, get_primop_name(i)) == 0) { - op = i; - break; - } - } - } - - if (op != PRIMOPS_COUNT) { - expr = prim_op(arena, (PrimOp) { - .op = op, - .type_arguments = ty_args, - .operands = ops - }); - continue; - } - - if (strcmp(callee_name, "alloca") == 0) { - expr = stack_alloc(arena, (StackAlloc) { - .type = first(ty_args) - }); - continue; - } else if (strcmp(callee_name, "debug_printf") == 0) { - expr = debug_printf(arena, (DebugPrintf) { - .string = get_string_literal(arena, first(ops)), - .args = nodes(arena, ops.count - 1, &ops.nodes[1]) - }); - continue; - } - - assert(ty_args.count == 0 && "Function calls do not support type arguments"); - expr = call(arena, (Call) { + expr = bind_instruction_single(bb, call(arena, (Call) { .callee = expr, .args = ops - }); + })); continue; } default: - if (parse_ty_args) - expect(false && "expected function call arguments"); break; } @@ -721,7 +722,7 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { } else { const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; - bind_instruction_outputs_count(bb, instr, 0); + //bind_instruction_outputs_count(bb, instr, 0); } return true; } @@ -731,8 +732,8 @@ static const Node* expect_jump(ctxparams, BodyBuilder* bb) { expect(target); Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return jump(arena, (Jump) { - .target = unbound(arena, (Unbound) { .name = target }), - .args = args + .target = unbound(arena, (Unbound) { .name = target }), + .args = args }); } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index a9fa0ddb2..23213ff87 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -31,11 +31,23 @@ BodyBuilder* begin_body(IrArena* a) { return bb; } +Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count) { + if (outputs_count > 1) { + LARRAY(const Node*, extracted, outputs_count); + for (size_t i = 0; i < outputs_count; i++) + extracted[i] = gen_extract_single(bb, value, int32_literal(bb->arena, i)); + return nodes(bb->arena, outputs_count, extracted); + } else if (outputs_count == 1) + return singleton(value); + else + return empty(bb->arena); +} + static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { if (bb->arena->config.check_types) { assert(is_instruction(instruction) || is_value(instruction)); } - if (is_instruction(instruction)) { + if (is_instruction(instruction) || !bb->arena->config.check_types) { StackEntry entry = { .vars = empty(bb->arena), .structured.payload.let = { @@ -44,15 +56,7 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp }; append_list(StackEntry, bb->stack, entry); } - if (outputs_count > 1) { - LARRAY(const Node*, extracted, outputs_count); - for (size_t i = 0; i < outputs_count; i++) - extracted[i] = gen_extract_single(bb, instruction, int32_literal(bb->arena, i)); - return nodes(bb->arena, outputs_count, extracted); - } else if (outputs_count == 1) - return singleton(instruction); - else - return empty(bb->arena); + return deconstruct_composite(bb->arena, bb, instruction, outputs_count); } Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 05597efc4..9da006b68 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -121,7 +121,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, BodyBuilder* bb, const const Node* ninstruction = rewrite_node(&ctx->rewriter, node->payload.bind_identifiers.instruction); Strings names = node->payload.bind_identifiers.names; - Nodes results = bind_instruction_outputs_count(bb, ninstruction, names.count); + Nodes results = deconstruct_composite(a, bb, ninstruction, names.count); for (size_t i = 0; i < names.count; i++) { String name = names.strings[i]; if (node->payload.bind_identifiers.mutable) { diff --git a/src/shady/passes/normalize.c b/src/shady/passes/normalize.c index e84ae0feb..be704b812 100644 --- a/src/shady/passes/normalize.c +++ b/src/shady/passes/normalize.c @@ -8,13 +8,8 @@ #include -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); - typedef struct Context_ { Rewriter rewriter; - BodyBuilder* bb; - struct Dict* bound; } Context; static const Node* process_node(Context* ctx, const Node* node); @@ -23,15 +18,6 @@ static const Node* force_to_be_value(Context* ctx, const Node* node) { if (node == NULL) return NULL; IrArena* a = ctx->rewriter.dst_arena; - if (is_instruction(node)) { - const Node** found = find_value_dict(const Node*, const Node*, ctx->bound, node); - if (found) - return *found; - const Node* let_bound = process_node(ctx, node); - insert_dict_and_get_result(const Node*, const Node*, ctx->bound, node, let_bound); - return first(bind_instruction_outputs_count(ctx->bb, let_bound, 1)); - } - switch (node->tag) { // All decls map to refdecl/fnaddr case Constant_TAG: @@ -112,48 +98,18 @@ static const Node* process_node(Context* ctx, const Node* node) { // add a builder to each abstraction... switch (node->tag) { - case Function_TAG: { - Node* new = recreate_decl_header_identity(&ctx->rewriter, node); - BodyBuilder* bb = begin_body(a); - Context ctx2 = *ctx; - ctx2.bb = bb; - ctx2.rewriter.rewrite_fn = (RewriteNodeFn) process_node; - ctx2.bound = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node); - new->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); - destroy_dict(ctx2.bound); - return new; - } - case BasicBlock_TAG: { - Node* new = basic_block(a, recreate_params(&ctx->rewriter, node->payload.basic_block.params), node->payload.basic_block.name); - register_processed(&ctx->rewriter, node, new); - register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new->payload.basic_block.params); - BodyBuilder* bb = begin_body(a); - Context ctx2 = *ctx; - ctx2.bb = bb; - ctx2.rewriter.rewrite_fn = (RewriteNodeFn) process_node; - set_abstraction_body(new, finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.basic_block.body))); - return new; - } - case Let_TAG: { - const Node* oinstr = get_let_instruction(node); - //const Node* found = search_processed(r, oinstr); - const Node** found = find_value_dict(const Node*, const Node*, ctx->bound, node); - if (found) - return rewrite_node(r, node->payload.let.in); - const Node* ninstr = rewrite_op(r, NcInstruction, "instruction", oinstr); - insert_dict_and_get_result(const Node*, const Node*, ctx->bound, oinstr, ninstr); - register_processed(r, oinstr, ninstr); - bind_instruction_outputs_count(ctx->bb, ninstr, 0); - return rewrite_node(r, node->payload.let.in); - - //const Node* new = recreate_node_identity(r, node); - //register_processed(r, node, new); - //return new; - } + // case Let_TAG: { + // const Node* ninstr = rewrite_op(r, NcInstruction, "instruction", get_let_instruction(node)); + // register_processed(r, get_let_instruction(node), ninstr); + // return let(a, ninstr, rewrite_op(r, NcTerminator, "in", node->payload.let.in)); + // } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + const Node* new = recreate_node_identity(&ctx->rewriter, node); + if (is_instruction(new)) + register_processed(r, node, new); + return new; } Module* normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -163,8 +119,6 @@ Module* normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process_op), - .bb = NULL, - .bound = NULL, }; ctx.rewriter.config.search_map = false; From fd04fed621ac76e8172843b1a9701d5f44cd83f6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 5 Aug 2024 15:23:53 +0200 Subject: [PATCH 412/693] fix build when llvm is absent --- CMakeLists.txt | 5 +++-- src/frontend/llvm/CMakeLists.txt | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 597cd0ec5..8a38d3dac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,9 @@ else () endif () find_package(LLVM QUIET) +if (LLVM_FOUND) + message("LLVM ${LLVM_VERSION} found") +endif() if(NOT ${LLVM_FOUND} AND WIN32 AND ${SHADY_WIN32_FIX_PARTIAL_LLVM_INSTALL}) find_program(clang_exe "clang.exe") if(${clang_exe} STREQUAL "clang_exe-NOTFOUND") @@ -78,8 +81,6 @@ if(NOT ${LLVM_FOUND} AND WIN32 AND ${SHADY_WIN32_FIX_PARTIAL_LLVM_INSTALL}) message(STATUS "Win32: Installed LLVM ${LLVM_VERSION} found at ${LLVM_DIR}") set(LLVM_FOUND TRUE) endif() -else() - message("LLVM ${LLVM_VERSION} found") endif() include(GNUInstallDirs) diff --git a/src/frontend/llvm/CMakeLists.txt b/src/frontend/llvm/CMakeLists.txt index 9e8f1a4c0..f4f8af10a 100644 --- a/src/frontend/llvm/CMakeLists.txt +++ b/src/frontend/llvm/CMakeLists.txt @@ -4,7 +4,7 @@ else () option (SHADY_ENABLE_LLVM_FRONTEND "Uses LLVM-C to parse and then convert LLVM IR into Shady IR" ON) endif () -if (SHADY_ENABLE_LLVM_FRONTEND) +if (LLVM_FOUND AND SHADY_ENABLE_LLVM_FRONTEND) add_generated_file(FILE_NAME l2s_generated.c SOURCES generator_l2s.c) add_library(shady_fe_llvm STATIC l2s.c l2s_type.c l2s_value.c l2s_instr.c l2s_meta.c l2s_postprocess.c l2s_annotations.c ${CMAKE_CURRENT_BINARY_DIR}/l2s_generated.c) From 74ef093197218a1bd3067f131b72c18a6c8f74a1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 7 Aug 2024 12:29:52 +0200 Subject: [PATCH 413/693] Added mem, removed let and associated scheduled machinery --- include/shady/grammar.json | 141 ++-- include/shady/ir.h | 27 +- include/shady/primops.json | 62 +- src/backend/c/emit_c.c | 9 +- src/backend/c/emit_c_instructions.c | 7 +- src/backend/spirv/emit_spv.c | 14 +- src/backend/spirv/emit_spv_instructions.c | 7 +- src/frontend/llvm/l2s_annotations.c | 2 +- src/frontend/llvm/l2s_value.c | 2 +- src/frontend/slim/parser.c | 45 +- src/frontend/spirv/s2s.c | 13 +- src/shady/CMakeLists.txt | 2 - src/shady/analysis/callgraph.c | 4 +- src/shady/analysis/cfg.c | 10 - src/shady/analysis/cfg_dump.c | 7 - src/shady/analysis/free_variables.c | 8 +- src/shady/analysis/verify.c | 41 +- src/shady/body_builder.c | 110 ++- src/shady/compile.c | 8 +- src/shady/constructors.c | 55 +- src/shady/fold.c | 69 +- src/shady/ir_private.h | 4 +- src/shady/node.c | 83 +- src/shady/passes/bind.c | 25 +- src/shady/passes/cleanup.c | 102 --- src/shady/passes/eliminate_constants.c | 10 +- src/shady/passes/import.c | 2 +- src/shady/passes/infer.c | 41 +- src/shady/passes/lift_indirect_targets.c | 18 +- src/shady/passes/lower_alloca.c | 15 +- src/shady/passes/lower_callf.c | 23 +- src/shady/passes/lower_cf_instrs.c | 29 +- src/shady/passes/lower_entrypoint_args.c | 7 +- src/shady/passes/lower_generic_globals.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 22 +- src/shady/passes/lower_int64.c | 2 +- src/shady/passes/lower_lea.c | 2 +- src/shady/passes/lower_logical_pointers.c | 9 +- src/shady/passes/lower_mask.c | 4 +- src/shady/passes/lower_memcpy.c | 21 +- src/shady/passes/lower_memory_layout.c | 1 - src/shady/passes/lower_nullptr.c | 6 +- src/shady/passes/lower_physical_ptrs.c | 23 +- src/shady/passes/lower_stack.c | 20 +- src/shady/passes/lower_subgroup_ops.c | 10 +- src/shady/passes/lower_subgroup_vars.c | 16 +- src/shady/passes/lower_switch_btree.c | 18 +- src/shady/passes/lower_tailcalls.c | 94 ++- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/lower_workgroups.c | 23 +- src/shady/passes/normalize_builtins.c | 13 +- src/shady/passes/opt_demote_alloca.c | 20 +- src/shady/passes/opt_inline.c | 8 +- src/shady/passes/opt_mem2reg.c | 758 ------------------ src/shady/passes/opt_restructure.c | 150 ++-- src/shady/passes/opt_stack.c | 128 --- src/shady/passes/reconvergence_heuristics.c | 91 +-- src/shady/passes/setup_stack_frames.c | 11 +- src/shady/passes/simt2d.c | 6 +- src/shady/passes/specialize_entry_point.c | 2 +- src/shady/passes/specialize_execution_model.c | 2 +- src/shady/passes/spirv_lift_globals_ssbo.c | 15 +- src/shady/passes/spirv_map_entrypoint_args.c | 1 - src/shady/print.c | 40 +- src/shady/rewrite.c | 21 +- src/shady/rewrite.h | 3 +- src/shady/transform/internal_constants.c | 2 +- src/shady/transform/ir_gen_helpers.c | 4 +- src/shady/type.c | 51 +- 69 files changed, 688 insertions(+), 1915 deletions(-) delete mode 100644 src/shady/passes/opt_mem2reg.c delete mode 100644 src/shady/passes/opt_stack.c diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 552812080..50cde4e0a 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -88,11 +88,21 @@ "name": "param", "generate-enum": false }, + { + "name": "abstraction", + "ops": [ + { "name": "params", "class": "param", "list": true }, + { "name": "body", "class": "terminator", "nullable": true } + ] + }, { "name": "instruction" }, { - "name": "terminator" + "name": "terminator", + "ops": [ + { "name": "mem", "class": "mem" } + ] }, { "name": "declaration", @@ -119,6 +129,9 @@ "ops": [ { "name": "tail", "class": "basic_block" } ] + }, + { + "name": "mem" } ], "nodes": [ @@ -363,11 +376,21 @@ }, { "name": "Call", - "class": ["instruction", "value"], + "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ { "name": "callee", "class": "value" }, - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } + ] + }, + { + "name": "MemAndValue", + "class": ["value", "mem"], + "description": "Associate a value with a mem object, this allows adding side effects to a value", + "ops": [ + { "name": "value", "class": "value" }, + { "name": "mem", "class": "mem" } ] }, { @@ -379,7 +402,8 @@ { "name": "condition", "class": "value" }, { "name": "if_true", "class": "basic_block" }, { "name": "if_false", "class": "basic_block", "nullable": true }, - { "name": "tail", "class": "basic_block" } + { "name": "tail", "class": "basic_block" }, + { "name": "mem", "class": "mem" } ] }, { @@ -392,7 +416,8 @@ { "name": "literals", "class": "value", "list": true }, { "name": "cases", "class": "basic_block", "list": true }, { "name": "default_case", "class": "basic_block" }, - { "name": "tail", "class": "basic_block" } + { "name": "tail", "class": "basic_block" }, + { "name": "mem", "class": "mem" } ] }, { @@ -403,7 +428,8 @@ { "name": "yield_types", "class": "type", "list": true }, { "name": "body", "class": "basic_block" }, { "name": "initial_args", "class": "value", "list": true }, - { "name": "tail", "class": "basic_block" } + { "name": "tail", "class": "basic_block" }, + { "name": "mem", "class": "mem" } ] }, { @@ -412,55 +438,30 @@ "ops": [ { "name": "yield_types", "class": "type", "list": true }, { "name": "inside", "class": "basic_block" }, - { "name": "tail", "class": "basic_block" } - ] - }, - { - "name": "Block", - "class": ["instruction", "value"], - "description": "Used as a helper to insert multiple instructions in place of one", - "ops": [ - { "name": "yield_types", "class": "type", "list": true }, - { "name": "inside", "class": "basic_block" } - ] - }, - { - "name": "CompoundInstruction", - "class": ["instruction", "value"], - "description": "Used as a helper to insert multiple instructions in place of one", - "constructor": "custom", - "ops": [ - { "name": "instructions", "class": "instruction", "list": true }, - { "name": "results", "class": "value", "list": "true" } + { "name": "tail", "class": "basic_block" }, + { "name": "mem", "class": "mem" } ] }, { "name": "Comment", - "class": "instruction", + "class": ["instruction", "mem"], "ops": [ - { "name": "string", "class": "string" } - ] - }, - { - "name": "Let", - "class": "terminator", - "constructor": "custom", - "ops": [ - { "name": "instruction", "class": "instruction" }, - { "name": "in", "class": "terminator" } + { "name": "string", "class": "string" }, + { "name": "mem", "class": "mem" } ] }, { "name": "BindIdentifiers", - "class": "instruction", + "class": ["instruction", "mem"], "constructor": "custom", "front-end-only": true, "type": false, "ops": [ - { "name": "instruction", "class": "instruction" }, + { "name": "value", "class": "value" }, { "name": "mutable", "type": "bool" }, { "name": "names", "class": "string", "list": true }, - { "name": "types", "class": "type", "list": true } + { "name": "types", "class": "type", "list": true }, + { "name": "mem", "class": "mem" } ] }, { @@ -468,7 +469,8 @@ "class": "terminator", "ops": [ { "name": "target", "class": "value" }, - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } ] }, { @@ -476,7 +478,8 @@ "class": ["terminator", "jump"], "ops": [ { "name": "target", "class": "basic_block" }, - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } ] }, { @@ -489,7 +492,8 @@ "ops": [ { "name": "condition", "class": "value" }, { "name": "true_jump", "class": "jump" }, - { "name": "false_jump", "class": "jump" } + { "name": "false_jump", "class": "jump" }, + { "name": "mem", "class": "mem" } ] }, { @@ -501,7 +505,8 @@ { "name": "switch_value", "class": "value" }, { "name": "case_values", "class": "value", "list": true }, { "name": "case_jumps", "class": "jump", "list": true }, - { "name": "default_jump", "class": "jump" } + { "name": "default_jump", "class": "jump" }, + { "name": "mem", "class": "mem" } ] }, { @@ -514,7 +519,8 @@ ], "ops": [ { "name": "join_point", "class": "value" }, - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } ] }, { @@ -522,7 +528,8 @@ "class": "terminator", "nominal": true, "ops": [ - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } ] }, { @@ -530,7 +537,8 @@ "class": "terminator", "nominal": true, "ops": [ - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } ] }, { @@ -538,15 +546,8 @@ "class": "terminator", "nominal": true, "ops": [ - { "name": "args", "class": "value", "list": true } - ] - }, - { - "name": "BlockYield", - "class": "terminator", - "nominal": true, - "ops": [ - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } ] }, { @@ -555,17 +556,21 @@ "class": "terminator", "nominal": true, "ops": [ - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } ] }, { "name": "Unreachable", - "class": "terminator" + "class": "terminator", + "ops": [ + { "name": "mem", "class": "mem" } + ] }, { "name": "Function", "snake_name": "fun", - "class": "declaration", + "class": ["abstraction", "declaration"], "constructor": "custom", "nominal": true, "ops": [ @@ -588,7 +593,7 @@ { "name": "name", "class": "string" }, { "name": "annotations", "class": "annotation", "list": true }, { "name": "type_hint", "class": "type" }, - { "name": "instruction", "class": "instruction", "nullable": true } + { "name": "value", "class": "value", "nullable": true } ] }, { @@ -658,12 +663,21 @@ "name": "BasicBlock", "constructor": "custom", "description": "A named abstraction that lives inside a function and can be jumped to", - "class": "basic_block", + "class": ["abstraction", "basic_block"], "nominal": true, "ops": [ { "name": "params", "class": "param", "list": true }, { "name": "body", "class": "terminator", "nullable": true }, - { "name": "name", "class": "string" } + { "name": "name", "class": "string" }, + { "name": "insert", "type": "BodyBuilder*", "ignore": true } + ] + }, + { + "name": "AbsMem", + "class": "mem", + "type": false, + "ops": [ + { "name": "abs", "class": "abstraction" } ] }, { @@ -672,7 +686,8 @@ "type": false, "front-end-only": true, "ops": [ - { "name": "name", "type": "String" } + { "name": "name", "type": "String" }, + { "name": "mem", "class": "mem", "nullable": true } ] }, { diff --git a/include/shady/ir.h b/include/shady/ir.h index 2be44ba35..d77dbcb1d 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -127,6 +127,8 @@ typedef enum { String get_primop_name(Op op); bool has_primop_got_side_effects(Op op); +typedef struct BodyBuilder_ BodyBuilder; + // see grammar.json #include "grammar_generated.h" @@ -176,22 +178,19 @@ const char* get_annotation_string_payload(const Node* annotation); bool lookup_annotation_with_string_payload(const Node* decl, const char* annotation_name, const char* expected_payload); Nodes filter_out_annotation(IrArena*, Nodes, const char* name); -bool is_abstraction (const Node*); +const Node* get_abstraction_mem(const Node* abs); String get_abstraction_name (const Node* abs); String get_abstraction_name_unsafe(const Node* abs); String get_abstraction_name_safe(const Node* abs); -const Node* get_abstraction_body (const Node* abs); -Nodes get_abstraction_params(const Node* abs); void set_abstraction_body (Node* abs, const Node* body); -const Node* get_let_instruction(const Node* let); -const Node* get_let_chain_end(const Node* terminator); - const Node* maybe_tuple_helper(IrArena* a, Nodes values); const Node* extract_helper(const Node* composite, const Node* index); const Node* extract_multiple_ret_types_helper(const Node* composite, int index); +const Node* maybe_tuple_helper(IrArena* a, Nodes values); + typedef struct { bool enter_loads; bool allow_incompatible_types; @@ -257,8 +256,7 @@ const Node* prim_op_helper(IrArena*, Op, Nodes, Nodes); const Node* compound_instruction(IrArena* arena, Nodes instructions, Nodes results); // terminators -const Node* let(IrArena*, const Node* instruction, const Node* tail); -const Node* jump_helper(IrArena* a, const Node* dst, Nodes args); +const Node* jump_helper(IrArena* a, const Node* dst, Nodes args, const Node* mem); // decl ctors Node* function (Module*, Nodes params, const char* name, Nodes annotations, Nodes return_types); @@ -273,8 +271,9 @@ static inline Node* case_(IrArena* a, Nodes params) { } /// Used to build a chain of let -typedef struct BodyBuilder_ BodyBuilder; -BodyBuilder* begin_body(IrArena*); +BodyBuilder* begin_body_with_mem(IrArena*, const Node*); +BodyBuilder* begin_block_pure(IrArena*); +BodyBuilder* begin_block_with_side_effects(IrArena*); /// Appends an instruction to the builder, may apply optimisations. /// If the arena is typed, returns a list of variables bound to the values yielded by that instruction @@ -288,19 +287,19 @@ Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, Node*); Nodes gen_loop(BodyBuilder*, Nodes, Nodes, Node*); Nodes gen_control(BodyBuilder*, Nodes, Node*); +const Node* bb_mem(BodyBuilder*); + /// Like append bind_instruction, but you explicitly give it information about any yielded values /// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count); const Node* finish_body(BodyBuilder*, const Node* terminator); void cancel_body(BodyBuilder*); -const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder*, Nodes, const Nodes); + +const Node* yield_value_and_wrap_in_block(BodyBuilder*, const Node*); const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); -const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder*, const Node*, const Nodes); const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder*, Nodes); -const Node* bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder*, const Node*, const Nodes); -const Node* bind_last_instruction_and_wrap_in_compound_instruction(BodyBuilder*, const Node*); #endif diff --git a/include/shady/primops.json b/include/shady/primops.json index c33156b91..91f81f394 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -292,35 +292,39 @@ }, { "name": "StackAlloc", - "class": ["instruction", "value"], + "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ - { "name": "type", "class": "type" } + { "name": "type", "class": "type" }, + { "name": "mem", "class": "mem" } ] }, { "name": "LocalAlloc", - "class": ["instruction", "value"], + "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ - { "name": "type", "class": "type" } + { "name": "type", "class": "type" }, + { "name": "mem", "class": "mem" } ] }, { "name": "Load", - "class": ["instruction", "value"], + "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ - { "name": "ptr", "class": "value" } + { "name": "ptr", "class": "value" }, + { "name": "mem", "class": "mem" } ] }, { "name": "Store", - "class": "instruction", + "class": ["instruction", "mem"], "nominal": true, "ops": [ { "name": "ptr", "class": "value" }, - { "name": "value", "class": "value" } + { "name": "value", "class": "value" }, + { "name": "mem", "class": "mem" } ] }, { @@ -334,65 +338,77 @@ }, { "name": "CopyBytes", - "class": "instruction", + "class": ["instruction", "mem"], "nominal": true, "ops": [ { "name": "dst", "class": "value" }, { "name": "src", "class": "value" }, - { "name": "count", "class": "value" } + { "name": "count", "class": "value" }, + { "name": "mem", "class": "mem" } ] }, { "name": "FillBytes", - "class": "instruction", + "class": ["instruction", "mem"], "nominal": true, "ops": [ { "name": "dst", "class": "value" }, { "name": "src", "class": "value" }, - { "name": "count", "class": "value" } + { "name": "count", "class": "value" }, + { "name": "mem", "class": "mem" } ] }, { "name": "PushStack", - "class": "instruction", + "class": ["instruction", "mem", "mem"], "nominal": true, "ops": [ - { "name": "value", "class": "value" } + { "name": "value", "class": "value" }, + { "name": "mem", "class": "mem" } ] }, { "name": "PopStack", - "class": ["instruction", "value"], + "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ - { "name": "type", "class": "type" } + { "name": "type", "class": "type" }, + { "name": "mem", "class": "mem" } ] }, { "name": "GetStackSize", - "class": ["instruction", "value"], - "nominal": true + "class": ["instruction", "value", "mem"], + "nominal": true, + "ops": [ + { "name": "mem", "class": "mem" } + ] }, { "name": "SetStackSize", - "class": "instruction", + "class": ["instruction", "mem"], "nominal": true, "ops": [ - { "name": "value", "class": "value" } + { "name": "value", "class": "value" }, + { "name": "mem", "class": "mem" } ] }, { "name": "GetStackBaseAddr", "class": ["instruction", "value"], - "nominal": true + "nominal": true, + "ops": [ + { "name": "mem", "class": "mem" } + ] }, { "name": "DebugPrintf", - "class": "instruction", + "class": ["instruction", "mem"], "nominal": true, "ops": [ { "name": "string", "class": "string" }, - { "name": "args", "class": "value", "list": true } + { "name": "args", "class": "value", "list": true }, + { "name": "mem", "class": "mem" } ] } ] diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 5c91b8366..2ae7b3dde 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -538,9 +538,8 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node case Jump_TAG: case Branch_TAG: case Switch_TAG: - case Terminator_BlockYield_TAG: case TailCall_TAG: error("TODO"); - case Let_TAG: { + /*case Let_TAG: { const Node* instruction = get_let_instruction(terminator); // we declare N local variables in order to store the result of the instruction @@ -589,7 +588,7 @@ static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node emit_terminator(emitter, block_printer, terminator->payload.let.in); break; - } + }*/ case If_TAG: return emit_if(emitter, block_printer, terminator->payload.if_instr); case Match_TAG: return emit_match(emitter, block_printer, terminator->payload.match_instr); case Loop_TAG: return emit_loop(emitter, block_printer, terminator->payload.loop_instr); @@ -777,9 +776,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { emit_as = term_from_cvalue(name); register_emitted(emitter, decl, emit_as); - const Node* init_value = resolve_node_to_definition(decl->payload.constant.instruction, (NodeResolveConfig) { 0 }); - assert(init_value && "TODO: support some measure of constant expressions"); - String init = to_cvalue(emitter, emit_value(emitter, NULL, init_value)); + String init = to_cvalue(emitter, emit_value(emitter, NULL, decl->payload.constant.value)); emit_global_variable_definition(emitter, AsGlobal, decl_center, decl->type, true, init); return; } diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 618bddf49..aa9d0618c 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -714,7 +714,7 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_BindIdentifiers_TAG: error("front-end only!"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; - case Instruction_CompoundInstruction_TAG: { + /*case Instruction_CompoundInstruction_TAG: { Nodes instructions = instruction->payload.compound_instruction.instructions; for (size_t i = 0; i < instructions.count; i++) { const Node* instruction2 = instructions.nodes[i]; @@ -738,9 +738,8 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins outputs.binding[0] = NoBinding; } return; - } - case Instruction_Block_TAG: error("Should be eliminated by the compiler") - case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; + }*/ + case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; case Instruction_StackAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.stack_alloc.type, outputs); case Instruction_LocalAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.local_alloc.type, outputs); case Instruction_Load_TAG: { diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 79162052b..1e8870b02 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -127,14 +127,7 @@ SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { break; } case Constant_TAG: { - const Node* init_value = resolve_node_to_definition(decl->payload.constant.instruction, (NodeResolveConfig) { 0 }); - if (!init_value && bb_builder) { - SpvId r; - emit_instruction(emitter, NULL, bb_builder, decl->payload.constant.instruction, 1, &r); - return r; - } - assert(init_value && "TODO: support some measure of constant expressions"); - new = emit_value(emitter, NULL, init_value); + new = emit_value(emitter, NULL, decl->payload.constant.value); break; } default: error("RefDecl must reference a constant or global"); @@ -380,7 +373,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo } } } - case Let_TAG: { + /*case Let_TAG: { const Node* instruction = terminator->payload.let.instruction; Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction->type); LARRAY(SpvId, results, types.count); @@ -390,7 +383,7 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo register_result(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); emit_terminator(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.let.in); return; - } + }*/ case Jump_TAG: { add_branch_phis(emitter, fn_builder, basic_block_builder, terminator); spvb_branch(basic_block_builder, find_reserved_id(emitter, terminator->payload.jump.target)); @@ -420,7 +413,6 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo return; } case Terminator_Control_TAG: - case Terminator_BlockYield_TAG: case TailCall_TAG: case Join_TAG: error("Lower me"); case MergeSelection_TAG: { diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 4857f90d5..ec121fbf9 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -388,12 +388,11 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build case Instruction_CopyBytes_TAG: case Instruction_FillBytes_TAG: case Instruction_BindIdentifiers_TAG: - case Instruction_StackAlloc_TAG: - case Instruction_Block_TAG: error("Should be lowered elsewhere") + case Instruction_StackAlloc_TAG: error("Should be lowered elsewhere") case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call, results_count, results); break; case PrimOp_TAG: emit_primop(emitter, fn_builder, bb_builder, instruction, results_count, results); break; case Comment_TAG: break; - case Instruction_CompoundInstruction_TAG: { + /*case Instruction_CompoundInstruction_TAG: { Nodes instructions = instruction->payload.compound_instruction.instructions; for (size_t i = 0; i < instructions.count; i++) { const Node* instruction2 = instructions.nodes[i]; @@ -409,7 +408,7 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build results[0] = emit_value(emitter, bb_builder, results2.nodes[i]); } return; - } + }*/ case Instruction_LocalAlloc_TAG: { SpvId result = spvb_local_variable(fn_builder, emit_type(emitter, ptr_type(emitter->arena, (PtrType) { .address_space = AsFunction, diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index ec0ff5ede..7397219a3 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -31,7 +31,7 @@ static const Node* assert_and_strip_fn_addr(const Node* fn) { static const Node* look_past_stuff(const Node* thing) { if (thing->tag == Constant_TAG) { - const Node* instr = thing->payload.constant.instruction; + const Node* instr = thing->payload.constant.value; assert(instr->tag == PrimOp_TAG); thing = instr; } diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index 49c2beb17..f5bb5b966 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -85,7 +85,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { insert_dict(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = begin_body(a); EmittedInstr emitted = convert_instruction(p, NULL, NULL, bb, v); - decl->payload.constant.instruction = bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(bb, emitted.instruction, singleton(t)); + decl->payload.constant.value = bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(bb, emitted.instruction, singleton(t)); return r; } case LLVMConstantDataArrayValueKind: { diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index b6e22ab0a..a40042719 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -80,7 +80,7 @@ static const char* accept_identifier(ctxparams) { return NULL; } -static const Node* expect_body(ctxparams, const Node* default_terminator); +static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator); static const Node* accept_value(ctxparams, BodyBuilder*); static const Type* accept_unqualified_type(ctxparams); static const Node* accept_expr(ctxparams, BodyBuilder*, int); @@ -608,14 +608,14 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { const Node* merge = config.front_end ? merge_selection(arena, (MergeSelection) { .args = nodes(arena, 0, NULL) }) : NULL; Node* true_case = case_(arena, nodes(arena, 0, NULL)); - set_abstraction_body(true_case, expect_body(ctx, merge)); + set_abstraction_body(true_case, expect_body(ctx, get_abstraction_mem(true_case), merge)); // else defaults to an empty body bool has_else = accept_token(ctx, else_tok); Node* false_case = NULL; if (has_else) { false_case = case_(arena, nodes(arena, 0, NULL)); - set_abstraction_body(false_case, expect_body(ctx, merge)); + set_abstraction_body(false_case, expect_body(ctx, get_abstraction_mem(false_case), merge)); } return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, true_case, false_case)); } @@ -628,7 +628,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { // by default loops continue forever const Node* default_loop_end_behaviour = config.front_end ? merge_continue(arena, (MergeContinue) { .args = nodes(arena, 0, NULL) }) : NULL; Node* loop_case = case_(arena, parameters); - set_abstraction_body(loop_case, expect_body(ctx, default_loop_end_behaviour)); + set_abstraction_body(loop_case, expect_body(ctx, get_abstraction_mem(loop_case), default_loop_end_behaviour)); return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, loop_case)); } case control_tok: { @@ -642,7 +642,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { }), str); expect(accept_token(ctx, rpar_tok)); Node* control_case = case_(arena, singleton(jp)); - set_abstraction_body(control_case, expect_body(ctx, NULL)); + set_abstraction_body(control_case, expect_body(ctx, get_abstraction_mem(control_case), NULL)); return maybe_tuple_helper(arena, gen_control(bb, yield_types, control_case)); } default: break; @@ -733,7 +733,8 @@ static const Node* expect_jump(ctxparams, BodyBuilder* bb) { Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return jump(arena, (Jump) { .target = unbound(arena, (Unbound) { .name = target }), - .args = args + .args = args, + .mem = bb_mem(bb) }); } @@ -756,11 +757,11 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { const Node* false_target = expect_jump(ctx, bb); expect(accept_token(ctx, rpar_tok)); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return branch(arena, (Branch) { .condition = condition, .true_jump = true_target, .false_jump = false_target, + .mem = bb_mem(bb) }); } case switch_tok: { @@ -794,34 +795,39 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { .case_values = values, .case_jumps = cases, .default_jump = default_jump, + .mem = bb_mem(bb) }); } case return_tok: { next_token(tokenizer); Nodes args = expect_operands(ctx, bb); return fn_ret(arena, (Return) { - .args = args + .args = args, + .mem = bb_mem(bb) }); } case merge_selection_tok: { next_token(tokenizer); Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return merge_selection(arena, (MergeSelection) { - .args = args + .args = args, + .mem = bb_mem(bb) }); } case continue_tok: { next_token(tokenizer); Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return merge_continue(arena, (MergeContinue) { - .args = args + .args = args, + .mem = bb_mem(bb) }); } case break_tok: { next_token(tokenizer); Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return merge_break(arena, (MergeBreak) { - .args = args + .args = args, + .mem = bb_mem(bb) }); } case join_tok: { @@ -832,23 +838,24 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { Nodes args = expect_operands(ctx, bb); return join(arena, (Join) { .join_point = jp, - .args = args + .args = args, + .mem = bb_mem(bb) }); } case unreachable_tok: { next_token(tokenizer); expect(accept_token(ctx, lpar_tok)); expect(accept_token(ctx, rpar_tok)); - return unreachable(arena); + return unreachable(arena, (Unreachable) { bb_mem(bb) }); } default: break; } return NULL; } -static const Node* expect_body(ctxparams, const Node* default_terminator) { +static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator) { expect(accept_token(ctx, lbracket_tok)); - BodyBuilder* bb = begin_body(arena); + BodyBuilder* bb = begin_body_with_mem(arena, mem); while (true) { if (!accept_statement(ctx, bb)) @@ -877,7 +884,7 @@ static const Node* expect_body(ctxparams, const Node* default_terminator) { Nodes parameters; expect_parameters(ctx, ¶meters, NULL, bb); Node* continuation = basic_block(arena, parameters, name); - continuation->payload.basic_block.body = expect_body(ctx, NULL); + continuation->payload.basic_block.body = expect_body(ctx, get_abstraction_mem(continuation), NULL); append_list(Node*, conts, continuation); } @@ -958,14 +965,14 @@ static const Node* accept_const(ctxparams, Nodes annotations) { const char* id = accept_identifier(ctx); expect(id); expect(accept_token(ctx, equal_tok)); - BodyBuilder* bb = begin_body(arena); + BodyBuilder* bb = begin_block_pure(arena); const Node* definition = accept_expr(ctx, bb, max_precedence()); expect(definition); expect(accept_token(ctx, semi_tok)); Node* cnst = constant(mod, annotations, type, id); - cnst->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(definition)); + cnst->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(definition)); return cnst; } @@ -982,7 +989,7 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { Node* fn = function(mod, parameters, name, annotations, types); if (!accept_token(ctx, semi_tok)) - fn->payload.fun.body = expect_body(ctx, types.count == 0 ? fn_ret(arena, (Return) { .args = types }) : NULL); + fn->payload.fun.body = expect_body(ctx, get_abstraction_mem(fn), types.count == 0 ? fn_ret(arena, (Return) { .args = types }) : NULL); const Node* declaration = fn; expect(declaration); diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index e43086b8f..fb2999f6b 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -898,7 +898,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { Node* block = basic_block(parser->arena, params, bb_name); parser->defs[result].node = block; - BodyBuilder* bb = begin_body(parser->arena); + BodyBuilder* bb = begin_body_with_mem(parser->arena, get_abstraction_mem(block)); parser->current_block.builder = bb; parser->current_block.finished = NULL; while (parser->current_block.builder) { @@ -1280,8 +1280,9 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpBranch: { BodyBuilder* bb = parser->current_block.builder; parser->current_block.finished = finish_body(bb, jump(parser->arena, (Jump) { - .target = get_def_block(parser, instruction[1]), - .args = get_args_from_phi(parser, instruction[1], parser->current_block.id), + .target = get_def_block(parser, instruction[1]), + .args = get_args_from_phi(parser, instruction[1], parser->current_block.id), + .mem = bb_mem(bb) })); parser->current_block.builder = NULL; break; @@ -1290,9 +1291,9 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { SpvId destinations[2] = { instruction[2], instruction[3] }; BodyBuilder* bb = parser->current_block.builder; parser->current_block.finished = finish_body(bb, branch(parser->arena, (Branch) { - .true_jump = jump_helper(parser->arena, get_def_block(parser, destinations[0]), get_args_from_phi(parser, destinations[0], parser->current_block.id)), - .false_jump = jump_helper(parser->arena, get_def_block(parser, destinations[1]), get_args_from_phi(parser, destinations[1], parser->current_block.id)), - .condition = get_def_ssa_value(parser, instruction[1]), + .true_jump = jump_helper(parser->arena, get_def_block(parser, destinations[0]), get_args_from_phi(parser, destinations[0], parser->current_block.id), bb_mem(bb)), + .false_jump = jump_helper(parser->arena, get_def_block(parser, destinations[1]), get_args_from_phi(parser, destinations[1], parser->current_block.id), bb_mem(bb)), + .condition = get_def_ssa_value(parser, instruction[1]), })); parser->current_block.builder = NULL; break; diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 71d78fc3e..be7afabc6 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -84,9 +84,7 @@ set(SHADY_SOURCES passes/lower_generic_globals.c passes/mark_leaf_functions.c passes/opt_inline.c - passes/opt_stack.c passes/opt_restructure.c - passes/opt_mem2reg.c passes/opt_demote_alloca.c passes/reconvergence_heuristics.c passes/simt2d.c diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index d4e29636e..075caa048 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -235,7 +235,7 @@ CallGraph* new_callgraph(Module* mod) { .abs = NULL, }; search_for_callsites(&v, decl->payload.global_variable.init); - } else if (decl->tag == Constant_TAG && decl->payload.constant.instruction) { + } else if (decl->tag == Constant_TAG && decl->payload.constant.value) { CGVisitor v = { .visitor = { .visit_node_fn = (VisitNodeFn) search_for_callsites @@ -244,7 +244,7 @@ CallGraph* new_callgraph(Module* mod) { .root = NULL, .abs = NULL, }; - search_for_callsites(&v, decl->payload.constant.instruction); + search_for_callsites(&v, decl->payload.constant.value); } } diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index fc1d8ea0d..9eed93490 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -145,13 +145,6 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { return; while (true) { switch (is_terminator(terminator)) { - case Let_TAG: { - terminator = terminator->payload.let.in; - continue; - // const Node* target = get_let_tail(terminator); - // add_structural_dominance_edge(ctx, node, target, LetTailEdge); - // break; - } case Jump_TAG: { add_jump_edge(ctx, abs, terminator); return; @@ -201,9 +194,6 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { case MergeBreak_TAG: { return; // TODO i guess } - case Terminator_BlockYield_TAG: { - return; - } case TailCall_TAG: case Return_TAG: case Unreachable_TAG: diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index aefff4df0..09d99900c 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -50,13 +50,6 @@ static void dump_cf_node(FILE* output, const CFNode* n) { print(p, "%s: \n%s: ", abs_name, abs_name); - while (body->tag == Let_TAG) { - print_node_helper(p, body); - print(p, "\\l"); - - body = body->payload.let.in; - } - print_node_helper(p, body); print(p, "\\l"); diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index 179079d5b..a1036f9af 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -84,17 +84,11 @@ static void dump_free_variables(Context* ctx, CFNode* cfnode, int depth) { static void search_op_for_free_variables(Context* visitor, NodeClass class, String op_name, const Node* node) { assert(node); switch (node->tag) { - case Let_TAG: { - const Node* instr = get_let_instruction(node); - bool r = insert_set_get_result(const Node*, visitor->bound, instr); - //assert(r); - break; - } case Function_TAG: case BasicBlock_TAG: assert(false); default: break; } - if (node->tag == Param_TAG || is_instruction(node)) + if (node->tag == Param_TAG) insert_set_get_result(const Node*, visitor->live, node); visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK, node); } diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 6f49ae229..4fd506085 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -85,8 +85,8 @@ static void verify_nominal_node(const Node* fn, const Node* n) { break; } case Constant_TAG: { - if (n->payload.constant.instruction) { - const Type* t = n->payload.constant.instruction->type; + if (n->payload.constant.value) { + const Type* t = n->payload.constant.value->type; bool u = deconstruct_qualified_type(&t); assert(u); assert(is_subtype(n->payload.constant.type_hint, t)); @@ -134,41 +134,6 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { visit_node_operands(&ctx->visitor, NcTerminator | NcDeclaration, node); } -static void verify_schedule_node(ScheduleContext* parent, CompilerConfig* config, Module* mod, CFNode* node) { - ScheduleContext new = { - .visitor = { - .visit_node_fn = (VisitNodeFn) verify_schedule_visitor - }, - .bound = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .parent = parent, - .config = config, - .mod = mod, - }; - struct List* dominated = node->dominates; - size_t len = entries_count_list(dominated); - - const Node* terminator = get_abstraction_body(node->node); - while (terminator) { - if (terminator->tag != Let_TAG) - break; - const Node* instr = get_let_instruction(terminator); - insert_set_get_key(const Node*, new.bound, instr); - visit_node_operands(&new.visitor, NcTerminator | NcDeclaration, instr); - terminator = terminator->payload.let.in; - } - - for (size_t i = 0; i < len; i++) { - verify_schedule_node(&new, config, mod, read_list(CFNode*, dominated)[i]); - } - - destroy_dict(new.bound); -} - -static void verify_schedule(const CompilerConfig* config, Module* mod, CFG* cfg) { - compute_domtree(cfg); - verify_schedule_node(NULL, config, mod, cfg->entry); -} - static void verify_bodies(const CompilerConfig* config, Module* mod) { struct List* cfgs = build_cfgs(mod); for (size_t i = 0; i < entries_count_list(cfgs); i++) { @@ -181,8 +146,6 @@ static void verify_bodies(const CompilerConfig* config, Module* mod) { } } - verify_schedule(config, mod, cfg); - destroy_cfg(cfg); } destroy_list(cfgs); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 23213ff87..599f9f7fb 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -22,15 +22,33 @@ typedef struct { Nodes vars; } StackEntry; -BodyBuilder* begin_body(IrArena* a) { +BodyBuilder* begin_body_with_mem(IrArena* a, const Node* mem) { BodyBuilder* bb = malloc(sizeof(BodyBuilder)); *bb = (BodyBuilder) { .arena = a, .stack = new_list(StackEntry), + .mem0 = mem, + .mem = mem, }; return bb; } +BodyBuilder* begin_block_with_side_effects(IrArena* a) { + Node* block = basic_block(a, empty(a), NULL); + BodyBuilder* builder = begin_body_with_mem(a, get_abstraction_mem(block)); + builder->bb = block; + return builder; +} + +BodyBuilder* begin_block_pure(IrArena* a) { + BodyBuilder* builder = begin_body_with_mem(a, NULL); + return builder; +} + +const Node* bb_mem(BodyBuilder* bb) { + return bb->mem; +} + Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count) { if (outputs_count > 1) { LARRAY(const Node*, extracted, outputs_count); @@ -47,15 +65,8 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp if (bb->arena->config.check_types) { assert(is_instruction(instruction) || is_value(instruction)); } - if (is_instruction(instruction) || !bb->arena->config.check_types) { - StackEntry entry = { - .vars = empty(bb->arena), - .structured.payload.let = { - .instruction = instruction, - } - }; - append_list(StackEntry, bb->stack, entry); - } + if (is_mem(instruction)) + bb->mem = instruction; return deconstruct_composite(bb->arena, bb, instruction, outputs_count); } @@ -70,15 +81,15 @@ Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String co return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count); } -const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes types); +const Node* bind_identifiers(IrArena* arena, const Node* instruction, const Node* mem, bool mut, Strings names, Nodes types); Nodes parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names) { - const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, true, output_names, provided_types); + const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, bb->mem, true, output_names, provided_types); return bind_internal(bb, let_mut_instr, 0); } Nodes parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names) { - const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, false, output_names, empty(bb->arena)); + const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, bb->mem, false, output_names, empty(bb->arena)); return bind_internal(bb, let_mut_instr, 0); } @@ -92,9 +103,7 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { for (size_t i = stack_size - 1; i < stack_size; i--) { StackEntry entry = read_list(StackEntry, bb->stack)[i]; switch (entry.structured.tag) { - case NotAStructured_construct: - terminator = let(a, entry.structured.payload.let.instruction, terminator); - break; + case NotAStructured_construct: error("") case Structured_construct_If_TAG: { Node* tail = basic_block(bb->arena, entry.vars, NULL); set_abstraction_body(tail, terminator); @@ -129,71 +138,52 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { } const Node* finish_body(BodyBuilder* bb, const Node* terminator) { + assert(bb->mem0); terminator = build_body(bb, terminator); destroy_list(bb->stack); free(bb); return terminator; } -const Node* yield_values_and_wrap_in_block_explicit_return_types(BodyBuilder* bb, Nodes values, const Nodes types) { - IrArena* arena = bb->arena; - const Node* terminator = block_yield(arena, (BlockYield) { .args = values }); - const Node* block_case = case_(arena, empty(arena)); - set_abstraction_body(block_case, finish_body(bb, terminator)); - return block(arena, (Block) { - .yield_types = types, - .inside = block_case, +const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { + IrArena* a = bb->arena; + if (entries_count_list(bb->stack) == 0) { + const Node* last_mem = bb_mem(bb); + cancel_body(bb); + if (last_mem) + return mem_and_value(a, (MemAndValue) { + .mem = last_mem, + .value = value + }); + return value; + } + assert(bb->bb && "This builder wasn't started with 'begin_block'"); + bb->bb->payload.basic_block.insert = bb; + const Node* r = mem_and_value(bb->arena, (MemAndValue) { + .mem = bb_mem(bb), + .value = value }); + return r; } const Node* yield_values_and_wrap_in_block(BodyBuilder* bb, Nodes values) { - return yield_values_and_wrap_in_block_explicit_return_types(bb, values, get_values_types(bb->arena, values)); + return yield_value_and_wrap_in_block(bb, maybe_tuple_helper(bb->arena, values)); } -const Node* bind_last_instruction_and_wrap_in_block_explicit_return_types(BodyBuilder* bb, const Node* instruction, const Nodes types) { +const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* instruction) { size_t stack_size = entries_count_list(bb->stack); if (stack_size == 0) { cancel_body(bb); return instruction; } - Nodes bound = bind_internal(bb, instruction, types.count); - return yield_values_and_wrap_in_block_explicit_return_types(bb, bound, types); -} - -const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* instruction) { - return bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type)); -} - -static Nodes finish_with_instruction_list(BodyBuilder* bb) { - IrArena* a = bb->arena; - size_t count = entries_count_list(bb->stack); - LARRAY(const Node*, list, count); - for (size_t i = 0; i < count; i++) { - StackEntry entry = read_list(StackEntry, bb->stack)[i]; - if (entry.structured.tag != NotAStructured_construct) { - error("When using a BodyBuilder to create compound instructions, control flow is not allowed.") - } - list[i] = entry.structured.payload.let.instruction; - } - - destroy_list(bb->stack); - free(bb); - return nodes(a, count, list); + bind_internal(bb, instruction, 0); + return yield_value_and_wrap_in_block(bb, instruction); } const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { IrArena* arena = bb->arena; - return compound_instruction(arena, finish_with_instruction_list(bb), values); -} - -const Node* bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(BodyBuilder* bb, const Node* instruction, const Nodes types) { - IrArena* arena = bb->arena; - Nodes values = bind_instruction_outputs_count(bb, instruction, types.count); - return compound_instruction(arena, finish_with_instruction_list(bb), values); -} - -const Node* bind_last_instruction_and_wrap_in_compound_instruction(BodyBuilder* bb, const Node* instruction) { - return bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type)); + assert(!bb->mem0 && !bb->stack); + return maybe_tuple_helper(arena, values); } static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { diff --git a/src/shady/compile.c b/src/shady/compile.c index 70ef5fb0c..eab4fccc8 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -54,7 +54,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(reconvergence_heuristics) RUN_PASS(lower_cf_instrs) - RUN_PASS(opt_mem2reg) // run because control-flow is now normalized + //RUN_PASS(opt_mem2reg) // run because control-flow is now normalized RUN_PASS(setup_stack_frames) if (!config->hacks.force_join_point_lifting) RUN_PASS(mark_leaf_functions) @@ -63,7 +63,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(opt_inline) RUN_PASS(lift_indirect_targets) - RUN_PASS(opt_mem2reg) // run because we can now weaken non-leaking allocas + //RUN_PASS(opt_mem2reg) // run because we can now weaken non-leaking allocas RUN_PASS(specialize_execution_model) @@ -72,7 +72,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_tailcalls) RUN_PASS(lower_switch_btree) RUN_PASS(opt_restructurize) - RUN_PASS(opt_mem2reg) + //RUN_PASS(opt_mem2reg) if (config->specialization.entry_point) RUN_PASS(specialize_entry_point) @@ -85,7 +85,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { if (config->lower.emulate_physical_memory) { RUN_PASS(lower_alloca) } - RUN_PASS(lower_stack) + //RUN_PASS(lower_stack) RUN_PASS(lower_lea) RUN_PASS(lower_generic_globals) if (config->lower.emulate_generic_ptrs) { diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 21b6ecdac..78a4ce626 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -59,51 +59,6 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { #include "constructors_generated.c" -const Node* let(IrArena* arena, const Node* instruction, const Node* in) { - // This is like a folding opt, but earlier, simplifies things by allowing to rewrite an instruction into a value - if (!is_instruction(instruction) && is_value(instruction)) - return in; - - Let payload = { - .instruction = instruction, - .in = in, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .tag = Let_TAG, - .payload.let = payload - }; - return create_node_helper(arena, node, NULL); -} - -const Node* compound_instruction(IrArena* arena, Nodes instructions, Nodes results) { - LARRAY(const Node*, ninstructions, instructions.count); - size_t count = 0; - for (size_t i = 0; i < instructions.count; i++) { - const Node* instr = instructions.nodes[i]; - if (is_instruction(instr)) - ninstructions[count++] = instr; - } - instructions = nodes(arena, count, ninstructions); - - CompoundInstruction payload = { - .instructions = instructions, - .results = results, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .tag = CompoundInstruction_TAG, - .payload.compound_instruction = payload - }; - return create_node_helper(arena, node, NULL); -} - Node* param(IrArena* arena, const Type* type, const char* name) { Param param = { .type = type, @@ -120,12 +75,13 @@ Node* param(IrArena* arena, const Type* type, const char* name) { return create_node_helper(arena, node, NULL); } -const Node* bind_identifiers(IrArena* arena, const Node* instruction, bool mut, Strings names, Nodes types) { +const Node* bind_identifiers(IrArena* arena, const Node* value, const Node* mem, bool mut, Strings names, Nodes types) { BindIdentifiers payload = { - .instruction = instruction, + .value = value, .mutable = mut, .names = names, .types = types, + .mem = mem, }; Node node; @@ -233,7 +189,7 @@ Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { .annotations = annotations, .name = string(arena, name), .type_hint = hint, - .instruction = NULL, + .value = NULL, }; Node node; memset((void*) &node, 0, sizeof(Node)); @@ -308,10 +264,11 @@ const Node* prim_op_helper(IrArena* a, Op op, Nodes types, Nodes operands) { }); } -const Node* jump_helper(IrArena* a, const Node* dst, Nodes args) { +const Node* jump_helper(IrArena* a, const Node* dst, Nodes args, const Node* mem) { return jump(a, (Jump) { .target = dst, .args = args, + .mem = mem, }); } diff --git a/src/shady/fold.c b/src/shady/fold.c index 21b985900..320ae6cb8 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -178,7 +178,7 @@ static inline const Node* fold_simplify_math(const Node* node) { return NULL; } -static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { +static inline const Node* resolve_ptr_source(const Node* ptr) { const Node* original_ptr = ptr; IrArena* a = ptr->arena; const Type* t = ptr->type; @@ -241,30 +241,28 @@ static inline const Node* resolve_ptr_source(BodyBuilder* bb, const Node* ptr) { if (new_src_ptr_type->tag != PtrType_TAG || new_src_ptr_type->payload.ptr_type.pointed_type != desired_pointee_type) { PtrType payload = t->payload.ptr_type; payload.address_space = src_as; - ptr = gen_reinterpret_cast(bb, ptr_type(a, payload), ptr); + ptr = prim_op_helper(a, reinterpret_op, singleton(ptr_type(a, payload)), singleton(ptr)); } return ptr; } - return original_ptr; + return NULL; } -static inline const Node* simplify_ptr_operand(IrArena* a, BodyBuilder* bb, const Node* old_op) { +static inline const Node* simplify_ptr_operand(IrArena* a, const Node* old_op) { const Type* ptr_t = old_op->type; deconstruct_qualified_type(&ptr_t); if (ptr_t->payload.ptr_type.is_reference) return NULL; - const Node* new_op = resolve_ptr_source(bb, old_op); - return old_op != new_op ? new_op : NULL; + return resolve_ptr_source(old_op); } static inline const Node* fold_simplify_ptr_operand(const Node* node) { IrArena* arena = node->arena; - BodyBuilder* bb = begin_body(arena); const Node* r = NULL; switch (node->tag) { case Load_TAG: { Load payload = node->payload.load; - const Node* nptr = simplify_ptr_operand(arena, bb, payload.ptr); + const Node* nptr = simplify_ptr_operand(arena, payload.ptr); if (!nptr) break; payload.ptr = nptr; r = load(arena, payload); @@ -272,7 +270,7 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { } case Store_TAG: { Store payload = node->payload.store; - const Node* nptr = simplify_ptr_operand(arena, bb, payload.ptr); + const Node* nptr = simplify_ptr_operand(arena, payload.ptr); if (!nptr) break; payload.ptr = nptr; r = store(arena, payload); @@ -280,28 +278,21 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { } case Lea_TAG: { Lea payload = node->payload.lea; - const Node* nptr = simplify_ptr_operand(arena, bb, payload.ptr); + const Node* nptr = simplify_ptr_operand(arena, payload.ptr); if (!nptr) break; payload.ptr = nptr; r = lea(arena, payload); break; } - default: { - cancel_body(bb); - return node; - } + default: return node; } - if (!r) { - cancel_body(bb); + if (!r) return node; - } - if (!is_subtype(node->type, r->type)) { - r = gen_conversion(bb, get_unqualified_type(node->type), first(bind_instruction(bb, r))); - return yield_values_and_wrap_in_block(bb, singleton(r)); - } - return bind_last_instruction_and_wrap_in_block(bb, r); + if (!is_subtype(node->type, r->type)) + r = prim_op_helper(arena, convert_op, singleton(get_unqualified_type(node->type)), singleton(r)); + return r; } static const Node* fold_prim_op(IrArena* arena, const Node* node) { @@ -383,36 +374,6 @@ const Node* fold_node(IrArena* arena, const Node* node) { node = fold_simplify_ptr_operand(node); switch (node->tag) { case PrimOp_TAG: node = fold_prim_op(arena, node); break; - case Block_TAG: { - const Node* lam = node->payload.block.inside; - const Node* body = get_abstraction_body(lam); - if (body->tag == BlockYield_TAG) { - return maybe_tuple_helper(arena, body->payload.block_yield.args); - } else if (body->tag == Let_TAG) { - // fold block { let x, y, z = I; yield (x, y, z); } back to I - const Node* instr = get_let_instruction(body); - const Node* let_case_body = body->payload.let.in; - if (let_case_body->tag == BlockYield_TAG) { - bool only_forwards = true; - Nodes let_case_params = empty(arena); - Nodes yield_args = let_case_body->payload.block_yield.args; - if (let_case_params.count == yield_args.count) { - for (size_t i = 0; i < yield_args.count; i++) { - only_forwards &= yield_args.nodes[i] == let_case_params.nodes[i]; - } - if (only_forwards) { - log_string(DEBUGVV, "Fold: simplify "); - log_node(DEBUGVV, node); - log_string(DEBUGVV, " into just "); - log_node(DEBUGVV, instr); - log_string(DEBUGVV, ".\n"); - return instr; - } - } - } - } - break; - } case Branch_TAG: { Branch payload = node->payload.branch; if (arena->config.optimisations.fold_static_control_flow) { @@ -448,11 +409,11 @@ const Node* fold_node(IrArena* arena, const Node* node) { if (new_cases_count == old_cases.count) break; - if (new_cases_count == 1 && is_unreachable_case(payload.default_case)) + /*if (new_cases_count == 1 && is_unreachable_case(payload.default_case)) return block(arena, (Block) { .inside = cases[0], .yield_types = add_qualifiers(arena, payload.yield_types, false) }); if (new_cases_count == 0) - return block(arena, (Block) { .inside = payload.default_case, .yield_types = add_qualifiers(arena, payload.yield_types, false) }); + return block(arena, (Block) { .inside = payload.default_case, .yield_types = add_qualifiers(arena, payload.yield_types, false) });*/ return match_instr(arena, (Match) { .inspect = payload.inspect, diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index 294d3222b..747ef94d7 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -37,7 +37,9 @@ void destroy_module(Module* m); struct BodyBuilder_ { IrArena* arena; struct List* stack; - //struct List* stack_stack; + const Node* mem0; + const Node* mem; + Node* bb; }; NodeId allocate_node_id(IrArena*, const Node* n); diff --git a/src/shady/node.c b/src/shady/node.c index 6a7e66564..a01ed0038 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -162,32 +162,11 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi while (node) { switch (node->tag) { case Constant_TAG: - node = node->payload.constant.instruction; + node = node->payload.constant.value; continue; case RefDecl_TAG: node = node->payload.ref_decl.decl; continue; - case Block_TAG: { - const Node* terminator = get_abstraction_body(node->payload.block.inside); - while (true) { - if (terminator->tag == Let_TAG) - terminator = terminator->payload.let.in; - else if (is_structured_construct(terminator)) - terminator = get_abstraction_body(get_structured_construct_tail(terminator)); - else - break; - } - if (terminator->tag == BlockYield_TAG) { - assert(terminator->payload.block_yield.args.count == 1); - return resolve_node_to_definition(first(terminator->payload.block_yield.args), config); - } - return NULL; - } - case CompoundInstruction_TAG: { - if (node->payload.compound_instruction.results.count == 1) - return resolve_node_to_definition(first(node->payload.compound_instruction.results), config); - return NULL; - } case Load_TAG: { if (config.enter_loads) { const Node* source = node->payload.load.ptr; @@ -255,7 +234,7 @@ const char* get_string_literal(IrArena* arena, const Node* node) { break; } case Declaration_Constant_TAG: { - return get_string_literal(arena, node->payload.constant.instruction); + return get_string_literal(arena, node->payload.constant.value); } case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; @@ -291,9 +270,8 @@ const char* get_string_literal(IrArena* arena, const Node* node) { return NULL; } -bool is_abstraction(const Node* node) { - NodeTag tag = node->tag; - return tag == Function_TAG || tag == BasicBlock_TAG; +const Node* get_abstraction_mem(const Node* abs) { + return abs_mem(abs->arena, (AbsMem) { abs }); } String get_abstraction_name(const Node* abs) { @@ -321,48 +299,41 @@ String get_abstraction_name_safe(const Node* abs) { return format_string_interned(abs->arena, "%%%d", abs->id); } -const Node* get_abstraction_body(const Node* abs) { - assert(is_abstraction(abs)); - switch (abs->tag) { - case Function_TAG: return abs->payload.fun.body; - case BasicBlock_TAG: return abs->payload.basic_block.body; - default: assert(false); - } +const Node* get_original_mem(const Node* mem) { + error("TODO"); + return mem; } void set_abstraction_body(Node* abs, const Node* body) { assert(is_abstraction(abs)); assert(!body || is_terminator(body)); + IrArena* a = abs->arena; switch (abs->tag) { case Function_TAG: abs->payload.fun.body = body; break; - case BasicBlock_TAG: abs->payload.basic_block.body = body; break; - default: assert(false); - } -} - -Nodes get_abstraction_params(const Node* abs) { - assert(is_abstraction(abs)); - switch (abs->tag) { - case Function_TAG: return abs->payload.fun.params; - case BasicBlock_TAG: return abs->payload.basic_block.params; - default: assert(false); - } -} + case BasicBlock_TAG: { + while (true) { + const Node* mem0 = get_original_mem(get_terminator_mem(body)); + assert(is_abstraction(mem0)); + if (is_basic_block(mem0)) { + BodyBuilder* insert = mem0->payload.basic_block.insert; + if (insert) { + const Node* mem = insert->mem0; + set_abstraction_body((Node*) mem0, finish_body(insert, body)); + body = jump_helper(a, mem0, empty(a), mem); + continue; + } + assert(mem0 == abs); + } + break; + } -const Node* get_let_instruction(const Node* let) { - switch (let->tag) { - case Let_TAG: return let->payload.let.instruction; + abs->payload.basic_block.body = body; + break; + } default: assert(false); } } -const Node* get_let_chain_end(const Node* terminator) { - while (terminator->tag == Let_TAG) { - terminator = terminator->payload.let.in; - } - return terminator; -} - KeyHash hash_node_payload(const Node* node); KeyHash hash_node(Node** pnode) { diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 9da006b68..69044c4ea 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -115,10 +115,12 @@ static const Node* get_node_address(Context* ctx, const Node* node) { return got; } -static const Node* desugar_bind_identifiers(Context* ctx, BodyBuilder* bb, const Node* node) { +static const Node* desugar_bind_identifiers(Context* ctx, const Node* node) { assert(node->tag == BindIdentifiers_TAG); - IrArena* a = ctx->rewriter.dst_arena; - const Node* ninstruction = rewrite_node(&ctx->rewriter, node->payload.bind_identifiers.instruction); + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.bind_identifiers.mem)); + const Node* ninstruction = rewrite_node(r, node->payload.bind_identifiers.value); Strings names = node->payload.bind_identifiers.names; Nodes results = deconstruct_composite(a, bb, ninstruction, names.count); @@ -140,7 +142,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, BodyBuilder* bb, const } } - return tuple_helper(a, empty(a)); + return yield_values_and_wrap_in_block(bb, empty(a)); } static const Node* rewrite_decl(Context* ctx, const Node* decl) { @@ -157,7 +159,7 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { const Constant* cnst = &decl->payload.constant; Node* bound = constant(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, cnst->annotations), rewrite_node(&ctx->rewriter, decl->payload.constant.type_hint), cnst->name); register_processed(&ctx->rewriter, decl, bound); - bound->payload.constant.instruction = rewrite_node(&ctx->rewriter, decl->payload.constant.instruction); + bound->payload.constant.value = rewrite_node(&ctx->rewriter, decl->payload.constant.value); return bound; } case Function_TAG: { @@ -270,18 +272,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { new_bb->payload.basic_block.body = rewrite_node(&ctx->rewriter, node->payload.basic_block.body); return new_bb; } - case Let_TAG: { - const Node* oinstruction = node->payload.let.instruction; - const Node* ninstr; - BodyBuilder* bb = begin_body(a); - if (oinstruction->tag == BindIdentifiers_TAG) { - ninstr = desugar_bind_identifiers(ctx, bb, oinstruction); - } else { - ninstr = rewrite_node(r, oinstruction); - } - return finish_body(bb, let(a, ninstr, rewrite_node(r, node->payload.let.in))); - } - case BindIdentifiers_TAG: assert(false); + case BindIdentifiers_TAG: return desugar_bind_identifiers(ctx, node); case Return_TAG: { assert(ctx->current_function); return fn_ret(a, (Return) { diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 690f6aac8..e4e726469 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -32,67 +32,6 @@ static size_t count_calls(const UsesMap* map, const Node* bb) { return count; } -Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constructTag tag, union NodesUnion payload); - -static void reset_params(Nodes params) { - for (size_t i = 0; i < params.count; i++) - ((Node*) params.nodes[i])->payload.param.abs = NULL; -} - -// eliminates blocks by "lifting" their contents out and replacing yield with the tail of the outer let -// In other words, we turn these patterns: -// -// let block { -// let I in case(x) => -// let J in case(y) => -// let K in case(z) => -// ... -// yield (x, y, z) } -// in case(a, b, c) => R -// -// into these: -// -// let I in case(x) => -// let J in case(y) => -// let K in case(z) => -// ... -// R[a->x, b->y, c->z] -const Node* flatten_block(IrArena* arena, const Node* instruction, BodyBuilder* bb) { - assert(instruction->tag == Block_TAG); - // follow the terminator of the block until we hit a yield() - const Node* const lam = instruction->payload.block.inside; - const Node* terminator = get_abstraction_body(lam); - while (true) { - if (is_structured_construct(terminator)) { - Nodes params = get_abstraction_params(get_structured_construct_tail(terminator)); - reset_params(params); - add_structured_construct(bb, params, (Structured_constructTag) terminator->tag, terminator->payload); - terminator = get_abstraction_body(get_structured_construct_tail(terminator)); - continue; - } - - switch (is_terminator(terminator)) { - case NotATerminator: assert(false); - case Terminator_Let_TAG: { - add_structured_construct(bb, empty(arena), (Structured_constructTag) NotAStructured_construct, terminator->payload); - terminator = terminator->payload.let.in; - continue; - } - case Terminator_BlockYield_TAG: { - return maybe_tuple_helper(arena, terminator->payload.block_yield.args); - } - case Terminator_Return_TAG: - case Terminator_TailCall_TAG: { - return terminator; - } - // if we see anything else, give up - default: { - assert(false && "invalid block"); - } - } - } -} - static bool has_side_effects(const Node* instr) { bool side_effects = true; if (instr->tag == PrimOp_TAG) @@ -116,47 +55,6 @@ const Node* process(Context* ctx, const Node* old) { } switch (old->tag) { - case Let_TAG: { - Let payload = old->payload.let; - bool consumed = false; - Nodes result_types = unwrap_multiple_yield_types(a, payload.instruction->type); - for (size_t i = 0; i < result_types.count; i++) { - const Use* use = get_first_use(ctx->map, extract_multiple_ret_types_helper(payload.instruction, i)); - assert(use); - for (;use; use = use->next_use) { - if (use->user == old) - continue; - consumed = true; - break; - } - if (consumed) - break; - } - if (!consumed && !has_side_effects(payload.instruction) && ctx->rewriter.dst_arena) { - debugvv_print("Cleanup: found an unused instruction: "); - log_node(DEBUGVV, payload.instruction); - debugvv_print("\n"); - *ctx->todo = true; - return rewrite_node(&ctx->rewriter, payload.in); - } - - BodyBuilder* bb = begin_body(a); - const Node* oinstruction = old->payload.let.instruction; - const Node* instruction; - // optimization: fold blocks - if (oinstruction->tag == Block_TAG) { - *ctx->todo = true; - instruction = flatten_block(a, recreate_node_identity(r, oinstruction), bb); - register_processed(r, oinstruction, instruction); - if (is_terminator(instruction)) - return finish_body(bb, instruction); - } else { - instruction = rewrite_node(r, oinstruction); - register_processed(r, oinstruction, instruction); - } - const Node* nlet = let(a, instruction, rewrite_node(r, old->payload.let.in)); - return finish_body(bb, nlet); - } case BasicBlock_TAG: { size_t uses = count_calls(ctx->map, old); if (uses <= 1) { diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 26e68ceef..8ab4cad1c 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -20,26 +20,26 @@ static const Node* process(Context* ctx, const Node* node) { Context c = *ctx; ctx = &c; if (is_abstraction(node)) { - c.bb = abs_bb = begin_body(a); + c.bb = abs_bb = begin_block_pure(a); } switch (node->tag) { case Constant_TAG: - if (!node->payload.constant.instruction) + if (!node->payload.constant.value) break; if (!ctx->all && !lookup_annotation(node, "Inline")) break; return NULL; case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; - if (decl->tag == Constant_TAG && decl->payload.constant.instruction) { - const Node* value = resolve_node_to_definition(decl->payload.constant.instruction, (NodeResolveConfig) { 0 }); + if (decl->tag == Constant_TAG && decl->payload.constant.value) { + const Node* value = resolve_node_to_definition(decl->payload.constant.value, (NodeResolveConfig) { 0 }); if (value) return rewrite_node(&ctx->rewriter, value); c.rewriter.map = clone_dict(c.rewriter.map); assert(ctx->bb); // TODO: actually _copy_ the instruction so we can duplicate the code safely! - const Node* rewritten = first(bind_instruction(ctx->bb, rewrite_node(&ctx->rewriter, decl->payload.constant.instruction))); + const Node* rewritten = first(bind_instruction(ctx->bb, rewrite_node(&ctx->rewriter, decl->payload.constant.value))); destroy_dict(c.rewriter.map); return rewritten; } diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 98c4a6cac..f77819bee 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -44,7 +44,7 @@ const Node* import_node(Rewriter* r, const Node* node) { replace_or_compare(&existing->payload.fun.body, rewrite_node(r, node->payload.fun.body)); break; case Declaration_Constant_TAG: - replace_or_compare(&existing->payload.constant.instruction, rewrite_node(r, node->payload.constant.instruction)); + replace_or_compare(&existing->payload.constant.value, rewrite_node(r, node->payload.constant.value)); break; case Declaration_GlobalVariable_TAG: replace_or_compare(&existing->payload.global_variable.init, rewrite_node(r, node->payload.global_variable.init)); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 0195b3bd2..ceb6747fc 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -123,10 +123,10 @@ static const Node* infer_decl(Context* ctx, const Node* node) { if (imported_hint) { assert(is_data_type(imported_hint)); const Node* s = qualified_type_helper(imported_hint, true); - if (oconstant->instruction) - instruction = infer(ctx, oconstant->instruction, s); - } else if (oconstant->instruction) { - instruction = infer(ctx, oconstant->instruction, NULL); + if (oconstant->value) + instruction = infer(ctx, oconstant->value, s); + } else if (oconstant->value) { + instruction = infer(ctx, oconstant->value, NULL); } if (instruction) imported_hint = get_unqualified_type(instruction->type); @@ -134,7 +134,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { Node* nconstant = constant(ctx->rewriter.dst_module, infer_nodes(ctx, oconstant->annotations), imported_hint, oconstant->name); register_processed(&ctx->rewriter, node, nconstant); - nconstant->payload.constant.instruction = instruction; + nconstant->payload.constant.value = instruction; return nconstant; } @@ -355,7 +355,7 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp Nodes type_args = infer_nodes(ctx, old_type_args); Nodes old_operands = node->payload.prim_op.operands; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); Op op = node->payload.prim_op.op; LARRAY(const Node*, new_operands, old_operands.count); Nodes input_types = empty(a); @@ -527,22 +527,6 @@ static const Node* infer_control(Context* ctx, const Node* node) { }); } -static const Node* infer_block(Context* ctx, const Node* node, const Nodes* expected_types) { - assert(node->tag == Block_TAG); - IrArena* a = ctx->rewriter.dst_arena; - - Context block_inside_ctx = *ctx; - Nodes nyield_types = infer_nodes(ctx, node->payload.block.yield_types); - block_inside_ctx.merge_types = &nyield_types; - Node* new_case = basic_block(a, empty(a), NULL); - set_abstraction_body(new_case, infer(&block_inside_ctx, get_abstraction_body(node->payload.block.inside), NULL)); - - return block(a, (Block) { - .yield_types = nyield_types, - .inside = new_case - }); -} - static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes* expected_types) { IrArena* a = ctx->rewriter.dst_arena; switch (is_instruction(node)) { @@ -556,7 +540,6 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes } case PrimOp_TAG: return infer_primop(ctx, node, expected_types); case Call_TAG: return infer_indirect_call(ctx, node, expected_types); - case Block_TAG: return infer_block (ctx, node, expected_types); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); case Instruction_Lea_TAG: { Lea payload = node->payload.lea; @@ -603,7 +586,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { case Match_TAG: error("TODO") case Loop_TAG: return infer_loop (ctx, node); case Control_TAG: return infer_control(ctx, node); - case Let_TAG: { + /*case Let_TAG: { // const Node* otail = node->payload.let.ttail; // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); const Node* inferred_instruction = infer(ctx, node->payload.let.instruction, NULL); @@ -614,7 +597,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { assert(is_value_type(inferred_yield_types.nodes[i])); } return let(a, inferred_instruction, infer(ctx, node->payload.let.in, NULL)); - } + }*/ case Return_TAG: { const Node* imported_fn = ctx->current_fn; Nodes return_types = imported_fn->payload.fun.return_types; @@ -644,7 +627,6 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { }); } case Branch_TAG: - case Terminator_BlockYield_TAG: case Terminator_Switch_TAG: break; case Terminator_TailCall_TAG: break; case Terminator_MergeSelection_TAG: { @@ -693,11 +675,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { .args = nodes(a, old_args.count, new_args) }); } - case Unreachable_TAG: return unreachable(a); - case Terminator_Join_TAG: return join(a, (Join) { - .join_point = infer(ctx, node->payload.join.join_point, NULL), - .args = infer_nodes(ctx, node->payload.join.args), - }); + default: break; } return recreate_node_identity(&ctx->rewriter, node); } @@ -756,7 +734,6 @@ Module* infer_program(SHADY_UNUSED const CompilerConfig* config, Module* src) { }; //ctx.rewriter.config.search_map = false; //ctx.rewriter.config.write_map = false; - ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); return dst; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index d11b75b1b..cc4024ff6 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -120,7 +120,8 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable Context lifting_ctx = *ctx; lifting_ctx.rewriter = create_children_rewriter(&ctx->rewriter); - register_processed_list(&lifting_ctx.rewriter, ovariables, new_params); + Rewriter* r = &lifting_ctx.rewriter; + register_processed_list(r, ovariables, new_params); const Node* payload = param(a, qualified_type_helper(uint32_type(a), false), "sp"); @@ -131,13 +132,13 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable lifted_cont->lifted_fn = new_fn; // Recover that stuff inside the new body - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_set_stack_size(bb, payload); for (size_t i = recover_context_size - 1; i < recover_context_size; i--) { const Node* ovar = read_list(const Node*, recover_context)[i]; // assert(ovar->tag == Variable_TAG); - const Type* value_type = rewrite_node(&ctx->rewriter, ovar->type); + const Type* value_type = rewrite_node(r, ovar->type); String param_name = get_value_name_unsafe(ovar); const Node* recovered_value = gen_pop_value_stack(bb, get_unqualified_type(value_type)); @@ -147,14 +148,15 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable if (is_qualified_type_uniform(ovar->type)) recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }), ¶m_name)); - register_processed(&lifting_ctx.rewriter, ovar, recovered_value); + register_processed(r, ovar, recovered_value); } - const Node* substituted = rewrite_node(&lifting_ctx.rewriter, obody); - destroy_rewriter(&lifting_ctx.rewriter); + register_processed(r, get_abstraction_mem(liftee), bb_mem(bb)); + const Node* substituted = rewrite_node(r, obody); + destroy_rewriter(r); assert(is_terminator(substituted)); - new_fn->payload.fun.body = finish_body(bb, substituted); + set_abstraction_body(new_fn, finish_body(bb, substituted)); return lifted_cont; } @@ -198,7 +200,7 @@ static const Node* process_node(Context* ctx, const Node* node) { *ctx->todo = true; const Node* otail = get_structured_construct_tail(node); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.control.mem)); LiftedCont* lifted_tail = lambda_lift(ctx, otail, get_abstraction_params(otail)); const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 181f45e25..40a5514b0 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -74,11 +74,12 @@ static const Node* process(Context* ctx, const Node* node) { const Node* found = search_processed(&ctx->rewriter, node); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; - Module* m = ctx->rewriter.dst_module; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + Module* m = r->dst_module; switch (node->tag) { case Function_TAG: { - Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); + Node* fun = recreate_decl_header_identity_no_register(&ctx->rewriter, node); if (!node->payload.fun.body) return fun; @@ -89,7 +90,7 @@ static const Node* process(Context* ctx, const Node* node) { return fun; } - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); ctx2.prepared_offsets = new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); ctx2.base_stack_addr_on_entry = gen_get_stack_base_addr(bb); ctx2.stack_size_on_entry = gen_get_stack_size(bb); @@ -120,7 +121,9 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.frame_size = gen_primop_e(bb, size_of_op, singleton(type_decl_ref_helper(a, vctx.nom_t)), empty(a)); ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); - fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); + // make sure to use the new mem from then on + register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(node))); destroy_dict(ctx2.prepared_offsets); return fun; @@ -136,7 +139,7 @@ static const Node* process(Context* ctx, const Node* node) { error_die(); } - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.stack_alloc.mem)); if (!ctx->stack_size_on_entry) { //String tmp_name = format_string_arena(a->arena, "stack_ptr_before_alloca_%s", get_abstraction_name(fun)); assert(false); diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 5dedcd2a2..3c2ebb040 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -32,7 +32,6 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { ctx2.return_jp = NULL; Node* fun = NULL; - BodyBuilder* bb = begin_body(a); if (!ctx2.disable_lowering) { Nodes oparams = get_abstraction_params(old); Nodes nparams = recreate_params(&ctx->rewriter, oparams); @@ -44,7 +43,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { }); if (lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { - ctx2.return_jp = gen_primop_e(bb, default_join_point_op, empty(a), empty(a)); + ctx2.return_jp = prim_op_helper(a, default_join_point_op, empty(a), empty(a)); } else { const Node* jp_variable = param(a, qualified_type_helper(jp_type, false), "return_jp"); nparams = append_nodes(a, nparams, jp_variable); @@ -58,9 +57,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { } else fun = recreate_decl_header_identity(&ctx->rewriter, old); if (old->payload.fun.body) - fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body)); - else - cancel_body(bb); + set_abstraction_body(fun, rewrite_node(&ctx2.rewriter, old->payload.fun.body)); return fun; } @@ -86,12 +83,13 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { const Node* return_jp = ctx->return_jp; if (return_jp) { - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, old->payload.fn_ret.mem)); return_jp = gen_primop_ce(bb, subgroup_broadcast_first_op, 1, (const Node* []) {return_jp}); // Join up at the return address instead of returning return finish_body(bb, join(a, (Join) { - .join_point = return_jp, - .args = nargs, + .join_point = return_jp, + .args = nargs, + .mem = bb_mem(bb), })); } else { assert(false); @@ -100,7 +98,8 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { // we convert calls to tail-calls within a control - only if the // call_indirect(...) to control(jp => save(jp); tailcall(...)) case Call_TAG: { - const Node* ocallee = old->payload.call.callee; + Call payload = old->payload.call; + const Node* ocallee = payload.callee; // if we know the callee and it's a leaf - then we don't change the call if (ocallee->tag == FnAddr_TAG && lookup_annotation(ocallee->payload.fn_addr.fn, "Leaf")) break; @@ -113,7 +112,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { // Rewrite the callee and its arguments const Node* ncallee = rewrite_node(&ctx->rewriter, ocallee); - Nodes nargs = rewrite_nodes(&ctx->rewriter, old->payload.call.args); + Nodes nargs = rewrite_nodes(&ctx->rewriter, payload.args); // Create the body of the control that receives the appropriately typed join point const Type* jp_type = qualified_type(a, (QualifiedType) { @@ -130,9 +129,9 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .target = ncallee, .args = nargs, }); - const Node* control_case = case_(a, singleton(jp)); + Node* control_case = case_(a, singleton(jp)); set_abstraction_body(control_case, control_body); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, old->payload.call.mem)); return yield_values_and_wrap_in_block(bb, gen_control(bb, strip_qualifiers(a, returned_types), control_case)); } default: break; diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 763728f3e..12fb8f471 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -72,6 +72,7 @@ static const Node* process_node(Context* ctx, const Node* node) { case If_TAG: { bool has_false_branch = node->payload.if_instr.if_false; Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.if_instr.yield_types); + const Node* nmem = rewrite_node(r, node->payload.if_instr.mem); const Type* jp_type = qualified_type(a, (QualifiedType) { .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), @@ -95,14 +96,14 @@ static const Node* process_node(Context* ctx, const Node* node) { flse_block->payload.basic_block.body = join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL) }); } + BodyBuilder* bb = begin_body_with_mem(a, nmem); + Node* control_case = basic_block(a, singleton(jp), NULL); const Node* control_body = branch(a, (Branch) { .condition = rewrite_node(r, node->payload.if_instr.condition), - .true_jump = jump_helper(a, true_block, empty(a)), - .false_jump = jump_helper(a, flse_block, empty(a)), + .true_jump = jump_helper(a, true_block, empty(a), get_abstraction_mem(control_case)), + .false_jump = jump_helper(a, flse_block, empty(a), get_abstraction_mem(control_case)), + .mem = get_abstraction_mem(control_case), }); - - BodyBuilder* bb = begin_body(a); - Node* control_case = basic_block(a, singleton(jp), NULL); set_abstraction_body(control_case, control_body); Nodes results = gen_control(bb, yield_types, control_case); @@ -110,7 +111,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* join = basic_block(a, recreate_params(r, get_abstraction_params(otail)), NULL); register_processed_list(r, get_abstraction_params(otail), get_abstraction_params(join)); set_abstraction_body(join, rewrite_node(r, get_abstraction_body(otail))); - return finish_body(bb, jump_helper(a, join, results)); + return finish_body(bb, jump_helper(a, join, results, bb_mem(bb))); // return control(a) //return yield_values_and_wrap_in_block(bb, ); } @@ -145,7 +146,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* inner_control_case = case_(a, singleton(continue_point)); set_abstraction_body(inner_control_case, inner_control_body); - BodyBuilder* inner_bb = begin_body(a); + BodyBuilder* inner_bb = begin_body_with_mem(a, get_abstraction_mem(inner_control_case)); Nodes args = gen_control(inner_bb, param_types, inner_control_case); // TODO let_in_block or use a Jump ! @@ -155,9 +156,9 @@ static const Node* process_node(Context* ctx, const Node* node) { .target = loop_body, .args = rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.initial_args), }); - BodyBuilder* outer_bb = begin_body(a); Node* outer_control_case = case_(a, singleton(break_point)); + BodyBuilder* outer_bb = begin_body_with_mem(a, get_abstraction_mem(outer_control_case)); Nodes results = gen_control(outer_bb, yield_types, outer_control_case); set_abstraction_body(outer_control_case, initial_jump); @@ -165,7 +166,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* join = basic_block(a, recreate_params(r, get_abstraction_params(otail)), NULL); register_processed_list(r, get_abstraction_params(otail), get_abstraction_params(join)); set_abstraction_body(join, rewrite_node(r, get_abstraction_body(otail))); - return finish_body(outer_bb, jump_helper(a, join, results)); + return finish_body(outer_bb, jump_helper(a, join, results, bb_mem(outer_bb))); } case MergeSelection_TAG: { if (!cfnode) @@ -173,7 +174,7 @@ static const Node* process_node(Context* ctx, const Node* node) { CFNode* dom = cfnode->idom; const Node* selection_instr = NULL; while (dom) { - const Node* body = get_let_chain_end(get_abstraction_body(dom->node)); + const Node* body = get_abstraction_body(dom->node); if(body->tag == If_TAG || body->tag == Match_TAG) { selection_instr = body; break; @@ -195,6 +196,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return join(a, (Join) { .join_point = jp, .args = rewrite_nodes(&ctx->rewriter, node->payload.merge_selection.args), + .mem = rewrite_node(r, node->payload.merge_selection.mem) }); } case MergeContinue_TAG: { @@ -202,7 +204,7 @@ static const Node* process_node(Context* ctx, const Node* node) { CFNode* dom = cfnode->idom; const Node* selection_instr = NULL; while (dom) { - const Node* body = get_let_chain_end(get_abstraction_body(dom->node)); + const Node* body = get_abstraction_body(dom->node); if (body->tag == Loop_TAG) { selection_instr = body; break; @@ -224,6 +226,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return join(a, (Join) { .join_point = jp, .args = rewrite_nodes(&ctx->rewriter, node->payload.merge_continue.args), + .mem = rewrite_node(r, node->payload.merge_continue.mem) }); } case MergeBreak_TAG: { @@ -231,7 +234,7 @@ static const Node* process_node(Context* ctx, const Node* node) { CFNode* dom = cfnode->idom; const Node* selection_instr = NULL; while (dom) { - const Node* body = get_let_chain_end(get_abstraction_body(dom->node)); + const Node* body = get_abstraction_body(dom->node); if (body->tag == Loop_TAG) { selection_instr = body; break; @@ -253,6 +256,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return join(a, (Join) { .join_point = jp, .args = rewrite_nodes(&ctx->rewriter, node->payload.merge_break.args), + .mem = rewrite_node(r, node->payload.merge_break.mem) }); } default: break; @@ -271,7 +275,6 @@ Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .structured_join_tokens = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), }; - ctx.rewriter.config.fold_quote = false; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); destroy_dict(ctx.structured_join_tokens); diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 770238414..f896cfc83 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -57,10 +57,10 @@ static const Node* generate_arg_struct(Rewriter* rewriter, const Node* old_entry return ref_decl_helper(a, var); } -static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const Node* arg_struct) { +static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const Node* new, const Node* arg_struct) { IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); Nodes params = old_entry_point->payload.fun.params; @@ -70,6 +70,7 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const register_processed(&ctx->rewriter, params.nodes[i], val); } + register_processed(&ctx->rewriter, get_abstraction_mem(old_entry_point), bb_mem(bb)); return finish_body(bb, rewrite_node(&ctx->rewriter, old_entry_point->payload.fun.body)); } @@ -83,7 +84,7 @@ static const Node* process(Context* ctx, const Node* node) { if (lookup_annotation(node, "EntryPoint") && node->payload.fun.params.count > 0) { Node* new_entry_point = rewrite_entry_point_fun(ctx, node); const Node* arg_struct = generate_arg_struct(&ctx->rewriter, node, new_entry_point); - new_entry_point->payload.fun.body = rewrite_body(ctx, node, arg_struct); + new_entry_point->payload.fun.body = rewrite_body(ctx, node, new_entry_point, arg_struct); return new_entry_point; } break; diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 1f91cfc8f..854614b6a 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -25,7 +25,7 @@ static const Node* process(Context* ctx, const Node* node) { Node* constant_decl = constant(ctx->rewriter.dst_module, decl_annotations, dst_t, format_string_interned(a, "%s_generic", get_declaration_name(node))); const Node* result = constant_decl; - constant_decl->payload.constant.instruction = prim_op_helper(a, convert_op, singleton(dst_t), singleton(ref_decl_helper(a, new_global))); + constant_decl->payload.constant.value = prim_op_helper(a, convert_op, singleton(dst_t), singleton(ref_decl_helper(a, new_global))); register_processed(&ctx->rewriter, node, result); new_global->payload.global_variable.init = rewrite_node(&ctx->rewriter, node->payload.global_variable.init); return result; diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index b7f3ccda0..eafe77a17 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -105,10 +105,10 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { cases[tag] = case_(a, empty(a)); - set_abstraction_body(cases[tag], unreachable(a)); + set_abstraction_body(cases[tag], unreachable(a, (Unreachable) { .mem = get_abstraction_mem(cases[tag]) })); continue; } - BodyBuilder* case_bb = begin_body(a); + BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(cases[tag])); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); cases[tag] = case_(a, empty(a)); @@ -117,15 +117,15 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo }))); } - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, empty(a)); - set_abstraction_body(default_case, unreachable(a)); + set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), default_case)); - new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value) })); + new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value), .mem = bb_mem(bb) })); break; } case StoreFn: { @@ -135,10 +135,10 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { cases[tag] = case_(a, empty(a)); - set_abstraction_body(cases[tag], unreachable(a)); + set_abstraction_body(cases[tag], unreachable(a, (Unreachable) { .mem = get_abstraction_mem(cases[tag]) })); continue; } - BodyBuilder* case_bb = begin_body(a); + BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(cases[tag])); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); cases[tag] = case_(a, empty(a)); @@ -147,15 +147,15 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo }))); } - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, empty(a)); - set_abstraction_body(default_case, unreachable(a)); + set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(new_fn) })); gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), default_case); - new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); + new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) })); break; } } @@ -219,7 +219,7 @@ static const Node* process(Context* ctx, const Node* old) { // cast _into_ generic AddressSpace src_as = old_src_t->payload.ptr_type.address_space; size_t tag = get_tag_for_addr_space(src_as); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); String x = format_string_arena(a->arena, "Generated generic ptr convert src %d tag %d", src_as, tag); gen_comment(bb, x); const Node* src_ptr = rewrite_node(&ctx->rewriter, old_src); diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index ba0b23271..2e73c535e 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -62,7 +62,7 @@ static const Node* process(Context* ctx, const Node* node) { case add_op: if (should_convert(ctx, first(old_nodes)->type)) { Nodes new_nodes = rewrite_nodes(&ctx->rewriter, old_nodes); // TODO: convert into and then out of unsigned - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); extract_low_hi_halves_list(bb, new_nodes, lows, his); Nodes low_and_carry = bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_carry_op, .operands = nodes(a, 2, lows)})); const Node* lo = first(low_and_carry); diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 1fbfa1b42..3e87106f7 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -122,7 +122,7 @@ static const Node* process(Context* ctx, const Node* old) { must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference && is_as_emulated(ctx, old_base_ptr_t->payload.ptr_type.address_space); if (!must_lower) break; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, rewrite_node(r, lea.ptr)); const Type* new_base_t = rewrite_node(&ctx->rewriter, old_base_ptr_t); diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 215b6e6b4..f9a7419f5 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -64,7 +64,7 @@ static const Node* process(Context* ctx, const Node* old) { const Type* expected_type = rewrite_node(r, optr_t); const Node* ptr = rewrite_node(r, payload.ptr); const Type* actual_type = get_unqualified_type(ptr->type); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); return bind_last_instruction_and_wrap_in_block(bb, lea(a, (Lea) { ptr, rewrite_node(r, payload.offset), rewrite_nodes(r, payload.indices)})); @@ -92,10 +92,10 @@ static const Node* process(Context* ctx, const Node* old) { const Type* expected_type = rewrite_node(r, optr_t); const Node* ptr = rewrite_node(r, payload.ptr); const Type* actual_type = get_unqualified_type(ptr->type); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); - return bind_last_instruction_and_wrap_in_block(bb, load(a, (Load) { ptr })); + return load(a, (Load) { .ptr = yield_value_and_wrap_in_block(bb, ptr), .mem = rewrite_node(r, payload.mem) }); } case Store_TAG: { Store payload = old->payload.store; @@ -105,10 +105,11 @@ static const Node* process(Context* ctx, const Node* old) { const Type* expected_type = rewrite_node(r, optr_t); const Node* ptr = rewrite_node(r, payload.ptr); const Type* actual_type = get_unqualified_type(ptr->type); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { ptr, rewrite_node(r, payload.value) })); + return store(a, (Store) { .ptr = ptr, .value = rewrite_node(r, payload.value), .mem = rewrite_node(r, payload.mem) }); } case GlobalVariable_TAG: { AddressSpace as = old->payload.global_variable.address_space; diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 2a0a1d85e..8de917539 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -30,7 +30,7 @@ static const Node* process(Context* ctx, const Node* node) { return prim_op(a, (PrimOp) { .op = subgroup_ballot_op, .type_arguments = empty(a), .operands = singleton(true_lit(ctx->rewriter.dst_arena)) }); // extract the relevant bit case mask_is_thread_active_op: { - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); const Node* mask = rewrite_node(&ctx->rewriter, old_nodes.nodes[0]); const Node* index = rewrite_node(&ctx->rewriter, old_nodes.nodes[1]); index = gen_conversion(bb, get_actual_mask_type(ctx->rewriter.dst_arena), index); @@ -41,7 +41,7 @@ static const Node* process(Context* ctx, const Node* node) { acc = gen_primop_ce(bb, and_op, 2, (const Node* []) { acc, ctx->one }); // acc == 1 acc = gen_primop_ce(bb, eq_op, 2, (const Node* []) { acc, ctx->one }); - return yield_values_and_wrap_in_block(bb, singleton(acc)); + return yield_value_and_wrap_in_block(bb, acc); } default: break; } diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 49f1197eb..f56e82d48 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -19,15 +19,16 @@ static const Node* process(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; - Module* m = ctx->rewriter.dst_module; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + Module* m = r->dst_module; switch (old->tag) { case CopyBytes_TAG: { CopyBytes payload = old->payload.copy_bytes; const Type* word_type = int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* dst_addr = rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; @@ -53,7 +54,8 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num_in_bytes)); const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memcpy_i"); - BodyBuilder* loop_bb = begin_body(a); + Node* loop_case = case_(a, singleton(index)); + BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, empty(a))); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); @@ -62,8 +64,7 @@ static const Node* process(Context* ctx, const Node* old) { Node* false_case = case_(a, empty(a)); set_abstraction_body(false_case, merge_break(a, (MergeBreak) {.args = empty(a)})); gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), true_case, false_case); - Node* loop_case = case_(a, singleton(index)); - set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a))); + set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a, (Unreachable) { .mem = bb_mem(loop_bb) }))); gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), loop_case); return yield_values_and_wrap_in_block(bb, empty(a)); } @@ -75,7 +76,7 @@ static const Node* process(Context* ctx, const Node* old) { assert(src_type->tag == Int_TAG); const Type* word_type = src_type;// int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* dst_addr = rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; @@ -91,7 +92,8 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num_in_bytes = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memset_i"); - BodyBuilder* loop_bb = begin_body(a); + Node* loop_case = case_(a, singleton(index)); + BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); Node* true_case = case_(a, empty(a)); @@ -99,8 +101,7 @@ static const Node* process(Context* ctx, const Node* old) { Node* false_case = case_(a, empty(a)); set_abstraction_body(false_case, merge_break(a, (MergeBreak) {.args = empty(a)})); gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), true_case, false_case); - Node* loop_case = case_(a, singleton(index)); - set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a))); + set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a, (Unreachable) { .mem = bb_mem(loop_bb) }))); gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), loop_case); return yield_values_and_wrap_in_block(bb, empty(a)); } diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index f45a0a036..22bf35bd8 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -59,7 +59,6 @@ Module* lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* s Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process) }; - ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); return dst; diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 24fd1d7cb..a769b6ee4 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -19,20 +19,20 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { if (found) return *found; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); const Node* nul = gen_reinterpret_cast(bb, t, uint64_literal(a, 0)); Node* decl = constant(ctx->rewriter.dst_module, singleton(annotation(a, (Annotation) { .name = "Generated", })), t, format_string_interned(a, "nullptr_%s", name_type_safe(a, t))); - decl->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(nul)); + decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(nul)); const Node* ref = ref_decl_helper(a, decl); insert_dict(const Type*, const Node*, ctx->map, t, ref); return ref; } static const Node* process(Context* ctx, const Node* node) { - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { case NullPtr_TAG: { const Type* t = rewrite_node(r, node->payload.null_ptr.ptr_type); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 523a773cb..1839e915e 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -276,7 +276,7 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un Node* fun = function(ctx->rewriter.dst_module, params, name, singleton(annotation(a, (Annotation) { .name = "Generated" })), return_ts); insert_dict(const Node*, Node*, cache, element_type, fun); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); const Node* address = bytes_to_words(bb, address_param); const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { @@ -294,7 +294,8 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (old->tag) { case Load_TAG: { @@ -304,7 +305,7 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(payload.mem)); const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, false, ptr_type->payload.ptr_type.address_space); @@ -318,7 +319,7 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(payload.mem)); const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); @@ -349,13 +350,13 @@ static const Node* process_node(Context* ctx, const Node* old) { } case Function_TAG: { if (strcmp(get_abstraction_name(old), "generated_init") == 0) { - Node *new = recreate_decl_header_identity(&ctx->rewriter, old); - BodyBuilder *bb = begin_body(a); - + Node* new = recreate_decl_header_identity(&ctx->rewriter, old); + BodyBuilder *bb = begin_body_with_mem(a, get_abstraction_mem(new)); for (AddressSpace as = 0; as < NumAddressSpaces; as++) { if (is_as_emulated(ctx, as)) store_init_data(ctx, as, ctx->collected[as], bb); } + register_processed(&ctx->rewriter, get_abstraction_mem(old), bb_mem(bb)); new->payload.fun.body = finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body)); return new; } @@ -413,10 +414,10 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect // we need to compute the actual pointer by getting the offset and dividing it // after lower_memory_layout, optimisations will eliminate this and resolve to a value - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); const Node* offset = gen_primop_e(bb, offset_of_op, singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), singleton(size_t_literal(a, i))); // const Node* offset_in_words = bytes_to_words(bb, offset); - new_address->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(offset)); + new_address->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(offset)); register_processed(&ctx->rewriter, decl, new_address); } @@ -467,12 +468,12 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { Nodes annotations = singleton(annotation(a, (Annotation) { .name = "Generated" })); // compute the size - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); const Node* size_of = gen_primop_e(bb, size_of_op, singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), empty(a)); const Node* size_in_words = bytes_to_words(bb, size_of); Node* constant_decl = constant(m, annotations, ptr_size_type, format_string_interned(a, "memory_%s_size", as_name)); - constant_decl->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(size_in_words)); + constant_decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(size_in_words)); const Type* words_array_type = arr_type(a, (ArrType) { .element_type = word_type, diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index ee4a14101..4465dfa23 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -44,7 +44,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { Node* fun = function(ctx->rewriter.dst_module, params, name, singleton(annotation(a, (Annotation) { .name = "Generated" })), return_ts); insert_dict(const Node*, Node*, cache, element_type, fun); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); const Node* element_size = gen_primop_e(bb, size_of_op, singleton(element_type), empty(a)); element_size = gen_conversion(bb, uint32_type(a), element_size); @@ -98,7 +98,7 @@ static const Node* process_node(Context* ctx, const Node* old) { if (old->tag == Function_TAG && strcmp(get_abstraction_name(old), "generated_init") == 0) { Node* new = recreate_decl_header_identity(&ctx->rewriter, old); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); // Make sure to zero-init the stack pointers // TODO isn't this redundant with thoose things having an initial value already ? @@ -107,6 +107,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* stack_pointer = ctx->stack_pointer; gen_store(bb, stack_pointer, uint32_literal(a, 0)); } + register_processed(r, get_abstraction_mem(old), bb_mem(bb)); new->payload.fun.body = finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body)); return new; } @@ -114,20 +115,23 @@ static const Node* process_node(Context* ctx, const Node* old) { switch (old->tag) { case GetStackSize_TAG: { assert(ctx->stack); - BodyBuilder* bb = begin_body(a); + GetStackSize payload = old->payload.get_stack_size; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* sp = gen_load(bb, ctx->stack_pointer); return yield_values_and_wrap_in_block(bb, singleton(sp)); } case SetStackSize_TAG: { assert(ctx->stack); - BodyBuilder* bb = begin_body(a); + SetStackSize payload = old->payload.set_stack_size; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* val = rewrite_node(r, old->payload.set_stack_size.value); gen_store(bb, ctx->stack_pointer, val); return yield_values_and_wrap_in_block(bb, empty(a)); } case GetStackBaseAddr_TAG: { assert(ctx->stack); - BodyBuilder* bb = begin_body(a); + GetStackBaseAddr payload = old->payload.get_stack_base_addr; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* stack_pointer = ctx->stack_pointer; const Node* stack_size = gen_load(bb, stack_pointer); const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); @@ -138,7 +142,8 @@ static const Node* process_node(Context* ctx, const Node* old) { } case PushStack_TAG:{ assert(ctx->stack); - BodyBuilder* bb = begin_body(a); + PushStack payload = old->payload.push_stack; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Type* element_type = rewrite_node(&ctx->rewriter, get_unqualified_type(old->payload.push_stack.value->type)); bool push = true; @@ -151,7 +156,8 @@ static const Node* process_node(Context* ctx, const Node* old) { } case PopStack_TAG: { assert(ctx->stack); - BodyBuilder* bb = begin_body(a); + PopStack payload = old->payload.pop_stack; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Type* element_type = rewrite_node(&ctx->rewriter, old->payload.pop_stack.type); bool push = false; diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 0f0314371..0cb46dad3 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -82,11 +82,12 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* t, const static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* t) { IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fn)); const Node* result = generate(ctx, bb, t, param); if (result) { fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { - .args = singleton(result) + .args = singleton(result), + .mem = bb_mem(bb), })); return; } @@ -131,9 +132,10 @@ static const Node* process(Context* ctx, const Node* node) { PrimOp payload = node->payload.prim_op; switch (payload.op) { case subgroup_broadcast_first_op: { - BodyBuilder* bb = begin_body(a); + error("TODO") + /*BodyBuilder* bb = begin_body(a); return yield_values_and_wrap_in_block(bb, singleton( - build_subgroup_first(ctx, bb, rewrite_node(r, first(payload.operands))))); + build_subgroup_first(ctx, bb, rewrite_node(r, first(payload.operands)))));*/ } default: break; } diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index bbf57f3e0..dc4fa1fe6 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -9,7 +9,6 @@ typedef struct { Rewriter rewriter; const CompilerConfig* config; - BodyBuilder* b; } Context; static const Node* process(Context* ctx, NodeClass class, String op_name, const Node* node) { @@ -32,11 +31,12 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const const Node* odecl = node->payload.ref_decl.decl; if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsSubgroup) break; - assert(ctx->b); const Node* ndecl = rewrite_op(&ctx->rewriter, NcDeclaration, "decl", odecl); - const Node* index = gen_builtin_load(ctx->rewriter.dst_module, ctx->b, BuiltinSubgroupId); - const Node* slice = gen_lea(ctx->b, ref_decl_helper(a, ndecl), int32_literal(a, 0), mk_nodes(a, index)); - return slice; + error("TODO") + // assert(ctx->b); + // const Node* index = gen_builtin_load(ctx->rewriter.dst_module, ctx->b, BuiltinSubgroupId); + // const Node* slice = gen_lea(ctx->b, ref_decl_helper(a, ndecl), int32_literal(a, 0), mk_nodes(a, index)); + // return slice; } case GlobalVariable_TAG: { AddressSpace as = node->payload.global_variable.address_space; @@ -64,12 +64,6 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const default: break; } - if (class == NcTerminator) { - BodyBuilder* b = begin_body(a); - Context c = *ctx; - c.b = b; - return finish_body(b, recreate_node_identity(&c.rewriter, node)); - } const Node* new = recreate_node_identity(&ctx->rewriter, node); if (class == NcInstruction) register_processed(r, node, new); diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 83cfbf1d5..9e25a98c9 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -76,15 +76,15 @@ TreeNode* insert(TreeNode* t, TreeNode* x) { return t; } -static const Node* gen_yield(Context* ctx, bool in_if, Nodes args) { +/*static const Node* gen_yield(Context* ctx, bool in_if, const Node* mem, Nodes args) { if (in_if) - return merge_selection(ctx->rewriter.dst_arena, (MergeSelection) { args }); + return merge_selection(ctx->rewriter.dst_arena, (MergeSelection) { .args = args, .mem = mem }); return block_yield(ctx->rewriter.dst_arena, (BlockYield) { args }); } -static const Node* generate_default_fallback_case(Context* ctx, bool in_if) { +static const Node* generate_default_fallback_case(Context* ctx, bool in_if, const Node* mem) { IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, mem); gen_store(bb, ctx->run_default_case, true_lit(a)); LARRAY(const Node*, undefs, ctx->yield_types.count); for (size_t i = 0; i < ctx->yield_types.count; i++) @@ -127,7 +127,7 @@ static const Node* generate_decision_tree(Context* ctx, TreeNode* n, bool in_if, } return body; -} +}*/ static const Node* process(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; @@ -135,6 +135,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Match_TAG: { + Match payload = node->payload.match_instr; Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.match_instr.yield_types); Nodes literals = rewrite_nodes(&ctx->rewriter, node->payload.match_instr.literals); Nodes cases = rewrite_nodes(&ctx->rewriter, node->payload.match_instr.cases); @@ -152,11 +153,11 @@ static const Node* process(Context* ctx, const Node* node) { root = insert(root, t); } - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* run_default_case = gen_stack_alloc(bb, bool_type(a)); gen_store(bb, run_default_case, false_lit(a)); - Context ctx2 = *ctx; + /*Context ctx2 = *ctx; ctx2.run_default_case = run_default_case; ctx2.yield_types = yield_types; ctx2.inspectee = rewrite_node(&ctx->rewriter, node->payload.match_instr.inspect); @@ -169,7 +170,8 @@ static const Node* process(Context* ctx, const Node* node) { register_processed_list(r, get_abstraction_params(get_structured_construct_tail(node)), final_results); destroy_arena(arena); - return finish_body(bb, rewrite_node(r, get_abstraction_body(get_structured_construct_tail(node)))); + return finish_body(bb, rewrite_node(r, get_abstraction_body(get_structured_construct_tail(node))));*/ + error("TODO") // return yield_values_and_wrap_in_block(bb, final_results); } default: break; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 5ec950d2c..8ed607b3c 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -62,7 +62,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { Nodes rewritten_params = recreate_params(&ctx2.rewriter, old->payload.fun.params); Node* new_entry_pt = function(ctx2.rewriter.dst_module, rewritten_params, old->payload.fun.name, rewrite_nodes(&ctx2.rewriter, old->payload.fun.annotations), nodes(a, 0, NULL)); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_entry_pt)); bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, ctx->init_fn), .args = empty(a) })); bind_instruction(bb, call(a, (Call) { .callee = access_decl(&ctx->rewriter, "builtin_init_scheduler"), .args = empty(a) })); @@ -87,9 +87,10 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { .args = nodes(a, 0, NULL) })); - new_entry_pt->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { - .args = nodes(a, 0, NULL) - })); + set_abstraction_body(new_entry_pt, finish_body(bb, fn_ret(a, (Return) { + .args = nodes(a, 0, NULL), + .mem = bb_mem(bb), + }))); } static const Node* process(Context* ctx, const Node* old) { @@ -112,11 +113,13 @@ static const Node* process(Context* ctx, const Node* old) { if (ctx2.disable_lowering) { Node* fun = recreate_decl_header_identity(&ctx2.rewriter, old); if (old->payload.fun.body) { + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); const Node* nbody = rewrite_node(&ctx2.rewriter, old->payload.fun.body); if (entry_point_annotation) { - nbody = let(a, call(a, (Call) { .callee = fn_addr_helper(a, ctx2.init_fn), .args = empty(a)}), nbody); + gen_call(bb, fn_addr_helper(a, ctx2.init_fn), empty(a)); } - fun->payload.fun.body = nbody; + register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); } destroy_uses_map(ctx2.uses); @@ -138,7 +141,7 @@ static const Node* process(Context* ctx, const Node* old) { if (entry_point_annotation) lift_entry_point(ctx, old, fun); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); // Params become stack pops ! for (size_t i = 0; i < old->payload.fun.params.count; i++) { const Node* old_param = old->payload.fun.params.nodes[i]; @@ -151,7 +154,8 @@ static const Node* process(Context* ctx, const Node* old) { popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_broadcast_first_op, .type_arguments = empty(a), .operands = singleton(popped) }), &old_param->payload.param.name)); register_processed(&ctx->rewriter, old_param, popped); } - fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body)); + register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); destroy_uses_map(ctx2.uses); destroy_cfg(ctx2.cfg); return fun; @@ -170,7 +174,7 @@ static const Node* process(Context* ctx, const Node* old) { }); case PrimOp_TAG: { switch (old->payload.prim_op.op) { - case create_joint_point_op: { + /*case create_joint_point_op: { BodyBuilder* bb = begin_body(a); Nodes args = rewrite_nodes(&ctx->rewriter, old->payload.prim_op.operands); assert(args.count == 2); @@ -190,16 +194,18 @@ static const Node* process(Context* ctx, const Node* old) { .args = empty(a) })); return yield_values_and_wrap_in_block(bb, r); - } + }*/ + error("TODO: unprimop-ify these") default: return recreate_node_identity(&ctx->rewriter, old); } } case TailCall_TAG: { //if (ctx->disable_lowering) // return recreate_node_identity(&ctx->rewriter, old); - BodyBuilder* bb = begin_body(a); - gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, old->payload.tail_call.args)); - const Node* target = rewrite_node(&ctx->rewriter, old->payload.tail_call.target); + TailCall payload = old->payload.tail_call; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, payload.args)); + const Node* target = rewrite_node(&ctx->rewriter, payload.target); target = gen_conversion(bb, uint32_type(a), target); const Node* fork_call = call(a, (Call) { @@ -210,6 +216,7 @@ static const Node* process(Context* ctx, const Node* old) { return finish_body(bb, fn_ret(a, (Return) { .args = nodes(a, 0, NULL) })); } case Join_TAG: { + Join payload = old->payload.join; //if (ctx->disable_lowering) // return recreate_node_identity(&ctx->rewriter, old); @@ -219,10 +226,10 @@ static const Node* process(Context* ctx, const Node* old) { if (jp_type->tag == JoinPointType_TAG) break; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, old->payload.join.args)); - const Node* payload = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 2))); - gen_push_value_stack(bb, payload); + const Node* jp_payload = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 2))); + gen_push_value_stack(bb, jp_payload); const Node* dst = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 1))); const Node* tree_node = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 0))); @@ -242,6 +249,7 @@ static const Node* process(Context* ctx, const Node* old) { break; } case Control_TAG: { + Control payload = old->payload.control; if (is_control_static(ctx->uses, old)) { const Node* old_inside = old->payload.control.inside; const Node* old_jp = first(get_abstraction_params(old_inside)); @@ -254,11 +262,16 @@ static const Node* process(Context* ctx, const Node* old) { }); const Node* new_jp = param(a, qualified_type_helper(new_jp_type, true), old_jp->payload.param.name); register_processed(&ctx->rewriter, old_jp, new_jp); - const Node* new_control_case = case_(a, singleton(new_jp)); + Node* new_control_case = case_(a, singleton(new_jp)); set_abstraction_body(new_control_case, rewrite_node(&ctx->rewriter, get_abstraction_body(old_inside))); - BodyBuilder* bb = begin_body(a); + // BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); Nodes nyield_types = rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types); - return control(a, (Control) { .yield_types = nyield_types, .inside = new_control_case, .tail = rewrite_node(r, get_structured_construct_tail(old))}); + return control(a, (Control) { + .yield_types = nyield_types, + .inside = new_control_case, + .tail = rewrite_node(r, get_structured_construct_tail(old)), + .mem = rewrite_node(r, payload.mem), + }); //return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, new_body)); } break; @@ -275,7 +288,14 @@ void generate_top_level_dispatch_fn(Context* ctx) { assert((*ctx->top_dispatcher_fn)->tag == Function_TAG); IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* loop_body_builder = begin_body(a); + bool count_iterations = ctx->config->shader_diagnostics.max_top_iterations > 0; + + const Node* iterations_count_param = NULL; + if (count_iterations) + iterations_count_param = param(a, qualified_type(a, (QualifiedType) { .type = int32_type(a), .is_uniform = true }), "iterations"); + + Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL)); + BodyBuilder* loop_body_builder = begin_body_with_mem(a, get_abstraction_mem(loop_inside_case)); const Node* next_function = gen_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); const Node* get_active_branch_fn = access_decl(&ctx->rewriter, "builtin_get_active_branch"); @@ -283,11 +303,6 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* local_id = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); const Node* should_run = gen_primop_e(loop_body_builder, mask_is_thread_active_op, empty(a), mk_nodes(a, next_mask, local_id)); - bool count_iterations = ctx->config->shader_diagnostics.max_top_iterations > 0; - const Node* iterations_count_param = NULL; - if (count_iterations) - iterations_count_param = param(a, qualified_type(a, (QualifiedType) { .type = int32_type(a), .is_uniform = true }), "iterations"); - if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); if (count_iterations) @@ -316,13 +331,14 @@ void generate_top_level_dispatch_fn(Context* ctx) { struct List* cases = new_list(const Node*); // Build 'zero' case (exits the program) - BodyBuilder* zero_case_builder = begin_body(a); - BodyBuilder* zero_if_case_builder = begin_body(a); + Node* zero_case_lam = case_(a, nodes(a, 0, NULL)); + BodyBuilder* zero_case_builder = begin_body_with_mem(a, get_abstraction_mem(zero_case_lam)); + Node* zero_if_true_lam = case_(a, empty(a)); + BodyBuilder* zero_if_case_builder = begin_body_with_mem(a, get_abstraction_mem(zero_if_true_lam)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } - Node* zero_if_true_lam = case_(a, empty(a)); set_abstraction_body(zero_if_true_lam, finish_body(zero_if_case_builder, break_terminator)); gen_if(zero_case_builder, empty(a), should_run, zero_if_true_lam, NULL); if (ctx->config->printf_trace.god_function) { @@ -330,7 +346,6 @@ void generate_top_level_dispatch_fn(Context* ctx) { gen_debug_printf(zero_case_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } - Node* zero_case_lam = case_(a, nodes(a, 0, NULL)); set_abstraction_body(zero_case_lam, finish_body(zero_case_builder, continue_terminator)); const Node* zero_lit = uint64_literal(a, 0); append_list(const Node*, literals, zero_lit); @@ -345,7 +360,8 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* fn_lit = lower_fn_addr(ctx, decl); - BodyBuilder* if_builder = begin_body(a); + Node* if_true_lam = case_(a, empty(a)); + BodyBuilder* if_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_lam)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %ul with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); @@ -354,11 +370,11 @@ void generate_top_level_dispatch_fn(Context* ctx) { .callee = fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), .args = nodes(a, 0, NULL) })); - Node* if_true_lam = case_(a, empty(a)); set_abstraction_body(if_true_lam, finish_body(if_builder, merge_selection(a, (MergeSelection) {.args = nodes(a, 0, NULL)}))); - BodyBuilder* case_builder = begin_body(a); - gen_if(case_builder, empty(a), should_run, if_true_lam, NULL); + Node* case_lam = case_(a, nodes(a, 0, NULL)); + BodyBuilder* case_builder = begin_body_with_mem(a, get_abstraction_mem(case_lam)); + gen_if(case_builder, empty(a), should_run, if_true_lam, NULL); set_abstraction_body(case_lam, finish_body(case_builder, continue_terminator)); append_list(const Node*, literals, fn_lit); @@ -367,24 +383,24 @@ void generate_top_level_dispatch_fn(Context* ctx) { } Node* default_case = case_(a, nodes(a, 0, NULL)); - set_abstraction_body(default_case, unreachable(a)); + set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); gen_match(loop_body_builder, empty(a), next_function, nodes(a, entries_count_list(literals), read_list(const Node*, literals)), nodes(a, entries_count_list(cases), read_list(const Node*, cases)), default_case); destroy_list(literals); destroy_list(cases); - Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL)); - set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, unreachable(a))); + set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, unreachable(a, (Unreachable) { .mem = bb_mem(loop_body_builder) }))); - BodyBuilder* dispatcher_body_builder = begin_body(a); + BodyBuilder* dispatcher_body_builder = begin_body_with_mem(a, get_abstraction_mem(*ctx->top_dispatcher_fn)); gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : nodes(a, 0, NULL), loop_inside_case); if (ctx->config->printf_trace.god_function) gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", empty(a)); - (*ctx->top_dispatcher_fn)->payload.fun.body = finish_body(dispatcher_body_builder, fn_ret(a, (Return) { + set_abstraction_body(*ctx->top_dispatcher_fn, finish_body(dispatcher_body_builder, fn_ret(a, (Return) { .args = nodes(a, 0, NULL), - })); + .mem = bb_mem(dispatcher_body_builder), + }))); } KeyHash hash_node(Node**); diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index a301a8e1a..cda9ed973 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -18,7 +18,7 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { if (width == 1) return recreate_node_identity(&ctx->rewriter, old); LARRAY(const Node*, elements, width); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); Nodes noperands = rewrite_nodes(&ctx->rewriter, old->payload.prim_op.operands); for (size_t i = 0; i < width; i++) { LARRAY(const Node*, nops, noperands.count); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 54d8f0f37..0a341daf2 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -18,8 +18,9 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - IrArena* a = ctx->rewriter.dst_arena; - Module* m = ctx->rewriter.dst_module; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + Module* m = r->dst_module; switch (node->tag) { case GlobalVariable_TAG: { @@ -62,7 +63,7 @@ static const Node* process(Context* ctx, const Node* node) { register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); inner->payload.fun.body = recreate_node_identity(&ctx->rewriter, node->payload.fun.body); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(wrapper)); const Node* num_workgroups_var = rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); const Node* workgroup_num_vec3 = gen_load(bb, ref_decl_helper(a, num_workgroups_var)); @@ -90,7 +91,7 @@ static const Node* process(Context* ctx, const Node* node) { num_subgroups_literals[dim] = uint32_literal(a, num_subgroups[dim]); } - BodyBuilder* bb2 = begin_body(a); + BodyBuilder* bb2 = begin_block_with_side_effects(a); // write the workgroup ID gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); // write the local ID @@ -123,14 +124,14 @@ static const Node* process(Context* ctx, const Node* node) { } else assert(false); for (int dim = 0; dim < 3; dim++) { - BodyBuilder* body_bb = begin_body(a); + Node* loop_body = case_(a, singleton(params[dim])); + BodyBuilder* body_bb = begin_body_with_mem(a, get_abstraction_mem(loop_body)); Node* out_of_bounds_case = case_(a, empty(a)); - set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) {.args = empty(a)})); + set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) {.args = empty(a), .mem = get_abstraction_mem(out_of_bounds_case)})); gen_if(body_bb, empty(a), gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), out_of_bounds_case, NULL); bind_instruction(body_bb, instr); - BodyBuilder* bb3 = begin_body(a); - Node* loop_body = case_(a, singleton(params[dim])); + BodyBuilder* bb3 = begin_block_with_side_effects(a); set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) {.args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1))))}))); gen_loop(bb3, empty(a), singleton(uint32_literal(a, 0)), loop_body); instr = yield_values_and_wrap_in_block(bb3, empty(a)); @@ -144,11 +145,12 @@ static const Node* process(Context* ctx, const Node* node) { return recreate_node_identity(&ctx2.rewriter, node); } case Load_TAG: { - const Node* ptr = node->payload.load.ptr; + Load payload = node->payload.load; + const Node* ptr = payload.ptr; if (ptr->tag == RefDecl_TAG) ptr = ptr->payload.ref_decl.decl; if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* loaded = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); const Node* uniformized = first(gen_primop(bb, subgroup_broadcast_first_op, empty(a), singleton(loaded))); return yield_values_and_wrap_in_block(bb, singleton(uniformized)); @@ -169,7 +171,6 @@ Module* lower_workgroups(const CompilerConfig* config, Module* src) { .config = config, .globals = calloc(sizeof(Node*), PRIMOPS_COUNT), }; - ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); free(ctx.globals); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index e99a5adcb..ce4f4b6cd 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -55,7 +55,8 @@ static const Node* process(Context* ctx, const Node* node) { const Node* found = search_processed(&ctx->rewriter, node); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { case GlobalVariable_TAG: { @@ -67,8 +68,8 @@ static const Node* process(Context* ctx, const Node* node) { if (ctx->builtins[b]) return ctx->builtins[b]; const Type* t = get_builtin_type(a, b); - Node* ndecl = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, global_variable.annotations), t, global_variable.name, get_builtin_as(b)); - register_processed(&ctx->rewriter, node, ndecl); + Node* ndecl = global_var(r->dst_module, rewrite_nodes(r, global_variable.annotations), t, global_variable.name, get_builtin_as(b)); + register_processed(r, node, ndecl); // no 'init' for builtins, right ? assert(!global_variable.init); ctx->builtins[b] = ndecl; @@ -80,9 +81,9 @@ static const Node* process(Context* ctx, const Node* node) { const Type* req_cast = get_req_cast(ctx, node->payload.load.ptr); if (req_cast) { assert(is_data_type(req_cast)); - BodyBuilder* bb = begin_body(a); - const Node* r = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); - const Node* r2 = first(gen_primop(bb, reinterpret_op, singleton(req_cast), singleton(r))); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.load.mem)); + const Node* r1 = first(bind_instruction(bb, recreate_node_identity(r, node))); + const Node* r2 = first(gen_primop(bb, reinterpret_op, singleton(req_cast), singleton(r1))); return yield_values_and_wrap_in_block(bb, singleton(r2)); } break; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index a017e8996..2f890c34e 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -47,15 +47,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca for (;use; use = use->next_use) { if (is_abstraction(use->user) && use->operand_class == NcParam) continue; - else if (use->user->tag == Let_TAG && use->operand_class == NcInstruction) { - /*Nodes vars = use->user->payload.let.variables; - for (size_t i = 0; i < vars.count; i++) { - debugv_print("demote_alloca leak analysis: following let-bound variable: "); - log_node(DEBUGV, vars.nodes[i]); - debugv_print(".\n"); - visit_ptr_uses(vars.nodes[i], slice_type, k, map); - }*/ - } else if (use->user->tag == Load_TAG) { + else if (use->user->tag == Load_TAG) { //if (get_pointer_type_element(ptr_type) != slice_type) // k->reinterpreted = true; k->read_from = true; @@ -189,8 +181,9 @@ static const Node* process(Context* ctx, const Node* old) { const Node* found = search_processed(&ctx->rewriter, old); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + switch (old->tag) { case Function_TAG: { Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); @@ -216,10 +209,10 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca->new == rewrite_node(r, payload.ptr)) break; ctx->todo |= true; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* data = gen_load(bb, k.src_alloca->new); data = gen_reinterpret_cast(bb, access_type, data); - return yield_values_and_wrap_in_block(bb, singleton(data)); + return yield_value_and_wrap_in_block(bb, data); } } break; @@ -233,7 +226,7 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca->new == rewrite_node(r, payload.ptr)) break; ctx->todo |= true; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.value)); gen_store(bb, k.src_alloca->new, data); return yield_values_and_wrap_in_block(bb, empty(a)); @@ -271,7 +264,6 @@ bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { .alloca_info = new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), .todo = false }; - ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); destroy_dict(ctx.alloca_info); diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 7ddbe2c8c..0018907fa 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -168,15 +168,15 @@ static const Node* process(Context* ctx, const Node* node) { case Call_TAG: { if (!ctx->graph) break; - const Node* ocallee = node->payload.call.callee; - Nodes oargs = node->payload.call.args; + Call payload = node->payload.call; + const Node* ocallee = payload.callee; ocallee = ignore_immediate_fn_addr(ocallee); if (ocallee->tag == Function_TAG) { CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined && is_call_potentially_inlineable(ctx->old_fun, ocallee)) { debugv_print("Inlining call to %s\n", get_abstraction_name(ocallee)); - Nodes nargs = rewrite_nodes(&ctx->rewriter, oargs); + Nodes nargs = rewrite_nodes(&ctx->rewriter, payload.args); // Prepare a join point to replace the old function return Nodes nyield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); @@ -187,7 +187,7 @@ static const Node* process(Context* ctx, const Node* node) { Node* control_case = case_(a, singleton(join_point)); set_abstraction_body(control_case, nbody); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, control_case)); } } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c deleted file mode 100644 index 5bd918e3f..000000000 --- a/src/shady/passes/opt_mem2reg.c +++ /dev/null @@ -1,758 +0,0 @@ -#include "pass.h" - -#include "../visit.h" -#include "../type.h" - -#include "../analysis/cfg.h" -#include "../analysis/uses.h" -#include "../analysis/leak.h" -#include "../analysis/verify.h" - -#include "../transform/ir_gen_helpers.h" - -#include "portability.h" -#include "dict.h" -#include "arena.h" -#include "log.h" - -typedef struct { - AddressSpace as; - const Type* type; -} PtrSourceKnowledge; - -typedef struct { - enum { - PSUnknown, - PSKnownValue, - PSKnownAlias, - PSKnownSubElement, - } state; - union { - const Node* ptr_value; - // for PSKnownAlias: old node to lookup - const Node* alias_old_address; - struct { const Node* old_base; Nodes indices; } sub_element; - }; - bool ptr_has_leaked; - PtrSourceKnowledge* source; -} PtrKnowledge; - -typedef struct KB KnowledgeBase; - -struct KB { - CFNode* cfnode; - // when the associated node has exactly one parent edge, we can safely assume what held true - // for it will hold true for this one too, unless we have conflicting information - const KnowledgeBase* dominator_kb; - struct Dict* map; - struct Dict* potential_additional_params; - Arena* a; -}; - -typedef struct { - const Node* old_jump; - Node* wrapper_bb; - KnowledgeBase* kb; -} TodoJump; - -typedef struct { - Rewriter rewriter; - CFG* cfg; - struct Dict* abs_to_kb; - const Node* oabs; - Arena* a; - - struct Dict* bb_new_args; - struct List* todo_jumps; -} Context; - -static PtrKnowledge* get_last_valid_ptr_knowledge(const KnowledgeBase* kb, const Node* n) { - PtrKnowledge** found = find_value_dict(const Node*, PtrKnowledge*, kb->map, n); - if (found) - return *found; - PtrKnowledge* k = NULL; - if (kb->dominator_kb) - k = get_last_valid_ptr_knowledge(kb->dominator_kb, n); - return k; -} - -static PtrKnowledge* create_root_ptr_knowledge(KnowledgeBase* kb, const Node* instruction) { - PtrKnowledge* k = arena_alloc(kb->a, sizeof(PtrKnowledge)); - PtrSourceKnowledge* sk = arena_alloc(kb->a, sizeof(PtrSourceKnowledge)); - *k = (PtrKnowledge) { .source = sk, .state = PSUnknown/*, .ptr_address = address_value*/ }; - *sk = (PtrSourceKnowledge) { 0 }; - bool fresh = insert_dict(const Node*, PtrKnowledge*, kb->map, instruction, k); - assert(fresh); - return k; -} - -static PtrKnowledge* update_ptr_knowledge(KnowledgeBase* kb, const Node* n, PtrKnowledge* existing) { - PtrKnowledge* k = arena_alloc(kb->a, sizeof(PtrKnowledge)); - *k = *existing; // copy the data - bool fresh = insert_dict(const Node*, PtrKnowledge*, kb->map, n, k); - assert(fresh); - return k; -} - -static void insert_ptr_knowledge(KnowledgeBase* kb, const Node* n, PtrKnowledge* k) { - PtrKnowledge** found = find_value_dict(const Node*, PtrKnowledge*, kb->map, n); - assert(!found); - insert_dict(const Node*, PtrKnowledge*, kb->map, n, k); -} - -static const Node* get_known_value(KnowledgeBase* kb, const PtrKnowledge* k) { - const Node* v = NULL; - while (k) { - if (k->state == PSKnownValue) { - v = k->ptr_value; - k = NULL; - } else if (k->state == PSKnownAlias) { - k = get_last_valid_ptr_knowledge(kb, k->alias_old_address); - } else - k = NULL; - } - return v; -} - -/*static const Node* get_known_address(Rewriter* r, const PtrKnowledge* k) { - const Node* v = NULL; - if (k) { - if (k->ptr_address) { - v = k->ptr_address; - } - } - if (v) - assert(v->arena == r->dst_arena); - // if (r && v && v->arena != r->dst_arena) - // return rewrite_node(r, v); - return v; -}*/ - -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); - -static void destroy_kb(KnowledgeBase* kb) { - destroy_dict(kb->map); - destroy_dict(kb->potential_additional_params); -} - -static KnowledgeBase* get_kb(Context* ctx, const Node* abs) { - assert(ctx->cfg); - KnowledgeBase** found = find_value_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, abs); - if (!found) - return NULL; - return *found; -} - -static KnowledgeBase* create_kb(Context* ctx, const Node* old) { - assert(ctx->cfg); - arena_alloc(ctx->a, sizeof(KnowledgeBase)); - CFNode* cf_node = cfg_lookup(ctx->cfg, old); - KnowledgeBase* kb = arena_alloc(ctx->a, sizeof(KnowledgeBase)); - *kb = (KnowledgeBase) { - .cfnode = cf_node, - .a = ctx->a, - .map = new_dict(const Node*, PtrKnowledge*, (HashFn) hash_node, (CmpFn) compare_node), - .potential_additional_params = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .dominator_kb = NULL, - }; - // log_string(DEBUGVV, "Creating KB for "); - // log_node(DEBUGVV, old); - // log_string(DEBUGVV, "\n."); - if (entries_count_list(cf_node->pred_edges) == 1) { - CFEdge edge = read_list(CFEdge, cf_node->pred_edges)[0]; - assert(edge.dst == cf_node); - if (edge.type == JumpEdge) { - CFNode* dominator = edge.src; - const KnowledgeBase* parent_kb = get_kb(ctx, dominator->node); - assert(parent_kb); - assert(parent_kb->map); - kb->dominator_kb = parent_kb; - } - } - assert(kb->map); - bool ok = insert_dict(const Node*, KnowledgeBase*, ctx->abs_to_kb, old, kb); - assert(ok); - return kb; -} - -static void wipe_all_leaked_pointers(KnowledgeBase* kb) { - size_t i = 0; - const Node* ptr; - PtrKnowledge* k; - while (dict_iter(kb->map, &i, &ptr, &k)) { - if (k->ptr_has_leaked) { - if (k->state == PSKnownValue || k->state == PSKnownSubElement) { - k->ptr_value = NULL; - k->state = PSUnknown; - } - debugvv_print("mem2reg: wiping the know ptr value for "); - log_node(DEBUGVV, ptr); - debugvv_print(".\n"); - } - } -} - -static const Node* find_or_request_known_ptr_value(Context* ctx, KnowledgeBase* kb, const Node* optr) { - IrArena* a = ctx->rewriter.dst_arena; - PtrKnowledge* ok = get_last_valid_ptr_knowledge(kb, optr); - const Node* known_value = get_known_value(kb, ok); - if (known_value) { - const Type* known_value_t = known_value->type; - bool kv_u = deconstruct_qualified_type(&known_value_t); - - const Type* load_result_t = rewrite_node(&ctx->rewriter, optr->type); - bool lrt_u = deconstruct_qualified_type(&load_result_t); - deconstruct_pointer_type(&load_result_t); - // assert(!lrt_u || kv_u); - if (is_reinterpret_cast_legal(load_result_t, known_value_t)) { - const Node* n = prim_op_helper(a, reinterpret_op, singleton(load_result_t), singleton(known_value)); - if (lrt_u && !kv_u) - n = prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(known_value)); - return n; - } - } else { - const KnowledgeBase* phi_kb = kb; - while (phi_kb->dominator_kb) { - phi_kb = phi_kb->dominator_kb; - } - log_string(DEBUGVV, "mem2reg: It'd sure be nice to know the value of "); - log_node(DEBUGVV, optr); - log_string(DEBUGVV, " at phi-like node %s.\n", get_abstraction_name_safe(phi_kb->cfnode->node)); - // log_node(DEBUGVV, phi_location->node); - insert_set_get_key(const Node*, phi_kb->potential_additional_params, optr); - } - return NULL; -} - -static PtrKnowledge* find_or_create_ptr_knowledge_for_updating(Context* ctx, KnowledgeBase* kb, const Node* optr, bool create) { - Rewriter* r = &ctx->rewriter; - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, optr); - if (k) { - k = update_ptr_knowledge(kb, optr, k); - } else { - PtrSourceKnowledge* sk = NULL; - CFNode* cf_node = cfg_lookup(ctx->cfg, ctx->oabs); - // we're creating a new chain of knowledge, but we want to use the same source if possible - while (cf_node) { - KnowledgeBase* kb2 = get_kb(ctx, cf_node->node); - assert(kb2); - PtrKnowledge* k2 = get_last_valid_ptr_knowledge(kb2, optr); - if (k2) { - sk = k2->source; - break; - } - cf_node = cf_node->idom; - } - if (sk) { - k = arena_alloc(ctx->a, sizeof(PtrKnowledge)); - *k = (PtrKnowledge) { - .source = sk, - .ptr_has_leaked = true // TODO: this is wrong in the "too conservative" way - // fixing this requires accounting for the dominance relation properly - // to visit all predecessors first, then merging the knowledge - }; - insert_ptr_knowledge(kb, optr, k); - } else if (create) { - // just make up a new source and assume it leaks/aliases - k = create_root_ptr_knowledge(kb, optr); - const Type* t = optr->type; - deconstruct_qualified_type(&t); - assert(t->tag == PtrType_TAG); - k->source->as = t->payload.ptr_type.address_space; - k->source->type = rewrite_node(r, get_pointer_type_element(t)); - k->ptr_has_leaked = true; - } - } - return k; -} - -static void mark_values_as_escaping(Context* ctx, KnowledgeBase* kb, Nodes values); - -static void mark_value_as_escaping(Context* ctx, KnowledgeBase* kb, const Node* value) { - PtrKnowledge* k = find_or_create_ptr_knowledge_for_updating(ctx, kb, value, false); - if (k) { - debugvv_print("mem2reg: marking "); - log_node(DEBUGVV, value); - log_string(DEBUGVV, " as leaking.\n"); - k->ptr_has_leaked = true; - // if (k->state == PSKnownValue) - // mark_value_as_escaping(ctx, kb, k->ptr_value); - if (k->state == PSKnownAlias) - mark_value_as_escaping(ctx, kb, k->alias_old_address); - } - switch (is_value(value)) { - case NotAValue: assert(false); - case Value_Param_TAG: - case Value_ConstrainedValue_TAG: - break; - case Value_UntypedNumber_TAG: - break; - case Value_IntLiteral_TAG: - break; - case Value_FloatLiteral_TAG: - break; - case Value_StringLiteral_TAG: - break; - case Value_True_TAG: - break; - case Value_False_TAG: - break; - case Value_NullPtr_TAG: - break; - case Value_Composite_TAG: - mark_values_as_escaping(ctx, kb, value->payload.composite.contents); - break; - case Value_Fill_TAG: - mark_value_as_escaping(ctx, kb, value->payload.fill.value); - break; - case Value_Undef_TAG: - break; - case Value_RefDecl_TAG: - break; - case Value_FnAddr_TAG: - break; - } -} - -static void mark_values_as_escaping(Context* ctx, KnowledgeBase* kb, Nodes values) { - for (size_t i = 0; i < values.count; i++) - mark_value_as_escaping(ctx, kb, values.nodes[i]); -} - -static const Node* handle_allocation(Context* ctx, KnowledgeBase* kb, const Node* instr, const Type* type) { - IrArena* a = ctx->rewriter.dst_arena; - Rewriter* r = &ctx->rewriter; - - PtrKnowledge* k = create_root_ptr_knowledge(kb, instr); - const Type* t = instr->type; - deconstruct_qualified_type(&t); - assert(t->tag == PtrType_TAG); - k->source->as = t->payload.ptr_type.address_space; - //k->source->type = qualified_type_helper(t, u); - k->source->type = rewrite_node(r, type); - - k->state = PSUnknown; - // TODO: we can only enable this safely once we properly deal with control-flow - // k->state = PSKnownValue; - // k->ptr_value = undef(a, (Undef) { .type = rewrite_node(r, first(payload.type_arguments)) }); - return recreate_node_identity(r, instr); -} - -static const Node* process_instruction(Context* ctx, KnowledgeBase* kb, const Node* oinstruction) { - IrArena* a = ctx->rewriter.dst_arena; - Rewriter* r = &ctx->rewriter; - switch (is_instruction(oinstruction)) { - case NotAnInstruction: assert(is_instruction(oinstruction)); - case Instruction_Call_TAG: - mark_values_as_escaping(ctx, kb, oinstruction->payload.call.args); - wipe_all_leaked_pointers(kb); - break; - case Load_TAG: { - const Node* optr = oinstruction->payload.load.ptr; - const Node* known_value = find_or_request_known_ptr_value(ctx, kb, optr); - if (known_value) - return known_value; - // const Node* other_ptr = get_known_address(&ctx->rewriter, ok); - // if (other_ptr && optr != other_ptr) { - // return prim_op_helper(a, load_op, empty(a), singleton(other_ptr)); - // } - return load(a, (Load) { rewrite_node(r, optr) }); - } - case Store_TAG: { - Store payload = oinstruction->payload.store; - PtrKnowledge* k = find_or_create_ptr_knowledge_for_updating(ctx, kb, payload.ptr, true); - if (k) { - k->state = PSKnownValue; - k->ptr_value = rewrite_node(r, payload.value); - } - mark_value_as_escaping(ctx, kb, payload.value); - wipe_all_leaked_pointers(kb); - // let's take care of dead stores another time - return recreate_node_identity(r, oinstruction); - } - case Instruction_LocalAlloc_TAG: return handle_allocation(ctx, kb, oinstruction, oinstruction->payload.local_alloc.type); - case Instruction_StackAlloc_TAG: return handle_allocation(ctx, kb, oinstruction, oinstruction->payload.stack_alloc.type); - case Instruction_PrimOp_TAG: { - PrimOp payload = oinstruction->payload.prim_op; - switch (payload.op) { - // case memcpy_op: { - // const Node* optr = first(payload.operands); - // } - case reinterpret_op: { - const Node* rewritten = recreate_node_identity(r, oinstruction); - // if we have knowledge on a particular ptr, the same knowledge propagates if we bitcast it! - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, first(payload.operands)); - if (k) { - log_string(DEBUGVV, "mem2reg: the reinterpreted ptr "); - log_node(DEBUGVV, oinstruction); - log_string(DEBUGVV, " is the same as "); - log_node(DEBUGVV, first(payload.operands)); - log_string(DEBUGVV, ".\n"); - k = update_ptr_knowledge(kb, oinstruction, k); - k->state = PSKnownAlias; - k->alias_old_address = first(payload.operands); - } - return rewritten; - } - case convert_op: { - const Node* rewritten = recreate_node_identity(r, oinstruction); - // if we convert a pointer to generic AS, we'd like to use the old address instead where possible - if (first(payload.type_arguments)->tag == PtrType_TAG) { - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb, first(payload.operands)); - if (k) { - log_string(DEBUGVV, "mem2reg: the converted ptr "); - log_node(DEBUGVV, oinstruction); - log_string(DEBUGVV, " is the same as "); - log_node(DEBUGVV, first(payload.operands)); - log_string(DEBUGVV, ".\n"); - k = update_ptr_knowledge(kb, oinstruction, k); - k->state = PSKnownAlias; - k->alias_old_address = first(payload.operands); - } - } - return rewritten; - } - default: break; - } - - mark_values_as_escaping(ctx, kb, payload.operands); - if (has_primop_got_side_effects(payload.op)) - wipe_all_leaked_pointers(kb); - - return recreate_node_identity(r, oinstruction); - } - case Instruction_Lea_TAG: { - mark_value_as_escaping(ctx, kb, oinstruction->payload.lea.ptr); - break; - } - case Instruction_CopyBytes_TAG: { - mark_value_as_escaping(ctx, kb, oinstruction->payload.copy_bytes.src); - mark_value_as_escaping(ctx, kb, oinstruction->payload.copy_bytes.dst); - break; - } - case Instruction_FillBytes_TAG: { - mark_value_as_escaping(ctx, kb, oinstruction->payload.fill_bytes.src); - mark_value_as_escaping(ctx, kb, oinstruction->payload.fill_bytes.dst); - break; - } - case Instruction_Block_TAG: - break; - case Instruction_Comment_TAG: - break; - } - - return recreate_node_identity(r, oinstruction); -} - -static const Node* process_terminator(Context* ctx, KnowledgeBase* kb, const Node* old) { - IrArena* a = ctx->rewriter.dst_arena; - Rewriter* r = &ctx->rewriter; - switch (is_terminator(old)) { - case NotATerminator: assert(false); - case Let_TAG: - break; - case Jump_TAG: { - const Node* old_target = old->payload.jump.target; - // rewrite_node(&ctx->rewriter, old_target); - Nodes args = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); - - String s = get_abstraction_name_unsafe(old_target); - Node* wrapper = basic_block(a, recreate_params(r, get_abstraction_params(old_target)), s); - TodoJump todo = { - .old_jump = old, - .wrapper_bb = wrapper, - .kb = kb, - }; - append_list(TodoJump, ctx->todo_jumps, todo); - - return jump_helper(a, wrapper, args); - } - case Terminator_TailCall_TAG: - mark_values_as_escaping(ctx, kb, old->payload.tail_call.args); - break; - case Terminator_Branch_TAG: - break; - case Terminator_Switch_TAG: - break; - case Terminator_Join_TAG: - // TODO: local joins are fine - mark_values_as_escaping(ctx, kb, old->payload.join.args); - break; - case Terminator_If_TAG: - break; - case Terminator_Match_TAG: - break; - case Terminator_Loop_TAG: - mark_values_as_escaping(ctx, kb, old->payload.loop_instr.initial_args); - // assert(false && "unsupported"); - break; - case Control_TAG: - break; - case Terminator_MergeContinue_TAG: - break; - case Terminator_MergeBreak_TAG: - break; - case Terminator_MergeSelection_TAG: - break; - case Terminator_BlockYield_TAG: - break; - case Terminator_Return_TAG: - mark_values_as_escaping(ctx, kb, old->payload.fn_ret.args); - break; - case Terminator_Unreachable_TAG: - break; - } - return recreate_node_identity(r, old); -} - -static void handle_bb(Context* ctx, const Node* old) { - IrArena* a = ctx->rewriter.dst_arena; - Rewriter* r = &ctx->rewriter; - - log_string(DEBUGV, "mem2reg: handling bb %s\n", get_abstraction_name_safe(old)); - - KnowledgeBase* kb = create_kb(ctx, old); - Context fn_ctx = *ctx; - fn_ctx.oabs = old; - ctx = &fn_ctx; - - Nodes params = recreate_params(&ctx->rewriter, get_abstraction_params(old)); - //Nodes let_params = recreate_params(&ctx->rewriter, get_abstraction_params(old)); - //register_processed_list(&ctx->rewriter, get_abstraction_params(old), let_params); - register_processed_list(r, get_abstraction_params(old), params); - const Node* nbody = rewrite_node(&ctx->rewriter, get_abstraction_body(old)); - //nbody = let(a, quote_helper(a, params), case_(a, let_params, nbody)); - - CFNode* cfnode = cfg_lookup(ctx->cfg, old); - BodyBuilder* bb = begin_body(a); - size_t i = 0; - const Node* ptr; - Nodes ptrs = empty(ctx->rewriter.src_arena); - while (dict_iter(kb->potential_additional_params, &i, &ptr, NULL)) { - PtrSourceKnowledge* source = NULL; - PtrKnowledge uk = { 0 }; - // check if all the edges have a value for this! - for (size_t j = 0; j < entries_count_list(cfnode->pred_edges); j++) { - CFEdge edge = read_list(CFEdge, cfnode->pred_edges)[j]; - if (edge.type == StructuredTailEdge) - continue; // these are not real edges... - KnowledgeBase* kb_at_src = get_kb(ctx, edge.src->node); - if (!kb_at_src) { - goto next_potential_param; - } - - const Node* kv = get_known_value(kb_at_src, get_last_valid_ptr_knowledge(kb_at_src, ptr)); - if (kv) { - log_node(DEBUGVV, ptr); - log_string(DEBUGVV, " has a known value ("); - log_node(DEBUGVV, kv); - log_string(DEBUGVV, ") in %s ...\n", get_abstraction_name_safe(edge.src->node)); - } else - goto next_potential_param; - - PtrKnowledge* k = get_last_valid_ptr_knowledge(kb_at_src, ptr); - if (!source) - source = k->source; - else - assert(source == k->source); - - const Type* kv_type = get_known_value(kb_at_src, get_last_valid_ptr_knowledge(kb_at_src, ptr))->type; - deconstruct_qualified_type(&kv_type); - const Type* alloca_type_t = source->type; - //deconstruct_qualified_type(&alloca_type_t); - if (kv_type != source->type && !is_reinterpret_cast_legal(kv_type, alloca_type_t)) { - log_node(DEBUGVV, ptr); - log_string(DEBUGVV, " has a known value in %s, but it's type ", get_abstraction_name_safe(edge.src->node)); - log_node(DEBUGVV, kv_type); - log_string(DEBUGVV, " cannot be reinterpreted into the alloca type "); - log_node(DEBUGVV, source->type); - log_string(DEBUGVV, "\n."); - goto next_potential_param; - } - - uk.ptr_has_leaked |= k->ptr_has_leaked; - } - - log_node(DEBUGVV, ptr); - log_string(DEBUGVV, " has a known value in all predecessors! Turning it into a new parameter.\n"); - - // assert(!is_qualified_type_uniform(source->type)); - const Node* nparam = param(a, qualified_type_helper(source->type, false), unique_name(a, "ssa_phi")); - params = append_nodes(a, params, nparam); - ptrs = append_nodes(ctx->rewriter.src_arena, ptrs, ptr); - gen_store(bb, rewrite_node(r, ptr), nparam); - - PtrKnowledge* k = arena_alloc(ctx->a, sizeof(PtrKnowledge)); - *k = (PtrKnowledge) { - .ptr_value = nparam, - .source = source, - .ptr_has_leaked = uk.ptr_has_leaked - }; - insert_ptr_knowledge(kb, ptr, k); - - next_potential_param: continue; - } - - Node* new_bb = basic_block(a, params, get_abstraction_name_unsafe(old)); - register_processed(&ctx->rewriter, old, new_bb); - new_bb->payload.basic_block.body = finish_body(bb, nbody); - - // new_bb->type = bb_type(a, (BBType) { - // .param_types = get_variables_types(a, get_abstraction_params(new_bb)), - // }); - - if (ptrs.count > 0) { - insert_dict(const Node*, Nodes, ctx->bb_new_args, old, ptrs); - } -} - -static void handle_jump_wrappers(Context* ctx) { - IrArena* a = ctx->rewriter.dst_arena; - for (size_t j = 0; j < entries_count_list(ctx->todo_jumps); j++) { - TodoJump todo = read_list(TodoJump, ctx->todo_jumps)[j]; - const Node* old = todo.old_jump; - const Node* old_target = old->payload.jump.target; - const Node* new_target = rewrite_node(&ctx->rewriter, old_target); - Nodes args = get_abstraction_params(todo.wrapper_bb); - - BodyBuilder* bb = begin_body(a); - Nodes* additional_ssa_params = find_value_dict(const Node*, Nodes, ctx->bb_new_args, old_target); - if (additional_ssa_params) { - assert(additional_ssa_params->count > 0); - - for (size_t i = 0; i < additional_ssa_params->count; i++) { - const Node* ptr = additional_ssa_params->nodes[i]; - PtrKnowledge* k = get_last_valid_ptr_knowledge(todo.kb, ptr); - const Node* value = get_known_value(todo.kb, k); - - const Type* known_value_t = value->type; - deconstruct_qualified_type(&known_value_t); - - const Type* alloca_type_t = k->source->type; - - if (alloca_type_t != known_value_t && is_reinterpret_cast_legal(alloca_type_t, known_value_t)) - value = first(gen_primop(bb, reinterpret_op, singleton(rewrite_node(&ctx->rewriter, alloca_type_t)), singleton(value))); - - assert(value); - args = append_nodes(a, args, value); - } - - } - todo.wrapper_bb->payload.basic_block.body = finish_body(bb, jump_helper(a, new_target, args)); - } -} - -static const Node* process(Context* ctx, const Node* old) { - assert(old); - Context fn_ctx = *ctx; - if (is_abstraction(old)) { - fn_ctx.oabs = old; - ctx = &fn_ctx; - } - - KnowledgeBase* kb = NULL; - if (old->tag == Function_TAG) { - // if (lookup_annotation(old, "Internal")) { - // fn_ctx.cfg = NULL; - // return recreate_node_identity(&fn_ctx.rewriter, old);; - // } - fn_ctx.cfg = build_fn_cfg(old); - fn_ctx.abs_to_kb = new_dict(const Node*, KnowledgeBase**, (HashFn) hash_node, (CmpFn) compare_node); - fn_ctx.todo_jumps = new_list(TodoJump), - kb = create_kb(ctx, old); - const Node* new_fn = recreate_node_identity(&fn_ctx.rewriter, old); - - for (size_t i = 1; i < ctx->cfg->size; i++) { - CFNode* cf_node = ctx->cfg->rpo[i]; - if (cf_node->node->tag == BasicBlock_TAG) - handle_bb(ctx, cf_node->node); - } - - //handle_bb_wrappers(ctx); - //clear_list(ctx->todo_bbs); - handle_jump_wrappers(ctx); - destroy_list(fn_ctx.todo_jumps); - - destroy_cfg(fn_ctx.cfg); - size_t i = 0; - while (dict_iter(fn_ctx.abs_to_kb, &i, NULL, &kb)) { - destroy_kb(kb); - } - destroy_dict(fn_ctx.abs_to_kb); - return new_fn; - } else if (old->tag == Constant_TAG) { - fn_ctx.cfg = NULL; - fn_ctx.abs_to_kb = NULL; - fn_ctx.todo_jumps = NULL; - ctx = &fn_ctx; - } - - // setup a new KB if this is a fresh abstraction - if (is_abstraction(old) && ctx->cfg) { - kb = create_kb(ctx, old); - } else if (ctx->oabs && ctx->abs_to_kb) { - // otherwise look up the enclosing one, if any - kb = get_kb(ctx, ctx->oabs); - assert(kb); - } - if (!kb) - return recreate_node_identity(&ctx->rewriter, old); - - if (is_instruction(old)) - return process_instruction(ctx, kb, old); - if (is_terminator(old)) - return process_terminator(ctx, kb, old); - - switch (old->tag) { - case BasicBlock_TAG: { - assert(false); - } - default: break; - } - return recreate_node_identity(&ctx->rewriter, old); -} - -RewritePass cleanup; - -Module* opt_mem2reg(const CompilerConfig* config, Module* src) { - return src; - - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* initial_arena = get_module_arena(src); - IrArena* a = new_ir_arena(&aconfig); - Module* dst = src; - - for (size_t round = 0; round < 5; round++) { - dst = new_module(a, get_module_name(src)); - - Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .bb_new_args = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), - .a = new_arena(), - - .todo_jumps = NULL, - }; - - ctx.rewriter.config.fold_quote = false; - // ctx.rewriter.config.rebind_let = false; - - rewrite_module(&ctx.rewriter); - - destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.bb_new_args); - destroy_arena(ctx.a); - - verify_module(config, dst); - - if (get_module_arena(src) != initial_arena) - destroy_ir_arena(get_module_arena(src)); - - dst = cleanup(config, dst); - src = dst; - } - - destroy_ir_arena(a); - - return dst; -} diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 0b3c0016c..f67d84208 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -82,13 +82,20 @@ static DFSStackEntry* encountered_before(Context* ctx, const Node* bb, size_t* p return entry; } -static const Node* structure(Context* ctx, const Node* abs, const Node* exit_ladder); +static const Node* make_unreachable_case(IrArena* a) { + Node* c = case_(a, empty(a)); + set_abstraction_body(c, unreachable(a, (Unreachable) { get_abstraction_mem(c) })); + return c; +} + +static const Node* structure(Context* ctx, const Node* abs, const Node* exit); + +static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* exit) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; -static const Node* handle_bb_callsite(Context* ctx, const Node* j, const Node* exit_ladder) { - assert(j->tag == Jump_TAG); - IrArena* a = ctx->rewriter.dst_arena; - const Node* dst = j->payload.jump.target; - Nodes oargs = j->payload.jump.args; + const Node* dst = jump.target; + Nodes oargs = jump.args; size_t path_len; DFSStackEntry* prior_encounter = encountered_before(ctx, dst, &path_len); @@ -108,7 +115,8 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* j, const Node* e } prior_encounter->loop_header = true; return merge_continue(a, (MergeContinue) { - .args = rewrite_nodes(&ctx->rewriter, oargs) + .args = rewrite_nodes(r, oargs), + .mem = rewrite_node(r, jump.mem), }); } else { Nodes oparams = get_abstraction_params(dst); @@ -120,7 +128,7 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* j, const Node* e DFSStackEntry dfs_entry = { .parent = ctx->dfs_stack, .old = dst, .containing_control = ctx->control_stack }; ctx2.dfs_stack = &dfs_entry; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, jump.mem)); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); @@ -137,7 +145,7 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* j, const Node* e Node* inner_exit_ladder_bb = basic_block(a, empty(a), unique_name(a, "exit_ladder_inline_me")); // Just jumps to the actual ladder - const Node* structured = structure(&ctx2, get_abstraction_body(dst), jump(a, (Jump) {.target = inner_exit_ladder_bb, .args = empty(a)})); + const Node* structured = structure(&ctx2, get_abstraction_body(dst), inner_exit_ladder_bb); assert(is_terminator(structured)); // forget we rewrote all that destroy_dict(tmp_processed); @@ -149,15 +157,13 @@ static const Node* handle_bb_callsite(Context* ctx, const Node* j, const Node* e set_abstraction_body(loop_case, structured); gen_loop(bb, empty(a), rewrite_nodes(&ctx->rewriter, oargs), loop_case); // we decide 'late' what the exit ladder should be - inner_exit_ladder_bb->payload.basic_block.body = merge_break(a, (MergeBreak) { .args = empty(a) }); - return finish_body(bb, exit_ladder); + inner_exit_ladder_bb->payload.basic_block.body = merge_break(a, (MergeBreak) { .args = empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) }); + return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); } else { Node* bb2 = basic_block(a, nodes(a, oargs.count, nparams), NULL); bb2->payload.basic_block.body = structured; - //bind_variables(bb, nodes(a, oargs.count, nparams), rewrite_nodes(&ctx->rewriter, oargs)); - inner_exit_ladder_bb->payload.basic_block.body = exit_ladder; - //return finish_body(bb, structured); - return finish_body(bb, jump_helper(a, bb2, rewrite_nodes(&ctx->rewriter, oargs))); + inner_exit_ladder_bb->payload.basic_block.body = jump_helper(a, exit, empty(a), get_abstraction_mem(inner_exit_ladder_bb)); + return finish_body(bb, jump_helper(a, bb2, rewrite_nodes(&ctx->rewriter, oargs), bb_mem(bb))); } } } @@ -173,127 +179,109 @@ static ControlEntry* search_containing_control(Context* ctx, const Node* old_tok return entry; } -static const Node* structure(Context* ctx, const Node* body, const Node* exit_ladder) { +static const Node* structure(Context* ctx, const Node* body, const Node* exit) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; assert(body && is_terminator(body)); switch (is_terminator(body)) { case NotATerminator: - case Let_TAG: { - const Node* old_instr = get_let_instruction(body); - switch (is_instruction(old_instr)) { - case NotAnInstruction: assert(false); - case Instruction_Block_TAG: error("Should be eliminated by the compiler"); - case Instruction_Call_TAG: { - const Node* callee = old_instr->payload.call.callee; - if (callee->tag == FnAddr_TAG) { - const Node* fn = rewrite_node(&ctx->rewriter, callee->payload.fn_addr.fn); - // leave leaf calls alone - if (lookup_annotation(fn, "Leaf")) { - break; - } - } - // if we don't manage that, give up :( - assert(false); // actually that should not come up. - longjmp(ctx->bail, 1); - } - default: { - break; - } - } - const Node* new_instruction = rewrite_node(&ctx->rewriter, old_instr); - return let(a, new_instruction, structure(ctx, body->payload.let.in, exit_ladder)); - } case Jump_TAG: { - return handle_bb_callsite(ctx, body, exit_ladder); + return handle_bb_callsite(ctx, body->payload.jump, exit); } // br(cond, true_bb, false_bb, args) // becomes // let(if(cond, _ => handle_bb_callsite[true_bb, args], _ => handle_bb_callsite[false_bb, args]), _ => unreachable) case Branch_TAG: { - const Node* condition = rewrite_node(&ctx->rewriter, body->payload.branch.condition); + Branch payload = body->payload.branch; + const Node* condition = rewrite_node(&ctx->rewriter, payload.condition); Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, handle_bb_callsite(ctx, body->payload.branch.true_jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); + set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); Node* false_case = case_(a, empty(a)); - set_abstraction_body(false_case, handle_bb_callsite(ctx, body->payload.branch.false_jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); + set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_if(bb, empty(a), condition, true_case, false_case); - return finish_body(bb, exit_ladder); + return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); } case Switch_TAG: { - const Node* switch_value = rewrite_node(&ctx->rewriter, body->payload.br_switch.switch_value); + Switch payload = body->payload.br_switch; + const Node* switch_value = rewrite_node(r, payload.switch_value); Node* default_case = case_(a, empty(a)); - set_abstraction_body(default_case, handle_bb_callsite(ctx, body->payload.br_switch.default_jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); + set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); LARRAY(Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { cases[i] = case_(a, empty(a)); - set_abstraction_body(cases[i], handle_bb_callsite(ctx, body->payload.br_switch.case_jumps.nodes[i], merge_selection(a, (MergeSelection) {.args = empty(a)}))); + set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, merge_selection(a, (MergeSelection) {.args = empty(a)}))); } - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_match(bb, empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), nodes(a, body->payload.br_switch.case_jumps.count, cases), default_case); - finish_body(bb, exit_ladder); + return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); } // let(control(body), tail) // var phi = undef; level = N+1; structurize[body, if (level == N+1, _ => tail(load(phi))); structured_exit_terminator] case Control_TAG: { - const Node* old_control_body = body->payload.control.inside; - Nodes old_control_params = get_abstraction_params(old_control_body); + Control payload = body->payload.control; + const Node* old_control_case = payload.inside; + Nodes old_control_params = get_abstraction_params(old_control_case); assert(old_control_params.count == 1); // Create N temporary variables to hold the join point arguments - BodyBuilder* bb_outer = begin_body(a); + BodyBuilder* bb_prelude = begin_body_with_mem(a, rewrite_node(r, payload.mem)); Nodes yield_types = rewrite_nodes(&ctx->rewriter, body->payload.control.yield_types); LARRAY(const Node*, phis, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { const Type* type = yield_types.nodes[i]; assert(is_data_type(type)); - phis[i] = gen_local_alloc(bb_outer, type); + phis[i] = gen_local_alloc(bb_prelude, type); } // Create a new context to rewrite the body with // TODO: Bail if we try to re-enter the same control construct Context control_ctx = *ctx; ControlEntry control_entry = { - .parent = ctx->control_stack, - .old_token = first(old_control_params), - .phis = phis, - .depth = ctx->control_stack ? ctx->control_stack->depth + 1 : 1, + .parent = ctx->control_stack, + .old_token = first(old_control_params), + .phis = phis, + .depth = ctx->control_stack ? ctx->control_stack->depth + 1 : 1, }; control_ctx.control_stack = &control_entry; // Set the depth for threads entering the control body - gen_store(bb_outer, ctx->level_ptr, int32_literal(a, control_entry.depth)); + gen_store(bb_prelude, ctx->level_ptr, int32_literal(a, control_entry.depth)); // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() - BodyBuilder* bb2 = begin_body(a); + Node* tail = case_(a, empty(a)); + BodyBuilder* bb_tail = begin_body_with_mem(a, get_abstraction_mem(tail)); LARRAY(const Node*, phi_values, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { - phi_values[i] = gen_load(bb2, phis[i]); + phi_values[i] = gen_load(bb_tail, phis[i]); register_processed(&ctx->rewriter, get_abstraction_params(get_structured_construct_tail(body)).nodes[i], phi_values[i]); } // Wrap the tail in a guarded if, to handle 'far' joins - const Node* level_value = gen_load(bb2, ctx->level_ptr); - const Node* guard = first(bind_instruction(bb2, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); - const Node* true_case = case_(a, empty(a)); + const Node* level_value = gen_load(bb_tail, ctx->level_ptr); + const Node* guard = first(bind_instruction(bb_tail, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); + Node* true_case = case_(a, empty(a)); set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), merge_selection(a, (MergeSelection) { .args = empty(a) }))); - gen_if(bb2, empty(a), guard, true_case, NULL); + gen_if(bb_tail, empty(a), guard, true_case, NULL); - return finish_body(bb_outer, structure(&control_ctx, get_abstraction_body(old_control_body), finish_body(bb2, exit_ladder))); + set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, exit, empty(a), bb_mem(bb_tail)))); + register_processed(r, get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); + return finish_body(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); } case Join_TAG: { + Join payload = body->payload.join; ControlEntry* control = search_containing_control(ctx, body->payload.join.join_point); if (!control) longjmp(ctx->bail, 1); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_store(bb, ctx->level_ptr, int32_literal(a, control->depth - 1)); Nodes args = rewrite_nodes(&ctx->rewriter, body->payload.join.args); @@ -301,7 +289,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit_la gen_store(bb, control->phis[i], args.nodes[i]); } - return finish_body(bb, exit_ladder); + return finish_body(bb, exit); } case Return_TAG: @@ -312,7 +300,6 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit_la case If_TAG: case Match_TAG: case Loop_TAG: error("not supposed to exist in IR at this stage"); - case Terminator_BlockYield_TAG: case Terminator_MergeBreak_TAG: case Terminator_MergeContinue_TAG: case Terminator_MergeSelection_TAG: error("Only control nodes are tolerated here.") @@ -320,7 +307,8 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit_la } static const Node* process(Context* ctx, const Node* node) { - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; if (!node) return NULL; assert(a != node->arena); assert(node->arena == ctx->rewriter.src_arena); @@ -356,7 +344,7 @@ static const Node* process(Context* ctx, const Node* node) { is_leaf = is_builtin || !node->payload.fun.body; } else { ctx2.lower = true; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); const Node* ptr = gen_local_alloc(bb, int32_type(a)); @@ -368,7 +356,8 @@ static const Node* process(Context* ctx, const Node* node) { TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; - new->payload.fun.body = finish_body(bb, structure(&ctx2, get_abstraction_body(node), unreachable(a))); + register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + new->payload.fun.body = finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a) )); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. pop_list_impl(ctx->cleanup_stack); @@ -397,6 +386,19 @@ static const Node* process(Context* ctx, const Node* node) { // assert(!is_terminator(node) && !is_instruction(node)); switch (node->tag) { + case Instruction_Call_TAG: { + const Node* callee = node->payload.call.callee; + if (callee->tag == FnAddr_TAG) { + const Node* fn = rewrite_node(&ctx->rewriter, callee->payload.fn_addr.fn); + // leave leaf calls alone + if (lookup_annotation(fn, "Leaf")) { + break; + } + } + // if we don't manage that, give up :( + assert(false); // actually that should not come up. + longjmp(ctx->bail, 1); + } default: return recreate_node_identity(&ctx->rewriter, node); } } diff --git a/src/shady/passes/opt_stack.c b/src/shady/passes/opt_stack.c deleted file mode 100644 index ea08412d0..000000000 --- a/src/shady/passes/opt_stack.c +++ /dev/null @@ -1,128 +0,0 @@ -#include "pass.h" - -#include "portability.h" -#include "log.h" - -typedef struct StackState_ StackState; -struct StackState_ { - StackState* prev; - enum { VALUE, MERGE } type; - bool leaks; - const Node* value; - size_t count; - const Node** values; -}; - -typedef struct { - Rewriter rewriter; - StackState* state; -} Context; - -static void tag_leaks(Context* ctx) { - StackState* s = ctx->state; - while (s) { - s->leaks = true; - s = s->prev; - } -} - -static const Node* process(Context* ctx, const Node* node) { - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - - IrArena* a = ctx->rewriter.dst_arena; - StackState entry; - Context child_ctx = *ctx; - - bool is_push = false; - bool is_pop = false; - - switch (is_terminator(node)) { - case Terminator_Unreachable_TAG: break; - case Let_TAG: { - const Node* old_instruction = node->payload.let.instruction; - const Node* ntail = NULL; - switch (is_instruction(old_instruction)) { - case Instruction_PushStack_TAG: { - const Node* value = rewrite_node(&ctx->rewriter, old_instruction->payload.push_stack.value); - entry = (StackState) { - .prev = ctx->state, - .type = VALUE, - .value = value, - .leaks = false, - }; - child_ctx.state = &entry; - is_push = true; - break; - } - case Instruction_PopStack_TAG: { - if (ctx->state) { - child_ctx.state = ctx->state->prev; - is_pop = true; - } - break; - } - case Instruction_Block_TAG: - // Leaf calls and indirect calls are not analysed and so they are considered to leak the state - // we also need to forget our information about the current state - case Instruction_Call_TAG: { - tag_leaks(ctx); - child_ctx.state = NULL; - break; - } - default: break; - case NotAnInstruction: assert(false); - } - - ntail = rewrite_node(&child_ctx.rewriter, node->payload.let.in); - - const Node* ninstruction = NULL; - if (is_push && !child_ctx.state->leaks) { - // replace stack pushes with no-ops - ninstruction = maybe_tuple_helper(a, empty(a)); - } else if (is_pop) { - assert(ctx->state->type == VALUE); - const Node* value = ctx->state->value; - ninstruction = value; - } else { - // if the stack state is observed, or this was an unrelated instruction, leave it alone - ninstruction = recreate_node_identity(&ctx->rewriter, old_instruction); - } - assert(ninstruction); - return let(a, ninstruction, ntail); - } - // Unreachable is assumed to never happen, so it doesn't observe the stack state - case NotATerminator: break; - default: { - // All other non-let terminators are considered to leak the stack state - tag_leaks(ctx); - break; - } - } - - // child_ctx.state = NULL; - switch (node->tag) { - case Function_TAG: { - Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); - child_ctx.state = NULL; - recreate_decl_body_identity(&child_ctx.rewriter, node, fun); - return fun; - } - default: return recreate_node_identity(&child_ctx.rewriter, node); - } -} - -Module* opt_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); - - Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .state = NULL, - }; - - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); - return dst; -} diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index b5c903f02..049aa37e9 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -112,11 +112,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(read_list(CFNode*, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); } - BodyBuilder* outer_bb = begin_body(arena); - size_t exiting_nodes_count = entries_count_list(exiting_nodes); if (exiting_nodes_count > 0) { Nodes nparams = recreate_params(rewriter, get_abstraction_params(node)); + Node* loop_container = basic_block(arena, nparams, node->payload.basic_block.name); + BodyBuilder* outer_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_container)); Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); CFNode* cf_pre = cfg_lookup(ctx->fwd_cfg, node); @@ -173,7 +173,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { switch (exiting_node->node->tag) { case BasicBlock_TAG: { Node* pre_join_exit_bb = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); - pre_join_exit_bb->payload.basic_block.body = jump_helper(arena, exit_helpers[i], empty(arena)); + pre_join_exit_bb->payload.basic_block.body = jump_helper(arena, exit_helpers[i], empty(arena), get_abstraction_mem(pre_join_exit_bb)); exit_wrappers[i] = pre_join_exit_bb; break; } @@ -229,7 +229,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = get_abstraction_params(exit_wrappers[i]); - BodyBuilder* exit_wrapper_bb = begin_body(arena); + BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_helpers[i])); for (size_t j = 0; j < exit_param_allocas[i].count; j++) gen_store(exit_wrapper_bb, exit_param_allocas[i].nodes[j], exit_wrapper_params.nodes[j]); @@ -262,17 +262,16 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (cached_entry) register_processed(rewriter, node, cached_entry); - BodyBuilder* inner_bb = begin_body(arena); + Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); + BodyBuilder* inner_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_outer)); Node* inner_control_case = case_(arena, singleton(join_token_continue)); set_abstraction_body(inner_control_case, loop_body); Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); - Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); - - loop_outer->payload.basic_block.body = finish_body(inner_bb, jump(arena, (Jump) { + set_abstraction_body(loop_outer, finish_body(inner_bb, jump(arena, (Jump) { .target = loop_outer, .args = inner_control_results - })); + }))); Node* outer_control_case = case_(arena, singleton(join_token_exit)); set_abstraction_body(outer_control_case, jump(arena, (Jump) { .target = loop_outer, @@ -283,10 +282,12 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(const Node*, exit_numbers, exiting_nodes_count); LARRAY(const Node*, exit_jumps, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { - BodyBuilder* exit_recover_bb = begin_body(arena); + CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + + Node* exit_bb = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); + BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); // recover the context - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { const Node* recovered = gen_load(exit_recover_bb, exit_fwd_allocas[i].nodes[j]); register_processed(rewriter, read_list(const Node*, leaking[i])[j], recovered); @@ -299,7 +300,6 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { recovered_args[j] = gen_load(exit_recover_bb, exit_param_allocas[i].nodes[j]); exit_numbers[i] = int32_literal(arena, i); - Node* exit_bb = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); if (recreated_exit->tag == BasicBlock_TAG) { exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, jump(arena, (Jump) { .target = recreated_exit, @@ -312,13 +312,13 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { // assert(recreated_exit->tag == Case_TAG); // exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, let(arena, quote_helper(arena, nodes(arena, exit_param_allocas[i].count, recovered_args)), recreated_exit)); } - exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena)); + exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena), bb_mem(outer_bb)); destroy_list(leaking[i]); } const Node* outer_body; if (exiting_nodes_count == 1) - outer_body = finish_body(outer_bb, exit_jumps[0]->payload.jump.target->payload.basic_block.body); + outer_body = finish_body(outer_bb, exit_jumps[0]); else { const Node* loaded_destination = gen_load(outer_bb, exit_destination_alloca); outer_body = finish_body(outer_bb, br_switch(arena, (Switch) { @@ -326,19 +326,10 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .default_jump = exit_jumps[0], .case_values = nodes(arena, exiting_nodes_count, exit_numbers), .case_jumps = nodes(arena, exiting_nodes_count, exit_jumps), + .mem = bb_mem(outer_bb) })); } - - Node* loop_container; - switch (node->tag) { - case BasicBlock_TAG: { - loop_container = basic_block(arena, nparams, node->payload.basic_block.name); - set_abstraction_body(loop_container, outer_body); - break; - } - default: - assert(false); - } + set_abstraction_body(loop_container, outer_body); destroy_list(exiting_nodes); return loop_container; } @@ -352,8 +343,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { static const Node* process_node(Context* ctx, const Node* node) { assert(node); - Rewriter* rewriter = &ctx->rewriter; - IrArena* arena = rewriter->dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; Context new_context = *ctx; @@ -377,7 +368,7 @@ static const Node* process_node(Context* ctx, const Node* node) { case Constant_TAG: { ctx = &new_context; ctx->current_fn = NULL; - rewriter = &ctx->rewriter; + r = &ctx->rewriter; break; } case BasicBlock_TAG: @@ -437,7 +428,7 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(idom_lt_node); assert(current_node); - Node* fn = (Node*) find_processed(rewriter, ctx->current_fn); + Node* fn = (Node*) find_processed(r, ctx->current_fn); //Regular if/then/else case. Control flow joins at the immediate post dominator. Nodes yield_types; @@ -446,8 +437,8 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes old_params = get_abstraction_params(idom); if (old_params.count == 0) { - yield_types = empty(arena); - exit_args = empty(arena); + yield_types = empty(a); + exit_args = empty(a); } else { LARRAY(const Node*, types,old_params.count); LARRAY(const Node*, inner_args,old_params.count); @@ -455,54 +446,54 @@ static const Node* process_node(Context* ctx, const Node* node) { for (size_t j = 0; j < old_params.count; j++) { //TODO: Is this correct? assert(old_params.nodes[j]->tag == Param_TAG); - const Node* qualified_type = rewrite_node(rewriter, old_params.nodes[j]->payload.param.type); + const Node* qualified_type = rewrite_node(r, old_params.nodes[j]->payload.param.type); //const Node* qualified_type = rewrite_node(rewriter, old_params.nodes[j]->type); //This should always contain a qualified type? //if (contains_qualified_type(types[j])) types[j] = get_unqualified_type(qualified_type); - inner_args[j] = param(arena, qualified_type, old_params.nodes[j]->payload.param.name); + inner_args[j] = param(a, qualified_type, old_params.nodes[j]->payload.param.name); } - yield_types = nodes(arena, old_params.count, types); - exit_args = nodes(arena, old_params.count, inner_args); + yield_types = nodes(a, old_params.count, types); + exit_args = nodes(a, old_params.count, inner_args); } - const Node* join_token = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { + const Node* join_token = param(a, qualified_type_helper(join_point_type(a, (JoinPointType) { .yield_types = yield_types }), true), "jp_postdom"); - Node* pre_join = basic_block(arena, exit_args, format_string_arena(arena->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); - pre_join->payload.basic_block.body = join(arena, (Join) { + Node* pre_join = basic_block(a, exit_args, format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); + pre_join->payload.basic_block.body = join(a, (Join) { .join_point = join_token, .args = exit_args }); - const Node* cached = search_processed(rewriter, idom); + const Node* cached = search_processed(r, idom); if (cached) - remove_dict(const Node*, is_declaration(idom) ? rewriter->decls_map : rewriter->map, idom); + remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); for (size_t i = 0; i < old_params.count; i++) { - assert(!search_processed(rewriter, old_params.nodes[i])); + assert(!search_processed(r, old_params.nodes[i])); } - register_processed(rewriter, idom, pre_join); + register_processed(r, idom, pre_join); - const Node* inner_terminator = recreate_node_identity(rewriter, node); + const Node* inner_terminator = recreate_node_identity(r, node); - remove_dict(const Node*, is_declaration(idom) ? rewriter->decls_map : rewriter->map, idom); + remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); if (cached) - register_processed(rewriter, idom, cached); + register_processed(r, idom, cached); - Node* control_case = case_(arena, singleton(join_token)); + Node* control_case = case_(a, singleton(join_token)); set_abstraction_body(control_case, inner_terminator); - const Node* join_target = rewrite_node(rewriter, idom); + const Node* join_target = rewrite_node(r, idom); switch (idom->tag) { case BasicBlock_TAG: { - BodyBuilder* bb = begin_body(arena); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); Nodes results = gen_control(bb, yield_types, control_case); - return finish_body(bb, jump(arena, (Jump) { + return finish_body(bb, jump(a, (Jump) { .target = join_target, .args = results })); @@ -513,7 +504,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } default: break; } - return recreate_node_identity(rewriter, node); + return recreate_node_identity(r, node); } Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index b2200849d..0d5b62a04 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -32,11 +32,12 @@ static const Node* process(Context* ctx, const Node* node) { Context ctx2 = *ctx; ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); if (!ctx2.disable_lowering) { ctx2.stack_size_on_entry = gen_get_stack_size(bb); set_value_name((Node*) ctx2.stack_size_on_entry, format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun))); } + register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); if (node->payload.fun.body) fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); else @@ -44,13 +45,17 @@ static const Node* process(Context* ctx, const Node* node) { return fun; } case Return_TAG: { - BodyBuilder* bb = begin_body(a); + Return payload = node->payload.fn_ret; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); if (!ctx->disable_lowering) { assert(ctx->stack_size_on_entry); // Restore SP before calling exit gen_set_stack_size(bb, ctx->stack_size_on_entry); } - return finish_body(bb, recreate_node_identity(r, node)); + return finish_body(bb, fn_ret(a, (Return) { + .mem = bb_mem(bb), + .args = rewrite_nodes(r, payload.args), + })); } default: break; } diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c index 6ec45b35b..d7eed477e 100644 --- a/src/shady/passes/simt2d.c +++ b/src/shady/passes/simt2d.c @@ -25,7 +25,8 @@ static const Node* process(Context* ctx, const Node* node) { const Node* found = search_processed(&ctx->rewriter, node); if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { case QualifiedType_TAG: { if (!node->payload.qualified_type.is_uniform) return qualified_type(a, (QualifiedType) { @@ -35,7 +36,8 @@ static const Node* process(Context* ctx, const Node* node) { goto rewrite; } case LocalAlloc_TAG: { - BodyBuilder* bb = begin_body(a); + LocalAlloc payload = node->payload.local_alloc; + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* type = rewrite_node(&ctx->rewriter, node->payload.local_alloc.type); LARRAY(const Node*, allocated, ctx->width); for (size_t i = 0; i < ctx->width; i++) { diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 20a7e709d..2140906dc 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -59,7 +59,7 @@ static const Node* process(Context* ctx, const Node* node) { uint32_t subgroups_per_wg = (wg_size[0] * wg_size[1] * wg_size[2]) / ctx->config->specialization.subgroup_size; if (subgroups_per_wg == 0) subgroups_per_wg = 1; // uh-oh - ncnst->payload.constant.instruction = uint32_literal(a, subgroups_per_wg); + ncnst->payload.constant.value = uint32_literal(a, subgroups_per_wg); } return ncnst; } diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 3ee495c14..098eb959e 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -24,7 +24,7 @@ static const Node* process(Context* ctx, const Node* node) { case Constant_TAG: { Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { - ncnst->payload.constant.instruction = uint32_literal(a, ctx->config->specialization.subgroup_size); + ncnst->payload.constant.value = uint32_literal(a, ctx->config->specialization.subgroup_size); } return ncnst; } diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index eb0cb9e2e..420a8571b 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -10,7 +10,7 @@ typedef struct { Rewriter rewriter; const CompilerConfig* config; - BodyBuilder* bb; + //BodyBuilder* bb; Node* lifted_globals_decl; } Context; @@ -21,7 +21,7 @@ static const Node* process(Context* ctx, const Node* node) { Context c = *ctx; ctx = &c; if (is_abstraction(node)) { - c.bb = abs_bb = begin_body(a); + //c.bb = abs_bb = begin_body(a); } switch (node->tag) { @@ -29,10 +29,11 @@ static const Node* process(Context* ctx, const Node* node) { const Node* odecl = node->payload.ref_decl.decl; if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) break; - assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); - const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), int32_literal(a, 0), singleton(rewrite_node(&ctx->rewriter, odecl))); + error("TODO") + /*assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); + const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), int32_literal(a, 0), singleton(rewrite_node(&ctx->rewriter, odecl))); const Node* ptr = gen_load(ctx->bb, ptr_addr); - return ptr; + return ptr;*/ } case GlobalVariable_TAG: if (node->payload.global_variable.address_space != AsGlobal) @@ -42,13 +43,13 @@ static const Node* process(Context* ctx, const Node* node) { } Node* new = (Node*) recreate_node_identity(&ctx->rewriter, node); - if (abs_bb) { + /*if (abs_bb) { assert(is_abstraction(new)); if (get_abstraction_body(new)) set_abstraction_body(new, finish_body(abs_bb, get_abstraction_body(new))); else cancel_body(abs_bb); - } + }*/ return new; } diff --git a/src/shady/passes/spirv_map_entrypoint_args.c b/src/shady/passes/spirv_map_entrypoint_args.c index 401cc0263..81d2e43a7 100644 --- a/src/shady/passes/spirv_map_entrypoint_args.c +++ b/src/shady/passes/spirv_map_entrypoint_args.c @@ -69,7 +69,6 @@ Module* spirv_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Mod .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; - ctx.rewriter.config.rebind_let = true; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); return dst; diff --git a/src/shady/print.c b/src/shady/print.c index 1905469cc..66c2299ad 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -648,25 +648,6 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { printf(")"); print_args_list(ctx, node->payload.call.args); break; - } case Block_TAG: { - printf(BGREEN); - printf("block"); - printf(RESET); - print_case_body(ctx, node->payload.block.inside); - break; - } case CompoundInstruction_TAG: { - printf("{\n"); - indent(ctx->printer); - Nodes instructions = node->payload.compound_instruction.instructions; - for (size_t i = 0; i < instructions.count; i++) { - print_instruction(ctx, instructions.nodes[i]); - printf(";\n"); - } - printf("}\n"); - deindent(ctx->printer); - printf("yields "); - print_args_list(ctx, node->payload.compound_instruction.results); - break; } default: print_node_generated(ctx, node); } @@ -702,7 +683,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { TerminatorTag tag = is_terminator(node); switch (tag) { case NotATerminator: assert(false); - case Let_TAG: { + /*case Let_TAG: { const Node* instruction = get_let_instruction(node); const BindIdentifiers* binders = NULL; if (instruction->tag == BindIdentifiers_TAG) @@ -717,11 +698,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { else printf("val"); printf(RESET); - }/* else { - printf(GREEN); - printf("let "); - printf(RESET); - }*/ + } if (binders) { Strings names = binders->names; @@ -774,7 +751,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(";"); } break; - } + }*/ case If_TAG: { print_structured_construct_results(ctx, get_structured_construct_tail(node)); printf(GREEN); @@ -943,13 +920,6 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { print_args_list(ctx, node->payload.merge_selection.args); printf(";"); break; - case Terminator_BlockYield_TAG: - printf(BGREEN); - printf("%s", node_tags[node->tag]); - printf(RESET); - print_args_list(ctx, node->payload.block_yield.args); - printf(";"); - break; } } @@ -996,9 +966,9 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { printf(BYELLOW); printf(" %s", cnst->name); printf(RESET); - if (cnst->instruction) { + if (cnst->value) { printf(" = "); - print_node_impl(ctx, cnst->instruction); + print_node_impl(ctx, cnst->value); } printf(";\n"); break; diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 3ce114864..4f6a01410 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -21,8 +21,6 @@ Rewriter create_rewriter_base(Module* src, Module* dst) { .config = { .search_map = true, .write_map = true, - .rebind_let = false, - .fold_quote = true, }, .map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), }; @@ -266,7 +264,7 @@ Nodes recreate_params(Rewriter* rewriter, Nodes oparams) { return nodes(rewriter->dst_arena, oparams.count, nparams); } -Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { +Node* recreate_decl_header_identity_no_register(Rewriter* rewriter, const Node* old) { Node* new = NULL; switch (is_declaration(old)) { case GlobalVariable_TAG: { @@ -305,6 +303,11 @@ Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { case NotADeclaration: error("not a decl"); } assert(new); + return new; +} + +Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { + Node* new = recreate_decl_header_identity_no_register(rewriter, old); register_processed(rewriter, old, new); return new; } @@ -317,7 +320,7 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) break; } case Constant_TAG: { - new->payload.constant.instruction = rewrite_op_helper(rewriter, NcInstruction, "instruction", old->payload.constant.instruction); + new->payload.constant.value = rewrite_op_helper(rewriter, NcValue, "value", old->payload.constant.value); // TODO check type now ? break; } @@ -353,21 +356,11 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { recreate_decl_body_identity(rewriter, node, new); return new; } - case CompoundInstruction_TAG: { - return compound_instruction(arena, rewrite_ops_helper(rewriter, NcInstruction, "instructions", node->payload.compound_instruction.instructions), rewrite_ops_helper(rewriter, NcValue, "results", node->payload.compound_instruction.results)); - } case Param_TAG: log_string(ERROR, "Can't rewrite: "); log_node(ERROR, node); log_string(ERROR, ", params should be rewritten by the abstraction rewrite logic"); error_die(); - case Let_TAG: { - BodyBuilder* bb = begin_body(arena); - const Node* instruction = rewrite_op_helper(rewriter, NcInstruction, "instruction", node->payload.let.instruction); - //register_processed(rewriter, node->payload.let.instruction, instruction); - const Node* nlet = let(arena, instruction, rewrite_op_helper(rewriter, NcTerminator, "in", node->payload.let.in)); - return finish_body(bb, nlet); - } case BasicBlock_TAG: { Nodes params = recreate_params(rewriter, node->payload.basic_block.params); register_processed_list(rewriter, node->payload.basic_block.params, params); diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index e6b673cb4..6912aebc7 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -33,8 +33,6 @@ struct Rewriter_ { struct { bool search_map; bool write_map; - bool rebind_let; - bool fold_quote; bool process_params; } config; @@ -60,6 +58,7 @@ void rewrite_module(Rewriter*); const Node* recreate_node_identity(Rewriter*, const Node*); /// Rewrites a constant / function header +Node* recreate_decl_header_identity_no_register(Rewriter*, const Node*); Node* recreate_decl_header_identity(Rewriter*, const Node*); void recreate_decl_body_identity(Rewriter*, const Node*, Node*); diff --git a/src/shady/transform/internal_constants.c b/src/shady/transform/internal_constants.c index 811e3cd78..6823f30f4 100644 --- a/src/shady/transform/internal_constants.c +++ b/src/shady/transform/internal_constants.c @@ -9,7 +9,7 @@ void generate_dummy_constants(SHADY_UNUSED const CompilerConfig* config, Module* IrArena* arena = get_module_arena(mod); #define X(constant_name, T, placeholder) \ Node* constant_name##_var = constant(mod, singleton(annotation(arena, (Annotation) { .name = "RetainAfterSpecialization" })), T, #constant_name); \ - constant_name##_var->payload.constant.instruction = placeholder; + constant_name##_var->payload.constant.value = placeholder; INTERNAL_CONSTANTS(X) #undef X } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index f5b22cb91..5f7450c2c 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -56,11 +56,11 @@ const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { } const Node* gen_get_stack_base_addr(BodyBuilder* bb) { - return first(bind_instruction(bb, get_stack_base_addr(bb->arena))); + return first(bind_instruction(bb, get_stack_base_addr(bb->arena, (GetStackBaseAddr) { .mem = bb_mem(bb) }))); } const Node* gen_get_stack_size(BodyBuilder* bb) { - return first(bind_instruction(bb, get_stack_size(bb->arena))); + return first(bind_instruction(bb, get_stack_size(bb->arena, (GetStackSize) { bb_mem(bb) }))); } void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { diff --git a/src/shady/type.c b/src/shady/type.c index e55d754b0..aea5efb7e 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -486,6 +486,10 @@ const Type* check_type_undef(IrArena* arena, Undef payload) { }); } +const Type* check_type_mem_and_value(IrArena* arena, MemAndValue mav) { + return mav.value->type; +} + const Type* check_type_fn_addr(IrArena* arena, FnAddr fn_addr) { assert(fn_addr.fn->type->tag == FnType_TAG); assert(fn_addr.fn->tag == Function_TAG); @@ -1008,32 +1012,6 @@ const Type* check_type_control(IrArena* arena, Control control) { return noret_type(arena); } -const Type* check_type_block(IrArena* arena, Block payload) { - ensure_types_are_value_types(&payload.yield_types); - assert(get_abstraction_params(payload.inside).count == 0); - - /*const Node* lam = payload.inside; - const Node* yield_instr = NULL; - while (true) { - assert(lam->tag == Case_TAG); - const Node* terminator = lam->payload.case_.body; - switch (terminator->tag) { - case Let_TAG: { - lam = terminator->payload.let.tail; - continue; - } - case Yield_TAG: - yield_instr = terminator; - break; - default: assert(false); - } - break; - } - - Nodes yield_values = yield_instr->payload.yield.args;*/ - return wrap_multiple_yield_types(arena, payload.yield_types); -} - const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { return empty_multiple_return_type(arena); } @@ -1162,11 +1140,11 @@ const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { return empty_multiple_return_type(a); } -const Type* check_type_get_stack_size(IrArena* a) { +const Type* check_type_get_stack_size(IrArena* a, SHADY_UNUSED GetStackSize ss) { return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = uint32_type(a) }); } -const Type* check_type_get_stack_base_addr(IrArena* a) { +const Type* check_type_get_stack_base_addr(IrArena* a, SHADY_UNUSED GetStackBaseAddr gsba) { const Node* ptr = ptr_type(a, (PtrType) { .pointed_type = uint8_type(a), .address_space = AsPrivate}); return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = ptr }); } @@ -1175,16 +1153,6 @@ const Type* check_type_debug_printf(IrArena* a, DebugPrintf payload) { return empty_multiple_return_type(a); } -const Type* check_type_let(IrArena* arena, Let let) { - Nodes produced_types = unwrap_multiple_yield_types(arena, let.instruction->type); - // check_arguments_types_against_parameters_helper(param_types, produced_types); - return noret_type(arena); -} - -const Type* check_type_compound_instruction(IrArena* arena, CompoundInstruction payload) { - return wrap_multiple_yield_types(arena, get_values_types(arena, payload.results)); -} - const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { Nodes args = tail_call.args; for (size_t i = 0; i < args.count; i++) { @@ -1245,7 +1213,7 @@ const Type* check_type_join(IrArena* arena, Join join) { return noret_type(arena); } -const Type* check_type_unreachable(IrArena* arena) { +const Type* check_type_unreachable(IrArena* arena, SHADY_UNUSED Unreachable u) { return noret_type(arena); } @@ -1264,11 +1232,6 @@ const Type* check_type_merge_selection(IrArena* arena, SHADY_UNUSED MergeSelecti return noret_type(arena); } -const Type* check_type_block_yield(IrArena* arena, SHADY_UNUSED BlockYield payload) { - // TODO check it - return noret_type(arena); -} - const Type* check_type_fn_ret(IrArena* arena, Return ret) { // assert(ret.fn); // TODO check it then ! From 6d562f8919c7a75399ede2f30352b0cb5f2525b4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 7 Aug 2024 16:39:43 +0200 Subject: [PATCH 414/693] fixes --- include/shady/ir.h | 3 +++ src/frontend/slim/parser.c | 29 ++++++++++++++++----- src/frontend/spirv/s2s.c | 4 +-- src/shady/passes/bind.c | 12 +++------ src/shady/passes/eliminate_constants.c | 28 ++------------------ src/shady/passes/infer.c | 17 +++++++----- src/shady/passes/lower_alloca.c | 4 +-- src/shady/passes/lower_cf_instrs.c | 10 +++---- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 4 +-- src/shady/passes/lower_physical_ptrs.c | 6 ++--- src/shady/passes/lower_stack.c | 6 ++--- src/shady/passes/lower_subgroup_ops.c | 4 +-- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/lower_workgroups.c | 4 +-- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_inline.c | 6 ++--- src/shady/passes/opt_restructure.c | 10 +++---- src/shady/passes/reconvergence_heuristics.c | 12 ++++----- src/shady/passes/setup_stack_frames.c | 2 +- src/shady/rewrite.c | 4 +-- src/shady/transform/ir_gen_helpers.c | 18 ++++++------- src/shady/visit.h | 2 +- 23 files changed, 91 insertions(+), 100 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index d77dbcb1d..1ee77d507 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -294,6 +294,9 @@ const Node* bb_mem(BodyBuilder*); Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count); const Node* finish_body(BodyBuilder*, const Node* terminator); +const Node* finish_body_with_return(BodyBuilder*, Nodes args); +const Node* finish_body_with_unreachable(BodyBuilder*); + void cancel_body(BodyBuilder*); const Node* yield_value_and_wrap_in_block(BodyBuilder*, const Node*); diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index a40042719..9a2ab4652 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -80,7 +80,7 @@ static const char* accept_identifier(ctxparams) { return NULL; } -static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator); +static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator(const Node*)); static const Node* accept_value(ctxparams, BodyBuilder*); static const Type* accept_unqualified_type(ctxparams); static const Node* accept_expr(ctxparams, BodyBuilder*, int); @@ -595,6 +595,16 @@ static Nodes expect_operands(ctxparams, BodyBuilder* bb) { return final; } +static const Node* make_selection_merge(const Node* mem) { + IrArena* a = mem->arena; + return merge_selection(a, (MergeSelection) { .args = nodes(a, 0, NULL), .mem = mem }); +} + +static const Node* make_loop_continue(const Node* mem) { + IrArena* a = mem->arena; + return merge_continue(a, (MergeContinue) { .args = nodes(a, 0, NULL), .mem = mem }); +} + static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { Token current_token = curr_token(tokenizer); switch (current_token.tag) { @@ -605,7 +615,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { const Node* condition = accept_operand(ctx, bb); expect(condition); expect(accept_token(ctx, rpar_tok)); - const Node* merge = config.front_end ? merge_selection(arena, (MergeSelection) { .args = nodes(arena, 0, NULL) }) : NULL; + const Node* (*merge)(const Node*) = config.front_end ? make_selection_merge : NULL; Node* true_case = case_(arena, nodes(arena, 0, NULL)); set_abstraction_body(true_case, expect_body(ctx, get_abstraction_mem(true_case), merge)); @@ -626,7 +636,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { Nodes initial_arguments; expect_parameters(ctx, ¶meters, &initial_arguments, bb); // by default loops continue forever - const Node* default_loop_end_behaviour = config.front_end ? merge_continue(arena, (MergeContinue) { .args = nodes(arena, 0, NULL) }) : NULL; + const Node* (*default_loop_end_behaviour)(const Node*) = config.front_end ? make_loop_continue : NULL; Node* loop_case = case_(arena, parameters); set_abstraction_body(loop_case, expect_body(ctx, get_abstraction_mem(loop_case), default_loop_end_behaviour)); return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, loop_case)); @@ -853,7 +863,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { return NULL; } -static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator) { +static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator(const Node*)) { expect(accept_token(ctx, lbracket_tok)); BodyBuilder* bb = begin_body_with_mem(arena, mem); @@ -869,7 +879,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t if (!terminator) { if (default_terminator) - terminator = default_terminator; + terminator = default_terminator(bb_mem(bb)); else error("expected terminator: return, jump, branch ..."); } @@ -884,7 +894,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t Nodes parameters; expect_parameters(ctx, ¶meters, NULL, bb); Node* continuation = basic_block(arena, parameters, name); - continuation->payload.basic_block.body = expect_body(ctx, get_abstraction_mem(continuation), NULL); + set_abstraction_body(continuation, expect_body(ctx, get_abstraction_mem(continuation), NULL)); append_list(Node*, conts, continuation); } @@ -976,6 +986,11 @@ static const Node* accept_const(ctxparams, Nodes annotations) { return cnst; } +static const Node* make_return_void(const Node* mem) { + IrArena* a = mem->arena; + return fn_ret(a, (Return) { .args = empty(a), .mem = mem }); +} + static const Node* accept_fn_decl(ctxparams, Nodes annotations) { if (!accept_token(ctx, fn_tok)) return NULL; @@ -989,7 +1004,7 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { Node* fn = function(mod, parameters, name, annotations, types); if (!accept_token(ctx, semi_tok)) - fn->payload.fun.body = expect_body(ctx, get_abstraction_mem(fn), types.count == 0 ? fn_ret(arena, (Return) { .args = types }) : NULL); + set_abstraction_body(fn, expect_body(ctx, get_abstraction_mem(fn), types.count == 0 ? make_return_void : NULL)); const Node* declaration = fn; expect(declaration); diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index fb2999f6b..47efc6055 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -846,7 +846,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { // steal the body of the first block, it can't be jumped to anyways! if (first_block) - fun->payload.fun.body = first_block->payload.basic_block.body; + set_abstraction_body(fun, first_block->payload.basic_block.body); parser->fun = old_fun; break; } @@ -908,7 +908,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { instruction_offset += s; } assert(parser->current_block.finished); - block->payload.basic_block.body = parser->current_block.finished; + set_abstraction_body(block, parser->current_block.finished); parser->current_block = old; break; } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 69044c4ea..4ef373e7b 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -173,7 +173,7 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { register_processed_list(&ctx->rewriter, decl->payload.fun.params, new_fn_params); fn_ctx.current_function = bound; - bound->payload.fun.body = rewrite_node(&fn_ctx.rewriter, decl->payload.fun.body); + set_abstraction_body(bound, rewrite_node(&fn_ctx.rewriter, decl->payload.fun.body)); return bound; } case NominalType_TAG: { @@ -247,7 +247,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { for (size_t j = 0; j < new_bb_params.count; j++) add_binding(&bb_ctx, false, new_bb->payload.basic_block.params.nodes[j]->payload.param.name, new_bb_params.nodes[j]); - new_bb->payload.basic_block.body = rewrite_node(&bb_ctx.rewriter, old_bb->payload.basic_block.body); + set_abstraction_body(new_bb, rewrite_node(&bb_ctx.rewriter, old_bb->payload.basic_block.body)); debugv_print("Bound basic block %s\n", new_bb->payload.basic_block.name); } @@ -269,16 +269,10 @@ static const Node* bind_node(Context* ctx, const Node* node) { } register_processed(&ctx->rewriter, node, new_bb); register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new_params); - new_bb->payload.basic_block.body = rewrite_node(&ctx->rewriter, node->payload.basic_block.body); + set_abstraction_body(new_bb, rewrite_node(&ctx->rewriter, node->payload.basic_block.body)); return new_bb; } case BindIdentifiers_TAG: return desugar_bind_identifiers(ctx, node); - case Return_TAG: { - assert(ctx->current_function); - return fn_ret(a, (Return) { - .args = rewrite_nodes(&ctx->rewriter, node->payload.fn_ret.args) - }); - } default: { if (node->tag == PrimOp_TAG && node->payload.prim_op.op == assign_op) { const Node* target_ptr = get_node_address(ctx, node->payload.prim_op.operands.nodes[0]); diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 8ab4cad1c..b8fbfa4b4 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -6,7 +6,6 @@ typedef struct { Rewriter rewriter; - BodyBuilder* bb; bool all; } Context; @@ -16,13 +15,6 @@ static const Node* process(Context* ctx, const Node* node) { if (found) return found; IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* abs_bb = NULL; - Context c = *ctx; - ctx = &c; - if (is_abstraction(node)) { - c.bb = abs_bb = begin_block_pure(a); - } - switch (node->tag) { case Constant_TAG: if (!node->payload.constant.value) @@ -33,30 +25,14 @@ static const Node* process(Context* ctx, const Node* node) { case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; if (decl->tag == Constant_TAG && decl->payload.constant.value) { - const Node* value = resolve_node_to_definition(decl->payload.constant.value, (NodeResolveConfig) { 0 }); - if (value) - return rewrite_node(&ctx->rewriter, value); - c.rewriter.map = clone_dict(c.rewriter.map); - assert(ctx->bb); - // TODO: actually _copy_ the instruction so we can duplicate the code safely! - const Node* rewritten = first(bind_instruction(ctx->bb, rewrite_node(&ctx->rewriter, decl->payload.constant.value))); - destroy_dict(c.rewriter.map); - return rewritten; + return rewrite_node(&ctx->rewriter, decl->payload.constant.value); } break; } default: break; } - Node* new = (Node*) recreate_node_identity(&ctx->rewriter, node); - if (abs_bb) { - assert(is_abstraction(new)); - if (get_abstraction_body(new)) - set_abstraction_body(new, finish_body(abs_bb, get_abstraction_body(new))); - else - cancel_body(abs_bb); - } - return new; + return recreate_node_identity(&ctx->rewriter, node); } static Module* eliminate_constants_(SHADY_UNUSED const CompilerConfig* config, Module* src, bool all) { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index ceb6747fc..eae8a808a 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -113,7 +113,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { Node* fun = function(ctx->rewriter.dst_module, nodes(a, node->payload.fun.params.count, nparams), string(a, node->payload.fun.name), infer_nodes(ctx, node->payload.fun.annotations), nret_types); register_processed(&ctx->rewriter, node, fun); body_context.current_fn = fun; - fun->payload.fun.body = infer(&body_context, node->payload.fun.body, NULL); + set_abstraction_body(fun, infer(&body_context, node->payload.fun.body, NULL)); return fun; } case Constant_TAG: { @@ -338,7 +338,7 @@ static const Node* _infer_basic_block(Context* ctx, const Node* node) { assert(bb); register_processed(&ctx->rewriter, node, bb); - bb->payload.basic_block.body = infer(&body_context, node->payload.basic_block.body, NULL); + set_abstraction_body(bb, infer(&body_context, node->payload.basic_block.body, NULL)); return bb; } @@ -602,12 +602,13 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { const Node* imported_fn = ctx->current_fn; Nodes return_types = imported_fn->payload.fun.return_types; - const Nodes* old_values = &node->payload.fn_ret.args; - LARRAY(const Node*, nvalues, old_values->count); - for (size_t i = 0; i < old_values->count; i++) - nvalues[i] = infer(ctx, old_values->nodes[i], return_types.nodes[i]); + Return payload = node->payload.fn_ret; + LARRAY(const Node*, nvalues, payload.args.count); + for (size_t i = 0; i < payload.args.count; i++) + nvalues[i] = infer(ctx, payload.args.nodes[i], return_types.nodes[i]); return fn_ret(a, (Return) { - .args = nodes(a, old_values->count, nvalues), + .args = nodes(a, payload.args.count, nvalues), + .mem = infer(ctx, payload.mem, NULL), }); } case Jump_TAG: { @@ -717,6 +718,8 @@ static const Node* process(Context* src_ctx, const Node* node) { return infer_annotation(&ctx, node); } else if (is_basic_block(node)) { return _infer_basic_block(&ctx, node); + }else if (is_mem(node)) { + return recreate_node_identity(&ctx.rewriter, node); } assert(false); } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 40a5514b0..06f9594a1 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -86,7 +86,7 @@ static const Node* process(Context* ctx, const Node* node) { Context ctx2 = *ctx; ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; if (ctx2.disable_lowering) { - fun->payload.fun.body = rewrite_node(&ctx2.rewriter, node->payload.fun.body); + set_abstraction_body(fun, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); return fun; } @@ -123,7 +123,7 @@ static const Node* process(Context* ctx, const Node* node) { // make sure to use the new mem from then on register_processed(r, get_abstraction_mem(node), bb_mem(bb)); - fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(node))); + set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); destroy_dict(ctx2.prepared_offsets); return fun; diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 12fb8f471..d241d66d1 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -47,7 +47,7 @@ static const Node* process_node(Context* ctx, const Node* node) { sub_ctx.current_fn = fun; sub_ctx.cfg = build_fn_cfg(node); sub_ctx.abs = node; - fun->payload.fun.body = rewrite_node(&sub_ctx.rewriter, node->payload.fun.body); + set_abstraction_body(fun, rewrite_node(&sub_ctx.rewriter, node->payload.fun.body)); destroy_cfg(sub_ctx.cfg); return fun; } else if (node->tag == Constant_TAG) { @@ -85,15 +85,15 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* true_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_true")); join_context.abs = node->payload.if_instr.if_true; - true_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, get_abstraction_body(node->payload.if_instr.if_true)); + set_abstraction_body(true_block, rewrite_node(&join_context.rewriter, get_abstraction_body(node->payload.if_instr.if_true))); Node* flse_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_false")); if (has_false_branch) { join_context.abs = node->payload.if_instr.if_false; - flse_block->payload.basic_block.body = rewrite_node(&join_context.rewriter, get_abstraction_body(node->payload.if_instr.if_false)); + set_abstraction_body(flse_block, rewrite_node(&join_context.rewriter, get_abstraction_body(node->payload.if_instr.if_false))); } else { assert(yield_types.count == 0); - flse_block->payload.basic_block.body = join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL) }); + set_abstraction_body(flse_block, join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL) })); } BodyBuilder* bb = begin_body_with_mem(a, nmem); @@ -150,7 +150,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes args = gen_control(inner_bb, param_types, inner_control_case); // TODO let_in_block or use a Jump ! - loop_body->payload.basic_block.body = finish_body(inner_bb, jump(a, (Jump) { .target = loop_body, .args = args })); + set_abstraction_body(loop_body, finish_body(inner_bb, jump(a, (Jump) { .target = loop_body, .args = args }))); const Node* initial_jump = jump(a, (Jump) { .target = loop_body, diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index f896cfc83..56d2fff87 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -84,7 +84,7 @@ static const Node* process(Context* ctx, const Node* node) { if (lookup_annotation(node, "EntryPoint") && node->payload.fun.params.count > 0) { Node* new_entry_point = rewrite_entry_point_fun(ctx, node); const Node* arg_struct = generate_arg_struct(&ctx->rewriter, node, new_entry_point); - new_entry_point->payload.fun.body = rewrite_body(ctx, node, new_entry_point, arg_struct); + set_abstraction_body(new_entry_point, rewrite_body(ctx, node, new_entry_point, arg_struct)); return new_entry_point; } break; diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index eafe77a17..700b1e78f 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -125,7 +125,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo Node* default_case = case_(a, empty(a)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), default_case)); - new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value), .mem = bb_mem(bb) })); + set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value), .mem = bb_mem(bb) }))); break; } case StoreFn: { @@ -155,7 +155,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo Node* default_case = case_(a, empty(a)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(new_fn) })); gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), default_case); - new_fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) })); + set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) }))); break; } } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 1839e915e..a7d71f6aa 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -281,11 +281,11 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { gen_serialisation(ctx, bb, element_type, base, address, value_param); - fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); + set_abstraction_body(fun, finish_body(bb, fn_ret(a, (Return) { .args = empty(a) }))); } else { const Node* loaded_value = gen_deserialisation(ctx, bb, element_type, base, address); assert(loaded_value); - fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value) })); + set_abstraction_body(fun, finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value) }))); } return fun; } @@ -357,7 +357,7 @@ static const Node* process_node(Context* ctx, const Node* old) { store_init_data(ctx, as, ctx->collected[as], bb); } register_processed(&ctx->rewriter, get_abstraction_mem(old), bb_mem(bb)); - new->payload.fun.body = finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body)); + set_abstraction_body(new, finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } break; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 4465dfa23..f04764684 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -81,10 +81,10 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { } if (push) { - fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); + set_abstraction_body(fun, finish_body(bb, fn_ret(a, (Return) { .args = empty(a) }))); } else { assert(popped_value); - fun->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = singleton(popped_value) })); + set_abstraction_body(fun, finish_body(bb, fn_ret(a, (Return) { .args = singleton(popped_value) }))); } return fun; } @@ -108,7 +108,7 @@ static const Node* process_node(Context* ctx, const Node* old) { gen_store(bb, stack_pointer, uint32_literal(a, 0)); } register_processed(r, get_abstraction_mem(old), bb_mem(bb)); - new->payload.fun.body = finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body)); + set_abstraction_body(new, finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 0cb46dad3..7f9488a48 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -85,10 +85,10 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fn)); const Node* result = generate(ctx, bb, t, param); if (result) { - fn->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { + set_abstraction_body(fn, finish_body(bb, fn_ret(a, (Return) { .args = singleton(result), .mem = bb_mem(bb), - })); + }))); return; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 8ed607b3c..a987dc831 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -414,7 +414,7 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) struct Dict* ptrs = new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); Node* init_fn = function(dst, nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" }), annotation(a, (Annotation) { .name = "Structured" })), nodes(a, 0, NULL)); - init_fn->payload.fun.body = fn_ret(a, (Return) { .args = empty(a) }); + set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = empty(a), .mem = get_abstraction_mem(init_fn) })); FnPtr next_fn_ptr = 1; diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 0a341daf2..689454a86 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -61,7 +61,7 @@ static const Node* process(Context* ctx, const Node* node) { Nodes nparams = recreate_params(&ctx->rewriter, node->payload.fun.params); Node* inner = function(m, nparams, format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, empty(a)); register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); - inner->payload.fun.body = recreate_node_identity(&ctx->rewriter, node->payload.fun.body); + set_abstraction_body(inner, recreate_node_identity(&ctx->rewriter, node->payload.fun.body)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(wrapper)); const Node* num_workgroups_var = rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); @@ -139,7 +139,7 @@ static const Node* process(Context* ctx, const Node* node) { } bind_instruction(bb, instr); - wrapper->payload.fun.body = finish_body(bb, fn_ret(a, (Return) { .args = empty(a) })); + set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = empty(a) }))); return wrapper; } return recreate_node_identity(&ctx2.rewriter, node); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 2f890c34e..9ca7b1952 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -191,7 +191,7 @@ static const Node* process(Context* ctx, const Node* old) { fun_ctx.uses = create_uses_map(old, (NcDeclaration | NcType)); fun_ctx.disable_lowering = lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); if (old->payload.fun.body) - fun->payload.fun.body = rewrite_node(&fun_ctx.rewriter, old->payload.fun.body); + set_abstraction_body(fun, rewrite_node(&fun_ctx.rewriter, old->payload.fun.body)); destroy_uses_map(fun_ctx.uses); return fun; } diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 0018907fa..010f6ea8f 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -193,14 +193,14 @@ static const Node* process(Context* ctx, const Node* node) { } break; } - case BasicBlock_TAG: { + /*case BasicBlock_TAG: { Nodes nparams = recreate_params(r, get_abstraction_params(node)); register_processed_list(r, get_abstraction_params(node), nparams); Node* bb = basic_block(a, nparams, get_abstraction_name(node)); register_processed(r, node, bb); - bb->payload.basic_block.body = rewrite_node(r, get_abstraction_body(node)); + set_abstraction_body(bb, rewrite_node(r, get_abstraction_body(node))); return bb; - } + }*/ case Return_TAG: { if (ctx->inlined_call) return join(a, (Join) { .join_point = ctx->inlined_call->return_jp, .args = rewrite_nodes(r, node->payload.fn_ret.args )}); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index f67d84208..8dfb290f3 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -157,12 +157,12 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* exit) set_abstraction_body(loop_case, structured); gen_loop(bb, empty(a), rewrite_nodes(&ctx->rewriter, oargs), loop_case); // we decide 'late' what the exit ladder should be - inner_exit_ladder_bb->payload.basic_block.body = merge_break(a, (MergeBreak) { .args = empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) }); + set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) })); return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); } else { Node* bb2 = basic_block(a, nodes(a, oargs.count, nparams), NULL); - bb2->payload.basic_block.body = structured; - inner_exit_ladder_bb->payload.basic_block.body = jump_helper(a, exit, empty(a), get_abstraction_mem(inner_exit_ladder_bb)); + set_abstraction_body(bb2, structured); + set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, exit, empty(a), get_abstraction_mem(inner_exit_ladder_bb))); return finish_body(bb, jump_helper(a, bb2, rewrite_nodes(&ctx->rewriter, oargs), bb_mem(bb))); } } @@ -339,7 +339,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.lower = false; ctx2.rewriter.map = ctx->rewriter.map; if (node->payload.fun.body) - new->payload.fun.body = rewrite_node(&ctx2.rewriter, node->payload.fun.body); + set_abstraction_body(new, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); // builtin functions are always considered leaf functions is_leaf = is_builtin || !node->payload.fun.body; } else { @@ -357,7 +357,7 @@ static const Node* process(Context* ctx, const Node* node) { append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; register_processed(r, get_abstraction_mem(node), bb_mem(bb)); - new->payload.fun.body = finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a) )); + set_abstraction_body(new, finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. pop_list_impl(ctx->cleanup_stack); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 049aa37e9..2780ca6bd 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -173,7 +173,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { switch (exiting_node->node->tag) { case BasicBlock_TAG: { Node* pre_join_exit_bb = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); - pre_join_exit_bb->payload.basic_block.body = jump_helper(arena, exit_helpers[i], empty(arena), get_abstraction_mem(pre_join_exit_bb)); + set_abstraction_body(pre_join_exit_bb, jump_helper(arena, exit_helpers[i], empty(arena), get_abstraction_mem(pre_join_exit_bb))); exit_wrappers[i] = pre_join_exit_bb; break; } @@ -245,7 +245,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .args = empty(arena) })); - exit_helpers[i]->payload.basic_block.body = exit_wrapper_body; + set_abstraction_body(exit_helpers[i], exit_wrapper_body); } destroy_dict(rewriter->map); @@ -301,10 +301,10 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { exit_numbers[i] = int32_literal(arena, i); if (recreated_exit->tag == BasicBlock_TAG) { - exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, jump(arena, (Jump) { + set_abstraction_body(exit_bb, finish_body(exit_recover_bb, jump(arena, (Jump) { .target = recreated_exit, .args = nodes(arena, exit_param_allocas[i].count, recovered_args), - })); + }))); } else { // TODO: rewrite assert(get_abstraction_params(recreated_exit).count == 0); @@ -465,10 +465,10 @@ static const Node* process_node(Context* ctx, const Node* node) { }), true), "jp_postdom"); Node* pre_join = basic_block(a, exit_args, format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); - pre_join->payload.basic_block.body = join(a, (Join) { + set_abstraction_body(pre_join, join(a, (Join) { .join_point = join_token, .args = exit_args - }); + })); const Node* cached = search_processed(r, idom); if (cached) diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 0d5b62a04..857302873 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -39,7 +39,7 @@ static const Node* process(Context* ctx, const Node* node) { } register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); if (node->payload.fun.body) - fun->payload.fun.body = finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); + set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body))); else cancel_body(bb); return fun; diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 4f6a01410..19ba04e53 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -326,7 +326,7 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) } case Function_TAG: { assert(new->payload.fun.body == NULL); - new->payload.fun.body = rewrite_op_helper(rewriter, NcTerminator, "body", old->payload.fun.body); + set_abstraction_body(new, rewrite_op_helper(rewriter, NcTerminator, "body", old->payload.fun.body)); break; } case NominalType_TAG: { @@ -367,7 +367,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { Node* bb = basic_block(arena, params, node->payload.basic_block.name); register_processed(rewriter, node, bb); const Node* nterminator = rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.basic_block.body); - bb->payload.basic_block.body = nterminator; + set_abstraction_body(bb, nterminator); return bb; } } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 5f7450c2c..42b3911ee 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -40,7 +40,7 @@ const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { } void gen_push_value_stack(BodyBuilder* bb, const Node* value) { - bind_instruction(bb, push_stack(bb->arena, (PushStack) { value })); + bind_instruction(bb, push_stack(bb->arena, (PushStack) { .value = value, .mem = bb_mem(bb) })); } void gen_push_values_stack(BodyBuilder* bb, Nodes values) { @@ -51,7 +51,7 @@ void gen_push_values_stack(BodyBuilder* bb, Nodes values) { } const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { - const Node* instruction = pop_stack(bb->arena, (PopStack) { .type = type }); + const Node* instruction = pop_stack(bb->arena, (PopStack) { .type = type, .mem = bb_mem(bb) }); return first(bind_instruction(bb, instruction)); } @@ -64,7 +64,7 @@ const Node* gen_get_stack_size(BodyBuilder* bb) { } void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { - bind_instruction(bb, set_stack_size(bb->arena, (SetStackSize) { new_size })); + bind_instruction(bb, set_stack_size(bb->arena, (SetStackSize) { .value = new_size, .mem = bb_mem(bb) })); } const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { @@ -95,11 +95,11 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { } const Node* gen_stack_alloc(BodyBuilder* bb, const Type* type) { - return first(bind_instruction(bb, stack_alloc(bb->arena, (StackAlloc) { type }))); + return first(bind_instruction(bb, stack_alloc(bb->arena, (StackAlloc) { .type = type, .mem = bb_mem(bb) }))); } const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { - return first(bind_instruction(bb, local_alloc(bb->arena, (LocalAlloc) { type }))); + return first(bind_instruction(bb, local_alloc(bb->arena, (LocalAlloc) { .type = type, .mem = bb_mem(bb) }))); } const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Node* index) { @@ -107,11 +107,11 @@ const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Nod } const Node* gen_load(BodyBuilder* bb, const Node* ptr) { - return first(bind_instruction(bb, load(bb->arena, (Load) { ptr }))); + return first(bind_instruction(bb, load(bb->arena, (Load) { .ptr = ptr, .mem = bb_mem(bb) }))); } void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { - bind_instruction(bb, store(bb->arena, (Store) {ptr, value })); + bind_instruction(bb, store(bb->arena, (Store) { .ptr = ptr, .value = value, .mem = bb_mem(bb) })); } const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { @@ -127,11 +127,11 @@ const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { } void gen_comment(BodyBuilder* bb, String str) { - bind_instruction(bb, comment(bb->arena, (Comment) { .string = str })); + bind_instruction(bb, comment(bb->arena, (Comment) { .string = str, .mem = bb_mem(bb) })); } void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { - bind_instruction(bb, debug_printf(bb->arena, (DebugPrintf) { pattern, args })); + bind_instruction(bb, debug_printf(bb->arena, (DebugPrintf) { pattern, args, .mem = bb_mem(bb) })); } const Node* get_builtin(Module* m, Builtin b) { diff --git a/src/shady/visit.h b/src/shady/visit.h index 0d943d4bf..504de99ce 100644 --- a/src/shady/visit.h +++ b/src/shady/visit.h @@ -24,6 +24,6 @@ void visit_ops(Visitor* visitor, NodeClass, String, Nodes nodes); // visits the abstractions in the function, _except_ for the entry block (ie the function itself) void visit_function_rpo(Visitor* visitor, const Node* function); // use this in visit_node_operands to avoid visiting nodes in non-rpo order -#define IGNORE_ABSTRACTIONS_MASK NcBasic_block | NcDeclaration +#define IGNORE_ABSTRACTIONS_MASK NcBasic_block | NcDeclaration | NcAbstraction #endif From c9ca087b896c10e3dd09d2db72efe1983c952984 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 7 Aug 2024 16:54:59 +0200 Subject: [PATCH 415/693] empty.slim compiles --- include/shady/ir.h | 3 ++ src/shady/CMakeLists.txt | 1 + src/shady/node.c | 18 +++----- src/shady/node_helpers.c | 68 ++++++++++++++++++++++++++++ src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_tailcalls.c | 1 - src/shady/passes/opt_restructure.c | 3 +- src/shady/rewrite.c | 7 +-- src/shady/rewrite.h | 1 - src/shady/transform/ir_gen_helpers.c | 2 +- 10 files changed, 84 insertions(+), 22 deletions(-) create mode 100644 src/shady/node_helpers.c diff --git a/include/shady/ir.h b/include/shady/ir.h index 1ee77d507..3413af85b 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -191,6 +191,9 @@ const Node* extract_multiple_ret_types_helper(const Node* composite, int index); const Node* maybe_tuple_helper(IrArena* a, Nodes values); +const Node* get_parent_mem(const Node* mem); +const Node* get_original_mem(const Node* mem); + typedef struct { bool enter_loads; bool allow_incompatible_types; diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index be7afabc6..25e97b4d1 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -24,6 +24,7 @@ target_link_libraries(api INTERFACE "$") set(SHADY_SOURCES ir.c node.c + node_helpers.c constructors.c type.c type_helpers.c diff --git a/src/shady/node.c b/src/shady/node.c index a01ed0038..7628ad821 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -299,11 +299,6 @@ String get_abstraction_name_safe(const Node* abs) { return format_string_interned(abs->arena, "%%%d", abs->id); } -const Node* get_original_mem(const Node* mem) { - error("TODO"); - return mem; -} - void set_abstraction_body(Node* abs, const Node* body) { assert(is_abstraction(abs)); assert(!body || is_terminator(body)); @@ -313,16 +308,17 @@ void set_abstraction_body(Node* abs, const Node* body) { case BasicBlock_TAG: { while (true) { const Node* mem0 = get_original_mem(get_terminator_mem(body)); - assert(is_abstraction(mem0)); - if (is_basic_block(mem0)) { - BodyBuilder* insert = mem0->payload.basic_block.insert; + assert(mem0->tag == AbsMem_TAG); + const Node* mem_abs = mem0->payload.abs_mem.abs; + if (is_basic_block(mem_abs)) { + BodyBuilder* insert = mem_abs->payload.basic_block.insert; if (insert) { const Node* mem = insert->mem0; - set_abstraction_body((Node*) mem0, finish_body(insert, body)); - body = jump_helper(a, mem0, empty(a), mem); + set_abstraction_body((Node*) mem_abs, finish_body(insert, body)); + body = jump_helper(a, mem_abs, empty(a), mem); continue; } - assert(mem0 == abs); + assert(mem_abs == abs); } break; } diff --git a/src/shady/node_helpers.c b/src/shady/node_helpers.c new file mode 100644 index 000000000..385ab2a1a --- /dev/null +++ b/src/shady/node_helpers.c @@ -0,0 +1,68 @@ +#include "shady/ir.h" + +#include + +#pragma GCC diagnostic error "-Wswitch" + +const Node* get_parent_mem(const Node* mem) { + assert(is_mem(mem)); + switch (is_mem(mem)) { + case NotAMem: return NULL; + case Mem_AbsMem_TAG: + return mem; + case Mem_Call_TAG: + mem = mem->payload.call.mem; + return mem; + case Mem_MemAndValue_TAG: + mem = mem->payload.mem_and_value.mem; + return mem; + case Mem_Comment_TAG: + mem = mem->payload.comment.mem; + return mem; + case Mem_BindIdentifiers_TAG: + mem = mem->payload.bind_identifiers.mem; + return mem; + case Mem_StackAlloc_TAG: + mem = mem->payload.stack_alloc.mem; + return mem; + case Mem_LocalAlloc_TAG: + mem = mem->payload.local_alloc.mem; + return mem; + case Mem_Load_TAG: + mem = mem->payload.load.mem; + return mem; + case Mem_Store_TAG: + mem = mem->payload.store.mem; + return mem; + case Mem_CopyBytes_TAG: + mem = mem->payload.copy_bytes.mem; + return mem; + case Mem_FillBytes_TAG: + mem = mem->payload.fill_bytes.mem; + return mem; + case Mem_PushStack_TAG: + mem = mem->payload.push_stack.mem; + return mem; + case Mem_PopStack_TAG: + mem = mem->payload.pop_stack.mem; + return mem; + case Mem_GetStackSize_TAG: + mem = mem->payload.get_stack_size.mem; + return mem; + case Mem_SetStackSize_TAG: + mem = mem->payload.set_stack_size.mem; + return mem; + case Mem_DebugPrintf_TAG: + mem = mem->payload.debug_printf.mem; + return mem; + } +} + +const Node* get_original_mem(const Node* mem) { + while (true) { + const Node* nmem = get_parent_mem(mem); + if (nmem != mem) + return mem; + return nmem; + } +} diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 06f9594a1..12e9a0ad0 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -79,7 +79,7 @@ static const Node* process(Context* ctx, const Node* node) { Module* m = r->dst_module; switch (node->tag) { case Function_TAG: { - Node* fun = recreate_decl_header_identity_no_register(&ctx->rewriter, node); + Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); if (!node->payload.fun.body) return fun; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index a987dc831..c73ffe92c 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -114,7 +114,6 @@ static const Node* process(Context* ctx, const Node* old) { Node* fun = recreate_decl_header_identity(&ctx2.rewriter, old); if (old->payload.fun.body) { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); - const Node* nbody = rewrite_node(&ctx2.rewriter, old->payload.fun.body); if (entry_point_annotation) { gen_call(bb, fn_addr_helper(a, ctx2.init_fn), empty(a)); } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 8dfb290f3..9b93478f2 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -399,8 +399,9 @@ static const Node* process(Context* ctx, const Node* node) { assert(false); // actually that should not come up. longjmp(ctx->bail, 1); } - default: return recreate_node_identity(&ctx->rewriter, node); + default: break; } + return recreate_node_identity(&ctx->rewriter, node); } Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src) { diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 19ba04e53..c7d995c69 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -264,7 +264,7 @@ Nodes recreate_params(Rewriter* rewriter, Nodes oparams) { return nodes(rewriter->dst_arena, oparams.count, nparams); } -Node* recreate_decl_header_identity_no_register(Rewriter* rewriter, const Node* old) { +Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { Node* new = NULL; switch (is_declaration(old)) { case GlobalVariable_TAG: { @@ -303,11 +303,6 @@ Node* recreate_decl_header_identity_no_register(Rewriter* rewriter, const Node* case NotADeclaration: error("not a decl"); } assert(new); - return new; -} - -Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { - Node* new = recreate_decl_header_identity_no_register(rewriter, old); register_processed(rewriter, old, new); return new; } diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index 6912aebc7..42c511e5a 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -58,7 +58,6 @@ void rewrite_module(Rewriter*); const Node* recreate_node_identity(Rewriter*, const Node*); /// Rewrites a constant / function header -Node* recreate_decl_header_identity_no_register(Rewriter*, const Node*); Node* recreate_decl_header_identity(Rewriter*, const Node*); void recreate_decl_body_identity(Rewriter*, const Node*, Node*); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 42b3911ee..5fbc249d9 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -14,7 +14,7 @@ Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { assert(bb->arena->config.check_types); - const Node* instruction = call(bb->arena, (Call) { .callee = callee, .args = args }); + const Node* instruction = call(bb->arena, (Call) { .callee = callee, .args = args, .mem = bb_mem(bb) }); return bind_instruction(bb, instruction); } From 1c3a71903feb317d5e98087d8c93432701fce737 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 00:10:18 +0200 Subject: [PATCH 416/693] ported l2s to mem --- src/frontend/llvm/l2s.c | 8 +-- src/frontend/llvm/l2s_instr.c | 31 ++++++----- src/frontend/llvm/l2s_postprocess.c | 80 +++++++++++++++-------------- src/frontend/llvm/l2s_value.c | 4 +- 4 files changed, 64 insertions(+), 59 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index a8138341c..5c9ca85d5 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -45,7 +45,7 @@ int vcc_get_linked_major_llvm_version() { #endif static const Node* write_bb_tail(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef bb, LLVMValueRef first_instr) { - BodyBuilder* b = begin_body(fn_or_bb->arena); + BodyBuilder* b = begin_body_with_mem(fn_or_bb->arena, get_abstraction_mem(fn_or_bb)); LLVMValueRef instr; for (instr = first_instr; instr; instr = LLVMGetNextInstruction(instr)) { bool last = instr == LLVMGetLastInstruction(bb); @@ -225,14 +225,14 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { if (UNTYPED_POINTERS) { Node* untyped_wrapper = constant(p->dst, singleton(annotation(a, (Annotation) { .name = "Inline" })), ptr_t, format_string_interned(a, "%s_untyped", name)); - untyped_wrapper->payload.constant.instruction = ref_decl_helper(a, decl); - untyped_wrapper->payload.constant.instruction = prim_op_helper(a, reinterpret_op, singleton(ptr_t), singleton(ref_decl_helper(a, decl))); + untyped_wrapper->payload.constant.value = ref_decl_helper(a, decl); + untyped_wrapper->payload.constant.value = prim_op_helper(a, reinterpret_op, singleton(ptr_t), singleton(ref_decl_helper(a, decl))); decl = untyped_wrapper; } } else { const Type* type = convert_type(p, LLVMTypeOf(global)); decl = constant(p->dst, empty(a), type, name); - decl->payload.constant.instruction = convert_value(p, global); + decl->payload.constant.value = convert_value(p, global); } assert(decl && is_declaration(decl)); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index ee623a3de..33b7fd178 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -56,7 +56,7 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { return v; } -static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef dst) { +static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef dst, const Node* mem) { IrArena* a = fn_or_bb->arena; Node* wrapper_bb = basic_block(a, empty(a), NULL); JumpTodo todo = { @@ -67,7 +67,7 @@ static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_ append_list(JumpTodo, fn_ctx->jumps_todo, todo); const Node* dst2 = convert_basic_block(p, fn_ctx, dst); insert_dict(Node*, const Node*, p->wrappers_map, wrapper_bb, dst2); - return jump_helper(a, wrapper_bb, empty(a)); + return jump_helper(a, wrapper_bb, empty(a), mem); } void convert_jump_finish(Parser* p, FnParseCtx* fn_ctx, JumpTodo todo) { @@ -88,7 +88,7 @@ void convert_jump_finish(Parser* p, FnParseCtx* fn_ctx, JumpTodo todo) { assert(false && "failed to find the appropriate source"); next: continue; } - todo.wrapper->payload.basic_block.body = jump_helper(a, dst_bb, nodes(a, params_count, params)); + todo.wrapper->payload.basic_block.body = jump_helper(a, dst_bb, nodes(a, params_count, params), get_abstraction_mem(todo.wrapper)); } static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* element_type) { @@ -146,7 +146,8 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, switch (opcode) { case LLVMRet: return (EmittedInstr) { .terminator = fn_ret(a, (Return) { - .args = num_ops == 0 ? empty(a) : convert_operands(p, num_ops, instr) + .args = num_ops == 0 ? empty(a) : convert_operands(p, num_ops, instr), + .mem = bb_mem(b), }) }; case LLVMBr: { @@ -160,33 +161,35 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, return (EmittedInstr) { .terminator = branch(a, (Branch) { .condition = condition, - .true_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0]), - .false_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[1]), + .true_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)), + .false_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[1], bb_mem(b)), + .mem = bb_mem(b), }) }; } else { assert(n_targets == 1); return (EmittedInstr) { - .terminator = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0]) + .terminator = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)) }; } } case LLVMSwitch: { const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); - const Node* default_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, 1)); + const Node* default_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, 1), bb_mem(b)); int n_targets = LLVMGetNumOperands(instr) / 2 - 1; LARRAY(const Node*, targets, n_targets); LARRAY(const Node*, literals, n_targets); for (size_t i = 0; i < n_targets; i++) { literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); - targets[i] = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3)); + targets[i] = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3), bb_mem(b)); } return (EmittedInstr) { .terminator = br_switch(a, (Switch) { - .switch_value = inspectee, - .default_jump = default_jump, - .case_values = nodes(a, n_targets, literals), - .case_jumps = nodes(a, n_targets, targets) + .switch_value = inspectee, + .default_jump = default_jump, + .case_values = nodes(a, n_targets, literals), + .case_jumps = nodes(a, n_targets, targets), + .mem = bb_mem(b), }) }; } @@ -195,7 +198,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, case LLVMInvoke: goto unimplemented; case LLVMUnreachable: return (EmittedInstr) { - .terminator = unreachable(a) + .terminator = unreachable(a, (Unreachable) { .mem = bb_mem(b) }) }; case LLVMCallBr: goto unimplemented; diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 54b600b89..c7edda8ca 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -32,21 +32,31 @@ static void initialize_controls(Context* ctx, Controls* controls, const Node* fn insert_dict(const Node*, Controls*, ctx->controls, fn_or_bb, controls); } -static const Node* wrap_in_controls(Context* ctx, Controls* controls, const Node* body) { - IrArena* a = ctx->rewriter.dst_arena; - if (!body) - return NULL; +static void wrap_in_controls(Context* ctx, Controls* controls, Node* nabs, const Node* oabs) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + const Node* obody = get_abstraction_body(oabs); + if (!obody) + return; + // const Node* mem = get_abstraction_mem(nabs); + Node* c = case_(a, empty(a)); + register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); + set_abstraction_body(c, rewrite_node(r, obody)); for (size_t i = 0; i < controls->destinations.count; i++) { const Node* token = controls->tokens.nodes[i]; const Node* dst = controls->destinations.nodes[i]; Nodes o_dst_params = get_abstraction_params(dst); Node* control_case = case_(a, singleton(token)); - set_abstraction_body(control_case, body); - BodyBuilder* bb = begin_body(a); + set_abstraction_body(control_case, jump_helper(a, c, empty(a), get_abstraction_mem(control_case))); + + Node* c2 = case_(a, empty(a)); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); Nodes results = gen_control(bb, get_param_types(a, o_dst_params), control_case); - body = finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results)); + set_abstraction_body(c2, finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results, bb_mem(bb)))); + c = c2; } - return body; + const Node* body = jump_helper(a, c, empty(a), get_abstraction_mem(nabs)); + return set_abstraction_body(nabs, body); } KeyHash hash_node(Node**); @@ -85,26 +95,12 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, return param(a, node->payload.param.type ? rewrite_node(&ctx->rewriter, node->payload.param.type) : NULL, node->payload.param.name); return param(a, qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.param.type), false), node->payload.param.name); } - case Block_TAG: { - Nodes yield_types = rewrite_nodes(r, node->payload.block.yield_types); - const Node* ninside = rewrite_node(r, node->payload.block.inside); - const Node* term = get_abstraction_body(ninside); - while (term->tag == Let_TAG) { - term = term->payload.let.in; - } - assert(term->tag == BlockYield_TAG); - yield_types = get_values_types(a, term->payload.block_yield.args); - return block(a, (Block) { - .yield_types = yield_types, - .inside = ninside, - }); - } case Constant_TAG: { Node* new = (Node*) recreate_node_identity(r, node); - BodyBuilder* bb = begin_body(a); - const Node* value = first(bind_instruction(bb, new->payload.constant.instruction)); + BodyBuilder* bb = begin_block_pure(a); + const Node* value = first(bind_instruction(bb, new->payload.constant.value)); value = first(bind_instruction(bb, prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)))); - new->payload.constant.instruction = yield_values_and_wrap_in_compound_instruction(bb, singleton(value)); + new->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(value)); return new; } case PrimOp_TAG: { @@ -149,11 +145,12 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, Node* decl = function(ctx->rewriter.dst_module, new_params, get_abstraction_name(node), new_annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); register_processed(&ctx->rewriter, node, decl); if (primop_intrinsic != PRIMOPS_COUNT) { - decl->payload.fun.body = fn_ret(a, (Return) { - .args = singleton(prim_op_helper(a, primop_intrinsic, empty(a), get_abstraction_params(decl))) - }); + set_abstraction_body(decl, fn_ret(a, (Return) { + .args = singleton(prim_op_helper(a, primop_intrinsic, empty(a), get_abstraction_params(decl))), + .mem = get_abstraction_mem(decl), + })); } else - decl->payload.fun.body = rewrite_node(&fn_ctx.rewriter, node->payload.fun.body); + wrap_in_controls(ctx, &controls, decl, node); destroy_cfg(fn_ctx.cfg); return decl; } @@ -162,7 +159,11 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, bb_ctx.old_fn_or_bb = node; Controls controls; initialize_controls(ctx, &controls, node); - Node* new_bb = (Node*) recreate_node_identity(&bb_ctx.rewriter, node); + Nodes nparams = recreate_params(&ctx->rewriter, get_abstraction_params(node)); + register_processed_list(r, get_abstraction_params(node), nparams); + Node* new_bb = (Node*) basic_block(a, nparams, get_abstraction_name_unsafe(node)); + register_processed(r, node, new_bb); + wrap_in_controls(ctx, &controls, new_bb, node); // new_bb->payload.basic_block.body = wrap_in_controls(ctx, &controls, new_bb->payload.basic_block.body); return new_bb; } @@ -233,9 +234,10 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, Node* wrapper = basic_block(a, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); wrapper->payload.basic_block.body = join(a, (Join) { .args = nparams, - .join_point = join_token + .join_point = join_token, + .mem = get_abstraction_mem(wrapper), }); - return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args)); + return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); } else { assert(false); } @@ -274,7 +276,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, Node* c = constant(ctx->rewriter.dst_module, singleton(annotation(a, (Annotation) { .name = "Inline" })), pt, format_string_interned(a, "%s_proxy", get_declaration_name(decl))); - c->payload.constant.instruction = prim_op_helper(a, convert_op, singleton(pt), singleton( + c->payload.constant.value = prim_op_helper(a, convert_op, singleton(pt), singleton( ref_decl_helper(a, decl))); result = c; } @@ -288,12 +290,12 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, } // This is required so we don't wrap jumps that are part of branches! - if (ctx->old_fn_or_bb && op_class == NcTerminator && node->tag != Let_TAG) { - Controls** found = find_value_dict(const Node, Controls*, ctx->controls, ctx->old_fn_or_bb); - assert(found); - Controls* controls = *found; - return wrap_in_controls(ctx, controls, recreate_node_identity(&ctx->rewriter, node)); - } + // if (ctx->old_fn_or_bb && op_class == NcTerminator) { + // Controls** found = find_value_dict(const Node, Controls*, ctx->controls, ctx->old_fn_or_bb); + // assert(found); + // Controls* controls = *found; + // return wrap_in_controls(ctx, controls, recreate_node_identity(&ctx->rewriter, node)); + // } return recreate_node_identity(&ctx->rewriter, node); } diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index f5bb5b966..d80f2a427 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -83,9 +83,9 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { Node* decl = constant(p->dst, annotations, t, name); r = ref_decl_helper(a, decl); insert_dict(LLVMTypeRef, const Type*, p->map, v, r); - BodyBuilder* bb = begin_body(a); + BodyBuilder* bb = begin_block_pure(a); EmittedInstr emitted = convert_instruction(p, NULL, NULL, bb, v); - decl->payload.constant.value = bind_last_instruction_and_wrap_in_compound_instruction_explicit_return_types(bb, emitted.instruction, singleton(t)); + decl->payload.constant.value = bind_last_instruction_and_wrap_in_block(bb, emitted.instruction); return r; } case LLVMConstantDataArrayValueKind: { From 4f47a0e2ee9c661a8a05a480e382352c8ba3ae94 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 12:00:00 +0200 Subject: [PATCH 417/693] added scheduler --- src/shady/CMakeLists.txt | 1 + src/shady/analysis/cfg.c | 2 +- src/shady/analysis/scheduler.c | 78 ++++++++++++++++++++++++++++++++++ src/shady/analysis/scheduler.h | 15 +++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/shady/analysis/scheduler.c create mode 100644 src/shady/analysis/scheduler.h diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 25e97b4d1..7017d1cc6 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -48,6 +48,7 @@ set(SHADY_SOURCES analysis/uses.c analysis/looptree.c analysis/leak.c + analysis/scheduler.c transform/memory_layout.c transform/ir_gen_helpers.c diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 9eed93490..3ed1a8f0c 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -199,7 +199,7 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { case Unreachable_TAG: return; case NotATerminator: - if (terminator->arena->config.check_types) {error("Grammar problem"); } + error("Grammar problem"); return; } SHADY_UNREACHABLE; diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c new file mode 100644 index 000000000..56865f111 --- /dev/null +++ b/src/shady/analysis/scheduler.c @@ -0,0 +1,78 @@ +#include "scheduler.h" + +#include "visit.h" + +#include "dict.h" +#include + +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + +struct Scheduler_ { + Visitor v; + CFNode* result; + CFG* cfg; + struct Dict* scheduled; +}; + +static void schedule_after(CFNode** scheduled, CFNode* req) { + if (!req) + return; + CFNode* old = *scheduled; + if (!old) + *scheduled = req; + else { + // TODO: validate that old post-dominates req + if (req->rpo_index > old->rpo_index) + *scheduled = req; + } +} + +static void visit_operand(Scheduler* s, NodeClass nc, String opname, const Node* op) { + switch (nc) { + // We only care about mem and value dependencies + case NcMem: + case NcValue: + schedule_after(&s->result, schedule_instruction(s, op)); + break; + default: + break; + } +} + +Scheduler* new_scheduler(CFG* cfg) { + Scheduler* s = calloc(sizeof(Scheduler), 1); + *s = (Scheduler) { + .v = { + .visit_op_fn = (VisitOpFn) visit_operand, + }, + .cfg = cfg, + .scheduled = new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), + }; + return s; +} + +CFNode* schedule_instruction(Scheduler* s, const Node* n) { + //assert(n && is_instruction(n)); + CFNode** found = find_value_dict(const Node*, CFNode*, s->scheduled, n); + if (found) + return *found; + + Scheduler s2 = *s; + s2.result = NULL; + + if (n->tag == Param_TAG) { + schedule_after(&s2.result, cfg_lookup(s->cfg, n->payload.param.abs)); + } else if (n->tag == AbsMem_TAG) { + schedule_after(&s2.result, cfg_lookup(s->cfg, n->payload.abs_mem.abs)); + } + + visit_node_operands(&s2.v, 0, n); + insert_dict(const Node*, CFNode*, s->scheduled, n, s2.result); + return s2.result; +} + +void destroy_scheduler(Scheduler* s) { + destroy_dict(s->scheduled); + free(s); +} diff --git a/src/shady/analysis/scheduler.h b/src/shady/analysis/scheduler.h new file mode 100644 index 000000000..146f54284 --- /dev/null +++ b/src/shady/analysis/scheduler.h @@ -0,0 +1,15 @@ +#ifndef SHADY_SCHEDULER_H +#define SHADY_SCHEDULER_H + +#include "shady/ir.h" +#include "cfg.h" + +typedef struct Scheduler_ Scheduler; + +Scheduler* new_scheduler(CFG*); +void destroy_scheduler(Scheduler*); + +/// Returns the CFNode where that instruction should be placed, or NULL if it can be computed at the top-level +CFNode* schedule_instruction(Scheduler*, const Node*); + +#endif From 1f5740c5b7fe79de7dabcad4b9fda08594d7a0ed Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 12:00:07 +0200 Subject: [PATCH 418/693] reworking pretty-printer (it's not pretty yet) --- src/shady/print.c | 321 +++++++++++++++++++++++++++++++--------------- 1 file changed, 217 insertions(+), 104 deletions(-) diff --git a/src/shady/print.c b/src/shady/print.c index 66c2299ad..cd0f87a23 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -2,6 +2,7 @@ #include "ir_private.h" #include "analysis/cfg.h" +#include "analysis/scheduler.h" #include "analysis/uses.h" #include "analysis/leak.h" @@ -12,6 +13,7 @@ #include "printer.h" #include "type.h" +#include "visit.h" #include #include @@ -24,29 +26,60 @@ struct PrinterCtx_ { NodePrintConfig config; const Node* fn; CFG* cfg; + Scheduler* scheduler; const UsesMap* uses; - long int min_rpo; + + Growy* root_growy; + Printer* root_printer; + + Growy** bb_growies; + Printer** bb_printers; + struct Dict* emitted; }; +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + static void print_node_impl(PrinterCtx* ctx, const Node* node); +static void print_terminator(PrinterCtx* ctx, const Node* node); static void print_mod_impl(PrinterCtx* ctx, Module* mod); -void print_module(Printer* printer, NodePrintConfig config, Module* mod) { +static String emit_node(PrinterCtx* ctx, const Node* node); +static void print_mem(PrinterCtx* ctx, const Node* node); + +static PrinterCtx make_printer_ctx(Printer* printer, NodePrintConfig config) { PrinterCtx ctx = { .printer = printer, .config = config, + .emitted = new_dict(const Node*, String, (HashFn) hash_node, (CmpFn) compare_node), + .root_growy = new_growy(), }; + ctx.root_printer = open_growy_as_printer(ctx.root_growy); + return ctx; +} + +static void destroy_printer_ctx(PrinterCtx ctx) { + destroy_dict(ctx.emitted); +} + +void print_module(Printer* printer, NodePrintConfig config, Module* mod) { + PrinterCtx ctx = make_printer_ctx(printer, config); print_mod_impl(&ctx, mod); + String s = printer_growy_unwrap(ctx.root_printer); + print(ctx.printer, "%s", s); + free((void*)s); flush(ctx.printer); + destroy_printer_ctx(ctx); } void print_node(Printer* printer, NodePrintConfig config, const Node* node) { - PrinterCtx ctx = { - .printer = printer, - .config = config, - }; - print_node_impl(&ctx, node); + PrinterCtx ctx = make_printer_ctx(printer, config); + String emitted = emit_node(&ctx, node); + String s = printer_growy_unwrap(ctx.root_printer); + print(ctx.printer, "%s%s", s, emitted); + free((void*)s); flush(ctx.printer); + destroy_printer_ctx(ctx); } void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { @@ -132,7 +165,6 @@ void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) #define print_node(n) print_operand_helper(ctx, 0, n) #define print_operand(nc, n) print_operand_helper(ctx, nc, n) -static void print_node_impl(PrinterCtx* ctx, const Node* node); static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op); void print_node_operand(PrinterCtx* ctx, const Node* node, String op_name, NodeClass op_class, const Node* op); @@ -240,7 +272,9 @@ static void print_dominated_bbs(PrinterCtx* ctx, const CFNode* dominator) { if (find_key_dict(const Node*, dominator->structurally_dominates, cfnode->node)) continue; assert(is_basic_block(cfnode->node)); - print_basic_block(ctx, cfnode->node); + PrinterCtx bb_ctx = *ctx; + bb_ctx.printer = bb_ctx.bb_printers[cfnode->rpo_index]; + print_basic_block(&bb_ctx, cfnode->node); } } @@ -248,17 +282,11 @@ static void print_abs_body(PrinterCtx* ctx, const Node* block) { assert(!ctx->fn || is_function(ctx->fn)); assert(is_abstraction(block)); - print_node(get_abstraction_body(block)); + emit_node(ctx, get_abstraction_body(block)); - // TODO: it's likely cleaner to instead print things according to the dominator tree in the first place. if (ctx->cfg != NULL) { const CFNode* dominator = cfg_lookup(ctx->cfg, block); - if (ctx->min_rpo < ((long int) dominator->rpo_index)) { - size_t save_rpo = ctx->min_rpo; - ctx->min_rpo = dominator->rpo_index; - print_dominated_bbs(ctx, dominator); - ctx->min_rpo = save_rpo; - } + print_dominated_bbs(ctx, dominator); } } @@ -275,20 +303,26 @@ static void print_function(PrinterCtx* ctx, const Node* node) { assert(is_function(node)); PrinterCtx sub_ctx = *ctx; - if (node->arena->config.check_op_classes) { + if (true || node->arena->config.check_op_classes) { CFG* cfg = build_fn_cfg(node); sub_ctx.cfg = cfg; + sub_ctx.scheduler = new_scheduler(cfg); sub_ctx.fn = node; + sub_ctx.bb_growies = calloc(sizeof(size_t), cfg->size); + sub_ctx.bb_printers = calloc(sizeof(size_t), cfg->size); + for (size_t i = 0; i < cfg->size; i++) { + sub_ctx.bb_growies[i] = new_growy(); + sub_ctx.bb_printers[i] = open_growy_as_printer(sub_ctx.bb_growies[i]); + } if (node->arena->config.check_types && node->arena->config.allow_fold) { sub_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); } } ctx = &sub_ctx; - ctx->min_rpo = -1; print_yield_types(ctx, node->payload.fun.return_types); print_param_list(ctx, node->payload.fun.params, NULL); - if (!node->payload.fun.body) { + if (!get_abstraction_body(node)) { printf(";"); return; } @@ -299,20 +333,31 @@ static void print_function(PrinterCtx* ctx, const Node* node) { print_abs_body(ctx, node); - deindent(ctx->printer); - printf("\n}"); - - if (node->arena->config.check_op_classes) { + if (sub_ctx.cfg) { if (sub_ctx.uses) destroy_uses_map(sub_ctx.uses); + for (size_t i = 0; i < sub_ctx.cfg->size; i++) { + String s = printer_growy_unwrap(sub_ctx.bb_printers[i]); + printf("%s", s); + free(s); + // destroy_printer(sub_ctx.bb_printers[i]); + // destroy_growy(sub_ctx.bb_growies[i]); + } + free(sub_ctx.bb_printers); + free(sub_ctx.bb_growies); destroy_cfg(sub_ctx.cfg); + destroy_scheduler(sub_ctx.scheduler); } + + deindent(ctx->printer); + printf("\n}"); } -static void print_annotations(PrinterCtx* ctx, Nodes annotations) { - for (size_t i = 0; i < annotations.count; i++) { - print_node(annotations.nodes[i]); - printf(" "); +static void print_nodes(PrinterCtx* ctx, Nodes nodes) { + for (size_t i = 0; i < nodes.count; i++) { + print_node(nodes.nodes[i]); + if (i + 1 < nodes.count) + printf(" "); } } @@ -623,34 +668,36 @@ static void print_value(PrinterCtx* ctx, const Node* node) { } static void print_instruction(PrinterCtx* ctx, const Node* node) { + //printf("%%%d = ", node->id); switch (is_instruction(node)) { case NotAnInstruction: assert(false); break; - case Instruction_Comment_TAG: { - printf(MAGENTA); - printf("/* %s */", node->payload.comment.string); - printf(RESET); - break; - } case PrimOp_TAG: { - printf(GREEN); - printf("%s", get_primop_name(node->payload.prim_op.op)); - printf(RESET); - Nodes ty_args = node->payload.prim_op.type_arguments; - if (ty_args.count > 0) - print_ty_args_list(ctx, node->payload.prim_op.type_arguments); - print_args_list(ctx, node->payload.prim_op.operands); - break; - } case Call_TAG: { - printf(GREEN); - printf("call"); - printf(RESET); - printf(" ("); - print_node(node->payload.call.callee); - printf(")"); - print_args_list(ctx, node->payload.call.args); - break; - } + // case Instruction_Comment_TAG: { + // printf(MAGENTA); + // printf("/* %s */", node->payload.comment.string); + // printf(RESET); + // break; + // } case PrimOp_TAG: { + // printf(GREEN); + // printf("%s", get_primop_name(node->payload.prim_op.op)); + // printf(RESET); + // Nodes ty_args = node->payload.prim_op.type_arguments; + // if (ty_args.count > 0) + // print_ty_args_list(ctx, node->payload.prim_op.type_arguments); + // print_args_list(ctx, node->payload.prim_op.operands); + // break; + // } case Call_TAG: { + // printf(GREEN); + // printf("call"); + // printf(RESET); + // printf(" ("); + // print_node(node->payload.call.callee); + // printf(")"); + // print_args_list(ctx, node->payload.call.args); + // break; + // } default: print_node_generated(ctx, node); } + //printf("\n"); } static void print_jump(PrinterCtx* ctx, const Node* node) { @@ -921,6 +968,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(";"); break; } + emit_node(ctx, get_terminator_mem(node)); } static void print_decl(PrinterCtx* ctx, const Node* node) { @@ -934,12 +982,14 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { PrinterCtx sub_ctx = *ctx; sub_ctx.cfg = NULL; + sub_ctx.scheduler = NULL; ctx = &sub_ctx; switch (node->tag) { case GlobalVariable_TAG: { const GlobalVariable* gvar = &node->payload.global_variable; - print_annotations(ctx, gvar->annotations); + print_nodes(ctx, gvar->annotations); + printf("\n"); printf(BLUE); printf("var "); printf(BLUE); @@ -958,7 +1008,8 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { } case Constant_TAG: { const Constant* cnst = &node->payload.constant; - print_annotations(ctx, cnst->annotations); + print_nodes(ctx, cnst->annotations); + printf("\n"); printf(BLUE); printf("const "); printf(RESET); @@ -967,15 +1018,15 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { printf(" %s", cnst->name); printf(RESET); if (cnst->value) { - printf(" = "); - print_node_impl(ctx, cnst->value); + printf(" = %s", emit_node(ctx, cnst->value)); } printf(";\n"); break; } case Function_TAG: { const Function* fun = &node->payload.fun; - print_annotations(ctx, fun->annotations); + print_nodes(ctx, fun->annotations); + printf("\n"); printf(BLUE); printf("fn"); printf(RESET); @@ -988,7 +1039,8 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { } case NominalType_TAG: { const NominalType* nom = &node->payload.nom_type; - print_annotations(ctx, nom->annotations); + print_nodes(ctx, nom->annotations); + printf("\n"); printf(BLUE); printf("type"); printf(RESET); @@ -1004,35 +1056,8 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { } } -static void print_node_impl(PrinterCtx* ctx, const Node* node) { - if (node == NULL) { - printf("?"); - return; - } - - if (ctx->config.print_ptrs) printf("%zu::", (size_t)(void*)node); - - if (is_type(node)) - print_type(ctx, node); - else if (is_instruction(node)) - print_instruction(ctx, node); - else if (is_value(node)) - print_value(ctx, node); - else if (is_terminator(node)) - print_terminator(ctx, node); - else if (is_declaration(node)) { - printf(BYELLOW); - printf("%s", get_declaration_name(node)); - printf(RESET); - } else if (node->tag == Unbound_TAG) { - printf(YELLOW); - printf("`%s`", node->payload.unbound.name); - printf(RESET); - } else if (node->tag == UnboundBBs_TAG) { - print_node(node->payload.unbound_bbs.body); - for (size_t i = 0; i < node->payload.unbound_bbs.children_blocks.count; i++) - print_basic_block(ctx, node->payload.unbound_bbs.children_blocks.nodes[i]); - } else switch (node->tag) { +static void print_annotation(PrinterCtx* ctx, const Node* node) { + switch (is_annotation(node)) { case Annotation_TAG: { const Annotation* annotation = &node->payload.annotation; printf(RED); @@ -1066,18 +1091,82 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { print_args_list(ctx, annotation->values); break; } - case BasicBlock_TAG: { - printf(BYELLOW); - if (node->payload.basic_block.name && strlen(node->payload.basic_block.name) > 0) - printf("%s", node->payload.basic_block.name); - else - printf("%%%d", node->id); - printf(RESET); - break; + case NotAnAnnotation: error(""); + } +} + +static String emit_node(PrinterCtx* ctx, const Node* node) { + if (node == NULL) { + return "?"; + } + + String* found = find_value_dict(const Node*, String, ctx->emitted, node); + if (found) + return *found; + + String r; + if (is_declaration(node)) + r = get_declaration_name(node); + else + r = format_string_interned(node->arena, "%%%d", node->id); + insert_dict(const Node*, String, ctx->emitted, node, r); + + //if (is_value(node) || is_instruction(node)) { + Growy* g = new_growy(); + PrinterCtx ctx2 = *ctx; + ctx2.printer = open_growy_as_printer(g); + print_node_impl(&ctx2, node); + String s = printer_growy_unwrap(ctx2.printer); + Printer* p = ctx->root_printer; + if (ctx->scheduler) { + CFNode* dst = schedule_instruction(ctx->scheduler, node); + if (dst) + p = ctx2.bb_printers[dst->rpo_index]; } - default: - print_node_generated(ctx, node); - break; + print(p, "%%%d = %s\n", node->id, s); + free((void*) s); + //} else { + // print_node_impl(ctx, node); + //} + return r; +} + +static void print_node_impl(PrinterCtx* ctx, const Node* node) { + assert(node); + + if (ctx->config.print_ptrs) printf("%zu::", (size_t)(void*)node); + + if (is_type(node)) + print_type(ctx, node); + else if (is_instruction(node)) + print_instruction(ctx, node); + else if (is_value(node)) + print_value(ctx, node); + else if (is_terminator(node)) + print_terminator(ctx, node); + else if (is_declaration(node)) { + printf(BYELLOW); + printf("%s", get_declaration_name(node)); + printf(RESET); + } else if (node->tag == Unbound_TAG) { + printf(YELLOW); + printf("`%s`", node->payload.unbound.name); + printf(RESET); + } else if (node->tag == UnboundBBs_TAG) { + print_node(node->payload.unbound_bbs.body); + for (size_t i = 0; i < node->payload.unbound_bbs.children_blocks.count; i++) + print_basic_block(ctx, node->payload.unbound_bbs.children_blocks.nodes[i]); + } else if (is_annotation(node)) { + print_annotation(ctx, node); + } else if (is_basic_block(node)) { + printf(BYELLOW); + if (node->payload.basic_block.name && strlen(node->payload.basic_block.name) > 0) + printf("%s", node->payload.basic_block.name); + else + printf("%%%d", node->id); + printf(RESET); + } else { + print_node_generated(ctx, node); } } @@ -1092,6 +1181,34 @@ static void print_mod_impl(PrinterCtx* ctx, Module* mod) { #undef print_node #undef printf +typedef struct { + Visitor v; + PrinterCtx* ctx; +} PrinterVisitor; + +static void print_mem_visitor(PrinterVisitor* ctx, NodeClass nc, String opname, const Node* op) { + if (nc == NcMem) + print_mem(ctx->ctx, op); +} + +static void print_mem(PrinterCtx* ctx, const Node* mem) { + PrinterVisitor pv = { + .v = { + .visit_op_fn = (VisitOpFn) print_mem_visitor, + }, + .ctx = ctx, + }; + switch (is_mem(mem)) { + case Mem_AbsMem_TAG: return; + case Mem_MemAndValue_TAG: return print_mem(ctx, mem->payload.mem_and_value.mem); + default: { + assert(is_instruction(mem)); + visit_node_operands(&pv, 0, mem); + return; + } + } +} + static void print_operand_name_helper(PrinterCtx* ctx, String name) { print(ctx->printer, GREY); print(ctx->printer, "%s", name); @@ -1103,13 +1220,9 @@ static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op) if (getenv("SHADY_SUPER_VERBOSE_NODE_DEBUG")) { if (op && (is_value(op) || is_instruction(op))) print(ctx->printer, "%%%d ", op->id); - print_node_impl(ctx, op); + print(ctx->printer, "%s", emit_node(ctx, op)); } else { - if (op && is_instruction(op) && op->arena->config.check_types) - print(ctx->printer, "%%%d", op->id); - else { - print_node_impl(ctx, op); - } + print(ctx->printer, "%s", emit_node(ctx, op)); } } From 4e287024ae518136aea40f5fe2b8bade0fe193a0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 14:18:27 +0200 Subject: [PATCH 419/693] added ExtInstr and migrated front-end ops to 'shady.frontend' --- include/shady/fe/slim.h | 11 +++ include/shady/grammar.json | 12 +++ include/shady/primops.json | 23 ------ src/backend/c/emit_c_instructions.c | 6 +- src/backend/spirv/emit_spv_instructions.c | 1 + src/frontend/slim/parser.c | 43 +++++++--- src/frontend/slim/parser.h | 6 +- src/shady/node_helpers.c | 3 + src/shady/passes/bind.c | 96 ++++++++++++++++------- src/shady/type.c | 9 ++- 10 files changed, 138 insertions(+), 72 deletions(-) create mode 100644 include/shady/fe/slim.h diff --git a/include/shady/fe/slim.h b/include/shady/fe/slim.h new file mode 100644 index 000000000..856f09c6f --- /dev/null +++ b/include/shady/fe/slim.h @@ -0,0 +1,11 @@ +#ifndef SHADY_SLIM_H +#define SHADY_SLIM_H + +typedef enum { + SlimOpDereference, + SlimOpAssign, + SlimOpAddrOf, + SlimOpSubscript, +} SlimFrontEndOpCodes; + +#endif diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 50cde4e0a..cbe667e11 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -690,6 +690,18 @@ { "name": "mem", "class": "mem", "nullable": true } ] }, + { + "name": "ExtInstr", + "description": "Turns a pointer into an assignable L-value", + "class": ["mem", "value", "instruction"], + "ops": [ + { "name": "mem", "class": "mem" }, + { "name": "result_t", "class": "type" }, + { "name": "set", "class": "string" }, + { "name": "opcode", "type": "uint32_t" }, + { "name": "operands", "type": "Nodes" } + ] + }, { "name": "UnboundBBs", "description": "A node together with unbound basic blocks it dominates, obtained by parsing a file", diff --git a/include/shady/primops.json b/include/shady/primops.json index 91f81f394..08477fb85 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -21,9 +21,6 @@ { "name": "subgroup_intrinsic" }, - { - "name": "ast" - }, { "name": "join_point" }, @@ -216,26 +213,6 @@ "name": "subgroup_ballot", "class": "subgroup_intrinsic" }, - { - "name": "assign", - "class": "ast", - "side-effects": true - }, - { - "name": "subscript", - "class": "ast", - "side-effects": true - }, - { - "name": "deref", - "class": "ast", - "side-effects": true - }, - { - "name": "addrof", - "class": "ast", - "side-effects": true - }, { "name": "select" }, diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index aa9d0618c..bde0db99c 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -240,9 +240,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct CTerm term = term_from_cvalue(format_string_interned(emitter->arena, "/* todo %s */", get_primop_name(prim_op->op))); const ISelTableEntry* isel_entry = lookup_entry(emitter, prim_op->op); switch (prim_op->op) { - case deref_op: - case assign_op: - case subscript_op: assert(false); case add_carry_op: case sub_borrow_op: case mul_extended_op: @@ -711,7 +708,8 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_GetStackSize_TAG: case Instruction_SetStackSize_TAG: case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); - case Instruction_BindIdentifiers_TAG: error("front-end only!"); + case Instruction_BindIdentifiers_TAG: error("front-end only!"); + case Instruction_ExtInstr_TAG: error("Extended instructions are not supported in C"); case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; /*case Instruction_CompoundInstruction_TAG: { diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index ec121fbf9..1f311b31e 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -389,6 +389,7 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build case Instruction_FillBytes_TAG: case Instruction_BindIdentifiers_TAG: case Instruction_StackAlloc_TAG: error("Should be lowered elsewhere") + case Instruction_ExtInstr_TAG: error("Extended instructions are not supported yet"); case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call, results_count, results); break; case PrimOp_TAG: emit_primop(emitter, fn_builder, bb_builder, instruction, results_count, results); break; case Comment_TAG: break; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 9a2ab4652..999940551 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -204,8 +204,12 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { .operands = expect_operands(ctx, bb) })); } else if (strcmp(id, "alloca") == 0) { + const Node* type = first(accept_type_arguments(ctx)); + Nodes ops = expect_operands(ctx, bb); + expect(ops.count == 0); return bind_instruction_single(bb, stack_alloc(arena, (StackAlloc) { - .type = first(accept_type_arguments(ctx)) + .type = type, + .mem = bb_mem(bb), })); } else if (strcmp(id, "debug_printf") == 0) { Nodes ops = expect_operands(ctx, bb); @@ -216,7 +220,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { } if (bb) - return bind_instruction_single(bb, unbound(arena, (Unbound) { .name = id })); + return bind_instruction_single(bb, unbound(arena, (Unbound) { .name = id, .mem = bb_mem(bb) })); return unbound(arena, (Unbound) { .name = id }); } case hex_lit_tok: @@ -504,16 +508,16 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { } else if (accept_token(ctx, star_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr); - return bind_instruction_single(bb, prim_op(arena, (PrimOp) { - .op = deref_op, - .operands = singleton(expr), - })); + return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpDereference, .operands = singleton(expr), .mem = bb_mem(bb) })); } else if (accept_token(ctx, infix_and_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr); - return bind_instruction_single(bb, prim_op(arena, (PrimOp) { - .op = addrof_op, + return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { + .set = "shady.frontend", + .result_t = unit_type(arena), + .opcode = SlimOpAddrOf, .operands = singleton(expr), + .mem = bb_mem(bb), })); } @@ -539,6 +543,26 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) .operands = nodes(arena, 2, (const Node* []) {expr, rhs}) })); } else switch (infix) { + case InfixAss: { + expr = bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { + .set = "shady.frontend", + .opcode = SlimOpAssign, + .result_t = unit_type(arena), + .operands = nodes(arena, 2, (const Node* []) {expr, rhs}), + .mem = bb_mem(bb), + })); + break; + } + case InfixSbs: { + expr = bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { + .set = "shady.frontend", + .opcode = SlimOpSubscript, + .result_t = unit_type(arena), + .operands = nodes(arena, 2, (const Node* []) {expr, rhs}), + .mem = bb_mem(bb), + })); + break; + } default: error("unknown infix operator") } continue; @@ -549,7 +573,8 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) Nodes ops = expect_operands(ctx, bb); expr = bind_instruction_single(bb, call(arena, (Call) { .callee = expr, - .args = ops + .args = ops, + .mem = bb_mem(bb), })); continue; } diff --git a/src/frontend/slim/parser.h b/src/frontend/slim/parser.h index 2dc9d6c7a..61b514b36 100644 --- a/src/frontend/slim/parser.h +++ b/src/frontend/slim/parser.h @@ -4,6 +4,8 @@ #include "shady/ir.h" +#include "shady/fe/slim.h" + typedef struct { bool front_end; } ParserConfig; @@ -26,8 +28,8 @@ INFIX_OPERATOR(Gt, infix_gt_tok, gt_op, 7) \ INFIX_OPERATOR(Ge, infix_geq_tok, gte_op, 7) \ INFIX_OPERATOR(Lt, infix_ls_tok, lt_op, 7) \ INFIX_OPERATOR(Le, infix_leq_tok, lte_op, 7) \ -INFIX_OPERATOR(Sbs, pound_tok, subscript_op, 0) \ -INFIX_OPERATOR(Ass, equal_tok, assign_op, 10) \ +INFIX_OPERATOR(Sbs, pound_tok, -1, 0) \ +INFIX_OPERATOR(Ass, equal_tok, -1, 10) \ typedef enum { #define INFIX_OPERATOR(name, token, primop, precedence) Infix##name, diff --git a/src/shady/node_helpers.c b/src/shady/node_helpers.c index 385ab2a1a..a5fc060f7 100644 --- a/src/shady/node_helpers.c +++ b/src/shady/node_helpers.c @@ -55,6 +55,9 @@ const Node* get_parent_mem(const Node* mem) { case Mem_DebugPrintf_TAG: mem = mem->payload.debug_printf.mem; return mem; + case Mem_ExtInstr_TAG: + mem = mem->payload.ext_instr.mem; + return mem; } } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 4ef373e7b..a4df848e7 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -9,6 +9,8 @@ #include #include +#include "shady/fe/slim.h" + typedef struct NamedBindEntry_ NamedBindEntry; struct NamedBindEntry_ { const char* name; @@ -83,25 +85,40 @@ static void add_binding(Context* ctx, bool is_var, String name, const Node* node static const Node* get_node_address(Context* ctx, const Node* node); static const Node* get_node_address_safe(Context* ctx, const Node* node) { - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { case Unbound_TAG: { + if (node->payload.unbound.mem) + rewrite_node(&ctx->rewriter, node->payload.unbound.mem); Resolved entry = resolve_using_name(ctx, node->payload.unbound.name); // can't take the address if it's not a var! if (!entry.is_var) return NULL; return entry.node; } - case PrimOp_TAG: { - if (node->tag == PrimOp_TAG && node->payload.prim_op.op == subscript_op) { - const Node* src_ptr = get_node_address_safe(ctx, node->payload.prim_op.operands.nodes[0]); - if (src_ptr == NULL) - return NULL; - const Node* index = rewrite_node(&ctx->rewriter, node->payload.prim_op.operands.nodes[1]); - return lea(a, (Lea) { .ptr = src_ptr, .offset = int32_literal(a, 0), singleton(index) }); - } else if (node->tag == PrimOp_TAG && node->payload.prim_op.op == deref_op) { - return rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)); + case ExtInstr_TAG: { + ExtInstr payload = node->payload.ext_instr; + if (strcmp(payload.set, "shady.frontend") == 0) { + if (payload.opcode == SlimOpSubscript) { + assert(payload.operands.count == 2); + const Node* src_ptr = get_node_address_safe(ctx, first(payload.operands)); + if (src_ptr == NULL) + return NULL; + const Node* index = rewrite_node(&ctx->rewriter, payload.operands.nodes[1]); + return mem_and_value(a, (MemAndValue) { + .mem = rewrite_node(r, payload.mem), + .value = lea(a, (Lea) { .ptr = src_ptr, .offset = int32_literal(a, 0), singleton(index) }), + }); + } else if (payload.opcode == SlimOpDereference) { + assert(payload.operands.count == 1); + return mem_and_value(a, (MemAndValue) { + .mem = rewrite_node(r, payload.mem), + .value = rewrite_node(&ctx->rewriter, first(payload.operands)), + }); + } } + break; } default: break; } @@ -129,7 +146,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, const Node* node) { if (node->payload.bind_identifiers.mutable) { const Type* type_annotation = node->payload.bind_identifiers.types.nodes[i]; assert(type_annotation); - const Node* alloca = stack_alloc(a, (StackAlloc) {rewrite_node(&ctx->rewriter, type_annotation)}); + const Node* alloca = stack_alloc(a, (StackAlloc) { .type = rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; set_value_name(ptr, names.strings[i]); bind_instruction_outputs_count(bb, store(a, (Store) {ptr, results.nodes[0]}), 0); @@ -200,10 +217,10 @@ static const Node* bind_node(Context* ctx, const Node* node) { if (found) return found; // in case the node is an l-value, we load it - const Node* lhs = get_node_address_safe(ctx, node); - if (lhs) { - return load(a, (Load) { lhs }); - } + // const Node* lhs = get_node_address_safe(ctx, node); + // if (lhs) { + // return load(a, (Load) { lhs, .mem = rewrite_node() }); + // } switch (node->tag) { case Function_TAG: @@ -215,6 +232,8 @@ static const Node* bind_node(Context* ctx, const Node* node) { } case Param_TAG: error("the binders should be handled such that this node is never reached"); case Unbound_TAG: { + if (node->payload.unbound.mem) + rewrite_node(r, node->payload.unbound.mem); Resolved entry = resolve_using_name(ctx, node->payload.unbound.name); assert(!entry.is_var); return entry.node; @@ -273,24 +292,41 @@ static const Node* bind_node(Context* ctx, const Node* node) { return new_bb; } case BindIdentifiers_TAG: return desugar_bind_identifiers(ctx, node); - default: { - if (node->tag == PrimOp_TAG && node->payload.prim_op.op == assign_op) { - const Node* target_ptr = get_node_address(ctx, node->payload.prim_op.operands.nodes[0]); - assert(target_ptr); - const Node* value = rewrite_node(&ctx->rewriter, node->payload.prim_op.operands.nodes[1]); - return store(a, (Store) { target_ptr, value }); - } else if (node->tag == PrimOp_TAG && node->payload.prim_op.op == subscript_op) { - return prim_op(a, (PrimOp) { - .op = extract_op, - .operands = mk_nodes(a, rewrite_node(&ctx->rewriter, node->payload.prim_op.operands.nodes[0]), rewrite_node(&ctx->rewriter, node->payload.prim_op.operands.nodes[1])) - }); - } else if (node->tag == PrimOp_TAG && node->payload.prim_op.op == addrof_op) { - const Node* target_ptr = get_node_address(ctx, node->payload.prim_op.operands.nodes[0]); - return target_ptr; + case ExtInstr_TAG: { + ExtInstr payload = node->payload.ext_instr; + if (strcmp("shady.frontend", payload.set) == 0) { + switch ((SlimFrontEndOpCodes) payload.opcode) { + case SlimOpDereference: + return load(a, (Load) { + .ptr = rewrite_node(r, first(payload.operands)), + .mem = rewrite_node(r, payload.mem), + }); + case SlimOpAssign: { + const Node* target_ptr = get_node_address(ctx, payload.operands.nodes[0]); + assert(target_ptr); + const Node* value = rewrite_node(r, payload.operands.nodes[1]); + return store(a, (Store) { target_ptr, value, .mem = rewrite_node(r, payload.mem) }); + } + case SlimOpAddrOf: { + const Node* target_ptr = get_node_address(ctx, payload.operands.nodes[0]); + return mem_and_value(a, (MemAndValue) { .value = target_ptr, .mem = rewrite_node(r, payload.mem) }); + } + case SlimOpSubscript: { + return mem_and_value(a, (MemAndValue) { + .value = prim_op(a, (PrimOp) { + .op = extract_op, + .operands = mk_nodes(a, rewrite_node(r, payload.operands.nodes[0]), rewrite_node(r, payload.operands.nodes[1])) + }), + .mem = rewrite_node(r, payload.mem) } + ); + } + } } - return recreate_node_identity(&ctx->rewriter, node); + break; } + default: break; } + return recreate_node_identity(&ctx->rewriter, node); } Module* bind_program(SHADY_UNUSED const CompilerConfig* compiler_config, Module* src) { diff --git a/src/shady/type.c b/src/shady/type.c index aea5efb7e..e89103901 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -531,10 +531,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { bool ordered = false; AddressSpace as; switch (prim_op.op) { - case deref_op: - case assign_op: - case addrof_op: - case subscript_op: error("These ops are only allowed in untyped IR before desugaring. They don't type to anything."); case neg_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); @@ -918,6 +914,11 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { } } +const Type* check_type_ext_instr(IrArena* arena, ExtInstr payload) { + assert(is_data_type(payload.result_t)); + return qualified_type_helper(payload.result_t, false); +} + static void check_arguments_types_against_parameters_helper(Nodes param_types, Nodes arg_types) { if (param_types.count != arg_types.count) error("Mismatched number of arguments/parameters"); From 8d793b22f070fa4e38eae7e167e93af323eaafd5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 14:57:07 +0200 Subject: [PATCH 420/693] removed support for multiple return types --- include/shady/ir.h | 11 +- src/backend/c/emit_c.c | 6 ++ src/backend/c/emit_c.h | 11 +- src/backend/c/emit_c_instructions.c | 117 ++++++++-------------- src/backend/c/emit_c_signatures.c | 2 +- src/backend/spirv/emit_spv_instructions.c | 5 +- src/backend/spirv/emit_spv_type.c | 2 +- src/shady/body_builder.c | 4 +- src/shady/constructors.c | 8 -- src/shady/passes/infer.c | 15 ++- src/shady/type.c | 26 ++--- src/shady/type.h | 3 - src/shady/type_helpers.c | 32 ------ 13 files changed, 79 insertions(+), 163 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 3413af85b..7d354ad0d 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -115,8 +115,6 @@ ExecutionModel execution_model_from_string(const char*); typedef enum { NotSpecial, - /// for instructions with multiple yield values. Must be deconstructed by a let, cannot appear anywhere else - MultipleReturn, /// Gets the 'Block' SPIR-V annotation, needed for UBO/SSBO variables DecorateBlock } RecordSpecialFlag; @@ -187,7 +185,6 @@ void set_abstraction_body (Node* abs, const Node* body); const Node* maybe_tuple_helper(IrArena* a, Nodes values); const Node* extract_helper(const Node* composite, const Node* index); -const Node* extract_multiple_ret_types_helper(const Node* composite, int index); const Node* maybe_tuple_helper(IrArena* a, Nodes values); @@ -207,12 +204,12 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi //////////////////////////////// Constructors //////////////////////////////// -/// For typing things that don't return at all +/// Empty type: there are no values of this type. +/// Useful for the codomain of things that don't return at all const Type* noret_type(IrArena*); -/// For making pointers to nothing in particular (equivalent to C's void*) +/// Unit type, carries no information (equivalent to C's void) +/// There is exactly one possible value of this type: () const Node* unit_type(IrArena*); -/// For typing instructions that return nothing (equivalent to C's void f()) -const Node* empty_multiple_return_type(IrArena*); const Type* int_type_helper(IrArena*, bool, IntSizes); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 2ae7b3dde..0a43aee1e 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -531,6 +531,12 @@ static void emit_loop(Emitter* emitter, Printer* p, Loop loop) { emit_terminator(emitter, p, get_abstraction_body(loop.tail)); } +CTerm bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { + String bind_to = unique_name(emitter->arena, ""); + emit_variable_declaration(emitter, p, t, bind_to, false, &term); + return term_from_cvalue(bind_to); +} + static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { switch (is_terminator(terminator)) { case NotATerminator: assert(false); diff --git a/src/backend/c/emit_c.h b/src/backend/c/emit_c.h index 70013b2bb..3ddcec071 100644 --- a/src/backend/c/emit_c.h +++ b/src/backend/c/emit_c.h @@ -79,16 +79,9 @@ String legalize_c_identifier(Emitter*, String); String get_record_field_name(const Type* t, size_t i); CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term); -typedef enum { NoBinding, LetBinding } InstrResultBinding; +CTerm bind_intermediary_result(Emitter*, Printer* p, const Type* t, CTerm term); -typedef struct { - size_t count; - CTerm* results; - /// What to do with the results at the call site - InstrResultBinding* binding; -} InstructionOutputs; - -void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, InstructionOutputs); +CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction); String emit_lambda_body (Emitter*, const Node*, const Nodes* nested_basic_blocks); void emit_lambda_body_at(Emitter*, Printer*, const Node*, const Nodes* nested_basic_blocks); diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index bde0db99c..72f9e41b4 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -233,7 +233,7 @@ static String index_into_array(Emitter* emitter, const Type* arr_type, CTerm exp return format_string_arena(arena->arena, "(%s.arr[%s])", deref_term(emitter, expr), index2); } -static void emit_primop(Emitter* emitter, Printer* p, const Node* node, InstructionOutputs outputs) { +static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { assert(node->tag == PrimOp_TAG); IrArena* arena = emitter->arena; const PrimOp* prim_op = &node->payload.prim_op; @@ -330,7 +330,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct break; } case convert_op: { - assert(outputs.count == 1); CTerm src = emit_value(emitter, p, first(prim_op->operands)); const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); @@ -347,7 +346,6 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct break; } case reinterpret_op: { - assert(outputs.count == 1); CTerm src_value = emit_value(emitter, p, first(prim_op->operands)); const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); @@ -359,38 +357,34 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct print(p, "\n%s = %s;", emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); print(p, "\n%s;", emit_type(emitter, dst_type, dst)); print(p, "\nmemcpy(&%s, &%s, sizeof(%s));", dst, src, src); - outputs.results[0] = term_from_cvalue(dst); - outputs.binding[0] = NoBinding; - break; + return term_from_cvalue(dst); } + // GLSL does not feature arbitrary casts, instead we need to run specialized conversion functions... case CDialect_GLSL: { - String n = NULL; + String conv_fn = NULL; if (dst_type->tag == Float_TAG) { assert(src_type->tag == Int_TAG); switch (dst_type->payload.float_type.width) { case FloatTy16: break; - case FloatTy32: n = src_type->payload.int_type.is_signed ? "intBitsToFloat" : "uintBitsToFloat"; + case FloatTy32: conv_fn = src_type->payload.int_type.is_signed ? "intBitsToFloat" : "uintBitsToFloat"; break; case FloatTy64: break; } } else if (dst_type->tag == Int_TAG) { if (src_type->tag == Int_TAG) { - outputs.results[0] = src_value; - outputs.binding[0] = NoBinding; - break; + return src_value; } assert(src_type->tag == Float_TAG); switch (src_type->payload.float_type.width) { case FloatTy16: break; - case FloatTy32: n = dst_type->payload.int_type.is_signed ? "floatBitsToInt" : "floatBitsToUint"; + case FloatTy32: conv_fn = dst_type->payload.int_type.is_signed ? "floatBitsToInt" : "floatBitsToUint"; break; case FloatTy64: break; } } - if (n) { - outputs.results[0] = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); - outputs.binding[0] = LetBinding; - break; + if (conv_fn) { + CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, to_cvalue(emitter, src_value))); + return bind_intermediary_result(emitter, p, node->type, converted); } error_print("glsl: unsupported bit cast from "); log_node(ERROR, src_type); @@ -411,23 +405,21 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct case FloatTy64: n = "doublebits"; break; } - outputs.results[0] = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); - outputs.binding[0] = LetBinding; + CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); + return bind_intermediary_result(emitter, p, node->type, converted); break; } else if (src_type->tag == Float_TAG) { assert(dst_type->tag == Int_TAG); - outputs.results[0] = term_from_cvalue(format_string_arena(emitter->arena->arena, "intbits(%s)", to_cvalue(emitter, src_value))); - outputs.binding[0] = LetBinding; + CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "intbits(%s)", to_cvalue(emitter, src_value))); + return bind_intermediary_result(emitter, p, node->type, converted); break; } CType t = emit_type(emitter, dst_type, NULL); - outputs.results[0] = term_from_cvalue(format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src_value))); - outputs.binding[0] = NoBinding; - break; + return term_from_cvalue(format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src_value))); } } - return; + SHADY_UNREACHABLE; } case insert_op: case extract_dynamic_op: @@ -527,9 +519,7 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct } case subgroup_assume_uniform_op: { if (emitter->config.dialect != CDialect_ISPC) { - outputs.results[0] = emit_value(emitter, p, prim_op->operands.nodes[0]); - outputs.binding[0] = NoBinding; - return; + return emit_value(emitter, p, prim_op->operands.nodes[0]); } } case subgroup_broadcast_first_op: { @@ -551,13 +541,10 @@ static void emit_primop(Emitter* emitter, Printer* p, const Node* node, Instruct if (isel_entry->isel_mechanism != IsNone) emit_using_entry(&term, emitter, p, isel_entry, prim_op->operands); - assert(outputs.count == 1); - outputs.binding[0] = LetBinding; - outputs.results[0] = term; - return; + return term; } -static void emit_call(Emitter* emitter, Printer* p, const Node* call, InstructionOutputs outputs) { +static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { Nodes args; if (call->tag == Call_TAG) args = call->payload.call.args; @@ -586,26 +573,14 @@ static void emit_call(Emitter* emitter, Printer* p, const Node* call, Instructio String params = printer_growy_unwrap(paramsp); - Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, call->type); - assert(yield_types.count == outputs.count); - if (yield_types.count > 1) { - String named = unique_name(emitter->arena, "result"); - print(p, "\n%s = %s(%s);", emit_type(emitter, call->type, named), e_callee, params); - for (size_t i = 0; i < yield_types.count; i++) { - outputs.results[i] = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s->_%d", named, i)); - // we have let-bound the actual result already, and extracting their components can be done inline - outputs.binding[i] = NoBinding; - } - } else if (yield_types.count == 1) { - outputs.results[0] = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); - outputs.binding[0] = LetBinding; - } else { - print(p, "\n%s(%s);", e_callee, params); - } + CTerm called = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); + called = bind_intermediary_result(emitter, p, call->type, called); + free_tmp_str(params); + return called; } -static void emit_lea(Emitter* emitter, Printer* p, Lea lea, InstructionOutputs outputs) { +static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { IrArena* arena = emitter->arena; CTerm acc = emit_value(emitter, p, lea.ptr); @@ -678,26 +653,24 @@ static void emit_lea(Emitter* emitter, Printer* p, Lea lea, InstructionOutputs o default: error("lea can't work on this"); } } - assert(outputs.count == 1); - outputs.results[0] = acc; - outputs.binding[0] = emitter->config.dialect == CDialect_ISPC ? LetBinding : NoBinding; - outputs.binding[0] = NoBinding; - return; + + if (emitter->config.dialect == CDialect_ISPC) + acc = bind_intermediary_result(emitter, p, curr_ptr_type, acc); + + return acc; } -static void emit_alloca(Emitter* emitter, Printer* p, const Type* type, InstructionOutputs outputs) { - assert(outputs.count == 1); +static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* type) { String variable_name = unique_name(emitter->arena, "alloca"); CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; emit_variable_declaration(emitter, p, type, variable_name, true, NULL); - outputs.results[0] = variable; if (emitter->config.dialect == CDialect_ISPC) { - outputs.results[0] = ispc_varying_ptr_helper(emitter, p, type, variable); + variable = ispc_varying_ptr_helper(emitter, p, type, variable); } - outputs.binding[0] = NoBinding; + return variable; } -void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, InstructionOutputs outputs) { +CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { assert(is_instruction(instruction)); IrArena* a = emitter->arena; @@ -710,8 +683,8 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); case Instruction_BindIdentifiers_TAG: error("front-end only!"); case Instruction_ExtInstr_TAG: error("Extended instructions are not supported in C"); - case Instruction_PrimOp_TAG: emit_primop(emitter, p, instruction, outputs); break; - case Instruction_Call_TAG: emit_call (emitter, p, instruction, outputs); break; + case Instruction_PrimOp_TAG: return emit_primop(emitter, p, instruction); + case Instruction_Call_TAG: return emit_call(emitter, p, instruction); /*case Instruction_CompoundInstruction_TAG: { Nodes instructions = instruction->payload.compound_instruction.instructions; for (size_t i = 0; i < instructions.count; i++) { @@ -738,14 +711,13 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins return; }*/ case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; - case Instruction_StackAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.stack_alloc.type, outputs); - case Instruction_LocalAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.local_alloc.type, outputs); + case Instruction_StackAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.stack_alloc.type); + case Instruction_LocalAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.local_alloc.type); case Instruction_Load_TAG: { Load payload = instruction->payload.load; CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, payload.ptr)); - outputs.results[0] = term_from_cvalue(dereferenced); - outputs.binding[0] = LetBinding; - return; + // we must bind the intermediary result here, otherwise we duplicate the load everwhere it is consumed + return bind_intermediary_result(emitter, p, instruction->type, term_from_cvalue(dereferenced)); } case Instruction_Store_TAG: { Store payload = instruction->payload.store; @@ -760,20 +732,19 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins cvalue = format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); print(p, "\n%s = %s;", dereferenced, cvalue); - return; + return empty_term(); } case Instruction_Lea_TAG: - emit_lea(emitter, p, instruction->payload.lea, outputs); - return; + return emit_lea(emitter, p, instruction->payload.lea); case Instruction_CopyBytes_TAG: { CopyBytes payload = instruction->payload.copy_bytes; print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, p, payload.src)), to_cvalue(emitter, c_emit_value(emitter, p, payload.count))); - return; + return empty_term(); } case Instruction_FillBytes_TAG:{ FillBytes payload = instruction->payload.fill_bytes; print(p, "\nmemset(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, p, payload.src)), to_cvalue(emitter, c_emit_value(emitter, p, payload.count))); - return; + return empty_term(); } case Instruction_DebugPrintf_TAG: { String args_list = format_string_interned(emitter->arena, "\"%s\"", instruction->payload.debug_printf.string); @@ -797,7 +768,7 @@ void emit_instruction(Emitter* emitter, Printer* p, const Node* instruction, Ins break; } - return; + return empty_term(); } } } diff --git a/src/backend/c/emit_c_signatures.c b/src/backend/c/emit_c_signatures.c index 546aef545..a83929375 100644 --- a/src/backend/c/emit_c_signatures.c +++ b/src/backend/c/emit_c_signatures.c @@ -99,7 +99,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const } free_tmp_str(parameters); - String c_decl = emit_type(emitter, wrap_multiple_yield_types(emitter->arena, codom), center); + String c_decl = emit_type(emitter, maybe_tuple_helper(emitter->arena, codom), center); if (entry_point) { switch (emitter->config.dialect) { case CDialect_C11: diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 1f311b31e..6e41f5f29 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -190,7 +190,8 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui return; } - Nodes results_ts = unwrap_multiple_yield_types(emitter->arena, instr->type); + error("TODO: convert spirv backend away from multiple returns") + /*Nodes results_ts = unwrap_multiple_yield_types(emitter->arena, instr->type); SpvId result_t = results_ts.count >= 1 ? emit_type(emitter, instr->type) : emitter->void_t; if (opcode == SpvOpMax) @@ -207,7 +208,7 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui if (results_count == 1) results[0] = result; } - return; + return;*/ } case Custom: SHADY_UNREACHABLE; } diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 40d36ed15..c3345aa6d 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -69,7 +69,7 @@ SpvId nodes_to_codom(Emitter* emitter, Nodes return_types) { case 0: return emitter->void_t; case 1: return emit_type(emitter, return_types.nodes[0]); default: { - const Type* codom_ret_type = record_type(emitter->arena, (RecordType) { .members = return_types, .special = MultipleReturn }); + const Type* codom_ret_type = record_type(emitter->arena, (RecordType) { .members = return_types, .special = 0 }); return emit_type(emitter, codom_ret_type); } } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 599f9f7fb..bb1acf7ef 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -72,13 +72,13 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { assert(bb->arena->config.check_types); - return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count); + return bind_internal(bb, instruction, singleton(instruction->type).count); } Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String const output_names[]) { assert(bb->arena->config.check_types); assert(output_names); - return bind_internal(bb, instruction, unwrap_multiple_yield_types(bb->arena, instruction->type).count); + return bind_internal(bb, instruction, singleton(instruction->type).count); } const Node* bind_identifiers(IrArena* arena, const Node* instruction, const Node* mem, bool mut, Strings names, Nodes types); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 78a4ce626..9ebeda0e3 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -273,16 +273,8 @@ const Node* jump_helper(IrArena* a, const Node* dst, Nodes args, const Node* mem } const Node* unit_type(IrArena* arena) { - /*return record_type(arena, (RecordType) { - .members = empty(arena), - });*/ - return empty_multiple_return_type(arena); -} - -const Node* empty_multiple_return_type(IrArena* arena) { return record_type(arena, (RecordType) { .members = empty(arena), - .special = MultipleReturn, }); } diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index eae8a808a..78a11ca9e 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -37,7 +37,7 @@ typedef struct { } Context; static const Node* infer_value(Context* ctx, const Node* node, const Type* expected_type); -static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes* expected_types); +static const Node* infer_instruction(Context* ctx, const Node* node, const Node* expected_type); static const Node* infer(Context* ctx, const Node* node, const Type* expect) { Context ctx2 = *ctx; @@ -342,7 +342,7 @@ static const Node* _infer_basic_block(Context* ctx, const Node* node) { return bb; } -static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* expected_types) { +static const Node* infer_primop(Context* ctx, const Node* node, const Node* expected_type) { assert(node->tag == PrimOp_TAG); IrArena* a = ctx->rewriter.dst_arena; @@ -409,7 +409,7 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Nodes* exp } } -static const Node* infer_indirect_call(Context* ctx, const Node* node, const Nodes* expected_types) { +static const Node* infer_indirect_call(Context* ctx, const Node* node, const Node* expected_type) { assert(node->tag == Call_TAG); IrArena* a = ctx->rewriter.dst_arena; @@ -527,7 +527,7 @@ static const Node* infer_control(Context* ctx, const Node* node) { }); } -static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes* expected_types) { +static const Node* infer_instruction(Context* ctx, const Node* node, const Type* expected_type) { IrArena* a = ctx->rewriter.dst_arena; switch (is_instruction(node)) { case Instruction_PushStack_TAG: { @@ -538,8 +538,8 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Nodes assert(is_data_type(element_type)); return pop_stack(a, (PopStack) { element_type }); } - case PrimOp_TAG: return infer_primop(ctx, node, expected_types); - case Call_TAG: return infer_indirect_call(ctx, node, expected_types); + case PrimOp_TAG: return infer_primop(ctx, node, expected_type); + case Call_TAG: return infer_indirect_call(ctx, node, expected_type); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); case Instruction_Lea_TAG: { Lea payload = node->payload.lea; @@ -700,8 +700,7 @@ static const Node* process(Context* src_ctx, const Node* node) { return infer_type(&ctx, node); } else if (is_instruction(node)) { if (expected_type) { - Nodes expected_types = unwrap_multiple_yield_types(a, expected_type); - return infer_instruction(&ctx, node, &expected_types); + return infer_instruction(&ctx, node, expected_type); } return infer_instruction(&ctx, node, NULL); } else if (is_value(node)) { diff --git a/src/shady/type.c b/src/shady/type.c index e89103901..d57e41cbe 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -234,8 +234,6 @@ bool is_data_type(const Type* type) { case Type_PackType_TAG: return is_data_type(type->payload.pack_type.element_type); case Type_RecordType_TAG: { - if (type->payload.record_type.members.count == 0) - return false; for (size_t i = 0; i < type->payload.record_type.members.count; i++) if (!is_data_type(type->payload.record_type.members.nodes[i])) return false; @@ -355,11 +353,7 @@ const Type* check_type_join_point_type(IrArena* arena, JoinPointType type) { const Type* check_type_record_type(IrArena* arena, RecordType type) { assert(type.names.count == 0 || type.names.count == type.members.count); for (size_t i = 0; i < type.members.count; i++) { - // member types are value types iff this is a return tuple - if (type.special == MultipleReturn) - assert(is_value_type(type.members.nodes[i])); - else - assert(is_data_type(type.members.nodes[i])); + assert(is_data_type(type.members.nodes[i])); } return NULL; } @@ -449,8 +443,6 @@ const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { } const Type* check_type_composite(IrArena* arena, Composite composite) { - if (composite.contents.count == 0) - return unit_type(arena); assert(is_data_type(composite.type)); Nodes expected_member_types = get_composite_type_element_types(composite.type); bool is_uniform = true; @@ -950,7 +942,7 @@ const Type* check_type_call(IrArena* arena, Call call) { assert(is_value(argument)); } Nodes argument_types = get_values_types(arena, args); - return wrap_multiple_yield_types(arena, check_value_call(call.callee, argument_types)); + return maybe_tuple_helper(arena, check_value_call(call.callee, argument_types)); } static void ensure_types_are_data_types(const Nodes* yield_types) { @@ -1014,7 +1006,7 @@ const Type* check_type_control(IrArena* arena, Control control) { } const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { - return empty_multiple_return_type(arena); + return qualified_type_helper(unit_type(arena), true); } const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { @@ -1069,7 +1061,7 @@ const Type* check_type_store(IrArena* a, Store store) { }); assert(is_subtype(val_expected_type, store.value->type)); - return empty_multiple_return_type(a); + return qualified_type_helper(unit_type(a), true); } const Type* check_type_lea(IrArena* a, Lea lea) { @@ -1111,7 +1103,7 @@ const Type* check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { const Type* cnt_t = copy_bytes.count->type; deconstruct_qualified_type(&cnt_t); assert(cnt_t->tag == Int_TAG); - return empty_multiple_return_type(a); + return qualified_type_helper(unit_type(a), true); } const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { @@ -1124,12 +1116,12 @@ const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { const Type* cnt_t = fill_bytes.count->type; deconstruct_qualified_type(&cnt_t); assert(cnt_t->tag == Int_TAG); - return empty_multiple_return_type(a); + return qualified_type_helper(unit_type(a), true); } const Type* check_type_push_stack(IrArena* a, PushStack payload) { assert(payload.value); - return empty_multiple_return_type(a); + return qualified_type_helper(unit_type(a), true); } const Type* check_type_pop_stack(IrArena* a, PopStack payload) { @@ -1138,7 +1130,7 @@ const Type* check_type_pop_stack(IrArena* a, PopStack payload) { const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { assert(get_unqualified_type(payload.value->type) == uint32_type(a)); - return empty_multiple_return_type(a); + return qualified_type_helper(unit_type(a), true); } const Type* check_type_get_stack_size(IrArena* a, SHADY_UNUSED GetStackSize ss) { @@ -1151,7 +1143,7 @@ const Type* check_type_get_stack_base_addr(IrArena* a, SHADY_UNUSED GetStackBase } const Type* check_type_debug_printf(IrArena* a, DebugPrintf payload) { - return empty_multiple_return_type(a); + return qualified_type_helper(unit_type(a), true);; } const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { diff --git a/src/shady/type.h b/src/shady/type.h index 07fb7a9a7..9235075a7 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -29,9 +29,6 @@ bool is_conversion_legal(const Type* src_type, const Type* dst_type); const Type* get_actual_mask_type(IrArena* arena); -const Type* wrap_multiple_yield_types(IrArena* arena, Nodes types); -Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); - /// Returns the (possibly qualified) pointee type from a (possibly qualified) ptr type const Type* get_pointee_type(IrArena*, const Type*); diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 8551a81f1..720f33998 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -5,31 +5,6 @@ #include -const Type* wrap_multiple_yield_types(IrArena* arena, Nodes types) { - switch (types.count) { - case 0: return empty_multiple_return_type(arena); - case 1: return types.nodes[0]; - default: return record_type(arena, (RecordType) { - .members = types, - .names = strings(arena, 0, NULL), - .special = MultipleReturn, - }); - } - SHADY_UNREACHABLE; -} - -Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type) { - switch (type->tag) { - case RecordType_TAG: - if (type->payload.record_type.special == MultipleReturn) - return type->payload.record_type.members; - // fallthrough - default: - assert(is_value_type(type)); - return singleton(type); - } -} - bool is_arrow_type(const Node* node) { NodeTag tag = node->tag; return tag == FnType_TAG || tag == BBType_TAG || tag == LamType_TAG; @@ -301,10 +276,3 @@ const Node* get_fill_type_size(const Type* composite_t) { default: error("fill values need to be either array or pack types") } } - -const Node* extract_multiple_ret_types_helper(const Node* composite, int index) { - Nodes types = unwrap_multiple_yield_types(composite->arena, composite->type); - if (types.count > 1) - return extract_helper(composite, int32_literal(composite->arena, index)); - return composite; -} From 2f4824df5a5964705b24ae21c7571e75f1b9c027 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 14:57:52 +0200 Subject: [PATCH 421/693] fix a couple mem issues in infer --- src/shady/passes/infer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 78a11ca9e..9a422ebc2 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -554,7 +554,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* return lea(a, (Lea) { ptr, offset, indices }); } case Instruction_Load_TAG: { - return load(a, (Load) { infer(ctx, node->payload.load.ptr, NULL) }); + return load(a, (Load) { infer(ctx, node->payload.load.ptr, NULL), .mem = infer(ctx, node->payload.load.mem, NULL) }); } case Instruction_Store_TAG: { Store payload = node->payload.store; @@ -564,13 +564,13 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* const Type* element_t = ptr_type->payload.ptr_type.pointed_type; assert(element_t); const Node* value = infer(ctx, payload.value, qualified_type_helper(element_t, false)); - return store(a, (Store) { ptr, value }); + return store(a, (Store) { ptr, value, .mem = infer(ctx, node->payload.store.mem, NULL) }); } case Instruction_StackAlloc_TAG: { const Type* element_type = node->payload.stack_alloc.type; assert(is_type(element_type)); assert(is_data_type(element_type)); - return stack_alloc(a, (StackAlloc) { .type = infer_type(ctx, element_type) }); + return stack_alloc(a, (StackAlloc) { .type = infer_type(ctx, element_type), .mem = infer(ctx, node->payload.stack_alloc.mem, NULL) }); } default: return recreate_node_identity(&ctx->rewriter, node); case NotAnInstruction: error("not an instruction"); From 632a4adbf50cf828c8de4bd9b625f10ba1218940 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 14:58:19 +0200 Subject: [PATCH 422/693] printer: print certain nodes inline --- src/shady/print.c | 170 +++++++++++++++------------------------------- 1 file changed, 56 insertions(+), 114 deletions(-) diff --git a/src/shady/print.c b/src/shady/print.c index cd0f87a23..9dc8a01b4 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -40,7 +40,7 @@ struct PrinterCtx_ { KeyHash hash_node(Node**); bool compare_node(Node**, Node**); -static void print_node_impl(PrinterCtx* ctx, const Node* node); +static bool print_node_impl(PrinterCtx* ctx, const Node* node); static void print_terminator(PrinterCtx* ctx, const Node* node); static void print_mod_impl(PrinterCtx* ctx, Module* mod); @@ -361,7 +361,7 @@ static void print_nodes(PrinterCtx* ctx, Nodes nodes) { } } -static void print_type(PrinterCtx* ctx, const Node* node) { +static bool print_type(PrinterCtx* ctx, const Node* node) { printf(BCYAN); switch (is_type(node)) { case NotAType: assert(false); break; @@ -395,12 +395,9 @@ static void print_type(PrinterCtx* ctx, const Node* node) { } break; case RecordType_TAG: - if (node->payload.record_type.special & MultipleReturn) { - if (node->payload.record_type.members.count == 0) { - printf("unit_t"); - break; - } - printf("multiple_return"); + if (node->payload.record_type.members.count == 0) { + printf("unit_t"); + break; } else if (node->payload.record_type.special & DecorateBlock) { printf("block"); } else { @@ -506,6 +503,7 @@ static void print_type(PrinterCtx* ctx, const Node* node) { break; } printf(RESET); + return true; } static void print_string_lit(PrinterCtx* ctx, const char* string) { @@ -529,7 +527,7 @@ static void print_string_lit(PrinterCtx* ctx, const char* string) { printf("\""); } -static void print_value(PrinterCtx* ctx, const Node* node) { +static bool print_value(PrinterCtx* ctx, const Node* node) { switch (is_value(node)) { case NotAValue: assert(false); break; case ConstrainedValue_TAG: { @@ -568,7 +566,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { default: error("Not a known valid int width") } printf(RESET); - break; + return true; case FloatLiteral_TAG: printf(BBLUE); switch (node->payload.float_literal.width) { @@ -587,22 +585,22 @@ static void print_value(PrinterCtx* ctx, const Node* node) { default: error("Not a known valid float width") } printf(RESET); - break; + return true; case True_TAG: printf(BBLUE); printf("true"); printf(RESET); - break; + return true; case False_TAG: printf(BBLUE); printf("false"); printf(RESET); - break; + return true; case StringLiteral_TAG: printf(BBLUE); print_string_lit(ctx, node->payload.string_lit.string); printf(RESET); - break; + return true; case Value_Undef_TAG: { const Type* type = node->payload.undef.type; printf(BBLUE); @@ -612,7 +610,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { print_node(type); printf(RESET); printf("]"); - break; + return true; } case Value_NullPtr_TAG: { const Type* type = node->payload.undef.type; @@ -623,7 +621,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { print_node(type); printf(RESET); printf("]"); - break; + return true; } case Value_Composite_TAG: { const Type* type = node->payload.composite.type; @@ -634,7 +632,7 @@ static void print_value(PrinterCtx* ctx, const Node* node) { print_node(type); printf("]"); print_args_list(ctx, node->payload.composite.contents); - break; + return true; } case Value_Fill_TAG: { const Type* type = node->payload.fill.type; @@ -648,23 +646,24 @@ static void print_value(PrinterCtx* ctx, const Node* node) { printf("("); print_node(node->payload.fill.value); printf(")"); - break; + return true; } case Value_RefDecl_TAG: { printf(BYELLOW); printf("%s", (char*) get_declaration_name(node->payload.ref_decl.decl)); printf(RESET); - break; + return true; } case FnAddr_TAG: printf(BYELLOW); printf("%s", (char*) get_declaration_name(node->payload.fn_addr.fn)); printf(RESET); - break; + return true; default: print_node_generated(ctx, node); break; } + return false; } static void print_instruction(PrinterCtx* ctx, const Node* node) { @@ -730,75 +729,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { TerminatorTag tag = is_terminator(node); switch (tag) { case NotATerminator: assert(false); - /*case Let_TAG: { - const Node* instruction = get_let_instruction(node); - const BindIdentifiers* binders = NULL; - if (instruction->tag == BindIdentifiers_TAG) - binders = &instruction->payload.bind_identifiers; - if (!ctx->config.reparseable) { - Nodes result_types = instruction->type ? unwrap_multiple_yield_types(node->arena, instruction->type) : empty(node->arena); - if (binders) { - //printf("%%%d = ", instruction->id); - printf(GREEN); - if (binders && binders->mutable) - printf("var"); - else - printf("val"); - printf(RESET); - } - - if (binders) { - Strings names = binders->names; - instruction = binders->instruction; - for (size_t i = 0; i < names.count; i++) { - if (binders->mutable) { - printf(" "); - print_node(binders->types.nodes[i]); - } - printf(" "); - printf("%s", names.strings[i]); - printf(RESET); - } - printf(" = "); - } else { - if (result_types.count > 1) { - printf("["); - for (size_t i = 0; i < result_types.count; i++) { - if (node->arena->config.check_types && !ctx->config.reparseable) { - printf(" "); - print_node(result_types.nodes[i]); - } - printf("%s", get_value_name_safe(extract_multiple_ret_types_helper(instruction, i))); - printf(RESET); - if (i + 1 < result_types.count) - printf(", "); - } - printf("]"); - printf(" = "); - } else { - printf("%%%d = ", instruction->id); - } - } - - print_node_impl(ctx, instruction); - if (!ctx->config.in_cfg) { - printf(";\n"); - print_node(node->payload.let.in); - } - } else { - printf(GREEN); - printf("let"); - printf(RESET); - printf(" "); - print_node(instruction); - printf(GREEN); - printf(" in "); - printf(RESET); - print_node(node->payload.let.in); - printf(";"); - } - break; - }*/ + /* case If_TAG: { print_structured_construct_results(ctx, get_structured_construct_tail(node)); printf(GREEN); @@ -966,7 +897,10 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf(RESET); print_args_list(ctx, node->payload.merge_selection.args); printf(";"); - break; + break;*/ + default: + print_node_generated(ctx, node); + return; } emit_node(ctx, get_terminator_mem(node)); } @@ -1111,37 +1045,41 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { r = format_string_interned(node->arena, "%%%d", node->id); insert_dict(const Node*, String, ctx->emitted, node, r); - //if (is_value(node) || is_instruction(node)) { - Growy* g = new_growy(); - PrinterCtx ctx2 = *ctx; - ctx2.printer = open_growy_as_printer(g); - print_node_impl(&ctx2, node); - String s = printer_growy_unwrap(ctx2.printer); - Printer* p = ctx->root_printer; - if (ctx->scheduler) { - CFNode* dst = schedule_instruction(ctx->scheduler, node); - if (dst) - p = ctx2.bb_printers[dst->rpo_index]; - } - print(p, "%%%d = %s\n", node->id, s); + Growy* g = new_growy(); + PrinterCtx ctx2 = *ctx; + ctx2.printer = open_growy_as_printer(g); + bool print_inline = print_node_impl(&ctx2, node); + String s = printer_growy_unwrap(ctx2.printer); + Printer* p = ctx->root_printer; + if (ctx->scheduler) { + CFNode* dst = schedule_instruction(ctx->scheduler, node); + if (dst) + p = ctx2.bb_printers[dst->rpo_index]; + } + print(p, "%%%d = %s\n", node->id, s); + + if (print_inline) { + String is = string(node->arena, s); + insert_dict(const Node*, String, ctx->emitted, node, is); free((void*) s); - //} else { - // print_node_impl(ctx, node); - //} - return r; + return is; + } else { + free((void*) s); + return r; + } } -static void print_node_impl(PrinterCtx* ctx, const Node* node) { +static bool print_node_impl(PrinterCtx* ctx, const Node* node) { assert(node); if (ctx->config.print_ptrs) printf("%zu::", (size_t)(void*)node); - if (is_type(node)) - print_type(ctx, node); - else if (is_instruction(node)) + if (is_type(node)) { + return print_type(ctx, node); + } else if (is_instruction(node)) print_instruction(ctx, node); else if (is_value(node)) - print_value(ctx, node); + return print_value(ctx, node); else if (is_terminator(node)) print_terminator(ctx, node); else if (is_declaration(node)) { @@ -1158,6 +1096,7 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { print_basic_block(ctx, node->payload.unbound_bbs.children_blocks.nodes[i]); } else if (is_annotation(node)) { print_annotation(ctx, node); + return true; } else if (is_basic_block(node)) { printf(BYELLOW); if (node->payload.basic_block.name && strlen(node->payload.basic_block.name) > 0) @@ -1168,6 +1107,7 @@ static void print_node_impl(PrinterCtx* ctx, const Node* node) { } else { print_node_generated(ctx, node); } + return false; } static void print_mod_impl(PrinterCtx* ctx, Module* mod) { @@ -1258,6 +1198,10 @@ void print_node_operand_Nodes_(PrinterCtx* ctx, const Node* n, String name, Node } } +void print_node_operand_Nodes(PrinterCtx* ctx, const Node* n, String name, Nodes op) { + print_node_operand_list(ctx, n, name, 0, op); +} + void print_node_operand_AddressSpace(PrinterCtx* ctx, const Node* n, String name, AddressSpace as) { print_operand_name_helper(ctx, name); print(ctx->printer, "%s", get_address_space_name(as)); @@ -1270,8 +1214,6 @@ void print_node_operand_Op(PrinterCtx* ctx, const Node* n, String name, Op op) { void print_node_operand_RecordSpecialFlag(PrinterCtx* ctx, const Node* n, String name, RecordSpecialFlag flags) { print_operand_name_helper(ctx, name); - if (flags & MultipleReturn) - print(ctx->printer, "MultipleReturn"); if (flags & DecorateBlock) print(ctx->printer, "DecorateBlock"); } From 891f28549ad646fdc02f342106bb052c06224c83 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 16:16:42 +0200 Subject: [PATCH 423/693] use BindIndentifiers to bind basic blocks --- include/shady/grammar.json | 14 ++--------- src/frontend/slim/parser.c | 30 ++++++++++++++-------- src/shady/body_builder.c | 51 ++++++++++++++++++++------------------ src/shady/node_helpers.c | 6 +++-- src/shady/passes/bind.c | 34 ------------------------- src/shady/passes/cleanup.c | 1 + src/shady/passes/infer.c | 7 ++++-- src/shady/print.c | 10 +++----- 8 files changed, 62 insertions(+), 91 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index cbe667e11..37f090db4 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -477,9 +477,9 @@ "name": "Jump", "class": ["terminator", "jump"], "ops": [ + { "name": "mem", "class": "mem" }, { "name": "target", "class": "basic_block" }, - { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "args", "class": "value", "list": true } ] }, { @@ -701,16 +701,6 @@ { "name": "opcode", "type": "uint32_t" }, { "name": "operands", "type": "Nodes" } ] - }, - { - "name": "UnboundBBs", - "description": "A node together with unbound basic blocks it dominates, obtained by parsing a file", - "type": false, - "front-end-only": true, - "ops": [ - { "name": "body", "class": "terminator" }, - { "name": "children_blocks", "class": "basic_block", "list": true } - ] } ] } \ No newline at end of file diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 999940551..cf66bcebc 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -738,8 +738,17 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* destroy_list(tlist); } -Nodes parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names); -Nodes parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names); +const Node* bind_identifiers(IrArena* arena, const Node* instruction, const Node* mem, bool mut, Strings names, Nodes types); + +void parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names) { + const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, bb->mem, true, output_names, provided_types); + bind_instruction_outputs_count(bb, let_mut_instr, 0); +} + +void parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names) { + const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, bb->mem, false, output_names, empty(bb->arena)); + bind_instruction_outputs_count(bb, let_mut_instr, 0); +} static bool accept_statement(ctxparams, BodyBuilder* bb) { Strings ids; @@ -767,7 +776,7 @@ static const Node* expect_jump(ctxparams, BodyBuilder* bb) { expect(target); Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); return jump(arena, (Jump) { - .target = unbound(arena, (Unbound) { .name = target }), + .target = unbound(arena, (Unbound) { .name = target, .mem = bb_mem(bb) }), .args = args, .mem = bb_mem(bb) }); @@ -890,7 +899,8 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator(const Node*)) { expect(accept_token(ctx, lbracket_tok)); - BodyBuilder* bb = begin_body_with_mem(arena, mem); + Node* c = case_(arena, empty(arena)); + BodyBuilder* bb = begin_body_with_mem(arena, get_abstraction_mem(c)); while (true) { if (!accept_statement(ctx, bb)) @@ -909,8 +919,11 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t error("expected terminator: return, jump, branch ..."); } + set_abstraction_body(c, finish_body(bb, terminator)); + + BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, mem); + if (curr_token(tokenizer).tag == cont_tok) { - struct List* conts = new_list(Node*); while (true) { if (!accept_token(ctx, cont_tok)) break; @@ -920,16 +933,13 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t expect_parameters(ctx, ¶meters, NULL, bb); Node* continuation = basic_block(arena, parameters, name); set_abstraction_body(continuation, expect_body(ctx, get_abstraction_mem(continuation), NULL)); - append_list(Node*, conts, continuation); + bind_instruction_single(cont_wrapper_bb, bind_identifiers(arena, continuation, bb_mem(cont_wrapper_bb), false, strings(arena, 1, &name), empty(arena))); } - - terminator = unbound_bbs(arena, (UnboundBBs) { .body = terminator, .children_blocks = nodes(arena, entries_count_list(conts), read_list(const Node*, conts)) }); - destroy_list(conts); } expect(accept_token(ctx, rbracket_tok)); - return finish_body(bb, terminator); + return finish_body(cont_wrapper_bb, jump_helper(arena, c, empty(arena), bb_mem(cont_wrapper_bb))); } static Nodes accept_annotations(ctxparams) { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index bb1acf7ef..683725a6b 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -81,18 +81,6 @@ Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String co return bind_internal(bb, instruction, singleton(instruction->type).count); } -const Node* bind_identifiers(IrArena* arena, const Node* instruction, const Node* mem, bool mut, Strings names, Nodes types); - -Nodes parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names) { - const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, bb->mem, true, output_names, provided_types); - return bind_internal(bb, let_mut_instr, 0); -} - -Nodes parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names) { - const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, bb->mem, false, output_names, empty(bb->arena)); - return bind_internal(bb, let_mut_instr, 0); -} - Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { return bind_internal(bb, instruction, outputs_count); } @@ -102,37 +90,27 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { size_t stack_size = entries_count_list(bb->stack); for (size_t i = stack_size - 1; i < stack_size; i--) { StackEntry entry = read_list(StackEntry, bb->stack)[i]; + const Node* t2 = terminator; switch (entry.structured.tag) { case NotAStructured_construct: error("") case Structured_construct_If_TAG: { - Node* tail = basic_block(bb->arena, entry.vars, NULL); - set_abstraction_body(tail, terminator); - entry.structured.payload.if_instr.tail = tail; terminator = if_instr(a, entry.structured.payload.if_instr); break; } case Structured_construct_Match_TAG: { - Node* tail = basic_block(bb->arena, entry.vars, NULL); - set_abstraction_body(tail, terminator); - entry.structured.payload.match_instr.tail = tail; terminator = match_instr(a, entry.structured.payload.match_instr); break; } case Structured_construct_Loop_TAG: { - Node* tail = basic_block(bb->arena, entry.vars, NULL); - set_abstraction_body(tail, terminator); - entry.structured.payload.loop_instr.tail = tail; terminator = loop_instr(a, entry.structured.payload.loop_instr); break; } case Structured_construct_Control_TAG: { - Node* tail = basic_block(bb->arena, entry.vars, NULL); - set_abstraction_body(tail, terminator); - entry.structured.payload.control.tail = tail; terminator = control(a, entry.structured.payload.control); break; } } + set_abstraction_body((Node*) get_structured_construct_tail(terminator), t2); } return terminator; } @@ -197,6 +175,7 @@ static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { } Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constructTag tag, union NodesUnion payload) { + Node* tail = basic_block(bb->arena, params, NULL); StackEntry entry = { .structured = { .tag = tag, @@ -204,6 +183,30 @@ Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constru }, .vars = params, }; + switch (entry.structured.tag) { + case NotAStructured_construct: error("") + case Structured_construct_If_TAG: { + entry.structured.payload.if_instr.tail = tail; + entry.structured.payload.if_instr.mem = bb_mem(bb); + break; + } + case Structured_construct_Match_TAG: { + entry.structured.payload.match_instr.tail = tail; + entry.structured.payload.match_instr.mem = bb_mem(bb); + break; + } + case Structured_construct_Loop_TAG: { + entry.structured.payload.loop_instr.tail = tail; + entry.structured.payload.loop_instr.mem = bb_mem(bb); + break; + } + case Structured_construct_Control_TAG: { + entry.structured.payload.control.tail = tail; + entry.structured.payload.control.mem = bb_mem(bb); + break; + } + } + bb->mem = get_abstraction_mem(tail); append_list(StackEntry , bb->stack, entry); return entry.vars; } diff --git a/src/shady/node_helpers.c b/src/shady/node_helpers.c index a5fc060f7..978a4a44f 100644 --- a/src/shady/node_helpers.c +++ b/src/shady/node_helpers.c @@ -64,8 +64,10 @@ const Node* get_parent_mem(const Node* mem) { const Node* get_original_mem(const Node* mem) { while (true) { const Node* nmem = get_parent_mem(mem); - if (nmem != mem) - return mem; + if (nmem != mem) { + mem = nmem; + continue; + } return nmem; } } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index a4df848e7..34cfdf214 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -238,40 +238,6 @@ static const Node* bind_node(Context* ctx, const Node* node) { assert(!entry.is_var); return entry.node; } - case UnboundBBs_TAG: { - Nodes unbound_blocks = node->payload.unbound_bbs.children_blocks; - LARRAY(Node*, new_bbs, unbound_blocks.count); - - // First create stubs - for (size_t i = 0; i < unbound_blocks.count; i++) { - const Node* old_bb = unbound_blocks.nodes[i]; - assert(is_basic_block(old_bb)); - Nodes new_bb_params = recreate_params(&ctx->rewriter, old_bb->payload.basic_block.params); - Node* new_bb = basic_block(a, new_bb_params, old_bb->payload.basic_block.name); - new_bbs[i] = new_bb; - add_binding(ctx, false, old_bb->payload.basic_block.name, new_bb); - register_processed(&ctx->rewriter, old_bb, new_bb); - debugv_print("Bound (stub) basic block %s\n", old_bb->payload.basic_block.name); - } - - const Node* bound_body = rewrite_node(&ctx->rewriter, node->payload.unbound_bbs.body); - - // Rebuild the basic blocks now - for (size_t i = 0; i < unbound_blocks.count; i++) { - const Node* old_bb = unbound_blocks.nodes[i]; - Node* new_bb = new_bbs[i]; - - Context bb_ctx = *ctx; - Nodes new_bb_params = get_abstraction_params(new_bb); - for (size_t j = 0; j < new_bb_params.count; j++) - add_binding(&bb_ctx, false, new_bb->payload.basic_block.params.nodes[j]->payload.param.name, new_bb_params.nodes[j]); - - set_abstraction_body(new_bb, rewrite_node(&bb_ctx.rewriter, old_bb->payload.basic_block.body)); - debugv_print("Bound basic block %s\n", new_bb->payload.basic_block.name); - } - - return bound_body; - } case BasicBlock_TAG: { assert(is_basic_block(node)); Nodes new_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index e4e726469..bb9fc08cc 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -70,6 +70,7 @@ const Node* process(Context* ctx, const Node* old) { // it's been inlined away! just steal the body Nodes nargs = rewrite_nodes(r, old->payload.jump.args); register_processed_list(r, get_abstraction_params(otarget), nargs); + register_processed(r, get_abstraction_mem(otarget), rewrite_node(r, old->payload.jump.mem)); return rewrite_node(r, get_abstraction_body(otarget)); } break; diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 9a422ebc2..39b13b305 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -290,7 +290,8 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec } static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg_type) { - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; assert(inferred_arg_type.count == node->payload.basic_block.params.count || node->payload.basic_block.params.count == 0); Context body_context = *ctx; @@ -314,6 +315,7 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg } Node* new_case = basic_block(a, nodes(a, inferred_arg_type.count, nparams), get_abstraction_name_unsafe(node)); + register_processed(r, node, new_case); set_abstraction_body(new_case, infer(&body_context, node->payload.basic_block.body, NULL)); return new_case; } @@ -461,7 +463,8 @@ static const Node* infer_if(Context* ctx, const Node* node) { .if_true = true_body, .if_false = false_body, //.tail = infer_case(ctx, node->payload.if_instr.tail, expected_join_types) - .tail = infer(ctx, node->payload.if_instr.tail, NULL) + .tail = infer(ctx, node->payload.if_instr.tail, NULL), + .mem = infer(ctx, node->payload.if_instr.mem, NULL), }); } diff --git a/src/shady/print.c b/src/shady/print.c index 9dc8a01b4..8bb23e57d 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -269,8 +269,8 @@ static void print_dominated_bbs(PrinterCtx* ctx, const CFNode* dominator) { for (size_t i = 0; i < dominator->dominates->elements_count; i++) { const CFNode* cfnode = read_list(const CFNode*, dominator->dominates)[i]; // ignore cases that make up basic structural dominance - if (find_key_dict(const Node*, dominator->structurally_dominates, cfnode->node)) - continue; + //if (find_key_dict(const Node*, dominator->structurally_dominates, cfnode->node)) + // continue; assert(is_basic_block(cfnode->node)); PrinterCtx bb_ctx = *ctx; bb_ctx.printer = bb_ctx.bb_printers[cfnode->rpo_index]; @@ -303,7 +303,7 @@ static void print_function(PrinterCtx* ctx, const Node* node) { assert(is_function(node)); PrinterCtx sub_ctx = *ctx; - if (true || node->arena->config.check_op_classes) { + if (node->arena->config.name_bound) { CFG* cfg = build_fn_cfg(node); sub_ctx.cfg = cfg; sub_ctx.scheduler = new_scheduler(cfg); @@ -1090,10 +1090,6 @@ static bool print_node_impl(PrinterCtx* ctx, const Node* node) { printf(YELLOW); printf("`%s`", node->payload.unbound.name); printf(RESET); - } else if (node->tag == UnboundBBs_TAG) { - print_node(node->payload.unbound_bbs.body); - for (size_t i = 0; i < node->payload.unbound_bbs.children_blocks.count; i++) - print_basic_block(ctx, node->payload.unbound_bbs.children_blocks.nodes[i]); } else if (is_annotation(node)) { print_annotation(ctx, node); return true; From 3f71959059431663963c3c425017ad37a6eaa802 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 16:18:18 +0200 Subject: [PATCH 424/693] infer: gut some suspicious code dealing with structured CF --- src/shady/passes/infer.c | 86 ---------------------------------------- 1 file changed, 86 deletions(-) diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 39b13b305..6d0e880d2 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -30,10 +30,6 @@ typedef struct { const Node* current_fn; const Type* expected_type; - - const Nodes* merge_types; - const Nodes* break_types; - const Nodes* continue_types; } Context; static const Node* infer_value(Context* ctx, const Node* node, const Type* expected_type); @@ -450,7 +446,6 @@ static const Node* infer_if(Context* ctx, const Node* node) { Context infer_if_body_ctx = *ctx; // When we infer the types of the arguments to a call to merge(), they are expected to be varying Nodes expected_join_types = add_qualifiers(a, join_types, false); - infer_if_body_ctx.merge_types = &expected_join_types; const Node* true_body = infer_case(&infer_if_body_ctx, node->payload.if_instr.if_true, nodes(a, 0, NULL)); // don't allow seeing the variables made available in the true branch @@ -487,10 +482,6 @@ static const Node* infer_loop(Context* ctx, const Node* node) { Nodes loop_yield_types = infer_nodes(ctx, node->payload.loop_instr.yield_types); Nodes qual_yield_types = add_qualifiers(a, loop_yield_types, false); - loop_body_ctx.merge_types = NULL; - loop_body_ctx.break_types = &qual_yield_types; - loop_body_ctx.continue_types = &new_params_types; - const Node* nbody = infer_case(&loop_body_ctx, old_body, new_params_types); // TODO check new body params match continue types @@ -589,18 +580,6 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { case Match_TAG: error("TODO") case Loop_TAG: return infer_loop (ctx, node); case Control_TAG: return infer_control(ctx, node); - /*case Let_TAG: { - // const Node* otail = node->payload.let.ttail; - // Nodes annotated_types = get_param_types(a, otail->payload.case_.params); - const Node* inferred_instruction = infer(ctx, node->payload.let.instruction, NULL); - register_processed(&ctx->rewriter, node->payload.let.instruction, inferred_instruction); - Nodes inferred_yield_types = unwrap_multiple_yield_types(a, inferred_instruction->type); - LARRAY(const Node*, vars, inferred_yield_types.count); - for (size_t i = 0; i < inferred_yield_types.count; i++) { - assert(is_value_type(inferred_yield_types.nodes[i])); - } - return let(a, inferred_instruction, infer(ctx, node->payload.let.in, NULL)); - }*/ case Return_TAG: { const Node* imported_fn = ctx->current_fn; Nodes return_types = imported_fn->payload.fun.return_types; @@ -614,71 +593,6 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { .mem = infer(ctx, payload.mem, NULL), }); } - case Jump_TAG: { - assert(is_basic_block(node->payload.jump.target)); - const Node* ntarget = infer(ctx, node->payload.jump.target, NULL); - Nodes param_types = get_param_types(a, get_abstraction_params(ntarget)); - - LARRAY(const Node*, tmp, node->payload.jump.args.count); - for (size_t i = 0; i < node->payload.jump.args.count; i++) - tmp[i] = infer(ctx, node->payload.jump.args.nodes[i], param_types.nodes[i]); - - Nodes new_args = nodes(a, node->payload.jump.args.count, tmp); - - return jump(a, (Jump) { - .target = ntarget, - .args = new_args - }); - } - case Branch_TAG: - case Terminator_Switch_TAG: break; - case Terminator_TailCall_TAG: break; - case Terminator_MergeSelection_TAG: { - // TODO: block nodes should set merge types - assert(ctx->merge_types && "Merge terminator found but we're not within a suitable if instruction !"); - Nodes expected_types = *ctx->merge_types; - Nodes old_args = node->payload.merge_selection.args; - assert(expected_types.count == old_args.count); - LARRAY(const Node*, new_args, old_args.count); - for (size_t i = 0; i < old_args.count; i++) { - const Node* e = expected_types.nodes[i]; - assert(is_value_type(e)); - new_args[i] = infer(ctx, old_args.nodes[i], e); - } - return merge_selection(a, (MergeSelection) { - .args = nodes(a, old_args.count, new_args) - }); - } - case MergeContinue_TAG: { - assert(ctx->continue_types && "Merge terminator found but we're not within a suitable loop instruction !"); - Nodes expected_types = *ctx->continue_types; - Nodes old_args = node->payload.merge_continue.args; - assert(expected_types.count == old_args.count); - LARRAY(const Node*, new_args, old_args.count); - for (size_t i = 0; i < old_args.count; i++) { - const Node* e = expected_types.nodes[i]; - assert(is_value_type(e)); - new_args[i] = infer(ctx, old_args.nodes[i], e); - } - return merge_continue(a, (MergeContinue) { - .args = nodes(a, old_args.count, new_args) - }); - } - case MergeBreak_TAG: { - assert(ctx->break_types && "Merge terminator found but we're not within a suitable loop instruction !"); - Nodes expected_types = *ctx->break_types; - Nodes old_args = node->payload.merge_break.args; - assert(expected_types.count == old_args.count); - LARRAY(const Node*, new_args, old_args.count); - for (size_t i = 0; i < old_args.count; i++) { - const Node* e = expected_types.nodes[i]; - assert(is_value_type(e)); - new_args[i] = infer(ctx, old_args.nodes[i], e); - } - return merge_break(a, (MergeBreak) { - .args = nodes(a, old_args.count, new_args) - }); - } default: break; } return recreate_node_identity(&ctx->rewriter, node); From 5632d72c85d2a7a5fa125cbc90ad1e34f8eb5852 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 16:36:54 +0200 Subject: [PATCH 425/693] added node operand folding --- src/shady/constructors.c | 2 ++ src/shady/fold.c | 12 ++++++++++++ src/shady/generator_constructors.c | 10 ++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 9ebeda0e3..24a1f6616 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -15,6 +15,8 @@ bool compare_nodes(Nodes* a, Nodes* b); static void pre_construction_validation(IrArena* arena, Node* node); +const Node* fold_node_operand(NodeTag tag, NodeClass, String, const Node* op); + const Type* check_type_generated(IrArena* a, const Node* node); static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { diff --git a/src/shady/fold.c b/src/shady/fold.c index 320ae6cb8..bfd72138d 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -437,3 +437,15 @@ const Node* fold_node(IrArena* arena, const Node* node) { return node; } + +const Node* fold_node_operand(NodeTag tag, NodeClass nc, String opname, const Node* op) { + if (!op) + return NULL; + if (op->tag == MemAndValue_TAG) { + MemAndValue payload = op->payload.mem_and_value; + if (nc == NcMem) + return payload.mem; + return payload.value; + } + return op; +} diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index f182c0a4f..9080cb51d 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -37,19 +37,21 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { if (list) { growy_append_formatted(g, "\t\t\tNodes ops = node->payload.%s.%s;\n", snake_name, op_name); growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < ops.count; i++) {\n"); - growy_append_formatted(g, "\t\t\tconst Node* op = ops.nodes[i];\n"); + growy_append_formatted(g, "\t\t\tconst Node** pop = &ops.nodes[i];\n"); extra = "\t"; } if (!list) - growy_append_formatted(g, "\t\t\tconst Node* op = node->payload.%s.%s;\n", snake_name, op_name); + growy_append_formatted(g, "\t\t\tconst Node** pop = &node->payload.%s.%s;\n", snake_name, op_name); + + growy_append_formatted(g, "\t\t\t*pop = fold_node_operand(%s_TAG, Nc%s, \"%s\", *pop);\n", name, cap, op_name); if (!(json_object_get_boolean(json_object_object_get(op, "nullable")) || json_object_get_boolean(json_object_object_get(op, "ignore")))) { - growy_append_formatted(g, "%s\t\t\tif (!op) {\n", extra); + growy_append_formatted(g, "%s\t\t\tif (!*pop) {\n", extra); growy_append_formatted(g, "%s\t\t\t\terror(\"operand '%s' of node '%s' cannot be null\");\n", extra, op_name, name); growy_append_formatted(g, "%s\t\t\t}\n", extra); } - growy_append_formatted(g, "%s\t\t\tif (arena->config.check_op_classes && op != NULL && !is_%s(op)) {\n", extra, class); + growy_append_formatted(g, "%s\t\t\tif (arena->config.check_op_classes && *pop != NULL && !is_%s(*pop)) {\n", extra, class); growy_append_formatted(g, "%s\t\t\t\terror_print(\"Invalid '%s' operand for node '%s', expected a %s\");\n", extra, op_name, name, class); growy_append_formatted(g, "%s\t\t\t\terror_die();\n", extra); growy_append_formatted(g, "%s\t\t\t}\n", extra); From 16a43760c34e784c3b5ab8a097d0579baf726a16 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 16:37:05 +0200 Subject: [PATCH 426/693] fixed demote_alloca --- src/shady/passes/opt_demote_alloca.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 9ca7b1952..a67d470de 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -202,6 +202,7 @@ static const Node* process(Context* ctx, const Node* old) { } case Load_TAG: { Load payload = old->payload.load; + rewrite_node(r, payload.mem); PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.ptr->type))); @@ -219,6 +220,7 @@ static const Node* process(Context* ctx, const Node* old) { } case Store_TAG: { Store payload = old->payload.store; + rewrite_node(r, payload.mem); PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.ptr->type))); From c0174c95a00ff51fd1f1d3be5a8a433f06641ecd Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 16:41:37 +0200 Subject: [PATCH 427/693] made operands of ExtInstr values --- include/shady/grammar.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 37f090db4..7ccfd80d2 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -699,7 +699,7 @@ { "name": "result_t", "class": "type" }, { "name": "set", "class": "string" }, { "name": "opcode", "type": "uint32_t" }, - { "name": "operands", "type": "Nodes" } + { "name": "operands", "class": "value", "list": true } ] } ] From 192945b22fa860a830ddc9a0172c6d7ea76d1d93 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 16:58:23 +0200 Subject: [PATCH 428/693] cleanup pass --- src/shady/fold.c | 6 +++--- src/shady/ir.c | 9 ++++++--- src/shady/passes/bind.c | 6 +++--- src/shady/passes/cleanup.c | 4 ++-- src/shady/print.c | 27 +-------------------------- src/shady/rewrite.c | 13 ------------- src/shady/rewrite.h | 3 --- src/shady/type.c | 22 ++++++++-------------- src/shady/type.h | 1 - src/shady/type_helpers.c | 16 ++-------------- src/shady/visit.c | 2 +- src/shady/visit.h | 4 ++-- 12 files changed, 28 insertions(+), 85 deletions(-) diff --git a/src/shady/fold.c b/src/shady/fold.c index bfd72138d..54b8441a7 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -100,11 +100,11 @@ break; if (all_int_literals) { uint64_t old_value = get_int_literal_value(*int_literals[0], int_literals[0]->is_signed); uint64_t value = old_value & bitmask; - return quote_single(arena, int_literal(arena, (IntLiteral) {.is_signed = dst_t->payload.int_type.is_signed, .width = dst_t->payload.int_type.width, .value = value})); + return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = dst_t->payload.int_type.is_signed, .width = dst_t->payload.int_type.width, .value = value })); } else if (all_float_literals) { double old_value = get_float_literal_value(*float_literals[0]); int64_t value = old_value; - return quote_single(arena, int_literal(arena, (IntLiteral) {.is_signed = dst_t->payload.int_type.is_signed, .width = dst_t->payload.int_type.width, .value = value})); + return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = dst_t->payload.int_type.is_signed, .width = dst_t->payload.int_type.width, .value = value })); } } else if (dst_t->tag == Float_TAG) { if (all_int_literals) { @@ -142,7 +142,7 @@ static inline const Node* fold_simplify_math(const Node* node) { return quote_single(arena, payload.operands.nodes[0]); // if first operand is zero, invert the second one if (is_zero(payload.operands.nodes[0])) - return prim_op(arena, (PrimOp) {.op = neg_op, .operands = singleton(payload.operands.nodes[1]), .type_arguments = empty(arena)}); + return prim_op(arena, (PrimOp) { .op = neg_op, .operands = singleton(payload.operands.nodes[1]), .type_arguments = empty(arena) }); break; } case mul_op: { diff --git a/src/shady/ir.c b/src/shady/ir.c index e4e5509b0..8a7d8ea95 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -88,7 +88,7 @@ Nodes nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { return nodes; } -Strings strings(IrArena* arena, size_t count, const char* in_strs[]) { +Strings strings(IrArena* arena, size_t count, const char* in_strs[]) { Strings tmp = { .count = count, .strings = in_strs, @@ -207,7 +207,10 @@ Strings import_strings(IrArena* dst_arena, Strings old_strings) { void format_string_internal(const char* str, va_list args, void* uptr, void callback(void*, size_t, char*)); -typedef struct { IrArena* a; const char** result; } InternInArenaPayload; +typedef struct { + IrArena* a; + const char** result; +} InternInArenaPayload; static void intern_in_arena(InternInArenaPayload* uptr, size_t len, char* tmp) { const char* interned = string_impl(uptr->a, len, tmp); @@ -219,7 +222,7 @@ String format_string_interned(IrArena* arena, const char* str, ...) { InternInArenaPayload p = { .a = arena, .result = &result }; va_list args; va_start(args, str); - format_string_internal(str, args, &p, (void(*)(void*, size_t, char*)) intern_in_arena); + format_string_internal(str, args, &p, (void (*)(void*, size_t, char*)) intern_in_arena); va_end(args); return result; } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 34cfdf214..26f806dbe 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -84,6 +84,7 @@ static void add_binding(Context* ctx, bool is_var, String name, const Node* node } static const Node* get_node_address(Context* ctx, const Node* node); + static const Node* get_node_address_safe(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; @@ -127,8 +128,7 @@ static const Node* get_node_address_safe(Context* ctx, const Node* node) { static const Node* get_node_address(Context* ctx, const Node* node) { const Node* got = get_node_address_safe(ctx, node); - if (!got) - error("This doesn't really look like a place expression...") + if (!got) error("This doesn't really look like a place expression...") return got; } @@ -149,7 +149,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, const Node* node) { const Node* alloca = stack_alloc(a, (StackAlloc) { .type = rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; set_value_name(ptr, names.strings[i]); - bind_instruction_outputs_count(bb, store(a, (Store) {ptr, results.nodes[0]}), 0); + bind_instruction_outputs_count(bb, store(a, (Store) { ptr, results.nodes[0] }), 0); add_binding(ctx, true, name, ptr); log_string(DEBUGV, "Bound mutable variable '%s'\n", name); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index bb9fc08cc..0ab1fbd10 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -18,7 +18,7 @@ typedef struct { static size_t count_calls(const UsesMap* map, const Node* bb) { size_t count = 0; const Use* use = get_first_use(map, bb); - for (;use; use = use->next_use) { + for (; use; use = use->next_use) { if (use->user->tag == Jump_TAG) { const Use* jump_use = get_first_use(map, use->user); for (; jump_use; jump_use = jump_use->next_use) { @@ -90,7 +90,7 @@ bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { *m = new_module(a, get_module_name(*m)); bool todo = false; Context ctx = { .todo = &todo }; - ctx.rewriter = create_node_rewriter(src, *m, (RewriteNodeFn) process), + ctx.rewriter = create_node_rewriter(src, *m, (RewriteNodeFn) process); rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); return todo; diff --git a/src/shady/print.c b/src/shady/print.c index 8bb23e57d..c492fc41e 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1139,7 +1139,7 @@ static void print_mem(PrinterCtx* ctx, const Node* mem) { case Mem_MemAndValue_TAG: return print_mem(ctx, mem->payload.mem_and_value.mem); default: { assert(is_instruction(mem)); - visit_node_operands(&pv, 0, mem); + visit_node_operands((Visitor*) &pv, 0, mem); return; } } @@ -1165,8 +1165,6 @@ static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op) void print_node_operand(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, const Node* op) { print_operand_name_helper(ctx, name); print_operand_helper(ctx, op_class, op); - // print(p, " '%s': ", name); - // print_node(p, op, config); } void print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, Nodes ops) { @@ -1180,24 +1178,6 @@ void print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, NodeCl print(ctx->printer, "]"); } -void print_node_operand_const_Node_(PrinterCtx* ctx, const Node* n, String name, const Node* op) { - print_operand_name_helper(ctx, name); - print_operand_helper(ctx, 0, op); -} - -void print_node_operand_Nodes_(PrinterCtx* ctx, const Node* n, String name, Nodes* op) { - if (op) { - print_node_operand_list(ctx, n, name, 0, *op); - } else { - print_operand_name_helper(ctx, name); - print(ctx->printer, "null"); - } -} - -void print_node_operand_Nodes(PrinterCtx* ctx, const Node* n, String name, Nodes op) { - print_node_operand_list(ctx, n, name, 0, op); -} - void print_node_operand_AddressSpace(PrinterCtx* ctx, const Node* n, String name, AddressSpace as) { print_operand_name_helper(ctx, name); print(ctx->printer, "%s", get_address_space_name(as)); @@ -1267,9 +1247,4 @@ void print_node_operand_bool(PrinterCtx* ctx, const Node* n, String name, bool b print(ctx->printer, "false"); } -void print_node_operand_unsigned(PrinterCtx* ctx, const Node* n, String name, unsigned u) { - print_operand_name_helper(ctx, name); - print(ctx->printer, "%u", u); -} - #include "print_generated.c" diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index c7d995c69..6dddde003 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -52,15 +52,6 @@ Rewriter create_importer(Module* src, Module* dst) { return create_node_rewriter(src, dst, recreate_node_identity); } -Module* rebuild_module(Module* src) { - IrArena* a = get_module_arena(src); - Module* dst = new_module(a, get_module_name(src)); - Rewriter r = create_importer(src, dst); - rewrite_module(&r); - destroy_rewriter(&r); - return dst; -} - Rewriter create_children_rewriter(Rewriter* parent) { Rewriter r = *parent; r.map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); @@ -227,10 +218,6 @@ void register_processed_list(Rewriter* rewriter, Nodes old, Nodes new) { register_processed(rewriter, old.nodes[i], new.nodes[i]); } -void clear_processed_non_decls(Rewriter* rewriter) { - clear_dict(rewriter->map); -} - KeyHash hash_node(Node**); bool compare_node(Node**, Node**); diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index 42c511e5a..f8580dbe9 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -46,8 +46,6 @@ Rewriter create_rewriter_base(Module* src, Module* dst); Rewriter create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn); Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn); Rewriter create_importer(Module* src, Module* dst); -Module* rebuild_module(Module*); -Rewriter create_substituter(Module* arena); Rewriter create_children_rewriter(Rewriter* parent); void destroy_rewriter(Rewriter*); @@ -74,7 +72,6 @@ const Node* search_processed(const Rewriter*, const Node*); const Node* find_processed(const Rewriter*, const Node*); void register_processed(Rewriter*, const Node*, const Node*); void register_processed_list(Rewriter*, Nodes, Nodes); -void clear_processed_non_decls(Rewriter*); void dump_rewriter_map(Rewriter*); diff --git a/src/shady/type.c b/src/shady/type.c index d57e41cbe..1739a6a52 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -172,10 +172,8 @@ bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { case AsInput: case AsOutput: case AsFunction: - case AsPrivate: - return !arena->config.is_simt; - default: - return true; + case AsPrivate: return !arena->config.is_simt; + default: return true; } } @@ -193,25 +191,22 @@ String name_type_safe(IrArena* arena, const Type* t) { case Type_MaskType_TAG: return "mask_t"; case Type_JoinPointType_TAG: return "join_type_t"; case Type_NoRet_TAG: return "no_ret"; - case Type_Int_TAG: + case Type_Int_TAG: { if (t->payload.int_type.is_signed) - return format_string_arena(arena->arena, "i%s", ((String[]) {"8", "16", "32", "64" })[t->payload.int_type.width]); + return format_string_arena(arena->arena, "i%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); else - return format_string_arena(arena->arena, "u%s", ((String[]) {"8", "16", "32", "64" })[t->payload.int_type.width]); - case Type_Float_TAG: - return format_string_arena(arena->arena, "f%s", ((String[]) {"16", "32", "64" })[t->payload.float_type.width]); + return format_string_arena(arena->arena, "u%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); + } + case Type_Float_TAG: return format_string_arena(arena->arena, "f%s", ((String[]) { "16", "32", "64" })[t->payload.float_type.width]); case Type_Bool_TAG: return "bool"; - default: - break; case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; + default: break; } return unique_name(arena, node_tags[t->tag]); } /// Is this a type that a value in the language can have ? bool is_value_type(const Type* type) { - //if (type->tag == RecordType_TAG && type->payload.record_type.special == MultipleReturn) - // return true; if (type->tag != QualifiedType_TAG) return false; return is_data_type(get_unqualified_type(type)); @@ -967,7 +962,6 @@ const Type* check_type_if_instr(IrArena* arena, If if_instr) { assert(if_instr.if_false); check_arguments_types_against_parameters_helper(get_param_types(arena, get_abstraction_params(if_instr.tail)), add_qualifiers(arena, if_instr.yield_types, false)); - //return wrap_multiple_yield_types(arena, add_qualifiers(arena, if_instr.yield_types, false)); return noret_type(arena); } diff --git a/src/shady/type.h b/src/shady/type.h index 9235075a7..29384d4e4 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -69,7 +69,6 @@ size_t deconstruct_maybe_packed_type(const Type**); // Pointer type helpers const Type* get_pointer_type_element(const Type*); -AddressSpace get_pointer_type_address_space(const Type*); AddressSpace deconstruct_pointer_type(const Type**); // Nominal type helpers diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 720f33998..c21638ea7 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -5,11 +5,6 @@ #include -bool is_arrow_type(const Node* node) { - NodeTag tag = node->tag; - return tag == FnType_TAG || tag == BBType_TAG || tag == LamType_TAG; -} - const Type* get_pointee_type(IrArena* arena, const Type* type) { bool qualified = false, uniform = false; if (is_value_type(type)) { @@ -20,8 +15,6 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { assert(type->tag == PtrType_TAG); uniform &= is_addr_space_uniform(arena, type->payload.ptr_type.address_space); type = type->payload.ptr_type.pointed_type; - // while (type->tag == ArrType_TAG && !type->payload.arr_type.size) - // type = type->payload.arr_type.element_type; if (qualified) type = qualified_type(arena, (QualifiedType) { @@ -196,11 +189,6 @@ const Type* get_pointer_type_element(const Type* type) { return t; } -AddressSpace get_pointer_type_address_space(const Type* type) { - const Type* t = type; - return deconstruct_pointer_type(&t); -} - AddressSpace deconstruct_pointer_type(const Type** type) { const Type* t = *type; assert(t->tag == PtrType_TAG); @@ -263,7 +251,7 @@ Nodes get_composite_type_element_types(const Type* type) { const Node* get_fill_type_element_type(const Type* composite_t) { switch (composite_t->tag) { - case ArrType_TAG: return composite_t->payload.arr_type.element_type; + case ArrType_TAG: return composite_t->payload.arr_type.element_type; case PackType_TAG: return composite_t->payload.pack_type.element_type; default: error("fill values need to be either array or pack types") } @@ -271,7 +259,7 @@ const Node* get_fill_type_element_type(const Type* composite_t) { const Node* get_fill_type_size(const Type* composite_t) { switch (composite_t->tag) { - case ArrType_TAG: return composite_t->payload.arr_type.size; + case ArrType_TAG: return composite_t->payload.arr_type.size; case PackType_TAG: return int32_literal(composite_t->arena, composite_t->payload.pack_type.width); default: error("fill values need to be either array or pack types") } diff --git a/src/shady/visit.c b/src/shady/visit.c index 9ed015ab5..a226ffec5 100644 --- a/src/shady/visit.c +++ b/src/shady/visit.c @@ -13,7 +13,7 @@ void visit_node(Visitor* visitor, const Node* node) { void visit_nodes(Visitor* visitor, Nodes nodes) { for (size_t i = 0; i < nodes.count; i++) { - visit_node(visitor, nodes.nodes[i]); + visit_node(visitor, nodes.nodes[i]); } } diff --git a/src/shady/visit.h b/src/shady/visit.h index 504de99ce..1caf7c1f5 100644 --- a/src/shady/visit.h +++ b/src/shady/visit.h @@ -8,8 +8,8 @@ typedef void (*VisitNodeFn)(Visitor*, const Node*); typedef void (*VisitOpFn)(Visitor*, NodeClass, String, const Node*); struct Visitor_ { - VisitNodeFn visit_node_fn; - VisitOpFn visit_op_fn; + VisitNodeFn visit_node_fn; + VisitOpFn visit_op_fn; }; void visit_node_operands(Visitor*, NodeClass exclude, const Node*); From 7e48e7b41e0e9c4178bc1aafe1c8b86b8b28310f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 17:01:22 +0200 Subject: [PATCH 429/693] fix demote_alloca forgetting mem --- src/shady/passes/opt_demote_alloca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index a67d470de..9e8ba3fbd 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -167,7 +167,7 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t } if (!k->non_logical_use && get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { ctx->todo |= true; - const Node* new = local_alloc(a, (LocalAlloc) {rewrite_node(r, old_type )}); + const Node* new = local_alloc(a, (LocalAlloc) { rewrite_node(r, old_type), .mem = rewrite_node(r, old->tag == StackAlloc_TAG ? old->payload.stack_alloc.mem : old->payload.local_alloc.mem) }); k->new = new; return new; } From 1b1a1664f3f152b978e18b2f26b8f4fea678300d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 8 Aug 2024 17:09:22 +0200 Subject: [PATCH 430/693] dead load removal --- src/shady/passes/cleanup.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 0ab1fbd10..2dc3b405f 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -32,15 +32,13 @@ static size_t count_calls(const UsesMap* map, const Node* bb) { return count; } -static bool has_side_effects(const Node* instr) { - bool side_effects = true; - if (instr->tag == PrimOp_TAG) - side_effects = has_primop_got_side_effects(instr->payload.prim_op.op); - switch (instr->tag) { - case Load_TAG: return false; - default: break; +static bool is_used_as_value(const UsesMap* map, const Node* instr) { + const Use* use = get_first_use(map, instr); + for (; use; use = use->next_use) { + if (use->operand_class == NcValue) + return true; } - return side_effects; + return false; } const Node* process(Context* ctx, const Node* old) { @@ -75,6 +73,11 @@ const Node* process(Context* ctx, const Node* old) { } break; } + case Load_TAG: { + if (!is_used_as_value(ctx->map, old)) + return rewrite_node(r, old->payload.load.mem); + break; + } default: break; } From 855fee1bb80b82e4d49e6aec217fa93bbdd56e46 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 9 Aug 2024 09:15:06 +0200 Subject: [PATCH 431/693] fix memory corruption when folding operands within a list --- src/shady/generator_constructors.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 9080cb51d..5d0a697b5 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -35,9 +35,11 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { growy_append_formatted(g, "\t\t{\n"); String extra = ""; if (list) { - growy_append_formatted(g, "\t\t\tNodes ops = node->payload.%s.%s;\n", snake_name, op_name); - growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < ops.count; i++) {\n"); - growy_append_formatted(g, "\t\t\tconst Node** pop = &ops.nodes[i];\n"); + growy_append_formatted(g, "\t\t\tsize_t ops_count = node->payload.%s.%s.count;\n", snake_name, op_name); + growy_append_formatted(g, "\t\t\tLARRAY(const Node*, ops, ops_count);\n"); + growy_append_formatted(g, "\t\t\tmemcpy(ops, node->payload.%s.%s.nodes, sizeof(const Node*) * ops_count);\n", snake_name, op_name); + growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < ops_count; i++) {\n"); + growy_append_formatted(g, "\t\t\tconst Node** pop = &ops[i];\n"); extra = "\t"; } if (!list) @@ -55,8 +57,10 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { growy_append_formatted(g, "%s\t\t\t\terror_print(\"Invalid '%s' operand for node '%s', expected a %s\");\n", extra, op_name, name, class); growy_append_formatted(g, "%s\t\t\t\terror_die();\n", extra); growy_append_formatted(g, "%s\t\t\t}\n", extra); - if (list) + if (list) { growy_append_formatted(g, "\t\t\t}\n"); + growy_append_formatted(g, "\t\t\tnode->payload.%s.%s = nodes(arena, ops_count, ops);\n", snake_name, op_name); + } free((void*) cap); growy_append_formatted(g, "\t\t}\n"); } From a313ae06edf11cbc08841157a59c766ff8da0a71 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 9 Aug 2024 09:23:36 +0200 Subject: [PATCH 432/693] dict: add some sanity/validation checks --- src/common/dict.c | 68 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/src/common/dict.c b/src/common/dict.c index 2c83d686f..bf8afc622 100644 --- a/src/common/dict.c +++ b/src/common/dict.c @@ -1,12 +1,13 @@ #include "dict.h" +#include "log.h" + #include #include #include #include inline static size_t div_roundup(size_t a, size_t b) { - //return (a + b - 1) / b; if (a % b == 0) return a / b; else @@ -27,6 +28,9 @@ static size_t init_size = 32; struct BucketTag { bool is_present; bool is_thombstone; +#ifdef GOBLIB_DICT_DEBUG + KeyHash cached_hash; +#endif }; struct Dict { @@ -46,6 +50,45 @@ struct Dict { void* alloc; }; +#ifdef GOBLIB_DICT_DEBUG +static size_t dict_count_sanity(struct Dict* dict) { + size_t i = 0; + size_t count = 0; + while (dict_iter(dict, &i, NULL, NULL)) { + count++; + } + return count; +} + +static void validate_hashmap_integrity(const struct Dict* dict) { + const size_t alloc_base = (size_t) dict->alloc; + for (size_t i = 0; i < dict->size; i++) { + size_t bucket = alloc_base + i * dict->bucket_entry_size; + void* in_dict_key = (void*) bucket; + struct BucketTag tag = *(struct BucketTag*) (void*) (bucket + dict->tag_offset); + if (tag.is_present) { + KeyHash fresh_hash = dict->hash_fn(in_dict_key); + if (fresh_hash != tag.cached_hash) { + error("hash changed under our noses"); + } + } + } +} + +static void dump_dict_keys(struct Dict* dict) { + const size_t alloc_base = (size_t) dict->alloc; + for (size_t i = 0; i < dict->size; i++) { + size_t bucket = alloc_base + i * dict->bucket_entry_size; + void* in_dict_key = (void*) bucket; + struct BucketTag tag = *(struct BucketTag*) (void*) (bucket + dict->tag_offset); + if (tag.is_present) { + KeyHash hash = dict->hash_fn(in_dict_key); + printf("@i = %zu, hash = %d\n", i, hash); + } + } +} +#endif + struct Dict* new_dict_impl(size_t key_size, size_t value_size, size_t key_align, size_t value_align, KeyHash (*hash_fn)(void*), bool (*cmp_fn) (void*, void*)) { // offset of key is obviously zero size_t value_offset = align_offset(key_size, value_align); @@ -100,6 +143,10 @@ struct Dict* clone_dict(struct Dict* source) { .alloc = malloc(source->bucket_entry_size * source->size) }; memcpy(dict->alloc, source->alloc, source->bucket_entry_size * source->size); +#ifdef GOBLIB_DICT_DEBUG + validate_hashmap_integrity(dict); + validate_hashmap_integrity(source); +#endif return dict; } @@ -119,6 +166,9 @@ size_t entries_count_dict(struct Dict* dict) { } void* find_key_dict_impl(struct Dict* dict, void* key) { +#ifdef GOBLIB_DICT_DEBUG_PARANOID + validate_hashmap_integrity(dict); +#endif KeyHash hash = dict->hash_fn(key); size_t pos = hash % dict->size; const size_t init_pos = pos; @@ -188,20 +238,20 @@ void* insert_dict_and_get_value_impl(struct Dict* dict, void* key, void* value) static void rehash(struct Dict* dict, void* old_alloc, size_t old_size) { const size_t alloc_base = (size_t) old_alloc; // Go over all the old entries and add them back - for(size_t pos = 0; pos < old_size; pos++) { + for (size_t pos = 0; pos < old_size; pos++) { size_t bucket = alloc_base + pos * dict->bucket_entry_size; struct BucketTag* tag = (struct BucketTag*) (void*) (bucket + dict->tag_offset); if (tag->is_present) { void* key = (void*) bucket; void* value = (void*) (bucket + dict->value_offset); - insert_dict_and_get_result_impl(dict, key, value); + bool fresh = insert_dict_and_get_result_impl(dict, key, value); + assert(fresh); } } } static void grow_and_rehash(struct Dict* dict) { - //printf("grow_rehash\n"); size_t old_entries_count = entries_count_dict(dict); void* old_alloc = dict->alloc; @@ -215,6 +265,9 @@ static void grow_and_rehash(struct Dict* dict) { memset(dict->alloc, 0, dict->size * dict->bucket_entry_size); rehash(dict, old_alloc, old_size); +#ifdef GOBLIB_DICT_DEBUG + assert(dict_count_sanity(dict) == entries_count_dict(dict)); +#endif assert(old_entries_count == entries_count_dict(dict)); free(old_alloc); @@ -290,11 +343,18 @@ bool insert_dict_impl(struct Dict* dict, void* key, void* value, void** out_ptr) dst_tag->is_present = true; dst_tag->is_thombstone = false; +#ifdef GOBLIB_DICT_DEBUG + dst_tag->cached_hash = hash; +#endif memcpy(in_dict_key, key, dict->key_size); if (dict->value_size) memcpy(in_dict_value, value, dict->value_size); *out_ptr = in_dict_key; +#ifdef GOBLIB_DICT_DEBUG + validate_hashmap_integrity(dict); +#endif + return mode == Inserting; } From 36cfcd0a0e6fecc77f1f72524ecb41a13428fbd1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 9 Aug 2024 10:10:11 +0200 Subject: [PATCH 433/693] use __attribute__((designated_init)) on node payloads --- include/shady/ir.h | 6 ++++++ src/shady/api/generator_grammar.c | 2 +- src/shady/passes/lower_logical_pointers.c | 3 +-- src/shady/transform/ir_gen_helpers.c | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 7d354ad0d..d1192f89a 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -119,6 +119,12 @@ typedef enum { DecorateBlock } RecordSpecialFlag; +#ifdef GCC +#define SHADY_DESIGNATED_INIT __attribute__((designated_init)) +#else +#define SHADY_DESIGNATED_INIT +#endif + // see primops.json #include "primops_generated.h" diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index f36253460..fb8b121b1 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -41,7 +41,7 @@ static void generate_node_payloads(Growy* g, json_object* src, json_object* node if (ops) { assert(json_object_get_type(ops) == json_type_array); add_comments(g, "", json_object_object_get(node, "description")); - growy_append_formatted(g, "typedef struct {\n"); + growy_append_formatted(g, "SHADY_DESIGNATED_INIT typedef struct {\n"); for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index f9a7419f5..de15534d1 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -108,8 +108,7 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); - return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { ptr, rewrite_node(r, payload.value) })); - return store(a, (Store) { .ptr = ptr, .value = rewrite_node(r, payload.value), .mem = rewrite_node(r, payload.mem) }); + return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { ptr, rewrite_node(r, payload.value), .mem = rewrite_node(r, payload.mem) })); } case GlobalVariable_TAG: { AddressSpace as = old->payload.global_variable.address_space; diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 5fbc249d9..60eb83a0e 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -131,7 +131,7 @@ void gen_comment(BodyBuilder* bb, String str) { } void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { - bind_instruction(bb, debug_printf(bb->arena, (DebugPrintf) { pattern, args, .mem = bb_mem(bb) })); + bind_instruction(bb, debug_printf(bb->arena, (DebugPrintf) { .string = pattern, .args = args, .mem = bb_mem(bb) })); } const Node* get_builtin(Module* m, Builtin b) { From 49618b1bb9cb1aa0cbe411ef9363debb1715e0e5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 9 Aug 2024 10:12:12 +0200 Subject: [PATCH 434/693] move 'mem' operand to be the first where it exists --- include/shady/grammar.json | 67 +++++++++++++++++++------------------- include/shady/primops.json | 40 +++++++++++------------ 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 7ccfd80d2..ddd34427b 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -379,9 +379,9 @@ "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ + { "name": "mem", "class": "mem" }, { "name": "callee", "class": "value" }, { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } ] }, { @@ -389,8 +389,8 @@ "class": ["value", "mem"], "description": "Associate a value with a mem object, this allows adding side effects to a value", "ops": [ - { "name": "value", "class": "value" }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "value", "class": "value" } ] }, { @@ -398,12 +398,12 @@ "snake_name": "if_instr", "class": ["terminator", "structured_construct"], "ops": [ + { "name": "mem", "class": "mem" }, { "name": "yield_types", "class": "type", "list": true }, { "name": "condition", "class": "value" }, { "name": "if_true", "class": "basic_block" }, { "name": "if_false", "class": "basic_block", "nullable": true }, - { "name": "tail", "class": "basic_block" }, - { "name": "mem", "class": "mem" } + { "name": "tail", "class": "basic_block" } ] }, { @@ -411,13 +411,13 @@ "snake_name": "match_instr", "class": ["terminator", "structured_construct"], "ops": [ + { "name": "mem", "class": "mem" }, { "name": "yield_types", "class": "type", "list": true }, { "name": "inspect", "class": "value" }, { "name": "literals", "class": "value", "list": true }, { "name": "cases", "class": "basic_block", "list": true }, { "name": "default_case", "class": "basic_block" }, - { "name": "tail", "class": "basic_block" }, - { "name": "mem", "class": "mem" } + { "name": "tail", "class": "basic_block" } ] }, { @@ -425,29 +425,29 @@ "snake_name": "loop_instr", "class": ["terminator", "structured_construct"], "ops": [ + { "name": "mem", "class": "mem" }, { "name": "yield_types", "class": "type", "list": true }, { "name": "body", "class": "basic_block" }, { "name": "initial_args", "class": "value", "list": true }, - { "name": "tail", "class": "basic_block" }, - { "name": "mem", "class": "mem" } + { "name": "tail", "class": "basic_block" } ] }, { "name": "Control", "class": ["terminator", "structured_construct"], "ops": [ + { "name": "mem", "class": "mem" }, { "name": "yield_types", "class": "type", "list": true }, { "name": "inside", "class": "basic_block" }, - { "name": "tail", "class": "basic_block" }, - { "name": "mem", "class": "mem" } + { "name": "tail", "class": "basic_block" } ] }, { "name": "Comment", "class": ["instruction", "mem"], "ops": [ - { "name": "string", "class": "string" }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "string", "class": "string" } ] }, { @@ -457,20 +457,20 @@ "front-end-only": true, "type": false, "ops": [ + { "name": "mem", "class": "mem" }, { "name": "value", "class": "value" }, { "name": "mutable", "type": "bool" }, { "name": "names", "class": "string", "list": true }, - { "name": "types", "class": "type", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "types", "class": "type", "list": true } ] }, { "name": "TailCall", "class": "terminator", "ops": [ + { "name": "mem", "class": "mem" }, { "name": "target", "class": "value" }, - { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "args", "class": "value", "list": true } ] }, { @@ -490,10 +490,10 @@ "Branch alternatives are made out of Jump terminators" ], "ops": [ + { "name": "mem", "class": "mem" }, { "name": "condition", "class": "value" }, { "name": "true_jump", "class": "jump" }, - { "name": "false_jump", "class": "jump" }, - { "name": "mem", "class": "mem" } + { "name": "false_jump", "class": "jump" } ] }, { @@ -502,11 +502,11 @@ "class": "terminator", "description": "N-way variant of Branch. See Branch.", "ops": [ + { "name": "mem", "class": "mem" }, { "name": "switch_value", "class": "value" }, { "name": "case_values", "class": "value", "list": true }, { "name": "case_jumps", "class": "jump", "list": true }, - { "name": "default_jump", "class": "jump" }, - { "name": "mem", "class": "mem" } + { "name": "default_jump", "class": "jump" } ] }, { @@ -518,9 +518,9 @@ "If @p is_indirect is set, the target must be a function pointer. Otherwise, the target must be a function directly." ], "ops": [ + { "name": "mem", "class": "mem" }, { "name": "join_point", "class": "value" }, - { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "args", "class": "value", "list": true } ] }, { @@ -528,8 +528,8 @@ "class": "terminator", "nominal": true, "ops": [ - { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "args", "class": "value", "list": true } ] }, { @@ -537,8 +537,8 @@ "class": "terminator", "nominal": true, "ops": [ - { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "args", "class": "value", "list": true } ] }, { @@ -546,8 +546,8 @@ "class": "terminator", "nominal": true, "ops": [ - { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "args", "class": "value", "list": true } ] }, { @@ -556,8 +556,8 @@ "class": "terminator", "nominal": true, "ops": [ - { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "args", "class": "value", "list": true } ] }, { @@ -685,9 +685,10 @@ "description": "Unbound identifier, obtained by parsing a file", "type": false, "front-end-only": true, + "class": ["value", "mem"], "ops": [ - { "name": "name", "type": "String" }, - { "name": "mem", "class": "mem", "nullable": true } + { "name": "mem", "class": "mem", "nullable": true }, + { "name": "name", "type": "String" } ] }, { diff --git a/include/shady/primops.json b/include/shady/primops.json index 08477fb85..48f2c072d 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -272,8 +272,8 @@ "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ - { "name": "type", "class": "type" }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "type", "class": "type" } ] }, { @@ -281,8 +281,8 @@ "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ - { "name": "type", "class": "type" }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "type", "class": "type" } ] }, { @@ -290,8 +290,8 @@ "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ - { "name": "ptr", "class": "value" }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "ptr", "class": "value" } ] }, { @@ -299,9 +299,9 @@ "class": ["instruction", "mem"], "nominal": true, "ops": [ + { "name": "mem", "class": "mem" }, { "name": "ptr", "class": "value" }, - { "name": "value", "class": "value" }, - { "name": "mem", "class": "mem" } + { "name": "value", "class": "value" } ] }, { @@ -318,10 +318,10 @@ "class": ["instruction", "mem"], "nominal": true, "ops": [ + { "name": "mem", "class": "mem" }, { "name": "dst", "class": "value" }, { "name": "src", "class": "value" }, - { "name": "count", "class": "value" }, - { "name": "mem", "class": "mem" } + { "name": "count", "class": "value" } ] }, { @@ -329,10 +329,10 @@ "class": ["instruction", "mem"], "nominal": true, "ops": [ + { "name": "mem", "class": "mem" }, { "name": "dst", "class": "value" }, { "name": "src", "class": "value" }, - { "name": "count", "class": "value" }, - { "name": "mem", "class": "mem" } + { "name": "count", "class": "value" } ] }, { @@ -340,8 +340,8 @@ "class": ["instruction", "mem", "mem"], "nominal": true, "ops": [ - { "name": "value", "class": "value" }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "value", "class": "value" } ] }, { @@ -349,8 +349,8 @@ "class": ["instruction", "value", "mem"], "nominal": true, "ops": [ - { "name": "type", "class": "type" }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "type", "class": "type" } ] }, { @@ -366,8 +366,8 @@ "class": ["instruction", "mem"], "nominal": true, "ops": [ - { "name": "value", "class": "value" }, - { "name": "mem", "class": "mem" } + { "name": "mem", "class": "mem" }, + { "name": "value", "class": "value" } ] }, { @@ -383,9 +383,9 @@ "class": ["instruction", "mem"], "nominal": true, "ops": [ + { "name": "mem", "class": "mem" }, { "name": "string", "class": "string" }, - { "name": "args", "class": "value", "list": true }, - { "name": "mem", "class": "mem" } + { "name": "args", "class": "value", "list": true } ] } ] From 5380fd1b076b775474a52e7f7bd9b1f415d44a42 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 9 Aug 2024 12:00:07 +0200 Subject: [PATCH 435/693] fix instances of designated initializers not being used properly --- include/shady/ir.h | 2 +- src/frontend/llvm/l2s_instr.c | 10 +++++----- src/frontend/slim/parser.c | 2 +- src/frontend/spirv/s2s.c | 10 +++++----- src/shady/api/generator_grammar.c | 2 +- src/shady/generator_rewrite.c | 3 ++- src/shady/node.c | 2 +- src/shady/passes/bind.c | 6 +++--- src/shady/passes/infer.c | 10 +++++----- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_logical_pointers.c | 4 ++-- src/shady/passes/lower_physical_ptrs.c | 5 +++-- src/shady/passes/opt_demote_alloca.c | 4 ++-- src/shady/passes/opt_restructure.c | 2 +- src/shady/passes/simt2d.c | 2 +- src/shady/transform/ir_gen_helpers.c | 4 ++-- 16 files changed, 36 insertions(+), 34 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index d1192f89a..220246f60 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -119,7 +119,7 @@ typedef enum { DecorateBlock } RecordSpecialFlag; -#ifdef GCC +#ifdef __GNUC__ #define SHADY_DESIGNATED_INIT __attribute__((designated_init)) #else #define SHADY_DESIGNATED_INIT diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 33b7fd178..94391e9e7 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -259,7 +259,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, assert(t->tag == PtrType_TAG); const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivate }); - r = first(bind_instruction_outputs_count(b, stack_alloc(a, (StackAlloc) { allocated_t }), 1)); + r = first(bind_instruction_outputs_count(b, stack_alloc(a, (StackAlloc) { .type = allocated_t, .mem = bb_mem(b) }), 1)); if (UNTYPED_POINTERS) { const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivate }); r = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), 1)); @@ -277,7 +277,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } - r = load(a, (Load) { ptr }); + r = load(a, (Load) { .ptr = ptr, .mem = bb_mem(b) }); break; } case LLVMStore: { @@ -291,7 +291,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } - r = store(a, (Store) { ptr, ops.nodes[0] }); + r = store(a, (Store) { .ptr = ptr, .value = ops.nodes[0], .mem = bb_mem(b) }); break; } case LLVMGetElementPtr: { @@ -304,7 +304,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } ops = change_node_at_index(a, ops, 0, ptr); - r = lea(a, (Lea) { ops.nodes[0], ops.nodes[1], nodes(a, ops.count - 2, &ops.nodes[2])}); + r = lea(a, (Lea) { .ptr = ops.nodes[0], .offset = ops.nodes[1], .indices = nodes(a, ops.count - 2, &ops.nodes[2])}); if (UNTYPED_POINTERS) { const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); @@ -598,7 +598,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LARRAY(const Node*, processed_ops, ops.count); for (i = 0; i < num_args; i++) { if (decoded[i].is_byval) - processed_ops[i] = first(bind_instruction_outputs_count(b, load(a, (Load) { ops.nodes[i] }), 1)); + processed_ops[i] = first(bind_instruction_outputs_count(b, load(a, (Load) { .ptr = ops.nodes[i], .mem = bb_mem(b) }), 1)); else processed_ops[i] = ops.nodes[i]; } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index cf66bcebc..abdcf0a99 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -890,7 +890,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { next_token(tokenizer); expect(accept_token(ctx, lpar_tok)); expect(accept_token(ctx, rpar_tok)); - return unreachable(arena, (Unreachable) { bb_mem(bb) }); + return unreachable(arena, (Unreachable) { .mem = bb_mem(bb) }); } default: break; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 47efc6055..b10b9dedd 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -742,13 +742,13 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { assert(is_data_type(contents_t)); if (parser->fun) { - const Node* ptr = first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { contents_t }), 1)); + const Node* ptr = first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { .type = contents_t, .mem = bb_mem(parser->current_block.builder) }), 1)); parser->defs[result].type = Value; parser->defs[result].node = ptr; if (size == 5) - bind_instruction_outputs_count(parser->current_block.builder, store(parser->arena, (Store) { ptr, get_def_ssa_value(parser, instruction[4]) }), 1); + bind_instruction_outputs_count(parser->current_block.builder, store(parser->arena, (Store) { .ptr = ptr, .value = get_def_ssa_value(parser, instruction[4]), .mem = bb_mem(parser->current_block.builder) }), 1); } else { Nodes annotations = empty(parser->arena); SpvDeco* builtin = find_decoration(parser, result, -1, SpvDecorationBuiltIn); @@ -786,7 +786,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { if (entry_point_type) { annotations = append_nodes(parser->arena, annotations, annotation_value(parser->arena, (AnnotationValue) { .name = "EntryPoint", - .value = string_lit(parser->arena, (StringLiteral) { entry_point_type->payload.str }) + .value = string_lit(parser->arena, (StringLiteral) { .string = entry_point_type->payload.str }) })); SpvDeco* entry_point_name = find_decoration(parser, result, -1, ShdDecorationEntryPointName); @@ -1071,13 +1071,13 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpLoad: { const Type* src = get_def_ssa_value(parser, instruction[3]); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, load(a, (Load) { src }), 1)); + parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, load(a, (Load) { .ptr = src, .mem = bb_mem(parser->current_block.builder) }), 1)); break; } case SpvOpStore: { const Type* ptr = get_def_ssa_value(parser, instruction[1]); const Type* value = get_def_ssa_value(parser, instruction[2]); - bind_instruction_outputs_count(parser->current_block.builder, store(a, (Store) { ptr, value }), 0); + bind_instruction_outputs_count(parser->current_block.builder, store(a, (Store) { .ptr = ptr, .value = value, .mem = bb_mem(parser->current_block.builder) }), 0); break; } case SpvOpCopyMemory: diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index fb8b121b1..0a7c4598b 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -41,7 +41,7 @@ static void generate_node_payloads(Growy* g, json_object* src, json_object* node if (ops) { assert(json_object_get_type(ops) == json_type_array); add_comments(g, "", json_object_object_get(node, "description")); - growy_append_formatted(g, "SHADY_DESIGNATED_INIT typedef struct {\n"); + growy_append_formatted(g, "typedef struct SHADY_DESIGNATED_INIT {\n"); for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); diff --git a/src/shady/generator_rewrite.c b/src/shady/generator_rewrite.c index e01b22d7e..c0ce02051 100644 --- a/src/shady/generator_rewrite.c +++ b/src/shady/generator_rewrite.c @@ -38,7 +38,8 @@ static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { if (ops) { assert(json_object_get_type(ops) == json_type_array); growy_append_formatted(g, "\t\t\t%s old_payload = node->payload.%s;\n", name, snake_name); - growy_append_formatted(g, "\t\t\t%s payload = { 0 };\n", name, snake_name); + growy_append_formatted(g, "\t\t\t%s payload;\n", name); + growy_append_formatted(g, "\t\t\tmemset(&payload, 0, sizeof(payload));\n"); for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); diff --git a/src/shady/node.c b/src/shady/node.c index 7628ad821..ecfa329be 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -271,7 +271,7 @@ const char* get_string_literal(IrArena* arena, const Node* node) { } const Node* get_abstraction_mem(const Node* abs) { - return abs_mem(abs->arena, (AbsMem) { abs }); + return abs_mem(abs->arena, (AbsMem) { .abs = abs }); } String get_abstraction_name(const Node* abs) { diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 26f806dbe..625faa5e0 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -109,7 +109,7 @@ static const Node* get_node_address_safe(Context* ctx, const Node* node) { const Node* index = rewrite_node(&ctx->rewriter, payload.operands.nodes[1]); return mem_and_value(a, (MemAndValue) { .mem = rewrite_node(r, payload.mem), - .value = lea(a, (Lea) { .ptr = src_ptr, .offset = int32_literal(a, 0), singleton(index) }), + .value = lea(a, (Lea) { .ptr = src_ptr, .offset = int32_literal(a, 0), .indices = singleton(index) }), }); } else if (payload.opcode == SlimOpDereference) { assert(payload.operands.count == 1); @@ -149,7 +149,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, const Node* node) { const Node* alloca = stack_alloc(a, (StackAlloc) { .type = rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; set_value_name(ptr, names.strings[i]); - bind_instruction_outputs_count(bb, store(a, (Store) { ptr, results.nodes[0] }), 0); + bind_instruction_outputs_count(bb, store(a, (Store) { .ptr = ptr, .value = results.nodes[0], .mem = bb_mem(bb) }), 0); add_binding(ctx, true, name, ptr); log_string(DEBUGV, "Bound mutable variable '%s'\n", name); @@ -271,7 +271,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { const Node* target_ptr = get_node_address(ctx, payload.operands.nodes[0]); assert(target_ptr); const Node* value = rewrite_node(r, payload.operands.nodes[1]); - return store(a, (Store) { target_ptr, value, .mem = rewrite_node(r, payload.mem) }); + return store(a, (Store) { .ptr = target_ptr, .value = value, .mem = rewrite_node(r, payload.mem) }); } case SlimOpAddrOf: { const Node* target_ptr = get_node_address(ctx, payload.operands.nodes[0]); diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 6d0e880d2..1fa5f207d 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -545,10 +545,10 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* const Type* base_datatype = src_ptr; assert(base_datatype->tag == PtrType_TAG); - return lea(a, (Lea) { ptr, offset, indices }); + return lea(a, (Lea) { .ptr = ptr, .offset = offset, .indices = indices }); } case Instruction_Load_TAG: { - return load(a, (Load) { infer(ctx, node->payload.load.ptr, NULL), .mem = infer(ctx, node->payload.load.mem, NULL) }); + return load(a, (Load) { .ptr = infer(ctx, node->payload.load.ptr, NULL), .mem = infer(ctx, node->payload.load.mem, NULL) }); } case Instruction_Store_TAG: { Store payload = node->payload.store; @@ -558,7 +558,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* const Type* element_t = ptr_type->payload.ptr_type.pointed_type; assert(element_t); const Node* value = infer(ctx, payload.value, qualified_type_helper(element_t, false)); - return store(a, (Store) { ptr, value, .mem = infer(ctx, node->payload.store.mem, NULL) }); + return store(a, (Store) { .ptr = ptr, .value = value, .mem = infer(ctx, node->payload.store.mem, NULL) }); } case Instruction_StackAlloc_TAG: { const Type* element_type = node->payload.stack_alloc.type; @@ -566,10 +566,10 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* assert(is_data_type(element_type)); return stack_alloc(a, (StackAlloc) { .type = infer_type(ctx, element_type), .mem = infer(ctx, node->payload.stack_alloc.mem, NULL) }); } - default: return recreate_node_identity(&ctx->rewriter, node); + default: break; case NotAnInstruction: error("not an instruction"); } - SHADY_UNREACHABLE; + return recreate_node_identity(&ctx->rewriter, node); } static const Node* infer_terminator(Context* ctx, const Node* node) { diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 12e9a0ad0..a57d443f6 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -147,7 +147,7 @@ static const Node* process(Context* ctx, const Node* node) { //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); - const Node* lea_instr = lea(a, (Lea) {ctx->base_stack_addr_on_entry, gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)), empty(a) }); + const Node* lea_instr = lea(a, (Lea) { .ptr = ctx->base_stack_addr_on_entry, .offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)), .indices = empty(a) }); const Node* slot = first(bind_instruction_named(bb, lea_instr, (String []) { format_string_arena(a->arena, "stack_slot_%d", found_slot->i) })); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = gen_reinterpret_cast(bb, ptr_t, slot); diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index de15534d1..fbe221395 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -67,7 +67,7 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); - return bind_last_instruction_and_wrap_in_block(bb, lea(a, (Lea) { ptr, rewrite_node(r, payload.offset), rewrite_nodes(r, payload.indices)})); + return bind_last_instruction_and_wrap_in_block(bb, lea(a, (Lea) { .ptr = ptr, .offset = rewrite_node(r, payload.offset), .indices = rewrite_nodes(r, payload.indices)})); } case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; @@ -108,7 +108,7 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); - return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { ptr, rewrite_node(r, payload.value), .mem = rewrite_node(r, payload.mem) })); + return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { .ptr = ptr, .value = rewrite_node(r, payload.value), .mem = rewrite_node(r, payload.mem) })); } case GlobalVariable_TAG: { AddressSpace as = old->payload.global_variable.address_space; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index a7d71f6aa..8202c253c 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -439,8 +439,9 @@ static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, Body assert(old_decl->tag == GlobalVariable_TAG); const Node* old_init = old_decl->payload.global_variable.init; if (old_init) { - const Node* old_store = store(oa, (Store) { ref_decl_helper(oa, old_decl), old_init }); - bind_instruction(bb, rewrite_node(&ctx->rewriter, old_store)); + error("TODO: reimplement") + // const Node* old_store = store(oa, (Store) { .ptr = ref_decl_helper(oa, old_decl), .value = old_init, bb_mem(bb) }); + // bind_instruction(bb, rewrite_node(&ctx->rewriter, old_store)); } } } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 9e8ba3fbd..390ee6c7f 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -161,13 +161,13 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t if (!k->leaks) { if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { ctx->todo |= true; - const Node* new = undef(a, (Undef) {.type = get_unqualified_type(rewrite_node(r, old->type))}); + const Node* new = undef(a, (Undef) { .type = get_unqualified_type(rewrite_node(r, old->type)) }); k->new = new; return new; } if (!k->non_logical_use && get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { ctx->todo |= true; - const Node* new = local_alloc(a, (LocalAlloc) { rewrite_node(r, old_type), .mem = rewrite_node(r, old->tag == StackAlloc_TAG ? old->payload.stack_alloc.mem : old->payload.local_alloc.mem) }); + const Node* new = local_alloc(a, (LocalAlloc) { .type = rewrite_node(r, old_type), .mem = nmem }); k->new = new; return new; } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 9b93478f2..e08d2cd58 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -84,7 +84,7 @@ static DFSStackEntry* encountered_before(Context* ctx, const Node* bb, size_t* p static const Node* make_unreachable_case(IrArena* a) { Node* c = case_(a, empty(a)); - set_abstraction_body(c, unreachable(a, (Unreachable) { get_abstraction_mem(c) })); + set_abstraction_body(c, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(c) })); return c; } diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c index d7eed477e..baf16c332 100644 --- a/src/shady/passes/simt2d.c +++ b/src/shady/passes/simt2d.c @@ -41,7 +41,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* type = rewrite_node(&ctx->rewriter, node->payload.local_alloc.type); LARRAY(const Node*, allocated, ctx->width); for (size_t i = 0; i < ctx->width; i++) { - allocated[i] = first(bind_instruction_named(bb, local_alloc(a, (LocalAlloc) { type }), (String[]) {"allocated"})); + allocated[i] = first(bind_instruction_named(bb, local_alloc(a, (LocalAlloc) { .type = type, .mem = bb_mem(bb) }), (String[]) {"allocated"})); } //return yield_values_and_wrap_in_control(bb, singleton(widen(ctx, allocated))); const Node* result_type = maybe_packed_type_helper(ptr_type(a, (PtrType) { .address_space = AsFunction, .pointed_type = type }), ctx->width); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 60eb83a0e..4743e5220 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -60,7 +60,7 @@ const Node* gen_get_stack_base_addr(BodyBuilder* bb) { } const Node* gen_get_stack_size(BodyBuilder* bb) { - return first(bind_instruction(bb, get_stack_size(bb->arena, (GetStackSize) { bb_mem(bb) }))); + return first(bind_instruction(bb, get_stack_size(bb->arena, (GetStackSize) { .mem = bb_mem(bb) }))); } void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { @@ -115,7 +115,7 @@ void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { } const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { - return first(bind_instruction(bb, lea(bb->arena, (Lea) { base, offset, selectors }))); + return first(bind_instruction(bb, lea(bb->arena, (Lea) { .ptr = base, .offset = offset, .indices = selectors }))); } const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { From 376e7a16fb2c3252dee3a634cc5d35d927cac08a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 9 Aug 2024 12:00:59 +0200 Subject: [PATCH 436/693] fix binding --- include/shady/grammar.json | 2 +- src/frontend/slim/parser.c | 4 +++- src/shady/analysis/cfg.c | 3 ++- src/shady/node_helpers.c | 3 +++ src/shady/passes/bind.c | 9 +++++++-- src/shady/print.c | 2 +- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index ddd34427b..36e2faf98 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -696,7 +696,7 @@ "description": "Turns a pointer into an assignable L-value", "class": ["mem", "value", "instruction"], "ops": [ - { "name": "mem", "class": "mem" }, + { "name": "mem", "class": "mem", "nullable": true }, { "name": "result_t", "class": "type" }, { "name": "set", "class": "string" }, { "name": "opcode", "type": "uint32_t" }, diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index abdcf0a99..84fd13336 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -775,8 +775,10 @@ static const Node* expect_jump(ctxparams, BodyBuilder* bb) { String target = accept_identifier(ctx); expect(target); Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); + const Node* tgt = unbound(arena, (Unbound) { .name = target, .mem = bb_mem(bb) }); + bind_instruction_single(bb, tgt); return jump(arena, (Jump) { - .target = unbound(arena, (Unbound) { .name = target, .mem = bb_mem(bb) }), + .target = tgt, .args = args, .mem = bb_mem(bb) }); diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 3ed1a8f0c..3af3fe5e9 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -131,7 +131,8 @@ static void add_structural_dominance_edge(CfgBuildContext* ctx, CFNode* parent, static void add_jump_edge(CfgBuildContext* ctx, const Node* src, const Node* j) { assert(j->tag == Jump_TAG); const Node* target = j->payload.jump.target; - add_edge(ctx, src, target, JumpEdge); + if (target->tag == BasicBlock_TAG) + add_edge(ctx, src, target, JumpEdge); } #pragma GCC diagnostic error "-Wswitch" diff --git a/src/shady/node_helpers.c b/src/shady/node_helpers.c index 978a4a44f..1045a86b9 100644 --- a/src/shady/node_helpers.c +++ b/src/shady/node_helpers.c @@ -58,6 +58,9 @@ const Node* get_parent_mem(const Node* mem) { case Mem_ExtInstr_TAG: mem = mem->payload.ext_instr.mem; return mem; + case Mem_Unbound_TAG: + mem = mem->payload.unbound.mem; + return mem; } } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 625faa5e0..b5e69795e 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -232,10 +232,15 @@ static const Node* bind_node(Context* ctx, const Node* node) { } case Param_TAG: error("the binders should be handled such that this node is never reached"); case Unbound_TAG: { + const Node* mem = NULL; if (node->payload.unbound.mem) - rewrite_node(r, node->payload.unbound.mem); + mem = rewrite_node(r, node->payload.unbound.mem); Resolved entry = resolve_using_name(ctx, node->payload.unbound.name); - assert(!entry.is_var); + if (entry.is_var) { + return load(a, (Load) { .ptr = entry.node, .mem = mem }); + } else if (mem) { + return mem_and_value(a, (MemAndValue) { .value = entry.node, .mem = mem }); + } return entry.node; } case BasicBlock_TAG: { diff --git a/src/shady/print.c b/src/shady/print.c index c492fc41e..739b266a5 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -303,7 +303,7 @@ static void print_function(PrinterCtx* ctx, const Node* node) { assert(is_function(node)); PrinterCtx sub_ctx = *ctx; - if (node->arena->config.name_bound) { + if (true || node->arena->config.name_bound) { CFG* cfg = build_fn_cfg(node); sub_ctx.cfg = cfg; sub_ctx.scheduler = new_scheduler(cfg); From 50c304bc26880dcaee0903d158b33a377f5f6b4e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 9 Aug 2024 12:01:25 +0200 Subject: [PATCH 437/693] misc. fixes --- src/backend/spirv/emit_spv_instructions.c | 3 ++- src/shady/passes/infer.c | 17 ++++++----------- src/shady/passes/lower_subgroup_vars.c | 2 +- src/shady/passes/opt_demote_alloca.c | 11 ++--------- src/shady/rewrite.c | 1 + 5 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 6e41f5f29..89018c10e 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -250,7 +250,8 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui SpvId local_id; const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); // TODO: very hacky indeed - emit_instruction(emitter, fn_builder, bb_builder, load(emitter->arena, (Load) { b }), 1, &local_id); + // emit_instruction(emitter, fn_builder, bb_builder, load(emitter->arena, (Load) { b }), 1, &local_id); + error("reimplement") result = spvb_group_shuffle(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), scope_subgroup, emit_value(emitter, bb_builder, first(args)), local_id); spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); } else { diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 1fa5f207d..a3b0fa7a3 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -433,7 +433,8 @@ static const Node* infer_indirect_call(Context* ctx, const Node* node, const Nod return call(a, (Call) { .callee = new_callee, - .args = nodes(a, node->payload.call.args.count, new_args) + .args = nodes(a, node->payload.call.args.count, new_args), + .mem = infer(ctx, node->payload.if_instr.mem, NULL), }); } @@ -490,7 +491,8 @@ static const Node* infer_loop(Context* ctx, const Node* node) { .initial_args = nodes(a, old_params.count, new_initial_args), .body = nbody, //.tail = infer_case(ctx, node->payload.loop_instr.tail, qual_yield_types) - .tail = infer(ctx, node->payload.loop_instr.tail, NULL) + .tail = infer(ctx, node->payload.loop_instr.tail, NULL), + .mem = infer(ctx, node->payload.if_instr.mem, NULL), }); } @@ -517,21 +519,14 @@ static const Node* infer_control(Context* ctx, const Node* node) { return control(a, (Control) { .yield_types = yield_types, .inside = new_case, - .tail = infer(ctx, get_structured_construct_tail(node), NULL /*add_qualifiers(a, yield_types, false)*/) + .tail = infer(ctx, get_structured_construct_tail(node), NULL /*add_qualifiers(a, yield_types, false)*/), + .mem = infer(ctx, node->payload.if_instr.mem, NULL), }); } static const Node* infer_instruction(Context* ctx, const Node* node, const Type* expected_type) { IrArena* a = ctx->rewriter.dst_arena; switch (is_instruction(node)) { - case Instruction_PushStack_TAG: { - return push_stack(a, (PushStack) { infer(ctx, node->payload.push_stack.value, NULL) }); - } - case Instruction_PopStack_TAG: { - const Type* element_type = node->payload.pop_stack.type; - assert(is_data_type(element_type)); - return pop_stack(a, (PopStack) { element_type }); - } case PrimOp_TAG: return infer_primop(ctx, node, expected_type); case Call_TAG: return infer_indirect_call(ctx, node, expected_type); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index dc4fa1fe6..5c5c206a3 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -65,7 +65,7 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const } const Node* new = recreate_node_identity(&ctx->rewriter, node); - if (class == NcInstruction) + if (is_instruction(new)) register_processed(r, node, new); return new; } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 390ee6c7f..6695ec477 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -150,6 +150,8 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; + const Node* nmem = rewrite_node(r, old->tag == StackAlloc_TAG ? old->payload.stack_alloc.mem : old->payload.local_alloc.mem); + AllocaInfo* k = arena_alloc(ctx->arena, sizeof(AllocaInfo)); *k = (AllocaInfo) { .type = rewrite_node(r, old_type) }; assert(ctx->uses); @@ -236,15 +238,6 @@ static const Node* process(Context* ctx, const Node* old) { } break; } - case PrimOp_TAG: { - PrimOp payload = old->payload.prim_op; - switch (payload.op) { - - default: - break; - } - break; - } case LocalAlloc_TAG: return handle_alloc(ctx, old, old->payload.local_alloc.type); case StackAlloc_TAG: return handle_alloc(ctx, old, old->payload.stack_alloc.type); default: break; diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 6dddde003..267e28cd7 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -8,6 +8,7 @@ #include "dict.h" #include +#include KeyHash hash_node(Node**); bool compare_node(Node**, Node**); From 4aab3783b4c076dd1c96cd7ecdd380d9df8f1799 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 9 Aug 2024 14:46:54 +0200 Subject: [PATCH 438/693] reinstate some helpers to deal with multiple return --- include/shady/ir.h | 4 ++++ src/shady/constructors.c | 7 +++++++ src/shady/type.c | 20 ++++++++++++-------- src/shady/type.h | 3 +++ src/shady/type_helpers.c | 25 +++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 220246f60..1cd0e2805 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -115,6 +115,8 @@ ExecutionModel execution_model_from_string(const char*); typedef enum { NotSpecial, + /// for instructions with multiple yield values. Must be deconstructed by a let, cannot appear anywhere else + MultipleReturn, /// Gets the 'Block' SPIR-V annotation, needed for UBO/SSBO variables DecorateBlock } RecordSpecialFlag; @@ -216,6 +218,8 @@ const Type* noret_type(IrArena*); /// Unit type, carries no information (equivalent to C's void) /// There is exactly one possible value of this type: () const Node* unit_type(IrArena*); +/// For typing instructions that return nothing (equivalent to C's void f()) +const Node* empty_multiple_return_type(IrArena*); const Type* int_type_helper(IrArena*, bool, IntSizes); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 24a1f6616..960f6c04a 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -280,6 +280,13 @@ const Node* unit_type(IrArena* arena) { }); } +const Node* empty_multiple_return_type(IrArena* arena) { + return record_type(arena, (RecordType) { + .members = empty(arena), + .special = MultipleReturn, + }); +} + const Node* annotation_value_helper(IrArena* a, String n, const Node* v) { return annotation_value(a, (AnnotationValue) { .name = n, .value = v}); } diff --git a/src/shady/type.c b/src/shady/type.c index 1739a6a52..a629c69b7 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -348,7 +348,11 @@ const Type* check_type_join_point_type(IrArena* arena, JoinPointType type) { const Type* check_type_record_type(IrArena* arena, RecordType type) { assert(type.names.count == 0 || type.names.count == type.members.count); for (size_t i = 0; i < type.members.count; i++) { - assert(is_data_type(type.members.nodes[i])); + // member types are value types iff this is a return tuple + if (type.special == MultipleReturn) + assert(is_value_type(type.members.nodes[i])); + else + assert(is_data_type(type.members.nodes[i])); } return NULL; } @@ -937,7 +941,7 @@ const Type* check_type_call(IrArena* arena, Call call) { assert(is_value(argument)); } Nodes argument_types = get_values_types(arena, args); - return maybe_tuple_helper(arena, check_value_call(call.callee, argument_types)); + return maybe_multiple_return(arena, check_value_call(call.callee, argument_types)); } static void ensure_types_are_data_types(const Nodes* yield_types) { @@ -1000,7 +1004,7 @@ const Type* check_type_control(IrArena* arena, Control control) { } const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { - return qualified_type_helper(unit_type(arena), true); + return empty_multiple_return_type(arena); } const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { @@ -1055,7 +1059,7 @@ const Type* check_type_store(IrArena* a, Store store) { }); assert(is_subtype(val_expected_type, store.value->type)); - return qualified_type_helper(unit_type(a), true); + return empty_multiple_return_type(a); } const Type* check_type_lea(IrArena* a, Lea lea) { @@ -1097,7 +1101,7 @@ const Type* check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { const Type* cnt_t = copy_bytes.count->type; deconstruct_qualified_type(&cnt_t); assert(cnt_t->tag == Int_TAG); - return qualified_type_helper(unit_type(a), true); + return empty_multiple_return_type(a); } const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { @@ -1110,12 +1114,12 @@ const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { const Type* cnt_t = fill_bytes.count->type; deconstruct_qualified_type(&cnt_t); assert(cnt_t->tag == Int_TAG); - return qualified_type_helper(unit_type(a), true); + return empty_multiple_return_type(a); } const Type* check_type_push_stack(IrArena* a, PushStack payload) { assert(payload.value); - return qualified_type_helper(unit_type(a), true); + return empty_multiple_return_type(a); } const Type* check_type_pop_stack(IrArena* a, PopStack payload) { @@ -1137,7 +1141,7 @@ const Type* check_type_get_stack_base_addr(IrArena* a, SHADY_UNUSED GetStackBase } const Type* check_type_debug_printf(IrArena* a, DebugPrintf payload) { - return qualified_type_helper(unit_type(a), true);; + return empty_multiple_return_type(a); } const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { diff --git a/src/shady/type.h b/src/shady/type.h index 29384d4e4..2ddc7f65a 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -29,6 +29,9 @@ bool is_conversion_legal(const Type* src_type, const Type* dst_type); const Type* get_actual_mask_type(IrArena* arena); +const Type* maybe_multiple_return(IrArena* arena, Nodes types); +Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); + /// Returns the (possibly qualified) pointee type from a (possibly qualified) ptr type const Type* get_pointee_type(IrArena*, const Type*); diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index c21638ea7..099ba9be2 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -5,6 +5,31 @@ #include +const Type* maybe_multiple_return(IrArena* arena, Nodes types) { + switch (types.count) { + case 0: return empty_multiple_return_type(arena); + case 1: return types.nodes[0]; + default: return record_type(arena, (RecordType) { + .members = types, + .names = strings(arena, 0, NULL), + .special = MultipleReturn, + }); + } + SHADY_UNREACHABLE; +} + +Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type) { + switch (type->tag) { + case RecordType_TAG: + if (type->payload.record_type.special == MultipleReturn) + return type->payload.record_type.members; + // fallthrough + default: + assert(is_value_type(type)); + return singleton(type); + } +} + const Type* get_pointee_type(IrArena* arena, const Type* type) { bool qualified = false, uniform = false; if (is_value_type(type)) { From c33e818da3afb85abcda31e3ff3d180f88616028 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 10 Aug 2024 10:15:45 +0200 Subject: [PATCH 439/693] cleaned up and fixed lower_cf_instrs --- src/shady/passes/lower_cf_instrs.c | 146 ++++++++++++----------------- 1 file changed, 59 insertions(+), 87 deletions(-) diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index d241d66d1..77c9d7b38 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -16,22 +16,10 @@ typedef struct Context_ { struct Dict* structured_join_tokens; CFG* cfg; - const Node* abs; } Context; static const Node* process_node(Context* ctx, const Node* node); -static const Node* process_instruction(Context* ctx, const Node* old_instruction) { - IrArena* a = ctx->rewriter.dst_arena; - - switch (old_instruction->tag) { - default: - break; - } - - return recreate_node_identity(&ctx->rewriter, old_instruction); -} - static const Node* process_node(Context* ctx, const Node* node) { const Node* already_done = search_processed(&ctx->rewriter, node); if (already_done) @@ -46,31 +34,22 @@ static const Node* process_node(Context* ctx, const Node* node) { sub_ctx.disable_lowering = lookup_annotation(fun, "Structured"); sub_ctx.current_fn = fun; sub_ctx.cfg = build_fn_cfg(node); - sub_ctx.abs = node; set_abstraction_body(fun, rewrite_node(&sub_ctx.rewriter, node->payload.fun.body)); destroy_cfg(sub_ctx.cfg); return fun; } else if (node->tag == Constant_TAG) { sub_ctx.cfg = NULL; - sub_ctx.abs = NULL; sub_ctx.current_fn = NULL; ctx = &sub_ctx; } - if (is_abstraction(node)) { - sub_ctx.abs = node; - ctx = &sub_ctx; - } - if (ctx->disable_lowering) return recreate_node_identity(&ctx->rewriter, node); - CFNode* cfnode = ctx->cfg ? cfg_lookup(ctx->cfg, ctx->abs) : NULL; - if (is_instruction(node)) - return process_instruction(ctx, node); switch (node->tag) { case If_TAG: { - bool has_false_branch = node->payload.if_instr.if_false; + If payload = node->payload.if_instr; + bool has_false_branch = payload.if_false; Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.if_instr.yield_types); const Node* nmem = rewrite_node(r, node->payload.if_instr.mem); @@ -79,48 +58,40 @@ static const Node* process_node(Context* ctx, const Node* node) { .is_uniform = false, }); const Node* jp = param(a, jp_type, "if_join"); - Context join_context = *ctx; Nodes jps = singleton(jp); insert_dict(const Node*, Nodes, ctx->structured_join_tokens, node, jps); - Node* true_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_true")); - join_context.abs = node->payload.if_instr.if_true; - set_abstraction_body(true_block, rewrite_node(&join_context.rewriter, get_abstraction_body(node->payload.if_instr.if_true))); + const Node* true_block = rewrite_node(r, payload.if_true); - Node* flse_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_false")); + const Node* false_block; if (has_false_branch) { - join_context.abs = node->payload.if_instr.if_false; - set_abstraction_body(flse_block, rewrite_node(&join_context.rewriter, get_abstraction_body(node->payload.if_instr.if_false))); + false_block = rewrite_node(r, payload.if_false); } else { assert(yield_types.count == 0); - set_abstraction_body(flse_block, join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL) })); + false_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_false")); + set_abstraction_body((Node*) false_block, join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL), .mem = get_abstraction_mem(false_block) })); } - BodyBuilder* bb = begin_body_with_mem(a, nmem); Node* control_case = basic_block(a, singleton(jp), NULL); const Node* control_body = branch(a, (Branch) { .condition = rewrite_node(r, node->payload.if_instr.condition), .true_jump = jump_helper(a, true_block, empty(a), get_abstraction_mem(control_case)), - .false_jump = jump_helper(a, flse_block, empty(a), get_abstraction_mem(control_case)), + .false_jump = jump_helper(a, false_block, empty(a), get_abstraction_mem(control_case)), .mem = get_abstraction_mem(control_case), }); set_abstraction_body(control_case, control_body); - Nodes results = gen_control(bb, yield_types, control_case); - const Node* otail = node->payload.if_instr.tail; - Node* join = basic_block(a, recreate_params(r, get_abstraction_params(otail)), NULL); - register_processed_list(r, get_abstraction_params(otail), get_abstraction_params(join)); - set_abstraction_body(join, rewrite_node(r, get_abstraction_body(otail))); - return finish_body(bb, jump_helper(a, join, results, bb_mem(bb))); - // return control(a) - //return yield_values_and_wrap_in_block(bb, ); + BodyBuilder* bb = begin_body_with_mem(a, nmem); + Nodes results = gen_control(bb, yield_types, control_case); + return finish_body(bb, jump_helper(a, rewrite_node(r, payload.tail), results, bb_mem(bb))); } // TODO: match case Loop_TAG: { - const Node* old_loop_body = node->payload.loop_instr.body; + Loop payload = node->payload.loop_instr; + const Node* old_loop_block = payload.body; Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.yield_types); - Nodes param_types = rewrite_nodes(&ctx->rewriter, get_param_types(a, get_abstraction_params(old_loop_body))); + Nodes param_types = rewrite_nodes(&ctx->rewriter, get_param_types(a, get_abstraction_params(old_loop_block))); param_types = strip_qualifiers(a, param_types); const Type* break_jp_type = qualified_type(a, (QualifiedType) { @@ -133,44 +104,36 @@ static const Node* process_node(Context* ctx, const Node* node) { }); const Node* break_point = param(a, break_jp_type, "loop_break_point"); const Node* continue_point = param(a, continue_jp_type, "loop_continue_point"); - Context join_context = *ctx; Nodes jps = mk_nodes(a, break_point, continue_point); insert_dict(const Node*, Nodes, ctx->structured_join_tokens, node, jps); - Nodes new_params = recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_body)); - Node* loop_body = basic_block(a, new_params, unique_name(a, "loop_body")); - register_processed_list(&join_context.rewriter, get_abstraction_params(old_loop_body), loop_body->payload.basic_block.params); + Nodes new_params = recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_block)); + Node* loop_header_block = basic_block(a, new_params, unique_name(a, "loop_header")); - join_context.abs = old_loop_body; - const Node* inner_control_body = rewrite_node(&join_context.rewriter, get_abstraction_body(old_loop_body)); + BodyBuilder* inner_bb = begin_body_with_mem(a, get_abstraction_mem(loop_header_block)); Node* inner_control_case = case_(a, singleton(continue_point)); - set_abstraction_body(inner_control_case, inner_control_body); - - BodyBuilder* inner_bb = begin_body_with_mem(a, get_abstraction_mem(inner_control_case)); + set_abstraction_body(inner_control_case, jump_helper(a, rewrite_node(r, old_loop_block), new_params, get_abstraction_mem(inner_control_case))); Nodes args = gen_control(inner_bb, param_types, inner_control_case); - // TODO let_in_block or use a Jump ! - set_abstraction_body(loop_body, finish_body(inner_bb, jump(a, (Jump) { .target = loop_body, .args = args }))); + set_abstraction_body(loop_header_block, finish_body(inner_bb, jump(a, (Jump) { .target = loop_header_block, .args = args, .mem = bb_mem(inner_bb) }))); - const Node* initial_jump = jump(a, (Jump) { - .target = loop_body, - .args = rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.initial_args), + Node* outer_control_case = case_(a, singleton(break_point)); + const Node* first_iteration_jump = jump(a, (Jump) { + .target = loop_header_block, + .args = rewrite_nodes(r, payload.initial_args), + .mem = get_abstraction_mem(outer_control_case), }); + set_abstraction_body(outer_control_case, first_iteration_jump); - Node* outer_control_case = case_(a, singleton(break_point)); - BodyBuilder* outer_bb = begin_body_with_mem(a, get_abstraction_mem(outer_control_case)); - Nodes results = gen_control(outer_bb, yield_types, outer_control_case); - set_abstraction_body(outer_control_case, initial_jump); - - const Node* otail = get_structured_construct_tail(node); - Node* join = basic_block(a, recreate_params(r, get_abstraction_params(otail)), NULL); - register_processed_list(r, get_abstraction_params(otail), get_abstraction_params(join)); - set_abstraction_body(join, rewrite_node(r, get_abstraction_body(otail))); - return finish_body(outer_bb, jump_helper(a, join, results, bb_mem(outer_bb))); + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + Nodes results = gen_control(bb, yield_types, outer_control_case); + return finish_body(bb, jump_helper(a, rewrite_node(r, payload.tail), results, bb_mem(bb))); } case MergeSelection_TAG: { - if (!cfnode) - break; + MergeSelection payload = node->payload.merge_selection; + const Node* root_mem = get_original_mem(payload.mem); + assert(root_mem->tag == AbsMem_TAG); + CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; const Node* selection_instr = NULL; while (dom) { @@ -193,70 +156,79 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(jps && jps->count == 1); const Node* jp = first(*jps); assert(jp); + const Node* nmem = rewrite_node(r, payload.mem); return join(a, (Join) { .join_point = jp, - .args = rewrite_nodes(&ctx->rewriter, node->payload.merge_selection.args), - .mem = rewrite_node(r, node->payload.merge_selection.mem) + .args = rewrite_nodes(&ctx->rewriter, payload.args), + .mem = nmem }); } case MergeContinue_TAG: { - assert(cfnode); + MergeContinue payload = node->payload.merge_continue; + const Node* root_mem = get_original_mem(payload.mem); + assert(root_mem->tag == AbsMem_TAG); + CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; - const Node* selection_instr = NULL; + const Node* loop_start = NULL; while (dom) { const Node* body = get_abstraction_body(dom->node); if (body->tag == Loop_TAG) { - selection_instr = body; + loop_start = body; break; } dom = dom->idom; } - if (!selection_instr) { - error_print("Scoping error: Failed to find a dominating selection construct for "); + if (!loop_start) { + error_print("Scoping error: Failed to find a dominating loop construct for "); log_node(ERROR, node); error_print(".\n"); error_die(); } - Nodes* jps = find_value_dict(const Node*, Nodes, ctx->structured_join_tokens, selection_instr); + Nodes* jps = find_value_dict(const Node*, Nodes, ctx->structured_join_tokens, loop_start); assert(jps && jps->count == 2); const Node* jp = jps->nodes[1]; assert(jp); + const Node* nmem = rewrite_node(r, payload.mem); return join(a, (Join) { .join_point = jp, - .args = rewrite_nodes(&ctx->rewriter, node->payload.merge_continue.args), - .mem = rewrite_node(r, node->payload.merge_continue.mem) + .args = rewrite_nodes(&ctx->rewriter, payload.args), + .mem = nmem, }); } case MergeBreak_TAG: { - assert(cfnode); + MergeBreak payload = node->payload.merge_break; + const Node* root_mem = get_original_mem(payload.mem); + assert(root_mem->tag == AbsMem_TAG); + CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; - const Node* selection_instr = NULL; + const Node* loop_start = NULL; while (dom) { const Node* body = get_abstraction_body(dom->node); if (body->tag == Loop_TAG) { - selection_instr = body; + loop_start = body; break; } dom = dom->idom; } - if (!selection_instr) { - error_print("Scoping error: Failed to find a dominating selection construct for "); + if (!loop_start) { + error_print("Scoping error: Failed to find a dominating loop construct for "); log_node(ERROR, node); error_print(".\n"); error_die(); } - Nodes* jps = find_value_dict(const Node*, Nodes, ctx->structured_join_tokens, selection_instr); + Nodes* jps = find_value_dict(const Node*, Nodes, ctx->structured_join_tokens, loop_start); assert(jps && jps->count == 2); const Node* jp = first(*jps); assert(jp); + const Node* nmem = rewrite_node(r, payload.mem); return join(a, (Join) { .join_point = jp, - .args = rewrite_nodes(&ctx->rewriter, node->payload.merge_break.args), - .mem = rewrite_node(r, node->payload.merge_break.mem) + .args = rewrite_nodes(&ctx->rewriter, payload.args), + .mem = nmem, }); } default: break; From bf7a6f363ecea0ff5c380ebf553a6ba5cb8a8aa4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 10 Aug 2024 10:30:01 +0200 Subject: [PATCH 440/693] printer: more pretty --- src/shady/print.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/shady/print.c b/src/shady/print.c index 739b266a5..fe2ff29bc 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -537,19 +537,13 @@ static bool print_value(PrinterCtx* ctx, const Node* node) { break; } case Value_Param_TAG: - if (ctx->uses) { - // if ((*find_value_dict(const Node*, Uses*, ctx->uses->map, node))->escapes_defining_block) - // printf(MANGENTA); - // else - printf(YELLOW); - } else - printf(YELLOW); + printf(YELLOW); String name = get_value_name_unsafe(node); if (name && strlen(name) > 0) printf("%s_", name); printf("%%%d", node->id); printf(RESET); - break; + return true; case UntypedNumber_TAG: printf(BBLUE); printf("%s", node->payload.untyped_number.plaintext); @@ -1038,17 +1032,24 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { if (found) return *found; + bool print_def = true; String r; - if (is_declaration(node)) + if (is_declaration(node)) { r = get_declaration_name(node); - else + print_def = false; + } else if (is_param(node) || is_basic_block(node) || node->tag == RefDecl_TAG || node->tag == FnAddr_TAG) { + print_def = false; r = format_string_interned(node->arena, "%%%d", node->id); + } else { + r = format_string_interned(node->arena, "%%%d", node->id); + } insert_dict(const Node*, String, ctx->emitted, node, r); Growy* g = new_growy(); PrinterCtx ctx2 = *ctx; ctx2.printer = open_growy_as_printer(g); bool print_inline = print_node_impl(&ctx2, node); + String s = printer_growy_unwrap(ctx2.printer); Printer* p = ctx->root_printer; if (ctx->scheduler) { @@ -1056,7 +1057,9 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { if (dst) p = ctx2.bb_printers[dst->rpo_index]; } - print(p, "%%%d = %s\n", node->id, s); + + if (print_def) + print(p, "%%%d = %s\n", node->id, s); if (print_inline) { String is = string(node->arena, s); From 10abbb6d002be59b3859041de196c8e330dcc7b2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 10 Aug 2024 10:44:05 +0200 Subject: [PATCH 441/693] partially fix lower_tailcalls --- src/shady/passes/lower_tailcalls.c | 46 +++++++++++------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index c73ffe92c..0eaf22ce4 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -64,8 +64,8 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_entry_pt)); - bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, ctx->init_fn), .args = empty(a) })); - bind_instruction(bb, call(a, (Call) { .callee = access_decl(&ctx->rewriter, "builtin_init_scheduler"), .args = empty(a) })); + gen_call(bb, fn_addr_helper(a, ctx->init_fn), empty(a)); + gen_call(bb, access_decl(&ctx->rewriter, "builtin_init_scheduler"), empty(a)); // shove the arguments on the stack for (size_t i = rewritten_params.count - 1; i < rewritten_params.count; i--) { @@ -76,16 +76,13 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { const Node* jump_fn = access_decl(&ctx->rewriter, "builtin_fork"); const Node* fn_addr = lower_fn_addr(ctx, old); fn_addr = gen_conversion(bb, uint32_type(a), fn_addr); - bind_instruction(bb, call(a, (Call) { .callee = jump_fn, .args = singleton(fn_addr) })); + gen_call(bb, jump_fn, singleton(fn_addr)); if (!*ctx->top_dispatcher_fn) { *ctx->top_dispatcher_fn = function(ctx->rewriter.dst_module, nodes(a, 0, NULL), "top_dispatcher", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" }), annotation(a, (Annotation) { .name = "Structured" })), nodes(a, 0, NULL)); } - bind_instruction(bb, call(a, (Call) { - .callee = fn_addr_helper(a, *ctx->top_dispatcher_fn), - .args = nodes(a, 0, NULL) - })); + gen_call(bb, fn_addr_helper(a, *ctx->top_dispatcher_fn), empty(a)); set_abstraction_body(new_entry_pt, finish_body(bb, fn_ret(a, (Return) { .args = nodes(a, 0, NULL), @@ -161,11 +158,12 @@ static const Node* process(Context* ctx, const Node* old) { } case FnAddr_TAG: return lower_fn_addr(ctx, old->payload.fn_addr.fn); case Call_TAG: { - const Node* ocallee = old->payload.call.callee; - assert(ocallee->tag == FnAddr_TAG); + Call payload = old->payload.call; + assert(payload.callee->tag == FnAddr_TAG && "Only direct calls should survive this pass"); return call(a, (Call) { - .callee = fn_addr_helper(a, rewrite_node(&ctx->rewriter, ocallee->payload.fn_addr.fn)), - .args = rewrite_nodes(&ctx->rewriter, old->payload.call.args), + .callee = fn_addr_helper(a, rewrite_node(&ctx->rewriter, payload.callee->payload.fn_addr.fn)), + .args = rewrite_nodes(&ctx->rewriter, payload.args), + .mem = rewrite_node(r, payload.mem) }); } case JoinPointType_TAG: return type_decl_ref(a, (TypeDeclRef) { @@ -207,11 +205,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* target = rewrite_node(&ctx->rewriter, payload.target); target = gen_conversion(bb, uint32_type(a), target); - const Node* fork_call = call(a, (Call) { - .callee = access_decl(&ctx->rewriter, "builtin_fork"), - .args = nodes(a, 1, (const Node*[]) { target }) - }); - bind_instruction(bb, fork_call); + gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), singleton(target)); return finish_body(bb, fn_ret(a, (Return) { .args = nodes(a, 0, NULL) })); } case Join_TAG: { @@ -232,11 +226,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* dst = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 1))); const Node* tree_node = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 0))); - const Node* join_call = call(a, (Call) { - .callee = access_decl(&ctx->rewriter, "builtin_join"), - .args = mk_nodes(a, dst, tree_node) - }); - bind_instruction(bb, join_call); + gen_call(bb, access_decl(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); return finish_body(bb, fn_ret(a, (Return) { .args = nodes(a, 0, NULL) })); } case PtrType_TAG: { @@ -250,8 +240,8 @@ static const Node* process(Context* ctx, const Node* old) { case Control_TAG: { Control payload = old->payload.control; if (is_control_static(ctx->uses, old)) { - const Node* old_inside = old->payload.control.inside; - const Node* old_jp = first(get_abstraction_params(old_inside)); + // const Node* old_inside = old->payload.control.inside; + const Node* old_jp = first(get_abstraction_params(payload.inside)); assert(old_jp->tag == Param_TAG); const Node* old_jp_type = old_jp->type; deconstruct_qualified_type(&old_jp_type); @@ -262,7 +252,8 @@ static const Node* process(Context* ctx, const Node* old) { const Node* new_jp = param(a, qualified_type_helper(new_jp_type, true), old_jp->payload.param.name); register_processed(&ctx->rewriter, old_jp, new_jp); Node* new_control_case = case_(a, singleton(new_jp)); - set_abstraction_body(new_control_case, rewrite_node(&ctx->rewriter, get_abstraction_body(old_inside))); + register_processed(r, payload.inside, new_control_case); + set_abstraction_body(new_control_case, rewrite_node(&ctx->rewriter, get_abstraction_body(payload.inside))); // BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); Nodes nyield_types = rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types); return control(a, (Control) { @@ -298,7 +289,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* next_function = gen_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); const Node* get_active_branch_fn = access_decl(&ctx->rewriter, "builtin_get_active_branch"); - const Node* next_mask = first(bind_instruction(loop_body_builder, call(a, (Call) { .callee = get_active_branch_fn, .args = empty(a) }))); + const Node* next_mask = first(gen_call(loop_body_builder, get_active_branch_fn, empty(a))); const Node* local_id = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); const Node* should_run = gen_primop_e(loop_body_builder, mask_is_thread_active_op, empty(a), mk_nodes(a, next_mask, local_id)); @@ -365,10 +356,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %ul with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } - bind_instruction(if_builder, call(a, (Call) { - .callee = fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), - .args = nodes(a, 0, NULL) - })); + gen_call(if_builder, fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), empty(a)); set_abstraction_body(if_true_lam, finish_body(if_builder, merge_selection(a, (MergeSelection) {.args = nodes(a, 0, NULL)}))); Node* case_lam = case_(a, nodes(a, 0, NULL)); From 17cdbc1e045ea69ca006d03a3502dc8ee57b52ff Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 10 Aug 2024 10:48:39 +0200 Subject: [PATCH 442/693] body_builder: added some useful helpers to reduce verbosity --- include/shady/ir.h | 3 +++ src/shady/body_builder.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/shady/ir.h b/include/shady/ir.h index 1cd0e2805..6830ac8d2 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -306,6 +306,9 @@ Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, si const Node* finish_body(BodyBuilder*, const Node* terminator); const Node* finish_body_with_return(BodyBuilder*, Nodes args); const Node* finish_body_with_unreachable(BodyBuilder*); +const Node* finish_body_with_selection_merge(BodyBuilder*, Nodes args); +const Node* finish_body_with_loop_continue(BodyBuilder*, Nodes args); +const Node* finish_body_with_loop_break(BodyBuilder*, Nodes args); void cancel_body(BodyBuilder*); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 683725a6b..0fa37aa00 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -123,6 +123,40 @@ const Node* finish_body(BodyBuilder* bb, const Node* terminator) { return terminator; } +const Node* finish_body_with_return(BodyBuilder* bb, Nodes args) { + return finish_body(bb, fn_ret(bb->arena, (Return) { + .args = args, + .mem = bb_mem(bb) + })); +} + +const Node* finish_body_with_unreachable(BodyBuilder* bb) { + return finish_body(bb, unreachable(bb->arena, (Unreachable) { + .mem = bb_mem(bb) + })); +} + +const Node* finish_body_with_selection_merge(BodyBuilder* bb, Nodes args) { + return finish_body(bb, merge_selection(bb->arena, (MergeSelection) { + .args = args, + .mem = bb_mem(bb), + })); +} + +const Node* finish_body_with_loop_continue(BodyBuilder* bb, Nodes args) { + return finish_body(bb, merge_continue(bb->arena, (MergeContinue) { + .args = args, + .mem = bb_mem(bb), + })); +} + +const Node* finish_body_with_loop_break(BodyBuilder* bb, Nodes args) { + return finish_body(bb, merge_break(bb->arena, (MergeBreak) { + .args = args, + .mem = bb_mem(bb), + })); +} + const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { IrArena* a = bb->arena; if (entries_count_list(bb->stack) == 0) { From 5da87eef93ba415979f37fa781d25ab5a182052e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 10 Aug 2024 11:46:37 +0200 Subject: [PATCH 443/693] fixed opt_restructure --- src/shady/passes/opt_restructure.c | 64 ++++++++++++++++++------------ 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index e08d2cd58..d01d648b7 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -88,17 +88,23 @@ static const Node* make_unreachable_case(IrArena* a) { return c; } +static const Node* make_selection_merge_case(IrArena* a) { + Node* c = case_(a, empty(a)); + set_abstraction_body(c, merge_selection(a, (MergeSelection) { .args = empty(a), .mem = get_abstraction_mem(c) })); + return c; +} + static const Node* structure(Context* ctx, const Node* abs, const Node* exit); -static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* exit) { +static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, const Node* exit) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; - const Node* dst = jump.target; + const Node* old_target = jump.target; Nodes oargs = jump.args; size_t path_len; - DFSStackEntry* prior_encounter = encountered_before(ctx, dst, &path_len); + DFSStackEntry* prior_encounter = encountered_before(ctx, old_target, &path_len); if (prior_encounter) { // Create path LARRAY(const Node*, path, path_len); @@ -116,19 +122,19 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* exit) prior_encounter->loop_header = true; return merge_continue(a, (MergeContinue) { .args = rewrite_nodes(r, oargs), - .mem = rewrite_node(r, jump.mem), + .mem = mem, }); } else { - Nodes oparams = get_abstraction_params(dst); + Nodes oparams = get_abstraction_params(old_target); assert(oparams.count == oargs.count); LARRAY(const Node*, nparams, oargs.count); Context ctx2 = *ctx; - + // Record each step of the depth-first search on a stack so we can identify loops - DFSStackEntry dfs_entry = { .parent = ctx->dfs_stack, .old = dst, .containing_control = ctx->control_stack }; + DFSStackEntry dfs_entry = { .parent = ctx->dfs_stack, .old = old_target, .containing_control = ctx->control_stack }; ctx2.dfs_stack = &dfs_entry; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, jump.mem)); + BodyBuilder* bb = begin_body_with_mem(a, mem); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); @@ -141,29 +147,32 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* exit) } // We use a basic block for the exit ladder because we don't know what the ladder needs to do ahead of time - // opt_simplify_cf will later inline this Node* inner_exit_ladder_bb = basic_block(a, empty(a), unique_name(a, "exit_ladder_inline_me")); // Just jumps to the actual ladder - const Node* structured = structure(&ctx2, get_abstraction_body(dst), inner_exit_ladder_bb); + Node* structured_target = case_(a, nodes(a, oargs.count, nparams)); + register_processed(&ctx2.rewriter, get_abstraction_mem(old_target), get_abstraction_mem(structured_target)); + const Node* structured = structure(&ctx2, get_abstraction_body(old_target), inner_exit_ladder_bb); assert(is_terminator(structured)); + set_abstraction_body(structured_target, structured); + // forget we rewrote all that destroy_dict(tmp_processed); pop_list_impl(ctx->cleanup_stack); pop_list_impl(ctx->cleanup_stack); if (dfs_entry.loop_header) { - Node* loop_case = case_(a, nodes(a, oargs.count, nparams)); - set_abstraction_body(loop_case, structured); - gen_loop(bb, empty(a), rewrite_nodes(&ctx->rewriter, oargs), loop_case); - // we decide 'late' what the exit ladder should be + // Use the structured target as the body of a loop + gen_loop(bb, empty(a), rewrite_nodes(&ctx->rewriter, oargs), structured_target); + // The exit ladder must exit that new loop set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) })); + // After that we jump to the parent exit return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); } else { - Node* bb2 = basic_block(a, nodes(a, oargs.count, nparams), NULL); - set_abstraction_body(bb2, structured); + // Simply jmp to the exit once done set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, exit, empty(a), get_abstraction_mem(inner_exit_ladder_bb))); - return finish_body(bb, jump_helper(a, bb2, rewrite_nodes(&ctx->rewriter, oargs), bb_mem(bb))); + // Jump into the new structured target + return finish_body(bb, jump_helper(a, structured_target, rewrite_nodes(&ctx->rewriter, oargs), bb_mem(bb))); } } } @@ -187,7 +196,8 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { switch (is_terminator(body)) { case NotATerminator: case Jump_TAG: { - return handle_bb_callsite(ctx, body->payload.jump, exit); + Jump payload = body->payload.jump; + return handle_bb_callsite(ctx, payload, rewrite_node(r, payload.mem), exit); } // br(cond, true_bb, false_bb, args) // becomes @@ -197,10 +207,10 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { const Node* condition = rewrite_node(&ctx->rewriter, payload.condition); Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); + set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, get_abstraction_mem(true_case), make_selection_merge_case(a))); Node* false_case = case_(a, empty(a)); - set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); + set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, get_abstraction_mem(false_case), make_selection_merge_case(a))); BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_if(bb, empty(a), condition, true_case, false_case); @@ -211,12 +221,12 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { const Node* switch_value = rewrite_node(r, payload.switch_value); Node* default_case = case_(a, empty(a)); - set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, merge_selection(a, (MergeSelection) { .args = empty(a) }))); + set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, get_abstraction_mem(default_case), make_selection_merge_case(a))); LARRAY(Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { cases[i] = case_(a, empty(a)); - set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, merge_selection(a, (MergeSelection) {.args = empty(a)}))); + set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, get_abstraction_mem(cases[i]), make_selection_merge_case(a))); } BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); @@ -268,10 +278,11 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { const Node* level_value = gen_load(bb_tail, ctx->level_ptr); const Node* guard = first(bind_instruction(bb_tail, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), merge_selection(a, (MergeSelection) { .args = empty(a) }))); + register_processed(r, get_abstraction_mem(get_structured_construct_tail(body)), get_abstraction_mem(true_case)); + set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); gen_if(bb_tail, empty(a), guard, true_case, NULL); - set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, exit, empty(a), bb_mem(bb_tail)))); + register_processed(r, get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); return finish_body(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); } @@ -289,7 +300,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { gen_store(bb, control->phis[i], args.nodes[i]); } - return finish_body(bb, exit); + return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); } case Return_TAG: @@ -356,7 +367,7 @@ static const Node* process(Context* ctx, const Node* node) { TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; - register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new, finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. @@ -399,6 +410,7 @@ static const Node* process(Context* ctx, const Node* node) { assert(false); // actually that should not come up. longjmp(ctx->bail, 1); } + case BasicBlock_TAG: error("All basic blocks should be processed explicitly") default: break; } return recreate_node_identity(&ctx->rewriter, node); From bdb6118d9c24c96a817af5cf9f4926e3daa040ac Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 10 Aug 2024 12:07:57 +0200 Subject: [PATCH 444/693] fix more memory simplfication logic --- src/shady/constructors.c | 5 +---- src/shady/fold.c | 4 ++-- src/shady/passes/opt_demote_alloca.c | 1 + 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 960f6c04a..942f31831 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -281,10 +281,7 @@ const Node* unit_type(IrArena* arena) { } const Node* empty_multiple_return_type(IrArena* arena) { - return record_type(arena, (RecordType) { - .members = empty(arena), - .special = MultipleReturn, - }); + return qualified_type_helper(unit_type(arena), true); } const Node* annotation_value_helper(IrArena* a, String n, const Node* v) { diff --git a/src/shady/fold.c b/src/shady/fold.c index 54b8441a7..f505a493f 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -324,12 +324,12 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { switch (node->tag) { case Load_TAG: { if (node->payload.load.ptr->tag == Undef_TAG) - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + return mem_and_value(arena, (MemAndValue) { .value = undef(arena, (Undef) { .type = get_unqualified_type(node->type) }), .mem = node->payload.load.mem }); break; } case Store_TAG: { if (node->payload.store.ptr->tag == Undef_TAG) - return tuple_helper(arena, empty(arena)); + return mem_and_value(arena, (MemAndValue) { .value = tuple_helper(arena, empty(arena)), .mem = node->payload.store.mem }); break; } case Lea_TAG: { diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 6695ec477..182e4df71 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -164,6 +164,7 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { ctx->todo |= true; const Node* new = undef(a, (Undef) { .type = get_unqualified_type(rewrite_node(r, old->type)) }); + new = mem_and_value(a, (MemAndValue) { .value = new, .mem = nmem }); k->new = new; return new; } From 6e5bfc59234f49fe440aa25b37982f7f8b39d2ca Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 10 Aug 2024 12:48:59 +0200 Subject: [PATCH 445/693] remove subgroup_broadcast_first in favor of using the equivalent spv --- include/shady/ir.h | 1 + include/shady/primops.json | 4 -- src/backend/c/emit_c_instructions.c | 35 ++++++++++----- src/backend/spirv/emit_spv_instructions.c | 53 +++++++++++++---------- src/frontend/slim/parser.c | 24 ++++++++-- src/shady/body_builder.c | 4 ++ src/shady/fold.c | 4 +- src/shady/internal/scheduler.slim | 14 +++--- src/shady/passes/infer.c | 3 -- src/shady/passes/lower_callf.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 4 +- src/shady/passes/lower_subgroup_ops.c | 24 +++++----- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/opt_restructure.c | 2 +- src/shady/transform/ir_gen_helpers.c | 10 +++++ src/shady/transform/ir_gen_helpers.h | 1 + src/shady/type.c | 4 +- 18 files changed, 119 insertions(+), 74 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 6830ac8d2..777dbcb7d 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -288,6 +288,7 @@ BodyBuilder* begin_block_with_side_effects(IrArena*); /// Appends an instruction to the builder, may apply optimisations. /// If the arena is typed, returns a list of variables bound to the values yielded by that instruction Nodes bind_instruction(BodyBuilder*, const Node* instruction); +const Node* bind_instruction_single(BodyBuilder*, const Node* instruction); Nodes bind_instruction_named(BodyBuilder*, const Node* instruction, String const output_names[]); Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count); diff --git a/include/shady/primops.json b/include/shady/primops.json index 48f2c072d..24141fcb4 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -193,10 +193,6 @@ "name": "subgroup_elect_first", "class": "subgroup_intrinsic" }, - { - "name": "subgroup_broadcast_first", - "class": "subgroup_intrinsic" - }, { "name": "subgroup_assume_uniform", "class": "subgroup_intrinsic" diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_instructions.c index 72f9e41b4..c49ec4fcc 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_instructions.c @@ -8,8 +8,11 @@ #include "../shady/type.h" #include "../shady/ir_private.h" +#include + #include #include +#include #pragma GCC diagnostic error "-Wswitch" @@ -522,16 +525,6 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { return emit_value(emitter, p, prim_op->operands.nodes[0]); } } - case subgroup_broadcast_first_op: { - CValue value = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); - switch (emitter->config.dialect) { - case CDialect_CUDA: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; - case CDialect_ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; - case CDialect_C11: - case CDialect_GLSL: error("TODO") - } - break; - } case empty_mask_op: case mask_is_thread_active_op: error("lower_me"); default: break; @@ -544,6 +537,26 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { return term; } +static CTerm emit_ext_instruction(Emitter* emitter, Printer* p, ExtInstr instr) { + if (strcmp(instr.set, "spirv.core") == 0) { + switch (instr.opcode) { + case SpvOpGroupNonUniformBroadcastFirst: { + CValue value = to_cvalue(emitter, emit_value(emitter, p, first(instr.operands))); + switch (emitter->config.dialect) { + case CDialect_CUDA: return term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; + case CDialect_ISPC: return term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; + case CDialect_C11: + case CDialect_GLSL: error("TODO") + } + break; + } + default: error("Unsupported core spir-v instruction: %d", instr.opcode); + } + } else { + error("Unsupported extended instruction set: %s", instr.set); + } +} + static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { Nodes args; if (call->tag == Call_TAG) @@ -682,7 +695,7 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { case Instruction_SetStackSize_TAG: case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); case Instruction_BindIdentifiers_TAG: error("front-end only!"); - case Instruction_ExtInstr_TAG: error("Extended instructions are not supported in C"); + case Instruction_ExtInstr_TAG: return emit_ext_instruction(emitter, p, instruction->payload.ext_instr); case Instruction_PrimOp_TAG: return emit_primop(emitter, p, instruction); case Instruction_Call_TAG: return emit_call(emitter, p, instruction); /*case Instruction_CompoundInstruction_TAG: { diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 89018c10e..799a904bf 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -8,6 +8,7 @@ #include "../shady/transform/ir_gen_helpers.h" #include +#include #include "spirv/unified1/NonSemanticDebugPrintf.h" #include "spirv/unified1/GLSL.std.450.h" @@ -242,27 +243,6 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); return; } - case subgroup_broadcast_first_op: { - SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); - SpvId result; - - if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { - SpvId local_id; - const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); - // TODO: very hacky indeed - // emit_instruction(emitter, fn_builder, bb_builder, load(emitter->arena, (Load) { b }), 1, &local_id); - error("reimplement") - result = spvb_group_shuffle(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), scope_subgroup, emit_value(emitter, bb_builder, first(args)), local_id); - spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); - } else { - result = spvb_group_broadcast_first(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), emit_value(emitter, bb_builder, first(args)), scope_subgroup); - } - - assert(results_count == 1); - results[0] = result; - spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); - return; - } case subgroup_reduce_sum_op: { SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); assert(results_count == 1); @@ -345,6 +325,35 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui error("unreachable"); } +static SpvId emit_ext_instr(Emitter* emitter, BBBuilder bb_builder, ExtInstr instr) { + if (strcmp("spirv.core", instr.set) == 0) { + switch (instr.opcode) { + case SpvOpGroupNonUniformBroadcastFirst: { + SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); + SpvId result; + + if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { + SpvId local_id; + const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); + // TODO: very hacky indeed + // emit_instruction(emitter, fn_builder, bb_builder, load(emitter->arena, (Load) { b }), 1, &local_id); + error("reimplement") + result = spvb_group_shuffle(bb_builder, emit_type(emitter, instr.result_t), scope_subgroup, emit_value(emitter, bb_builder, first(instr.operands)), local_id); + spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); + } else { + result = spvb_group_broadcast_first(bb_builder, emit_type(emitter, instr.result_t), emit_value(emitter, bb_builder, first(instr.operands)), scope_subgroup); + } + + spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); + return result; + } + default: break; + } + error("TODO: emit arbitrary spv instr here"); + } + error("TODO: emit arbitrary ext spv instr here"); +} + static void emit_leaf_call(Emitter* emitter, SHADY_UNUSED FnBuilder fn_builder, BBBuilder bb_builder, Call call, size_t results_count, SpvId results[]) { const Node* fn = call.callee; assert(fn->tag == FnAddr_TAG); @@ -391,7 +400,7 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build case Instruction_FillBytes_TAG: case Instruction_BindIdentifiers_TAG: case Instruction_StackAlloc_TAG: error("Should be lowered elsewhere") - case Instruction_ExtInstr_TAG: error("Extended instructions are not supported yet"); + case Instruction_ExtInstr_TAG: emit_ext_instr(emitter, bb_builder, instruction->payload.ext_instr); case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call, results_count, results); break; case PrimOp_TAG: emit_primop(emitter, fn_builder, bb_builder, instruction, results_count, results); break; case Comment_TAG: break; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 84fd13336..23a62ee84 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -86,10 +86,7 @@ static const Type* accept_unqualified_type(ctxparams); static const Node* accept_expr(ctxparams, BodyBuilder*, int); static Nodes expect_operands(ctxparams, BodyBuilder*); static const Node* expect_operand(ctxparams, BodyBuilder*); - -static const Node* bind_instruction_single(BodyBuilder* bb, const Node* instr) { - return first(bind_instruction_outputs_count(bb, instr, 1)); -} +static const Type* accept_qualified_type(ctxparams); static const Type* accept_numerical_type(ctxparams) { if (accept_token(ctx, i8_tok)) { @@ -203,6 +200,25 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { .type_arguments = accept_type_arguments(ctx), .operands = expect_operands(ctx, bb) })); + } else if (strcmp(id, "ext_instr") == 0) { + expect(accept_token(ctx, lsbracket_tok)); + const Node* set = accept_value(ctx, NULL); + assert(set->tag == StringLiteral_TAG); + expect(accept_token(ctx, comma_tok)); + const Node* opcode = accept_value(ctx, NULL); + assert(opcode->tag == UntypedNumber_TAG); + expect(accept_token(ctx, comma_tok)); + const Type* type = accept_qualified_type(ctx); + expect(type); + expect(accept_token(ctx, rsbracket_tok)); + Nodes ops = expect_operands(ctx, bb); + return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { + .result_t = type, + .set = set->payload.string_lit.string, + .opcode = strtoll(opcode->payload.untyped_number.plaintext, NULL, 10), + .mem = bb_mem(bb), + .operands = ops, + })); } else if (strcmp(id, "alloca") == 0) { const Node* type = first(accept_type_arguments(ctx)); Nodes ops = expect_operands(ctx, bb); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 0fa37aa00..3b71a1f40 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -75,6 +75,10 @@ Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { return bind_internal(bb, instruction, singleton(instruction->type).count); } +const Node* bind_instruction_single(BodyBuilder* bb, const Node* instr) { + return first(bind_instruction_outputs_count(bb, instr, 1)); +} + Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String const output_names[]) { assert(bb->arena->config.check_types); assert(output_names); diff --git a/src/shady/fold.c b/src/shady/fold.c index f505a493f..75b2726a4 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -301,8 +301,8 @@ static const Node* fold_prim_op(IrArena* arena, const Node* node) { PrimOp payload = node->payload.prim_op; switch (payload.op) { - case subgroup_assume_uniform_op: - case subgroup_broadcast_first_op: { + // TODO: case subgroup_broadcast_first_op: + case subgroup_assume_uniform_op: { const Node* value = first(payload.operands); if (is_qualified_type_uniform(value->type)) return quote_single(arena, value); diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index f3255d125..213245d4a 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -44,7 +44,7 @@ fn builtin_entry_join_point uniform JoinPoint() { @Internal @Leaf fn builtin_create_control_point varying JoinPoint(uniform u32 join_destination, varying u32 payload) { val curr_mask = subgroup_active_mask(); - val depth = subgroup_broadcast_first(scheduler_vector#(subgroup_local_id)#1); + val depth = ext_instr["spirv.core", 338, uniform u32](scheduler_vector#(subgroup_local_id)#1); val tree_node = composite TreeNode(curr_mask, depth); val jp = composite JoinPoint(tree_node, join_destination, payload); @@ -56,7 +56,7 @@ fn builtin_create_control_point varying JoinPoint(uniform u32 join_destination, @Internal @Leaf fn builtin_fork(varying u32 branch_destination) { - val first_branch = subgroup_broadcast_first(branch_destination); + val first_branch = ext_instr["spirv.core", 338, uniform u32](branch_destination); // if there is disagreement on the destination, then increase the depth of every branch val uniform_branch = subgroup_active_mask() == subgroup_ballot(first_branch == branch_destination); @@ -68,7 +68,7 @@ fn builtin_fork(varying u32 branch_destination) { // Partition the set of branch destinations and adapt the masks in turn loop() { - val elected = subgroup_broadcast_first(branch_destination); + val elected = ext_instr["spirv.core", 338, uniform u32](branch_destination); resume_at#(subgroup_local_id) = elected; scheduler_vector#(subgroup_local_id)#0 = subgroup_ballot(elected == branch_destination); if (elected == branch_destination) { @@ -79,8 +79,8 @@ fn builtin_fork(varying u32 branch_destination) { // We must pick one branch as our 'favourite child' to schedule for immediate execution // we could do fancy intrinsics, but for now we'll just pick the first one if (subgroup_elect_first()) { - next_fn = subgroup_broadcast_first(branch_destination); - active_branch = subgroup_broadcast_first(scheduler_vector#(subgroup_local_id)); + next_fn = ext_instr["spirv.core", 338, uniform u32](branch_destination); + active_branch = ext_instr["spirv.core", 338, uniform TreeNode](scheduler_vector#(subgroup_local_id)); // tag those variables as not in use# // resume_at#(subgroup_local_id) = -1; @@ -155,8 +155,8 @@ fn builtin_find_schedulable_leaf() { continue(i + u32 1); } - next_fn = subgroup_broadcast_first(resume_at#reduced); - active_branch = subgroup_broadcast_first(scheduler_vector#reduced); + next_fn = ext_instr["spirv.core", 338, uniform u32](resume_at#reduced); + active_branch = ext_instr["spirv.core", 338, uniform TreeNode](scheduler_vector#reduced); return (); } diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index a3b0fa7a3..1917cc9aa 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -375,9 +375,6 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe case subgroup_elect_first_op: input_types = nodes(a, 0, NULL); break; - case subgroup_broadcast_first_op: - new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); - goto rebuild; case subgroup_ballot_op: input_types = singleton(qualified_type_helper(bool_type(a), false)); break; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 3c2ebb040..f5b211e7b 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -84,7 +84,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { const Node* return_jp = ctx->return_jp; if (return_jp) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, old->payload.fn_ret.mem)); - return_jp = gen_primop_ce(bb, subgroup_broadcast_first_op, 1, (const Node* []) {return_jp}); + return_jp = gen_primop_ce(bb, subgroup_assume_uniform_op, 1, (const Node* []) { return_jp }); // Join up at the return address instead of returning return finish_body(bb, join(a, (Join) { .join_point = return_jp, diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 700b1e78f..f2e8431d0 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -124,7 +124,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo Node* default_case = case_(a, empty(a)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); - const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), default_case)); + const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, (const Node**) cases), default_case)); set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value), .mem = bb_mem(bb) }))); break; } @@ -154,7 +154,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo Node* default_case = case_(a, empty(a)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(new_fn) })); - gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, cases), default_case); + gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, (const Node**) cases), default_case); set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) }))); break; } diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 7f9488a48..c63c83189 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -8,6 +8,10 @@ #include "log.h" #include "dict.h" +#include + +#include + typedef struct { Rewriter rewriter; const CompilerConfig* config; @@ -101,9 +105,9 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* src) { IrArena* a = ctx->rewriter.dst_arena; Module* m = ctx->rewriter.dst_module; - const Node* t = get_unqualified_type(src->type); + const Node* t = get_unqualified_type(src->type); if (is_supported_natively(ctx, t)) - return gen_primop_e(bb, subgroup_broadcast_first_op, empty(a), singleton(src)); + return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, qualified_type_helper(t, true), singleton(src)); Node* fn = NULL; Node** found = find_value_dict(const Node*, Node*, ctx->fns, t); @@ -128,16 +132,12 @@ static const Node* process(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (node->tag) { - case PrimOp_TAG: { - PrimOp payload = node->payload.prim_op; - switch (payload.op) { - case subgroup_broadcast_first_op: { - error("TODO") - /*BodyBuilder* bb = begin_body(a); - return yield_values_and_wrap_in_block(bb, singleton( - build_subgroup_first(ctx, bb, rewrite_node(r, first(payload.operands)))));*/ - } - default: break; + case ExtInstr_TAG: { + ExtInstr payload = node->payload.ext_instr; + if (strcmp(payload.set, "spirv.core") == 0 && payload.opcode == SpvOpGroupNonUniformBroadcastFirst) { + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + return yield_values_and_wrap_in_block(bb, singleton( + build_subgroup_first(ctx, bb, rewrite_node(r, first(payload.operands))))); } } default: break; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 0eaf22ce4..b89f309a0 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -147,7 +147,7 @@ static const Node* process(Context* ctx, const Node* old) { set_value_name((Node*) popped, old_param->payload.param.name); // TODO use the uniform stack instead ? or no ? if (is_qualified_type_uniform(old_param->type)) - popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_broadcast_first_op, .type_arguments = empty(a), .operands = singleton(popped) }), &old_param->payload.param.name)); + popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = empty(a), .operands = singleton(popped) }), &old_param->payload.param.name)); register_processed(&ctx->rewriter, old_param, popped); } register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 689454a86..e681a2d6c 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -152,7 +152,7 @@ static const Node* process(Context* ctx, const Node* node) { if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* loaded = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); - const Node* uniformized = first(gen_primop(bb, subgroup_broadcast_first_op, empty(a), singleton(loaded))); + const Node* uniformized = first(gen_primop(bb, subgroup_assume_uniform_op, empty(a), singleton(loaded))); return yield_values_and_wrap_in_block(bb, singleton(uniformized)); } } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index d01d648b7..028cdd5e6 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -230,7 +230,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { } BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - gen_match(bb, empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), nodes(a, body->payload.br_switch.case_jumps.count, cases), default_case); + gen_match(bb, empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), nodes(a, body->payload.br_switch.case_jumps.count, (const Node**) cases), default_case); return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); } // let(control(body), tail) diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 4743e5220..d27d84fed 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -39,6 +39,16 @@ const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { return first(result); } +const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { + return bind_instruction_single(bb, ext_instr(bb->arena, (ExtInstr) { + .mem = bb_mem(bb), + .set = set, + .opcode = opcode, + .result_t = return_t, + .operands = operands, + })); +} + void gen_push_value_stack(BodyBuilder* bb, const Node* value) { bind_instruction(bb, push_stack(bb->arena, (PushStack) { .value = value, .mem = bb_mem(bb) })); } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index ff9b2fe47..c974520a4 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -16,6 +16,7 @@ Nodes gen_primop(BodyBuilder*, Op, Nodes, Nodes); Nodes gen_primop_c(BodyBuilder*, Op op, size_t operands_count, const Node* operands[]); const Node* gen_primop_ce(BodyBuilder*, Op op, size_t operands_count, const Node* operands[]); const Node* gen_primop_e(BodyBuilder*, Op op, Nodes, Nodes); +const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); const Node* gen_reinterpret_cast(BodyBuilder*, const Type* dst, const Node* src); const Node* gen_conversion(BodyBuilder*, const Type* dst, const Node* src); diff --git a/src/shady/type.c b/src/shady/type.c index a629c69b7..713d7d1fe 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -866,7 +866,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { }); } case subgroup_assume_uniform_op: - case subgroup_broadcast_first_op: case subgroup_reduce_sum_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); @@ -906,8 +905,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { } const Type* check_type_ext_instr(IrArena* arena, ExtInstr payload) { - assert(is_data_type(payload.result_t)); - return qualified_type_helper(payload.result_t, false); + return payload.result_t; } static void check_arguments_types_against_parameters_helper(Nodes param_types, Nodes arg_types) { From df9521f39c2c94617ec9a0c35a36e7a01368e1f0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 10 Aug 2024 18:10:33 +0200 Subject: [PATCH 446/693] fixed lower_subgroup_vars --- src/shady/passes/lower_subgroup_vars.c | 51 ++++++++++++++++++-------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 5c5c206a3..2d48d0cef 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -1,3 +1,5 @@ +#include + #include "pass.h" #include "../type.h" @@ -9,9 +11,10 @@ typedef struct { Rewriter rewriter; const CompilerConfig* config; + BodyBuilder* bb; } Context; -static const Node* process(Context* ctx, NodeClass class, String op_name, const Node* node) { +static const Node* process(Context* ctx, const Node* node) { if (!node) return NULL; const Node* found = search_processed(&ctx->rewriter, node); if (found) return found; @@ -20,6 +23,20 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const IrArena* a = r->dst_arena; switch (node->tag) { + case Function_TAG: { + Node* newfun = recreate_decl_header_identity(r, node); + Context functx = *ctx; + functx.rewriter.map = clone_dict(functx.rewriter.map); + clear_dict(functx.rewriter.map); + register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); + functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); + Node* post_prelude = basic_block(a, empty(a), "post-prelude"); + register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); + set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); + set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); + destroy_dict(functx.rewriter.map); + return newfun; + } case PtrType_TAG: { AddressSpace as = node->payload.ptr_type.address_space; if (as == AsSubgroup) { @@ -31,30 +48,29 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const const Node* odecl = node->payload.ref_decl.decl; if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsSubgroup) break; - const Node* ndecl = rewrite_op(&ctx->rewriter, NcDeclaration, "decl", odecl); - error("TODO") - // assert(ctx->b); - // const Node* index = gen_builtin_load(ctx->rewriter.dst_module, ctx->b, BuiltinSubgroupId); - // const Node* slice = gen_lea(ctx->b, ref_decl_helper(a, ndecl), int32_literal(a, 0), mk_nodes(a, index)); - // return slice; + const Node* ndecl = rewrite_node(&ctx->rewriter, odecl); + assert(ctx->bb); + const Node* index = gen_builtin_load(ctx->rewriter.dst_module, ctx->bb, BuiltinSubgroupId); + const Node* slice = gen_lea(ctx->bb, ref_decl_helper(a, ndecl), int32_literal(a, 0), mk_nodes(a, index)); + return slice; } case GlobalVariable_TAG: { AddressSpace as = node->payload.global_variable.address_space; if (as == AsSubgroup) { - const Type* ntype = rewrite_op(&ctx->rewriter, NcType, "type", node->payload.global_variable.type); + const Type* ntype = rewrite_node(&ctx->rewriter, node->payload.global_variable.type); const Type* atype = arr_type(a, (ArrType) { .element_type = ntype, - .size = ref_decl_helper(a, rewrite_op(&ctx->rewriter, NcDeclaration, "decl", get_declaration(ctx->rewriter.src_module, "SUBGROUPS_PER_WG"))) + .size = ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_declaration(ctx->rewriter.src_module, "SUBGROUPS_PER_WG"))) }); assert(lookup_annotation(node, "Logical") && "All subgroup variables should be logical by now!"); - Node* new = global_var(ctx->rewriter.dst_module, rewrite_ops(&ctx->rewriter, NcAnnotation, "annotations", node->payload.global_variable.annotations), atype, node->payload.global_variable.name, AsShared); + Node* new = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations), atype, node->payload.global_variable.name, AsShared); register_processed(&ctx->rewriter, node, new); if (node->payload.global_variable.init) { new->payload.global_variable.init = fill(a, (Fill) { .type = atype, - .value = rewrite_op(&ctx->rewriter, NcValue, "init", node->payload.global_variable.init) + .value = rewrite_node(&ctx->rewriter, node->payload.global_variable.init) }); } return new; @@ -64,10 +80,13 @@ static const Node* process(Context* ctx, NodeClass class, String op_name, const default: break; } - const Node* new = recreate_node_identity(&ctx->rewriter, node); - if (is_instruction(new)) - register_processed(r, node, new); - return new; + if (is_declaration(node)) { + Context declctx = *ctx; + declctx.bb = NULL; + return recreate_node_identity(&declctx.rewriter, node); + } + + return recreate_node_identity(&ctx->rewriter, node); } Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { @@ -75,7 +94,7 @@ Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process), + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; rewrite_module(&ctx.rewriter); From 2477851027291a8cf3e70a6f12b4fa67afefd973 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 11:11:37 +0200 Subject: [PATCH 447/693] spv: converted emit_instruction to single-return --- src/backend/spirv/emit_spv.h | 2 +- src/backend/spirv/emit_spv_instructions.c | 166 +++++++--------------- src/backend/spirv/spirv_builder.c | 4 + src/backend/spirv/spirv_builder.h | 1 + 4 files changed, 57 insertions(+), 116 deletions(-) diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index 9f6b7dbac..62b7b592a 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -41,7 +41,7 @@ typedef struct { SpvId emit_decl(Emitter*, const Node*); SpvId emit_type(Emitter*, const Type*); SpvId emit_value(Emitter*, BBBuilder, const Node*); -void emit_instruction(Emitter*, FnBuilder, BBBuilder, const Node* instruction, size_t results_count, SpvId results[]); +SpvId emit_instruction(Emitter*, BBBuilder, const Node* instruction); void emit_terminator(Emitter*, FnBuilder, BBBuilder, MergeTargets, const Node* terminator); SpvId find_reserved_id(Emitter* emitter, const Node* node); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_instructions.c index 799a904bf..93b98dfa5 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_instructions.c @@ -170,14 +170,13 @@ static SpvOp get_opcode(SHADY_UNUSED Emitter* emitter, IselTableEntry entry, Nod } } -static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, const Node* instr, size_t results_count, SpvId results[]) { +static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* instr) { PrimOp the_op = instr->payload.prim_op; Nodes args = the_op.operands; Nodes type_arguments = the_op.type_arguments; IselTableEntry entry = isel_table[the_op.op]; if (entry.class != Custom) { - assert(results_count <= 1); LARRAY(SpvId, emitted_args, args.count); for (size_t i = 0; i < args.count; i++) emitted_args[i] = emit_value(emitter, bb_builder, args.nodes[i]); @@ -186,35 +185,27 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui case Plain: { SpvOp opcode = get_opcode(emitter, entry, args, type_arguments); if (opcode == SpvOpNop) { - assert(results_count == 1); - results[0] = emitted_args[0]; - return; + assert(args.count == 1); + return emitted_args[0]; } error("TODO: convert spirv backend away from multiple returns") - /*Nodes results_ts = unwrap_multiple_yield_types(emitter->arena, instr->type); - SpvId result_t = results_ts.count >= 1 ? emit_type(emitter, instr->type) : emitter->void_t; + Nodes results_ts = unwrap_multiple_yield_types(emitter->arena, instr->type); + SpvId result_t = instr->type == empty_multiple_return_type(emitter->arena) ? emit_type(emitter, instr->type) : emitter->void_t; if (opcode == SpvOpMax) goto custom; if (entry.extended_set) { SpvId set_id = get_extended_instruction_set(emitter, entry.extended_set); - - SpvId result = spvb_ext_instruction(bb_builder, result_t, set_id, opcode, args.count, emitted_args); - if (results_count == 1) - results[0] = result; + return spvb_ext_instruction(bb_builder, result_t, set_id, opcode, args.count, emitted_args); } else { - SpvId result = spvb_op(bb_builder, opcode, result_t, args.count, emitted_args); - if (results_count == 1) - results[0] = result; + return spvb_op(bb_builder, opcode, result_t, args.count, emitted_args); } - return;*/ } case Custom: SHADY_UNREACHABLE; } - - return; + SHADY_UNREACHABLE; } custom: @@ -224,10 +215,10 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui const Type* src = get_unqualified_type(first(the_op.operands)->type); assert(dst->tag == PtrType_TAG && src->tag == PtrType_TAG); assert(src != dst); - results[0] = spvb_op(bb_builder, SpvOpBitcast, emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, bb_builder, first(the_op.operands)) }); - return; + return spvb_op(bb_builder, SpvOpBitcast, emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, bb_builder, first(the_op.operands)) }); } case subgroup_ballot_op: { + spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = uint32_type(emitter->arena) }); SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); SpvId raw_result = spvb_group_ballot(bb_builder, emit_type(emitter, i32x4), emit_value(emitter, bb_builder, first(args)), scope_subgroup); @@ -238,31 +229,22 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui SpvId hi64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &hi32); hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { hi64, emit_value(emitter, bb_builder, int64_literal(emitter->arena, 32)) }); SpvId final_result = spvb_op(bb_builder, SpvOpBitwiseOr, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { low64, hi64 }); - assert(results_count == 1); - results[0] = final_result; - spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); - return; + return final_result; } case subgroup_reduce_sum_op: { - SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); - assert(results_count == 1); - results[0] = spvb_group_non_uniform_iadd(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), emit_value(emitter, bb_builder, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformArithmetic); - return; + SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); + return spvb_group_non_uniform_iadd(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), emit_value(emitter, bb_builder, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); } case subgroup_elect_first_op: { + spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniform); SpvId result_t = emit_type(emitter, bool_type(emitter->arena)); SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); - SpvId result = spvb_group_elect(bb_builder, result_t, scope_subgroup); - assert(results_count == 1); - results[0] = result; - spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniform); - return; + return spvb_group_elect(bb_builder, result_t, scope_subgroup); } case insert_op: case extract_dynamic_op: case extract_op: { - assert(results_count == 1); bool insert = the_op.op == insert_op; const Node* src_value = first(args); @@ -279,20 +261,18 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui indices[i] = emit_value(emitter, bb_builder, args.nodes[i + indices_start]); } assert(indices_count == 1); - results[0] = spvb_vector_extract_dynamic(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, src_value), indices[0]); - } else { - LARRAY(uint32_t, indices, indices_count); - for (size_t i = 0; i < indices_count; i++) { - // TODO: fallback to Dynamic variants transparently - indices[i] = get_int_literal_value(*resolve_to_int_literal(args.nodes[i + indices_start]), false); - } - - if (!insert) { - results[0] = spvb_extract(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, src_value), indices_count, indices); - } else - results[0] = spvb_insert(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, args.nodes[1]), emit_value(emitter, bb_builder, src_value), indices_count, indices); + return spvb_vector_extract_dynamic(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, src_value), indices[0]); + } + LARRAY(uint32_t, indices, indices_count); + for (size_t i = 0; i < indices_count; i++) { + // TODO: fallback to Dynamic variants transparently + indices[i] = get_int_literal_value(*resolve_to_int_literal(args.nodes[i + indices_start]), false); } - return; + + if (insert) + return spvb_insert(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, args.nodes[1]), emit_value(emitter, bb_builder, src_value), indices_count, indices); + else + return spvb_extract(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, src_value), indices_count, indices); } case shuffle_op: { const Type* result_t = instr->type; @@ -306,19 +286,14 @@ static void emit_primop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_bui else indices[i] = indice; } - assert(results_count == 1); - results[0] = spvb_vecshuffle(bb_builder, emit_type(emitter, result_t), a, b, args.count - 2, indices); - return; + return spvb_vecshuffle(bb_builder, emit_type(emitter, result_t), a, b, args.count - 2, indices); } case select_op: { SpvId cond = emit_value(emitter, bb_builder, first(args)); SpvId truv = emit_value(emitter, bb_builder, args.nodes[1]); SpvId flsv = emit_value(emitter, bb_builder, args.nodes[2]); - SpvId result = spvb_select(bb_builder, emit_type(emitter, args.nodes[1]->type), cond, truv, flsv); - assert(results_count == 1); - results[0] = result; - return; + return spvb_select(bb_builder, emit_type(emitter, args.nodes[1]->type), cond, truv, flsv); } default: error("TODO: unhandled op"); } @@ -333,11 +308,8 @@ static SpvId emit_ext_instr(Emitter* emitter, BBBuilder bb_builder, ExtInstr ins SpvId result; if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { - SpvId local_id; const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); - // TODO: very hacky indeed - // emit_instruction(emitter, fn_builder, bb_builder, load(emitter->arena, (Load) { b }), 1, &local_id); - error("reimplement") + SpvId local_id = spvb_op(bb_builder, SpvOpLoad, emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { emit_value(emitter, bb_builder, b) }); result = spvb_group_shuffle(bb_builder, emit_type(emitter, instr.result_t), scope_subgroup, emit_value(emitter, bb_builder, first(instr.operands)), local_id); spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); } else { @@ -349,12 +321,19 @@ static SpvId emit_ext_instr(Emitter* emitter, BBBuilder bb_builder, ExtInstr ins } default: break; } - error("TODO: emit arbitrary spv instr here"); + LARRAY(SpvId, ops, instr.operands.count); + for (size_t i = 0; i < instr.operands.count; i++) + ops[i] = emit_value(emitter, bb_builder, instr.operands.nodes[i]); + return spvb_op(bb_builder, instr.opcode, emit_type(emitter, instr.result_t), instr.operands.count, ops); } - error("TODO: emit arbitrary ext spv instr here"); + LARRAY(SpvId, ops, instr.operands.count); + for (size_t i = 0; i < instr.operands.count; i++) + ops[i] = emit_value(emitter, bb_builder, instr.operands.nodes[i]); + SpvId set_id = get_extended_instruction_set(emitter, instr.set); + return spvb_ext_instruction(bb_builder, emit_type(emitter, instr.result_t), set_id, instr.opcode, instr.operands.count, ops); } -static void emit_leaf_call(Emitter* emitter, SHADY_UNUSED FnBuilder fn_builder, BBBuilder bb_builder, Call call, size_t results_count, SpvId results[]) { +static SpvId emit_leaf_call(Emitter* emitter, BBBuilder bb_builder, Call call) { const Node* fn = call.callee; assert(fn->tag == FnAddr_TAG); fn = fn->payload.fn_addr.fn; @@ -367,26 +346,10 @@ static void emit_leaf_call(Emitter* emitter, SHADY_UNUSED FnBuilder fn_builder, LARRAY(SpvId, args, call.args.count); for (size_t i = 0; i < call.args.count; i++) args[i] = emit_value(emitter, bb_builder, call.args.nodes[i]); - SpvId result = spvb_call(bb_builder, return_type, callee, call.args.count, args); - switch (results_count) { - case 0: break; - case 1: { - results[0] = result; - break; - } - default: { - assert(return_types.count == results_count); - for (size_t i = 0; i < results_count; i++) { - SpvId result_type = emit_type(emitter, return_types.nodes[i]->type); - SpvId extracted_component = spvb_extract(bb_builder, result_type, result, 1, (uint32_t []) { i }); - results[i] = extracted_component; - } - break; - } - } + return spvb_call(bb_builder, return_type, callee, call.args.count, args); } -void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, const Node* instruction, size_t results_count, SpvId results[]) { +SpvId emit_instruction(Emitter* emitter, BBBuilder bb_builder, const Node* instruction) { assert(is_instruction(instruction)); switch (is_instruction(instruction)) { @@ -400,35 +363,16 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build case Instruction_FillBytes_TAG: case Instruction_BindIdentifiers_TAG: case Instruction_StackAlloc_TAG: error("Should be lowered elsewhere") - case Instruction_ExtInstr_TAG: emit_ext_instr(emitter, bb_builder, instruction->payload.ext_instr); - case Instruction_Call_TAG: emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call, results_count, results); break; - case PrimOp_TAG: emit_primop(emitter, fn_builder, bb_builder, instruction, results_count, results); break; + case Instruction_ExtInstr_TAG: return emit_ext_instr(emitter, bb_builder, instruction->payload.ext_instr); + case Instruction_Call_TAG: return emit_leaf_call(emitter, bb_builder, instruction->payload.call); + case PrimOp_TAG: return emit_primop(emitter, bb_builder, instruction); case Comment_TAG: break; - /*case Instruction_CompoundInstruction_TAG: { - Nodes instructions = instruction->payload.compound_instruction.instructions; - for (size_t i = 0; i < instructions.count; i++) { - const Node* instruction2 = instructions.nodes[i]; - - // we declare N local variables in order to store the result of the instruction - Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, instruction2->type); - - LARRAY(SpvId, results2, yield_types.count); - emit_instruction(emitter, fn_builder, bb_builder, instruction2, yield_types.count, results2); - } - Nodes results2 = instruction->payload.compound_instruction.results; - for (size_t i = 0; i < results2.count; i++) { - results[0] = emit_value(emitter, bb_builder, results2.nodes[i]); - } - return; - }*/ case Instruction_LocalAlloc_TAG: { - SpvId result = spvb_local_variable(fn_builder, emit_type(emitter, ptr_type(emitter->arena, (PtrType) { + assert(bb_builder); + return spvb_local_variable(spvb_get_fn_builder(bb_builder), emit_type(emitter, ptr_type(emitter->arena, (PtrType) { .address_space = AsFunction, .pointed_type = instruction->payload.local_alloc.type })), SpvStorageClassFunction); - assert(results_count == 1); - results[0] = result; - return; } case Instruction_Load_TAG: { Load payload = instruction->payload.load; @@ -448,10 +392,7 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build } SpvId eptr = emit_value(emitter, bb_builder, payload.ptr); - SpvId result = spvb_load(bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); - assert(results_count == 1); - results[0] = result; - return; + return spvb_load(bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); } case Instruction_Store_TAG: { Store payload = instruction->payload.store; @@ -473,8 +414,7 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build SpvId eptr = emit_value(emitter, bb_builder, payload.ptr); SpvId eval = emit_value(emitter, bb_builder, payload.value); spvb_store(bb_builder, eval, eptr, operands_count, operands); - assert(results_count == 0); - return; + return 0; } case Lea_TAG: { Lea payload = instruction->payload.lea; @@ -487,16 +427,11 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build const IntLiteral* known_offset = resolve_to_int_literal(payload.offset); if (known_offset && known_offset->value == 0) { const Type* target_type = instruction->type; - SpvId result = spvb_access_chain(bb_builder, emit_type(emitter, target_type), base, payload.indices.count, indices); - assert(results_count == 1); - results[0] = result; + return spvb_access_chain(bb_builder, emit_type(emitter, target_type), base, payload.indices.count, indices); } else { const Type* target_type = instruction->type; - SpvId result = spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, emit_value(emitter, bb_builder, payload.offset), payload.indices.count, indices); - assert(results_count == 1); - results[0] = result; + return spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, emit_value(emitter, bb_builder, payload.offset), payload.indices.count, indices); } - return; } case Instruction_DebugPrintf_TAG: { SpvId set_id = get_extended_instruction_set(emitter, "NonSemantic.DebugPrintf"); @@ -505,6 +440,7 @@ void emit_instruction(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_build for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) args[i + 1] = emit_value(emitter, bb_builder, instruction->payload.debug_printf.args.nodes[i]); spvb_ext_instruction(bb_builder, emit_type(emitter, instruction->type), set_id, (SpvOp) NonSemanticDebugPrintfDebugPrintf, instruction->payload.debug_printf.args.count + 1, args); + return 0; } } } diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index cdef57206..e31a59bef 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -648,6 +648,10 @@ SpvbBasicBlockBuilder* spvb_begin_bb(SpvbFnBuilder* fn_builder, SpvId label) { return bbb; } +SpvbFnBuilder* spvb_get_fn_builder(SpvbBasicBlockBuilder* bb_builder) { + return bb_builder->fn_builder; +} + void spvb_add_bb(SpvbFnBuilder* fn_builder, SpvbBasicBlockBuilder* bb_builder) { append_list(SpvbBasicBlockBuilder*, fn_builder->bbs, bb_builder); } diff --git a/src/backend/spirv/spirv_builder.h b/src/backend/spirv/spirv_builder.h index d769336a5..8a39cdb6e 100644 --- a/src/backend/spirv/spirv_builder.h +++ b/src/backend/spirv/spirv_builder.h @@ -73,6 +73,7 @@ void spvb_declare_function(SpvbFileBuilder*, SpvbFnBuilder* fn_builder); void spvb_define_function(SpvbFileBuilder*, SpvbFnBuilder* fn_builder); SpvbBasicBlockBuilder* spvb_begin_bb(SpvbFnBuilder*, SpvId label); +SpvbFnBuilder* spvb_get_fn_builder(SpvbBasicBlockBuilder*); /// Actually adds the basic block to the function /// This is a separate action from begin_bb because the ordering in which the basic blocks are written matters... void spvb_add_bb(SpvbFnBuilder*, SpvbBasicBlockBuilder*); From 1d5e46a150b7725deb644f7f526dd632b4dd2bf2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 11:21:03 +0200 Subject: [PATCH 448/693] backends: put value code near instruction code --- src/backend/c/CMakeLists.txt | 6 +- src/backend/c/emit_c.c | 255 ++---------------- .../c/{emit_c_builtins.c => emit_c_builtin.c} | 0 .../c/{emit_c_signatures.c => emit_c_type.c} | 0 .../{emit_c_instructions.c => emit_c_value.c} | 229 ++++++++++++++-- src/backend/spirv/CMakeLists.txt | 2 +- src/backend/spirv/emit_spv.c | 113 +------- ...it_spv_instructions.c => emit_spv_value.c} | 110 ++++++++ 8 files changed, 349 insertions(+), 366 deletions(-) rename src/backend/c/{emit_c_builtins.c => emit_c_builtin.c} (100%) rename src/backend/c/{emit_c_signatures.c => emit_c_type.c} (100%) rename src/backend/c/{emit_c_instructions.c => emit_c_value.c} (79%) rename src/backend/spirv/{emit_spv_instructions.c => emit_spv_value.c} (84%) diff --git a/src/backend/c/CMakeLists.txt b/src/backend/c/CMakeLists.txt index 6094feb58..6928a00f7 100644 --- a/src/backend/c/CMakeLists.txt +++ b/src/backend/c/CMakeLists.txt @@ -1,8 +1,8 @@ add_library(shady_c STATIC emit_c.c - emit_c_instructions.c - emit_c_signatures.c - emit_c_builtins.c + emit_c_value.c + emit_c_type.c + emit_c_builtin.c ) set_property(TARGET shady_c PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 0a43aee1e..138019065 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -17,7 +17,6 @@ #include #include #include -#include #pragma GCC diagnostic error "-Wswitch" @@ -70,42 +69,6 @@ String legalize_c_identifier(Emitter* e, String src) { return string(e->arena, dst); } -#include - -static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e, Printer* block_printer, Printer* p, Growy* g, const Node* t, Nodes c) { - if (t->tag == Int_TAG && t->payload.int_type.width == 8) { - uint8_t* tmp = malloc(sizeof(uint8_t) * c.count); - bool ends_zero = false; - for (size_t i = 0; i < c.count; i++) { - tmp[i] = get_int_literal_value(*resolve_to_int_literal(c.nodes[i]), false); - if (tmp[i] == 0) { - if (i == c.count - 1) - ends_zero = true; - } - } - bool is_stringy = ends_zero; - for (size_t i = 0; i < c.count; i++) { - // ignore the last char in a string - if (is_stringy && i == c.count - 1) - break; - if (isprint(tmp[i])) - print(p, "%c", tmp[i]); - else - print(p, "\\x%02x", tmp[i]); - } - free(tmp); - return is_stringy ? StringLit : CharsLit; - } else { - for (size_t i = 0; i < c.count; i++) { - print(p, to_cvalue(e, emit_value(e, block_printer, c.nodes[i]))); - if (i + 1 < c.count) - print(p, ", "); - } - growy_append_bytes(g, 1, "\0"); - return ObjectsList; - } -} - static bool has_forward_declarations(CDialect dialect) { switch (dialect) { case CDialect_C11: return true; @@ -116,6 +79,34 @@ static bool has_forward_declarations(CDialect dialect) { } } +/// hack for ISPC: there is no nice way to get a set of varying pointers (instead of a "pointer to a varying") pointing to a varying global +CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term) { + String interm = unique_name(emitter->arena, "intermediary_ptr_value"); + const Type* ut = qualified_type_helper(ptr_type, true); + const Type* vt = qualified_type_helper(ptr_type, false); + String lhs = emit_type(emitter, vt, interm); + print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, emit_type(emitter, ut, NULL), to_cvalue(emitter, term)); + return term_from_cvalue(interm); +} + +CTerm bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { + String bind_to = unique_name(emitter->arena, ""); + emit_variable_declaration(emitter, p, t, bind_to, false, &term); + return term_from_cvalue(bind_to); +} + +void emit_pack_code(Printer* p, Strings src, String dst) { + for (size_t i = 0; i < src.count; i++) { + print(p, "\n%s->_%d = %s", dst, src.strings[i], i); + } +} + +void emit_unpack_code(Printer* p, String src, Strings dst) { + for (size_t i = 0; i < dst.count; i++) { + print(p, "\n%s = %s->_%d", dst.strings[i], src, i); + } +} + static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, String decl_center, const Type* type, bool constant, String init) { String prefix = NULL; @@ -201,190 +192,6 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S //print(emitter->fn_decls, "\n%s;", declaration); } -CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { - CTerm* found = lookup_existing_term(emitter, value); - if (found) return *found; - - String emitted = NULL; - - switch (is_value(value)) { - case NotAValue: assert(false); - case Value_ConstrainedValue_TAG: - case Value_UntypedNumber_TAG: error("lower me"); - case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); - default: { - assert(!is_instruction(value)); - error("Unhandled value for code generation: %s", node_tags[value->tag]); - } - case Value_IntLiteral_TAG: { - if (value->payload.int_literal.is_signed) - emitted = format_string_arena(emitter->arena->arena, "%" PRIi64, value->payload.int_literal.value); - else - emitted = format_string_arena(emitter->arena->arena, "%" PRIu64, value->payload.int_literal.value); - - bool is_long = value->payload.int_literal.width == IntTy64; - bool is_signed = value->payload.int_literal.is_signed; - if (emitter->config.dialect == CDialect_GLSL && emitter->config.glsl_version >= 130) { - if (!is_signed) - emitted = format_string_arena(emitter->arena->arena, "%sU", emitted); - if (is_long) - emitted = format_string_arena(emitter->arena->arena, "%sL", emitted); - } - - break; - } - case Value_FloatLiteral_TAG: { - uint64_t v = value->payload.float_literal.value; - switch (value->payload.float_literal.width) { - case FloatTy16: - assert(false); - case FloatTy32: { - float f; - memcpy(&f, &v, sizeof(uint32_t)); - double d = (double) f; - emitted = format_string_arena(emitter->arena->arena, "%#.9gf", d); break; - } - case FloatTy64: { - double d; - memcpy(&d, &v, sizeof(uint64_t)); - emitted = format_string_arena(emitter->arena->arena, "%.17g", d); break; - } - } - break; - } - case Value_True_TAG: return term_from_cvalue("true"); - case Value_False_TAG: return term_from_cvalue("false"); - case Value_Undef_TAG: { - if (emitter->config.dialect == CDialect_GLSL) - return emit_value(emitter, block_printer, get_default_zero_value(emitter->arena, value->payload.undef.type)); - String name = unique_name(emitter->arena, "undef"); - emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); - emitted = name; - break; - } - case Value_NullPtr_TAG: return term_from_cvalue("NULL"); - case Value_Composite_TAG: { - const Type* type = value->payload.composite.type; - Nodes elements = value->payload.composite.contents; - - Growy* g = new_growy(); - Printer* p = open_growy_as_printer(g); - - if (type->tag == ArrType_TAG) { - switch (array_insides_helper(emitter, block_printer, p, g, type, elements)) { - case ObjectsList: - emitted = growy_data(g); - break; - case StringLit: - emitted = format_string_arena(emitter->arena->arena, "\"%s\"", growy_data(g)); - break; - case CharsLit: - emitted = format_string_arena(emitter->arena->arena, "'%s'", growy_data(g)); - break; - } - } else { - for (size_t i = 0; i < elements.count; i++) { - print(p, "%s", to_cvalue(emitter, emit_value(emitter, block_printer, elements.nodes[i]))); - if (i + 1 < elements.count) - print(p, ", "); - } - emitted = growy_data(g); - } - growy_append_bytes(g, 1, "\0"); - - switch (emitter->config.dialect) { - no_compound_literals: - case CDialect_ISPC: { - // arrays need double the brackets - if (type->tag == ArrType_TAG) - emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); - - if (block_printer) { - String tmp = unique_name(emitter->arena, "composite"); - print(block_printer, "\n%s = { %s };", emit_type(emitter, value->type, tmp), emitted); - emitted = tmp; - } else { - // this requires us to end up in the initialisation side of a declaration - emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); - } - break; - } - case CDialect_CUDA: - case CDialect_C11: - // If we're C89 (ew) - if (!emitter->config.allow_compound_literals) - goto no_compound_literals; - emitted = format_string_arena(emitter->arena->arena, "((%s) { %s })", emit_type(emitter, value->type, NULL), emitted); - break; - case CDialect_GLSL: - if (type->tag != PackType_TAG) - goto no_compound_literals; - // GLSL doesn't have compound literals, but it does have constructor syntax for vectors - emitted = format_string_arena(emitter->arena->arena, "%s(%s)", emit_type(emitter, value->type, NULL), emitted); - break; - } - - destroy_growy(g); - destroy_printer(p); - break; - } - case Value_Fill_TAG: error("lower me") - case Value_StringLiteral_TAG: { - Growy* g = new_growy(); - Printer* p = open_growy_as_printer(g); - - String str = value->payload.string_lit.string; - size_t len = strlen(str); - for (size_t i = 0; i < len; i++) { - char c = str[i]; - switch (c) { - case '\n': print(p, "\\n"); - break; - default: - growy_append_bytes(g, 1, &c); - } - } - growy_append_bytes(g, 1, "\0"); - - emitted = format_string_arena(emitter->arena->arena, "\"%s\"", growy_data(g)); - destroy_growy(g); - destroy_printer(p); - break; - } - case Value_FnAddr_TAG: { - emitted = legalize_c_identifier(emitter, get_declaration_name(value->payload.fn_addr.fn)); - emitted = format_string_arena(emitter->arena->arena, "(&%s)", emitted); - break; - } - case Value_RefDecl_TAG: { - const Node* decl = value->payload.ref_decl.decl; - emit_decl(emitter, decl); - - if (emitter->config.dialect == CDialect_ISPC && decl->tag == GlobalVariable_TAG) { - if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !is_decl_builtin(decl)) { - assert(block_printer && "ISPC backend cannot statically refer to a varying variable"); - return ispc_varying_ptr_helper(emitter, block_printer, decl->type, *lookup_existing_term(emitter, decl)); - } - } - - return *lookup_existing_term(emitter, decl); - } - } - - assert(emitted); - return term_from_cvalue(emitted); -} - -/// hack for ISPC: there is no nice way to get a set of varying pointers (instead of a "pointer to a varying") pointing to a varying global -CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term) { - String interm = unique_name(emitter->arena, "intermediary_ptr_value"); - const Type* ut = qualified_type_helper(ptr_type, true); - const Type* vt = qualified_type_helper(ptr_type, false); - String lhs = emit_type(emitter, vt, interm); - print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, emit_type(emitter, ut, NULL), to_cvalue(emitter, term)); - return term_from_cvalue(interm); -} - void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer) { assert((mut || initializer != NULL) && "unbound results are only allowed when creating a mutable local variable"); @@ -531,12 +338,6 @@ static void emit_loop(Emitter* emitter, Printer* p, Loop loop) { emit_terminator(emitter, p, get_abstraction_body(loop.tail)); } -CTerm bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { - String bind_to = unique_name(emitter->arena, ""); - emit_variable_declaration(emitter, p, t, bind_to, false, &term); - return term_from_cvalue(bind_to); -} - static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { switch (is_terminator(terminator)) { case NotATerminator: assert(false); diff --git a/src/backend/c/emit_c_builtins.c b/src/backend/c/emit_c_builtin.c similarity index 100% rename from src/backend/c/emit_c_builtins.c rename to src/backend/c/emit_c_builtin.c diff --git a/src/backend/c/emit_c_signatures.c b/src/backend/c/emit_c_type.c similarity index 100% rename from src/backend/c/emit_c_signatures.c rename to src/backend/c/emit_c_type.c diff --git a/src/backend/c/emit_c_instructions.c b/src/backend/c/emit_c_value.c similarity index 79% rename from src/backend/c/emit_c_instructions.c rename to src/backend/c/emit_c_value.c index c49ec4fcc..e2ad79c7d 100644 --- a/src/backend/c/emit_c_instructions.c +++ b/src/backend/c/emit_c_value.c @@ -7,44 +7,225 @@ #include "../shady/type.h" #include "../shady/ir_private.h" +#include "../shady/transform/ir_gen_helpers.h" #include #include #include #include +#include +#include #pragma GCC diagnostic error "-Wswitch" -void emit_pack_code(Printer* p, Strings src, String dst) { - for (size_t i = 0; i < src.count; i++) { - print(p, "\n%s->_%d = %s", dst, src.strings[i], i); +static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e, Printer* block_printer, Printer* p, Growy* g, const Node* t, Nodes c) { + if (t->tag == Int_TAG && t->payload.int_type.width == 8) { + uint8_t* tmp = malloc(sizeof(uint8_t) * c.count); + bool ends_zero = false; + for (size_t i = 0; i < c.count; i++) { + tmp[i] = get_int_literal_value(*resolve_to_int_literal(c.nodes[i]), false); + if (tmp[i] == 0) { + if (i == c.count - 1) + ends_zero = true; + } + } + bool is_stringy = ends_zero; + for (size_t i = 0; i < c.count; i++) { + // ignore the last char in a string + if (is_stringy && i == c.count - 1) + break; + if (isprint(tmp[i])) + print(p, "%c", tmp[i]); + else + print(p, "\\x%02x", tmp[i]); + } + free(tmp); + return is_stringy ? StringLit : CharsLit; + } else { + for (size_t i = 0; i < c.count; i++) { + print(p, to_cvalue(e, emit_value(e, block_printer, c.nodes[i]))); + if (i + 1 < c.count) + print(p, ", "); + } + growy_append_bytes(g, 1, "\0"); + return ObjectsList; } } -void emit_unpack_code(Printer* p, String src, Strings dst) { - for (size_t i = 0; i < dst.count; i++) { - print(p, "\n%s = %s->_%d", dst.strings[i], src, i); - } -} +CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { + CTerm* found = lookup_existing_term(emitter, value); + if (found) return *found; -static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String given_name, Strings* given_names, Nodes types, bool mut, const Nodes* init_values) { - if (given_names) - assert(given_names->count == types.count); - if (init_values) - assert(init_values->count == types.count); - LARRAY(String, names, types.count); - for (size_t i = 0; i < types.count; i++) { - String name = given_names ? given_names->strings[i] : given_name; - assert(name); - names[i] = unique_name(emitter->arena, name); - if (init_values) { - CTerm initializer = emit_value(emitter, p, init_values->nodes[i]); - emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); - } else - emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); + String emitted = NULL; + + switch (is_value(value)) { + case NotAValue: assert(false); + case Value_ConstrainedValue_TAG: + case Value_UntypedNumber_TAG: error("lower me"); + case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); + default: { + assert(!is_instruction(value)); + error("Unhandled value for code generation: %s", node_tags[value->tag]); + } + case Value_IntLiteral_TAG: { + if (value->payload.int_literal.is_signed) + emitted = format_string_arena(emitter->arena->arena, "%" PRIi64, value->payload.int_literal.value); + else + emitted = format_string_arena(emitter->arena->arena, "%" PRIu64, value->payload.int_literal.value); + + bool is_long = value->payload.int_literal.width == IntTy64; + bool is_signed = value->payload.int_literal.is_signed; + if (emitter->config.dialect == CDialect_GLSL && emitter->config.glsl_version >= 130) { + if (!is_signed) + emitted = format_string_arena(emitter->arena->arena, "%sU", emitted); + if (is_long) + emitted = format_string_arena(emitter->arena->arena, "%sL", emitted); + } + + break; + } + case Value_FloatLiteral_TAG: { + uint64_t v = value->payload.float_literal.value; + switch (value->payload.float_literal.width) { + case FloatTy16: + assert(false); + case FloatTy32: { + float f; + memcpy(&f, &v, sizeof(uint32_t)); + double d = (double) f; + emitted = format_string_arena(emitter->arena->arena, "%#.9gf", d); break; + } + case FloatTy64: { + double d; + memcpy(&d, &v, sizeof(uint64_t)); + emitted = format_string_arena(emitter->arena->arena, "%.17g", d); break; + } + } + break; + } + case Value_True_TAG: return term_from_cvalue("true"); + case Value_False_TAG: return term_from_cvalue("false"); + case Value_Undef_TAG: { + if (emitter->config.dialect == CDialect_GLSL) + return emit_value(emitter, block_printer, get_default_zero_value(emitter->arena, value->payload.undef.type)); + String name = unique_name(emitter->arena, "undef"); + emit_variable_declaration(emitter, block_printer, value->type, name, true, NULL); + // emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); + emitted = name; + break; + } + case Value_NullPtr_TAG: return term_from_cvalue("NULL"); + case Value_Composite_TAG: { + const Type* type = value->payload.composite.type; + Nodes elements = value->payload.composite.contents; + + Growy* g = new_growy(); + Printer* p = open_growy_as_printer(g); + + if (type->tag == ArrType_TAG) { + switch (array_insides_helper(emitter, block_printer, p, g, type, elements)) { + case ObjectsList: + emitted = growy_data(g); + break; + case StringLit: + emitted = format_string_arena(emitter->arena->arena, "\"%s\"", growy_data(g)); + break; + case CharsLit: + emitted = format_string_arena(emitter->arena->arena, "'%s'", growy_data(g)); + break; + } + } else { + for (size_t i = 0; i < elements.count; i++) { + print(p, "%s", to_cvalue(emitter, emit_value(emitter, block_printer, elements.nodes[i]))); + if (i + 1 < elements.count) + print(p, ", "); + } + emitted = growy_data(g); + } + growy_append_bytes(g, 1, "\0"); + + switch (emitter->config.dialect) { + no_compound_literals: + case CDialect_ISPC: { + // arrays need double the brackets + if (type->tag == ArrType_TAG) + emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); + + if (block_printer) { + String tmp = unique_name(emitter->arena, "composite"); + print(block_printer, "\n%s = { %s };", emit_type(emitter, value->type, tmp), emitted); + emitted = tmp; + } else { + // this requires us to end up in the initialisation side of a declaration + emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); + } + break; + } + case CDialect_CUDA: + case CDialect_C11: + // If we're C89 (ew) + if (!emitter->config.allow_compound_literals) + goto no_compound_literals; + emitted = format_string_arena(emitter->arena->arena, "((%s) { %s })", emit_type(emitter, value->type, NULL), emitted); + break; + case CDialect_GLSL: + if (type->tag != PackType_TAG) + goto no_compound_literals; + // GLSL doesn't have compound literals, but it does have constructor syntax for vectors + emitted = format_string_arena(emitter->arena->arena, "%s(%s)", emit_type(emitter, value->type, NULL), emitted); + break; + } + + destroy_growy(g); + destroy_printer(p); + break; + } + case Value_Fill_TAG: error("lower me") + case Value_StringLiteral_TAG: { + Growy* g = new_growy(); + Printer* p = open_growy_as_printer(g); + + String str = value->payload.string_lit.string; + size_t len = strlen(str); + for (size_t i = 0; i < len; i++) { + char c = str[i]; + switch (c) { + case '\n': print(p, "\\n"); + break; + default: + growy_append_bytes(g, 1, &c); + } + } + growy_append_bytes(g, 1, "\0"); + + emitted = format_string_arena(emitter->arena->arena, "\"%s\"", growy_data(g)); + destroy_growy(g); + destroy_printer(p); + break; + } + case Value_FnAddr_TAG: { + emitted = legalize_c_identifier(emitter, get_declaration_name(value->payload.fn_addr.fn)); + emitted = format_string_arena(emitter->arena->arena, "(&%s)", emitted); + break; + } + case Value_RefDecl_TAG: { + const Node* decl = value->payload.ref_decl.decl; + emit_decl(emitter, decl); + + if (emitter->config.dialect == CDialect_ISPC && decl->tag == GlobalVariable_TAG) { + if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !is_decl_builtin(decl)) { + assert(block_printer && "ISPC backend cannot statically refer to a varying variable"); + return ispc_varying_ptr_helper(emitter, block_printer, decl->type, *lookup_existing_term(emitter, decl)); + } + } + + return *lookup_existing_term(emitter, decl); + } } - return strings(emitter->arena, types.count, names); + + assert(emitted); + return term_from_cvalue(emitted); } static const Type* get_first_op_scalar_type(Nodes ops) { diff --git a/src/backend/spirv/CMakeLists.txt b/src/backend/spirv/CMakeLists.txt index b1df68860..89896ac1e 100644 --- a/src/backend/spirv/CMakeLists.txt +++ b/src/backend/spirv/CMakeLists.txt @@ -1,7 +1,7 @@ add_library(shady_spirv STATIC emit_spv.c emit_spv_type.c - emit_spv_instructions.c + emit_spv_value.c spirv_builder.c ) set_property(TARGET shady_spirv PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 1e8870b02..f60c102d1 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -1,3 +1,5 @@ +#include "emit_spv.h" + #include "shady/builtins.h" #include "../shady/ir_private.h" @@ -12,8 +14,6 @@ #include "growy.h" #include "util.h" -#include "emit_spv.h" - #include #include #include @@ -31,115 +31,6 @@ void register_result(Emitter* emitter, const Node* node, SpvId id) { insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, node, id); } -SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { - SpvId* existing = find_value_dict(const Node*, SpvId, emitter->node_ids, node); - if (existing) - return *existing; - - SpvId new; - switch (is_value(node)) { - case NotAValue: error(""); - case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); - case Value_ConstrainedValue_TAG: - case Value_UntypedNumber_TAG: - case Value_FnAddr_TAG: error("Should be lowered away earlier!"); - default: { - assert(!is_instruction(node)); - error("Unhandled value for code generation: %s", node_tags[node->tag]); - } - case IntLiteral_TAG: { - new = spvb_fresh_id(emitter->file_builder); - SpvId ty = emit_type(emitter, node->type); - // 64-bit constants take two spirv words, anything else fits in one - if (node->payload.int_literal.width == IntTy64) { - uint32_t arr[] = { node->payload.int_literal.value & 0xFFFFFFFF, node->payload.int_literal.value >> 32 }; - spvb_constant(emitter->file_builder, new, ty, 2, arr); - } else { - uint32_t arr[] = { node->payload.int_literal.value }; - spvb_constant(emitter->file_builder, new, ty, 1, arr); - } - break; - } - case FloatLiteral_TAG: { - new = spvb_fresh_id(emitter->file_builder); - SpvId ty = emit_type(emitter, node->type); - switch (node->payload.float_literal.width) { - case FloatTy16: { - uint32_t arr[] = { node->payload.float_literal.value & 0xFFFF }; - spvb_constant(emitter->file_builder, new, ty, 1, arr); - break; - } - case FloatTy32: { - uint32_t arr[] = { node->payload.float_literal.value }; - spvb_constant(emitter->file_builder, new, ty, 1, arr); - break; - } - case FloatTy64: { - uint32_t arr[] = { node->payload.float_literal.value & 0xFFFFFFFF, node->payload.float_literal.value >> 32 }; - spvb_constant(emitter->file_builder, new, ty, 2, arr); - break; - } - } - break; - } - case True_TAG: { - new = spvb_fresh_id(emitter->file_builder); - spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), true); - break; - } - case False_TAG: { - new = spvb_fresh_id(emitter->file_builder); - spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), false); - break; - } - case Value_StringLiteral_TAG: { - new = spvb_debug_string(emitter->file_builder, node->payload.string_lit.string); - break; - } - case Value_NullPtr_TAG: { - new = spvb_constant_null(emitter->file_builder, emit_type(emitter, node->payload.null_ptr.ptr_type)); - break; - } - case Composite_TAG: { - Nodes contents = node->payload.composite.contents; - LARRAY(SpvId, ids, contents.count); - for (size_t i = 0; i < contents.count; i++) { - ids[i] = emit_value(emitter, bb_builder, contents.nodes[i]); - } - if (bb_builder) { - new = spvb_composite(bb_builder, emit_type(emitter, node->type), contents.count, ids); - return new; - } else { - new = spvb_constant_composite(emitter->file_builder, emit_type(emitter, node->type), contents.count, ids); - break; - } - } - case Value_Undef_TAG: { - new = spvb_undef(emitter->file_builder, emit_type(emitter, node->payload.undef.type)); - break; - } - case Value_Fill_TAG: error("lower me") - case RefDecl_TAG: { - const Node* decl = node->payload.ref_decl.decl; - switch (decl->tag) { - case GlobalVariable_TAG: { - new = emit_decl(emitter, decl); - break; - } - case Constant_TAG: { - new = emit_value(emitter, NULL, decl->payload.constant.value); - break; - } - default: error("RefDecl must reference a constant or global"); - } - break; - } - } - - insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, node, new); - return new; -} - SpvId spv_find_reserved_id(Emitter* emitter, const Node* node) { SpvId* found = find_value_dict(const Node*, SpvId, emitter->node_ids, node); assert(found); diff --git a/src/backend/spirv/emit_spv_instructions.c b/src/backend/spirv/emit_spv_value.c similarity index 84% rename from src/backend/spirv/emit_spv_instructions.c rename to src/backend/spirv/emit_spv_value.c index 93b98dfa5..22fa5a380 100644 --- a/src/backend/spirv/emit_spv_instructions.c +++ b/src/backend/spirv/emit_spv_value.c @@ -1,6 +1,7 @@ #include "emit_spv.h" #include "log.h" +#include "dict.h" #include "portability.h" #include "../shady/type.h" @@ -13,6 +14,115 @@ #include "spirv/unified1/NonSemanticDebugPrintf.h" #include "spirv/unified1/GLSL.std.450.h" +SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { + SpvId* existing = find_value_dict(const Node*, SpvId, emitter->node_ids, node); + if (existing) + return *existing; + + SpvId new; + switch (is_value(node)) { + case NotAValue: error(""); + case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); + case Value_ConstrainedValue_TAG: + case Value_UntypedNumber_TAG: + case Value_FnAddr_TAG: error("Should be lowered away earlier!"); + default: { + assert(!is_instruction(node)); + error("Unhandled value for code generation: %s", node_tags[node->tag]); + } + case IntLiteral_TAG: { + new = spvb_fresh_id(emitter->file_builder); + SpvId ty = emit_type(emitter, node->type); + // 64-bit constants take two spirv words, anything else fits in one + if (node->payload.int_literal.width == IntTy64) { + uint32_t arr[] = { node->payload.int_literal.value & 0xFFFFFFFF, node->payload.int_literal.value >> 32 }; + spvb_constant(emitter->file_builder, new, ty, 2, arr); + } else { + uint32_t arr[] = { node->payload.int_literal.value }; + spvb_constant(emitter->file_builder, new, ty, 1, arr); + } + break; + } + case FloatLiteral_TAG: { + new = spvb_fresh_id(emitter->file_builder); + SpvId ty = emit_type(emitter, node->type); + switch (node->payload.float_literal.width) { + case FloatTy16: { + uint32_t arr[] = { node->payload.float_literal.value & 0xFFFF }; + spvb_constant(emitter->file_builder, new, ty, 1, arr); + break; + } + case FloatTy32: { + uint32_t arr[] = { node->payload.float_literal.value }; + spvb_constant(emitter->file_builder, new, ty, 1, arr); + break; + } + case FloatTy64: { + uint32_t arr[] = { node->payload.float_literal.value & 0xFFFFFFFF, node->payload.float_literal.value >> 32 }; + spvb_constant(emitter->file_builder, new, ty, 2, arr); + break; + } + } + break; + } + case True_TAG: { + new = spvb_fresh_id(emitter->file_builder); + spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), true); + break; + } + case False_TAG: { + new = spvb_fresh_id(emitter->file_builder); + spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), false); + break; + } + case Value_StringLiteral_TAG: { + new = spvb_debug_string(emitter->file_builder, node->payload.string_lit.string); + break; + } + case Value_NullPtr_TAG: { + new = spvb_constant_null(emitter->file_builder, emit_type(emitter, node->payload.null_ptr.ptr_type)); + break; + } + case Composite_TAG: { + Nodes contents = node->payload.composite.contents; + LARRAY(SpvId, ids, contents.count); + for (size_t i = 0; i < contents.count; i++) { + ids[i] = emit_value(emitter, bb_builder, contents.nodes[i]); + } + if (bb_builder) { + new = spvb_composite(bb_builder, emit_type(emitter, node->type), contents.count, ids); + return new; + } else { + new = spvb_constant_composite(emitter->file_builder, emit_type(emitter, node->type), contents.count, ids); + break; + } + } + case Value_Undef_TAG: { + new = spvb_undef(emitter->file_builder, emit_type(emitter, node->payload.undef.type)); + break; + } + case Value_Fill_TAG: error("lower me") + case RefDecl_TAG: { + const Node* decl = node->payload.ref_decl.decl; + switch (decl->tag) { + case GlobalVariable_TAG: { + new = emit_decl(emitter, decl); + break; + } + case Constant_TAG: { + new = emit_value(emitter, NULL, decl->payload.constant.value); + break; + } + default: error("RefDecl must reference a constant or global"); + } + break; + } + } + + insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, node, new); + return new; +} + typedef enum { Custom, Plain, } InstrClass; From 2fde749927f0e25aa2e54932b3590252fabff217 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 11:32:51 +0200 Subject: [PATCH 449/693] backends: moved control flow to own files --- src/backend/c/CMakeLists.txt | 1 + src/backend/c/emit_c.c | 247 +---------------- src/backend/c/emit_c.h | 2 +- src/backend/c/emit_c_control_flow.c | 249 +++++++++++++++++ src/backend/spirv/CMakeLists.txt | 1 + src/backend/spirv/emit_spv.c | 302 +-------------------- src/backend/spirv/emit_spv.h | 1 + src/backend/spirv/emit_spv_control_flow.c | 309 ++++++++++++++++++++++ 8 files changed, 565 insertions(+), 547 deletions(-) create mode 100644 src/backend/c/emit_c_control_flow.c create mode 100644 src/backend/spirv/emit_spv_control_flow.c diff --git a/src/backend/c/CMakeLists.txt b/src/backend/c/CMakeLists.txt index 6928a00f7..b44988143 100644 --- a/src/backend/c/CMakeLists.txt +++ b/src/backend/c/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(shady_c STATIC emit_c_value.c emit_c_type.c emit_c_builtin.c + emit_c_control_flow.c ) set_property(TARGET shady_c PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 138019065..424df54bb 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -20,8 +20,6 @@ #pragma GCC diagnostic error "-Wswitch" -static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator); - CValue to_cvalue(SHADY_UNUSED Emitter* e, CTerm term) { if (term.value) return term.value; @@ -220,253 +218,12 @@ void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const T print(block_printer, "\n%s%s;", prefix, decl); } -static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String given_name, Strings* given_names, Nodes types, bool mut, const Nodes* init_values) { - if (given_names) - assert(given_names->count == types.count); - if (init_values) - assert(init_values->count == types.count); - LARRAY(String, names, types.count); - for (size_t i = 0; i < types.count; i++) { - String name = given_names ? given_names->strings[i] : given_name; - assert(name); - names[i] = unique_name(emitter->arena, name); - if (init_values) { - CTerm initializer = emit_value(emitter, p, init_values->nodes[i]); - emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); - } else - emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); - } - return strings(emitter->arena, types.count, names); -} - -static void emit_if(Emitter* emitter, Printer* p, If if_) { - Emitter sub_emiter = *emitter; - Strings ephis = emit_variable_declarations(emitter, p, "if_phi", NULL, if_.yield_types, true, NULL); - sub_emiter.phis.selection = ephis; - - assert(get_abstraction_params(if_.if_true).count == 0); - String true_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_true), NULL); - CValue condition = to_cvalue(emitter, emit_value(emitter, p, if_.condition)); - print(p, "\nif (%s) { %s}", condition, true_body); - free_tmp_str(true_body); - if (if_.if_false) { - assert(get_abstraction_params(if_.if_false).count == 0); - String false_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_false), NULL); - print(p, " else {%s}", false_body); - free_tmp_str(false_body); - } - - Nodes results = get_abstraction_params(if_.tail); - for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); - } - - emit_terminator(emitter, p, get_abstraction_body(if_.tail)); -} - -static void emit_match(Emitter* emitter, Printer* p, Match match) { - Emitter sub_emiter = *emitter; - Strings ephis = emit_variable_declarations(emitter, p, "match_phi", NULL, match.yield_types, true, NULL); - sub_emiter.phis.selection = ephis; - - // Of course, the sensible thing to do here would be to emit a switch statement. - // ... - // Except that doesn't work, because C/GLSL have a baffling design wart: the `break` statement is overloaded, - // meaning that if you enter a switch statement, which should be orthogonal to loops, you can't actually break - // out of the outer loop anymore. Brilliant. So we do this terrible if-chain instead. - // - // We could do GOTO for C, but at the cost of arguably even more noise in the output, and two different codepaths. - // I don't think it's quite worth it, just like it's not worth doing some data-flow based solution either. - - CValue inspectee = to_cvalue(emitter, emit_value(emitter, p, match.inspect)); - bool first = true; - LARRAY(CValue, literals, match.cases.count); - for (size_t i = 0; i < match.cases.count; i++) { - literals[i] = to_cvalue(emitter, emit_value(emitter, p, match.literals.nodes[i])); - } - for (size_t i = 0; i < match.cases.count; i++) { - String case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match.cases.nodes[i]), NULL); - print(p, "\n"); - if (!first) - print(p, "else "); - print(p, "if (%s == %s) { %s}", inspectee, literals[i], case_body); - free_tmp_str(case_body); - first = false; - } - if (match.default_case) { - String default_case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match.default_case), NULL); - print(p, "\nelse { %s}", default_case_body); - free_tmp_str(default_case_body); - } - - Nodes results = get_abstraction_params(match.tail); - for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); - } - - emit_terminator(emitter, p, get_abstraction_body(match.tail)); -} - -static void emit_loop(Emitter* emitter, Printer* p, Loop loop) { - Emitter sub_emiter = *emitter; - Nodes params = get_abstraction_params(loop.body); - Nodes variables = params; - LARRAY(String, arr, variables.count); - for (size_t i = 0; i < variables.count; i++) { - arr[i] = get_value_name_unsafe(variables.nodes[i]); - if (!arr[i]) - arr[i] = unique_name(emitter->arena, "phi"); - } - Strings param_names = strings(emitter->arena, variables.count, arr); - Strings eparams = emit_variable_declarations(emitter, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop.initial_args); - for (size_t i = 0; i < params.count; i++) - register_emitted(&sub_emiter, params.nodes[i], term_from_cvalue(eparams.strings[i])); - - sub_emiter.phis.loop_continue = eparams; - Strings ephis = emit_variable_declarations(emitter, p, "loop_break_phi", NULL, loop.yield_types, true, NULL); - sub_emiter.phis.loop_break = ephis; - - String body = emit_lambda_body(&sub_emiter, get_abstraction_body(loop.body), NULL); - print(p, "\nwhile(true) { %s}", body); - free_tmp_str(body); - - Nodes results = get_abstraction_params(loop.tail); - for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); - } - - emit_terminator(emitter, p, get_abstraction_body(loop.tail)); -} - -static void emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { - switch (is_terminator(terminator)) { - case NotATerminator: assert(false); - case Join_TAG: error("this must be lowered away!"); - case Jump_TAG: - case Branch_TAG: - case Switch_TAG: - case TailCall_TAG: error("TODO"); - /*case Let_TAG: { - const Node* instruction = get_let_instruction(terminator); - - // we declare N local variables in order to store the result of the instruction - Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, instruction->type); - - LARRAY(CTerm, results, yield_types.count); - LARRAY(InstrResultBinding, bindings, yield_types.count); - InstructionOutputs ioutputs = { - .count = yield_types.count, - .results = results, - .binding = bindings, - }; - emit_instruction(emitter, block_printer, instruction, ioutputs); - - // Nodes vars = terminator->payload.let.variables; - // assert(vars.count == yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - bool has_result = results[i].value || results[i].var; - switch (bindings[i]) { - case NoBinding: { - assert(has_result && "unbound results can't be empty"); - register_emitted(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); - break; - } - case LetBinding: { - String variable_name = get_value_name_unsafe(extract_multiple_ret_types_helper(instruction, i)); - - if (!variable_name) - variable_name = ""; - - String bind_to = unique_name(emitter->arena, variable_name); - - const Type* t = yield_types.nodes[i]; - - if (has_result) - emit_variable_declaration(emitter, block_printer, t, bind_to, false, &results[i]); - else - emit_variable_declaration(emitter, block_printer, t, bind_to, false, NULL); - - register_emitted(emitter, extract_multiple_ret_types_helper(instruction, i), term_from_cvalue(bind_to)); - break; - } - default: assert(false); - } - } - emit_terminator(emitter, block_printer, terminator->payload.let.in); - - break; - }*/ - case If_TAG: return emit_if(emitter, block_printer, terminator->payload.if_instr); - case Match_TAG: return emit_match(emitter, block_printer, terminator->payload.match_instr); - case Loop_TAG: return emit_loop(emitter, block_printer, terminator->payload.loop_instr); - case Control_TAG: error("TODO") - case Terminator_Return_TAG: { - Nodes args = terminator->payload.fn_ret.args; - if (args.count == 0) { - print(block_printer, "\nreturn;"); - } else if (args.count == 1) { - print(block_printer, "\nreturn %s;", to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[0]))); - } else { - String packed = unique_name(emitter->arena, "pack_return"); - LARRAY(CValue, values, args.count); - for (size_t i = 0; i < args.count; i++) - values[i] = to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i])); - emit_pack_code(block_printer, strings(emitter->arena, args.count, values), packed); - print(block_printer, "\nreturn %s;", packed); - } - break; - } - case MergeSelection_TAG: { - Nodes args = terminator->payload.merge_selection.args; - Phis phis = emitter->phis.selection; - assert(phis.count == args.count); - for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); - - break; - } - case MergeContinue_TAG: { - Nodes args = terminator->payload.merge_continue.args; - Phis phis = emitter->phis.loop_continue; - assert(phis.count == args.count); - for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); - print(block_printer, "\ncontinue;"); - break; - } - case MergeBreak_TAG: { - Nodes args = terminator->payload.merge_break.args; - Phis phis = emitter->phis.loop_break; - assert(phis.count == args.count); - for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); - print(block_printer, "\nbreak;"); - break; - } - case Terminator_Unreachable_TAG: { - switch (emitter->config.dialect) { - case CDialect_CUDA: - case CDialect_C11: - print(block_printer, "\n__builtin_unreachable();"); - break; - case CDialect_ISPC: - print(block_printer, "\nassert(false);"); - break; - case CDialect_GLSL: - print(block_printer, "\n//unreachable"); - break; - } - break; - } - } -} - -void emit_lambda_body_at(Emitter* emitter, Printer* p, const Node* body, const Nodes* bbs) { +static void emit_lambda_body_at(Emitter* emitter, Printer* p, const Node* body, const Nodes* bbs) { assert(is_terminator(body)); //print(p, "{"); indent(p); - emit_terminator(emitter, p, body); + c_emit_terminator(emitter, p, body); if (bbs && bbs->count > 0) { assert(emitter->config.dialect != CDialect_GLSL); diff --git a/src/backend/c/emit_c.h b/src/backend/c/emit_c.h index 3ddcec071..8a2b23932 100644 --- a/src/backend/c/emit_c.h +++ b/src/backend/c/emit_c.h @@ -82,8 +82,8 @@ CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Ty CTerm bind_intermediary_result(Emitter*, Printer* p, const Type* t, CTerm term); CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction); +void c_emit_terminator(Emitter* emitter, Printer* p, const Node* terminator); String emit_lambda_body (Emitter*, const Node*, const Nodes* nested_basic_blocks); -void emit_lambda_body_at(Emitter*, Printer*, const Node*, const Nodes* nested_basic_blocks); void emit_pack_code(Printer*, Strings, String dst); void emit_unpack_code(Printer*, String src, Strings dst); diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c new file mode 100644 index 000000000..5503d8041 --- /dev/null +++ b/src/backend/c/emit_c_control_flow.c @@ -0,0 +1,249 @@ +#include "emit_c.h" + +#include "../shady/type.h" + +#include "log.h" +#include "portability.h" + +#include + +static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String given_name, Strings* given_names, Nodes types, bool mut, const Nodes* init_values) { + if (given_names) + assert(given_names->count == types.count); + if (init_values) + assert(init_values->count == types.count); + LARRAY(String, names, types.count); + for (size_t i = 0; i < types.count; i++) { + String name = given_names ? given_names->strings[i] : given_name; + assert(name); + names[i] = unique_name(emitter->arena, name); + if (init_values) { + CTerm initializer = emit_value(emitter, p, init_values->nodes[i]); + emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); + } else + emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); + } + return strings(emitter->arena, types.count, names); +} + +static void emit_if(Emitter* emitter, Printer* p, If if_) { + Emitter sub_emiter = *emitter; + Strings ephis = emit_variable_declarations(emitter, p, "if_phi", NULL, if_.yield_types, true, NULL); + sub_emiter.phis.selection = ephis; + + assert(get_abstraction_params(if_.if_true).count == 0); + String true_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_true), NULL); + CValue condition = to_cvalue(emitter, emit_value(emitter, p, if_.condition)); + print(p, "\nif (%s) { %s}", condition, true_body); + free_tmp_str(true_body); + if (if_.if_false) { + assert(get_abstraction_params(if_.if_false).count == 0); + String false_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_false), NULL); + print(p, " else {%s}", false_body); + free_tmp_str(false_body); + } + + Nodes results = get_abstraction_params(if_.tail); + for (size_t i = 0; i < ephis.count; i++) { + register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + } + + c_emit_terminator(emitter, p, get_abstraction_body(if_.tail)); +} + +static void emit_match(Emitter* emitter, Printer* p, Match match) { + Emitter sub_emiter = *emitter; + Strings ephis = emit_variable_declarations(emitter, p, "match_phi", NULL, match.yield_types, true, NULL); + sub_emiter.phis.selection = ephis; + + // Of course, the sensible thing to do here would be to emit a switch statement. + // ... + // Except that doesn't work, because C/GLSL have a baffling design wart: the `break` statement is overloaded, + // meaning that if you enter a switch statement, which should be orthogonal to loops, you can't actually break + // out of the outer loop anymore. Brilliant. So we do this terrible if-chain instead. + // + // We could do GOTO for C, but at the cost of arguably even more noise in the output, and two different codepaths. + // I don't think it's quite worth it, just like it's not worth doing some data-flow based solution either. + + CValue inspectee = to_cvalue(emitter, emit_value(emitter, p, match.inspect)); + bool first = true; + LARRAY(CValue, literals, match.cases.count); + for (size_t i = 0; i < match.cases.count; i++) { + literals[i] = to_cvalue(emitter, emit_value(emitter, p, match.literals.nodes[i])); + } + for (size_t i = 0; i < match.cases.count; i++) { + String case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match.cases.nodes[i]), NULL); + print(p, "\n"); + if (!first) + print(p, "else "); + print(p, "if (%s == %s) { %s}", inspectee, literals[i], case_body); + free_tmp_str(case_body); + first = false; + } + if (match.default_case) { + String default_case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match.default_case), NULL); + print(p, "\nelse { %s}", default_case_body); + free_tmp_str(default_case_body); + } + + Nodes results = get_abstraction_params(match.tail); + for (size_t i = 0; i < ephis.count; i++) { + register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + } + + c_emit_terminator(emitter, p, get_abstraction_body(match.tail)); +} + +static void emit_loop(Emitter* emitter, Printer* p, Loop loop) { + Emitter sub_emiter = *emitter; + Nodes params = get_abstraction_params(loop.body); + Nodes variables = params; + LARRAY(String, arr, variables.count); + for (size_t i = 0; i < variables.count; i++) { + arr[i] = get_value_name_unsafe(variables.nodes[i]); + if (!arr[i]) + arr[i] = unique_name(emitter->arena, "phi"); + } + Strings param_names = strings(emitter->arena, variables.count, arr); + Strings eparams = emit_variable_declarations(emitter, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop.initial_args); + for (size_t i = 0; i < params.count; i++) + register_emitted(&sub_emiter, params.nodes[i], term_from_cvalue(eparams.strings[i])); + + sub_emiter.phis.loop_continue = eparams; + Strings ephis = emit_variable_declarations(emitter, p, "loop_break_phi", NULL, loop.yield_types, true, NULL); + sub_emiter.phis.loop_break = ephis; + + String body = emit_lambda_body(&sub_emiter, get_abstraction_body(loop.body), NULL); + print(p, "\nwhile(true) { %s}", body); + free_tmp_str(body); + + Nodes results = get_abstraction_params(loop.tail); + for (size_t i = 0; i < ephis.count; i++) { + register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + } + + c_emit_terminator(emitter, p, get_abstraction_body(loop.tail)); +} + +void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { + switch (is_terminator(terminator)) { + case NotATerminator: assert(false); + case Join_TAG: error("this must be lowered away!"); + case Jump_TAG: + case Branch_TAG: + case Switch_TAG: + case TailCall_TAG: error("TODO"); + /*case Let_TAG: { + const Node* instruction = get_let_instruction(terminator); + + // we declare N local variables in order to store the result of the instruction + Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, instruction->type); + + LARRAY(CTerm, results, yield_types.count); + LARRAY(InstrResultBinding, bindings, yield_types.count); + InstructionOutputs ioutputs = { + .count = yield_types.count, + .results = results, + .binding = bindings, + }; + emit_instruction(emitter, block_printer, instruction, ioutputs); + + // Nodes vars = terminator->payload.let.variables; + // assert(vars.count == yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) { + bool has_result = results[i].value || results[i].var; + switch (bindings[i]) { + case NoBinding: { + assert(has_result && "unbound results can't be empty"); + register_emitted(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); + break; + } + case LetBinding: { + String variable_name = get_value_name_unsafe(extract_multiple_ret_types_helper(instruction, i)); + + if (!variable_name) + variable_name = ""; + + String bind_to = unique_name(emitter->arena, variable_name); + + const Type* t = yield_types.nodes[i]; + + if (has_result) + emit_variable_declaration(emitter, block_printer, t, bind_to, false, &results[i]); + else + emit_variable_declaration(emitter, block_printer, t, bind_to, false, NULL); + + register_emitted(emitter, extract_multiple_ret_types_helper(instruction, i), term_from_cvalue(bind_to)); + break; + } + default: assert(false); + } + } + emit_terminator(emitter, block_printer, terminator->payload.let.in); + + break; + }*/ + case If_TAG: return emit_if(emitter, block_printer, terminator->payload.if_instr); + case Match_TAG: return emit_match(emitter, block_printer, terminator->payload.match_instr); + case Loop_TAG: return emit_loop(emitter, block_printer, terminator->payload.loop_instr); + case Control_TAG: error("TODO") + case Terminator_Return_TAG: { + Nodes args = terminator->payload.fn_ret.args; + if (args.count == 0) { + print(block_printer, "\nreturn;"); + } else if (args.count == 1) { + print(block_printer, "\nreturn %s;", to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[0]))); + } else { + String packed = unique_name(emitter->arena, "pack_return"); + LARRAY(CValue, values, args.count); + for (size_t i = 0; i < args.count; i++) + values[i] = to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i])); + emit_pack_code(block_printer, strings(emitter->arena, args.count, values), packed); + print(block_printer, "\nreturn %s;", packed); + } + break; + } + case MergeSelection_TAG: { + Nodes args = terminator->payload.merge_selection.args; + Phis phis = emitter->phis.selection; + assert(phis.count == args.count); + for (size_t i = 0; i < phis.count; i++) + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); + + break; + } + case MergeContinue_TAG: { + Nodes args = terminator->payload.merge_continue.args; + Phis phis = emitter->phis.loop_continue; + assert(phis.count == args.count); + for (size_t i = 0; i < phis.count; i++) + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); + print(block_printer, "\ncontinue;"); + break; + } + case MergeBreak_TAG: { + Nodes args = terminator->payload.merge_break.args; + Phis phis = emitter->phis.loop_break; + assert(phis.count == args.count); + for (size_t i = 0; i < phis.count; i++) + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); + print(block_printer, "\nbreak;"); + break; + } + case Terminator_Unreachable_TAG: { + switch (emitter->config.dialect) { + case CDialect_CUDA: + case CDialect_C11: + print(block_printer, "\n__builtin_unreachable();"); + break; + case CDialect_ISPC: + print(block_printer, "\nassert(false);"); + break; + case CDialect_GLSL: + print(block_printer, "\n//unreachable"); + break; + } + break; + } + } +} diff --git a/src/backend/spirv/CMakeLists.txt b/src/backend/spirv/CMakeLists.txt index 89896ac1e..2cbe5f975 100644 --- a/src/backend/spirv/CMakeLists.txt +++ b/src/backend/spirv/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(shady_spirv STATIC emit_spv.c emit_spv_type.c emit_spv_value.c + emit_spv_control_flow.c spirv_builder.c ) set_property(TARGET shady_spirv PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index f60c102d1..1f8342fe5 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -37,305 +37,6 @@ SpvId spv_find_reserved_id(Emitter* emitter, const Node* node) { return *found; } -static BBBuilder find_basic_block_builder(Emitter* emitter, SHADY_UNUSED FnBuilder fn_builder, const Node* bb) { - // assert(is_basic_block(bb)); - BBBuilder* found = find_value_dict(const Node*, BBBuilder, emitter->bb_builders, bb); - assert(found); - return *found; -} - -static void add_branch_phis(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, const Node* jump) { - assert(jump->tag == Jump_TAG); - const Node* dst = jump->payload.jump.target; - Nodes args = jump->payload.jump.args; - // because it's forbidden to jump back into the entry block of a function - // (which is actually a Function in this IR, not a BasicBlock) - // we assert that the destination must be an actual BasicBlock - assert(is_basic_block(dst)); - BBBuilder dst_builder = find_basic_block_builder(emitter, fn_builder, dst); - struct List* phis = spbv_get_phis(dst_builder); - assert(entries_count_list(phis) == args.count); - for (size_t i = 0; i < args.count; i++) { - SpvbPhi* phi = read_list(SpvbPhi*, phis)[i]; - spvb_add_phi_source(phi, get_block_builder_id(bb_builder), emit_value(emitter, bb_builder, args.nodes[i])); - } -} - -static void emit_if(Emitter* emitter, FnBuilder fn_builder, BBBuilder* pbb_builder, MergeTargets* merge_targets, If if_instr) { - Nodes yield_types = if_instr.yield_types; - Nodes results = get_abstraction_params(if_instr.tail); - SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); - - SpvId true_id = spvb_fresh_id(emitter->file_builder); - SpvId false_id = if_instr.if_false ? spvb_fresh_id(emitter->file_builder) : join_bb_id; - - spvb_selection_merge(*pbb_builder, join_bb_id, 0); - SpvId condition = emit_value(emitter, *pbb_builder, if_instr.condition); - spvb_branch_conditional(*pbb_builder, condition, true_id, false_id); - - // When 'join' is codegen'd, these will be filled with the values given to it - BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); - LARRAY(SpvbPhi*, join_phis, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - assert(if_instr.if_false && "Ifs with yield types need false branches !"); - SpvId phi_id = spvb_fresh_id(emitter->file_builder); - SpvId type = emit_type(emitter, yield_types.nodes[i]); - SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); - join_phis[i] = phi; - register_result(emitter, results.nodes[i], phi_id); - } - - MergeTargets merge_targets_branches = *merge_targets; - merge_targets_branches.join_target = join_bb_id; - merge_targets_branches.join_phis = join_phis; - - BBBuilder true_bb = spvb_begin_bb(fn_builder, true_id); - spvb_add_bb(fn_builder, true_bb); - emit_terminator(emitter, fn_builder, true_bb, merge_targets_branches, get_abstraction_body(if_instr.if_true)); - if (if_instr.if_false) { - BBBuilder false_bb = spvb_begin_bb(fn_builder, false_id); - spvb_add_bb(fn_builder, false_bb); - emit_terminator(emitter, fn_builder, false_bb, merge_targets_branches, get_abstraction_body(if_instr.if_false)); - } - - spvb_add_bb(fn_builder, join_bb); - *pbb_builder = join_bb; - - emit_terminator(emitter, fn_builder, *pbb_builder, *merge_targets, get_abstraction_body(if_instr.tail)); -} - -static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Match match) { - Nodes yield_types = match.yield_types; - SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); - - assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); - SpvId inspectee = emit_value(emitter, *bb_builder, match.inspect); - - SpvId default_id = spvb_fresh_id(emitter->file_builder); - - const Type* inspectee_t = match.inspect->type; - deconstruct_qualified_type(&inspectee_t); - assert(inspectee_t->tag == Int_TAG); - size_t literal_width = inspectee_t->payload.int_type.width == IntTy64 ? 2 : 1; - size_t literal_case_entry_size = literal_width + 1; - LARRAY(uint32_t, literals_and_cases, match.cases.count * literal_case_entry_size); - for (size_t i = 0; i < match.cases.count; i++) { - uint64_t value = (uint64_t) get_int_literal_value(*resolve_to_int_literal(match.literals.nodes[i]), false); - if (inspectee_t->payload.int_type.width == IntTy64) { - literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) (value & 0xFFFFFFFF); - literals_and_cases[i * literal_case_entry_size + 1] = (SpvId) (uint32_t) (value >> 32); - } else { - literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) value; - } - literals_and_cases[i * literal_case_entry_size + literal_width] = spvb_fresh_id(emitter->file_builder); - } - - spvb_selection_merge(*bb_builder, join_bb_id, 0); - spvb_switch(*bb_builder, inspectee, default_id, match.cases.count * literal_case_entry_size, literals_and_cases); - - // When 'join' is codegen'd, these will be filled with the values given to it - BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); - LARRAY(SpvbPhi*, join_phis, yield_types.count); - Nodes results = get_abstraction_params(match.tail); - for (size_t i = 0; i < yield_types.count; i++) { - SpvId phi_id = spvb_fresh_id(emitter->file_builder); - SpvId type = emit_type(emitter, yield_types.nodes[i]); - SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); - join_phis[i] = phi; - register_result(emitter, results.nodes[i], phi_id); - } - - MergeTargets merge_targets_branches = *merge_targets; - merge_targets_branches.join_target = join_bb_id; - merge_targets_branches.join_phis = join_phis; - - for (size_t i = 0; i < match.cases.count; i++) { - BBBuilder case_bb = spvb_begin_bb(fn_builder, literals_and_cases[i * literal_case_entry_size + literal_width]); - const Node* case_ = match.cases.nodes[i]; - spvb_add_bb(fn_builder, case_bb); - emit_terminator(emitter, fn_builder, case_bb, merge_targets_branches, get_abstraction_body(case_)); - } - BBBuilder default_bb = spvb_begin_bb(fn_builder, default_id); - spvb_add_bb(fn_builder, default_bb); - emit_terminator(emitter, fn_builder, default_bb, merge_targets_branches, get_abstraction_body(match.default_case)); - - spvb_add_bb(fn_builder, join_bb); - *bb_builder = join_bb; - - emit_terminator(emitter, fn_builder, *bb_builder, *merge_targets, get_abstraction_body(match.tail)); -} - -static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder* bb_builder, MergeTargets* merge_targets, Loop loop_instr) { - Nodes yield_types = loop_instr.yield_types; - - const Node* loop_inside = loop_instr.body; - Nodes loop_params = get_abstraction_params(loop_inside); - - // First we create all the basic blocks we'll need - SpvId header_id = spvb_fresh_id(emitter->file_builder); - BBBuilder header_builder = spvb_begin_bb(fn_builder, header_id); - spvb_name(emitter->file_builder, header_id, "loop_header"); - - SpvId body_id = spvb_fresh_id(emitter->file_builder); - BBBuilder body_builder = spvb_begin_bb(fn_builder, body_id); - spvb_name(emitter->file_builder, body_id, "loop_body"); - - SpvId continue_id = spvb_fresh_id(emitter->file_builder); - BBBuilder continue_builder = spvb_begin_bb(fn_builder, continue_id); - spvb_name(emitter->file_builder, continue_id, "loop_continue"); - - SpvId next_id = spvb_fresh_id(emitter->file_builder); - BBBuilder next = spvb_begin_bb(fn_builder, next_id); - spvb_name(emitter->file_builder, next_id, "loop_next"); - - // Wire up the phi nodes for loop exit - LARRAY(SpvbPhi*, loop_break_phis, yield_types.count); - Nodes results = get_abstraction_params(loop_instr.tail); - for (size_t i = 0; i < yield_types.count; i++) { - SpvId yielded_type = emit_type(emitter, get_unqualified_type(yield_types.nodes[i])); - - SpvId break_phi_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* phi = spvb_add_phi(next, yielded_type, break_phi_id); - loop_break_phis[i] = phi; - register_result(emitter, results.nodes[i], break_phi_id); - } - - // Wire up the phi nodes for the loop contents - LARRAY(SpvbPhi*, loop_continue_phis, loop_params.count); - for (size_t i = 0; i < loop_params.count; i++) { - SpvId loop_param_type = emit_type(emitter, get_unqualified_type(loop_params.nodes[i]->type)); - - SpvId continue_phi_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* continue_phi = spvb_add_phi(continue_builder, loop_param_type, continue_phi_id); - loop_continue_phis[i] = continue_phi; - - // To get the actual loop parameter, we make a second phi for the nodes that go into the header - // We already know the two edges into the header so we immediately add the Phi sources for it. - SpvId loop_param_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* loop_param_phi = spvb_add_phi(header_builder, loop_param_type, loop_param_id); - SpvId param_initial_value = emit_value(emitter, *bb_builder, loop_instr.initial_args.nodes[i]); - spvb_add_phi_source(loop_param_phi, get_block_builder_id(*bb_builder), param_initial_value); - spvb_add_phi_source(loop_param_phi, get_block_builder_id(continue_builder), continue_phi_id); - register_result(emitter, loop_params.nodes[i], loop_param_id); - } - - // The current block goes to the header (it can't be the header itself !) - spvb_branch(*bb_builder, header_id); - spvb_add_bb(fn_builder, header_builder); - - // the header block receives the loop merge annotation - spvb_loop_merge(header_builder, next_id, continue_id, 0, 0, NULL); - spvb_branch(header_builder, body_id); - spvb_add_bb(fn_builder, body_builder); - - // Emission of the body requires extra info for the break/continue merge terminators - MergeTargets merge_targets_branches = *merge_targets; - merge_targets_branches.continue_target = continue_id; - merge_targets_branches.continue_phis = loop_continue_phis; - merge_targets_branches.break_target = next_id; - merge_targets_branches.break_phis = loop_break_phis; - emit_terminator(emitter, fn_builder, body_builder, merge_targets_branches, get_abstraction_body(loop_inside)); - - // the continue block just jumps back into the header - spvb_branch(continue_builder, header_id); - spvb_add_bb(fn_builder, continue_builder); - - // We start the next block - spvb_add_bb(fn_builder, next); - *bb_builder = next; - - emit_terminator(emitter, fn_builder, *bb_builder, *merge_targets, get_abstraction_body(loop_instr.tail)); -} - -void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_block_builder, MergeTargets merge_targets, const Node* terminator) { - switch (is_terminator(terminator)) { - case Return_TAG: { - const Nodes* ret_values = &terminator->payload.fn_ret.args; - switch (ret_values->count) { - case 0: spvb_return_void(basic_block_builder); return; - case 1: spvb_return_value(basic_block_builder, emit_value(emitter, basic_block_builder, ret_values->nodes[0])); return; - default: { - LARRAY(SpvId, arr, ret_values->count); - for (size_t i = 0; i < ret_values->count; i++) - arr[i] = emit_value(emitter, basic_block_builder, ret_values->nodes[i]); - SpvId return_that = spvb_composite(basic_block_builder, fn_ret_type_id(fn_builder), ret_values->count, arr); - spvb_return_value(basic_block_builder, return_that); - return; - } - } - } - /*case Let_TAG: { - const Node* instruction = terminator->payload.let.instruction; - Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction->type); - LARRAY(SpvId, results, types.count); - emit_instruction(emitter, fn_builder, basic_block_builder, instruction, types.count, results); - - for (size_t i = 0; i < types.count; i++) - register_result(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); - emit_terminator(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.let.in); - return; - }*/ - case Jump_TAG: { - add_branch_phis(emitter, fn_builder, basic_block_builder, terminator); - spvb_branch(basic_block_builder, find_reserved_id(emitter, terminator->payload.jump.target)); - return; - } - case Branch_TAG: { - SpvId condition = emit_value(emitter, basic_block_builder, terminator->payload.branch.condition); - add_branch_phis(emitter, fn_builder, basic_block_builder, terminator->payload.branch.true_jump); - add_branch_phis(emitter, fn_builder, basic_block_builder, terminator->payload.branch.false_jump); - spvb_branch_conditional(basic_block_builder, condition, find_reserved_id(emitter, terminator->payload.branch.true_jump->payload.jump.target), find_reserved_id(emitter, terminator->payload.branch.false_jump->payload.jump.target)); - return; - } - case If_TAG: return emit_if(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.if_instr); - case Match_TAG: return emit_match(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.match_instr); - case Loop_TAG: return emit_loop(emitter, fn_builder, &basic_block_builder, &merge_targets, terminator->payload.loop_instr); - case Switch_TAG: { - SpvId inspectee = emit_value(emitter, basic_block_builder, terminator->payload.br_switch.switch_value); - LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); - for (size_t i = 0; i < terminator->payload.br_switch.case_jumps.count; i++) { - add_branch_phis(emitter, fn_builder, basic_block_builder, terminator->payload.br_switch.case_jumps.nodes[i]); - error("TODO finish") - } - add_branch_phis(emitter, fn_builder, basic_block_builder, terminator->payload.br_switch.default_jump); - SpvId default_tgt = find_reserved_id(emitter, terminator->payload.br_switch.default_jump->payload.jump.target); - - spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); - return; - } - case Terminator_Control_TAG: - case TailCall_TAG: - case Join_TAG: error("Lower me"); - case MergeSelection_TAG: { - Nodes args = terminator->payload.merge_selection.args; - for (size_t i = 0; i < args.count; i++) - spvb_add_phi_source(merge_targets.join_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); - spvb_branch(basic_block_builder, merge_targets.join_target); - return; - } - case MergeContinue_TAG: { - Nodes args = terminator->payload.merge_continue.args; - for (size_t i = 0; i < args.count; i++) - spvb_add_phi_source(merge_targets.continue_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); - spvb_branch(basic_block_builder, merge_targets.continue_target); - return; - } - case MergeBreak_TAG: { - Nodes args = terminator->payload.merge_break.args; - for (size_t i = 0; i < args.count; i++) - spvb_add_phi_source(merge_targets.break_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); - spvb_branch(basic_block_builder, merge_targets.break_target); - return; - } - case Unreachable_TAG: { - spvb_unreachable(basic_block_builder); - return; - } - case NotATerminator: error("TODO: emit terminator %s", node_tags[terminator->tag]); - } - SHADY_UNREACHABLE; -} - static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const CFG* cfg, const CFNode* cf_node) { const Node* bb_node = cf_node->node; assert(is_basic_block(bb_node) || cf_node == cfg->entry); @@ -343,7 +44,7 @@ static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const CFG* const Node* body = get_abstraction_body(bb_node); // Find the preassigned ID to this - BBBuilder bb_builder = find_basic_block_builder(emitter, fn_builder, bb_node); + BBBuilder bb_builder = spv_find_basic_block_builder(emitter, bb_node); SpvId bb_id = get_block_builder_id(bb_builder); spvb_add_bb(fn_builder, bb_builder); @@ -404,7 +105,6 @@ static void emit_function(Emitter* emitter, const Node* node) { } } // emit the blocks using the dominator tree - //emit_basic_block(emitter, fn_builder, &cfg, cfg.entry); for (size_t i = 0; i < cfg->size; i++) { CFNode* cfnode = cfg->rpo[i]; if (i == 0) diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index 62b7b592a..bae62fe41 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -46,6 +46,7 @@ void emit_terminator(Emitter*, FnBuilder, BBBuilder, MergeTargets, const Node* t SpvId find_reserved_id(Emitter* emitter, const Node* node); void register_result(Emitter*, const Node*, SpvId id); +BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb); SpvId get_extended_instruction_set(Emitter*, const char*); diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c new file mode 100644 index 000000000..dbbaa0630 --- /dev/null +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -0,0 +1,309 @@ +#include "emit_spv.h" + +#include "../shady/type.h" + +#include "list.h" +#include "dict.h" +#include "log.h" +#include "portability.h" + +#include + +BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb) { + // assert(is_basic_block(bb)); + BBBuilder* found = find_value_dict(const Node*, BBBuilder, emitter->bb_builders, bb); + assert(found); + return *found; +} + +static void add_branch_phis(Emitter* emitter, BBBuilder bb_builder, const Node* jump) { + assert(jump->tag == Jump_TAG); + const Node* dst = jump->payload.jump.target; + Nodes args = jump->payload.jump.args; + // because it's forbidden to jump back into the entry block of a function + // (which is actually a Function in this IR, not a BasicBlock) + // we assert that the destination must be an actual BasicBlock + assert(is_basic_block(dst)); + BBBuilder dst_builder = spv_find_basic_block_builder(emitter, dst); + struct List* phis = spbv_get_phis(dst_builder); + assert(entries_count_list(phis) == args.count); + for (size_t i = 0; i < args.count; i++) { + SpvbPhi* phi = read_list(SpvbPhi*, phis)[i]; + spvb_add_phi_source(phi, get_block_builder_id(bb_builder), emit_value(emitter, bb_builder, args.nodes[i])); + } +} + +static void emit_if(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, MergeTargets merge_targets, If if_instr) { + Nodes yield_types = if_instr.yield_types; + Nodes results = get_abstraction_params(if_instr.tail); + SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); + + SpvId true_id = spvb_fresh_id(emitter->file_builder); + SpvId false_id = if_instr.if_false ? spvb_fresh_id(emitter->file_builder) : join_bb_id; + + spvb_selection_merge(bb_builder, join_bb_id, 0); + SpvId condition = emit_value(emitter, bb_builder, if_instr.condition); + spvb_branch_conditional(bb_builder, condition, true_id, false_id); + + // When 'join' is codegen'd, these will be filled with the values given to it + BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); + LARRAY(SpvbPhi*, join_phis, yield_types.count); + for (size_t i = 0; i < yield_types.count; i++) { + assert(if_instr.if_false && "Ifs with yield types need false branches !"); + SpvId phi_id = spvb_fresh_id(emitter->file_builder); + SpvId type = emit_type(emitter, yield_types.nodes[i]); + SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); + join_phis[i] = phi; + register_result(emitter, results.nodes[i], phi_id); + } + + MergeTargets merge_targets_branches = merge_targets; + merge_targets_branches.join_target = join_bb_id; + merge_targets_branches.join_phis = join_phis; + + BBBuilder true_bb = spvb_begin_bb(fn_builder, true_id); + spvb_add_bb(fn_builder, true_bb); + emit_terminator(emitter, fn_builder, true_bb, merge_targets_branches, get_abstraction_body(if_instr.if_true)); + if (if_instr.if_false) { + BBBuilder false_bb = spvb_begin_bb(fn_builder, false_id); + spvb_add_bb(fn_builder, false_bb); + emit_terminator(emitter, fn_builder, false_bb, merge_targets_branches, get_abstraction_body(if_instr.if_false)); + } + + spvb_add_bb(fn_builder, join_bb); + bb_builder = join_bb; + + emit_terminator(emitter, fn_builder, bb_builder, merge_targets, get_abstraction_body(if_instr.tail)); +} + +static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, MergeTargets merge_targets, Match match) { + Nodes yield_types = match.yield_types; + SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); + + assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); + SpvId inspectee = emit_value(emitter, bb_builder, match.inspect); + + SpvId default_id = spvb_fresh_id(emitter->file_builder); + + const Type* inspectee_t = match.inspect->type; + deconstruct_qualified_type(&inspectee_t); + assert(inspectee_t->tag == Int_TAG); + size_t literal_width = inspectee_t->payload.int_type.width == IntTy64 ? 2 : 1; + size_t literal_case_entry_size = literal_width + 1; + LARRAY(uint32_t, literals_and_cases, match.cases.count * literal_case_entry_size); + for (size_t i = 0; i < match.cases.count; i++) { + uint64_t value = (uint64_t) get_int_literal_value(*resolve_to_int_literal(match.literals.nodes[i]), false); + if (inspectee_t->payload.int_type.width == IntTy64) { + literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) (value & 0xFFFFFFFF); + literals_and_cases[i * literal_case_entry_size + 1] = (SpvId) (uint32_t) (value >> 32); + } else { + literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) value; + } + literals_and_cases[i * literal_case_entry_size + literal_width] = spvb_fresh_id(emitter->file_builder); + } + + spvb_selection_merge(bb_builder, join_bb_id, 0); + spvb_switch(bb_builder, inspectee, default_id, match.cases.count * literal_case_entry_size, literals_and_cases); + + // When 'join' is codegen'd, these will be filled with the values given to it + BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); + LARRAY(SpvbPhi*, join_phis, yield_types.count); + Nodes results = get_abstraction_params(match.tail); + for (size_t i = 0; i < yield_types.count; i++) { + SpvId phi_id = spvb_fresh_id(emitter->file_builder); + SpvId type = emit_type(emitter, yield_types.nodes[i]); + SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); + join_phis[i] = phi; + register_result(emitter, results.nodes[i], phi_id); + } + + MergeTargets merge_targets_branches = merge_targets; + merge_targets_branches.join_target = join_bb_id; + merge_targets_branches.join_phis = join_phis; + + for (size_t i = 0; i < match.cases.count; i++) { + BBBuilder case_bb = spvb_begin_bb(fn_builder, literals_and_cases[i * literal_case_entry_size + literal_width]); + const Node* case_ = match.cases.nodes[i]; + spvb_add_bb(fn_builder, case_bb); + emit_terminator(emitter, fn_builder, case_bb, merge_targets_branches, get_abstraction_body(case_)); + } + BBBuilder default_bb = spvb_begin_bb(fn_builder, default_id); + spvb_add_bb(fn_builder, default_bb); + emit_terminator(emitter, fn_builder, default_bb, merge_targets_branches, get_abstraction_body(match.default_case)); + + spvb_add_bb(fn_builder, join_bb); + bb_builder = join_bb; + + emit_terminator(emitter, fn_builder, bb_builder, merge_targets, get_abstraction_body(match.tail)); +} + +static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, MergeTargets merge_targets, Loop loop_instr) { + Nodes yield_types = loop_instr.yield_types; + + const Node* loop_inside = loop_instr.body; + Nodes loop_params = get_abstraction_params(loop_inside); + + // First we create all the basic blocks we'll need + SpvId header_id = spvb_fresh_id(emitter->file_builder); + BBBuilder header_builder = spvb_begin_bb(fn_builder, header_id); + spvb_name(emitter->file_builder, header_id, "loop_header"); + + SpvId body_id = spvb_fresh_id(emitter->file_builder); + BBBuilder body_builder = spvb_begin_bb(fn_builder, body_id); + spvb_name(emitter->file_builder, body_id, "loop_body"); + + SpvId continue_id = spvb_fresh_id(emitter->file_builder); + BBBuilder continue_builder = spvb_begin_bb(fn_builder, continue_id); + spvb_name(emitter->file_builder, continue_id, "loop_continue"); + + SpvId next_id = spvb_fresh_id(emitter->file_builder); + BBBuilder next = spvb_begin_bb(fn_builder, next_id); + spvb_name(emitter->file_builder, next_id, "loop_next"); + + // Wire up the phi nodes for loop exit + LARRAY(SpvbPhi*, loop_break_phis, yield_types.count); + Nodes results = get_abstraction_params(loop_instr.tail); + for (size_t i = 0; i < yield_types.count; i++) { + SpvId yielded_type = emit_type(emitter, get_unqualified_type(yield_types.nodes[i])); + + SpvId break_phi_id = spvb_fresh_id(emitter->file_builder); + SpvbPhi* phi = spvb_add_phi(next, yielded_type, break_phi_id); + loop_break_phis[i] = phi; + register_result(emitter, results.nodes[i], break_phi_id); + } + + // Wire up the phi nodes for the loop contents + LARRAY(SpvbPhi*, loop_continue_phis, loop_params.count); + for (size_t i = 0; i < loop_params.count; i++) { + SpvId loop_param_type = emit_type(emitter, get_unqualified_type(loop_params.nodes[i]->type)); + + SpvId continue_phi_id = spvb_fresh_id(emitter->file_builder); + SpvbPhi* continue_phi = spvb_add_phi(continue_builder, loop_param_type, continue_phi_id); + loop_continue_phis[i] = continue_phi; + + // To get the actual loop parameter, we make a second phi for the nodes that go into the header + // We already know the two edges into the header so we immediately add the Phi sources for it. + SpvId loop_param_id = spvb_fresh_id(emitter->file_builder); + SpvbPhi* loop_param_phi = spvb_add_phi(header_builder, loop_param_type, loop_param_id); + SpvId param_initial_value = emit_value(emitter, bb_builder, loop_instr.initial_args.nodes[i]); + spvb_add_phi_source(loop_param_phi, get_block_builder_id(bb_builder), param_initial_value); + spvb_add_phi_source(loop_param_phi, get_block_builder_id(continue_builder), continue_phi_id); + register_result(emitter, loop_params.nodes[i], loop_param_id); + } + + // The current block goes to the header (it can't be the header itself !) + spvb_branch(bb_builder, header_id); + spvb_add_bb(fn_builder, header_builder); + + // the header block receives the loop merge annotation + spvb_loop_merge(header_builder, next_id, continue_id, 0, 0, NULL); + spvb_branch(header_builder, body_id); + spvb_add_bb(fn_builder, body_builder); + + // Emission of the body requires extra info for the break/continue merge terminators + MergeTargets merge_targets_branches = merge_targets; + merge_targets_branches.continue_target = continue_id; + merge_targets_branches.continue_phis = loop_continue_phis; + merge_targets_branches.break_target = next_id; + merge_targets_branches.break_phis = loop_break_phis; + emit_terminator(emitter, fn_builder, body_builder, merge_targets_branches, get_abstraction_body(loop_inside)); + + // the continue block just jumps back into the header + spvb_branch(continue_builder, header_id); + spvb_add_bb(fn_builder, continue_builder); + + // We start the next block + spvb_add_bb(fn_builder, next); + bb_builder = next; + + emit_terminator(emitter, fn_builder, bb_builder, merge_targets, get_abstraction_body(loop_instr.tail)); +} + +void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_block_builder, MergeTargets merge_targets, const Node* terminator) { + switch (is_terminator(terminator)) { + case Return_TAG: { + const Nodes* ret_values = &terminator->payload.fn_ret.args; + switch (ret_values->count) { + case 0: spvb_return_void(basic_block_builder); return; + case 1: spvb_return_value(basic_block_builder, emit_value(emitter, basic_block_builder, ret_values->nodes[0])); return; + default: { + LARRAY(SpvId, arr, ret_values->count); + for (size_t i = 0; i < ret_values->count; i++) + arr[i] = emit_value(emitter, basic_block_builder, ret_values->nodes[i]); + SpvId return_that = spvb_composite(basic_block_builder, fn_ret_type_id(fn_builder), ret_values->count, arr); + spvb_return_value(basic_block_builder, return_that); + return; + } + } + } + /*case Let_TAG: { + const Node* instruction = terminator->payload.let.instruction; + Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction->type); + LARRAY(SpvId, results, types.count); + emit_instruction(emitter, fn_builder, basic_block_builder, instruction, types.count, results); + + for (size_t i = 0; i < types.count; i++) + register_result(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); + emit_terminator(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.let.in); + return; + }*/ + case Unreachable_TAG: { + spvb_unreachable(basic_block_builder); + return; + } + case Jump_TAG: { + add_branch_phis(emitter, basic_block_builder, terminator); + spvb_branch(basic_block_builder, find_reserved_id(emitter, terminator->payload.jump.target)); + return; + } + case Branch_TAG: { + SpvId condition = emit_value(emitter, basic_block_builder, terminator->payload.branch.condition); + add_branch_phis(emitter, basic_block_builder, terminator->payload.branch.true_jump); + add_branch_phis(emitter, basic_block_builder, terminator->payload.branch.false_jump); + spvb_branch_conditional(basic_block_builder, condition, find_reserved_id(emitter, terminator->payload.branch.true_jump->payload.jump.target), find_reserved_id(emitter, terminator->payload.branch.false_jump->payload.jump.target)); + return; + } + case Switch_TAG: { + SpvId inspectee = emit_value(emitter, basic_block_builder, terminator->payload.br_switch.switch_value); + LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); + for (size_t i = 0; i < terminator->payload.br_switch.case_jumps.count; i++) { + add_branch_phis(emitter, basic_block_builder, terminator->payload.br_switch.case_jumps.nodes[i]); + error("TODO finish") + } + add_branch_phis(emitter, basic_block_builder, terminator->payload.br_switch.default_jump); + SpvId default_tgt = find_reserved_id(emitter, terminator->payload.br_switch.default_jump->payload.jump.target); + + spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); + return; + } + case If_TAG: return emit_if(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.if_instr); + case Match_TAG: return emit_match(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.match_instr); + case Loop_TAG: return emit_loop(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.loop_instr); + case MergeSelection_TAG: { + Nodes args = terminator->payload.merge_selection.args; + for (size_t i = 0; i < args.count; i++) + spvb_add_phi_source(merge_targets.join_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); + spvb_branch(basic_block_builder, merge_targets.join_target); + return; + } + case MergeContinue_TAG: { + Nodes args = terminator->payload.merge_continue.args; + for (size_t i = 0; i < args.count; i++) + spvb_add_phi_source(merge_targets.continue_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); + spvb_branch(basic_block_builder, merge_targets.continue_target); + return; + } + case MergeBreak_TAG: { + Nodes args = terminator->payload.merge_break.args; + for (size_t i = 0; i < args.count; i++) + spvb_add_phi_source(merge_targets.break_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); + spvb_branch(basic_block_builder, merge_targets.break_target); + return; + } + case Terminator_Control_TAG: + case TailCall_TAG: + case Join_TAG: error("Lower me"); + case NotATerminator: error("TODO: emit terminator %s", node_tags[terminator->tag]); + } + SHADY_UNREACHABLE; +} From 0557bbbbab61adcda2a0822b163ea2c7db0d9394 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 11:38:34 +0200 Subject: [PATCH 450/693] backends cleanup --- src/backend/c/emit_c.c | 114 +++++++++++----------- src/backend/c/emit_c.h | 2 +- src/backend/c/emit_c_type.c | 2 +- src/backend/c/emit_c_value.c | 2 +- src/backend/spirv/emit_spv_control_flow.c | 12 --- src/backend/spirv/emit_spv_type.c | 3 - 6 files changed, 60 insertions(+), 75 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 424df54bb..3b5282112 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -37,7 +37,7 @@ CAddr deref_term(Emitter* e, CTerm term) { } // TODO: utf8 -static bool is_legal_c_identifier_char(char c) { +static bool c_is_legal_identifier_char(char c) { if (c >= '0' && c <= '9') return true; if (c >= 'a' && c <= 'z') @@ -49,7 +49,7 @@ static bool is_legal_c_identifier_char(char c) { return false; } -String legalize_c_identifier(Emitter* e, String src) { +String c_legalize_identifier(Emitter* e, String src) { if (!src) return "unnamed"; size_t len = strlen(src); @@ -57,7 +57,7 @@ String legalize_c_identifier(Emitter* e, String src) { size_t i; for (i = 0; i < len; i++) { char c = src[i]; - if (is_legal_c_identifier_char(c)) + if (c_is_legal_identifier_char(c)) dst[i] = c; else dst[i] = '_'; @@ -105,6 +105,58 @@ void emit_unpack_code(Printer* p, String src, Strings dst) { } } +void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer) { + assert((mut || initializer != NULL) && "unbound results are only allowed when creating a mutable local variable"); + + String prefix = ""; + String center = variable_name; + + // add extra qualifiers if immutable + if (!mut) switch (emitter->config.dialect) { + case CDialect_ISPC: + center = format_string_arena(emitter->arena->arena, "const %s", center); + break; + case CDialect_C11: + case CDialect_CUDA: + center = format_string_arena(emitter->arena->arena, "const %s", center); + break; + case CDialect_GLSL: + if (emitter->config.glsl_version >= 130) + prefix = "const "; + break; + } + + String decl = c_emit_type(emitter, t, center); + if (initializer) + print(block_printer, "\n%s%s = %s;", prefix, decl, to_cvalue(emitter, *initializer)); + else + print(block_printer, "\n%s%s;", prefix, decl); +} + +static void emit_lambda_body_at(Emitter* emitter, Printer* p, const Node* body, const Nodes* bbs) { + assert(is_terminator(body)); + //print(p, "{"); + indent(p); + + c_emit_terminator(emitter, p, body); + + if (bbs && bbs->count > 0) { + assert(emitter->config.dialect != CDialect_GLSL); + error("TODO"); + } + + deindent(p); + print(p, "\n"); +} + +String emit_lambda_body(Emitter* emitter, const Node* body, const Nodes* bbs) { + Growy* g = new_growy(); + Printer* p = open_growy_as_printer(g); + emit_lambda_body_at(emitter, p, body, bbs); + growy_append_bytes(g, 1, (char[]) { 0 }); + return printer_growy_unwrap(p); +} + static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, String decl_center, const Type* type, bool constant, String init) { String prefix = NULL; @@ -190,58 +242,6 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S //print(emitter->fn_decls, "\n%s;", declaration); } -void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer) { - assert((mut || initializer != NULL) && "unbound results are only allowed when creating a mutable local variable"); - - String prefix = ""; - String center = variable_name; - - // add extra qualifiers if immutable - if (!mut) switch (emitter->config.dialect) { - case CDialect_ISPC: - center = format_string_arena(emitter->arena->arena, "const %s", center); - break; - case CDialect_C11: - case CDialect_CUDA: - center = format_string_arena(emitter->arena->arena, "const %s", center); - break; - case CDialect_GLSL: - if (emitter->config.glsl_version >= 130) - prefix = "const "; - break; - } - - String decl = c_emit_type(emitter, t, center); - if (initializer) - print(block_printer, "\n%s%s = %s;", prefix, decl, to_cvalue(emitter, *initializer)); - else - print(block_printer, "\n%s%s;", prefix, decl); -} - -static void emit_lambda_body_at(Emitter* emitter, Printer* p, const Node* body, const Nodes* bbs) { - assert(is_terminator(body)); - //print(p, "{"); - indent(p); - - c_emit_terminator(emitter, p, body); - - if (bbs && bbs->count > 0) { - assert(emitter->config.dialect != CDialect_GLSL); - error("TODO"); - } - - deindent(p); - print(p, "\n"); -} - -String emit_lambda_body(Emitter* emitter, const Node* body, const Nodes* bbs) { - Growy* g = new_growy(); - Printer* p = open_growy_as_printer(g); - emit_lambda_body_at(emitter, p, body, bbs); - growy_append_bytes(g, 1, (char[]) { 0 }); - return printer_growy_unwrap(p); -} - void emit_decl(Emitter* emitter, const Node* decl) { assert(is_declaration(decl)); @@ -251,7 +251,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { CType* found2 = lookup_existing_type(emitter, decl); if (found2) return; - const char* name = legalize_c_identifier(emitter, get_declaration_name(decl)); + const char* name = c_legalize_identifier(emitter, get_declaration_name(decl)); const Type* decl_type = decl->type; const char* decl_center = name; CTerm emit_as; @@ -309,7 +309,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { for (size_t i = 0; i < decl->payload.fun.params.count; i++) { String param_name; String variable_name = get_value_name_unsafe(decl->payload.fun.params.nodes[i]); - param_name = format_string_interned(emitter->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); + param_name = format_string_interned(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); register_emitted(emitter, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } diff --git a/src/backend/c/emit_c.h b/src/backend/c/emit_c.h index 8a2b23932..ac82266bb 100644 --- a/src/backend/c/emit_c.h +++ b/src/backend/c/emit_c.h @@ -75,7 +75,7 @@ void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const T CTerm emit_value(Emitter* emitter, Printer*, const Node* value); CTerm emit_c_builtin(Emitter*, Builtin); -String legalize_c_identifier(Emitter*, String); +String c_legalize_identifier(Emitter*, String); String get_record_field_name(const Type* t, size_t i); CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term); diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index a83929375..532377d65 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -66,7 +66,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const for (size_t i = 0; i < dom.count; i++) { String param_name; String variable_name = get_value_name_unsafe(fn->payload.fun.params.nodes[i]); - param_name = format_string_interned(emitter->arena, "%s_%d", legalize_c_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); + param_name = format_string_interned(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); print(paramp, emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { print(paramp, ", "); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index e2ad79c7d..1ed47ced4 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -205,7 +205,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { break; } case Value_FnAddr_TAG: { - emitted = legalize_c_identifier(emitter, get_declaration_name(value->payload.fn_addr.fn)); + emitted = c_legalize_identifier(emitter, get_declaration_name(value->payload.fn_addr.fn)); emitted = format_string_arena(emitter->arena->arena, "(&%s)", emitted); break; } diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index dbbaa0630..3b635ba6e 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -10,7 +10,6 @@ #include BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb) { - // assert(is_basic_block(bb)); BBBuilder* found = find_value_dict(const Node*, BBBuilder, emitter->bb_builders, bb); assert(found); return *found; @@ -236,17 +235,6 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo } } } - /*case Let_TAG: { - const Node* instruction = terminator->payload.let.instruction; - Nodes types = unwrap_multiple_yield_types(emitter->arena, instruction->type); - LARRAY(SpvId, results, types.count); - emit_instruction(emitter, fn_builder, basic_block_builder, instruction, types.count, results); - - for (size_t i = 0; i < types.count; i++) - register_result(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); - emit_terminator(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.let.in); - return; - }*/ case Unreachable_TAG: { spvb_unreachable(basic_block_builder); return; diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index c3345aa6d..e4678ca27 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -12,9 +12,6 @@ #pragma GCC diagnostic error "-Wswitch" -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); - SpvStorageClass emit_addr_space(Emitter* emitter, AddressSpace address_space) { switch(address_space) { case AsShared: return SpvStorageClassWorkgroup; From 209956762af81bf9b6976d1789d3ac49b6d652de Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 12:54:45 +0200 Subject: [PATCH 451/693] spirv: use the scheduler --- src/backend/spirv/emit_spv.c | 71 +++-- src/backend/spirv/emit_spv.h | 33 ++- src/backend/spirv/emit_spv_control_flow.c | 237 +++++------------ src/backend/spirv/emit_spv_type.c | 14 +- src/backend/spirv/emit_spv_value.c | 306 +++++++++++----------- 5 files changed, 290 insertions(+), 371 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 1f8342fe5..410553b25 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -17,23 +17,31 @@ #include #include #include +#include extern SpvBuiltIn spv_builtins[]; #pragma GCC diagnostic error "-Wswitch" -void register_result(Emitter* emitter, const Node* node, SpvId id) { +void register_result(Emitter* emitter, bool global, const Node* node, SpvId id) { if (is_value(node)) { String name = get_value_name_unsafe(node); if (name) spvb_name(emitter->file_builder, id, name); } - insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, node, id); + struct Dict* map = global ? emitter->global_node_ids : emitter->current_fn_node_ids; + insert_dict_and_get_result(struct Node*, SpvId, map, node, id); +} + +SpvId* spv_search_emitted(Emitter* emitter, const Node* node) { + SpvId* found = find_value_dict(const Node*, SpvId, emitter->current_fn_node_ids, node); + if (!found) + found = find_value_dict(const Node*, SpvId, emitter->global_node_ids, node); + return found; } SpvId spv_find_reserved_id(Emitter* emitter, const Node* node) { - SpvId* found = find_value_dict(const Node*, SpvId, emitter->node_ids, node); - assert(found); + SpvId* found = spv_search_emitted(emitter, node); return *found; } @@ -52,27 +60,25 @@ static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const CFG* if (name) spvb_name(emitter->file_builder, bb_id, name); - MergeTargets merge_targets = { - .continue_target = 0, - .break_target = 0, - .join_target = 0 - }; - - emit_terminator(emitter, fn_builder, bb_builder, merge_targets, body); + spv_emit_terminator(emitter, fn_builder, bb_builder, bb_node, body); } static void emit_function(Emitter* emitter, const Node* node) { assert(node->tag == Function_TAG); + emitter->cfg = build_fn_cfg(node); + emitter->scheduler = new_scheduler(emitter->cfg); + const Type* fn_type = node->type; - SpvId fn_id = find_reserved_id(emitter, node); + SpvId fn_id = spv_find_reserved_id(emitter, node); FnBuilder fn_builder = spvb_begin_fn(emitter->file_builder, fn_id, emit_type(emitter, fn_type), nodes_to_codom(emitter, node->payload.fun.return_types)); Nodes params = node->payload.fun.params; for (size_t i = 0; i < params.count; i++) { - const Type* param_type = params.nodes[i]->payload.param.type; + const Node* param = params.nodes[i]; + const Type* param_type = param->payload.param.type; SpvId param_id = spvb_parameter(fn_builder, emit_type(emitter, param_type)); - insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, params.nodes[i], param_id); + register_result(emitter, false, param, param_id); deconstruct_qualified_type(¶m_type); if (param_type->tag == PtrType_TAG && param_type->payload.ptr_type.address_space == AsGlobal) { spvb_decorate(emitter->file_builder, param_id, SpvDecorationAliased, 0, NULL); @@ -86,12 +92,12 @@ static void emit_function(Emitter* emitter, const Node* node) { CFNode* cfnode = read_list(CFNode*, cfg->contents)[i]; assert(cfnode); const Node* bb = cfnode->node; - if (is_cfnode_structural_target(cfnode)) - continue; assert(is_basic_block(bb) || bb == node); SpvId bb_id = spvb_fresh_id(emitter->file_builder); BBBuilder basic_block_builder = spvb_begin_bb(fn_builder, bb_id); insert_dict(const Node*, BBBuilder, emitter->bb_builders, bb, basic_block_builder); + // if (is_cfnode_structural_target(cfnode)) + // continue; // add phis for every non-entry basic block if (i > 0) { assert(is_basic_block(bb) && bb != node); @@ -101,7 +107,7 @@ static void emit_function(Emitter* emitter, const Node* node) { spvb_add_phi(basic_block_builder, emit_type(emitter, bb_param->type), spvb_fresh_id(emitter->file_builder)); } // also make sure to register the label for basic blocks - register_result(emitter, bb, bb_id); + register_result(emitter, false, bb, bb_id); } } // emit the blocks using the dominator tree @@ -109,8 +115,8 @@ static void emit_function(Emitter* emitter, const Node* node) { CFNode* cfnode = cfg->rpo[i]; if (i == 0) assert(cfnode == cfg->entry); - if (is_cfnode_structural_target(cfnode)) - continue; + // if (is_cfnode_structural_target(cfnode)) + // continue; emit_basic_block(emitter, fn_builder, cfg, cfnode); } @@ -125,10 +131,15 @@ static void emit_function(Emitter* emitter, const Node* node) { destroy_growy(g); spvb_declare_function(emitter->file_builder, fn_builder); } + + clear_dict(emitter->current_fn_node_ids); + destroy_scheduler(emitter->scheduler); + emitter->scheduler = NULL; + destroy_cfg(emitter->cfg); } SpvId emit_decl(Emitter* emitter, const Node* decl) { - SpvId* existing = find_value_dict(const Node*, SpvId, emitter->node_ids, decl); + SpvId* existing = find_value_dict(const Node*, SpvId, emitter->global_node_ids, decl); if (existing) return *existing; @@ -136,11 +147,11 @@ SpvId emit_decl(Emitter* emitter, const Node* decl) { case GlobalVariable_TAG: { const GlobalVariable* gvar = &decl->payload.global_variable; SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, decl, given_id); + register_result(emitter, true, decl, given_id); spvb_name(emitter->file_builder, given_id, gvar->name); SpvId init = 0; if (gvar->init) - init = emit_value(emitter, NULL, gvar->init); + init = spv_emit_value(emitter, gvar->init); SpvStorageClass storage_class = emit_addr_space(emitter, gvar->address_space); spvb_global_variable(emitter->file_builder, given_id, emit_type(emitter, decl->type), storage_class, false, init); @@ -191,7 +202,7 @@ SpvId emit_decl(Emitter* emitter, const Node* decl) { return given_id; } case Function_TAG: { SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, decl, given_id); + register_result(emitter, true, decl, given_id); spvb_name(emitter->file_builder, given_id, decl->payload.fun.name); emit_function(emitter, decl); return given_id; @@ -204,9 +215,9 @@ SpvId emit_decl(Emitter* emitter, const Node* decl) { return 0; } case NominalType_TAG: { SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, decl, given_id); + register_result(emitter, true, decl, given_id); spvb_name(emitter->file_builder, given_id, decl->payload.nom_type.name); - emit_nominal_type_body(emitter, decl->payload.nom_type.body, given_id); + spv_emit_nominal_type_body(emitter, decl->payload.nom_type.body, given_id); return given_id; } case NotADeclaration: error(""); @@ -241,13 +252,13 @@ static void emit_entry_points(Emitter* emitter, Nodes declarations) { default: continue; } } - interface_arr[interface_size++] = find_reserved_id(emitter, node); + interface_arr[interface_size++] = spv_find_reserved_id(emitter, node); } for (size_t i = 0; i < declarations.count; i++) { const Node* decl = declarations.nodes[i]; if (decl->tag != Function_TAG) continue; - SpvId fn_id = find_reserved_id(emitter, decl); + SpvId fn_id = spv_find_reserved_id(emitter, decl); const Node* entry_point = lookup_annotation(decl, "EntryPoint"); if (entry_point) { @@ -327,7 +338,8 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, .arena = arena, .configuration = config, .file_builder = file_builder, - .node_ids = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), + .global_node_ids = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), + .current_fn_node_ids = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), .bb_builders = new_dict(Node*, BBBuilder, (HashFn) hash_node, (CmpFn) compare_node), .num_entry_pts = 0, }; @@ -350,7 +362,8 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, *output_size = spvb_finish(file_builder, output); // cleanup the emitter - destroy_dict(emitter.node_ids); + destroy_dict(emitter.global_node_ids); + destroy_dict(emitter.current_fn_node_ids); destroy_dict(emitter.bb_builders); destroy_dict(emitter.extended_instruction_sets); diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index bae62fe41..5251491c3 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -10,14 +10,22 @@ typedef SpvbFileBuilder* FileBuilder; typedef SpvbFnBuilder* FnBuilder; typedef SpvbBasicBlockBuilder* BBBuilder; +typedef struct CFG_ CFG; +typedef struct Scheduler_ Scheduler; + typedef struct Emitter_ { Module* module; IrArena* arena; const CompilerConfig* configuration; FileBuilder file_builder; SpvId void_t; - struct Dict* node_ids; + struct Dict* global_node_ids; + + struct Dict* current_fn_node_ids; struct Dict* bb_builders; + CFG* cfg; + Scheduler* scheduler; + size_t num_entry_pts; struct Dict* extended_instruction_sets; @@ -25,27 +33,18 @@ typedef struct Emitter_ { typedef SpvbPhi** Phis; -typedef struct { - SpvId continue_target, break_target, join_target; - Phis continue_phis, break_phis, join_phis; -} MergeTargets; - #define emit_decl spv_emit_decl #define emit_type spv_emit_type -#define emit_value spv_emit_value -#define emit_instruction spv_emit_instruction -#define emit_terminator spv_emit_terminator -#define find_reserved_id spv_find_reserved_id -#define emit_nominal_type_body spv_emit_nominal_type_body SpvId emit_decl(Emitter*, const Node*); SpvId emit_type(Emitter*, const Type*); -SpvId emit_value(Emitter*, BBBuilder, const Node*); -SpvId emit_instruction(Emitter*, BBBuilder, const Node* instruction); -void emit_terminator(Emitter*, FnBuilder, BBBuilder, MergeTargets, const Node* terminator); +SpvId spv_emit_value(Emitter*, const Node*); +void spv_emit_terminator(Emitter*, FnBuilder, BBBuilder, const Node* abs, const Node* terminator); + +void register_result(Emitter*, bool, const Node*, SpvId id); +SpvId* spv_search_emitted(Emitter* emitter, const Node* node); +SpvId spv_find_reserved_id(Emitter* emitter, const Node* node); -SpvId find_reserved_id(Emitter* emitter, const Node* node); -void register_result(Emitter*, const Node*, SpvId id); BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb); SpvId get_extended_instruction_set(Emitter*, const char*); @@ -54,6 +53,6 @@ SpvStorageClass emit_addr_space(Emitter*, AddressSpace address_space); // SPIR-V doesn't have multiple return types, this bridges the gap... SpvId nodes_to_codom(Emitter* emitter, Nodes return_types); const Type* normalize_type(Emitter* emitter, const Type* type); -void emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id); +void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id); #endif diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 3b635ba6e..9247cd362 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -1,6 +1,7 @@ #include "emit_spv.h" #include "../shady/type.h" +#include "../shady/analysis/cfg.h" #include "list.h" #include "dict.h" @@ -15,10 +16,7 @@ BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb) { return *found; } -static void add_branch_phis(Emitter* emitter, BBBuilder bb_builder, const Node* jump) { - assert(jump->tag == Jump_TAG); - const Node* dst = jump->payload.jump.target; - Nodes args = jump->payload.jump.args; +static void add_branch_phis(Emitter* emitter, BBBuilder bb_builder, const Node* dst, Nodes args) { // because it's forbidden to jump back into the entry block of a function // (which is actually a Function in this IR, not a BasicBlock) // we assert that the destination must be an actual BasicBlock @@ -28,61 +26,32 @@ static void add_branch_phis(Emitter* emitter, BBBuilder bb_builder, const Node* assert(entries_count_list(phis) == args.count); for (size_t i = 0; i < args.count; i++) { SpvbPhi* phi = read_list(SpvbPhi*, phis)[i]; - spvb_add_phi_source(phi, get_block_builder_id(bb_builder), emit_value(emitter, bb_builder, args.nodes[i])); + spvb_add_phi_source(phi, get_block_builder_id(bb_builder), spv_emit_value(emitter, args.nodes[i])); } } -static void emit_if(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, MergeTargets merge_targets, If if_instr) { - Nodes yield_types = if_instr.yield_types; - Nodes results = get_abstraction_params(if_instr.tail); - SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); +static void add_branch_phis_from_jump(Emitter* emitter, BBBuilder bb_builder, Jump jump) { + return add_branch_phis(emitter, bb_builder, jump.target, jump.args); +} + +static void emit_if(Emitter* emitter, BBBuilder bb_builder, If if_instr) { + SpvId join_bb_id = spv_find_reserved_id(emitter, if_instr.tail); - SpvId true_id = spvb_fresh_id(emitter->file_builder); - SpvId false_id = if_instr.if_false ? spvb_fresh_id(emitter->file_builder) : join_bb_id; + SpvId true_id = spv_find_reserved_id(emitter, if_instr.if_true); + SpvId false_id = if_instr.if_false ? spv_find_reserved_id(emitter, if_instr.if_false) : join_bb_id; spvb_selection_merge(bb_builder, join_bb_id, 0); - SpvId condition = emit_value(emitter, bb_builder, if_instr.condition); + SpvId condition = spv_emit_value(emitter, if_instr.condition); spvb_branch_conditional(bb_builder, condition, true_id, false_id); - - // When 'join' is codegen'd, these will be filled with the values given to it - BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); - LARRAY(SpvbPhi*, join_phis, yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - assert(if_instr.if_false && "Ifs with yield types need false branches !"); - SpvId phi_id = spvb_fresh_id(emitter->file_builder); - SpvId type = emit_type(emitter, yield_types.nodes[i]); - SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); - join_phis[i] = phi; - register_result(emitter, results.nodes[i], phi_id); - } - - MergeTargets merge_targets_branches = merge_targets; - merge_targets_branches.join_target = join_bb_id; - merge_targets_branches.join_phis = join_phis; - - BBBuilder true_bb = spvb_begin_bb(fn_builder, true_id); - spvb_add_bb(fn_builder, true_bb); - emit_terminator(emitter, fn_builder, true_bb, merge_targets_branches, get_abstraction_body(if_instr.if_true)); - if (if_instr.if_false) { - BBBuilder false_bb = spvb_begin_bb(fn_builder, false_id); - spvb_add_bb(fn_builder, false_bb); - emit_terminator(emitter, fn_builder, false_bb, merge_targets_branches, get_abstraction_body(if_instr.if_false)); - } - - spvb_add_bb(fn_builder, join_bb); - bb_builder = join_bb; - - emit_terminator(emitter, fn_builder, bb_builder, merge_targets, get_abstraction_body(if_instr.tail)); } -static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, MergeTargets merge_targets, Match match) { - Nodes yield_types = match.yield_types; - SpvId join_bb_id = spvb_fresh_id(emitter->file_builder); +static void emit_match(Emitter* emitter, BBBuilder bb_builder, Match match) { + SpvId join_bb_id = spv_find_reserved_id(emitter, match.tail); assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); - SpvId inspectee = emit_value(emitter, bb_builder, match.inspect); + SpvId inspectee = spv_emit_value(emitter, match.inspect); - SpvId default_id = spvb_fresh_id(emitter->file_builder); + SpvId default_id = spv_find_reserved_id(emitter, match.default_case); const Type* inspectee_t = match.inspect->type; deconstruct_qualified_type(&inspectee_t); @@ -98,137 +67,55 @@ static void emit_match(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_buil } else { literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) value; } - literals_and_cases[i * literal_case_entry_size + literal_width] = spvb_fresh_id(emitter->file_builder); + literals_and_cases[i * literal_case_entry_size + literal_width] = spv_find_reserved_id(emitter, match.cases.nodes[i]); } spvb_selection_merge(bb_builder, join_bb_id, 0); spvb_switch(bb_builder, inspectee, default_id, match.cases.count * literal_case_entry_size, literals_and_cases); - - // When 'join' is codegen'd, these will be filled with the values given to it - BBBuilder join_bb = spvb_begin_bb(fn_builder, join_bb_id); - LARRAY(SpvbPhi*, join_phis, yield_types.count); - Nodes results = get_abstraction_params(match.tail); - for (size_t i = 0; i < yield_types.count; i++) { - SpvId phi_id = spvb_fresh_id(emitter->file_builder); - SpvId type = emit_type(emitter, yield_types.nodes[i]); - SpvbPhi* phi = spvb_add_phi(join_bb, type, phi_id); - join_phis[i] = phi; - register_result(emitter, results.nodes[i], phi_id); - } - - MergeTargets merge_targets_branches = merge_targets; - merge_targets_branches.join_target = join_bb_id; - merge_targets_branches.join_phis = join_phis; - - for (size_t i = 0; i < match.cases.count; i++) { - BBBuilder case_bb = spvb_begin_bb(fn_builder, literals_and_cases[i * literal_case_entry_size + literal_width]); - const Node* case_ = match.cases.nodes[i]; - spvb_add_bb(fn_builder, case_bb); - emit_terminator(emitter, fn_builder, case_bb, merge_targets_branches, get_abstraction_body(case_)); - } - BBBuilder default_bb = spvb_begin_bb(fn_builder, default_id); - spvb_add_bb(fn_builder, default_bb); - emit_terminator(emitter, fn_builder, default_bb, merge_targets_branches, get_abstraction_body(match.default_case)); - - spvb_add_bb(fn_builder, join_bb); - bb_builder = join_bb; - - emit_terminator(emitter, fn_builder, bb_builder, merge_targets, get_abstraction_body(match.tail)); } -static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, MergeTargets merge_targets, Loop loop_instr) { - Nodes yield_types = loop_instr.yield_types; - - const Node* loop_inside = loop_instr.body; - Nodes loop_params = get_abstraction_params(loop_inside); - - // First we create all the basic blocks we'll need - SpvId header_id = spvb_fresh_id(emitter->file_builder); - BBBuilder header_builder = spvb_begin_bb(fn_builder, header_id); - spvb_name(emitter->file_builder, header_id, "loop_header"); - - SpvId body_id = spvb_fresh_id(emitter->file_builder); - BBBuilder body_builder = spvb_begin_bb(fn_builder, body_id); - spvb_name(emitter->file_builder, body_id, "loop_body"); +static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, Loop loop_instr) { + SpvId body_id = spv_find_reserved_id(emitter, loop_instr.body); SpvId continue_id = spvb_fresh_id(emitter->file_builder); BBBuilder continue_builder = spvb_begin_bb(fn_builder, continue_id); spvb_name(emitter->file_builder, continue_id, "loop_continue"); - SpvId next_id = spvb_fresh_id(emitter->file_builder); - BBBuilder next = spvb_begin_bb(fn_builder, next_id); - spvb_name(emitter->file_builder, next_id, "loop_next"); - - // Wire up the phi nodes for loop exit - LARRAY(SpvbPhi*, loop_break_phis, yield_types.count); - Nodes results = get_abstraction_params(loop_instr.tail); - for (size_t i = 0; i < yield_types.count; i++) { - SpvId yielded_type = emit_type(emitter, get_unqualified_type(yield_types.nodes[i])); - - SpvId break_phi_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* phi = spvb_add_phi(next, yielded_type, break_phi_id); - loop_break_phis[i] = phi; - register_result(emitter, results.nodes[i], break_phi_id); - } - - // Wire up the phi nodes for the loop contents - LARRAY(SpvbPhi*, loop_continue_phis, loop_params.count); - for (size_t i = 0; i < loop_params.count; i++) { - SpvId loop_param_type = emit_type(emitter, get_unqualified_type(loop_params.nodes[i]->type)); - - SpvId continue_phi_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* continue_phi = spvb_add_phi(continue_builder, loop_param_type, continue_phi_id); - loop_continue_phis[i] = continue_phi; - - // To get the actual loop parameter, we make a second phi for the nodes that go into the header - // We already know the two edges into the header so we immediately add the Phi sources for it. - SpvId loop_param_id = spvb_fresh_id(emitter->file_builder); - SpvbPhi* loop_param_phi = spvb_add_phi(header_builder, loop_param_type, loop_param_id); - SpvId param_initial_value = emit_value(emitter, bb_builder, loop_instr.initial_args.nodes[i]); - spvb_add_phi_source(loop_param_phi, get_block_builder_id(bb_builder), param_initial_value); - spvb_add_phi_source(loop_param_phi, get_block_builder_id(continue_builder), continue_phi_id); - register_result(emitter, loop_params.nodes[i], loop_param_id); - } - - // The current block goes to the header (it can't be the header itself !) - spvb_branch(bb_builder, header_id); - spvb_add_bb(fn_builder, header_builder); + SpvId next_id = spv_find_reserved_id(emitter, loop_instr.tail); // the header block receives the loop merge annotation - spvb_loop_merge(header_builder, next_id, continue_id, 0, 0, NULL); - spvb_branch(header_builder, body_id); - spvb_add_bb(fn_builder, body_builder); - - // Emission of the body requires extra info for the break/continue merge terminators - MergeTargets merge_targets_branches = merge_targets; - merge_targets_branches.continue_target = continue_id; - merge_targets_branches.continue_phis = loop_continue_phis; - merge_targets_branches.break_target = next_id; - merge_targets_branches.break_phis = loop_break_phis; - emit_terminator(emitter, fn_builder, body_builder, merge_targets_branches, get_abstraction_body(loop_inside)); + spvb_loop_merge(bb_builder, next_id, continue_id, 0, 0, NULL); + spvb_branch(bb_builder, body_id); + add_branch_phis(emitter, bb_builder, loop_instr.body, loop_instr.initial_args); // the continue block just jumps back into the header - spvb_branch(continue_builder, header_id); + spvb_branch(continue_builder, body_id); spvb_add_bb(fn_builder, continue_builder); +} - // We start the next block - spvb_add_bb(fn_builder, next); - bb_builder = next; - - emit_terminator(emitter, fn_builder, bb_builder, merge_targets, get_abstraction_body(loop_instr.tail)); +static const Node* find_construct(Emitter* emitter, const Node* abs, Structured_constructTag tag) { + CFNode* n = cfg_lookup(emitter->cfg, abs); + while (n) { + const Node* terminator = get_abstraction_body(n->node); + assert(terminator); + if (terminator->tag == tag) + return terminator; + n = n->idom; + } + return NULL; } -void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_block_builder, MergeTargets merge_targets, const Node* terminator) { +void spv_emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_block_builder, const Node* abs, const Node* terminator) { switch (is_terminator(terminator)) { case Return_TAG: { const Nodes* ret_values = &terminator->payload.fn_ret.args; switch (ret_values->count) { case 0: spvb_return_void(basic_block_builder); return; - case 1: spvb_return_value(basic_block_builder, emit_value(emitter, basic_block_builder, ret_values->nodes[0])); return; + case 1: spvb_return_value(basic_block_builder, spv_emit_value(emitter, ret_values->nodes[0])); return; default: { LARRAY(SpvId, arr, ret_values->count); for (size_t i = 0; i < ret_values->count; i++) - arr[i] = emit_value(emitter, basic_block_builder, ret_values->nodes[i]); + arr[i] = spv_emit_value(emitter, ret_values->nodes[i]); SpvId return_that = spvb_composite(basic_block_builder, fn_ret_type_id(fn_builder), ret_values->count, arr); spvb_return_value(basic_block_builder, return_that); return; @@ -240,52 +127,58 @@ void emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_blo return; } case Jump_TAG: { - add_branch_phis(emitter, basic_block_builder, terminator); - spvb_branch(basic_block_builder, find_reserved_id(emitter, terminator->payload.jump.target)); + add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.jump); + spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, terminator->payload.jump.target)); return; } case Branch_TAG: { - SpvId condition = emit_value(emitter, basic_block_builder, terminator->payload.branch.condition); - add_branch_phis(emitter, basic_block_builder, terminator->payload.branch.true_jump); - add_branch_phis(emitter, basic_block_builder, terminator->payload.branch.false_jump); - spvb_branch_conditional(basic_block_builder, condition, find_reserved_id(emitter, terminator->payload.branch.true_jump->payload.jump.target), find_reserved_id(emitter, terminator->payload.branch.false_jump->payload.jump.target)); + SpvId condition = spv_emit_value(emitter, terminator->payload.branch.condition); + add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.branch.true_jump->payload.jump); + add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.branch.false_jump->payload.jump); + spvb_branch_conditional(basic_block_builder, condition, spv_find_reserved_id(emitter, terminator->payload.branch.true_jump->payload.jump.target), spv_find_reserved_id(emitter, terminator->payload.branch.false_jump->payload.jump.target)); return; } case Switch_TAG: { - SpvId inspectee = emit_value(emitter, basic_block_builder, terminator->payload.br_switch.switch_value); + SpvId inspectee = spv_emit_value(emitter, terminator->payload.br_switch.switch_value); LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); for (size_t i = 0; i < terminator->payload.br_switch.case_jumps.count; i++) { - add_branch_phis(emitter, basic_block_builder, terminator->payload.br_switch.case_jumps.nodes[i]); + add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.br_switch.case_jumps.nodes[i]->payload.jump); error("TODO finish") } - add_branch_phis(emitter, basic_block_builder, terminator->payload.br_switch.default_jump); - SpvId default_tgt = find_reserved_id(emitter, terminator->payload.br_switch.default_jump->payload.jump.target); + add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.br_switch.default_jump->payload.jump); + SpvId default_tgt = spv_find_reserved_id(emitter, terminator->payload.br_switch.default_jump->payload.jump.target); spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); return; } - case If_TAG: return emit_if(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.if_instr); - case Match_TAG: return emit_match(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.match_instr); - case Loop_TAG: return emit_loop(emitter, fn_builder, basic_block_builder, merge_targets, terminator->payload.loop_instr); + case If_TAG: return emit_if(emitter, basic_block_builder, terminator->payload.if_instr); + case Match_TAG: return emit_match(emitter, basic_block_builder, terminator->payload.match_instr); + case Loop_TAG: return emit_loop(emitter, fn_builder, basic_block_builder, terminator->payload.loop_instr); case MergeSelection_TAG: { + const Node* construct = find_construct(emitter, abs, Structured_construct_If_TAG); + if (!construct) + construct = find_construct(emitter, abs, Structured_construct_Match_TAG); + const Node* tail = get_structured_construct_tail(construct); Nodes args = terminator->payload.merge_selection.args; for (size_t i = 0; i < args.count; i++) - spvb_add_phi_source(merge_targets.join_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); - spvb_branch(basic_block_builder, merge_targets.join_target); + add_branch_phis(emitter, basic_block_builder, tail, args); + spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, tail)); return; } case MergeContinue_TAG: { + const Node* construct = find_construct(emitter, abs, Structured_construct_Loop_TAG); + Loop payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_continue.args; - for (size_t i = 0; i < args.count; i++) - spvb_add_phi_source(merge_targets.continue_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); - spvb_branch(basic_block_builder, merge_targets.continue_target); + add_branch_phis(emitter, basic_block_builder, payload.body, args); + spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, payload.body)); return; } case MergeBreak_TAG: { + const Node* construct = find_construct(emitter, abs, Structured_construct_Loop_TAG); + Loop payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_break.args; - for (size_t i = 0; i < args.count; i++) - spvb_add_phi_source(merge_targets.break_phis[i], get_block_builder_id(basic_block_builder), emit_value(emitter, basic_block_builder, args.nodes[i])); - spvb_branch(basic_block_builder, merge_targets.break_target); + add_branch_phis(emitter, basic_block_builder, payload.tail, args); + spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, payload.tail)); return; } case Terminator_Control_TAG: diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index e4678ca27..61b23f876 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -72,7 +72,7 @@ SpvId nodes_to_codom(Emitter* emitter, Nodes return_types) { } } -void emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id) { +void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id) { switch (type->tag) { case RecordType_TAG: { Nodes member_types = type->payload.record_type.members; @@ -99,7 +99,7 @@ SpvId emit_type(Emitter* emitter, const Type* type) { // we could hash the spirv types we generate to find duplicates, but it is easier to normalise our shady types and reuse their infra type = normalize_type(emitter, type); - SpvId* existing = find_value_dict(struct Node*, SpvId, emitter->node_ids, type); + SpvId* existing = spv_search_emitted(emitter, type); if (existing) return *existing; @@ -144,7 +144,7 @@ SpvId emit_type(Emitter* emitter, const Type* type) { const Type* pointed_type = type->payload.ptr_type.pointed_type; if (get_maybe_nominal_type_decl(pointed_type) && sc == SpvStorageClassPhysicalStorageBuffer) { new = spvb_forward_ptr_type(emitter->file_builder, sc); - insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, type, new); + register_result(emitter, true, type, new); SpvId pointee = emit_type(emitter, pointed_type); spvb_ptr_type_define(emitter->file_builder, new, sc, pointee); return new; @@ -179,7 +179,7 @@ SpvId emit_type(Emitter* emitter, const Type* type) { case ArrType_TAG: { SpvId element_type = emit_type(emitter, type->payload.arr_type.element_type); if (type->payload.arr_type.size) { - new = spvb_array_type(emitter->file_builder, element_type, emit_value(emitter, NULL, type->payload.arr_type.size)); + new = spvb_array_type(emitter->file_builder, element_type, spv_emit_value(emitter, type->payload.arr_type.size)); } else { new = spvb_runtime_array_type(emitter->file_builder, element_type); } @@ -199,8 +199,8 @@ SpvId emit_type(Emitter* emitter, const Type* type) { break; } new = spvb_fresh_id(emitter->file_builder); - insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, type, new); - emit_nominal_type_body(emitter, type, new); + register_result(emitter, true, type, new); + spv_emit_nominal_type_body(emitter, type, new); return new; } case Type_TypeDeclRef_TAG: { @@ -225,6 +225,6 @@ SpvId emit_type(Emitter* emitter, const Type* type) { } } - insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, type, new); + register_result(emitter, true, type, new); return new; } diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 22fa5a380..42ff4009c 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -7,6 +7,8 @@ #include "../shady/type.h" #include "../shady/transform/memory_layout.h" #include "../shady/transform/ir_gen_helpers.h" +#include "../shady/analysis/cfg.h" +#include "../shady/analysis/scheduler.h" #include #include @@ -14,115 +16,6 @@ #include "spirv/unified1/NonSemanticDebugPrintf.h" #include "spirv/unified1/GLSL.std.450.h" -SpvId emit_value(Emitter* emitter, BBBuilder bb_builder, const Node* node) { - SpvId* existing = find_value_dict(const Node*, SpvId, emitter->node_ids, node); - if (existing) - return *existing; - - SpvId new; - switch (is_value(node)) { - case NotAValue: error(""); - case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); - case Value_ConstrainedValue_TAG: - case Value_UntypedNumber_TAG: - case Value_FnAddr_TAG: error("Should be lowered away earlier!"); - default: { - assert(!is_instruction(node)); - error("Unhandled value for code generation: %s", node_tags[node->tag]); - } - case IntLiteral_TAG: { - new = spvb_fresh_id(emitter->file_builder); - SpvId ty = emit_type(emitter, node->type); - // 64-bit constants take two spirv words, anything else fits in one - if (node->payload.int_literal.width == IntTy64) { - uint32_t arr[] = { node->payload.int_literal.value & 0xFFFFFFFF, node->payload.int_literal.value >> 32 }; - spvb_constant(emitter->file_builder, new, ty, 2, arr); - } else { - uint32_t arr[] = { node->payload.int_literal.value }; - spvb_constant(emitter->file_builder, new, ty, 1, arr); - } - break; - } - case FloatLiteral_TAG: { - new = spvb_fresh_id(emitter->file_builder); - SpvId ty = emit_type(emitter, node->type); - switch (node->payload.float_literal.width) { - case FloatTy16: { - uint32_t arr[] = { node->payload.float_literal.value & 0xFFFF }; - spvb_constant(emitter->file_builder, new, ty, 1, arr); - break; - } - case FloatTy32: { - uint32_t arr[] = { node->payload.float_literal.value }; - spvb_constant(emitter->file_builder, new, ty, 1, arr); - break; - } - case FloatTy64: { - uint32_t arr[] = { node->payload.float_literal.value & 0xFFFFFFFF, node->payload.float_literal.value >> 32 }; - spvb_constant(emitter->file_builder, new, ty, 2, arr); - break; - } - } - break; - } - case True_TAG: { - new = spvb_fresh_id(emitter->file_builder); - spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), true); - break; - } - case False_TAG: { - new = spvb_fresh_id(emitter->file_builder); - spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), false); - break; - } - case Value_StringLiteral_TAG: { - new = spvb_debug_string(emitter->file_builder, node->payload.string_lit.string); - break; - } - case Value_NullPtr_TAG: { - new = spvb_constant_null(emitter->file_builder, emit_type(emitter, node->payload.null_ptr.ptr_type)); - break; - } - case Composite_TAG: { - Nodes contents = node->payload.composite.contents; - LARRAY(SpvId, ids, contents.count); - for (size_t i = 0; i < contents.count; i++) { - ids[i] = emit_value(emitter, bb_builder, contents.nodes[i]); - } - if (bb_builder) { - new = spvb_composite(bb_builder, emit_type(emitter, node->type), contents.count, ids); - return new; - } else { - new = spvb_constant_composite(emitter->file_builder, emit_type(emitter, node->type), contents.count, ids); - break; - } - } - case Value_Undef_TAG: { - new = spvb_undef(emitter->file_builder, emit_type(emitter, node->payload.undef.type)); - break; - } - case Value_Fill_TAG: error("lower me") - case RefDecl_TAG: { - const Node* decl = node->payload.ref_decl.decl; - switch (decl->tag) { - case GlobalVariable_TAG: { - new = emit_decl(emitter, decl); - break; - } - case Constant_TAG: { - new = emit_value(emitter, NULL, decl->payload.constant.value); - break; - } - default: error("RefDecl must reference a constant or global"); - } - break; - } - } - - insert_dict_and_get_result(struct Node*, SpvId, emitter->node_ids, node, new); - return new; -} - typedef enum { Custom, Plain, } InstrClass; @@ -289,7 +182,7 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins if (entry.class != Custom) { LARRAY(SpvId, emitted_args, args.count); for (size_t i = 0; i < args.count; i++) - emitted_args[i] = emit_value(emitter, bb_builder, args.nodes[i]); + emitted_args[i] = spv_emit_value(emitter, args.nodes[i]); switch (entry.class) { case Plain: { @@ -299,13 +192,10 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins return emitted_args[0]; } - error("TODO: convert spirv backend away from multiple returns") - Nodes results_ts = unwrap_multiple_yield_types(emitter->arena, instr->type); - SpvId result_t = instr->type == empty_multiple_return_type(emitter->arena) ? emit_type(emitter, instr->type) : emitter->void_t; - if (opcode == SpvOpMax) goto custom; + SpvId result_t = instr->type == empty_multiple_return_type(emitter->arena) ? emit_type(emitter, instr->type) : emitter->void_t; if (entry.extended_set) { SpvId set_id = get_extended_instruction_set(emitter, entry.extended_set); return spvb_ext_instruction(bb_builder, result_t, set_id, opcode, args.count, emitted_args); @@ -325,31 +215,31 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins const Type* src = get_unqualified_type(first(the_op.operands)->type); assert(dst->tag == PtrType_TAG && src->tag == PtrType_TAG); assert(src != dst); - return spvb_op(bb_builder, SpvOpBitcast, emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, bb_builder, first(the_op.operands)) }); + return spvb_op(bb_builder, SpvOpBitcast, emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, first(the_op.operands)) }); } case subgroup_ballot_op: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = uint32_type(emitter->arena) }); - SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); - SpvId raw_result = spvb_group_ballot(bb_builder, emit_type(emitter, i32x4), emit_value(emitter, bb_builder, first(args)), scope_subgroup); + SpvId scope_subgroup = spv_emit_value(emitter, int32_literal(emitter->arena, SpvScopeSubgroup)); + SpvId raw_result = spvb_group_ballot(bb_builder, emit_type(emitter, i32x4), spv_emit_value(emitter, first(args)), scope_subgroup); // TODO: why are we doing this in SPIR-V and not the IR ? SpvId low32 = spvb_extract(bb_builder, emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 0 }); SpvId hi32 = spvb_extract(bb_builder, emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 1 }); SpvId low64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &low32); SpvId hi64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &hi32); - hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { hi64, emit_value(emitter, bb_builder, int64_literal(emitter->arena, 32)) }); + hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { hi64, spv_emit_value(emitter, int64_literal(emitter->arena, 32)) }); SpvId final_result = spvb_op(bb_builder, SpvOpBitwiseOr, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { low64, hi64 }); return final_result; } case subgroup_reduce_sum_op: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformArithmetic); - SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); - return spvb_group_non_uniform_iadd(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), emit_value(emitter, bb_builder, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); + SpvId scope_subgroup = spv_emit_value(emitter, int32_literal(emitter->arena, SpvScopeSubgroup)); + return spvb_group_non_uniform_iadd(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), spv_emit_value(emitter, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); } case subgroup_elect_first_op: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniform); SpvId result_t = emit_type(emitter, bool_type(emitter->arena)); - SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); + SpvId scope_subgroup = spv_emit_value(emitter, int32_literal(emitter->arena, SpvScopeSubgroup)); return spvb_group_elect(bb_builder, result_t, scope_subgroup); } case insert_op: @@ -368,10 +258,10 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins if (dynamic) { LARRAY(SpvId, indices, indices_count); for (size_t i = 0; i < indices_count; i++) { - indices[i] = emit_value(emitter, bb_builder, args.nodes[i + indices_start]); + indices[i] = spv_emit_value(emitter, args.nodes[i + indices_start]); } assert(indices_count == 1); - return spvb_vector_extract_dynamic(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, src_value), indices[0]); + return spvb_vector_extract_dynamic(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, src_value), indices[0]); } LARRAY(uint32_t, indices, indices_count); for (size_t i = 0; i < indices_count; i++) { @@ -380,14 +270,14 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins } if (insert) - return spvb_insert(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, args.nodes[1]), emit_value(emitter, bb_builder, src_value), indices_count, indices); + return spvb_insert(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, args.nodes[1]), spv_emit_value(emitter, src_value), indices_count, indices); else - return spvb_extract(bb_builder, emit_type(emitter, result_t), emit_value(emitter, bb_builder, src_value), indices_count, indices); + return spvb_extract(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, src_value), indices_count, indices); } case shuffle_op: { const Type* result_t = instr->type; - SpvId a = emit_value(emitter, bb_builder, args.nodes[0]); - SpvId b = emit_value(emitter, bb_builder, args.nodes[1]); + SpvId a = spv_emit_value(emitter, args.nodes[0]); + SpvId b = spv_emit_value(emitter, args.nodes[1]); LARRAY(uint32_t, indices, args.count - 2); for (size_t i = 0; i < args.count - 2; i++) { int64_t indice = get_int_literal_value(*resolve_to_int_literal(args.nodes[i + 2]), true); @@ -399,9 +289,9 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins return spvb_vecshuffle(bb_builder, emit_type(emitter, result_t), a, b, args.count - 2, indices); } case select_op: { - SpvId cond = emit_value(emitter, bb_builder, first(args)); - SpvId truv = emit_value(emitter, bb_builder, args.nodes[1]); - SpvId flsv = emit_value(emitter, bb_builder, args.nodes[2]); + SpvId cond = spv_emit_value(emitter, first(args)); + SpvId truv = spv_emit_value(emitter, args.nodes[1]); + SpvId flsv = spv_emit_value(emitter, args.nodes[2]); return spvb_select(bb_builder, emit_type(emitter, args.nodes[1]->type), cond, truv, flsv); } @@ -414,16 +304,16 @@ static SpvId emit_ext_instr(Emitter* emitter, BBBuilder bb_builder, ExtInstr ins if (strcmp("spirv.core", instr.set) == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { - SpvId scope_subgroup = emit_value(emitter, bb_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); + SpvId scope_subgroup = spv_emit_value(emitter, int32_literal(emitter->arena, SpvScopeSubgroup)); SpvId result; if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); - SpvId local_id = spvb_op(bb_builder, SpvOpLoad, emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { emit_value(emitter, bb_builder, b) }); - result = spvb_group_shuffle(bb_builder, emit_type(emitter, instr.result_t), scope_subgroup, emit_value(emitter, bb_builder, first(instr.operands)), local_id); + SpvId local_id = spvb_op(bb_builder, SpvOpLoad, emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, b) }); + result = spvb_group_shuffle(bb_builder, emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, first(instr.operands)), local_id); spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); } else { - result = spvb_group_broadcast_first(bb_builder, emit_type(emitter, instr.result_t), emit_value(emitter, bb_builder, first(instr.operands)), scope_subgroup); + result = spvb_group_broadcast_first(bb_builder, emit_type(emitter, instr.result_t), spv_emit_value(emitter, first(instr.operands)), scope_subgroup); } spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); @@ -433,12 +323,12 @@ static SpvId emit_ext_instr(Emitter* emitter, BBBuilder bb_builder, ExtInstr ins } LARRAY(SpvId, ops, instr.operands.count); for (size_t i = 0; i < instr.operands.count; i++) - ops[i] = emit_value(emitter, bb_builder, instr.operands.nodes[i]); + ops[i] = spv_emit_value(emitter, instr.operands.nodes[i]); return spvb_op(bb_builder, instr.opcode, emit_type(emitter, instr.result_t), instr.operands.count, ops); } LARRAY(SpvId, ops, instr.operands.count); for (size_t i = 0; i < instr.operands.count; i++) - ops[i] = emit_value(emitter, bb_builder, instr.operands.nodes[i]); + ops[i] = spv_emit_value(emitter, instr.operands.nodes[i]); SpvId set_id = get_extended_instruction_set(emitter, instr.set); return spvb_ext_instruction(bb_builder, emit_type(emitter, instr.result_t), set_id, instr.opcode, instr.operands.count, ops); } @@ -455,11 +345,11 @@ static SpvId emit_leaf_call(Emitter* emitter, BBBuilder bb_builder, Call call) { SpvId return_type = nodes_to_codom(emitter, return_types); LARRAY(SpvId, args, call.args.count); for (size_t i = 0; i < call.args.count; i++) - args[i] = emit_value(emitter, bb_builder, call.args.nodes[i]); + args[i] = spv_emit_value(emitter, call.args.nodes[i]); return spvb_call(bb_builder, return_type, callee, call.args.count, args); } -SpvId emit_instruction(Emitter* emitter, BBBuilder bb_builder, const Node* instruction) { +static SpvId spv_emit_instruction(Emitter* emitter, BBBuilder bb_builder, const Node* instruction) { assert(is_instruction(instruction)); switch (is_instruction(instruction)) { @@ -501,7 +391,7 @@ SpvId emit_instruction(Emitter* emitter, BBBuilder bb_builder, const Node* instr operands_count += 2; } - SpvId eptr = emit_value(emitter, bb_builder, payload.ptr); + SpvId eptr = spv_emit_value(emitter, payload.ptr); return spvb_load(bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); } case Instruction_Store_TAG: { @@ -521,18 +411,18 @@ SpvId emit_instruction(Emitter* emitter, BBBuilder bb_builder, const Node* instr operands_count += 2; } - SpvId eptr = emit_value(emitter, bb_builder, payload.ptr); - SpvId eval = emit_value(emitter, bb_builder, payload.value); + SpvId eptr = spv_emit_value(emitter, payload.ptr); + SpvId eval = spv_emit_value(emitter, payload.value); spvb_store(bb_builder, eval, eptr, operands_count, operands); return 0; } case Lea_TAG: { Lea payload = instruction->payload.lea; - SpvId base = emit_value(emitter, bb_builder, payload.ptr); + SpvId base = spv_emit_value(emitter, payload.ptr); LARRAY(SpvId, indices, payload.indices.count); for (size_t i = 0; i < payload.indices.count; i++) - indices[i] = payload.indices.nodes[i] ? emit_value(emitter, bb_builder, payload.indices.nodes[i]) : 0; + indices[i] = payload.indices.nodes[i] ? spv_emit_value(emitter, payload.indices.nodes[i]) : 0; const IntLiteral* known_offset = resolve_to_int_literal(payload.offset); if (known_offset && known_offset->value == 0) { @@ -540,17 +430,141 @@ SpvId emit_instruction(Emitter* emitter, BBBuilder bb_builder, const Node* instr return spvb_access_chain(bb_builder, emit_type(emitter, target_type), base, payload.indices.count, indices); } else { const Type* target_type = instruction->type; - return spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, emit_value(emitter, bb_builder, payload.offset), payload.indices.count, indices); + return spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, spv_emit_value(emitter, payload.offset), payload.indices.count, indices); } } case Instruction_DebugPrintf_TAG: { SpvId set_id = get_extended_instruction_set(emitter, "NonSemantic.DebugPrintf"); LARRAY(SpvId, args, instruction->payload.debug_printf.args.count + 1); - args[0] = emit_value(emitter, bb_builder, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); + args[0] = spv_emit_value(emitter, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) - args[i + 1] = emit_value(emitter, bb_builder, instruction->payload.debug_printf.args.nodes[i]); + args[i + 1] = spv_emit_value(emitter, instruction->payload.debug_printf.args.nodes[i]); spvb_ext_instruction(bb_builder, emit_type(emitter, instruction->type), set_id, (SpvOp) NonSemanticDebugPrintfDebugPrintf, instruction->payload.debug_printf.args.count + 1, args); return 0; } } } + +static SpvId spv_emit_value_(Emitter* emitter, BBBuilder bb_builder, const Node* node) { + if (is_instruction(node)) + return spv_emit_instruction(emitter, bb_builder, node); + + SpvId new; + switch (is_value(node)) { + case NotAValue: error(""); + case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); + case Value_ConstrainedValue_TAG: + case Value_UntypedNumber_TAG: + case Value_FnAddr_TAG: error("Should be lowered away earlier!"); + case IntLiteral_TAG: { + new = spvb_fresh_id(emitter->file_builder); + SpvId ty = emit_type(emitter, node->type); + // 64-bit constants take two spirv words, anything else fits in one + if (node->payload.int_literal.width == IntTy64) { + uint32_t arr[] = { node->payload.int_literal.value & 0xFFFFFFFF, node->payload.int_literal.value >> 32 }; + spvb_constant(emitter->file_builder, new, ty, 2, arr); + } else { + uint32_t arr[] = { node->payload.int_literal.value }; + spvb_constant(emitter->file_builder, new, ty, 1, arr); + } + break; + } + case FloatLiteral_TAG: { + new = spvb_fresh_id(emitter->file_builder); + SpvId ty = emit_type(emitter, node->type); + switch (node->payload.float_literal.width) { + case FloatTy16: { + uint32_t arr[] = { node->payload.float_literal.value & 0xFFFF }; + spvb_constant(emitter->file_builder, new, ty, 1, arr); + break; + } + case FloatTy32: { + uint32_t arr[] = { node->payload.float_literal.value }; + spvb_constant(emitter->file_builder, new, ty, 1, arr); + break; + } + case FloatTy64: { + uint32_t arr[] = { node->payload.float_literal.value & 0xFFFFFFFF, node->payload.float_literal.value >> 32 }; + spvb_constant(emitter->file_builder, new, ty, 2, arr); + break; + } + } + break; + } + case True_TAG: { + new = spvb_fresh_id(emitter->file_builder); + spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), true); + break; + } + case False_TAG: { + new = spvb_fresh_id(emitter->file_builder); + spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), false); + break; + } + case Value_StringLiteral_TAG: { + new = spvb_debug_string(emitter->file_builder, node->payload.string_lit.string); + break; + } + case Value_NullPtr_TAG: { + new = spvb_constant_null(emitter->file_builder, emit_type(emitter, node->payload.null_ptr.ptr_type)); + break; + } + case Composite_TAG: { + Nodes contents = node->payload.composite.contents; + LARRAY(SpvId, ids, contents.count); + for (size_t i = 0; i < contents.count; i++) { + ids[i] = spv_emit_value(emitter, contents.nodes[i]); + } + if (bb_builder) { + new = spvb_composite(bb_builder, emit_type(emitter, node->type), contents.count, ids); + return new; + } else { + new = spvb_constant_composite(emitter->file_builder, emit_type(emitter, node->type), contents.count, ids); + break; + } + } + case Value_Undef_TAG: { + new = spvb_undef(emitter->file_builder, emit_type(emitter, node->payload.undef.type)); + break; + } + case Value_Fill_TAG: error("lower me") + case RefDecl_TAG: { + const Node* decl = node->payload.ref_decl.decl; + switch (decl->tag) { + case GlobalVariable_TAG: { + new = emit_decl(emitter, decl); + break; + } + case Constant_TAG: { + new = spv_emit_value(emitter, decl->payload.constant.value); + break; + } + default: error("RefDecl must reference a constant or global"); + } + break; + } + default: { + error("Unhandled value for code generation: %s", node_tags[node->tag]); + } + } + + return new; +} + +SpvId spv_emit_value(Emitter* emitter, const Node* node) { + SpvId* existing = spv_search_emitted(emitter, node); + if (existing) + return *existing; + + CFNode* where = emitter->scheduler ? schedule_instruction(emitter->scheduler, node) : NULL; + if (where) { + BBBuilder bb_builder = spv_find_basic_block_builder(emitter, where->node); + SpvId emitted = spv_emit_value_(emitter, bb_builder, node); + register_result(emitter, false, node, emitted); + return emitted; + } else { + SpvId emitted = spv_emit_value_(emitter, NULL, node); + register_result(emitter, true, node, emitted); + return emitted; + } +} From af5c8a16928de96ebee15013554ba0ff9acbf349 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 14:26:27 +0200 Subject: [PATCH 452/693] remove subgroup primops (except assume) and use spv ops directly --- include/shady/primops.json | 16 ------ src/backend/c/emit_c_value.c | 28 +++++----- src/backend/spirv/emit_spv_value.c | 75 ++++++++++++++------------- src/shady/internal/scheduler.slim | 39 ++++++++++---- src/shady/passes/bind.c | 2 +- src/shady/passes/infer.c | 7 --- src/shady/passes/lower_mask.c | 2 - src/shady/passes/lower_subgroup_ops.c | 27 +++++----- src/shady/type.c | 23 +------- 9 files changed, 99 insertions(+), 120 deletions(-) diff --git a/include/shady/primops.json b/include/shady/primops.json index 24141fcb4..8c8d071b6 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -189,26 +189,10 @@ "name": "offset_of", "class": "memory_layout" }, - { - "name": "subgroup_elect_first", - "class": "subgroup_intrinsic" - }, { "name": "subgroup_assume_uniform", "class": "subgroup_intrinsic" }, - { - "name": "subgroup_reduce_sum", - "class": "subgroup_intrinsic" - }, - { - "name": "subgroup_active_mask", - "class": "subgroup_intrinsic" - }, - { - "name": "subgroup_ballot", - "class": "subgroup_intrinsic" - }, { "name": "select" }, diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 1ed47ced4..70e5762e5 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -327,10 +327,6 @@ static const ISelTableEntry isel_table_ispc[PRIMOPS_COUNT] = { [sqrt_op] = { IsMono, OsCall, "sqrt" }, [exp_op] = { IsMono, OsCall, "exp" }, [pow_op] = { IsMono, OsCall, "pow" }, - - [subgroup_active_mask_op] = { IsMono, OsCall, "lanemask" }, - [subgroup_ballot_op] = { IsMono, OsCall, "packmask" }, - [subgroup_reduce_sum_op] = { IsMono, OsCall, "reduce_add" }, }; static bool emit_using_entry(CTerm* out, Emitter* emitter, Printer* p, const ISelTableEntry* entry, Nodes operands) { @@ -692,15 +688,6 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { } case default_join_point_op: case create_joint_point_op: error("lowered in lower_tailcalls.c"); - case subgroup_elect_first_op: { - switch (emitter->config.dialect) { - case CDialect_CUDA: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_elect_first()")); break; - case CDialect_ISPC: term = term_from_cvalue(format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); break; - case CDialect_C11: - case CDialect_GLSL: error("TODO") - } - break; - } case subgroup_assume_uniform_op: { if (emitter->config.dialect != CDialect_ISPC) { return emit_value(emitter, p, prim_op->operands.nodes[0]); @@ -731,6 +718,21 @@ static CTerm emit_ext_instruction(Emitter* emitter, Printer* p, ExtInstr instr) } break; } + case SpvOpGroupNonUniformElect: { + assert(instr.operands.count == 1); + const IntLiteral* scope = resolve_to_int_literal(first(instr.operands)); + assert(scope && scope->value == SpvScopeSubgroup); + switch (emitter->config.dialect) { + case CDialect_CUDA: return term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_elect_first()")); + case CDialect_ISPC: return term_from_cvalue(format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); + case CDialect_C11: + case CDialect_GLSL: error("TODO") + } + break; + } + // [subgroup_active_mask_op] = { IsMono, OsCall, "lanemask" }, + // [subgroup_ballot_op] = { IsMono, OsCall, "packmask" }, + // [subgroup_reduce_sum_op] = { IsMono, OsCall, "reduce_add" }, default: error("Unsupported core spir-v instruction: %d", instr.opcode); } } else { diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 42ff4009c..610c5eb4a 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -215,32 +215,7 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins const Type* src = get_unqualified_type(first(the_op.operands)->type); assert(dst->tag == PtrType_TAG && src->tag == PtrType_TAG); assert(src != dst); - return spvb_op(bb_builder, SpvOpBitcast, emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, first(the_op.operands)) }); - } - case subgroup_ballot_op: { - spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); - const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = uint32_type(emitter->arena) }); - SpvId scope_subgroup = spv_emit_value(emitter, int32_literal(emitter->arena, SpvScopeSubgroup)); - SpvId raw_result = spvb_group_ballot(bb_builder, emit_type(emitter, i32x4), spv_emit_value(emitter, first(args)), scope_subgroup); - // TODO: why are we doing this in SPIR-V and not the IR ? - SpvId low32 = spvb_extract(bb_builder, emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 0 }); - SpvId hi32 = spvb_extract(bb_builder, emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 1 }); - SpvId low64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &low32); - SpvId hi64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &hi32); - hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { hi64, spv_emit_value(emitter, int64_literal(emitter->arena, 32)) }); - SpvId final_result = spvb_op(bb_builder, SpvOpBitwiseOr, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { low64, hi64 }); - return final_result; - } - case subgroup_reduce_sum_op: { - spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformArithmetic); - SpvId scope_subgroup = spv_emit_value(emitter, int32_literal(emitter->arena, SpvScopeSubgroup)); - return spvb_group_non_uniform_iadd(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), spv_emit_value(emitter, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); - } - case subgroup_elect_first_op: { - spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniform); - SpvId result_t = emit_type(emitter, bool_type(emitter->arena)); - SpvId scope_subgroup = spv_emit_value(emitter, int32_literal(emitter->arena, SpvScopeSubgroup)); - return spvb_group_elect(bb_builder, result_t, scope_subgroup); + return spvb_op(bb_builder, SpvOpBitcast, emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, fn_builder, first(the_op.operands)) }); } case insert_op: case extract_dynamic_op: @@ -304,20 +279,48 @@ static SpvId emit_ext_instr(Emitter* emitter, BBBuilder bb_builder, ExtInstr ins if (strcmp("spirv.core", instr.set) == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { - SpvId scope_subgroup = spv_emit_value(emitter, int32_literal(emitter->arena, SpvScopeSubgroup)); - SpvId result; - + spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); + SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { - const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); - SpvId local_id = spvb_op(bb_builder, SpvOpLoad, emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, b) }); - result = spvb_group_shuffle(bb_builder, emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, first(instr.operands)), local_id); spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); - } else { - result = spvb_group_broadcast_first(bb_builder, emit_type(emitter, instr.result_t), spv_emit_value(emitter, first(instr.operands)), scope_subgroup); + const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); + SpvId local_id = spvb_op(bb_builder, SpvOpLoad, emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, fn_builder, b) }); + return spvb_group_shuffle(bb_builder, emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, fn_builder, first(instr.operands)), local_id); } - + break; + } + case SpvCapabilityGroupNonUniformBallot: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); - return result; + assert(instr.operands.count == 2); + // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); + // ad-hoc extension for my sanity + if (get_unqualified_type(instr.result_t) == get_actual_mask_type(emitter->arena)) { + const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = uint32_type(emitter->arena) }); + SpvId raw_result = spvb_group_ballot(bb_builder, emit_type(emitter, i32x4), spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), spv_emit_value(emitter, fn_builder, first(instr.operands))); + // TODO: why are we doing this in SPIR-V and not the IR ? + SpvId low32 = spvb_extract(bb_builder, emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 0 }); + SpvId hi32 = spvb_extract(bb_builder, emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 1 }); + SpvId low64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &low32); + SpvId hi64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &hi32); + hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { hi64, spv_emit_value(emitter, fn_builder, int64_literal(emitter->arena, 32)) }); + SpvId final_result = spvb_op(bb_builder, SpvOpBitwiseOr, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { low64, hi64 }); + return final_result; + } + break; + } + case SpvOpGroupNonUniformIAdd: { + spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformArithmetic); + break; + // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); + // return spvb_group_non_uniform_iadd(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), spv_emit_value(emitter, fn_builder, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); + } + case SpvOpGroupNonUniformElect: { + spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniform); + assert(instr.operands.count == 1); + break; + // SpvId result_t = emit_type(emitter, bool_type(emitter->arena)); + // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); + // return spvb_group_elect(bb_builder, result_t, scope_subgroup); } default: break; } diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index 213245d4a..4570cd2ac 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -9,6 +9,13 @@ u32 payload; }; +// const u32 SpvScopeSubgroup = 3; +// const u32 SpvGroupOperationReduce = 0; +// const u32 OpGroupNonUniformElect = 333; +// const u32 OpGroupNonUniformBroadcastFirst = 338; +// const u32 OpGroupNonUniformBallot = 339; +// const u32 OpGroupNonUniformIAdd = 349; + @Internal var logical private u32 actual_subgroup_size; @Internal var logical subgroup u32 scheduler_cursor = 0; @@ -21,6 +28,16 @@ @Internal @Builtin("SubgroupLocalInvocationId") var input u32 subgroup_local_id; +@Internal @Leaf +fn subgroup_active_mask uniform mask_t() { + return (ext_instr["spirv.core", 339, uniform mask_t](3, true)); +} + +@Internal @Leaf +fn subgroup_ballot uniform mask_t(varying bool b) { + return (ext_instr["spirv.core", 339, uniform mask_t](3, b)); +} + @Internal @Leaf fn builtin_init_scheduler() { val init_mask = subgroup_active_mask(); @@ -29,7 +46,7 @@ fn builtin_init_scheduler() { scheduler_vector#(subgroup_local_id) = tree_node1; active_branch = tree_node1; - actual_subgroup_size = subgroup_reduce_sum(u32 1); + actual_subgroup_size = (ext_instr["spirv.core", 349, varying u32](3, 0, u32 1)); } @Internal @Leaf @@ -44,7 +61,7 @@ fn builtin_entry_join_point uniform JoinPoint() { @Internal @Leaf fn builtin_create_control_point varying JoinPoint(uniform u32 join_destination, varying u32 payload) { val curr_mask = subgroup_active_mask(); - val depth = ext_instr["spirv.core", 338, uniform u32](scheduler_vector#(subgroup_local_id)#1); + val depth = ext_instr["spirv.core", 338, uniform u32](3, scheduler_vector#(subgroup_local_id)#1); val tree_node = composite TreeNode(curr_mask, depth); val jp = composite JoinPoint(tree_node, join_destination, payload); @@ -56,7 +73,7 @@ fn builtin_create_control_point varying JoinPoint(uniform u32 join_destination, @Internal @Leaf fn builtin_fork(varying u32 branch_destination) { - val first_branch = ext_instr["spirv.core", 338, uniform u32](branch_destination); + val first_branch = ext_instr["spirv.core", 338, uniform u32](3, branch_destination); // if there is disagreement on the destination, then increase the depth of every branch val uniform_branch = subgroup_active_mask() == subgroup_ballot(first_branch == branch_destination); @@ -68,7 +85,7 @@ fn builtin_fork(varying u32 branch_destination) { // Partition the set of branch destinations and adapt the masks in turn loop() { - val elected = ext_instr["spirv.core", 338, uniform u32](branch_destination); + val elected = ext_instr["spirv.core", 338, uniform u32](3, branch_destination); resume_at#(subgroup_local_id) = elected; scheduler_vector#(subgroup_local_id)#0 = subgroup_ballot(elected == branch_destination); if (elected == branch_destination) { @@ -78,9 +95,9 @@ fn builtin_fork(varying u32 branch_destination) { // We must pick one branch as our 'favourite child' to schedule for immediate execution // we could do fancy intrinsics, but for now we'll just pick the first one - if (subgroup_elect_first()) { - next_fn = ext_instr["spirv.core", 338, uniform u32](branch_destination); - active_branch = ext_instr["spirv.core", 338, uniform TreeNode](scheduler_vector#(subgroup_local_id)); + if (ext_instr["spirv.core", 333, varying bool](3)) { + next_fn = ext_instr["spirv.core", 338, uniform u32](3, branch_destination); + active_branch = ext_instr["spirv.core", 338, uniform TreeNode](3, scheduler_vector#(subgroup_local_id)); // tag those variables as not in use# // resume_at#(subgroup_local_id) = -1; @@ -95,7 +112,7 @@ fn builtin_yield(uniform u32 resume_target) { // resume_with#(subgroup_local_id) = subgroup_active_mask(); // only one thread runs that part - if (subgroup_elect_first()) { + if (ext_instr["spirv.core", 333, varying bool](3)) { // bump the cursor // TODO bump it in a smarter way scheduler_cursor = (scheduler_cursor + u32 1) % actual_subgroup_size; @@ -109,7 +126,7 @@ fn builtin_join(varying u32 join_at, varying TreeNode token) { scheduler_vector#(subgroup_local_id) = token; // only one thread runs that part - if (subgroup_elect_first()) { + if (ext_instr["spirv.core", 333, varying bool](3)) { builtin_find_schedulable_leaf(); } } @@ -155,8 +172,8 @@ fn builtin_find_schedulable_leaf() { continue(i + u32 1); } - next_fn = ext_instr["spirv.core", 338, uniform u32](resume_at#reduced); - active_branch = ext_instr["spirv.core", 338, uniform TreeNode](scheduler_vector#reduced); + next_fn = ext_instr["spirv.core", 338, uniform u32](3, resume_at#reduced); + active_branch = ext_instr["spirv.core", 338, uniform TreeNode](3, scheduler_vector#reduced); return (); } diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index b5e69795e..817117fee 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -285,7 +285,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { case SlimOpSubscript: { return mem_and_value(a, (MemAndValue) { .value = prim_op(a, (PrimOp) { - .op = extract_op, + .op = extract_dynamic_op, .operands = mk_nodes(a, rewrite_node(r, payload.operands.nodes[0]), rewrite_node(r, payload.operands.nodes[1])) }), .mem = rewrite_node(r, payload.mem) } diff --git a/src/shady/passes/infer.c b/src/shady/passes/infer.c index 1917cc9aa..034aaf929 100644 --- a/src/shady/passes/infer.c +++ b/src/shady/passes/infer.c @@ -371,13 +371,6 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe goto rebuild; } case empty_mask_op: - case subgroup_active_mask_op: - case subgroup_elect_first_op: - input_types = nodes(a, 0, NULL); - break; - case subgroup_ballot_op: - input_types = singleton(qualified_type_helper(bool_type(a), false)); - break; case mask_is_thread_active_op: { input_types = mk_nodes(a, qualified_type_helper(mask_type(a), false), qualified_type_helper(uint32_type(a), false)); break; diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 8de917539..6b8704696 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -26,8 +26,6 @@ static const Node* process(Context* ctx, const Node* node) { Nodes old_nodes = node->payload.prim_op.operands; switch(op) { case empty_mask_op: return ctx->zero; - case subgroup_active_mask_op: // this is just ballot(true) - return prim_op(a, (PrimOp) { .op = subgroup_ballot_op, .type_arguments = empty(a), .operands = singleton(true_lit(ctx->rewriter.dst_arena)) }); // extract the relevant bit case mask_is_thread_active_op: { BodyBuilder* bb = begin_block_pure(a); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index c63c83189..0a3dd6a20 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -42,9 +42,9 @@ static bool is_supported_natively(Context* ctx, const Type* element_type) { return false; } -static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* src); +static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* scope, const Node* src); -static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* t, const Node* param) { +static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, const Node* t, const Node* param) { IrArena* a = ctx->rewriter.dst_arena; const Type* original_t = t; t = get_maybe_nominal_type_body(t); @@ -56,7 +56,7 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* t, const LARRAY(const Node*, elements, element_types.count); for (size_t i = 0; i < element_types.count; i++) { const Node* e = gen_extract(bb, param, singleton(uint32_literal(a, i))); - elements[i] = build_subgroup_first(ctx, bb, e); + elements[i] = build_subgroup_first(ctx, bb, scope, e); } return composite_helper(a, original_t, nodes(a, element_types.count, elements)); } @@ -65,8 +65,8 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* t, const const Node* hi = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, param, int32_literal(a, 32))); hi = convert_int_zero_extend(bb, int32_type(a), hi); const Node* lo = convert_int_zero_extend(bb, int32_type(a), param); - hi = build_subgroup_first(ctx, bb, hi); - lo = build_subgroup_first(ctx, bb, lo); + hi = build_subgroup_first(ctx, bb, scope, hi); + lo = build_subgroup_first(ctx, bb, scope, lo); const Node* it = int_type(a, (Int) { .width = IntTy64, .is_signed = t->payload.int_type.is_signed }); hi = convert_int_zero_extend(bb, it, hi); lo = convert_int_zero_extend(bb, it, lo); @@ -77,17 +77,17 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* t, const } case Type_PtrType_TAG: { param = gen_reinterpret_cast(bb, uint64_type(a), param); - return gen_reinterpret_cast(bb, t, generate(ctx, bb, uint64_type(a), param)); + return gen_reinterpret_cast(bb, t, generate(ctx, bb, scope, uint64_type(a), param)); } default: break; } return NULL; } -static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* t) { +static void build_fn_body(Context* ctx, Node* fn, const Node* scope, const Node* param, const Type* t) { IrArena* a = ctx->rewriter.dst_arena; BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fn)); - const Node* result = generate(ctx, bb, t, param); + const Node* result = generate(ctx, bb, scope, t, param); if (result) { set_abstraction_body(fn, finish_body(bb, fn_ret(a, (Return) { .args = singleton(result), @@ -102,12 +102,15 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* param, const Type* error_die(); } -static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* src) { +static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* scope, const Node* src) { IrArena* a = ctx->rewriter.dst_arena; Module* m = ctx->rewriter.dst_module; const Node* t = get_unqualified_type(src->type); if (is_supported_natively(ctx, t)) - return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, qualified_type_helper(t, true), singleton(src)); + return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, qualified_type_helper(t, true), mk_nodes(a, scope, src)); + + if (resolve_to_int_literal(scope)->value != SpvScopeSubgroup) + error("TODO") Node* fn = NULL; Node** found = find_value_dict(const Node*, Node*, ctx->fns, t); @@ -118,7 +121,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod fn = function(m, singleton(src_param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), singleton(annotation(a, (Annotation) { .name = "Generated"})), singleton(qualified_type_helper(t, true))); insert_dict(const Node*, Node*, ctx->fns, t, fn); - build_fn_body(ctx, fn, src_param, t); + build_fn_body(ctx, fn, scope, src_param, t); } return first(gen_call(bb, fn_addr_helper(a, fn), singleton(src))); @@ -137,7 +140,7 @@ static const Node* process(Context* ctx, const Node* node) { if (strcmp(payload.set, "spirv.core") == 0 && payload.opcode == SpvOpGroupNonUniformBroadcastFirst) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, singleton( - build_subgroup_first(ctx, bb, rewrite_node(r, first(payload.operands))))); + build_subgroup_first(ctx, bb, rewrite_node(r, payload.operands.nodes[0]), rewrite_node(r, payload.operands.nodes[1])))); } } default: break; diff --git a/src/shady/type.c b/src/shady/type.c index 713d7d1fe..5cef7b5c0 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -845,28 +845,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { }); } // Subgroup ops - case subgroup_active_mask_op: { - assert(prim_op.type_arguments.count == 0 && prim_op.operands.count == 0); - return qualified_type_helper(get_actual_mask_type(arena), true); - } - case subgroup_ballot_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 1); - return qualified_type(arena, (QualifiedType) { - .is_uniform = true, - .type = get_actual_mask_type(arena) - }); - } - case subgroup_elect_first_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 0); - return qualified_type(arena, (QualifiedType) { - .is_uniform = false, - .type = bool_type(arena) - }); - } - case subgroup_assume_uniform_op: - case subgroup_reduce_sum_op: { + case subgroup_assume_uniform_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); const Type* operand_type = get_unqualified_type(prim_op.operands.nodes[0]->type); From da884399c747b384114a474e4e08d3042faff473 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 14:26:46 +0200 Subject: [PATCH 453/693] spv: refactor to put all the fn-related data in a struct --- src/backend/spirv/emit_spv.c | 77 +++++++++--------- src/backend/spirv/emit_spv.h | 26 +++--- src/backend/spirv/emit_spv_control_flow.c | 96 +++++++++++------------ src/backend/spirv/emit_spv_type.c | 10 +-- src/backend/spirv/emit_spv_value.c | 79 ++++++++++--------- src/shady/analysis/cfg.h | 4 +- src/shady/body_builder.c | 2 +- 7 files changed, 151 insertions(+), 143 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 410553b25..9614585ff 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -21,31 +21,39 @@ extern SpvBuiltIn spv_builtins[]; +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + +KeyHash hash_string(const char** string); +bool compare_string(const char** a, const char** b); + #pragma GCC diagnostic error "-Wswitch" -void register_result(Emitter* emitter, bool global, const Node* node, SpvId id) { +void register_result(Emitter* emitter, FnBuilder* fn_builder, const Node* node, SpvId id) { if (is_value(node)) { String name = get_value_name_unsafe(node); if (name) spvb_name(emitter->file_builder, id, name); } - struct Dict* map = global ? emitter->global_node_ids : emitter->current_fn_node_ids; + struct Dict* map = fn_builder ? fn_builder->emitted : emitter->global_node_ids; insert_dict_and_get_result(struct Node*, SpvId, map, node, id); } -SpvId* spv_search_emitted(Emitter* emitter, const Node* node) { - SpvId* found = find_value_dict(const Node*, SpvId, emitter->current_fn_node_ids, node); +SpvId* spv_search_emitted(Emitter* emitter, FnBuilder* fn_builder, const Node* node) { + SpvId* found = NULL; + if (fn_builder) + found = find_value_dict(const Node*, SpvId, fn_builder->emitted, node); if (!found) found = find_value_dict(const Node*, SpvId, emitter->global_node_ids, node); return found; } -SpvId spv_find_reserved_id(Emitter* emitter, const Node* node) { - SpvId* found = spv_search_emitted(emitter, node); +SpvId spv_find_reserved_id(Emitter* emitter, FnBuilder* fn_builder, const Node* node) { + SpvId* found = spv_search_emitted(emitter, fn_builder, node); return *found; } -static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const CFG* cfg, const CFNode* cf_node) { +static void emit_basic_block(Emitter* emitter, FnBuilder* fn_builder, const CFG* cfg, const CFNode* cf_node) { const Node* bb_node = cf_node->node; assert(is_basic_block(bb_node) || cf_node == cfg->entry); @@ -54,7 +62,7 @@ static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const CFG* // Find the preassigned ID to this BBBuilder bb_builder = spv_find_basic_block_builder(emitter, bb_node); SpvId bb_id = get_block_builder_id(bb_builder); - spvb_add_bb(fn_builder, bb_builder); + spvb_add_bb(fn_builder->base, bb_builder); String name = get_abstraction_name_unsafe(bb_node); if (name) @@ -66,18 +74,20 @@ static void emit_basic_block(Emitter* emitter, FnBuilder fn_builder, const CFG* static void emit_function(Emitter* emitter, const Node* node) { assert(node->tag == Function_TAG); - emitter->cfg = build_fn_cfg(node); - emitter->scheduler = new_scheduler(emitter->cfg); - const Type* fn_type = node->type; - SpvId fn_id = spv_find_reserved_id(emitter, node); - FnBuilder fn_builder = spvb_begin_fn(emitter->file_builder, fn_id, emit_type(emitter, fn_type), nodes_to_codom(emitter, node->payload.fun.return_types)); + SpvId fn_id = spv_find_reserved_id(emitter, NULL, node); + FnBuilder fn_builder = { + .base = spvb_begin_fn(emitter->file_builder, fn_id, emit_type(emitter, fn_type), nodes_to_codom(emitter, node->payload.fun.return_types)), + .emitted = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), + .cfg = build_fn_cfg(node), + }; + fn_builder.scheduler = new_scheduler(fn_builder.cfg); Nodes params = node->payload.fun.params; for (size_t i = 0; i < params.count; i++) { const Node* param = params.nodes[i]; const Type* param_type = param->payload.param.type; - SpvId param_id = spvb_parameter(fn_builder, emit_type(emitter, param_type)); + SpvId param_id = spvb_parameter(fn_builder.base, emit_type(emitter, param_type)); register_result(emitter, false, param, param_id); deconstruct_qualified_type(¶m_type); if (param_type->tag == PtrType_TAG && param_type->payload.ptr_type.address_space == AsGlobal) { @@ -94,7 +104,7 @@ static void emit_function(Emitter* emitter, const Node* node) { const Node* bb = cfnode->node; assert(is_basic_block(bb) || bb == node); SpvId bb_id = spvb_fresh_id(emitter->file_builder); - BBBuilder basic_block_builder = spvb_begin_bb(fn_builder, bb_id); + BBBuilder basic_block_builder = spvb_begin_bb(fn_builder.base, bb_id); insert_dict(const Node*, BBBuilder, emitter->bb_builders, bb, basic_block_builder); // if (is_cfnode_structural_target(cfnode)) // continue; @@ -104,7 +114,9 @@ static void emit_function(Emitter* emitter, const Node* node) { Nodes bb_params = bb->payload.basic_block.params; for (size_t j = 0; j < bb_params.count; j++) { const Node* bb_param = bb_params.nodes[j]; - spvb_add_phi(basic_block_builder, emit_type(emitter, bb_param->type), spvb_fresh_id(emitter->file_builder)); + SpvId phi_id = spvb_fresh_id(emitter->file_builder); + spvb_add_phi(basic_block_builder, emit_type(emitter, bb_param->type), phi_id); + register_result(emitter, false, bb_param, phi_id); } // also make sure to register the label for basic blocks register_result(emitter, false, bb, bb_id); @@ -117,25 +129,24 @@ static void emit_function(Emitter* emitter, const Node* node) { assert(cfnode == cfg->entry); // if (is_cfnode_structural_target(cfnode)) // continue; - emit_basic_block(emitter, fn_builder, cfg, cfnode); + emit_basic_block(emitter, &fn_builder, cfg, cfnode); } destroy_cfg(cfg); - spvb_define_function(emitter->file_builder, fn_builder); + spvb_define_function(emitter->file_builder, fn_builder.base); } else { Growy* g = new_growy(); spvb_literal_name(g, get_abstraction_name(node)); growy_append_bytes(g, 4, (char*) &(uint32_t) { SpvLinkageTypeImport }); spvb_decorate(emitter->file_builder, fn_id, SpvDecorationLinkageAttributes, growy_size(g) / 4, (uint32_t*) growy_data(g)); destroy_growy(g); - spvb_declare_function(emitter->file_builder, fn_builder); + spvb_declare_function(emitter->file_builder, fn_builder.base); } - clear_dict(emitter->current_fn_node_ids); - destroy_scheduler(emitter->scheduler); - emitter->scheduler = NULL; - destroy_cfg(emitter->cfg); + destroy_scheduler(fn_builder.scheduler); + destroy_cfg(fn_builder.cfg); + destroy_dict(fn_builder.emitted); } SpvId emit_decl(Emitter* emitter, const Node* decl) { @@ -147,11 +158,11 @@ SpvId emit_decl(Emitter* emitter, const Node* decl) { case GlobalVariable_TAG: { const GlobalVariable* gvar = &decl->payload.global_variable; SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, true, decl, given_id); + register_result(emitter, NULL, decl, given_id); spvb_name(emitter->file_builder, given_id, gvar->name); SpvId init = 0; if (gvar->init) - init = spv_emit_value(emitter, gvar->init); + init = spv_emit_value(emitter, NULL, gvar->init); SpvStorageClass storage_class = emit_addr_space(emitter, gvar->address_space); spvb_global_variable(emitter->file_builder, given_id, emit_type(emitter, decl->type), storage_class, false, init); @@ -202,7 +213,7 @@ SpvId emit_decl(Emitter* emitter, const Node* decl) { return given_id; } case Function_TAG: { SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, true, decl, given_id); + register_result(emitter, NULL, decl, given_id); spvb_name(emitter->file_builder, given_id, decl->payload.fun.name); emit_function(emitter, decl); return given_id; @@ -215,7 +226,7 @@ SpvId emit_decl(Emitter* emitter, const Node* decl) { return 0; } case NominalType_TAG: { SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, true, decl, given_id); + register_result(emitter, NULL, decl, given_id); spvb_name(emitter->file_builder, given_id, decl->payload.nom_type.name); spv_emit_nominal_type_body(emitter, decl->payload.nom_type.body, given_id); return given_id; @@ -252,13 +263,13 @@ static void emit_entry_points(Emitter* emitter, Nodes declarations) { default: continue; } } - interface_arr[interface_size++] = spv_find_reserved_id(emitter, node); + interface_arr[interface_size++] = spv_find_reserved_id(emitter, NULL, node); } for (size_t i = 0; i < declarations.count; i++) { const Node* decl = declarations.nodes[i]; if (decl->tag != Function_TAG) continue; - SpvId fn_id = spv_find_reserved_id(emitter, decl); + SpvId fn_id = spv_find_reserved_id(emitter, NULL, decl); const Node* entry_point = lookup_annotation(decl, "EntryPoint"); if (entry_point) { @@ -305,12 +316,6 @@ SpvId get_extended_instruction_set(Emitter* emitter, const char* name) { return new; } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); - -KeyHash hash_string(const char** string); -bool compare_string(const char** a, const char** b); - static Module* run_backend_specific_passes(const CompilerConfig* config, Module* initial_mod) { IrArena* initial_arena = initial_mod->arena; Module** pmod = &initial_mod; @@ -339,7 +344,6 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, .configuration = config, .file_builder = file_builder, .global_node_ids = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), - .current_fn_node_ids = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), .bb_builders = new_dict(Node*, BBBuilder, (HashFn) hash_node, (CmpFn) compare_node), .num_entry_pts = 0, }; @@ -363,7 +367,6 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, // cleanup the emitter destroy_dict(emitter.global_node_ids); - destroy_dict(emitter.current_fn_node_ids); destroy_dict(emitter.bb_builders); destroy_dict(emitter.extended_instruction_sets); diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index 5251491c3..0f1a8457f 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -6,13 +6,20 @@ #include "spirv_builder.h" -typedef SpvbFileBuilder* FileBuilder; -typedef SpvbFnBuilder* FnBuilder; -typedef SpvbBasicBlockBuilder* BBBuilder; typedef struct CFG_ CFG; typedef struct Scheduler_ Scheduler; +typedef struct { + SpvbFnBuilder* base; + CFG* cfg; + Scheduler* scheduler; + struct Dict* emitted; +} FnBuilder; + +typedef SpvbFileBuilder* FileBuilder; +typedef SpvbBasicBlockBuilder* BBBuilder; + typedef struct Emitter_ { Module* module; IrArena* arena; @@ -21,10 +28,7 @@ typedef struct Emitter_ { SpvId void_t; struct Dict* global_node_ids; - struct Dict* current_fn_node_ids; struct Dict* bb_builders; - CFG* cfg; - Scheduler* scheduler; size_t num_entry_pts; @@ -38,12 +42,12 @@ typedef SpvbPhi** Phis; SpvId emit_decl(Emitter*, const Node*); SpvId emit_type(Emitter*, const Type*); -SpvId spv_emit_value(Emitter*, const Node*); -void spv_emit_terminator(Emitter*, FnBuilder, BBBuilder, const Node* abs, const Node* terminator); +SpvId spv_emit_value(Emitter*, FnBuilder*, const Node*); +void spv_emit_terminator(Emitter*, FnBuilder*, BBBuilder, const Node* abs, const Node* terminator); -void register_result(Emitter*, bool, const Node*, SpvId id); -SpvId* spv_search_emitted(Emitter* emitter, const Node* node); -SpvId spv_find_reserved_id(Emitter* emitter, const Node* node); +void register_result(Emitter*, FnBuilder*, const Node*, SpvId id); +SpvId* spv_search_emitted(Emitter* emitter, FnBuilder*, const Node* node); +SpvId spv_find_reserved_id(Emitter* emitter, FnBuilder*, const Node* node); BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb); diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 9247cd362..bcb6a2afe 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -16,7 +16,7 @@ BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb) { return *found; } -static void add_branch_phis(Emitter* emitter, BBBuilder bb_builder, const Node* dst, Nodes args) { +static void add_branch_phis(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* dst, Nodes args) { // because it's forbidden to jump back into the entry block of a function // (which is actually a Function in this IR, not a BasicBlock) // we assert that the destination must be an actual BasicBlock @@ -26,32 +26,32 @@ static void add_branch_phis(Emitter* emitter, BBBuilder bb_builder, const Node* assert(entries_count_list(phis) == args.count); for (size_t i = 0; i < args.count; i++) { SpvbPhi* phi = read_list(SpvbPhi*, phis)[i]; - spvb_add_phi_source(phi, get_block_builder_id(bb_builder), spv_emit_value(emitter, args.nodes[i])); + spvb_add_phi_source(phi, get_block_builder_id(bb_builder), spv_emit_value(emitter, fn_builder, args.nodes[i])); } } -static void add_branch_phis_from_jump(Emitter* emitter, BBBuilder bb_builder, Jump jump) { - return add_branch_phis(emitter, bb_builder, jump.target, jump.args); +static void add_branch_phis_from_jump(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Jump jump) { + return add_branch_phis(emitter, fn_builder, bb_builder, jump.target, jump.args); } -static void emit_if(Emitter* emitter, BBBuilder bb_builder, If if_instr) { - SpvId join_bb_id = spv_find_reserved_id(emitter, if_instr.tail); +static void emit_if(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, If if_instr) { + SpvId join_bb_id = spv_find_reserved_id(emitter, fn_builder, if_instr.tail); - SpvId true_id = spv_find_reserved_id(emitter, if_instr.if_true); - SpvId false_id = if_instr.if_false ? spv_find_reserved_id(emitter, if_instr.if_false) : join_bb_id; + SpvId true_id = spv_find_reserved_id(emitter, fn_builder, if_instr.if_true); + SpvId false_id = if_instr.if_false ? spv_find_reserved_id(emitter, fn_builder, if_instr.if_false) : join_bb_id; spvb_selection_merge(bb_builder, join_bb_id, 0); - SpvId condition = spv_emit_value(emitter, if_instr.condition); + SpvId condition = spv_emit_value(emitter, fn_builder, if_instr.condition); spvb_branch_conditional(bb_builder, condition, true_id, false_id); } -static void emit_match(Emitter* emitter, BBBuilder bb_builder, Match match) { - SpvId join_bb_id = spv_find_reserved_id(emitter, match.tail); +static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Match match) { + SpvId join_bb_id = spv_find_reserved_id(emitter, fn_builder, match.tail); assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); - SpvId inspectee = spv_emit_value(emitter, match.inspect); + SpvId inspectee = spv_emit_value(emitter, fn_builder, match.inspect); - SpvId default_id = spv_find_reserved_id(emitter, match.default_case); + SpvId default_id = spv_find_reserved_id(emitter, fn_builder, match.default_case); const Type* inspectee_t = match.inspect->type; deconstruct_qualified_type(&inspectee_t); @@ -67,34 +67,34 @@ static void emit_match(Emitter* emitter, BBBuilder bb_builder, Match match) { } else { literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) value; } - literals_and_cases[i * literal_case_entry_size + literal_width] = spv_find_reserved_id(emitter, match.cases.nodes[i]); + literals_and_cases[i * literal_case_entry_size + literal_width] = spv_find_reserved_id(emitter, fn_builder, match.cases.nodes[i]); } spvb_selection_merge(bb_builder, join_bb_id, 0); spvb_switch(bb_builder, inspectee, default_id, match.cases.count * literal_case_entry_size, literals_and_cases); } -static void emit_loop(Emitter* emitter, FnBuilder fn_builder, BBBuilder bb_builder, Loop loop_instr) { - SpvId body_id = spv_find_reserved_id(emitter, loop_instr.body); +static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Loop loop_instr) { + SpvId body_id = spv_find_reserved_id(emitter, fn_builder, loop_instr.body); SpvId continue_id = spvb_fresh_id(emitter->file_builder); - BBBuilder continue_builder = spvb_begin_bb(fn_builder, continue_id); + BBBuilder continue_builder = spvb_begin_bb(fn_builder->base, continue_id); spvb_name(emitter->file_builder, continue_id, "loop_continue"); - SpvId next_id = spv_find_reserved_id(emitter, loop_instr.tail); + SpvId next_id = spv_find_reserved_id(emitter, fn_builder, loop_instr.tail); // the header block receives the loop merge annotation spvb_loop_merge(bb_builder, next_id, continue_id, 0, 0, NULL); spvb_branch(bb_builder, body_id); - add_branch_phis(emitter, bb_builder, loop_instr.body, loop_instr.initial_args); + add_branch_phis(emitter, fn_builder, bb_builder, loop_instr.body, loop_instr.initial_args); // the continue block just jumps back into the header spvb_branch(continue_builder, body_id); - spvb_add_bb(fn_builder, continue_builder); + spvb_add_bb(fn_builder->base, continue_builder); } -static const Node* find_construct(Emitter* emitter, const Node* abs, Structured_constructTag tag) { - CFNode* n = cfg_lookup(emitter->cfg, abs); +static const Node* find_construct(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Structured_constructTag tag) { + CFNode* n = cfg_lookup(fn_builder->cfg, abs); while (n) { const Node* terminator = get_abstraction_body(n->node); assert(terminator); @@ -105,18 +105,18 @@ static const Node* find_construct(Emitter* emitter, const Node* abs, Structured_ return NULL; } -void spv_emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic_block_builder, const Node* abs, const Node* terminator) { +void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basic_block_builder, const Node* abs, const Node* terminator) { switch (is_terminator(terminator)) { case Return_TAG: { const Nodes* ret_values = &terminator->payload.fn_ret.args; switch (ret_values->count) { case 0: spvb_return_void(basic_block_builder); return; - case 1: spvb_return_value(basic_block_builder, spv_emit_value(emitter, ret_values->nodes[0])); return; + case 1: spvb_return_value(basic_block_builder, spv_emit_value(emitter, fn_builder, ret_values->nodes[0])); return; default: { LARRAY(SpvId, arr, ret_values->count); for (size_t i = 0; i < ret_values->count; i++) - arr[i] = spv_emit_value(emitter, ret_values->nodes[i]); - SpvId return_that = spvb_composite(basic_block_builder, fn_ret_type_id(fn_builder), ret_values->count, arr); + arr[i] = spv_emit_value(emitter, fn_builder, ret_values->nodes[i]); + SpvId return_that = spvb_composite(basic_block_builder, fn_ret_type_id(fn_builder->base), ret_values->count, arr); spvb_return_value(basic_block_builder, return_that); return; } @@ -127,58 +127,58 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder fn_builder, BBBuilder basic return; } case Jump_TAG: { - add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.jump); - spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, terminator->payload.jump.target)); + add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.jump); + spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, fn_builder, terminator->payload.jump.target)); return; } case Branch_TAG: { - SpvId condition = spv_emit_value(emitter, terminator->payload.branch.condition); - add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.branch.true_jump->payload.jump); - add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.branch.false_jump->payload.jump); - spvb_branch_conditional(basic_block_builder, condition, spv_find_reserved_id(emitter, terminator->payload.branch.true_jump->payload.jump.target), spv_find_reserved_id(emitter, terminator->payload.branch.false_jump->payload.jump.target)); + SpvId condition = spv_emit_value(emitter, fn_builder, terminator->payload.branch.condition); + add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.branch.true_jump->payload.jump); + add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.branch.false_jump->payload.jump); + spvb_branch_conditional(basic_block_builder, condition, spv_find_reserved_id(emitter, fn_builder, terminator->payload.branch.true_jump->payload.jump.target), spv_find_reserved_id(emitter, fn_builder, terminator->payload.branch.false_jump->payload.jump.target)); return; } case Switch_TAG: { - SpvId inspectee = spv_emit_value(emitter, terminator->payload.br_switch.switch_value); + SpvId inspectee = spv_emit_value(emitter, fn_builder, terminator->payload.br_switch.switch_value); LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); for (size_t i = 0; i < terminator->payload.br_switch.case_jumps.count; i++) { - add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.br_switch.case_jumps.nodes[i]->payload.jump); + add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.br_switch.case_jumps.nodes[i]->payload.jump); error("TODO finish") } - add_branch_phis_from_jump(emitter, basic_block_builder, terminator->payload.br_switch.default_jump->payload.jump); - SpvId default_tgt = spv_find_reserved_id(emitter, terminator->payload.br_switch.default_jump->payload.jump.target); + add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.br_switch.default_jump->payload.jump); + SpvId default_tgt = spv_find_reserved_id(emitter, fn_builder, terminator->payload.br_switch.default_jump->payload.jump.target); spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); return; } - case If_TAG: return emit_if(emitter, basic_block_builder, terminator->payload.if_instr); - case Match_TAG: return emit_match(emitter, basic_block_builder, terminator->payload.match_instr); + case If_TAG: return emit_if(emitter, fn_builder, basic_block_builder, terminator->payload.if_instr); + case Match_TAG: return emit_match(emitter, fn_builder, basic_block_builder, terminator->payload.match_instr); case Loop_TAG: return emit_loop(emitter, fn_builder, basic_block_builder, terminator->payload.loop_instr); case MergeSelection_TAG: { - const Node* construct = find_construct(emitter, abs, Structured_construct_If_TAG); + const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_If_TAG); if (!construct) - construct = find_construct(emitter, abs, Structured_construct_Match_TAG); + construct = find_construct(emitter, fn_builder, abs, Structured_construct_Match_TAG); const Node* tail = get_structured_construct_tail(construct); Nodes args = terminator->payload.merge_selection.args; for (size_t i = 0; i < args.count; i++) - add_branch_phis(emitter, basic_block_builder, tail, args); - spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, tail)); + add_branch_phis(emitter, fn_builder, basic_block_builder, tail, args); + spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, fn_builder, tail)); return; } case MergeContinue_TAG: { - const Node* construct = find_construct(emitter, abs, Structured_construct_Loop_TAG); + const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_Loop_TAG); Loop payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_continue.args; - add_branch_phis(emitter, basic_block_builder, payload.body, args); - spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, payload.body)); + add_branch_phis(emitter, fn_builder, basic_block_builder, payload.body, args); + spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, fn_builder, payload.body)); return; } case MergeBreak_TAG: { - const Node* construct = find_construct(emitter, abs, Structured_construct_Loop_TAG); + const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_Loop_TAG); Loop payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_break.args; - add_branch_phis(emitter, basic_block_builder, payload.tail, args); - spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, payload.tail)); + add_branch_phis(emitter, fn_builder, basic_block_builder, payload.tail, args); + spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, fn_builder, payload.tail)); return; } case Terminator_Control_TAG: diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 61b23f876..55fd3336c 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -99,7 +99,7 @@ SpvId emit_type(Emitter* emitter, const Type* type) { // we could hash the spirv types we generate to find duplicates, but it is easier to normalise our shady types and reuse their infra type = normalize_type(emitter, type); - SpvId* existing = spv_search_emitted(emitter, type); + SpvId* existing = spv_search_emitted(emitter, NULL, type); if (existing) return *existing; @@ -144,7 +144,7 @@ SpvId emit_type(Emitter* emitter, const Type* type) { const Type* pointed_type = type->payload.ptr_type.pointed_type; if (get_maybe_nominal_type_decl(pointed_type) && sc == SpvStorageClassPhysicalStorageBuffer) { new = spvb_forward_ptr_type(emitter->file_builder, sc); - register_result(emitter, true, type, new); + register_result(emitter, NULL, type, new); SpvId pointee = emit_type(emitter, pointed_type); spvb_ptr_type_define(emitter->file_builder, new, sc, pointee); return new; @@ -179,7 +179,7 @@ SpvId emit_type(Emitter* emitter, const Type* type) { case ArrType_TAG: { SpvId element_type = emit_type(emitter, type->payload.arr_type.element_type); if (type->payload.arr_type.size) { - new = spvb_array_type(emitter->file_builder, element_type, spv_emit_value(emitter, type->payload.arr_type.size)); + new = spvb_array_type(emitter->file_builder, element_type, spv_emit_value(emitter, NULL, type->payload.arr_type.size)); } else { new = spvb_runtime_array_type(emitter->file_builder, element_type); } @@ -199,7 +199,7 @@ SpvId emit_type(Emitter* emitter, const Type* type) { break; } new = spvb_fresh_id(emitter->file_builder); - register_result(emitter, true, type, new); + register_result(emitter, NULL, type, new); spv_emit_nominal_type_body(emitter, type, new); return new; } @@ -225,6 +225,6 @@ SpvId emit_type(Emitter* emitter, const Type* type) { } } - register_result(emitter, true, type, new); + register_result(emitter, NULL, type, new); return new; } diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 610c5eb4a..81bfbc8ce 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -173,7 +173,7 @@ static SpvOp get_opcode(SHADY_UNUSED Emitter* emitter, IselTableEntry entry, Nod } } -static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* instr) { +static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* instr) { PrimOp the_op = instr->payload.prim_op; Nodes args = the_op.operands; Nodes type_arguments = the_op.type_arguments; @@ -182,7 +182,7 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins if (entry.class != Custom) { LARRAY(SpvId, emitted_args, args.count); for (size_t i = 0; i < args.count; i++) - emitted_args[i] = spv_emit_value(emitter, args.nodes[i]); + emitted_args[i] = spv_emit_value(emitter, fn_builder, args.nodes[i]); switch (entry.class) { case Plain: { @@ -233,10 +233,10 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins if (dynamic) { LARRAY(SpvId, indices, indices_count); for (size_t i = 0; i < indices_count; i++) { - indices[i] = spv_emit_value(emitter, args.nodes[i + indices_start]); + indices[i] = spv_emit_value(emitter, fn_builder, args.nodes[i + indices_start]); } assert(indices_count == 1); - return spvb_vector_extract_dynamic(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, src_value), indices[0]); + return spvb_vector_extract_dynamic(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, src_value), indices[0]); } LARRAY(uint32_t, indices, indices_count); for (size_t i = 0; i < indices_count; i++) { @@ -245,14 +245,14 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins } if (insert) - return spvb_insert(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, args.nodes[1]), spv_emit_value(emitter, src_value), indices_count, indices); + return spvb_insert(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, args.nodes[1]), spv_emit_value(emitter, fn_builder, src_value), indices_count, indices); else - return spvb_extract(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, src_value), indices_count, indices); + return spvb_extract(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, src_value), indices_count, indices); } case shuffle_op: { const Type* result_t = instr->type; - SpvId a = spv_emit_value(emitter, args.nodes[0]); - SpvId b = spv_emit_value(emitter, args.nodes[1]); + SpvId a = spv_emit_value(emitter, fn_builder, args.nodes[0]); + SpvId b = spv_emit_value(emitter, fn_builder, args.nodes[1]); LARRAY(uint32_t, indices, args.count - 2); for (size_t i = 0; i < args.count - 2; i++) { int64_t indice = get_int_literal_value(*resolve_to_int_literal(args.nodes[i + 2]), true); @@ -264,9 +264,9 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins return spvb_vecshuffle(bb_builder, emit_type(emitter, result_t), a, b, args.count - 2, indices); } case select_op: { - SpvId cond = spv_emit_value(emitter, first(args)); - SpvId truv = spv_emit_value(emitter, args.nodes[1]); - SpvId flsv = spv_emit_value(emitter, args.nodes[2]); + SpvId cond = spv_emit_value(emitter, fn_builder, first(args)); + SpvId truv = spv_emit_value(emitter, fn_builder, args.nodes[1]); + SpvId flsv = spv_emit_value(emitter, fn_builder, args.nodes[2]); return spvb_select(bb_builder, emit_type(emitter, args.nodes[1]->type), cond, truv, flsv); } @@ -275,7 +275,7 @@ static SpvId emit_primop(Emitter* emitter, BBBuilder bb_builder, const Node* ins error("unreachable"); } -static SpvId emit_ext_instr(Emitter* emitter, BBBuilder bb_builder, ExtInstr instr) { +static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, ExtInstr instr) { if (strcmp("spirv.core", instr.set) == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { @@ -326,17 +326,17 @@ static SpvId emit_ext_instr(Emitter* emitter, BBBuilder bb_builder, ExtInstr ins } LARRAY(SpvId, ops, instr.operands.count); for (size_t i = 0; i < instr.operands.count; i++) - ops[i] = spv_emit_value(emitter, instr.operands.nodes[i]); + ops[i] = spv_emit_value(emitter, fn_builder, instr.operands.nodes[i]); return spvb_op(bb_builder, instr.opcode, emit_type(emitter, instr.result_t), instr.operands.count, ops); } LARRAY(SpvId, ops, instr.operands.count); for (size_t i = 0; i < instr.operands.count; i++) - ops[i] = spv_emit_value(emitter, instr.operands.nodes[i]); + ops[i] = spv_emit_value(emitter, fn_builder, instr.operands.nodes[i]); SpvId set_id = get_extended_instruction_set(emitter, instr.set); return spvb_ext_instruction(bb_builder, emit_type(emitter, instr.result_t), set_id, instr.opcode, instr.operands.count, ops); } -static SpvId emit_leaf_call(Emitter* emitter, BBBuilder bb_builder, Call call) { +static SpvId emit_leaf_call(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Call call) { const Node* fn = call.callee; assert(fn->tag == FnAddr_TAG); fn = fn->payload.fn_addr.fn; @@ -348,11 +348,11 @@ static SpvId emit_leaf_call(Emitter* emitter, BBBuilder bb_builder, Call call) { SpvId return_type = nodes_to_codom(emitter, return_types); LARRAY(SpvId, args, call.args.count); for (size_t i = 0; i < call.args.count; i++) - args[i] = spv_emit_value(emitter, call.args.nodes[i]); + args[i] = spv_emit_value(emitter, fn_builder, call.args.nodes[i]); return spvb_call(bb_builder, return_type, callee, call.args.count, args); } -static SpvId spv_emit_instruction(Emitter* emitter, BBBuilder bb_builder, const Node* instruction) { +static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* instruction) { assert(is_instruction(instruction)); switch (is_instruction(instruction)) { @@ -366,9 +366,9 @@ static SpvId spv_emit_instruction(Emitter* emitter, BBBuilder bb_builder, const case Instruction_FillBytes_TAG: case Instruction_BindIdentifiers_TAG: case Instruction_StackAlloc_TAG: error("Should be lowered elsewhere") - case Instruction_ExtInstr_TAG: return emit_ext_instr(emitter, bb_builder, instruction->payload.ext_instr); - case Instruction_Call_TAG: return emit_leaf_call(emitter, bb_builder, instruction->payload.call); - case PrimOp_TAG: return emit_primop(emitter, bb_builder, instruction); + case Instruction_ExtInstr_TAG: return emit_ext_instr(emitter, fn_builder, bb_builder, instruction->payload.ext_instr); + case Instruction_Call_TAG: return emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call); + case PrimOp_TAG: return emit_primop(emitter, fn_builder, bb_builder, instruction); case Comment_TAG: break; case Instruction_LocalAlloc_TAG: { assert(bb_builder); @@ -394,7 +394,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, BBBuilder bb_builder, const operands_count += 2; } - SpvId eptr = spv_emit_value(emitter, payload.ptr); + SpvId eptr = spv_emit_value(emitter, fn_builder, payload.ptr); return spvb_load(bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); } case Instruction_Store_TAG: { @@ -414,18 +414,18 @@ static SpvId spv_emit_instruction(Emitter* emitter, BBBuilder bb_builder, const operands_count += 2; } - SpvId eptr = spv_emit_value(emitter, payload.ptr); - SpvId eval = spv_emit_value(emitter, payload.value); + SpvId eptr = spv_emit_value(emitter, fn_builder, payload.ptr); + SpvId eval = spv_emit_value(emitter, fn_builder, payload.value); spvb_store(bb_builder, eval, eptr, operands_count, operands); return 0; } case Lea_TAG: { Lea payload = instruction->payload.lea; - SpvId base = spv_emit_value(emitter, payload.ptr); + SpvId base = spv_emit_value(emitter, fn_builder, payload.ptr); LARRAY(SpvId, indices, payload.indices.count); for (size_t i = 0; i < payload.indices.count; i++) - indices[i] = payload.indices.nodes[i] ? spv_emit_value(emitter, payload.indices.nodes[i]) : 0; + indices[i] = payload.indices.nodes[i] ? spv_emit_value(emitter, fn_builder, payload.indices.nodes[i]) : 0; const IntLiteral* known_offset = resolve_to_int_literal(payload.offset); if (known_offset && known_offset->value == 0) { @@ -433,24 +433,24 @@ static SpvId spv_emit_instruction(Emitter* emitter, BBBuilder bb_builder, const return spvb_access_chain(bb_builder, emit_type(emitter, target_type), base, payload.indices.count, indices); } else { const Type* target_type = instruction->type; - return spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, spv_emit_value(emitter, payload.offset), payload.indices.count, indices); + return spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, spv_emit_value(emitter, fn_builder, payload.offset), payload.indices.count, indices); } } case Instruction_DebugPrintf_TAG: { SpvId set_id = get_extended_instruction_set(emitter, "NonSemantic.DebugPrintf"); LARRAY(SpvId, args, instruction->payload.debug_printf.args.count + 1); - args[0] = spv_emit_value(emitter, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); + args[0] = spv_emit_value(emitter, fn_builder, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) - args[i + 1] = spv_emit_value(emitter, instruction->payload.debug_printf.args.nodes[i]); + args[i + 1] = spv_emit_value(emitter, fn_builder, instruction->payload.debug_printf.args.nodes[i]); spvb_ext_instruction(bb_builder, emit_type(emitter, instruction->type), set_id, (SpvOp) NonSemanticDebugPrintfDebugPrintf, instruction->payload.debug_printf.args.count + 1, args); return 0; } } } -static SpvId spv_emit_value_(Emitter* emitter, BBBuilder bb_builder, const Node* node) { +static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* node) { if (is_instruction(node)) - return spv_emit_instruction(emitter, bb_builder, node); + return spv_emit_instruction(emitter, fn_builder, bb_builder, node); SpvId new; switch (is_value(node)) { @@ -516,7 +516,7 @@ static SpvId spv_emit_value_(Emitter* emitter, BBBuilder bb_builder, const Node* Nodes contents = node->payload.composite.contents; LARRAY(SpvId, ids, contents.count); for (size_t i = 0; i < contents.count; i++) { - ids[i] = spv_emit_value(emitter, contents.nodes[i]); + ids[i] = spv_emit_value(emitter, fn_builder, contents.nodes[i]); } if (bb_builder) { new = spvb_composite(bb_builder, emit_type(emitter, node->type), contents.count, ids); @@ -539,7 +539,7 @@ static SpvId spv_emit_value_(Emitter* emitter, BBBuilder bb_builder, const Node* break; } case Constant_TAG: { - new = spv_emit_value(emitter, decl->payload.constant.value); + new = spv_emit_value(emitter, fn_builder, decl->payload.constant.value); break; } default: error("RefDecl must reference a constant or global"); @@ -554,20 +554,21 @@ static SpvId spv_emit_value_(Emitter* emitter, BBBuilder bb_builder, const Node* return new; } -SpvId spv_emit_value(Emitter* emitter, const Node* node) { - SpvId* existing = spv_search_emitted(emitter, node); +SpvId spv_emit_value(Emitter* emitter, FnBuilder* fn_builder, const Node* node) { + SpvId* existing = spv_search_emitted(emitter, fn_builder, node); if (existing) return *existing; - CFNode* where = emitter->scheduler ? schedule_instruction(emitter->scheduler, node) : NULL; + CFNode* where = fn_builder ? schedule_instruction(fn_builder->scheduler, node) : NULL; if (where) { BBBuilder bb_builder = spv_find_basic_block_builder(emitter, where->node); - SpvId emitted = spv_emit_value_(emitter, bb_builder, node); - register_result(emitter, false, node, emitted); + SpvId emitted = spv_emit_value_(emitter, fn_builder, bb_builder, node); + register_result(emitter, fn_builder, node, emitted); return emitted; } else { - SpvId emitted = spv_emit_value_(emitter, NULL, node); - register_result(emitter, true, node, emitted); + assert(!is_mem(node)); + SpvId emitted = spv_emit_value_(emitter, NULL, NULL, node); + register_result(emitter, NULL, node, emitted); return emitted; } } diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index 134adadc3..5e6a35ad8 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -86,13 +86,13 @@ CFG* build_cfg(const Node* fn, const Node* entry, LoopTree* lt, bool flipped); /** Construct the CFG starting in node. * Dominance will only be computed with respect to the nodes reachable by @p entry. */ -#define build_fn_cfg(node) build_cfg(node, node, NULL, false); +#define build_fn_cfg(node) build_cfg(node, node, NULL, false) /** Construct the CFG stating in Node. * Dominance will only be computed with respect to the nodes reachable by @p entry. * This CFG will contain post dominance information instead of regular dominance! */ -#define build_fn_cfg_flipped(node) build_cfg(node, node, NULL, true); +#define build_fn_cfg_flipped(node) build_cfg(node, node, NULL, true) CFNode* cfg_lookup(CFG* cfg, const Node* abs); void compute_rpo(CFG*); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 3b71a1f40..81ea614ab 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -198,7 +198,7 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { IrArena* arena = bb->arena; - assert(!bb->mem0 && !bb->stack); + assert(!bb->mem0 && entries_count_list(bb->stack) == 0); return maybe_tuple_helper(arena, values); } From b0f53131e72c1d6d860cec767b30d1434fe3c38d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 14:30:35 +0200 Subject: [PATCH 454/693] spv: get rid of leftover namespacing macros --- src/backend/spirv/emit_spv.c | 12 ++--- src/backend/spirv/emit_spv.h | 8 +--- src/backend/spirv/emit_spv_type.c | 26 +++++------ src/backend/spirv/emit_spv_value.c | 70 +++++++++++++++--------------- 4 files changed, 56 insertions(+), 60 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 9614585ff..f13282960 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -77,7 +77,7 @@ static void emit_function(Emitter* emitter, const Node* node) { const Type* fn_type = node->type; SpvId fn_id = spv_find_reserved_id(emitter, NULL, node); FnBuilder fn_builder = { - .base = spvb_begin_fn(emitter->file_builder, fn_id, emit_type(emitter, fn_type), nodes_to_codom(emitter, node->payload.fun.return_types)), + .base = spvb_begin_fn(emitter->file_builder, fn_id, spv_emit_type(emitter, fn_type), nodes_to_codom(emitter, node->payload.fun.return_types)), .emitted = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), .cfg = build_fn_cfg(node), }; @@ -87,7 +87,7 @@ static void emit_function(Emitter* emitter, const Node* node) { for (size_t i = 0; i < params.count; i++) { const Node* param = params.nodes[i]; const Type* param_type = param->payload.param.type; - SpvId param_id = spvb_parameter(fn_builder.base, emit_type(emitter, param_type)); + SpvId param_id = spvb_parameter(fn_builder.base, spv_emit_type(emitter, param_type)); register_result(emitter, false, param, param_id); deconstruct_qualified_type(¶m_type); if (param_type->tag == PtrType_TAG && param_type->payload.ptr_type.address_space == AsGlobal) { @@ -115,7 +115,7 @@ static void emit_function(Emitter* emitter, const Node* node) { for (size_t j = 0; j < bb_params.count; j++) { const Node* bb_param = bb_params.nodes[j]; SpvId phi_id = spvb_fresh_id(emitter->file_builder); - spvb_add_phi(basic_block_builder, emit_type(emitter, bb_param->type), phi_id); + spvb_add_phi(basic_block_builder, spv_emit_type(emitter, bb_param->type), phi_id); register_result(emitter, false, bb_param, phi_id); } // also make sure to register the label for basic blocks @@ -149,7 +149,7 @@ static void emit_function(Emitter* emitter, const Node* node) { destroy_dict(fn_builder.emitted); } -SpvId emit_decl(Emitter* emitter, const Node* decl) { +SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { SpvId* existing = find_value_dict(const Node*, SpvId, emitter->global_node_ids, decl); if (existing) return *existing; @@ -164,7 +164,7 @@ SpvId emit_decl(Emitter* emitter, const Node* decl) { if (gvar->init) init = spv_emit_value(emitter, NULL, gvar->init); SpvStorageClass storage_class = emit_addr_space(emitter, gvar->address_space); - spvb_global_variable(emitter->file_builder, given_id, emit_type(emitter, decl->type), storage_class, false, init); + spvb_global_variable(emitter->file_builder, given_id, spv_emit_type(emitter, decl->type), storage_class, false, init); Builtin b = BuiltinsCount; for (size_t i = 0; i < gvar->annotations.count; i++) { @@ -302,7 +302,7 @@ static void emit_entry_points(Emitter* emitter, Nodes declarations) { static void emit_decls(Emitter* emitter, Nodes declarations) { for (size_t i = 0; i < declarations.count; i++) { const Node* decl = declarations.nodes[i]; - emit_decl(emitter, decl); + spv_emit_decl(emitter, decl); } } diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index 0f1a8457f..00ab75e73 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -6,7 +6,6 @@ #include "spirv_builder.h" - typedef struct CFG_ CFG; typedef struct Scheduler_ Scheduler; @@ -37,11 +36,8 @@ typedef struct Emitter_ { typedef SpvbPhi** Phis; -#define emit_decl spv_emit_decl -#define emit_type spv_emit_type - -SpvId emit_decl(Emitter*, const Node*); -SpvId emit_type(Emitter*, const Type*); +SpvId spv_emit_decl(Emitter*, const Node*); +SpvId spv_emit_type(Emitter*, const Type*); SpvId spv_emit_value(Emitter*, FnBuilder*, const Node*); void spv_emit_terminator(Emitter*, FnBuilder*, BBBuilder, const Node* abs, const Node* terminator); diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 55fd3336c..7bda84adf 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -64,10 +64,10 @@ const Type* normalize_type(Emitter* emitter, const Type* type) { SpvId nodes_to_codom(Emitter* emitter, Nodes return_types) { switch (return_types.count) { case 0: return emitter->void_t; - case 1: return emit_type(emitter, return_types.nodes[0]); + case 1: return spv_emit_type(emitter, return_types.nodes[0]); default: { const Type* codom_ret_type = record_type(emitter->arena, (RecordType) { .members = return_types, .special = 0 }); - return emit_type(emitter, codom_ret_type); + return spv_emit_type(emitter, codom_ret_type); } } } @@ -78,7 +78,7 @@ void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id) { Nodes member_types = type->payload.record_type.members; LARRAY(SpvId, members, member_types.count); for (size_t i = 0; i < member_types.count; i++) - members[i] = emit_type(emitter, member_types.nodes[i]); + members[i] = spv_emit_type(emitter, member_types.nodes[i]); spvb_struct_type(emitter->file_builder, id, member_types.count, members); if (type->payload.record_type.special == DecorateBlock) { spvb_decorate(emitter->file_builder, id, SpvDecorationBlock, 0, NULL); @@ -94,7 +94,7 @@ void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id) { } } -SpvId emit_type(Emitter* emitter, const Type* type) { +SpvId spv_emit_type(Emitter* emitter, const Type* type) { // Some types in shady lower to the same spir-v type, but spir-v is unhappy with having duplicates of the same types // we could hash the spirv types we generate to find duplicates, but it is easier to normalise our shady types and reuse their infra type = normalize_type(emitter, type); @@ -145,12 +145,12 @@ SpvId emit_type(Emitter* emitter, const Type* type) { if (get_maybe_nominal_type_decl(pointed_type) && sc == SpvStorageClassPhysicalStorageBuffer) { new = spvb_forward_ptr_type(emitter->file_builder, sc); register_result(emitter, NULL, type, new); - SpvId pointee = emit_type(emitter, pointed_type); + SpvId pointee = spv_emit_type(emitter, pointed_type); spvb_ptr_type_define(emitter->file_builder, new, sc, pointee); return new; } - SpvId pointee = emit_type(emitter, pointed_type); + SpvId pointee = spv_emit_type(emitter, pointed_type); new = spvb_ptr_type(emitter->file_builder, sc, pointee); //if (is_physical_as(type->payload.ptr_type.address_space) && type->payload.ptr_type.pointed_type->tag == ArrType_TAG) { @@ -166,18 +166,18 @@ SpvId emit_type(Emitter* emitter, const Type* type) { const FnType* fnt = &type->payload.fn_type; LARRAY(SpvId, params, fnt->param_types.count); for (size_t i = 0; i < fnt->param_types.count; i++) - params[i] = emit_type(emitter, fnt->param_types.nodes[i]); + params[i] = spv_emit_type(emitter, fnt->param_types.nodes[i]); new = spvb_fn_type(emitter->file_builder, fnt->param_types.count, params, nodes_to_codom(emitter, fnt->return_types)); break; } case QualifiedType_TAG: { // SPIR-V does not care about our type qualifiers. - new = emit_type(emitter, type->payload.qualified_type.type); + new = spv_emit_type(emitter, type->payload.qualified_type.type); break; } case ArrType_TAG: { - SpvId element_type = emit_type(emitter, type->payload.arr_type.element_type); + SpvId element_type = spv_emit_type(emitter, type->payload.arr_type.element_type); if (type->payload.arr_type.size) { new = spvb_array_type(emitter->file_builder, element_type, spv_emit_value(emitter, NULL, type->payload.arr_type.size)); } else { @@ -189,7 +189,7 @@ SpvId emit_type(Emitter* emitter, const Type* type) { } case PackType_TAG: { assert(type->payload.pack_type.width >= 2); - SpvId element_type = emit_type(emitter, type->payload.pack_type.element_type); + SpvId element_type = spv_emit_type(emitter, type->payload.pack_type.element_type); new = spvb_vector_type(emitter->file_builder, element_type, type->payload.pack_type.width); break; } @@ -204,14 +204,14 @@ SpvId emit_type(Emitter* emitter, const Type* type) { return new; } case Type_TypeDeclRef_TAG: { - new = emit_decl(emitter, type->payload.type_decl_ref.decl); + new = spv_emit_decl(emitter, type->payload.type_decl_ref.decl); break; } - case Type_SampledImageType_TAG: new = spvb_sampled_image_type(emitter->file_builder, emit_type(emitter, type->payload.sampled_image_type.image_type)); break; + case Type_SampledImageType_TAG: new = spvb_sampled_image_type(emitter->file_builder, spv_emit_type(emitter, type->payload.sampled_image_type.image_type)); break; case Type_SamplerType_TAG: new = spvb_sampler_type(emitter->file_builder); break; case Type_ImageType_TAG: { ImageType p = type->payload.image_type; - new = spvb_image_type(emitter->file_builder, emit_type(emitter, p.sampled_type), p.dim, p.depth, p.arrayed, p.ms, p.sampled, p.imageformat); + new = spvb_image_type(emitter->file_builder, spv_emit_type(emitter, p.sampled_type), p.dim, p.depth, p.arrayed, p.ms, p.sampled, p.imageformat); break; } case Type_MaskType_TAG: diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 81bfbc8ce..931b9bd51 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -195,7 +195,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b if (opcode == SpvOpMax) goto custom; - SpvId result_t = instr->type == empty_multiple_return_type(emitter->arena) ? emit_type(emitter, instr->type) : emitter->void_t; + SpvId result_t = instr->type == empty_multiple_return_type(emitter->arena) ? spv_emit_type(emitter, instr->type) : emitter->void_t; if (entry.extended_set) { SpvId set_id = get_extended_instruction_set(emitter, entry.extended_set); return spvb_ext_instruction(bb_builder, result_t, set_id, opcode, args.count, emitted_args); @@ -215,7 +215,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b const Type* src = get_unqualified_type(first(the_op.operands)->type); assert(dst->tag == PtrType_TAG && src->tag == PtrType_TAG); assert(src != dst); - return spvb_op(bb_builder, SpvOpBitcast, emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, fn_builder, first(the_op.operands)) }); + return spvb_op(bb_builder, SpvOpBitcast, spv_emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, fn_builder, first(the_op.operands)) }); } case insert_op: case extract_dynamic_op: @@ -236,7 +236,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b indices[i] = spv_emit_value(emitter, fn_builder, args.nodes[i + indices_start]); } assert(indices_count == 1); - return spvb_vector_extract_dynamic(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, src_value), indices[0]); + return spvb_vector_extract_dynamic(bb_builder, spv_emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, src_value), indices[0]); } LARRAY(uint32_t, indices, indices_count); for (size_t i = 0; i < indices_count; i++) { @@ -245,9 +245,9 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b } if (insert) - return spvb_insert(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, args.nodes[1]), spv_emit_value(emitter, fn_builder, src_value), indices_count, indices); + return spvb_insert(bb_builder, spv_emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, args.nodes[1]), spv_emit_value(emitter, fn_builder, src_value), indices_count, indices); else - return spvb_extract(bb_builder, emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, src_value), indices_count, indices); + return spvb_extract(bb_builder, spv_emit_type(emitter, result_t), spv_emit_value(emitter, fn_builder, src_value), indices_count, indices); } case shuffle_op: { const Type* result_t = instr->type; @@ -261,14 +261,14 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b else indices[i] = indice; } - return spvb_vecshuffle(bb_builder, emit_type(emitter, result_t), a, b, args.count - 2, indices); + return spvb_vecshuffle(bb_builder, spv_emit_type(emitter, result_t), a, b, args.count - 2, indices); } case select_op: { SpvId cond = spv_emit_value(emitter, fn_builder, first(args)); SpvId truv = spv_emit_value(emitter, fn_builder, args.nodes[1]); SpvId flsv = spv_emit_value(emitter, fn_builder, args.nodes[2]); - return spvb_select(bb_builder, emit_type(emitter, args.nodes[1]->type), cond, truv, flsv); + return spvb_select(bb_builder, spv_emit_type(emitter, args.nodes[1]->type), cond, truv, flsv); } default: error("TODO: unhandled op"); } @@ -284,8 +284,8 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); - SpvId local_id = spvb_op(bb_builder, SpvOpLoad, emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, fn_builder, b) }); - return spvb_group_shuffle(bb_builder, emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, fn_builder, first(instr.operands)), local_id); + SpvId local_id = spvb_op(bb_builder, SpvOpLoad, spv_emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, fn_builder, b) }); + return spvb_group_shuffle(bb_builder, spv_emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, fn_builder, first(instr.operands)), local_id); } break; } @@ -296,14 +296,14 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b // ad-hoc extension for my sanity if (get_unqualified_type(instr.result_t) == get_actual_mask_type(emitter->arena)) { const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = uint32_type(emitter->arena) }); - SpvId raw_result = spvb_group_ballot(bb_builder, emit_type(emitter, i32x4), spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), spv_emit_value(emitter, fn_builder, first(instr.operands))); + SpvId raw_result = spvb_group_ballot(bb_builder, spv_emit_type(emitter, i32x4), spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), spv_emit_value(emitter, fn_builder, first(instr.operands))); // TODO: why are we doing this in SPIR-V and not the IR ? - SpvId low32 = spvb_extract(bb_builder, emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 0 }); - SpvId hi32 = spvb_extract(bb_builder, emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 1 }); - SpvId low64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &low32); - SpvId hi64 = spvb_op(bb_builder, SpvOpUConvert, emit_type(emitter, uint64_type(emitter->arena)), 1, &hi32); - hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { hi64, spv_emit_value(emitter, fn_builder, int64_literal(emitter->arena, 32)) }); - SpvId final_result = spvb_op(bb_builder, SpvOpBitwiseOr, emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { low64, hi64 }); + SpvId low32 = spvb_extract(bb_builder, spv_emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 0 }); + SpvId hi32 = spvb_extract(bb_builder, spv_emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 1 }); + SpvId low64 = spvb_op(bb_builder, SpvOpUConvert, spv_emit_type(emitter, uint64_type(emitter->arena)), 1, &low32); + SpvId hi64 = spvb_op(bb_builder, SpvOpUConvert, spv_emit_type(emitter, uint64_type(emitter->arena)), 1, &hi32); + hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, spv_emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { hi64, spv_emit_value(emitter, fn_builder, int64_literal(emitter->arena, 32)) }); + SpvId final_result = spvb_op(bb_builder, SpvOpBitwiseOr, spv_emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { low64, hi64 }); return final_result; } break; @@ -312,13 +312,13 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformArithmetic); break; // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); - // return spvb_group_non_uniform_iadd(bb_builder, emit_type(emitter, get_unqualified_type(first(args)->type)), spv_emit_value(emitter, fn_builder, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); + // return spvb_group_non_uniform_iadd(bb_builder, spv_emit_type(emitter, get_unqualified_type(first(args)->type)), spv_emit_value(emitter, fn_builder, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); } case SpvOpGroupNonUniformElect: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniform); assert(instr.operands.count == 1); break; - // SpvId result_t = emit_type(emitter, bool_type(emitter->arena)); + // SpvId result_t = spv_emit_type(emitter, bool_type(emitter->arena)); // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); // return spvb_group_elect(bb_builder, result_t, scope_subgroup); } @@ -327,20 +327,20 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b LARRAY(SpvId, ops, instr.operands.count); for (size_t i = 0; i < instr.operands.count; i++) ops[i] = spv_emit_value(emitter, fn_builder, instr.operands.nodes[i]); - return spvb_op(bb_builder, instr.opcode, emit_type(emitter, instr.result_t), instr.operands.count, ops); + return spvb_op(bb_builder, instr.opcode, spv_emit_type(emitter, instr.result_t), instr.operands.count, ops); } LARRAY(SpvId, ops, instr.operands.count); for (size_t i = 0; i < instr.operands.count; i++) ops[i] = spv_emit_value(emitter, fn_builder, instr.operands.nodes[i]); SpvId set_id = get_extended_instruction_set(emitter, instr.set); - return spvb_ext_instruction(bb_builder, emit_type(emitter, instr.result_t), set_id, instr.opcode, instr.operands.count, ops); + return spvb_ext_instruction(bb_builder, spv_emit_type(emitter, instr.result_t), set_id, instr.opcode, instr.operands.count, ops); } static SpvId emit_leaf_call(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Call call) { const Node* fn = call.callee; assert(fn->tag == FnAddr_TAG); fn = fn->payload.fn_addr.fn; - SpvId callee = emit_decl(emitter, fn); + SpvId callee = spv_emit_decl(emitter, fn); const Type* callee_type = fn->type; assert(callee_type->tag == FnType_TAG); @@ -372,7 +372,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui case Comment_TAG: break; case Instruction_LocalAlloc_TAG: { assert(bb_builder); - return spvb_local_variable(spvb_get_fn_builder(bb_builder), emit_type(emitter, ptr_type(emitter->arena, (PtrType) { + return spvb_local_variable(spvb_get_fn_builder(bb_builder), spv_emit_type(emitter, ptr_type(emitter->arena, (PtrType) { .address_space = AsFunction, .pointed_type = instruction->payload.local_alloc.type })), SpvStorageClassFunction); @@ -395,7 +395,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui } SpvId eptr = spv_emit_value(emitter, fn_builder, payload.ptr); - return spvb_load(bb_builder, emit_type(emitter, elem_type), eptr, operands_count, operands); + return spvb_load(bb_builder, spv_emit_type(emitter, elem_type), eptr, operands_count, operands); } case Instruction_Store_TAG: { Store payload = instruction->payload.store; @@ -430,10 +430,10 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui const IntLiteral* known_offset = resolve_to_int_literal(payload.offset); if (known_offset && known_offset->value == 0) { const Type* target_type = instruction->type; - return spvb_access_chain(bb_builder, emit_type(emitter, target_type), base, payload.indices.count, indices); + return spvb_access_chain(bb_builder, spv_emit_type(emitter, target_type), base, payload.indices.count, indices); } else { const Type* target_type = instruction->type; - return spvb_ptr_access_chain(bb_builder, emit_type(emitter, target_type), base, spv_emit_value(emitter, fn_builder, payload.offset), payload.indices.count, indices); + return spvb_ptr_access_chain(bb_builder, spv_emit_type(emitter, target_type), base, spv_emit_value(emitter, fn_builder, payload.offset), payload.indices.count, indices); } } case Instruction_DebugPrintf_TAG: { @@ -442,7 +442,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui args[0] = spv_emit_value(emitter, fn_builder, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) args[i + 1] = spv_emit_value(emitter, fn_builder, instruction->payload.debug_printf.args.nodes[i]); - spvb_ext_instruction(bb_builder, emit_type(emitter, instruction->type), set_id, (SpvOp) NonSemanticDebugPrintfDebugPrintf, instruction->payload.debug_printf.args.count + 1, args); + spvb_ext_instruction(bb_builder, spv_emit_type(emitter, instruction->type), set_id, (SpvOp) NonSemanticDebugPrintfDebugPrintf, instruction->payload.debug_printf.args.count + 1, args); return 0; } } @@ -461,7 +461,7 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder case Value_FnAddr_TAG: error("Should be lowered away earlier!"); case IntLiteral_TAG: { new = spvb_fresh_id(emitter->file_builder); - SpvId ty = emit_type(emitter, node->type); + SpvId ty = spv_emit_type(emitter, node->type); // 64-bit constants take two spirv words, anything else fits in one if (node->payload.int_literal.width == IntTy64) { uint32_t arr[] = { node->payload.int_literal.value & 0xFFFFFFFF, node->payload.int_literal.value >> 32 }; @@ -474,7 +474,7 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder } case FloatLiteral_TAG: { new = spvb_fresh_id(emitter->file_builder); - SpvId ty = emit_type(emitter, node->type); + SpvId ty = spv_emit_type(emitter, node->type); switch (node->payload.float_literal.width) { case FloatTy16: { uint32_t arr[] = { node->payload.float_literal.value & 0xFFFF }; @@ -496,12 +496,12 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder } case True_TAG: { new = spvb_fresh_id(emitter->file_builder); - spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), true); + spvb_bool_constant(emitter->file_builder, new, spv_emit_type(emitter, bool_type(emitter->arena)), true); break; } case False_TAG: { new = spvb_fresh_id(emitter->file_builder); - spvb_bool_constant(emitter->file_builder, new, emit_type(emitter, bool_type(emitter->arena)), false); + spvb_bool_constant(emitter->file_builder, new, spv_emit_type(emitter, bool_type(emitter->arena)), false); break; } case Value_StringLiteral_TAG: { @@ -509,7 +509,7 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder break; } case Value_NullPtr_TAG: { - new = spvb_constant_null(emitter->file_builder, emit_type(emitter, node->payload.null_ptr.ptr_type)); + new = spvb_constant_null(emitter->file_builder, spv_emit_type(emitter, node->payload.null_ptr.ptr_type)); break; } case Composite_TAG: { @@ -519,15 +519,15 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder ids[i] = spv_emit_value(emitter, fn_builder, contents.nodes[i]); } if (bb_builder) { - new = spvb_composite(bb_builder, emit_type(emitter, node->type), contents.count, ids); + new = spvb_composite(bb_builder, spv_emit_type(emitter, node->type), contents.count, ids); return new; } else { - new = spvb_constant_composite(emitter->file_builder, emit_type(emitter, node->type), contents.count, ids); + new = spvb_constant_composite(emitter->file_builder, spv_emit_type(emitter, node->type), contents.count, ids); break; } } case Value_Undef_TAG: { - new = spvb_undef(emitter->file_builder, emit_type(emitter, node->payload.undef.type)); + new = spvb_undef(emitter->file_builder, spv_emit_type(emitter, node->payload.undef.type)); break; } case Value_Fill_TAG: error("lower me") @@ -535,7 +535,7 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder const Node* decl = node->payload.ref_decl.decl; switch (decl->tag) { case GlobalVariable_TAG: { - new = emit_decl(emitter, decl); + new = spv_emit_decl(emitter, decl); break; } case Constant_TAG: { From 9a711239e24e52278d5313df8ee98359e68e44bc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 14:31:58 +0200 Subject: [PATCH 455/693] spv: namespace everything --- src/backend/spirv/emit_spv.c | 28 +++++++++++------------ src/backend/spirv/emit_spv.h | 12 +++++----- src/backend/spirv/emit_spv_control_flow.c | 28 +++++++++++------------ src/backend/spirv/emit_spv_type.c | 18 +++++++-------- src/backend/spirv/emit_spv_value.c | 12 +++++----- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index f13282960..14df22a5f 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -29,7 +29,7 @@ bool compare_string(const char** a, const char** b); #pragma GCC diagnostic error "-Wswitch" -void register_result(Emitter* emitter, FnBuilder* fn_builder, const Node* node, SpvId id) { +void spv_register_emitted(Emitter* emitter, FnBuilder* fn_builder, const Node* node, SpvId id) { if (is_value(node)) { String name = get_value_name_unsafe(node); if (name) @@ -48,7 +48,7 @@ SpvId* spv_search_emitted(Emitter* emitter, FnBuilder* fn_builder, const Node* n return found; } -SpvId spv_find_reserved_id(Emitter* emitter, FnBuilder* fn_builder, const Node* node) { +SpvId spv_find_emitted(Emitter* emitter, FnBuilder* fn_builder, const Node* node) { SpvId* found = spv_search_emitted(emitter, fn_builder, node); return *found; } @@ -75,9 +75,9 @@ static void emit_function(Emitter* emitter, const Node* node) { assert(node->tag == Function_TAG); const Type* fn_type = node->type; - SpvId fn_id = spv_find_reserved_id(emitter, NULL, node); + SpvId fn_id = spv_find_emitted(emitter, NULL, node); FnBuilder fn_builder = { - .base = spvb_begin_fn(emitter->file_builder, fn_id, spv_emit_type(emitter, fn_type), nodes_to_codom(emitter, node->payload.fun.return_types)), + .base = spvb_begin_fn(emitter->file_builder, fn_id, spv_emit_type(emitter, fn_type), spv_types_to_codom(emitter, node->payload.fun.return_types)), .emitted = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), .cfg = build_fn_cfg(node), }; @@ -88,7 +88,7 @@ static void emit_function(Emitter* emitter, const Node* node) { const Node* param = params.nodes[i]; const Type* param_type = param->payload.param.type; SpvId param_id = spvb_parameter(fn_builder.base, spv_emit_type(emitter, param_type)); - register_result(emitter, false, param, param_id); + spv_register_emitted(emitter, false, param, param_id); deconstruct_qualified_type(¶m_type); if (param_type->tag == PtrType_TAG && param_type->payload.ptr_type.address_space == AsGlobal) { spvb_decorate(emitter->file_builder, param_id, SpvDecorationAliased, 0, NULL); @@ -116,10 +116,10 @@ static void emit_function(Emitter* emitter, const Node* node) { const Node* bb_param = bb_params.nodes[j]; SpvId phi_id = spvb_fresh_id(emitter->file_builder); spvb_add_phi(basic_block_builder, spv_emit_type(emitter, bb_param->type), phi_id); - register_result(emitter, false, bb_param, phi_id); + spv_register_emitted(emitter, false, bb_param, phi_id); } // also make sure to register the label for basic blocks - register_result(emitter, false, bb, bb_id); + spv_register_emitted(emitter, false, bb, bb_id); } } // emit the blocks using the dominator tree @@ -158,12 +158,12 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { case GlobalVariable_TAG: { const GlobalVariable* gvar = &decl->payload.global_variable; SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, NULL, decl, given_id); + spv_register_emitted(emitter, NULL, decl, given_id); spvb_name(emitter->file_builder, given_id, gvar->name); SpvId init = 0; if (gvar->init) init = spv_emit_value(emitter, NULL, gvar->init); - SpvStorageClass storage_class = emit_addr_space(emitter, gvar->address_space); + SpvStorageClass storage_class = spv_emit_addr_space(emitter, gvar->address_space); spvb_global_variable(emitter->file_builder, given_id, spv_emit_type(emitter, decl->type), storage_class, false, init); Builtin b = BuiltinsCount; @@ -213,7 +213,7 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { return given_id; } case Function_TAG: { SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, NULL, decl, given_id); + spv_register_emitted(emitter, NULL, decl, given_id); spvb_name(emitter->file_builder, given_id, decl->payload.fun.name); emit_function(emitter, decl); return given_id; @@ -226,7 +226,7 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { return 0; } case NominalType_TAG: { SpvId given_id = spvb_fresh_id(emitter->file_builder); - register_result(emitter, NULL, decl, given_id); + spv_register_emitted(emitter, NULL, decl, given_id); spvb_name(emitter->file_builder, given_id, decl->payload.nom_type.name); spv_emit_nominal_type_body(emitter, decl->payload.nom_type.body, given_id); return given_id; @@ -263,13 +263,13 @@ static void emit_entry_points(Emitter* emitter, Nodes declarations) { default: continue; } } - interface_arr[interface_size++] = spv_find_reserved_id(emitter, NULL, node); + interface_arr[interface_size++] = spv_find_emitted(emitter, NULL, node); } for (size_t i = 0; i < declarations.count; i++) { const Node* decl = declarations.nodes[i]; if (decl->tag != Function_TAG) continue; - SpvId fn_id = spv_find_reserved_id(emitter, NULL, decl); + SpvId fn_id = spv_find_emitted(emitter, NULL, decl); const Node* entry_point = lookup_annotation(decl, "EntryPoint"); if (entry_point) { @@ -306,7 +306,7 @@ static void emit_decls(Emitter* emitter, Nodes declarations) { } } -SpvId get_extended_instruction_set(Emitter* emitter, const char* name) { +SpvId spv_get_extended_instruction_set(Emitter* emitter, const char* name) { SpvId* found = find_value_dict(const char*, SpvId, emitter->extended_instruction_sets, name); if (found) return *found; diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index 00ab75e73..2a4ff4d16 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -41,18 +41,18 @@ SpvId spv_emit_type(Emitter*, const Type*); SpvId spv_emit_value(Emitter*, FnBuilder*, const Node*); void spv_emit_terminator(Emitter*, FnBuilder*, BBBuilder, const Node* abs, const Node* terminator); -void register_result(Emitter*, FnBuilder*, const Node*, SpvId id); +void spv_register_emitted(Emitter*, FnBuilder*, const Node*, SpvId id); SpvId* spv_search_emitted(Emitter* emitter, FnBuilder*, const Node* node); -SpvId spv_find_reserved_id(Emitter* emitter, FnBuilder*, const Node* node); +SpvId spv_find_emitted(Emitter* emitter, FnBuilder*, const Node* node); BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb); -SpvId get_extended_instruction_set(Emitter*, const char*); +SpvId spv_get_extended_instruction_set(Emitter*, const char*); -SpvStorageClass emit_addr_space(Emitter*, AddressSpace address_space); +SpvStorageClass spv_emit_addr_space(Emitter*, AddressSpace address_space); // SPIR-V doesn't have multiple return types, this bridges the gap... -SpvId nodes_to_codom(Emitter* emitter, Nodes return_types); -const Type* normalize_type(Emitter* emitter, const Type* type); +SpvId spv_types_to_codom(Emitter* emitter, Nodes return_types); +const Type* spv_normalize_type(Emitter* emitter, const Type* type); void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id); #endif diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index bcb6a2afe..f9a7c9121 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -35,10 +35,10 @@ static void add_branch_phis_from_jump(Emitter* emitter, FnBuilder* fn_builder, B } static void emit_if(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, If if_instr) { - SpvId join_bb_id = spv_find_reserved_id(emitter, fn_builder, if_instr.tail); + SpvId join_bb_id = spv_find_emitted(emitter, fn_builder, if_instr.tail); - SpvId true_id = spv_find_reserved_id(emitter, fn_builder, if_instr.if_true); - SpvId false_id = if_instr.if_false ? spv_find_reserved_id(emitter, fn_builder, if_instr.if_false) : join_bb_id; + SpvId true_id = spv_find_emitted(emitter, fn_builder, if_instr.if_true); + SpvId false_id = if_instr.if_false ? spv_find_emitted(emitter, fn_builder, if_instr.if_false) : join_bb_id; spvb_selection_merge(bb_builder, join_bb_id, 0); SpvId condition = spv_emit_value(emitter, fn_builder, if_instr.condition); @@ -46,12 +46,12 @@ static void emit_if(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builde } static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Match match) { - SpvId join_bb_id = spv_find_reserved_id(emitter, fn_builder, match.tail); + SpvId join_bb_id = spv_find_emitted(emitter, fn_builder, match.tail); assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); SpvId inspectee = spv_emit_value(emitter, fn_builder, match.inspect); - SpvId default_id = spv_find_reserved_id(emitter, fn_builder, match.default_case); + SpvId default_id = spv_find_emitted(emitter, fn_builder, match.default_case); const Type* inspectee_t = match.inspect->type; deconstruct_qualified_type(&inspectee_t); @@ -67,7 +67,7 @@ static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_bui } else { literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) value; } - literals_and_cases[i * literal_case_entry_size + literal_width] = spv_find_reserved_id(emitter, fn_builder, match.cases.nodes[i]); + literals_and_cases[i * literal_case_entry_size + literal_width] = spv_find_emitted(emitter, fn_builder, match.cases.nodes[i]); } spvb_selection_merge(bb_builder, join_bb_id, 0); @@ -75,13 +75,13 @@ static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_bui } static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Loop loop_instr) { - SpvId body_id = spv_find_reserved_id(emitter, fn_builder, loop_instr.body); + SpvId body_id = spv_find_emitted(emitter, fn_builder, loop_instr.body); SpvId continue_id = spvb_fresh_id(emitter->file_builder); BBBuilder continue_builder = spvb_begin_bb(fn_builder->base, continue_id); spvb_name(emitter->file_builder, continue_id, "loop_continue"); - SpvId next_id = spv_find_reserved_id(emitter, fn_builder, loop_instr.tail); + SpvId next_id = spv_find_emitted(emitter, fn_builder, loop_instr.tail); // the header block receives the loop merge annotation spvb_loop_merge(bb_builder, next_id, continue_id, 0, 0, NULL); @@ -128,14 +128,14 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi } case Jump_TAG: { add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.jump); - spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, fn_builder, terminator->payload.jump.target)); + spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, terminator->payload.jump.target)); return; } case Branch_TAG: { SpvId condition = spv_emit_value(emitter, fn_builder, terminator->payload.branch.condition); add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.branch.true_jump->payload.jump); add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.branch.false_jump->payload.jump); - spvb_branch_conditional(basic_block_builder, condition, spv_find_reserved_id(emitter, fn_builder, terminator->payload.branch.true_jump->payload.jump.target), spv_find_reserved_id(emitter, fn_builder, terminator->payload.branch.false_jump->payload.jump.target)); + spvb_branch_conditional(basic_block_builder, condition, spv_find_emitted(emitter, fn_builder, terminator->payload.branch.true_jump->payload.jump.target), spv_find_emitted(emitter, fn_builder, terminator->payload.branch.false_jump->payload.jump.target)); return; } case Switch_TAG: { @@ -146,7 +146,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi error("TODO finish") } add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.br_switch.default_jump->payload.jump); - SpvId default_tgt = spv_find_reserved_id(emitter, fn_builder, terminator->payload.br_switch.default_jump->payload.jump.target); + SpvId default_tgt = spv_find_emitted(emitter, fn_builder, terminator->payload.br_switch.default_jump->payload.jump.target); spvb_switch(basic_block_builder, inspectee, default_tgt, terminator->payload.br_switch.case_jumps.count, targets); return; @@ -162,7 +162,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi Nodes args = terminator->payload.merge_selection.args; for (size_t i = 0; i < args.count; i++) add_branch_phis(emitter, fn_builder, basic_block_builder, tail, args); - spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, fn_builder, tail)); + spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, tail)); return; } case MergeContinue_TAG: { @@ -170,7 +170,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi Loop payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_continue.args; add_branch_phis(emitter, fn_builder, basic_block_builder, payload.body, args); - spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, fn_builder, payload.body)); + spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, payload.body)); return; } case MergeBreak_TAG: { @@ -178,7 +178,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi Loop payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_break.args; add_branch_phis(emitter, fn_builder, basic_block_builder, payload.tail, args); - spvb_branch(basic_block_builder, spv_find_reserved_id(emitter, fn_builder, payload.tail)); + spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, payload.tail)); return; } case Terminator_Control_TAG: diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 7bda84adf..5f4da5a87 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -12,7 +12,7 @@ #pragma GCC diagnostic error "-Wswitch" -SpvStorageClass emit_addr_space(Emitter* emitter, AddressSpace address_space) { +SpvStorageClass spv_emit_addr_space(Emitter* emitter, AddressSpace address_space) { switch(address_space) { case AsShared: return SpvStorageClassWorkgroup; case AsPrivate: return SpvStorageClassPrivate; @@ -54,14 +54,14 @@ static const Node* rewrite_normalize(Rewriter* rewriter, const Node* node) { } } -const Type* normalize_type(Emitter* emitter, const Type* type) { +const Type* spv_normalize_type(Emitter* emitter, const Type* type) { Rewriter rewriter = create_node_rewriter(emitter->module, emitter->module, rewrite_normalize); const Node* rewritten = rewrite_node(&rewriter, type); destroy_rewriter(&rewriter); return rewritten; } -SpvId nodes_to_codom(Emitter* emitter, Nodes return_types) { +SpvId spv_types_to_codom(Emitter* emitter, Nodes return_types) { switch (return_types.count) { case 0: return emitter->void_t; case 1: return spv_emit_type(emitter, return_types.nodes[0]); @@ -97,7 +97,7 @@ void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id) { SpvId spv_emit_type(Emitter* emitter, const Type* type) { // Some types in shady lower to the same spir-v type, but spir-v is unhappy with having duplicates of the same types // we could hash the spirv types we generate to find duplicates, but it is easier to normalise our shady types and reuse their infra - type = normalize_type(emitter, type); + type = spv_normalize_type(emitter, type); SpvId* existing = spv_search_emitted(emitter, NULL, type); if (existing) @@ -140,11 +140,11 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { new = spvb_float_type(emitter->file_builder, width); break; } case PtrType_TAG: { - SpvStorageClass sc = emit_addr_space(emitter, type->payload.ptr_type.address_space); + SpvStorageClass sc = spv_emit_addr_space(emitter, type->payload.ptr_type.address_space); const Type* pointed_type = type->payload.ptr_type.pointed_type; if (get_maybe_nominal_type_decl(pointed_type) && sc == SpvStorageClassPhysicalStorageBuffer) { new = spvb_forward_ptr_type(emitter->file_builder, sc); - register_result(emitter, NULL, type, new); + spv_register_emitted(emitter, NULL, type, new); SpvId pointee = spv_emit_type(emitter, pointed_type); spvb_ptr_type_define(emitter->file_builder, new, sc, pointee); return new; @@ -168,7 +168,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { for (size_t i = 0; i < fnt->param_types.count; i++) params[i] = spv_emit_type(emitter, fnt->param_types.nodes[i]); - new = spvb_fn_type(emitter->file_builder, fnt->param_types.count, params, nodes_to_codom(emitter, fnt->return_types)); + new = spvb_fn_type(emitter->file_builder, fnt->param_types.count, params, spv_types_to_codom(emitter, fnt->return_types)); break; } case QualifiedType_TAG: { @@ -199,7 +199,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { break; } new = spvb_fresh_id(emitter->file_builder); - register_result(emitter, NULL, type, new); + spv_register_emitted(emitter, NULL, type, new); spv_emit_nominal_type_body(emitter, type, new); return new; } @@ -225,6 +225,6 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { } } - register_result(emitter, NULL, type, new); + spv_register_emitted(emitter, NULL, type, new); return new; } diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 931b9bd51..898a1c97e 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -197,7 +197,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b SpvId result_t = instr->type == empty_multiple_return_type(emitter->arena) ? spv_emit_type(emitter, instr->type) : emitter->void_t; if (entry.extended_set) { - SpvId set_id = get_extended_instruction_set(emitter, entry.extended_set); + SpvId set_id = spv_get_extended_instruction_set(emitter, entry.extended_set); return spvb_ext_instruction(bb_builder, result_t, set_id, opcode, args.count, emitted_args); } else { return spvb_op(bb_builder, opcode, result_t, args.count, emitted_args); @@ -332,7 +332,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b LARRAY(SpvId, ops, instr.operands.count); for (size_t i = 0; i < instr.operands.count; i++) ops[i] = spv_emit_value(emitter, fn_builder, instr.operands.nodes[i]); - SpvId set_id = get_extended_instruction_set(emitter, instr.set); + SpvId set_id = spv_get_extended_instruction_set(emitter, instr.set); return spvb_ext_instruction(bb_builder, spv_emit_type(emitter, instr.result_t), set_id, instr.opcode, instr.operands.count, ops); } @@ -345,7 +345,7 @@ static SpvId emit_leaf_call(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b const Type* callee_type = fn->type; assert(callee_type->tag == FnType_TAG); Nodes return_types = callee_type->payload.fn_type.return_types; - SpvId return_type = nodes_to_codom(emitter, return_types); + SpvId return_type = spv_types_to_codom(emitter, return_types); LARRAY(SpvId, args, call.args.count); for (size_t i = 0; i < call.args.count; i++) args[i] = spv_emit_value(emitter, fn_builder, call.args.nodes[i]); @@ -437,7 +437,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui } } case Instruction_DebugPrintf_TAG: { - SpvId set_id = get_extended_instruction_set(emitter, "NonSemantic.DebugPrintf"); + SpvId set_id = spv_get_extended_instruction_set(emitter, "NonSemantic.DebugPrintf"); LARRAY(SpvId, args, instruction->payload.debug_printf.args.count + 1); args[0] = spv_emit_value(emitter, fn_builder, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) @@ -563,12 +563,12 @@ SpvId spv_emit_value(Emitter* emitter, FnBuilder* fn_builder, const Node* node) if (where) { BBBuilder bb_builder = spv_find_basic_block_builder(emitter, where->node); SpvId emitted = spv_emit_value_(emitter, fn_builder, bb_builder, node); - register_result(emitter, fn_builder, node, emitted); + spv_register_emitted(emitter, fn_builder, node, emitted); return emitted; } else { assert(!is_mem(node)); SpvId emitted = spv_emit_value_(emitter, NULL, NULL, node); - register_result(emitter, NULL, node, emitted); + spv_register_emitted(emitter, NULL, node, emitted); return emitted; } } From 86ddaeec782b0046bf3227fda0d02f80139ef6c5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 14:41:58 +0200 Subject: [PATCH 456/693] spv: emit mems --- src/backend/spirv/emit_spv.h | 1 + src/backend/spirv/emit_spv_control_flow.c | 31 ++++++++++++++++++----- src/backend/spirv/emit_spv_value.c | 17 +++++++++++++ src/shady/compile.c | 2 +- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index 2a4ff4d16..343a0dd8b 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -39,6 +39,7 @@ typedef SpvbPhi** Phis; SpvId spv_emit_decl(Emitter*, const Node*); SpvId spv_emit_type(Emitter*, const Type*); SpvId spv_emit_value(Emitter*, FnBuilder*, const Node*); +SpvId spv_emit_mem(Emitter*, FnBuilder*, const Node*); void spv_emit_terminator(Emitter*, FnBuilder*, BBBuilder, const Node* abs, const Node* terminator); void spv_register_emitted(Emitter*, FnBuilder*, const Node*, SpvId id); diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index f9a7c9121..0db1157ee 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -35,6 +35,7 @@ static void add_branch_phis_from_jump(Emitter* emitter, FnBuilder* fn_builder, B } static void emit_if(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, If if_instr) { + spv_emit_mem(emitter, fn_builder, if_instr.mem); SpvId join_bb_id = spv_find_emitted(emitter, fn_builder, if_instr.tail); SpvId true_id = spv_find_emitted(emitter, fn_builder, if_instr.if_true); @@ -46,6 +47,7 @@ static void emit_if(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builde } static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Match match) { + spv_emit_mem(emitter, fn_builder, match.mem); SpvId join_bb_id = spv_find_emitted(emitter, fn_builder, match.tail); assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); @@ -75,6 +77,7 @@ static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_bui } static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Loop loop_instr) { + spv_emit_mem(emitter, fn_builder, loop_instr.mem); SpvId body_id = spv_find_emitted(emitter, fn_builder, loop_instr.body); SpvId continue_id = spvb_fresh_id(emitter->file_builder); @@ -108,6 +111,8 @@ static const Node* find_construct(Emitter* emitter, FnBuilder* fn_builder, const void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basic_block_builder, const Node* abs, const Node* terminator) { switch (is_terminator(terminator)) { case Return_TAG: { + Return payload = terminator->payload.fn_ret; + spv_emit_mem(emitter, fn_builder, payload.mem); const Nodes* ret_values = &terminator->payload.fn_ret.args; switch (ret_values->count) { case 0: spvb_return_void(basic_block_builder); return; @@ -123,15 +128,21 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi } } case Unreachable_TAG: { + Unreachable payload = terminator->payload.unreachable; + spv_emit_mem(emitter, fn_builder, payload.mem); spvb_unreachable(basic_block_builder); return; } case Jump_TAG: { + Jump payload = terminator->payload.jump; + spv_emit_mem(emitter, fn_builder, payload.mem); add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.jump); spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, terminator->payload.jump.target)); return; } case Branch_TAG: { + Branch payload = terminator->payload.branch; + spv_emit_mem(emitter, fn_builder, payload.mem); SpvId condition = spv_emit_value(emitter, fn_builder, terminator->payload.branch.condition); add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.branch.true_jump->payload.jump); add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.branch.false_jump->payload.jump); @@ -139,6 +150,8 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi return; } case Switch_TAG: { + Switch payload = terminator->payload.br_switch; + spv_emit_mem(emitter, fn_builder, payload.mem); SpvId inspectee = spv_emit_value(emitter, fn_builder, terminator->payload.br_switch.switch_value); LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); for (size_t i = 0; i < terminator->payload.br_switch.case_jumps.count; i++) { @@ -155,6 +168,8 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi case Match_TAG: return emit_match(emitter, fn_builder, basic_block_builder, terminator->payload.match_instr); case Loop_TAG: return emit_loop(emitter, fn_builder, basic_block_builder, terminator->payload.loop_instr); case MergeSelection_TAG: { + MergeSelection payload = terminator->payload.merge_selection; + spv_emit_mem(emitter, fn_builder, payload.mem); const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_If_TAG); if (!construct) construct = find_construct(emitter, fn_builder, abs, Structured_construct_Match_TAG); @@ -166,19 +181,23 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi return; } case MergeContinue_TAG: { + MergeContinue payload = terminator->payload.merge_continue; + spv_emit_mem(emitter, fn_builder, payload.mem); const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_Loop_TAG); - Loop payload = construct->payload.loop_instr; + Loop loop_payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_continue.args; - add_branch_phis(emitter, fn_builder, basic_block_builder, payload.body, args); - spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, payload.body)); + add_branch_phis(emitter, fn_builder, basic_block_builder, loop_payload.body, args); + spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, loop_payload.body)); return; } case MergeBreak_TAG: { + MergeBreak payload = terminator->payload.merge_break; + spv_emit_mem(emitter, fn_builder, payload.mem); const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_Loop_TAG); - Loop payload = construct->payload.loop_instr; + Loop loop_payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_break.args; - add_branch_phis(emitter, fn_builder, basic_block_builder, payload.tail, args); - spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, payload.tail)); + add_branch_phis(emitter, fn_builder, basic_block_builder, loop_payload.tail, args); + spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, loop_payload.tail)); return; } case Terminator_Control_TAG: diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 898a1c97e..a8af70c0d 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -276,6 +276,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b } static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, ExtInstr instr) { + spv_emit_mem(emitter, fn_builder, instr.mem); if (strcmp("spirv.core", instr.set) == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { @@ -337,6 +338,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b } static SpvId emit_leaf_call(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Call call) { + spv_emit_mem(emitter, fn_builder, call.mem); const Node* fn = call.callee; assert(fn->tag == FnAddr_TAG); fn = fn->payload.fn_addr.fn; @@ -371,6 +373,8 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui case PrimOp_TAG: return emit_primop(emitter, fn_builder, bb_builder, instruction); case Comment_TAG: break; case Instruction_LocalAlloc_TAG: { + LocalAlloc payload = instruction->payload.local_alloc; + spv_emit_mem(emitter, fn_builder, payload.mem); assert(bb_builder); return spvb_local_variable(spvb_get_fn_builder(bb_builder), spv_emit_type(emitter, ptr_type(emitter->arena, (PtrType) { .address_space = AsFunction, @@ -379,6 +383,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui } case Instruction_Load_TAG: { Load payload = instruction->payload.load; + spv_emit_mem(emitter, fn_builder, payload.mem); const Type* ptr_type = payload.ptr->type; deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); @@ -399,6 +404,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui } case Instruction_Store_TAG: { Store payload = instruction->payload.store; + spv_emit_mem(emitter, fn_builder, payload.mem); const Type* ptr_type = payload.ptr->type; deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); @@ -437,6 +443,8 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui } } case Instruction_DebugPrintf_TAG: { + DebugPrintf payload = instruction->payload.debug_printf; + spv_emit_mem(emitter, fn_builder, payload.mem); SpvId set_id = spv_get_extended_instruction_set(emitter, "NonSemantic.DebugPrintf"); LARRAY(SpvId, args, instruction->payload.debug_printf.args.count + 1); args[0] = spv_emit_value(emitter, fn_builder, string_lit_helper(emitter->arena, instruction->payload.debug_printf.string)); @@ -572,3 +580,12 @@ SpvId spv_emit_value(Emitter* emitter, FnBuilder* fn_builder, const Node* node) return emitted; } } + +SpvId spv_emit_mem(Emitter* e, FnBuilder* b, const Node* mem) { + assert(is_mem(mem)); + if (mem->tag == AbsMem_TAG) + return 0; + if (is_instruction(mem)) + return spv_emit_value(e, b, mem); + error("What sort of mem is this ?"); +} diff --git a/src/shady/compile.c b/src/shady/compile.c index eab4fccc8..b6229a8b8 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -85,7 +85,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { if (config->lower.emulate_physical_memory) { RUN_PASS(lower_alloca) } - //RUN_PASS(lower_stack) + RUN_PASS(lower_stack) RUN_PASS(lower_lea) RUN_PASS(lower_generic_globals) if (config->lower.emulate_generic_ptrs) { From 62a5a9ef10b2fc91c1c5a67a4468ae61bb47712b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 17:40:27 +0200 Subject: [PATCH 457/693] fix reduce op in scheduler --- src/backend/spirv/emit_spv_value.c | 6 +++--- src/backend/spirv/spirv_builder.c | 4 ++-- src/backend/spirv/spirv_builder.h | 2 +- src/shady/internal/scheduler.slim | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index a8af70c0d..4f0c0d2ec 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -311,9 +311,9 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b } case SpvOpGroupNonUniformIAdd: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformArithmetic); - break; - // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); - // return spvb_group_non_uniform_iadd(bb_builder, spv_emit_type(emitter, get_unqualified_type(first(args)->type)), spv_emit_value(emitter, fn_builder, first(args)), scope_subgroup, SpvGroupOperationReduce, NULL); + SpvId scope = spv_emit_value(emitter, fn_builder, first(instr.operands)); + SpvGroupOperation group_op = get_int_literal_value(*resolve_to_int_literal(instr.operands.nodes[2]), false); + return spvb_group_non_uniform_group_op(bb_builder, spv_emit_type(emitter, instr.result_t), instr.opcode, scope, group_op, spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), NULL); } case SpvOpGroupNonUniformElect: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniform); diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index e31a59bef..2ae355461 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -849,8 +849,8 @@ SpvId spvb_group_shuffle(SpvbBasicBlockBuilder* bb_builder, SpvId result_type, S return rid; } -SpvId spvb_group_non_uniform_iadd(SpvbBasicBlockBuilder* bb_builder, SpvId result_type, SpvId value, SpvId scope, SpvGroupOperation group_op, SpvId* cluster_size) { - op(SpvOpGroupNonUniformIAdd, cluster_size ? 7 : 6); +SpvId spvb_group_non_uniform_group_op(SpvbBasicBlockBuilder* bb_builder, SpvId result_type, SpvOp op, SpvId scope, SpvGroupOperation group_op, SpvId value, SpvId* cluster_size) { + op(op, cluster_size ? 7 : 6); SpvId id = spvb_fresh_id(bb_builder->fn_builder->file_builder); ref_id(result_type); ref_id(id); diff --git a/src/backend/spirv/spirv_builder.h b/src/backend/spirv/spirv_builder.h index 8a39cdb6e..024648232 100644 --- a/src/backend/spirv/spirv_builder.h +++ b/src/backend/spirv/spirv_builder.h @@ -100,7 +100,7 @@ SpvId spvb_group_elect(SpvbBasicBlockBuilder*, SpvId result_type, SpvId scope); SpvId spvb_group_ballot(SpvbBasicBlockBuilder*, SpvId result_t, SpvId predicate, SpvId scope); SpvId spvb_group_shuffle(SpvbBasicBlockBuilder*, SpvId result_type, SpvId scope, SpvId value, SpvId id); SpvId spvb_group_broadcast_first(SpvbBasicBlockBuilder*, SpvId result_t, SpvId value, SpvId scope); -SpvId spvb_group_non_uniform_iadd(SpvbBasicBlockBuilder*, SpvId result_t, SpvId value, SpvId scope, SpvGroupOperation group_op, SpvId* cluster_size); +SpvId spvb_group_non_uniform_group_op(SpvbBasicBlockBuilder*, SpvId result_t, SpvOp op, SpvId scope, SpvGroupOperation group_op, SpvId value, SpvId* cluster_size); // Terminators void spvb_branch(SpvbBasicBlockBuilder*, SpvId target); diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index 4570cd2ac..1bc31e405 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -46,7 +46,7 @@ fn builtin_init_scheduler() { scheduler_vector#(subgroup_local_id) = tree_node1; active_branch = tree_node1; - actual_subgroup_size = (ext_instr["spirv.core", 349, varying u32](3, 0, u32 1)); + actual_subgroup_size = (ext_instr["spirv.core", 349, varying u32](3, 0, u32 1, 0)); } @Internal @Leaf From 9ad6b525c0af64a8a4a5f5f04cacccf1f44a78cb Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 11 Aug 2024 20:33:03 +0200 Subject: [PATCH 458/693] fixing some more spirv bugs --- src/backend/spirv/emit_spv_value.c | 4 +- src/backend/spirv/spirv_builder.c | 72 +++++++++++++++++------------- src/shady/internal/scheduler.slim | 2 +- src/shady/passes/bind.c | 2 +- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 4f0c0d2ec..8387d8295 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -195,7 +195,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b if (opcode == SpvOpMax) goto custom; - SpvId result_t = instr->type == empty_multiple_return_type(emitter->arena) ? spv_emit_type(emitter, instr->type) : emitter->void_t; + SpvId result_t = instr->type == empty_multiple_return_type(emitter->arena) ? emitter->void_t : spv_emit_type(emitter, instr->type); if (entry.extended_set) { SpvId set_id = spv_get_extended_instruction_set(emitter, entry.extended_set); return spvb_ext_instruction(bb_builder, result_t, set_id, opcode, args.count, emitted_args); @@ -290,7 +290,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b } break; } - case SpvCapabilityGroupNonUniformBallot: { + case SpvOpGroupNonUniformBallot: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); assert(instr.operands.count == 2); // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index 2ae355461..7eee49eda 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -564,7 +564,8 @@ void spvb_declare_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_buil struct SpvbBasicBlockBuilder_ { SpvbFnBuilder* fn_builder; - SpvbSectionBuilder section_data; + SpvbSectionBuilder instructions_section; + SpvbSectionBuilder terminator_section; struct List* phis; SpvId label; @@ -621,10 +622,12 @@ void spvb_define_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_build free(phi); } - copy_section(bb->section_data); + copy_section(bb->instructions_section); + copy_section(bb->terminator_section); destroy_list(bb->phis); - destroy_growy(bb->section_data); + destroy_growy(bb->instructions_section); + destroy_growy(bb->terminator_section); free(bb); } @@ -640,10 +643,11 @@ void spvb_define_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_build SpvbBasicBlockBuilder* spvb_begin_bb(SpvbFnBuilder* fn_builder, SpvId label) { SpvbBasicBlockBuilder* bbb = (SpvbBasicBlockBuilder*) malloc(sizeof(SpvbBasicBlockBuilder)); *bbb = (SpvbBasicBlockBuilder) { - .fn_builder = fn_builder, - .label = label, - .phis = new_list(SpvbPhi*), - .section_data = new_growy() + .fn_builder = fn_builder, + .label = label, + .phis = new_list(SpvbPhi*), + .instructions_section = new_growy(), + .terminator_section = new_growy(), }; return bbb; } @@ -679,7 +683,7 @@ struct List* spbv_get_phis(SpvbBasicBlockBuilder* bb_builder) { // It is tiresome to pass the context over and over again. Let's not ! // We use this macro to save us some typing -#define target_data bb_builder->section_data +#define target_data bb_builder->instructions_section SpvId spvb_composite(SpvbBasicBlockBuilder* bb_builder, SpvId aggregate_t, size_t elements_count, SpvId elements[]) { op(SpvOpCompositeConstruct, 3u + elements_count); ref_id(aggregate_t); @@ -779,7 +783,7 @@ SpvId spvb_load(SpvbBasicBlockBuilder* bb_builder, SpvId target_type, SpvId poin return id; } -SpvId spvb_vecshuffle(SpvbBasicBlockBuilder* bb_builder, SpvId result_type, SpvId a, SpvId b, size_t operands_count, uint32_t operands[]) { +SpvId spvb_vecshuffle(SpvbBasicBlockBuilder* bb_builder, SpvId result_type, SpvId a, SpvId b, size_t operands_count, uint32_t operands[]) { op(SpvOpVectorShuffle, 5 + operands_count); SpvId id = spvb_fresh_id(bb_builder->fn_builder->file_builder); ref_id(result_type); @@ -862,6 +866,32 @@ SpvId spvb_group_non_uniform_group_op(SpvbBasicBlockBuilder* bb_builder, SpvId r return id; } +SpvId spvb_call(SpvbBasicBlockBuilder* bb_builder, SpvId return_type, SpvId callee, size_t arguments_count, SpvId arguments[]) { + op(SpvOpFunctionCall, 4u + arguments_count); + SpvId id = spvb_fresh_id(bb_builder->fn_builder->file_builder); + ref_id(return_type); + ref_id(id); + ref_id(callee); + for (size_t i = 0; i < arguments_count; i++) + ref_id(arguments[i]); + return id; +} + +SpvId spvb_ext_instruction(SpvbBasicBlockBuilder* bb_builder, SpvId return_type, SpvId set, uint32_t instruction, size_t arguments_count, SpvId arguments[]) { + op(SpvOpExtInst, 5 + arguments_count); + SpvId id = spvb_fresh_id(bb_builder->fn_builder->file_builder); + ref_id(return_type); + ref_id(id); + ref_id(set); + literal_int(instruction); + for (size_t i = 0; i < arguments_count; i++) + ref_id(arguments[i]); + return id; +} + +#undef target_data +#define target_data bb_builder->terminator_section + void spvb_branch(SpvbBasicBlockBuilder* bb_builder, SpvId target) { op(SpvOpBranch, 2); ref_id(target); @@ -899,29 +929,6 @@ void spvb_loop_merge(SpvbBasicBlockBuilder* bb_builder, SpvId merge_bb, SpvId co literal_int(loop_control_ops[i]); } -SpvId spvb_call(SpvbBasicBlockBuilder* bb_builder, SpvId return_type, SpvId callee, size_t arguments_count, SpvId arguments[]) { - op(SpvOpFunctionCall, 4u + arguments_count); - SpvId id = spvb_fresh_id(bb_builder->fn_builder->file_builder); - ref_id(return_type); - ref_id(id); - ref_id(callee); - for (size_t i = 0; i < arguments_count; i++) - ref_id(arguments[i]); - return id; -} - -SpvId spvb_ext_instruction(SpvbBasicBlockBuilder* bb_builder, SpvId return_type, SpvId set, uint32_t instruction, size_t arguments_count, SpvId arguments[]) { - op(SpvOpExtInst, 5 + arguments_count); - SpvId id = spvb_fresh_id(bb_builder->fn_builder->file_builder); - ref_id(return_type); - ref_id(id); - ref_id(set); - literal_int(instruction); - for (size_t i = 0; i < arguments_count; i++) - ref_id(arguments[i]); - return id; -} - void spvb_return_void(SpvbBasicBlockBuilder* bb_builder) { op(SpvOpReturn, 1); } @@ -934,4 +941,5 @@ void spvb_return_value(SpvbBasicBlockBuilder* bb_builder, SpvId value) { void spvb_unreachable(SpvbBasicBlockBuilder* bb_builder) { op(SpvOpUnreachable, 1); } + #undef target_data diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index 1bc31e405..54b46f499 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -46,7 +46,7 @@ fn builtin_init_scheduler() { scheduler_vector#(subgroup_local_id) = tree_node1; active_branch = tree_node1; - actual_subgroup_size = (ext_instr["spirv.core", 349, varying u32](3, 0, u32 1, 0)); + actual_subgroup_size = (ext_instr["spirv.core", 349, varying u32](3, u32 1, 0)); } @Internal @Leaf diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index 817117fee..b5e69795e 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -285,7 +285,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { case SlimOpSubscript: { return mem_and_value(a, (MemAndValue) { .value = prim_op(a, (PrimOp) { - .op = extract_dynamic_op, + .op = extract_op, .operands = mk_nodes(a, rewrite_node(r, payload.operands.nodes[0]), rewrite_node(r, payload.operands.nodes[1])) }), .mem = rewrite_node(r, payload.mem) } From 862c85e6f227b2de0e0e22cf61c57bf6eb8cf90d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 10:12:54 +0200 Subject: [PATCH 459/693] bind: try to use LEAs for subscript ops --- src/shady/passes/bind.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/shady/passes/bind.c b/src/shady/passes/bind.c index b5e69795e..7e6b09f40 100644 --- a/src/shady/passes/bind.c +++ b/src/shady/passes/bind.c @@ -85,7 +85,7 @@ static void add_binding(Context* ctx, bool is_var, String name, const Node* node static const Node* get_node_address(Context* ctx, const Node* node); -static const Node* get_node_address_safe(Context* ctx, const Node* node) { +static const Node* get_node_address_maybe(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; switch (node->tag) { @@ -103,7 +103,7 @@ static const Node* get_node_address_safe(Context* ctx, const Node* node) { if (strcmp(payload.set, "shady.frontend") == 0) { if (payload.opcode == SlimOpSubscript) { assert(payload.operands.count == 2); - const Node* src_ptr = get_node_address_safe(ctx, first(payload.operands)); + const Node* src_ptr = get_node_address_maybe(ctx, first(payload.operands)); if (src_ptr == NULL) return NULL; const Node* index = rewrite_node(&ctx->rewriter, payload.operands.nodes[1]); @@ -127,7 +127,7 @@ static const Node* get_node_address_safe(Context* ctx, const Node* node) { } static const Node* get_node_address(Context* ctx, const Node* node) { - const Node* got = get_node_address_safe(ctx, node); + const Node* got = get_node_address_maybe(ctx, node); if (!got) error("This doesn't really look like a place expression...") return got; } @@ -283,6 +283,12 @@ static const Node* bind_node(Context* ctx, const Node* node) { return mem_and_value(a, (MemAndValue) { .value = target_ptr, .mem = rewrite_node(r, payload.mem) }); } case SlimOpSubscript: { + const Node* ptr = get_node_address_maybe(ctx, node); + if (ptr) + return load(a, (Load) { + .ptr = ptr, + .mem = rewrite_node(r, payload.mem) + }); return mem_and_value(a, (MemAndValue) { .value = prim_op(a, (PrimOp) { .op = extract_op, From 7fb67633bb9f63b576270fc65a38703a955ff254 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 10:22:16 +0200 Subject: [PATCH 460/693] move slim-specific passes out of main target --- {src/shady/passes => include/shady}/pass.h | 4 +- src/frontend/slim/CMakeLists.txt | 2 +- src/{shady/passes => frontend/slim}/bind.c | 7 ++- src/{shady/passes => frontend/slim}/infer.c | 6 +-- .../passes => frontend/slim}/normalize.c | 4 +- src/frontend/slim/parser.c | 32 +------------- src/frontend/slim/slim_driver.c | 43 +++++++++++++++++++ src/shady/CMakeLists.txt | 3 -- src/shady/passes/cleanup.c | 2 +- src/shady/passes/eliminate_constants.c | 2 +- src/shady/passes/import.c | 2 +- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_callf.c | 2 +- src/shady/passes/lower_cf_instrs.c | 2 +- src/shady/passes/lower_decay_ptrs.c | 2 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_fill.c | 2 +- src/shady/passes/lower_generic_globals.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 2 +- src/shady/passes/lower_int64.c | 2 +- src/shady/passes/lower_lea.c | 2 +- src/shady/passes/lower_logical_pointers.c | 2 +- src/shady/passes/lower_mask.c | 2 +- src/shady/passes/lower_memcpy.c | 2 +- src/shady/passes/lower_memory_layout.c | 2 +- src/shady/passes/lower_nullptr.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 2 +- src/shady/passes/lower_stack.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_subgroup_vars.c | 2 +- src/shady/passes/lower_switch_btree.c | 2 +- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/mark_leaf_functions.c | 2 +- src/shady/passes/normalize_builtins.c | 2 +- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_inline.c | 2 +- src/shady/passes/opt_restructure.c | 2 +- src/shady/passes/passes.h | 9 +--- src/shady/passes/reconvergence_heuristics.c | 2 +- src/shady/passes/setup_stack_frames.c | 2 +- src/shady/passes/simt2d.c | 2 +- src/shady/passes/specialize_entry_point.c | 2 +- src/shady/passes/specialize_execution_model.c | 2 +- src/shady/passes/spirv_lift_globals_ssbo.c | 2 +- src/shady/passes/spirv_map_entrypoint_args.c | 2 +- 48 files changed, 95 insertions(+), 93 deletions(-) rename {src/shady/passes => include/shady}/pass.h (82%) rename src/{shady/passes => frontend/slim}/bind.c (99%) rename src/{shady/passes => frontend/slim}/infer.c (99%) rename src/{shady/passes => frontend/slim}/normalize.c (98%) create mode 100644 src/frontend/slim/slim_driver.c diff --git a/src/shady/passes/pass.h b/include/shady/pass.h similarity index 82% rename from src/shady/passes/pass.h rename to include/shady/pass.h index 9a9ad2f6f..e2bfc7c22 100644 --- a/src/shady/passes/pass.h +++ b/include/shady/pass.h @@ -1,5 +1,5 @@ -#ifndef SHD_PASS_H -#define SHD_PASS_H +#ifndef SHADY_PASS_H +#define SHADY_PASS_H #include "shady/config.h" #include "rewrite.h" diff --git a/src/frontend/slim/CMakeLists.txt b/src/frontend/slim/CMakeLists.txt index 6df10e398..eb55eafc9 100644 --- a/src/frontend/slim/CMakeLists.txt +++ b/src/frontend/slim/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(slim_parser STATIC parser.c token.c) +add_library(slim_parser STATIC slim_driver.c parser.c token.c bind.c normalize.c infer.c) target_link_libraries(slim_parser PUBLIC common api) target_link_libraries(slim_parser PRIVATE shady) target_include_directories(slim_parser PUBLIC $) diff --git a/src/shady/passes/bind.c b/src/frontend/slim/bind.c similarity index 99% rename from src/shady/passes/bind.c rename to src/frontend/slim/bind.c index 7e6b09f40..2442cd00b 100644 --- a/src/shady/passes/bind.c +++ b/src/frontend/slim/bind.c @@ -1,6 +1,7 @@ -#include "pass.h" +#include "shady/pass.h" +#include "shady/fe/slim.h" -#include "../ir_private.h" +#include "../shady/ir_private.h" #include "list.h" #include "log.h" @@ -9,8 +10,6 @@ #include #include -#include "shady/fe/slim.h" - typedef struct NamedBindEntry_ NamedBindEntry; struct NamedBindEntry_ { const char* name; diff --git a/src/shady/passes/infer.c b/src/frontend/slim/infer.c similarity index 99% rename from src/shady/passes/infer.c rename to src/frontend/slim/infer.c index 034aaf929..4bf750ca1 100644 --- a/src/shady/passes/infer.c +++ b/src/frontend/slim/infer.c @@ -1,7 +1,7 @@ -#include "pass.h" +#include "shady/pass.h" -#include "../type.h" -#include "../transform/ir_gen_helpers.h" +#include "../shady/type.h" +#include "../shady/transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/normalize.c b/src/frontend/slim/normalize.c similarity index 98% rename from src/shady/passes/normalize.c rename to src/frontend/slim/normalize.c index be704b812..490971d2e 100644 --- a/src/shady/passes/normalize.c +++ b/src/frontend/slim/normalize.c @@ -1,6 +1,6 @@ -#include "pass.h" +#include "shady/pass.h" -#include "../type.h" +#include "../shady/type.h" #include "log.h" #include "portability.h" diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 23a62ee84..a5be23073 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -1144,7 +1144,7 @@ static const Node* accept_nominal_type_decl(ctxparams, Nodes annotations) { return nom; } -static void parse_shady_ir(ParserConfig config, const char* contents, Module* mod) { +void slim_parse_string(ParserConfig config, const char* contents, Module* mod) { IrArena* arena = get_module_arena(mod); Tokenizer* tokenizer = new_tokenizer(contents); @@ -1174,33 +1174,3 @@ static void parse_shady_ir(ParserConfig config, const char* contents, Module* mo destroy_tokenizer(tokenizer); } -#include "compile.h" -#include "transform/internal_constants.h" - -Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name) { - ArenaConfig aconfig = default_arena_config(&config->target); - aconfig.name_bound = false; - aconfig.check_op_classes = false; - aconfig.check_types = false; - aconfig.validate_builtin_types = false; - aconfig.allow_fold = false; - IrArena* initial_arena = new_ir_arena(&aconfig); - Module* m = new_module(initial_arena, name); - parse_shady_ir(pconfig, contents, m); - Module** pmod = &m; - Module* old_mod = NULL; - - debugv_print("Parsed slim module:\n"); - log_module(DEBUGV, config, *pmod); - - generate_dummy_constants(config, *pmod); - - RUN_PASS(bind_program) - RUN_PASS(normalize) - - RUN_PASS(normalize_builtins) - RUN_PASS(infer_program) - - destroy_ir_arena(initial_arena); - return *pmod; -} diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c new file mode 100644 index 000000000..67e565e02 --- /dev/null +++ b/src/frontend/slim/slim_driver.c @@ -0,0 +1,43 @@ +#include "compile.h" +#include "parser.h" + +#include "shady/pass.h" + +#include "../shady/transform/internal_constants.h" + +/// Removes all Unresolved nodes and replaces them with the appropriate decl/value +RewritePass bind_program; +/// Enforces the grammar, notably by let-binding any intermediary result +RewritePass normalize; +/// Makes sure every node is well-typed +RewritePass infer_program; + +void slim_parse_string(ParserConfig config, const char* contents, Module* mod); + +Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name) { + ArenaConfig aconfig = default_arena_config(&config->target); + aconfig.name_bound = false; + aconfig.check_op_classes = false; + aconfig.check_types = false; + aconfig.validate_builtin_types = false; + aconfig.allow_fold = false; + IrArena* initial_arena = new_ir_arena(&aconfig); + Module* m = new_module(initial_arena, name); + slim_parse_string(pconfig, contents, m); + Module** pmod = &m; + Module* old_mod = NULL; + + debugv_print("Parsed slim module:\n"); + log_module(DEBUGV, config, *pmod); + + generate_dummy_constants(config, *pmod); + + RUN_PASS(bind_program) + RUN_PASS(normalize) + + RUN_PASS(normalize_builtins) + RUN_PASS(infer_program) + + destroy_ir_arena(initial_arena); + return *pmod; +} diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 7017d1cc6..4ff0e530d 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -56,9 +56,6 @@ set(SHADY_SOURCES passes/import.c passes/cleanup.c - passes/bind.c - passes/normalize.c - passes/infer.c passes/lower_cf_instrs.c passes/lift_indirect_targets.c passes/lower_callf.c diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 2dc3b405f..3dbf4587d 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../analysis/uses.h" #include "../ir_private.h" diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index b8fbfa4b4..80737e945 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "portability.h" #include "log.h" diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index f77819bee..102bd2046 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index cc4024ff6..94d4fc99b 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index a57d443f6..8608bd1a1 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../visit.h" #include "../type.h" diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index f5b211e7b..5fe5d561e 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 77c9d7b38..34e19f1ff 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../analysis/cfg.h" diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index e043269c2..fcb46f4ba 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 56d2fff87..74826b142 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index 18f748ffe..98d7e1937 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 854614b6a..fdcc11444 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index f2e8431d0..cf1517d7a 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 2e73c535e..05f9c06f3 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 3e87106f7..8ea6594c8 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index fbe221395..b7c24cd8a 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 6b8704696..beb1f48e6 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index f56e82d48..42b78d933 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../transform/ir_gen_helpers.h" #include "../transform/memory_layout.h" diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 22bf35bd8..77f0d5a54 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../transform/memory_layout.h" #include "../type.h" diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index a769b6ee4..3774363ed 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 8202c253c..2692dcc83 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index f04764684..451634717 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 0a3dd6a20..e7f8e07e3 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 2d48d0cef..499b32887 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -1,6 +1,6 @@ #include -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 9e25a98c9..636a87c6e 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index b89f309a0..c5b7f4670 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index cda9ed973..35f4e323a 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index e681a2d6c..9c2410a4c 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index 90c6ab9f3..a66d04366 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../analysis/callgraph.h" #include "../analysis/cfg.h" diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index ce4f4b6cd..7eec9ef0a 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 182e4df71..8b24eae9d 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../visit.h" #include "../type.h" diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 010f6ea8f..a9c491a02 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 028cdd5e6..1e121a2be 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index c3b1b1abf..20a52c5b0 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -1,7 +1,7 @@ #ifndef SHADY_PASSES_H #include "shady/ir.h" -#include "pass.h" +#include "shady/pass.h" /// @name Boring, regular compiler stuff /// @{ @@ -9,13 +9,6 @@ RewritePass import; RewritePass cleanup; -/// Removes all Unresolved nodes and replaces them with the appropriate decl/value -RewritePass bind_program; -/// Enforces the grammar, notably by let-binding any intermediary result -RewritePass normalize; -/// Makes sure every node is well-typed -RewritePass infer_program; - /// @} /// @name Initial CF lowering passes diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 2780ca6bd..1f92c7258 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 857302873..afe056f8f 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../visit.h" #include "../type.h" diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c index baf16c332..0202a338e 100644 --- a/src/shady/passes/simt2d.c +++ b/src/shady/passes/simt2d.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 2140906dc..839e96310 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 098eb959e..d88623508 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index 420a8571b..9320669a7 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/spirv_map_entrypoint_args.c b/src/shady/passes/spirv_map_entrypoint_args.c index 81d2e43a7..3b2bfd7cc 100644 --- a/src/shady/passes/spirv_map_entrypoint_args.c +++ b/src/shady/passes/spirv_map_entrypoint_args.c @@ -1,4 +1,4 @@ -#include "pass.h" +#include "shady/pass.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" From 6e011caab0323d7a26820d10f88b97038569fb04 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 10:29:11 +0200 Subject: [PATCH 461/693] fix lower_alloca --- src/shady/passes/lower_alloca.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 8608bd1a1..15fe75d5a 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -57,13 +57,11 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { insert_dict(const Node*, StackSlot, vctx->prepared_offsets, node, slot); vctx->num_slots++; - - return; + break; } default: break; } - not_alloca: visit_node_operands(&vctx->visitor, IGNORE_ABSTRACTIONS_MASK, node); } From 22c375a4b78a6f64910ab798f4d3fde476e0fcfe Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 10:29:17 +0200 Subject: [PATCH 462/693] fix debug_printf parsing --- src/frontend/slim/parser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index a5be23073..f4c7fa69f 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -231,7 +231,8 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { Nodes ops = expect_operands(ctx, bb); return bind_instruction_single(bb, debug_printf(arena, (DebugPrintf) { .string = get_string_literal(arena, first(ops)), - .args = nodes(arena, ops.count - 1, &ops.nodes[1]) + .args = nodes(arena, ops.count - 1, &ops.nodes[1]), + .mem = bb_mem(bb), })); } From 52a4ff090b31e39ee904357e20c4594b9393894a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 11:17:15 +0200 Subject: [PATCH 463/693] added builder sanity-check test --- test/CMakeLists.txt | 4 +++ test/test_builder.c | 87 +++++++++++++++++++++++++++++++++++++++++++++ test/test_math.c | 8 ++--- 3 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 test/test_builder.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 97a5899ec..04c8a08b0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,6 +3,10 @@ if (BUILD_TESTING) target_link_libraries(test_math driver) add_test(NAME test_math COMMAND test_math) + add_executable(test_builder test_builder.c) + target_link_libraries(test_builder driver) + add_test(NAME test_builder COMMAND test_builder) + list(APPEND BASIC_TESTS empty.slim) list(APPEND BASIC_TESTS entrypoint_args1.slim) list(APPEND BASIC_TESTS basic_blocks1.slim) diff --git a/test/test_builder.c b/test/test_builder.c new file mode 100644 index 000000000..c82c37ba7 --- /dev/null +++ b/test/test_builder.c @@ -0,0 +1,87 @@ +#include "shady/ir.h" +#include "shady/driver.h" +#include "shady/be/dump.h" + +#include "../shady/transform/ir_gen_helpers.h" +#include "../shady/analysis/cfg.h" + +#include "log.h" +#include "type.h" + +#include +#include +#include + +#define CHECK(x, failure_handler) { if (!(x)) { error_print(#x " failed\n"); failure_handler; } } + +static void test_body_builder_constants(IrArena* a) { + BodyBuilder* bb = begin_block_pure(a); + const Node* sum = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, int32_literal(a, 4), int32_literal(a, 38))); + const Node* result = yield_value_and_wrap_in_block(bb, sum); + CHECK(sum == result, exit(-1)); + CHECK(result->tag == IntLiteral_TAG, exit(-1)); + CHECK(get_int_literal_value(result->payload.int_literal, false) == 42, exit(-1)); +} + +static void test_body_builder_fun_body(IrArena* a) { + Module* m = new_module(a, "test_module"); + const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = uint32_type(a), + }), false), NULL); + const Node* p2 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = uint32_type(a), + }), false), NULL); + // const Node* p3 = param(a, qualified_type_helper(bool_type(a), false), NULL); + // const Node* p4 = param(a, qualified_type_helper(uint32_type(a), false), NULL); + Node* fun = function(m, mk_nodes(a, p1, p2), "fun", empty(a), empty(a)); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + + const Node* p1_value = gen_load(bb, p1); + CHECK(p1_value->tag == Load_TAG, exit(-1)); + Node* true_case = case_(a, empty(a)); + BodyBuilder* tc_builder = begin_body_with_mem(a, get_abstraction_mem(true_case)); + gen_store(tc_builder, p1, uint32_literal(a, 0)); + set_abstraction_body(true_case, finish_body_with_selection_merge(tc_builder, empty(a))); + gen_if(bb, empty(a), gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, p1_value, uint32_literal(a, 0))), true_case, NULL); + + const Node* p2_value = gen_load(bb, p2); + + const Node* sum = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, p1_value, p2_value)); + const Node* return_terminator = fn_ret(a, (Return) { + .mem = bb_mem(bb), + .args = singleton(sum) + }); + set_abstraction_body(fun, finish_body(bb, return_terminator)); + // set_abstraction_body(fun, finish_body_with_return(bb, singleton(sum))); + + dump_module(m); + + // Follow the CFG and the mems to make sure we arrive back at the initial start ! + CFG* cfg = build_fn_cfg(fun); + const Node* mem = get_terminator_mem(return_terminator); + do { + mem = get_original_mem(mem); + CHECK(mem->tag == AbsMem_TAG, exit(-1)); + CFNode* n = cfg_lookup(cfg, mem->payload.abs_mem.abs); + if (n->idom) { + mem = get_terminator_mem(get_abstraction_body(n->idom->node)); + continue; + } + } while (false); + mem = get_original_mem(mem); + CHECK(mem == get_abstraction_mem(fun), exit(-1)); + destroy_cfg(cfg); +} + +int main(int argc, char** argv) { + cli_parse_common_args(&argc, argv); + + TargetConfig target_config = default_target_config(); + ArenaConfig aconfig = default_arena_config(&target_config); + IrArena* a = new_ir_arena(&aconfig); + test_body_builder_constants(a); + test_body_builder_fun_body(a); + destroy_ir_arena(a); +} diff --git a/test/test_math.c b/test/test_math.c index 0cbc1d2f8..da13a97af 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -1,12 +1,12 @@ -#include -#include -#include - #include "shady/ir.h" #include "shady/driver.h" #include "log.h" +#include +#include +#include + #define CHECK(x, failure_handler) { if (!(x)) { error_print(#x " failed\n"); failure_handler; } } static bool check_same_bytes(char* a, char* b, size_t size) { From 2fc88e70ce30fc0289371d19bfefcac80e783132 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 11:50:42 +0200 Subject: [PATCH 464/693] magic control-flow insertion works --- include/shady/ir.h | 2 +- src/shady/body_builder.c | 18 +++++++++---- src/shady/ir_private.h | 2 +- src/shady/node.c | 42 ++++++++++++++--------------- src/shady/passes/lower_workgroups.c | 4 +-- test/test_builder.c | 40 +++++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 30 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 777dbcb7d..baad5eda7 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -283,7 +283,7 @@ static inline Node* case_(IrArena* a, Nodes params) { /// Used to build a chain of let BodyBuilder* begin_body_with_mem(IrArena*, const Node*); BodyBuilder* begin_block_pure(IrArena*); -BodyBuilder* begin_block_with_side_effects(IrArena*); +BodyBuilder* begin_block_with_side_effects(IrArena*, const Node*); /// Appends an instruction to the builder, may apply optimisations. /// If the arena is typed, returns a list of variables bound to the values yielded by that instruction diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 81ea614ab..1eb66166d 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -27,16 +27,16 @@ BodyBuilder* begin_body_with_mem(IrArena* a, const Node* mem) { *bb = (BodyBuilder) { .arena = a, .stack = new_list(StackEntry), - .mem0 = mem, .mem = mem, }; return bb; } -BodyBuilder* begin_block_with_side_effects(IrArena* a) { +BodyBuilder* begin_block_with_side_effects(IrArena* a, const Node* mem) { Node* block = basic_block(a, empty(a), NULL); BodyBuilder* builder = begin_body_with_mem(a, get_abstraction_mem(block)); builder->bb = block; + builder->block_entry_mem = mem; return builder; } @@ -120,7 +120,15 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { } const Node* finish_body(BodyBuilder* bb, const Node* terminator) { - assert(bb->mem0); + assert(bb->mem && !bb->block_entry_mem); + terminator = build_body(bb, terminator); + destroy_list(bb->stack); + free(bb); + return terminator; +} + +const Node* finish_block_body(BodyBuilder* bb, const Node* terminator) { + assert(bb->block_entry_mem); terminator = build_body(bb, terminator); destroy_list(bb->stack); free(bb); @@ -163,7 +171,7 @@ const Node* finish_body_with_loop_break(BodyBuilder* bb, Nodes args) { const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { IrArena* a = bb->arena; - if (entries_count_list(bb->stack) == 0) { + if (!bb->bb && entries_count_list(bb->stack) == 0) { const Node* last_mem = bb_mem(bb); cancel_body(bb); if (last_mem) @@ -198,7 +206,7 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { IrArena* arena = bb->arena; - assert(!bb->mem0 && entries_count_list(bb->stack) == 0); + assert(!bb->mem && !bb->block_entry_mem && entries_count_list(bb->stack) == 0); return maybe_tuple_helper(arena, values); } diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index 747ef94d7..c983bc291 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -37,7 +37,7 @@ void destroy_module(Module* m); struct BodyBuilder_ { IrArena* arena; struct List* stack; - const Node* mem0; + const Node* block_entry_mem; const Node* mem; Node* bb; }; diff --git a/src/shady/node.c b/src/shady/node.c index ecfa329be..d19d2c8aa 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -299,33 +299,33 @@ String get_abstraction_name_safe(const Node* abs) { return format_string_interned(abs->arena, "%%%d", abs->id); } +const Node* finish_block_body(BodyBuilder* bb, const Node* terminator); + void set_abstraction_body(Node* abs, const Node* body) { assert(is_abstraction(abs)); assert(!body || is_terminator(body)); IrArena* a = abs->arena; - switch (abs->tag) { - case Function_TAG: abs->payload.fun.body = body; break; - case BasicBlock_TAG: { - while (true) { - const Node* mem0 = get_original_mem(get_terminator_mem(body)); - assert(mem0->tag == AbsMem_TAG); - const Node* mem_abs = mem0->payload.abs_mem.abs; - if (is_basic_block(mem_abs)) { - BodyBuilder* insert = mem_abs->payload.basic_block.insert; - if (insert) { - const Node* mem = insert->mem0; - set_abstraction_body((Node*) mem_abs, finish_body(insert, body)); - body = jump_helper(a, mem_abs, empty(a), mem); - continue; - } - assert(mem_abs == abs); - } - break; - } - abs->payload.basic_block.body = body; - break; + while (true) { + const Node* mem0 = get_original_mem(get_terminator_mem(body)); + assert(mem0->tag == AbsMem_TAG); + const Node* mem_abs = mem0->payload.abs_mem.abs; + if (is_basic_block(mem_abs)) { + BodyBuilder* insert = mem_abs->payload.basic_block.insert; + if (insert && mem_abs != abs) { + const Node* mem = insert->block_entry_mem; + set_abstraction_body((Node*) mem_abs, finish_block_body(insert, body)); + body = jump_helper(a, mem_abs, empty(a), mem); + continue; + } + assert(mem_abs == abs); } + break; + } + + switch (abs->tag) { + case Function_TAG: abs->payload.fun.body = body; break; + case BasicBlock_TAG: abs->payload.basic_block.body = body; break; default: assert(false); } } diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 9c2410a4c..64ee49139 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -91,7 +91,7 @@ static const Node* process(Context* ctx, const Node* node) { num_subgroups_literals[dim] = uint32_literal(a, num_subgroups[dim]); } - BodyBuilder* bb2 = begin_block_with_side_effects(a); + BodyBuilder* bb2 = begin_block_with_side_effects(a, bb_mem(bb)); // write the workgroup ID gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); // write the local ID @@ -131,7 +131,7 @@ static const Node* process(Context* ctx, const Node* node) { gen_if(body_bb, empty(a), gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), out_of_bounds_case, NULL); bind_instruction(body_bb, instr); - BodyBuilder* bb3 = begin_block_with_side_effects(a); + BodyBuilder* bb3 = begin_block_with_side_effects(a, NULL); set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) {.args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1))))}))); gen_loop(bb3, empty(a), singleton(uint32_literal(a, 0)), loop_body); instr = yield_values_and_wrap_in_block(bb3, empty(a)); diff --git a/test/test_builder.c b/test/test_builder.c index c82c37ba7..4c87831b2 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -75,6 +75,45 @@ static void test_body_builder_fun_body(IrArena* a) { destroy_cfg(cfg); } +/// There is some "magic" code in body_builder and set_abstraction_body to enable inserting control-flow +/// where there is only a mem dependency. This is useful when writing some complex polyfills. +static void test_body_builder_impure_block(IrArena* a) { + Module* m = new_module(a, "test_module"); + const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = uint32_type(a), + }), false), NULL); + Node* fun = function(m, mk_nodes(a, p1), "fun", empty(a), empty(a)); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + + const Node* first_load = gen_load(bb, p1); + + BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); + gen_store(block_builder, p1, uint32_literal(a, 0)); + bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, empty(a))); + + const Node* second_load = gen_load(bb, p1); + + const Node* sum = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, first_load, second_load)); + const Node* return_terminator = fn_ret(a, (Return) { + .mem = bb_mem(bb), + .args = singleton(sum) + }); + set_abstraction_body(fun, finish_body(bb, return_terminator)); + + dump_module(m); + + bool found_store = false; + const Node* mem = get_terminator_mem(return_terminator); + while (mem->tag != AbsMem_TAG) { + if (mem->tag == Store_TAG) + found_store = true; + mem = get_parent_mem(mem); + } + + CHECK(found_store, exit(-1)); +} + int main(int argc, char** argv) { cli_parse_common_args(&argc, argv); @@ -83,5 +122,6 @@ int main(int argc, char** argv) { IrArena* a = new_ir_arena(&aconfig); test_body_builder_constants(a); test_body_builder_fun_body(a); + test_body_builder_impure_block(a); destroy_ir_arena(a); } From b79a67769cdf4f8340202e9b07e026dc213c6cc6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 13:13:25 +0200 Subject: [PATCH 465/693] lower_alloca: fix --- src/shady/passes/lower_alloca.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 15fe75d5a..6bc231e17 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -48,6 +48,10 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { IrArena* a = vctx->context->rewriter.dst_arena; switch (node->tag) { case StackAlloc_TAG: { + StackSlot* found = find_value_dict(const Node*, StackSlot, vctx->prepared_offsets, node); + if (found) + break; + const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); assert(is_data_type(element_type)); const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, singleton(type_decl_ref_helper(a, vctx->nom_t)), singleton(int32_literal(a, entries_count_list(vctx->members)))); @@ -137,7 +141,7 @@ static const Node* process(Context* ctx, const Node* node) { error_die(); } - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.stack_alloc.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, node->payload.stack_alloc.mem)); if (!ctx->stack_size_on_entry) { //String tmp_name = format_string_arena(a->arena, "stack_ptr_before_alloca_%s", get_abstraction_name(fun)); assert(false); From 0dc0271772f8ae02447143e27f32a71c8e2f20c4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 13:13:43 +0200 Subject: [PATCH 466/693] fix lower_physical_ptrs --- src/shady/passes/lower_physical_ptrs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 2692dcc83..8eb2c8b8c 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -281,11 +281,11 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { gen_serialisation(ctx, bb, element_type, base, address, value_param); - set_abstraction_body(fun, finish_body(bb, fn_ret(a, (Return) { .args = empty(a) }))); + set_abstraction_body(fun, finish_body_with_return(bb, empty(a))); } else { const Node* loaded_value = gen_deserialisation(ctx, bb, element_type, base, address); assert(loaded_value); - set_abstraction_body(fun, finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value) }))); + set_abstraction_body(fun, finish_body_with_return(bb, singleton(loaded_value))); } return fun; } @@ -305,12 +305,12 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, false, ptr_type->payload.ptr_type.address_space); - Nodes r = bind_instruction(bb, call(a, (Call) {.callee = fn_addr_helper(a, fn), .args = singleton(pointer_as_offset)})); - return yield_values_and_wrap_in_block(bb, r); + Nodes results = gen_call(bb, fn_addr_helper(a, fn), singleton(pointer_as_offset)); + return yield_values_and_wrap_in_block(bb, results); } case Store_TAG: { Store payload = old->payload.store; @@ -319,14 +319,14 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, true, ptr_type->payload.ptr_type.address_space); const Node* value = rewrite_node(&ctx->rewriter, payload.value); - bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = mk_nodes(a, pointer_as_offset, value) })); + gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, pointer_as_offset, value)); return yield_values_and_wrap_in_block(bb, empty(a)); } case StackAlloc_TAG: error("This needs to be lowered (see setup_stack_frames.c)") From d6560d9442f19fa88f3e89e3b6f845d4fa03b995 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 13:19:29 +0200 Subject: [PATCH 467/693] restore spirv_lift_globals_ssbo functionality --- src/shady/passes/lower_subgroup_vars.c | 7 +-- src/shady/passes/spirv_lift_globals_ssbo.c | 50 ++++++++++++---------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 499b32887..bd358fb43 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -1,10 +1,9 @@ -#include - #include "shady/pass.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" +#include "dict.h" #include "portability.h" #include "log.h" @@ -15,10 +14,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/shady/passes/spirv_lift_globals_ssbo.c index 9320669a7..7bddf5941 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/shady/passes/spirv_lift_globals_ssbo.c @@ -4,36 +4,44 @@ #include "../transform/ir_gen_helpers.h" #include "../transform/memory_layout.h" +#include "dict.h" #include "portability.h" #include "log.h" typedef struct { Rewriter rewriter; const CompilerConfig* config; - //BodyBuilder* bb; + BodyBuilder* bb; Node* lifted_globals_decl; } Context; static const Node* process(Context* ctx, const Node* node) { - IrArena* a = ctx->rewriter.dst_arena; - - BodyBuilder* abs_bb = NULL; - Context c = *ctx; - ctx = &c; - if (is_abstraction(node)) { - //c.bb = abs_bb = begin_body(a); - } + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { + case Function_TAG: { + Node* newfun = recreate_decl_header_identity(r, node); + Context functx = *ctx; + functx.rewriter.map = clone_dict(functx.rewriter.map); + clear_dict(functx.rewriter.map); + register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); + functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); + Node* post_prelude = basic_block(a, empty(a), "post-prelude"); + register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); + set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); + set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); + destroy_dict(functx.rewriter.map); + return newfun; + } case RefDecl_TAG: { const Node* odecl = node->payload.ref_decl.decl; if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) break; - error("TODO") - /*assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); - const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), int32_literal(a, 0), singleton(rewrite_node(&ctx->rewriter, odecl))); + assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); + const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), int32_literal(a, 0), singleton(rewrite_node(&ctx->rewriter, odecl))); const Node* ptr = gen_load(ctx->bb, ptr_addr); - return ptr;*/ + return ptr; } case GlobalVariable_TAG: if (node->payload.global_variable.address_space != AsGlobal) @@ -42,15 +50,13 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - Node* new = (Node*) recreate_node_identity(&ctx->rewriter, node); - /*if (abs_bb) { - assert(is_abstraction(new)); - if (get_abstraction_body(new)) - set_abstraction_body(new, finish_body(abs_bb, get_abstraction_body(new))); - else - cancel_body(abs_bb); - }*/ - return new; + if (is_declaration(node)) { + Context declctx = *ctx; + declctx.bb = NULL; + return recreate_node_identity(&declctx.rewriter, node); + } + + return recreate_node_identity(&ctx->rewriter, node); } Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Module* src) { From 523888fe17425e4c3a02b58aeff5448ea2359db6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 13:21:58 +0200 Subject: [PATCH 468/693] move spirv passes to the backend --- src/backend/spirv/CMakeLists.txt | 2 ++ src/backend/spirv/emit_spv.c | 3 +++ .../passes => backend/spirv}/spirv_lift_globals_ssbo.c | 6 +++--- .../passes => backend/spirv}/spirv_map_entrypoint_args.c | 6 +++--- src/shady/CMakeLists.txt | 2 -- src/shady/passes/passes.h | 3 --- 6 files changed, 11 insertions(+), 11 deletions(-) rename src/{shady/passes => backend/spirv}/spirv_lift_globals_ssbo.c (97%) rename src/{shady/passes => backend/spirv}/spirv_map_entrypoint_args.c (95%) diff --git a/src/backend/spirv/CMakeLists.txt b/src/backend/spirv/CMakeLists.txt index 2cbe5f975..9b300f7d8 100644 --- a/src/backend/spirv/CMakeLists.txt +++ b/src/backend/spirv/CMakeLists.txt @@ -3,6 +3,8 @@ add_library(shady_spirv STATIC emit_spv_type.c emit_spv_value.c emit_spv_control_flow.c + spirv_lift_globals_ssbo.c + spirv_map_entrypoint_args.c spirv_builder.c ) set_property(TARGET shady_spirv PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 14df22a5f..28912f537 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -316,6 +316,9 @@ SpvId spv_get_extended_instruction_set(Emitter* emitter, const char* name) { return new; } +RewritePass spirv_map_entrypoint_args; +RewritePass spirv_lift_globals_ssbo; + static Module* run_backend_specific_passes(const CompilerConfig* config, Module* initial_mod) { IrArena* initial_arena = initial_mod->arena; Module** pmod = &initial_mod; diff --git a/src/shady/passes/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c similarity index 97% rename from src/shady/passes/spirv_lift_globals_ssbo.c rename to src/backend/spirv/spirv_lift_globals_ssbo.c index 7bddf5941..fc5d5f878 100644 --- a/src/shady/passes/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -1,8 +1,8 @@ #include "shady/pass.h" -#include "../type.h" -#include "../transform/ir_gen_helpers.h" -#include "../transform/memory_layout.h" +#include "../shady/type.h" +#include "../shady/transform/ir_gen_helpers.h" +#include "../shady/transform/memory_layout.h" #include "dict.h" #include "portability.h" diff --git a/src/shady/passes/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c similarity index 95% rename from src/shady/passes/spirv_map_entrypoint_args.c rename to src/backend/spirv/spirv_map_entrypoint_args.c index 3b2bfd7cc..7e6f52532 100644 --- a/src/shady/passes/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -1,8 +1,8 @@ #include "shady/pass.h" -#include "../type.h" -#include "../transform/ir_gen_helpers.h" -#include "../transform/memory_layout.h" +#include "../shady/type.h" +#include "../shady/transform/ir_gen_helpers.h" +#include "../shady/transform/memory_layout.h" #include "portability.h" #include "log.h" diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 4ff0e530d..b3bb14d2d 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -92,8 +92,6 @@ set(SHADY_SOURCES passes/lower_logical_pointers.c passes/lower_entrypoint_args.c - passes/spirv_map_entrypoint_args.c - passes/spirv_lift_globals_ssbo.c ) add_library(shady STATIC ${SHADY_SOURCES}) diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 20a52c5b0..c21c039e0 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -116,9 +116,6 @@ RewritePass lower_switch_btree; RewritePass lower_entrypoint_args; -RewritePass spirv_map_entrypoint_args; -RewritePass spirv_lift_globals_ssbo; - RewritePass specialize_entry_point; RewritePass specialize_execution_model; From 6c3054c00ae56d695156084533ba0da331901ef6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 13:30:15 +0200 Subject: [PATCH 469/693] reorganise shady target sources --- src/shady/CMakeLists.txt | 62 ++++-------------------------- src/shady/analysis/CMakeLists.txt | 11 ++++++ src/shady/passes/CMakeLists.txt | 39 +++++++++++++++++++ src/shady/passes/passes.h | 10 +---- src/shady/transform/CMakeLists.txt | 5 +++ 5 files changed, 64 insertions(+), 63 deletions(-) create mode 100644 src/shady/analysis/CMakeLists.txt create mode 100644 src/shady/passes/CMakeLists.txt create mode 100644 src/shady/transform/CMakeLists.txt diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index b3bb14d2d..ead1d19c0 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -21,7 +21,9 @@ add_dependencies(shady_generated node_generated primops_generated type_generated target_include_directories(shady_generated INTERFACE "$") target_link_libraries(api INTERFACE "$") -set(SHADY_SOURCES +add_library(shady STATIC) + +target_sources(shady PRIVATE ir.c node.c node_helpers.c @@ -39,62 +41,12 @@ set(SHADY_SOURCES annotation.c module.c config.c - - analysis/cfg.c - analysis/cfg_dump.c - analysis/free_variables.c - analysis/verify.c - analysis/callgraph.c - analysis/uses.c - analysis/looptree.c - analysis/leak.c - analysis/scheduler.c - - transform/memory_layout.c - transform/ir_gen_helpers.c - transform/internal_constants.c - - passes/import.c - passes/cleanup.c - passes/lower_cf_instrs.c - passes/lift_indirect_targets.c - passes/lower_callf.c - passes/lower_alloca.c - passes/lower_stack.c - passes/lower_lea.c - passes/lower_physical_ptrs.c - passes/lower_generic_ptrs.c - passes/lower_memory_layout.c - passes/lower_memcpy.c - passes/lower_decay_ptrs.c - passes/lower_tailcalls.c - passes/lower_mask.c - passes/lower_fill.c - passes/lower_nullptr.c - passes/lower_switch_btree.c - passes/setup_stack_frames.c - passes/eliminate_constants.c - passes/normalize_builtins.c - passes/lower_subgroup_ops.c - passes/lower_subgroup_vars.c - passes/lower_int64.c - passes/lower_vec_arr.c - passes/lower_workgroups.c - passes/lower_generic_globals.c - passes/mark_leaf_functions.c - passes/opt_inline.c - passes/opt_restructure.c - passes/opt_demote_alloca.c - passes/reconvergence_heuristics.c - passes/simt2d.c - passes/specialize_entry_point.c - passes/specialize_execution_model.c - passes/lower_logical_pointers.c - - passes/lower_entrypoint_args.c ) -add_library(shady STATIC ${SHADY_SOURCES}) +add_subdirectory(analysis) +add_subdirectory(transform) +add_subdirectory(passes) + target_include_directories(shady PUBLIC $) if (WIN32) diff --git a/src/shady/analysis/CMakeLists.txt b/src/shady/analysis/CMakeLists.txt new file mode 100644 index 000000000..a29b92264 --- /dev/null +++ b/src/shady/analysis/CMakeLists.txt @@ -0,0 +1,11 @@ +target_sources(shady PRIVATE + cfg.c + cfg_dump.c + free_variables.c + verify.c + callgraph.c + uses.c + looptree.c + leak.c + scheduler.c +) diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt new file mode 100644 index 000000000..d786a3c7e --- /dev/null +++ b/src/shady/passes/CMakeLists.txt @@ -0,0 +1,39 @@ +target_sources(shady PRIVATE + import.c + cleanup.c + lower_cf_instrs.c + lift_indirect_targets.c + lower_callf.c + lower_alloca.c + lower_stack.c + lower_lea.c + lower_physical_ptrs.c + lower_generic_ptrs.c + lower_memory_layout.c + lower_memcpy.c + lower_decay_ptrs.c + lower_tailcalls.c + lower_mask.c + lower_fill.c + lower_nullptr.c + lower_switch_btree.c + setup_stack_frames.c + eliminate_constants.c + normalize_builtins.c + lower_subgroup_ops.c + lower_subgroup_vars.c + lower_int64.c + lower_vec_arr.c + lower_workgroups.c + lower_generic_globals.c + mark_leaf_functions.c + opt_inline.c + opt_restructure.c + opt_demote_alloca.c + reconvergence_heuristics.c + simt2d.c + specialize_entry_point.c + specialize_execution_model.c + lower_logical_pointers.c + lower_entrypoint_args.c +) diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index c21c039e0..d3ca4ae2b 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -16,6 +16,8 @@ RewritePass cleanup; /// Gets rid of structured control flow constructs, and turns them into branches, joins and tailcalls RewritePass lower_cf_instrs; +/// Try to identify reconvergence points throughout the program for unstructured control flow programs +RewritePass reconvergence_heuristics; /// @} @@ -24,11 +26,6 @@ RewritePass lower_cf_instrs; /// Extracts unstructured basic blocks into separate functions (including spilling) RewritePass lift_indirect_targets; -/// Emulates uniform jumps within functions using a loop -RewritePass lower_jumps_loop; -/// Emulates uniform jumps within functions by applying a structuring transformation -RewritePass lower_jumps_structure; -RewritePass lcssa; RewritePass normalize_builtins; /// @} @@ -107,9 +104,6 @@ RewritePass mark_leaf_functions; RewritePass opt_inline; RewritePass opt_mem2reg; -/// Try to identify reconvergence points throughout the program for unstructured control flow programs -RewritePass reconvergence_heuristics; - RewritePass opt_stack; RewritePass opt_restructurize; RewritePass lower_switch_btree; diff --git a/src/shady/transform/CMakeLists.txt b/src/shady/transform/CMakeLists.txt new file mode 100644 index 000000000..2cd22ba9f --- /dev/null +++ b/src/shady/transform/CMakeLists.txt @@ -0,0 +1,5 @@ +target_sources(shady PRIVATE + internal_constants.c + ir_gen_helpers.c + memory_layout.c +) From 383c26245c2f8feb9eacd28497cfa820b236b5dc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 13:31:45 +0200 Subject: [PATCH 470/693] removed unfinished simt2d pass --- include/shady/config.h | 1 - src/backend/c/emit_c.c | 3 - src/driver/cli.c | 1 - src/shady/compile.c | 2 - src/shady/passes/CMakeLists.txt | 1 - src/shady/passes/passes.h | 2 - src/shady/passes/simt2d.c | 100 -------------------------------- 7 files changed, 110 deletions(-) delete mode 100644 src/shady/passes/simt2d.c diff --git a/include/shady/config.h b/include/shady/config.h index eae39cb47..cf245efc0 100644 --- a/include/shady/config.h +++ b/include/shady/config.h @@ -71,7 +71,6 @@ struct CompilerConfig_ { bool emulate_subgroup_ops; bool emulate_subgroup_ops_extended_types; - bool simt_to_explicit_simd; bool int64; bool decay_ptrs; } lower; diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 3b5282112..7174717e9 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -392,9 +392,6 @@ static Module* run_backend_specific_passes(const CompilerConfig* config, CEmitte if (econfig->dialect != CDialect_GLSL) { RUN_PASS(lower_vec_arr) } - if (config->lower.simt_to_explicit_simd) { - RUN_PASS(simt2d) - } return *pmod; } diff --git a/src/driver/cli.c b/src/driver/cli.c index 8d0998c69..3adebef91 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -90,7 +90,6 @@ F(config->hacks.force_join_point_lifting, lift-join-points) \ F(config->logging.print_internal, print-internal) \ F(config->logging.print_generated, print-builtin) \ F(config->logging.print_generated, print-generated) \ -F(config->lower.simt_to_explicit_simd, lower-simt-to-simd) \ F(config->optimisations.inline_everything, inline-everything) \ F(config->hacks.restructure_everything, restructure-everything) \ F(config->hacks.recover_structure, recover-structure) \ diff --git a/src/shady/compile.c b/src/shady/compile.c index b6229a8b8..c737e352c 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -102,8 +102,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_int) - if (config->lower.simt_to_explicit_simd) - RUN_PASS(simt2d) RUN_PASS(lower_fill) RUN_PASS(lower_nullptr) RUN_PASS(normalize_builtins) diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index d786a3c7e..0efd2349c 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -31,7 +31,6 @@ target_sources(shady PRIVATE opt_restructure.c opt_demote_alloca.c reconvergence_heuristics.c - simt2d.c specialize_entry_point.c specialize_execution_model.c lower_logical_pointers.c diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index d3ca4ae2b..80bd779ae 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -37,8 +37,6 @@ RewritePass normalize_builtins; RewritePass lower_callf; /// Emulates tailcalls, forks and joins using a god function RewritePass lower_tailcalls; -/// Turns SIMT code back into SIMD (intended for debugging with the help of the C backend) -RewritePass simt2d; /// @} diff --git a/src/shady/passes/simt2d.c b/src/shady/passes/simt2d.c deleted file mode 100644 index 0202a338e..000000000 --- a/src/shady/passes/simt2d.c +++ /dev/null @@ -1,100 +0,0 @@ -#include "shady/pass.h" - -#include "../type.h" - -#include "portability.h" -#include "log.h" - -typedef struct { - Rewriter rewriter; - size_t width; - const Node* mask; -} Context; - -static const Node* widen(Context* ctx, const Node* value) { - IrArena* a = ctx->rewriter.dst_arena; - LARRAY(const Node*, copies, ctx->width); - for (size_t j = 0; j < ctx->width; j++) - copies[j] = value; - const Type* type = pack_type(a, (PackType) { .width = ctx->width, .element_type = get_unqualified_type(value->type)}); - return composite_helper(a, type, nodes(a, ctx->width, copies)); -} - -static const Node* process(Context* ctx, const Node* node) { - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - - Rewriter* r = &ctx->rewriter; - IrArena* a = r->dst_arena; - switch (node->tag) { - case QualifiedType_TAG: { - if (!node->payload.qualified_type.is_uniform) return qualified_type(a, (QualifiedType) { - .is_uniform = true, - .type = pack_type(a, (PackType) { .width = ctx->width, .element_type = rewrite_node(&ctx->rewriter, node->payload.qualified_type.type )}) - }); - goto rewrite; - } - case LocalAlloc_TAG: { - LocalAlloc payload = node->payload.local_alloc; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - const Node* type = rewrite_node(&ctx->rewriter, node->payload.local_alloc.type); - LARRAY(const Node*, allocated, ctx->width); - for (size_t i = 0; i < ctx->width; i++) { - allocated[i] = first(bind_instruction_named(bb, local_alloc(a, (LocalAlloc) { .type = type, .mem = bb_mem(bb) }), (String[]) {"allocated"})); - } - //return yield_values_and_wrap_in_control(bb, singleton(widen(ctx, allocated))); - const Node* result_type = maybe_packed_type_helper(ptr_type(a, (PtrType) { .address_space = AsFunction, .pointed_type = type }), ctx->width); - const Node* packed = composite_helper(a, result_type, nodes(a, ctx->width, allocated)); - return yield_values_and_wrap_in_block(bb, singleton(packed)); - } - case PrimOp_TAG: { - Op op = node->payload.prim_op.op; - switch (op) { - default: break; - } - - bool was_uniform = true; - Nodes old_operands = node->payload.prim_op.operands; - for (size_t i = 0; i < old_operands.count; i++) - was_uniform &= is_qualified_type_uniform(old_operands.nodes[i]->type); - Nodes new_type_arguments = rewrite_nodes(&ctx->rewriter, node->payload.prim_op.type_arguments); - - LARRAY(const Node*, new_operands, old_operands.count); - // Nodes new_operands = rewrite_nodes(&ctx->rewriter, node->payload.prim_op.operands); - for (size_t i = 0; i < old_operands.count; i++) { - const Node* old_operand = old_operands.nodes[i]; - const Type* old_operand_type = old_operand->type; - bool op_was_uniform = deconstruct_qualified_type(&old_operand_type); - // assert(was_uniform || !op_was_uniform && "result was uniform implies=> operand was uniform"); - new_operands[i] = rewrite_node(&ctx->rewriter, old_operand); - if (op_was_uniform) - new_operands[i] = widen(ctx, new_operands[i]); - } - return prim_op(a, (PrimOp) { - .op = op, - .type_arguments = new_type_arguments, - .operands = nodes(a, old_operands.count, new_operands) - }); - } - rewrite: - default: return recreate_node_identity(&ctx->rewriter, node); - } -} - -Module* simt2d(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - aconfig.is_simt = false; - IrArena* a = new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); - - Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .width = config->specialization.subgroup_size, - .mask = NULL, - }; - - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); - return dst; -} From 3e9c315a7fe28765fdc6df52493703f3f2ee5929 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 13:44:43 +0200 Subject: [PATCH 471/693] spv: handle the fact some things cannot be emitted at top level --- src/backend/spirv/emit_spv_value.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 8387d8295..81a27636a 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -371,7 +371,10 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui case Instruction_ExtInstr_TAG: return emit_ext_instr(emitter, fn_builder, bb_builder, instruction->payload.ext_instr); case Instruction_Call_TAG: return emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call); case PrimOp_TAG: return emit_primop(emitter, fn_builder, bb_builder, instruction); - case Comment_TAG: break; + case Comment_TAG: { + spv_emit_mem(emitter, fn_builder, instruction->payload.comment.mem); + return 0; + } case Instruction_LocalAlloc_TAG: { LocalAlloc payload = instruction->payload.local_alloc; spv_emit_mem(emitter, fn_builder, payload.mem); @@ -454,6 +457,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui return 0; } } + SHADY_UNREACHABLE; } static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* node) { @@ -562,6 +566,12 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder return new; } +static bool can_appear_at_top_level(const Node* node) { + if (is_instruction(node)) + return false; + return true; +} + SpvId spv_emit_value(Emitter* emitter, FnBuilder* fn_builder, const Node* node) { SpvId* existing = spv_search_emitted(emitter, fn_builder, node); if (existing) @@ -573,6 +583,17 @@ SpvId spv_emit_value(Emitter* emitter, FnBuilder* fn_builder, const Node* node) SpvId emitted = spv_emit_value_(emitter, fn_builder, bb_builder, node); spv_register_emitted(emitter, fn_builder, node, emitted); return emitted; + } else if (!can_appear_at_top_level(node)) { + if (!fn_builder) { + log_node(ERROR, node); + log_string(ERROR, "cannot appear at top-level"); + exit(-1); + } + // Pick the entry block of the current fn + BBBuilder bb_builder = spv_find_basic_block_builder(emitter, fn_builder->cfg->entry->node); + SpvId emitted = spv_emit_value_(emitter, fn_builder, bb_builder, node); + spv_register_emitted(emitter, fn_builder, node, emitted); + return emitted; } else { assert(!is_mem(node)); SpvId emitted = spv_emit_value_(emitter, NULL, NULL, node); From f172575ccf457a221f67c2598c569d5679464f5c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 16:03:15 +0200 Subject: [PATCH 472/693] body_builder: handle blocks with non-trivial control flow --- src/shady/body_builder.c | 26 ++++++++++++++------------ src/shady/ir_private.h | 3 ++- src/shady/node.c | 6 +++--- test/test_builder.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 1eb66166d..7d21f7366 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -35,7 +35,8 @@ BodyBuilder* begin_body_with_mem(IrArena* a, const Node* mem) { BodyBuilder* begin_block_with_side_effects(IrArena* a, const Node* mem) { Node* block = basic_block(a, empty(a), NULL); BodyBuilder* builder = begin_body_with_mem(a, get_abstraction_mem(block)); - builder->bb = block; + builder->tail_block = block; + builder->block_entry_block = block; builder->block_entry_mem = mem; return builder; } @@ -127,14 +128,6 @@ const Node* finish_body(BodyBuilder* bb, const Node* terminator) { return terminator; } -const Node* finish_block_body(BodyBuilder* bb, const Node* terminator) { - assert(bb->block_entry_mem); - terminator = build_body(bb, terminator); - destroy_list(bb->stack); - free(bb); - return terminator; -} - const Node* finish_body_with_return(BodyBuilder* bb, Nodes args) { return finish_body(bb, fn_ret(bb->arena, (Return) { .args = args, @@ -171,7 +164,7 @@ const Node* finish_body_with_loop_break(BodyBuilder* bb, Nodes args) { const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { IrArena* a = bb->arena; - if (!bb->bb && entries_count_list(bb->stack) == 0) { + if (!bb->tail_block && entries_count_list(bb->stack) == 0) { const Node* last_mem = bb_mem(bb); cancel_body(bb); if (last_mem) @@ -181,8 +174,8 @@ const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { }); return value; } - assert(bb->bb && "This builder wasn't started with 'begin_block'"); - bb->bb->payload.basic_block.insert = bb; + assert(bb->block_entry_mem && "This builder wasn't started with 'begin_block'"); + bb->tail_block->payload.basic_block.insert = bb; const Node* r = mem_and_value(bb->arena, (MemAndValue) { .mem = bb_mem(bb), .value = value @@ -194,6 +187,14 @@ const Node* yield_values_and_wrap_in_block(BodyBuilder* bb, Nodes values) { return yield_value_and_wrap_in_block(bb, maybe_tuple_helper(bb->arena, values)); } +const Node* finish_block_body(BodyBuilder* bb, const Node* terminator) { + assert(bb->block_entry_mem); + terminator = build_body(bb, terminator); + destroy_list(bb->stack); + free(bb); + return terminator; +} + const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* instruction) { size_t stack_size = entries_count_list(bb->stack); if (stack_size == 0) { @@ -254,6 +255,7 @@ Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constru } bb->mem = get_abstraction_mem(tail); append_list(StackEntry , bb->stack, entry); + bb->tail_block = tail; return entry.vars; } diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index c983bc291..0c1e3dbcd 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -37,9 +37,10 @@ void destroy_module(Module* m); struct BodyBuilder_ { IrArena* arena; struct List* stack; + const Node* block_entry_block; const Node* block_entry_mem; const Node* mem; - Node* bb; + Node* tail_block; }; NodeId allocate_node_id(IrArena*, const Node* n); diff --git a/src/shady/node.c b/src/shady/node.c index d19d2c8aa..ef74280ed 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -309,13 +309,13 @@ void set_abstraction_body(Node* abs, const Node* body) { while (true) { const Node* mem0 = get_original_mem(get_terminator_mem(body)); assert(mem0->tag == AbsMem_TAG); - const Node* mem_abs = mem0->payload.abs_mem.abs; + Node* mem_abs = mem0->payload.abs_mem.abs; if (is_basic_block(mem_abs)) { BodyBuilder* insert = mem_abs->payload.basic_block.insert; if (insert && mem_abs != abs) { const Node* mem = insert->block_entry_mem; - set_abstraction_body((Node*) mem_abs, finish_block_body(insert, body)); - body = jump_helper(a, mem_abs, empty(a), mem); + set_abstraction_body((Node*) insert->block_entry_block, finish_block_body(insert, body)); + body = jump_helper(a, insert->block_entry_block, empty(a), mem); continue; } assert(mem_abs == abs); diff --git a/test/test_builder.c b/test/test_builder.c index 4c87831b2..4b88dc584 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -114,6 +114,39 @@ static void test_body_builder_impure_block(IrArena* a) { CHECK(found_store, exit(-1)); } +/// There is some "magic" code in body_builder and set_abstraction_body to enable inserting control-flow +/// where there is only a mem dependency. This is useful when writing some complex polyfills. +static void test_body_builder_impure_block_with_control_flow(IrArena* a) { + Module* m = new_module(a, "test_module"); + const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = uint32_type(a), + }), false), NULL); + Node* fun = function(m, mk_nodes(a, p1), "fun", empty(a), empty(a)); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + + const Node* first_load = gen_load(bb, p1); + + BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); + Node* if_true_case = case_(a, empty(a)); + BodyBuilder* if_true_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); + gen_store(if_true_builder, p1, uint32_literal(a, 0)); + set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_true_builder, empty(a))); + gen_if(block_builder, empty(a), gen_primop_e(block_builder, neq_op, empty(a), mk_nodes(a, first_load, uint32_literal(a, 0))), if_true_case, NULL); + bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, empty(a))); + + const Node* second_load = gen_load(bb, p1); + + const Node* sum = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, first_load, second_load)); + const Node* return_terminator = fn_ret(a, (Return) { + .mem = bb_mem(bb), + .args = singleton(sum) + }); + set_abstraction_body(fun, finish_body(bb, return_terminator)); + + dump_module(m); +} + int main(int argc, char** argv) { cli_parse_common_args(&argc, argv); @@ -123,5 +156,6 @@ int main(int argc, char** argv) { test_body_builder_constants(a); test_body_builder_fun_body(a); test_body_builder_impure_block(a); + test_body_builder_impure_block_with_control_flow(a); destroy_ir_arena(a); } From 2d0495596d4f1daf46473db2bfe34ffb768db606 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 16:03:42 +0200 Subject: [PATCH 473/693] fixed inlining --- src/shady/compile.c | 7 ++++--- src/shady/passes/opt_inline.c | 12 +++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index c737e352c..c9c15ea95 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -43,10 +43,11 @@ void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { IrArena* initial_arena = (*pmod)->arena; - + + // we don't want to mess with the original module + *pmod = import(config, *pmod); + if (config->dynamic_scheduling) { - *pmod = import(config, *pmod); // we don't want to mess with the original module - add_scheduler_source(config, *pmod); } diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index a9c491a02..c61f32b86 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -103,7 +103,7 @@ static FnInliningCriteria get_inlining_heuristic(const CompilerConfig* config, C } /// inlines the abstraction with supplied arguments -static const Node* inline_call(Context* ctx, const Node* ocallee, Nodes nargs, const Node* return_to) { +static const Node* inline_call(Context* ctx, const Node* ocallee, const Node* nmem, Nodes nargs, const Node* return_to) { assert(is_abstraction(ocallee)); log_string(DEBUG, "Inlining '%s' inside '%s'\n", get_abstraction_name(ocallee), get_abstraction_name(ctx->fun)); @@ -119,6 +119,7 @@ static const Node* inline_call(Context* ctx, const Node* ocallee, Nodes nargs, c Nodes oparams = get_abstraction_params(ocallee); register_processed_list(&inline_context.rewriter, oparams, nargs); + register_processed(&inline_context.rewriter, get_abstraction_mem(ocallee), nmem); const Node* nbody = rewrite_node(&inline_context.rewriter, get_abstraction_body(ocallee)); @@ -183,11 +184,11 @@ static const Node* process(Context* ctx, const Node* node) { const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); const Node* join_point = param(a, qualified_type_helper(jp_type, true), format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); - const Node* nbody = inline_call(ctx, ocallee, nargs, join_point); Node* control_case = case_(a, singleton(join_point)); + const Node* nbody = inline_call(ctx, ocallee, get_abstraction_mem(control_case), nargs, join_point); set_abstraction_body(control_case, nbody); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, control_case)); } } @@ -202,8 +203,9 @@ static const Node* process(Context* ctx, const Node* node) { return bb; }*/ case Return_TAG: { + Return payload = node->payload.fn_ret; if (ctx->inlined_call) - return join(a, (Join) { .join_point = ctx->inlined_call->return_jp, .args = rewrite_nodes(r, node->payload.fn_ret.args )}); + return join(a, (Join) { .mem = rewrite_node(r, payload.mem), .join_point = ctx->inlined_call->return_jp, .args = rewrite_nodes(r, payload.args )}); break; } case TailCall_TAG: { @@ -216,7 +218,7 @@ static const Node* process(Context* ctx, const Node* node) { if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined) { debugv_print("Inlining tail call to %s\n", get_abstraction_name(ocallee)); Nodes nargs = rewrite_nodes(&ctx->rewriter, node->payload.tail_call.args); - return inline_call(ctx, ocallee, nargs, NULL); + return inline_call(ctx, ocallee, rewrite_node(r, node->payload.tail_call.mem), nargs, NULL); } } break; From 31b342894ec2f89aa3c045e6c5118674de96b13a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 16:45:18 +0200 Subject: [PATCH 474/693] misc. fixes --- src/frontend/slim/bind.c | 6 ++++-- src/frontend/slim/infer.c | 1 + src/shady/node.c | 28 +++++++++++++++------------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 2442cd00b..850ebaef9 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -188,8 +188,10 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { } register_processed_list(&ctx->rewriter, decl->payload.fun.params, new_fn_params); - fn_ctx.current_function = bound; - set_abstraction_body(bound, rewrite_node(&fn_ctx.rewriter, decl->payload.fun.body)); + if (decl->payload.fun.body) { + fn_ctx.current_function = bound; + set_abstraction_body(bound, rewrite_node(&fn_ctx.rewriter, decl->payload.fun.body)); + } return bound; } case NominalType_TAG: { diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 4bf750ca1..b5ac1a186 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -504,6 +504,7 @@ static const Node* infer_control(Context* ctx, const Node* node) { register_processed(&joinable_ctx.rewriter, ojp, jp); Node* new_case = basic_block(a, singleton(jp), NULL); + register_processed(&joinable_ctx.rewriter, olam, new_case); set_abstraction_body(new_case, infer(&joinable_ctx, get_abstraction_body(olam), NULL)); return control(a, (Control) { diff --git a/src/shady/node.c b/src/shady/node.c index ef74280ed..64a066b43 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -306,21 +306,23 @@ void set_abstraction_body(Node* abs, const Node* body) { assert(!body || is_terminator(body)); IrArena* a = abs->arena; - while (true) { - const Node* mem0 = get_original_mem(get_terminator_mem(body)); - assert(mem0->tag == AbsMem_TAG); - Node* mem_abs = mem0->payload.abs_mem.abs; - if (is_basic_block(mem_abs)) { - BodyBuilder* insert = mem_abs->payload.basic_block.insert; - if (insert && mem_abs != abs) { - const Node* mem = insert->block_entry_mem; - set_abstraction_body((Node*) insert->block_entry_block, finish_block_body(insert, body)); - body = jump_helper(a, insert->block_entry_block, empty(a), mem); - continue; + if (body) { + while (true) { + const Node* mem0 = get_original_mem(get_terminator_mem(body)); + assert(mem0->tag == AbsMem_TAG); + Node* mem_abs = mem0->payload.abs_mem.abs; + if (is_basic_block(mem_abs)) { + BodyBuilder* insert = mem_abs->payload.basic_block.insert; + if (insert && mem_abs != abs) { + const Node* mem = insert->block_entry_mem; + set_abstraction_body((Node*) insert->block_entry_block, finish_block_body(insert, body)); + body = jump_helper(a, insert->block_entry_block, empty(a), mem); + continue; + } + assert(mem_abs == abs); } - assert(mem_abs == abs); + break; } - break; } switch (abs->tag) { From 0c229e5ac220b651c525c2cdf8200e3b774ec267 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 16:54:06 +0200 Subject: [PATCH 475/693] fix lower_generic_ptrs --- src/shady/passes/lower_generic_ptrs.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index cf1517d7a..30bd91dc6 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -108,13 +108,11 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo set_abstraction_body(cases[tag], unreachable(a, (Unreachable) { .mem = get_abstraction_mem(cases[tag]) })); continue; } + cases[tag] = case_(a, empty(a)); BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(cases[tag])); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); - cases[tag] = case_(a, empty(a)); - set_abstraction_body(cases[tag], finish_body(case_bb, merge_selection(a, (MergeSelection) { - .args = singleton(loaded_value), - }))); + set_abstraction_body(cases[tag], finish_body_with_selection_merge(case_bb, singleton(loaded_value))); } BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); @@ -138,13 +136,11 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo set_abstraction_body(cases[tag], unreachable(a, (Unreachable) { .mem = get_abstraction_mem(cases[tag]) })); continue; } + cases[tag] = case_(a, empty(a)); BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(cases[tag])); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); - cases[tag] = case_(a, empty(a)); - set_abstraction_body(cases[tag], finish_body(case_bb, merge_selection(a, (MergeSelection) { - .args = empty(a), - }))); + set_abstraction_body(cases[tag], finish_body_with_selection_merge(case_bb, empty(a))); } BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); @@ -184,14 +180,15 @@ static const Node* process(Context* ctx, const Node* old) { break; } case Load_TAG: { - const Node* old_ptr = old->payload.load.ptr; - const Type* old_ptr_t = old_ptr->type; + Load payload = old->payload.load; + const Type* old_ptr_t = payload.ptr->type; bool u = deconstruct_qualified_type(&old_ptr_t); u &= is_addr_space_uniform(a, old_ptr_t->payload.ptr_type.address_space); if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { return call(a, (Call) { .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, u, rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), - .args = singleton(rewrite_node(&ctx->rewriter, old_ptr)), + .args = singleton(rewrite_node(&ctx->rewriter, payload.ptr)), + .mem = rewrite_node(r, payload.mem) }); } break; @@ -204,6 +201,7 @@ static const Node* process(Context* ctx, const Node* old) { return call(a, (Call) { .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, StoreFn, false, rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), .args = mk_nodes(a, rewrite_node(r, payload.ptr), rewrite_node(r, payload.value)), + .mem = rewrite_node(r, payload.mem), }); } break; @@ -220,8 +218,9 @@ static const Node* process(Context* ctx, const Node* old) { AddressSpace src_as = old_src_t->payload.ptr_type.address_space; size_t tag = get_tag_for_addr_space(src_as); BodyBuilder* bb = begin_block_pure(a); - String x = format_string_arena(a->arena, "Generated generic ptr convert src %d tag %d", src_as, tag); - gen_comment(bb, x); + // TODO: find another way to annotate this ? + // String x = format_string_arena(a->arena, "Generated generic ptr convert src %d tag %d", src_as, tag); + // gen_comment(bb, x); const Node* src_ptr = rewrite_node(&ctx->rewriter, old_src); const Node* generic_ptr = gen_reinterpret_cast(bb, ctx->generic_ptr_type, src_ptr); const Node* ptr_mask = size_t_literal(a, (UINT64_MAX >> (uint64_t) (generic_ptr_tag_bitwidth))); From 1c2c91c3903c4fa0dc34301f5e6fd2d4f492a16f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 17:06:44 +0200 Subject: [PATCH 476/693] fix grammar.json grammar --- include/shady/grammar.json | 2 +- test/basic_blocks2.slim | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 test/basic_blocks2.slim diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 36e2faf98..0449cab97 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -381,7 +381,7 @@ "ops": [ { "name": "mem", "class": "mem" }, { "name": "callee", "class": "value" }, - { "name": "args", "class": "value", "list": true }, + { "name": "args", "class": "value", "list": true } ] }, { diff --git a/test/basic_blocks2.slim b/test/basic_blocks2.slim new file mode 100644 index 000000000..f4efe670a --- /dev/null +++ b/test/basic_blocks2.slim @@ -0,0 +1,8 @@ +@EntryPoint("Compute") @WorkgroupSize(64, 1, 1) +fn main() { + jump bb1(7); + + cont bb1(varying i32 n) { + return (); + } +} From 3f7bbaa397b3daaa95151eaeb0a7168e962c0e91 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 17:41:12 +0200 Subject: [PATCH 477/693] moved name binding nodes to ExtInstr --- include/shady/fe/slim.h | 4 + include/shady/grammar.json | 25 ------ src/backend/c/emit_c_value.c | 1 - src/backend/spirv/emit_spv_value.c | 1 - src/frontend/slim/bind.c | 122 ++++++++++++++++++---------- src/frontend/slim/parser.c | 53 +++++++----- src/shady/analysis/free_variables.c | 2 +- src/shady/body_builder.c | 2 +- src/shady/constructors.c | 20 ----- src/shady/node_helpers.c | 6 -- src/shady/print.c | 4 - test/CMakeLists.txt | 1 + test/basic_blocks2.slim | 4 + 13 files changed, 123 insertions(+), 122 deletions(-) diff --git a/include/shady/fe/slim.h b/include/shady/fe/slim.h index 856f09c6f..01cae7e5e 100644 --- a/include/shady/fe/slim.h +++ b/include/shady/fe/slim.h @@ -6,6 +6,10 @@ typedef enum { SlimOpAssign, SlimOpAddrOf, SlimOpSubscript, + SlimOpBindVal, + SlimOpBindVar, + SlimOpBindContinuations, + SlimOpUnbound, } SlimFrontEndOpCodes; #endif diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 0449cab97..25a5515ac 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -450,20 +450,6 @@ { "name": "string", "class": "string" } ] }, - { - "name": "BindIdentifiers", - "class": ["instruction", "mem"], - "constructor": "custom", - "front-end-only": true, - "type": false, - "ops": [ - { "name": "mem", "class": "mem" }, - { "name": "value", "class": "value" }, - { "name": "mutable", "type": "bool" }, - { "name": "names", "class": "string", "list": true }, - { "name": "types", "class": "type", "list": true } - ] - }, { "name": "TailCall", "class": "terminator", @@ -680,17 +666,6 @@ { "name": "abs", "class": "abstraction" } ] }, - { - "name": "Unbound", - "description": "Unbound identifier, obtained by parsing a file", - "type": false, - "front-end-only": true, - "class": ["value", "mem"], - "ops": [ - { "name": "mem", "class": "mem", "nullable": true }, - { "name": "name", "type": "String" } - ] - }, { "name": "ExtInstr", "description": "Turns a pointer into an assignable L-value", diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 70e5762e5..8cf833a5a 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -877,7 +877,6 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { case Instruction_GetStackSize_TAG: case Instruction_SetStackSize_TAG: case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); - case Instruction_BindIdentifiers_TAG: error("front-end only!"); case Instruction_ExtInstr_TAG: return emit_ext_instruction(emitter, p, instruction->payload.ext_instr); case Instruction_PrimOp_TAG: return emit_primop(emitter, p, instruction); case Instruction_Call_TAG: return emit_call(emitter, p, instruction); diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 81a27636a..7e7ad2f6e 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -366,7 +366,6 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); case Instruction_CopyBytes_TAG: case Instruction_FillBytes_TAG: - case Instruction_BindIdentifiers_TAG: case Instruction_StackAlloc_TAG: error("Should be lowered elsewhere") case Instruction_ExtInstr_TAG: return emit_ext_instr(emitter, fn_builder, bb_builder, instruction->payload.ext_instr); case Instruction_Call_TAG: return emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call); diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 850ebaef9..6301a2a6d 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -88,15 +88,6 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; switch (node->tag) { - case Unbound_TAG: { - if (node->payload.unbound.mem) - rewrite_node(&ctx->rewriter, node->payload.unbound.mem); - Resolved entry = resolve_using_name(ctx, node->payload.unbound.name); - // can't take the address if it's not a var! - if (!entry.is_var) - return NULL; - return entry.node; - } case ExtInstr_TAG: { ExtInstr payload = node->payload.ext_instr; if (strcmp(payload.set, "shady.frontend") == 0) { @@ -116,6 +107,14 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { .mem = rewrite_node(r, payload.mem), .value = rewrite_node(&ctx->rewriter, first(payload.operands)), }); + } else if (payload.opcode == SlimOpUnbound) { + if (payload.mem) + rewrite_node(&ctx->rewriter, payload.mem); + Resolved entry = resolve_using_name(ctx, get_string_literal(a, first(payload.operands))); + // can't take the address if it's not a var! + if (!entry.is_var) + return NULL; + return entry.node; } } break; @@ -131,30 +130,69 @@ static const Node* get_node_address(Context* ctx, const Node* node) { return got; } -static const Node* desugar_bind_identifiers(Context* ctx, const Node* node) { - assert(node->tag == BindIdentifiers_TAG); +static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.bind_identifiers.mem)); - const Node* ninstruction = rewrite_node(r, node->payload.bind_identifiers.value); + BodyBuilder* bb = instr.mem ? begin_body_with_mem(a, rewrite_node(r, instr.mem)) : begin_block_pure(a); - Strings names = node->payload.bind_identifiers.names; - Nodes results = deconstruct_composite(a, bb, ninstruction, names.count); - for (size_t i = 0; i < names.count; i++) { - String name = names.strings[i]; - if (node->payload.bind_identifiers.mutable) { - const Type* type_annotation = node->payload.bind_identifiers.types.nodes[i]; - assert(type_annotation); - const Node* alloca = stack_alloc(a, (StackAlloc) { .type = rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); - const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; - set_value_name(ptr, names.strings[i]); - bind_instruction_outputs_count(bb, store(a, (Store) { .ptr = ptr, .value = results.nodes[0], .mem = bb_mem(bb) }), 0); + switch (instr.opcode) { + case SlimOpBindVal: { + size_t names_count = instr.operands.count - 1; + const Node** names = &instr.operands.nodes[1]; + const Node* value = rewrite_node(r, first(instr.operands)); + Nodes results = deconstruct_composite(a, bb, value, names_count); + for (size_t i = 0; i < names_count; i++) { + String name = get_string_literal(a, names[i]); + log_string(DEBUGV, "Bound immutable variable '%s'\n", name); + add_binding(ctx, false, name, results.nodes[i]); + } + break; + } + case SlimOpBindVar: { + size_t names_count = (instr.operands.count - 1) / 2; + const Node** names = &instr.operands.nodes[1]; + const Node** types = &instr.operands.nodes[1 + names_count]; + const Node* value = rewrite_node(r, first(instr.operands)); + Nodes results = deconstruct_composite(a, bb, value, names_count); + for (size_t i = 0; i < names_count; i++) { + String name = get_string_literal(a, names[i]); + const Type* type_annotation = types[i]; + assert(type_annotation); + const Node* alloca = stack_alloc(a, (StackAlloc) { .type = rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); + const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; + set_value_name(ptr, name); + bind_instruction_outputs_count(bb, store(a, (Store) { .ptr = ptr, .value = results.nodes[0], .mem = bb_mem(bb) }), 0); - add_binding(ctx, true, name, ptr); - log_string(DEBUGV, "Bound mutable variable '%s'\n", name); - } else { - log_string(DEBUGV, "Bound immutable variable '%s'\n", name); - add_binding(ctx, false, name, results.nodes[i]); + add_binding(ctx, true, name, ptr); + log_string(DEBUGV, "Bound mutable variable '%s'\n", name); + } + break; + } + case SlimOpBindContinuations: { + size_t names_count = (instr.operands.count ) / 2; + const Node** names = &instr.operands.nodes[0]; + const Node** conts = &instr.operands.nodes[0 + names_count]; + LARRAY(Node*, bbs, names_count); + for (size_t i = 0; i < names_count; i++) { + String name = get_string_literal(a, names[i]); + Nodes nparams = recreate_params(r, get_abstraction_params(conts[i])); + bbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(conts[i])); + register_processed(r, conts[i], bbs[i]); + add_binding(ctx, false, name, bbs[i]); + log_string(DEBUGV, "Bound continuation '%s'\n", name); + } + for (size_t i = 0; i < names_count; i++) { + Context cont_ctx = *ctx; + Nodes bb_params = get_abstraction_params(bbs[i]); + for (size_t j = 0; j < bb_params.count; j++) { + const Node* bb_param = bb_params.nodes[j]; + assert(bb_param->tag == Param_TAG); + String param_name = bb_param->payload.param.name; + if (param_name) + add_binding(&cont_ctx, false, param_name, bb_param); + } + set_abstraction_body(bbs[i], rewrite_node(&cont_ctx.rewriter, get_abstraction_body(conts[i]))); + } } } @@ -232,18 +270,6 @@ static const Node* bind_node(Context* ctx, const Node* node) { return rewrite_decl(ctx, node); } case Param_TAG: error("the binders should be handled such that this node is never reached"); - case Unbound_TAG: { - const Node* mem = NULL; - if (node->payload.unbound.mem) - mem = rewrite_node(r, node->payload.unbound.mem); - Resolved entry = resolve_using_name(ctx, node->payload.unbound.name); - if (entry.is_var) { - return load(a, (Load) { .ptr = entry.node, .mem = mem }); - } else if (mem) { - return mem_and_value(a, (MemAndValue) { .value = entry.node, .mem = mem }); - } - return entry.node; - } case BasicBlock_TAG: { assert(is_basic_block(node)); Nodes new_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); @@ -263,7 +289,6 @@ static const Node* bind_node(Context* ctx, const Node* node) { set_abstraction_body(new_bb, rewrite_node(&ctx->rewriter, node->payload.basic_block.body)); return new_bb; } - case BindIdentifiers_TAG: return desugar_bind_identifiers(ctx, node); case ExtInstr_TAG: { ExtInstr payload = node->payload.ext_instr; if (strcmp("shady.frontend", payload.set) == 0) { @@ -298,6 +323,19 @@ static const Node* bind_node(Context* ctx, const Node* node) { .mem = rewrite_node(r, payload.mem) } ); } + case SlimOpUnbound: { + const Node* mem = NULL; + if (payload.mem) + mem = rewrite_node(r, payload.mem); + Resolved entry = resolve_using_name(ctx, get_string_literal(a, first(payload.operands))); + if (entry.is_var) { + return load(a, (Load) { .ptr = entry.node, .mem = mem }); + } else if (mem) { + return mem_and_value(a, (MemAndValue) { .value = entry.node, .mem = mem }); + } + return entry.node; + } + default: return desugar_bind_identifiers(ctx, payload); } } break; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index f4c7fa69f..5965df556 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -8,6 +8,7 @@ #include "type.h" #include "ir_private.h" +#include "transform/ir_gen_helpers.h" #include #include @@ -171,6 +172,16 @@ static Nodes accept_type_arguments(ctxparams) { return ty_args; } +static const Node* make_unbound(IrArena* a, const Node* mem, String identifier) { + return ext_instr(a, (ExtInstr) { + .mem = mem, + .set = "shady.frontend", + .opcode = SlimOpUnbound, + .result_t = unit_type(a), + .operands = singleton(string_lit_helper(a, identifier)), + }); +} + static const Node* accept_value(ctxparams, BodyBuilder* bb) { Token tok = curr_token(tokenizer); size_t size = tok.end - tok.start; @@ -237,8 +248,8 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { } if (bb) - return bind_instruction_single(bb, unbound(arena, (Unbound) { .name = id, .mem = bb_mem(bb) })); - return unbound(arena, (Unbound) { .name = id }); + return bind_instruction_single(bb, make_unbound(arena, bb_mem(bb), id)); + return make_unbound(arena, NULL, id); } case hex_lit_tok: case dec_lit_tok: { @@ -391,7 +402,7 @@ static const Type* accept_unqualified_type(ctxparams) { } else { String id = accept_identifier(ctx); if (id) - return unbound(arena, (Unbound) { .name = id }); + return make_unbound(arena, NULL, id); return NULL; } @@ -755,16 +766,11 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* destroy_list(tlist); } -const Node* bind_identifiers(IrArena* arena, const Node* instruction, const Node* mem, bool mut, Strings names, Nodes types); - -void parser_create_mutable_variables(BodyBuilder* bb, const Node* instruction, Nodes provided_types, Strings output_names) { - const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, bb->mem, true, output_names, provided_types); - bind_instruction_outputs_count(bb, let_mut_instr, 0); -} - -void parser_create_immutable_variables(BodyBuilder* bb, const Node* instruction, Strings output_names) { - const Node* let_mut_instr = bind_identifiers(bb->arena, instruction, bb->mem, false, output_names, empty(bb->arena)); - bind_instruction_outputs_count(bb, let_mut_instr, 0); +static Nodes strings2nodes(IrArena* a, Strings strings) { + LARRAY(const Node*, arr, strings.count); + for (size_t i = 0; i < strings.count; i++) + arr[i] = string_lit_helper(a, strings.strings[i]); + return nodes(a, strings.count, arr); } static bool accept_statement(ctxparams, BodyBuilder* bb) { @@ -773,13 +779,13 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok)); const Node* instruction = accept_instruction(ctx, bb); - parser_create_immutable_variables(bb, instruction, ids); + gen_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(bb->arena), prepend_nodes(bb->arena, strings2nodes(bb->arena, ids), instruction)); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok)); const Node* instruction = accept_instruction(ctx, bb); - parser_create_mutable_variables(bb, instruction, types, ids); + gen_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(bb->arena), prepend_nodes(bb->arena, concat_nodes(bb->arena, strings2nodes(bb->arena, ids), types), instruction)); } else { const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; @@ -792,7 +798,7 @@ static const Node* expect_jump(ctxparams, BodyBuilder* bb) { String target = accept_identifier(ctx); expect(target); Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); - const Node* tgt = unbound(arena, (Unbound) { .name = target, .mem = bb_mem(bb) }); + const Node* tgt = make_unbound(arena, bb_mem(bb), target); bind_instruction_single(bb, tgt); return jump(arena, (Jump) { .target = tgt, @@ -942,6 +948,9 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, mem); + //struct List* bb_names = new_list(String); + Nodes ids = empty(arena); + Nodes conts = empty(arena); if (curr_token(tokenizer).tag == cont_tok) { while (true) { if (!accept_token(ctx, cont_tok)) @@ -952,10 +961,14 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t expect_parameters(ctx, ¶meters, NULL, bb); Node* continuation = basic_block(arena, parameters, name); set_abstraction_body(continuation, expect_body(ctx, get_abstraction_mem(continuation), NULL)); - bind_instruction_single(cont_wrapper_bb, bind_identifiers(arena, continuation, bb_mem(cont_wrapper_bb), false, strings(arena, 1, &name), empty(arena))); + ids = append_nodes(arena, ids, string_lit_helper(arena, name)); + conts = append_nodes(arena, conts, continuation); } } + gen_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), concat_nodes(arena, ids, conts)); + //destroy_list(bb_names); + expect(accept_token(ctx, rbracket_tok)); return finish_body(cont_wrapper_bb, jump_helper(arena, c, empty(arena), bb_mem(cont_wrapper_bb))); @@ -975,10 +988,8 @@ static Nodes accept_annotations(ctxparams) { goto no_params; } - // this is a map - if (first_value->tag == Unbound_TAG && accept_token(ctx, equal_tok)) { - error("TODO: parse map") - } else if (curr_token(tokenizer).tag == comma_tok) { + // TODO: AnnotationCompound ? + if (curr_token(tokenizer).tag == comma_tok) { next_token(tokenizer); struct List* values = new_list(const Node*); append_list(const Node*, values, first_value); diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c index a1036f9af..63fa590dd 100644 --- a/src/shady/analysis/free_variables.c +++ b/src/shady/analysis/free_variables.c @@ -196,7 +196,7 @@ struct Dict* compute_cfg_variables_map(const CFG* cfg, CfgVariablesAnalysisFlags .flags = flags, }; - debugv_print("Computing free variables for function '%s' ...\n", get_abstraction_name(cfg->entry->node)); + // debugv_print("Computing free variables for function '%s' ...\n", get_abstraction_name(cfg->entry->node)); root_context = visit_domtree(&root_context, cfg->entry, 0); destroy_dict(root_context.bound); destroy_dict(root_context.live); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 7d21f7366..b6d6ebd4f 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -66,7 +66,7 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp if (bb->arena->config.check_types) { assert(is_instruction(instruction) || is_value(instruction)); } - if (is_mem(instruction)) + if (is_mem(instruction) && /* avoid things like ExtInstr with null mem input! */ get_parent_mem(instruction)) bb->mem = instruction; return deconstruct_composite(bb->arena, bb, instruction, outputs_count); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 942f31831..716c36c40 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -77,26 +77,6 @@ Node* param(IrArena* arena, const Type* type, const char* name) { return create_node_helper(arena, node, NULL); } -const Node* bind_identifiers(IrArena* arena, const Node* value, const Node* mem, bool mut, Strings names, Nodes types) { - BindIdentifiers payload = { - .value = value, - .mutable = mut, - .names = names, - .types = types, - .mem = mem, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .type = NULL, - .tag = BindIdentifiers_TAG, - .payload.bind_identifiers = payload - }; - return create_node_helper(arena, node, NULL); -} - const Node* composite_helper(IrArena* a, const Type* t, Nodes contents) { return composite(a, (Composite) { .type = t, .contents = contents }); } diff --git a/src/shady/node_helpers.c b/src/shady/node_helpers.c index 1045a86b9..885e617f8 100644 --- a/src/shady/node_helpers.c +++ b/src/shady/node_helpers.c @@ -19,9 +19,6 @@ const Node* get_parent_mem(const Node* mem) { case Mem_Comment_TAG: mem = mem->payload.comment.mem; return mem; - case Mem_BindIdentifiers_TAG: - mem = mem->payload.bind_identifiers.mem; - return mem; case Mem_StackAlloc_TAG: mem = mem->payload.stack_alloc.mem; return mem; @@ -58,9 +55,6 @@ const Node* get_parent_mem(const Node* mem) { case Mem_ExtInstr_TAG: mem = mem->payload.ext_instr.mem; return mem; - case Mem_Unbound_TAG: - mem = mem->payload.unbound.mem; - return mem; } } diff --git a/src/shady/print.c b/src/shady/print.c index fe2ff29bc..2c36a7bc7 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1089,10 +1089,6 @@ static bool print_node_impl(PrinterCtx* ctx, const Node* node) { printf(BYELLOW); printf("%s", get_declaration_name(node)); printf(RESET); - } else if (node->tag == Unbound_TAG) { - printf(YELLOW); - printf("`%s`", node->payload.unbound.name); - printf(RESET); } else if (is_annotation(node)) { print_annotation(ctx, node); return true; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 04c8a08b0..0b546f404 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,6 +10,7 @@ if (BUILD_TESTING) list(APPEND BASIC_TESTS empty.slim) list(APPEND BASIC_TESTS entrypoint_args1.slim) list(APPEND BASIC_TESTS basic_blocks1.slim) + list(APPEND BASIC_TESTS basic_blocks2.slim) list(APPEND BASIC_TESTS control_flow1.slim) list(APPEND BASIC_TESTS control_flow2.slim) list(APPEND BASIC_TESTS functions1.slim) diff --git a/test/basic_blocks2.slim b/test/basic_blocks2.slim index f4efe670a..1dc6e00a0 100644 --- a/test/basic_blocks2.slim +++ b/test/basic_blocks2.slim @@ -3,6 +3,10 @@ fn main() { jump bb1(7); cont bb1(varying i32 n) { + jump bb2(n); + } + + cont bb2(varying i32 n) { return (); } } From c1c95a567f3affd94058dc5d91a7b477439cec77 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 18:22:52 +0200 Subject: [PATCH 478/693] slim: remove remnants of old j/br syntax --- src/frontend/slim/parser.c | 2 +- test/reconvergence_heuristics/acyclic1.slim | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 5965df556..ba47edbea 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -797,7 +797,7 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { static const Node* expect_jump(ctxparams, BodyBuilder* bb) { String target = accept_identifier(ctx); expect(target); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); + Nodes args = expect_operands(ctx, bb); const Node* tgt = make_unbound(arena, bb_mem(bb), target); bind_instruction_single(bb, tgt); return jump(arena, (Jump) { diff --git a/test/reconvergence_heuristics/acyclic1.slim b/test/reconvergence_heuristics/acyclic1.slim index 7625c6d2f..0f4993c08 100644 --- a/test/reconvergence_heuristics/acyclic1.slim +++ b/test/reconvergence_heuristics/acyclic1.slim @@ -42,7 +42,7 @@ fn f2 i32(varying bool b) { @Restructure fn g i32(varying bool b) { - branch(b, bb1, bb2)(); + branch(b, bb1(), bb2()); cont bb1() { jump bb3(); @@ -142,7 +142,7 @@ fn hnot2 i32(varying bool b) { @Restructure fn i i32(varying bool b) { - branch(b, bb1, bb2)(); + branch(b, bb1(), bb2()); cont bb1() { jump bb2(); From 4ba856cfef186a35749b0b2d0218a1cc4bfd04f2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 12 Aug 2024 18:23:17 +0200 Subject: [PATCH 479/693] reconvergence_heuristics: in progress --- include/shady/ir.h | 2 + src/shady/body_builder.c | 16 ++++++ src/shady/passes/opt_demote_alloca.c | 6 +- src/shady/passes/reconvergence_heuristics.c | 62 +++++---------------- 4 files changed, 36 insertions(+), 50 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index baad5eda7..bb69a3997 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -310,6 +310,8 @@ const Node* finish_body_with_unreachable(BodyBuilder*); const Node* finish_body_with_selection_merge(BodyBuilder*, Nodes args); const Node* finish_body_with_loop_continue(BodyBuilder*, Nodes args); const Node* finish_body_with_loop_break(BodyBuilder*, Nodes args); +const Node* finish_body_with_join(BodyBuilder*, const Node* jp, Nodes args); +const Node* finish_body_with_jump(BodyBuilder*, const Node* target, Nodes args); void cancel_body(BodyBuilder*); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index b6d6ebd4f..5ffac7638 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -162,6 +162,22 @@ const Node* finish_body_with_loop_break(BodyBuilder* bb, Nodes args) { })); } +const Node* finish_body_with_join(BodyBuilder* bb, const Node* jp, Nodes args) { + return finish_body(bb, join(bb->arena, (Join) { + .join_point = jp, + .args = args, + .mem = bb_mem(bb), + })); +} + +const Node* finish_body_with_jump(BodyBuilder* bb, const Node* target, Nodes args) { + return finish_body(bb, jump(bb->arena, (Jump) { + .target = target, + .args = args, + .mem = bb_mem(bb), + })); +} + const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { IrArena* a = bb->arena; if (!bb->tail_block && entries_count_list(bb->stack) == 0) { diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 8b24eae9d..ea0a513b4 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -157,9 +157,9 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t assert(ctx->uses); visit_ptr_uses(old, old_type, k, ctx->uses); insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, old, k); - debugv_print("demote_alloca: uses analysis results for "); - log_node(DEBUGV, old); - debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); + // debugv_print("demote_alloca: uses analysis results for "); + // log_node(DEBUGV, old); + // debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); if (!k->leaks) { if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { ctx->todo |= true; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 1f92c7258..e970613ea 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -183,20 +183,14 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { } Nodes continue_wrapper_params = recreate_params(rewriter, get_abstraction_params(node)); + Node* continue_wrapper; + continue_wrapper = basic_block(arena, continue_wrapper_params, "continue"); const Node* continue_wrapper_body = join(arena, (Join) { .join_point = join_token_continue, - .args = continue_wrapper_params + .args = continue_wrapper_params, + .mem = get_abstraction_mem(continue_wrapper), }); - Node* continue_wrapper; - switch (node->tag) { - case BasicBlock_TAG: { - continue_wrapper = basic_block(arena, continue_wrapper_params, "continue"); - set_abstraction_body(continue_wrapper, continue_wrapper_body); - break; - } - default: - assert(false); - } + set_abstraction_body(continue_wrapper, continue_wrapper_body); // replace the exit nodes by the exit wrappers LARRAY(const Node*, cached_exits, exiting_nodes_count); @@ -240,12 +234,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { gen_store(exit_wrapper_bb, exit_fwd_allocas[i].nodes[j], rewrite_node(rewriter, read_list(const Node*, leaking[i])[j])); } - const Node* exit_wrapper_body = finish_body(exit_wrapper_bb, join(arena, (Join) { - .join_point = join_token_exit, - .args = empty(arena) - })); - - set_abstraction_body(exit_helpers[i], exit_wrapper_body); + set_abstraction_body(exit_helpers[i], finish_body_with_join(exit_wrapper_bb, join_token_exit, empty(arena))); } destroy_dict(rewriter->map); @@ -268,14 +257,12 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { set_abstraction_body(inner_control_case, loop_body); Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); - set_abstraction_body(loop_outer, finish_body(inner_bb, jump(arena, (Jump) { - .target = loop_outer, - .args = inner_control_results - }))); + set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_body, inner_control_results)); Node* outer_control_case = case_(arena, singleton(join_token_exit)); set_abstraction_body(outer_control_case, jump(arena, (Jump) { .target = loop_outer, - .args = nparams + .args = nparams, + .mem = get_abstraction_mem(outer_control_case), })); gen_control(outer_bb, empty(arena), outer_control_case); @@ -300,18 +287,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { recovered_args[j] = gen_load(exit_recover_bb, exit_param_allocas[i].nodes[j]); exit_numbers[i] = int32_literal(arena, i); - if (recreated_exit->tag == BasicBlock_TAG) { - set_abstraction_body(exit_bb, finish_body(exit_recover_bb, jump(arena, (Jump) { - .target = recreated_exit, - .args = nodes(arena, exit_param_allocas[i].count, recovered_args), - }))); - } else { - // TODO: rewrite - assert(get_abstraction_params(recreated_exit).count == 0); - error("") - // assert(recreated_exit->tag == Case_TAG); - // exit_bb->payload.basic_block.body = finish_body(exit_recover_bb, let(arena, quote_helper(arena, nodes(arena, exit_param_allocas[i].count, recovered_args)), recreated_exit)); - } + set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, nodes(arena, exit_param_allocas[i].count, recovered_args))); exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena), bb_mem(outer_bb)); destroy_list(leaking[i]); } @@ -467,7 +443,8 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* pre_join = basic_block(a, exit_args, format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); set_abstraction_body(pre_join, join(a, (Join) { .join_point = join_token, - .args = exit_args + .args = exit_args, + .mem = get_abstraction_mem(pre_join), })); const Node* cached = search_processed(r, idom); @@ -489,18 +466,9 @@ static const Node* process_node(Context* ctx, const Node* node) { set_abstraction_body(control_case, inner_terminator); const Node* join_target = rewrite_node(r, idom); - switch (idom->tag) { - case BasicBlock_TAG: { - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); - Nodes results = gen_control(bb, yield_types, control_case); - return finish_body(bb, jump(a, (Jump) { - .target = join_target, - .args = results - })); - } - default: - assert(false); - } + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); + Nodes results = gen_control(bb, yield_types, control_case); + return finish_body_with_jump(bb, join_target, results); } default: break; } From 5906216fe4b17ebac3db45b0f4573480f1032360 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 10:45:37 +0200 Subject: [PATCH 480/693] parser: allow continuations to see results in their dominator --- src/frontend/slim/parser.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index ba47edbea..4dc9689d1 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -924,31 +924,32 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator(const Node*)) { expect(accept_token(ctx, lbracket_tok)); - Node* c = case_(arena, empty(arena)); - BodyBuilder* bb = begin_body_with_mem(arena, get_abstraction_mem(c)); + BodyBuilder* bb = begin_body_with_mem(arena, mem); while (true) { if (!accept_statement(ctx, bb)) break; } - const Node* terminator = accept_terminator(ctx, bb); + Node* terminator_case = case_(arena, empty(arena)); + BodyBuilder* terminator_bb = begin_body_with_mem(arena, get_abstraction_mem(terminator_case)); + const Node* terminator = accept_terminator(ctx, terminator_bb); if (terminator) expect(accept_token(ctx, semi_tok)); if (!terminator) { if (default_terminator) - terminator = default_terminator(bb_mem(bb)); + terminator = default_terminator(bb_mem(terminator_bb)); else error("expected terminator: return, jump, branch ..."); } - set_abstraction_body(c, finish_body(bb, terminator)); + set_abstraction_body(terminator_case, finish_body(terminator_bb, terminator)); - BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, mem); + Node* cont_wrapper_case = case_(arena, empty(arena)); + BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(cont_wrapper_case)); - //struct List* bb_names = new_list(String); Nodes ids = empty(arena); Nodes conts = empty(arena); if (curr_token(tokenizer).tag == cont_tok) { @@ -967,11 +968,10 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t } gen_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), concat_nodes(arena, ids, conts)); - //destroy_list(bb_names); - expect(accept_token(ctx, rbracket_tok)); - return finish_body(cont_wrapper_bb, jump_helper(arena, c, empty(arena), bb_mem(cont_wrapper_bb))); + set_abstraction_body(cont_wrapper_case, finish_body_with_jump(cont_wrapper_bb, terminator_case, empty(arena))); + return finish_body_with_jump(bb, cont_wrapper_case, empty(arena)); } static Nodes accept_annotations(ctxparams) { From cecc3210ae4fec66ca23905624950d7ed85802e2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 10:46:11 +0200 Subject: [PATCH 481/693] fix bad mem threading in reconvergence_heuristics --- src/shady/passes/reconvergence_heuristics.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index e970613ea..8def78018 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -352,6 +352,7 @@ static const Node* process_node(Context* ctx, const Node* node) { break; return process_abstraction(ctx, node); case Branch_TAG: { + Branch payload = node->payload.branch; if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) break; assert(ctx->fwd_cfg); @@ -456,13 +457,17 @@ static const Node* process_node(Context* ctx, const Node* node) { register_processed(r, idom, pre_join); - const Node* inner_terminator = recreate_node_identity(r, node); - remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); if (cached) register_processed(r, idom, cached); Node* control_case = case_(a, singleton(join_token)); + const Node* inner_terminator = branch(a, (Branch) { + .mem = get_abstraction_mem(control_case), + .condition = rewrite_node(r, payload.condition), + .true_jump = jump_helper(a, rewrite_node(r, payload.true_jump->payload.jump.target), rewrite_nodes(r, payload.true_jump->payload.jump.args), get_abstraction_mem(control_case)), + .false_jump = jump_helper(a, rewrite_node(r, payload.false_jump->payload.jump.target), rewrite_nodes(r, payload.false_jump->payload.jump.args), get_abstraction_mem(control_case)), + }); set_abstraction_body(control_case, inner_terminator); const Node* join_target = rewrite_node(r, idom); From 97041590db567aea404de739e270caa42875c17a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 11:36:25 +0200 Subject: [PATCH 482/693] print: nest continuations according to dominance --- src/shady/print.c | 72 ++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/src/shady/print.c b/src/shady/print.c index 2c36a7bc7..7da4984f2 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -120,8 +120,6 @@ void dump_module(Module* mod) { void log_node(LogLevel level, const Node* node) { if (level <= get_log_level()) { Printer* p = open_file_as_printer(stderr); - if (node) - print(p, "%%%d = ", node->id); print_node(p, (NodePrintConfig) {.color = true}, node); destroy_printer(p); } @@ -240,11 +238,12 @@ static void print_yield_types(PrinterCtx* ctx, Nodes types) { } } -static void print_abs_body(PrinterCtx* ctx, const Node* block); +static String emit_abs_body(PrinterCtx* ctx, const CFNode* cfnode); -static void print_basic_block(PrinterCtx* ctx, const Node* bb) { +static void print_basic_block(PrinterCtx* ctx, const CFNode* node) { + const Node* bb = node->node; printf(GREEN); - printf("\n\ncont"); + printf("\ncont"); printf(BYELLOW); if (bb->payload.basic_block.name && strlen(bb->payload.basic_block.name) > 0) printf(" %s", bb->payload.basic_block.name); @@ -259,44 +258,34 @@ static void print_basic_block(PrinterCtx* ctx, const Node* bb) { printf(" {"); indent(ctx->printer); printf("\n"); - print_abs_body(ctx, bb); + printf("%s", emit_abs_body(ctx, node)); deindent(ctx->printer); printf("\n}"); } -static void print_dominated_bbs(PrinterCtx* ctx, const CFNode* dominator) { - assert(dominator); - for (size_t i = 0; i < dominator->dominates->elements_count; i++) { - const CFNode* cfnode = read_list(const CFNode*, dominator->dominates)[i]; - // ignore cases that make up basic structural dominance - //if (find_key_dict(const Node*, dominator->structurally_dominates, cfnode->node)) - // continue; - assert(is_basic_block(cfnode->node)); - PrinterCtx bb_ctx = *ctx; - bb_ctx.printer = bb_ctx.bb_printers[cfnode->rpo_index]; - print_basic_block(&bb_ctx, cfnode->node); - } -} - -static void print_abs_body(PrinterCtx* ctx, const Node* block) { - assert(!ctx->fn || is_function(ctx->fn)); - assert(is_abstraction(block)); +static String emit_abs_body(PrinterCtx* ctx, const CFNode* cfnode) { + Growy* g = new_growy(); + Printer* p = open_growy_as_printer(g); + ctx->bb_printers[cfnode->rpo_index] = p; - emit_node(ctx, get_abstraction_body(block)); + emit_node(ctx, get_abstraction_body(cfnode->node)); - if (ctx->cfg != NULL) { - const CFNode* dominator = cfg_lookup(ctx->cfg, block); - print_dominated_bbs(ctx, dominator); + size_t count = cfnode->dominates->elements_count; + for (size_t i = 0; i < count; i++) { + const CFNode* dominated = read_list(const CFNode*, cfnode->dominates)[i]; + assert(is_basic_block(dominated->node)); + PrinterCtx bb_ctx = *ctx; + bb_ctx.printer = p; + print_basic_block(&bb_ctx, dominated); + if (i + 1 < count) + newline(bb_ctx.printer); } -} -static void print_case_body(PrinterCtx* ctx, const Node* case_) { - printf(" {"); - indent(ctx->printer); - printf("\n"); - print_abs_body(ctx, case_); - deindent(ctx->printer); - printf("\n}"); + String s = printer_growy_unwrap(p); + String s2 = string(ctx->fn->arena, s); + ctx->bb_printers[cfnode->rpo_index] = NULL; + free((void*) s); + return s2; } static void print_function(PrinterCtx* ctx, const Node* node) { @@ -310,10 +299,6 @@ static void print_function(PrinterCtx* ctx, const Node* node) { sub_ctx.fn = node; sub_ctx.bb_growies = calloc(sizeof(size_t), cfg->size); sub_ctx.bb_printers = calloc(sizeof(size_t), cfg->size); - for (size_t i = 0; i < cfg->size; i++) { - sub_ctx.bb_growies[i] = new_growy(); - sub_ctx.bb_printers[i] = open_growy_as_printer(sub_ctx.bb_growies[i]); - } if (node->arena->config.check_types && node->arena->config.allow_fold) { sub_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); } @@ -331,18 +316,11 @@ static void print_function(PrinterCtx* ctx, const Node* node) { indent(ctx->printer); printf("\n"); - print_abs_body(ctx, node); + printf("%s", emit_abs_body(ctx, ctx->cfg->entry)); if (sub_ctx.cfg) { if (sub_ctx.uses) destroy_uses_map(sub_ctx.uses); - for (size_t i = 0; i < sub_ctx.cfg->size; i++) { - String s = printer_growy_unwrap(sub_ctx.bb_printers[i]); - printf("%s", s); - free(s); - // destroy_printer(sub_ctx.bb_printers[i]); - // destroy_growy(sub_ctx.bb_growies[i]); - } free(sub_ctx.bb_printers); free(sub_ctx.bb_growies); destroy_cfg(sub_ctx.cfg); From 8b9d9c1be3e53e9729d08aa813f3d176c49e2c47 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 14:44:59 +0200 Subject: [PATCH 483/693] fixed lift_indirect_targets --- src/shady/passes/lift_indirect_targets.c | 114 ++++++++++++++--------- src/shady/rewrite.c | 2 +- 2 files changed, 72 insertions(+), 44 deletions(-) diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 94d4fc99b..3959503d8 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -2,13 +2,14 @@ #include "../type.h" #include "../ir_private.h" +#include "../visit.h" #include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" -#include "../analysis/free_variables.h" #include "../analysis/uses.h" #include "../analysis/leak.h" #include "../analysis/verify.h" +#include "../analysis/scheduler.h" #include "log.h" #include "portability.h" @@ -17,7 +18,6 @@ #include "util.h" #include -#include KeyHash hash_node(Node**); bool compare_node(Node**, Node**); @@ -39,17 +39,14 @@ static const Node* process_node(Context* ctx, const Node* node); typedef struct { const Node* old_cont; const Node* lifted_fn; - struct List* save_values; + Nodes save_values; } LiftedCont; #pragma GCC diagnostic error "-Wswitch" -static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, struct List* spilled_vars) { - IrArena* a = ctx->rewriter.dst_arena; - - size_t recover_context_size = entries_count_list(spilled_vars); - for (size_t i = 0; i < recover_context_size; i++) { - const Node* ovar = read_list(const Node*, spilled_vars)[i]; +static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, Nodes spilled_vars) { + for (size_t i = 0; i < spilled_vars.count; i++) { + const Node* ovar = spilled_vars.nodes[i]; const Node* nvar = rewrite_node(&ctx->rewriter, ovar); const Type* t = nvar->type; deconstruct_qualified_type(&t); @@ -57,51 +54,82 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, struct L gen_push_value_stack(builder, nvar); } - const Node* sp = gen_get_stack_size(builder); + return gen_get_stack_size(builder); +} - return sp; +typedef struct { + Visitor v; + Scheduler* scheduler; + CFNode* start; + struct Dict* frontier; +} FreeFrontierVisitor; + +/// Whether 'a' is dominated by 'b' +static bool is_dominated(CFNode* a, CFNode* b) { + while (a) { + if (a == b) + return true; + a = a->idom; + } + return false; } -static void add_to_recover_context(struct List* recover_context, struct Dict* set, Nodes except) { - size_t i = 0; - const Node* item; - while (dict_iter(set, &i, &item, NULL)) { - if (find_in_nodes(except, item)) - continue; - append_list(const Node*, recover_context, item ); +static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { + CFNode* where = schedule_instruction(v->scheduler, node); + if (where) { + FreeFrontierVisitor vv = *v; + if (is_dominated(where, v->start)) { + visit_node_operands(&vv.v, IGNORE_ABSTRACTIONS_MASK | NcType, node); + } else { + insert_set_get_result(const Node*, v->frontier, node); + } } } -static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariables) { +static Nodes free_frontier(Scheduler* scheduler, CFNode* start) { + FreeFrontierVisitor ffv = { + .v = { + .visit_node_fn = (VisitNodeFn) visit_free_frontier, + }, + .scheduler = scheduler, + .start = start, + .frontier = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + }; + visit_free_frontier(&ffv, get_abstraction_body(start->node)); + size_t count = entries_count_dict(ffv.frontier); + LARRAY(const Node*, tmp, count); + size_t i = 0, j = 0; + const Node* key; + while (dict_iter(ffv.frontier, &i, &key, NULL)) { + tmp[j++] = key; + } + assert(j == count); + return nodes(start->node->arena, count, tmp); +} + +static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { assert(is_basic_block(liftee)); LiftedCont** found = find_value_dict(const Node*, LiftedCont*, ctx->lifted, liftee); if (found) return *found; IrArena* a = ctx->rewriter.dst_arena; - //Nodes oparams = get_abstraction_params(liftee); const Node* obody = get_abstraction_body(liftee); - String name = get_abstraction_name_safe(liftee); - // Compute the live stuff we'll need - CFG* cfg_rooted_in_liftee = build_cfg(ctx->cfg->entry->node, liftee, NULL, false); - CFNode* cf_node = cfg_lookup(cfg_rooted_in_liftee, liftee); - struct Dict* live_vars = compute_cfg_variables_map(cfg_rooted_in_liftee, CfgVariablesAnalysisFlagFreeSet); - CFNodeVariables* node_vars = *find_value_dict(CFNode*, CFNodeVariables*, live_vars, cf_node); - struct List* recover_context = new_list(const Node*); + Scheduler* scheduler = new_scheduler(cfg); + CFNode* cfn_liftee = cfg_lookup(cfg, liftee); + Nodes frontier = free_frontier(scheduler, cfn_liftee); - add_to_recover_context(recover_context, node_vars->free_set, ovariables); - size_t recover_context_size = entries_count_list(recover_context); + size_t recover_context_size = frontier.count; - destroy_cfg_variables_map(live_vars); - destroy_cfg(cfg_rooted_in_liftee); + destroy_scheduler(scheduler); + Nodes ovariables = get_abstraction_params(liftee); debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { - const Node* item = read_list(const Node*, recover_context)[i]; - String item_name = get_value_name_unsafe(item); - debugv_print("%s %%%d", item_name ? item_name : "", item->id); + const Node* item = frontier.nodes[i]; + debugv_print("%%%d", item->id); if (i + 1 < recover_context_size) debugv_print(", "); } @@ -115,7 +143,7 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable LiftedCont* lifted_cont = calloc(sizeof(LiftedCont), 1); lifted_cont->old_cont = liftee; - lifted_cont->save_values = recover_context; + lifted_cont->save_values = frontier; insert_dict(const Node*, LiftedCont*, ctx->lifted, liftee, lifted_cont); Context lifting_ctx = *ctx; @@ -135,18 +163,18 @@ static LiftedCont* lambda_lift(Context* ctx, const Node* liftee, Nodes ovariable BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_set_stack_size(bb, payload); for (size_t i = recover_context_size - 1; i < recover_context_size; i--) { - const Node* ovar = read_list(const Node*, recover_context)[i]; + const Node* ovar = frontier.nodes[i]; // assert(ovar->tag == Variable_TAG); const Type* value_type = rewrite_node(r, ovar->type); - String param_name = get_value_name_unsafe(ovar); + //String param_name = get_value_name_unsafe(ovar); const Node* recovered_value = gen_pop_value_stack(bb, get_unqualified_type(value_type)); - if (param_name) - set_value_name(recovered_value, param_name); + //if (param_name) + // set_value_name(recovered_value, param_name); if (is_qualified_type_uniform(ovar->type)) - recovered_value = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }), ¶m_name)); + recovered_value = bind_instruction_single(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) })); register_processed(r, ovar, recovered_value); } @@ -201,7 +229,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* otail = get_structured_construct_tail(node); BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.control.mem)); - LiftedCont* lifted_tail = lambda_lift(ctx, otail, get_abstraction_params(otail)); + LiftedCont* lifted_tail = lambda_lift(ctx, ctx->cfg, otail); const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); @@ -210,6 +238,8 @@ static const Node* process_node(Context* ctx, const Node* node) { jp = gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(jp)); register_processed(r, first(get_abstraction_params(oinside)), jp); + register_processed(r, get_abstraction_mem(oinside), bb_mem(bb)); + register_processed(r, oinside, NULL); return finish_body(bb, rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); } break; @@ -244,12 +274,10 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { size_t iter = 0; LiftedCont* lifted_cont; while (dict_iter(ctx.lifted, &iter, NULL, &lifted_cont)) { - destroy_list(lifted_cont->save_values); free(lifted_cont); } destroy_dict(ctx.lifted); destroy_rewriter(&ctx.rewriter); - // log_module(DEBUGVV, config, dst); verify_module(config, dst); src = dst; if (oa) diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 267e28cd7..ac76890f7 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -187,7 +187,7 @@ const Node* find_processed(const Rewriter* ctx, const Node* old) { void register_processed(Rewriter* ctx, const Node* old, const Node* new) { assert(old->arena == ctx->src_arena); - assert(new->arena == ctx->dst_arena); + assert(new ? new->arena == ctx->dst_arena : true); #ifndef NDEBUG const Node* found = search_processed_(ctx, old, false); if (found) { From 13a86b92f034495a791e7da4a8deb3b4fcee61d5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 14:45:20 +0200 Subject: [PATCH 484/693] cfg_dump: avoid % in output --- src/shady/analysis/cfg_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 09d99900c..82f16790e 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -68,7 +68,7 @@ static void dump_cfg(FILE* output, CFG* cfg) { extra_uniqueness++; const Node* entry = cfg->entry->node; - fprintf(output, "subgraph cluster_%s {\n", get_abstraction_name_safe(entry)); + fprintf(output, "subgraph cluster_%d {\n", entry->id); fprintf(output, "label = \"%s\";\n", get_abstraction_name_safe(entry)); for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { const CFNode* n = read_list(const CFNode*, cfg->contents)[i]; From 81389f3d8fadc09d878d4ef3cce4a29367f7f235 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 15:08:18 +0200 Subject: [PATCH 485/693] removed join point primops --- include/shady/primops.json | 13 -------- src/backend/c/emit_c_value.c | 2 -- src/shady/passes/join_point_ops.h | 9 ++++++ src/shady/passes/lift_indirect_targets.c | 6 +++- src/shady/passes/lower_callf.c | 27 ++++++++++------ src/shady/passes/lower_tailcalls.c | 40 +++++++++--------------- src/shady/type.c | 11 ------- 7 files changed, 46 insertions(+), 62 deletions(-) create mode 100644 src/shady/passes/join_point_ops.h diff --git a/include/shady/primops.json b/include/shady/primops.json index 8c8d071b6..bd0529e64 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -21,9 +21,6 @@ { "name": "subgroup_intrinsic" }, - { - "name": "join_point" - }, { "name": "mask" } @@ -218,16 +215,6 @@ "name": "sample_texture", "side-effects": true }, - { - "name": "create_joint_point", - "class": "join_point", - "side-effects": true - }, - { - "name": "default_join_point", - "class": "join_point", - "side-effects": true - }, { "name": "empty_mask", "class": "mask" diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 8cf833a5a..f2a1be32e 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -686,8 +686,6 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { term = term_from_cvalue(dst); break; } - case default_join_point_op: - case create_joint_point_op: error("lowered in lower_tailcalls.c"); case subgroup_assume_uniform_op: { if (emitter->config.dialect != CDialect_ISPC) { return emit_value(emitter, p, prim_op->operands.nodes[0]); diff --git a/src/shady/passes/join_point_ops.h b/src/shady/passes/join_point_ops.h new file mode 100644 index 000000000..338cab249 --- /dev/null +++ b/src/shady/passes/join_point_ops.h @@ -0,0 +1,9 @@ +#ifndef SHADY_JOIN_POINT_OPS_H +#define SHADY_JOIN_POINT_OPS_H + +typedef enum { + ShadyOpDefaultJoinPoint, + ShadyOpCreateJoinPoint, +} ShadyJoinPointOpcodes; + +#endif diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 3959503d8..dd73cb60d 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "join_point_ops.h" #include "../type.h" #include "../ir_private.h" @@ -233,7 +234,10 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); - const Node* jp = gen_primop_e(bb, create_joint_point_op, rewrite_nodes(&ctx->rewriter, node->payload.control.yield_types), mk_nodes(a, tail_ptr, sp)); + const Type* jp_type = join_point_type(a, (JoinPointType) { + .yield_types = rewrite_nodes(&ctx->rewriter, node->payload.control.yield_types), + }); + const Node* jp = gen_ext_instruction(bb, "shady.internal", ShadyOpCreateJoinPoint, qualified_type_helper(jp_type, true), mk_nodes(a, tail_ptr, sp)); // dumbass hack jp = gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(jp)); diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 5fe5d561e..3c8eab059 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -1,7 +1,7 @@ #include "shady/pass.h" +#include "join_point_ops.h" #include "../type.h" - #include "../transform/ir_gen_helpers.h" #include "log.h" @@ -15,7 +15,6 @@ typedef struct Context_ { Rewriter rewriter; bool disable_lowering; - Node* self; const Node* return_jp; } Context; @@ -30,32 +29,40 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { Context ctx2 = *ctx; ctx2.disable_lowering = lookup_annotation(old, "Leaf"); ctx2.return_jp = NULL; - Node* fun = NULL; - if (!ctx2.disable_lowering) { + if (!ctx2.disable_lowering && get_abstraction_body(old)) { Nodes oparams = get_abstraction_params(old); Nodes nparams = recreate_params(&ctx->rewriter, oparams); register_processed_list(&ctx->rewriter, oparams, nparams); + Nodes nannots = rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); + + Node* prelude = case_(a, empty(a)); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(prelude)); + // Supplement an additional parameter for the join point const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, old->payload.fun.return_types)) }); if (lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { - ctx2.return_jp = prim_op_helper(a, default_join_point_op, empty(a), empty(a)); + ctx2.return_jp = gen_ext_instruction(bb, "shady.internal", ShadyOpDefaultJoinPoint, qualified_type_helper(jp_type, true), empty(a)); } else { const Node* jp_variable = param(a, qualified_type_helper(jp_type, false), "return_jp"); nparams = append_nodes(a, nparams, jp_variable); ctx2.return_jp = jp_variable; } - Nodes nannots = rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); - fun = function(ctx->rewriter.dst_module, nparams, get_abstraction_name(old), nannots, empty(a)); - ctx2.self = fun; + Node* fun = function(ctx->rewriter.dst_module, nparams, get_abstraction_name(old), nannots, empty(a)); register_processed(&ctx->rewriter, old, fun); - } else - fun = recreate_decl_header_identity(&ctx->rewriter, old); + + register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + set_abstraction_body(prelude, finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body))); + set_abstraction_body(fun, jump_helper(a, prelude, empty(a), get_abstraction_mem(fun))); + return fun; + } + + Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); if (old->payload.fun.body) set_abstraction_body(fun, rewrite_node(&ctx2.rewriter, old->payload.fun.body)); return fun; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index c5b7f4670..5878e7d2d 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "join_point_ops.h" #include "../type.h" #include "../ir_private.h" @@ -36,7 +37,7 @@ typedef struct Context_ { static const Node* process(Context* ctx, const Node* old); static const Node* fn_ptr_as_value(IrArena* a, FnPtr ptr) { - return uint64_literal(a, ptr); + return uint32_literal(a, ptr); } static const Node* lower_fn_addr(Context* ctx, const Node* the_function) { @@ -169,32 +170,21 @@ static const Node* process(Context* ctx, const Node* old) { case JoinPointType_TAG: return type_decl_ref(a, (TypeDeclRef) { .decl = find_or_process_decl(&ctx->rewriter, "JoinPoint"), }); - case PrimOp_TAG: { - switch (old->payload.prim_op.op) { - /*case create_joint_point_op: { - BodyBuilder* bb = begin_body(a); - Nodes args = rewrite_nodes(&ctx->rewriter, old->payload.prim_op.operands); - assert(args.count == 2); - const Node* dst = first(args); - const Node* sp = args.nodes[1]; - dst = gen_conversion(bb, uint32_type(a), dst); - Nodes r = bind_instruction(bb, call(a, (Call) { - .callee = access_decl(&ctx->rewriter, "builtin_create_control_point"), - .args = mk_nodes(a, dst, sp), - })); - return yield_values_and_wrap_in_block(bb, r); + case ExtInstr_TAG: { + ExtInstr payload = old->payload.ext_instr; + if (strcmp(payload.set, "shady.internal") == 0) { + String callee_name = NULL; + switch ((ShadyJoinPointOpcodes ) payload.opcode) { + case ShadyOpDefaultJoinPoint: callee_name = "builtin_entry_join_point"; break; + case ShadyOpCreateJoinPoint: callee_name = "builtin_create_control_point"; break; } - case default_join_point_op: { - BodyBuilder* bb = begin_body(a); - Nodes r = bind_instruction(bb, call(a, (Call) { - .callee = access_decl(&ctx->rewriter, "builtin_entry_join_point"), - .args = empty(a) - })); - return yield_values_and_wrap_in_block(bb, r); - }*/ - error("TODO: unprimop-ify these") - default: return recreate_node_identity(&ctx->rewriter, old); + return call(a, (Call) { + .mem = rewrite_node(r, payload.mem), + .callee = access_decl(r, callee_name), + .args = rewrite_nodes(r, payload.operands), + }); } + break; } case TailCall_TAG: { //if (ctx->disable_lowering) diff --git a/src/shady/type.c b/src/shady/type.c index 5cef7b5c0..a765db5e7 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -855,17 +855,6 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { }); } // Intermediary ops - case create_joint_point_op: { - assert(prim_op.operands.count == 2); - const Node* join_point = first(prim_op.operands); - assert(is_qualified_type_uniform(join_point->type)); - return qualified_type(arena, (QualifiedType) { .type = join_point_type(arena, (JoinPointType) { .yield_types = prim_op.type_arguments }), .is_uniform = false }); - } - case default_join_point_op: { - assert(prim_op.operands.count == 0); - assert(prim_op.type_arguments.count == 0); - return qualified_type(arena, (QualifiedType) { .type = join_point_type(arena, (JoinPointType) { .yield_types = empty(arena) }), .is_uniform = true }); - } case sample_texture_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); From ccbcb7722552a030aa1e2956d61fb8fcf73eb797 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 15:08:28 +0200 Subject: [PATCH 486/693] fix a bunch more mem threading issues --- src/shady/passes/lower_callf.c | 5 +++-- src/shady/passes/lower_stack.c | 9 ++++----- src/shady/passes/lower_tailcalls.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 3c8eab059..0f7b165fc 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -132,13 +132,14 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { nargs = append_nodes(a, nargs, jp); // the body of the control is just an immediate tail-call + Node* control_case = case_(a, singleton(jp)); const Node* control_body = tail_call(a, (TailCall) { .target = ncallee, .args = nargs, + .mem = get_abstraction_mem(control_case), }); - Node* control_case = case_(a, singleton(jp)); set_abstraction_body(control_case, control_body); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, old->payload.call.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, gen_control(bb, strip_qualifiers(a, returned_types), control_case)); } default: break; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 451634717..d330d7cb0 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -81,10 +81,10 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { } if (push) { - set_abstraction_body(fun, finish_body(bb, fn_ret(a, (Return) { .args = empty(a) }))); + set_abstraction_body(fun, finish_body_with_return(bb, empty(a))); } else { assert(popped_value); - set_abstraction_body(fun, finish_body(bb, fn_ret(a, (Return) { .args = singleton(popped_value) }))); + set_abstraction_body(fun, finish_body_with_return(bb, singleton(popped_value))); } return fun; } @@ -150,7 +150,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* fn = gen_fn(ctx, element_type, push); Nodes args = singleton(rewrite_node(&ctx->rewriter, old->payload.push_stack.value)); - Nodes results = bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = args})); + gen_call(bb, fn_addr_helper(a, fn), args); return yield_values_and_wrap_in_block(bb, empty(a)); } @@ -163,8 +163,7 @@ static const Node* process_node(Context* ctx, const Node* old) { bool push = false; const Node* fn = gen_fn(ctx, element_type, push); - Nodes args = empty(a); - Nodes results = bind_instruction(bb, call(a, (Call) { .callee = fn_addr_helper(a, fn), .args = args})); + Nodes results = gen_call(bb, fn_addr_helper(a, fn), empty(a)); assert(results.count == 1); return yield_values_and_wrap_in_block(bb, results); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 5878e7d2d..2394f1e2d 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -196,7 +196,7 @@ static const Node* process(Context* ctx, const Node* old) { target = gen_conversion(bb, uint32_type(a), target); gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), singleton(target)); - return finish_body(bb, fn_ret(a, (Return) { .args = nodes(a, 0, NULL) })); + return finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) })); } case Join_TAG: { Join payload = old->payload.join; @@ -217,7 +217,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* tree_node = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 0))); gen_call(bb, access_decl(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); - return finish_body(bb, fn_ret(a, (Return) { .args = nodes(a, 0, NULL) })); + return finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) })); } case PtrType_TAG: { const Node* pointee = old->payload.ptr_type.pointed_type; From 8be3e0611378ac56fd2dde7faf4505b0b249affe Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 16:57:20 +0200 Subject: [PATCH 487/693] print: accurately deal with late-scheduled instructions --- src/shady/print.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/shady/print.c b/src/shady/print.c index 7da4984f2..69e0ce312 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -270,17 +270,24 @@ static String emit_abs_body(PrinterCtx* ctx, const CFNode* cfnode) { emit_node(ctx, get_abstraction_body(cfnode->node)); + Growy* g2 = new_growy(); + Printer* p2 = open_growy_as_printer(g2); + size_t count = cfnode->dominates->elements_count; for (size_t i = 0; i < count; i++) { const CFNode* dominated = read_list(const CFNode*, cfnode->dominates)[i]; assert(is_basic_block(dominated->node)); PrinterCtx bb_ctx = *ctx; - bb_ctx.printer = p; + bb_ctx.printer = p2; print_basic_block(&bb_ctx, dominated); if (i + 1 < count) newline(bb_ctx.printer); } + String bbs = printer_growy_unwrap(p2); + print(p, "%s", bbs); + free((void*) bbs); + String s = printer_growy_unwrap(p); String s2 = string(ctx->fn->arena, s); ctx->bb_printers[cfnode->rpo_index] = NULL; From cdacaa6c559dea6c35aa582c15c19a6dcaa693e1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 16:58:17 +0200 Subject: [PATCH 488/693] lift_indirect_targets works correctly with transitive dependencies --- src/shady/analysis/scheduler.c | 2 + src/shady/passes/lift_indirect_targets.c | 51 ++++++++++++++++++------ src/shady/passes/lower_tailcalls.c | 14 +++---- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c index 56865f111..90ed74cd3 100644 --- a/src/shady/analysis/scheduler.c +++ b/src/shady/analysis/scheduler.c @@ -63,6 +63,8 @@ CFNode* schedule_instruction(Scheduler* s, const Node* n) { if (n->tag == Param_TAG) { schedule_after(&s2.result, cfg_lookup(s->cfg, n->payload.param.abs)); + } else if (n->tag == BasicBlock_TAG) { + schedule_after(&s2.result, cfg_lookup(s->cfg, n)); } else if (n->tag == AbsMem_TAG) { schedule_after(&s2.result, cfg_lookup(s->cfg, n->payload.abs_mem.abs)); } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index dd73cb60d..c8cc08a55 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -61,6 +61,7 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, Nodes sp typedef struct { Visitor v; Scheduler* scheduler; + CFG* cfg; CFNode* start; struct Dict* frontier; } FreeFrontierVisitor; @@ -75,37 +76,60 @@ static bool is_dominated(CFNode* a, CFNode* b) { return false; } +static struct Dict* free_frontier(Scheduler* scheduler, CFG*, const Node* abs); + +static void copy_node_set(struct Dict* dst, struct Dict* src) { + size_t i = 0, j = 0; + const Node* key; + while (dict_iter(src, &i, &key, NULL)) { + insert_set_get_result(const Node*, dst, key); + } +} + static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { CFNode* where = schedule_instruction(v->scheduler, node); if (where) { - FreeFrontierVisitor vv = *v; - if (is_dominated(where, v->start)) { - visit_node_operands(&vv.v, IGNORE_ABSTRACTIONS_MASK | NcType, node); - } else { - insert_set_get_result(const Node*, v->frontier, node); + /*if (is_abstraction(node)) { + if (is_dominated(where, v->start)) { + struct Dict* frontier = free_frontier(v->scheduler, v->cfg, node); + copy_node_set(v->frontier, frontier); + destroy_dict(frontier); + } + } else*/ { + FreeFrontierVisitor vv = *v; + if (is_dominated(where, v->start)) { + visit_node_operands(&vv.v, NcAbstraction | NcDeclaration | NcType, node); + } else { + insert_set_get_result(const Node*, v->frontier, node); + } } } } -static Nodes free_frontier(Scheduler* scheduler, CFNode* start) { +static struct Dict* free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs) { FreeFrontierVisitor ffv = { .v = { .visit_node_fn = (VisitNodeFn) visit_free_frontier, }, .scheduler = scheduler, - .start = start, + .cfg = cfg, + .start = cfg_lookup(cfg, abs), .frontier = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), }; - visit_free_frontier(&ffv, get_abstraction_body(start->node)); - size_t count = entries_count_dict(ffv.frontier); + visit_free_frontier(&ffv, get_abstraction_body(abs)); + return ffv.frontier; +} + +static Nodes set2nodes(IrArena* a, struct Dict* set) { + size_t count = entries_count_dict(set); LARRAY(const Node*, tmp, count); size_t i = 0, j = 0; const Node* key; - while (dict_iter(ffv.frontier, &i, &key, NULL)) { + while (dict_iter(set, &i, &key, NULL)) { tmp[j++] = key; } assert(j == count); - return nodes(start->node->arena, count, tmp); + return nodes(a, count, tmp); } static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { @@ -119,8 +143,9 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { String name = get_abstraction_name_safe(liftee); Scheduler* scheduler = new_scheduler(cfg); - CFNode* cfn_liftee = cfg_lookup(cfg, liftee); - Nodes frontier = free_frontier(scheduler, cfn_liftee); + struct Dict* frontier_set = free_frontier(scheduler, cfg, liftee); + Nodes frontier = set2nodes(a, frontier_set); + destroy_dict(frontier_set); size_t recover_context_size = frontier.count; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 2394f1e2d..e6fc14f0b 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -295,14 +295,10 @@ void generate_top_level_dispatch_fn(Context* ctx) { if (count_iterations) iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, 1))); - const Node* break_terminator = merge_break(a, (MergeBreak) { .args = nodes(a, 0, NULL) }); - const Node* continue_terminator = merge_continue(a, (MergeContinue) { - .args = count_iterations ? singleton(iteration_count_plus_one) : nodes(a, 0, NULL), - }); - if (ctx->config->shader_diagnostics.max_top_iterations > 0) { const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); Node* true_case = case_(a, empty(a)); + const Node* break_terminator = merge_break(a, (MergeBreak) { .args = empty(a), .mem = get_abstraction_mem(true_case) }); set_abstraction_body(true_case, break_terminator); gen_if(loop_body_builder, empty(a), bail_condition, true_case, NULL); } @@ -319,14 +315,14 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } - set_abstraction_body(zero_if_true_lam, finish_body(zero_if_case_builder, break_terminator)); + set_abstraction_body(zero_if_true_lam, finish_body_with_loop_break(zero_if_case_builder, empty(a))); gen_if(zero_case_builder, empty(a), should_run, zero_if_true_lam, NULL); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_case_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } - set_abstraction_body(zero_case_lam, finish_body(zero_case_builder, continue_terminator)); + set_abstraction_body(zero_case_lam, finish_body_with_loop_continue(zero_case_builder, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); const Node* zero_lit = uint64_literal(a, 0); append_list(const Node*, literals, zero_lit); append_list(const Node*, cases, zero_case_lam); @@ -347,12 +343,12 @@ void generate_top_level_dispatch_fn(Context* ctx) { gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %ul with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } gen_call(if_builder, fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), empty(a)); - set_abstraction_body(if_true_lam, finish_body(if_builder, merge_selection(a, (MergeSelection) {.args = nodes(a, 0, NULL)}))); + set_abstraction_body(if_true_lam, finish_body_with_selection_merge(if_builder, empty(a))); Node* case_lam = case_(a, nodes(a, 0, NULL)); BodyBuilder* case_builder = begin_body_with_mem(a, get_abstraction_mem(case_lam)); gen_if(case_builder, empty(a), should_run, if_true_lam, NULL); - set_abstraction_body(case_lam, finish_body(case_builder, continue_terminator)); + set_abstraction_body(case_lam, finish_body_with_loop_continue(case_builder, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); append_list(const Node*, literals, fn_lit); append_list(const Node*, cases, case_lam); From 225278aa5f1a2843f62b8a99a0ef8b66347efea9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 17:13:30 +0200 Subject: [PATCH 489/693] c: remove namespacing macros --- src/backend/c/emit_c.c | 42 +++++----- src/backend/c/emit_c.h | 33 +++----- src/backend/c/emit_c_builtin.c | 2 +- src/backend/c/emit_c_control_flow.c | 34 ++++---- src/backend/c/emit_c_type.c | 38 ++++----- src/backend/c/emit_c_value.c | 122 ++++++++++++++-------------- 6 files changed, 132 insertions(+), 139 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 7174717e9..3556f30f8 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -82,30 +82,30 @@ CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Ty String interm = unique_name(emitter->arena, "intermediary_ptr_value"); const Type* ut = qualified_type_helper(ptr_type, true); const Type* vt = qualified_type_helper(ptr_type, false); - String lhs = emit_type(emitter, vt, interm); - print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, emit_type(emitter, ut, NULL), to_cvalue(emitter, term)); + String lhs = c_emit_type(emitter, vt, interm); + print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, c_emit_type(emitter, ut, NULL), to_cvalue(emitter, term)); return term_from_cvalue(interm); } -CTerm bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { +CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { String bind_to = unique_name(emitter->arena, ""); - emit_variable_declaration(emitter, p, t, bind_to, false, &term); + c_emit_variable_declaration(emitter, p, t, bind_to, false, &term); return term_from_cvalue(bind_to); } -void emit_pack_code(Printer* p, Strings src, String dst) { +void c_emit_pack_code(Printer* p, Strings src, String dst) { for (size_t i = 0; i < src.count; i++) { print(p, "\n%s->_%d = %s", dst, src.strings[i], i); } } -void emit_unpack_code(Printer* p, String src, Strings dst) { +void c_emit_unpack_code(Printer* p, String src, Strings dst) { for (size_t i = 0; i < dst.count; i++) { print(p, "\n%s = %s->_%d", dst.strings[i], src, i); } } -void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer) { +void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer) { assert((mut || initializer != NULL) && "unbound results are only allowed when creating a mutable local variable"); String prefix = ""; @@ -149,7 +149,7 @@ static void emit_lambda_body_at(Emitter* emitter, Printer* p, const Node* body, print(p, "\n"); } -String emit_lambda_body(Emitter* emitter, const Node* body, const Nodes* bbs) { +String c_emit_lambda_body(Emitter* emitter, const Node* body, const Nodes* bbs) { Growy* g = new_growy(); Printer* p = open_growy_as_printer(g); emit_lambda_body_at(emitter, p, body, bbs); @@ -231,18 +231,18 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S } if (init) - print(emitter->fn_decls, "\n%s%s = %s;", prefix, emit_type(emitter, type, decl_center), init); + print(emitter->fn_decls, "\n%s%s = %s;", prefix, c_emit_type(emitter, type, decl_center), init); else - print(emitter->fn_decls, "\n%s%s;", prefix, emit_type(emitter, type, decl_center)); + print(emitter->fn_decls, "\n%s%s;", prefix, c_emit_type(emitter, type, decl_center)); //if (!has_forward_declarations(emitter->config.dialect) || !init) // return; // - //String declaration = emit_type(emitter, type, decl_center); + //String declaration = c_emit_type(emitter, type, decl_center); //print(emitter->fn_decls, "\n%s;", declaration); } -void emit_decl(Emitter* emitter, const Node* decl) { +void c_emit_decl(Emitter* emitter, const Node* decl) { assert(is_declaration(decl)); CTerm* found = lookup_existing_term(emitter, decl); @@ -260,7 +260,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { case GlobalVariable_TAG: { String init = NULL; if (decl->payload.global_variable.init) - init = to_cvalue(emitter, emit_value(emitter, NULL, decl->payload.global_variable.init)); + init = to_cvalue(emitter, c_emit_value(emitter, NULL, decl->payload.global_variable.init)); AddressSpace ass = decl->payload.global_variable.address_space; if (ass == AsInput || ass == AsOutput) init = NULL; @@ -268,7 +268,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { const GlobalVariable* gvar = &decl->payload.global_variable; if (is_decl_builtin(decl)) { Builtin b = get_decl_builtin(decl); - CTerm t = emit_c_builtin(emitter, b); + CTerm t = c_emit_builtin(emitter, b); register_emitted(emitter, decl, t); return; } @@ -303,7 +303,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { case Function_TAG: { emit_as = term_from_cvalue(name); register_emitted(emitter, decl, emit_as); - String head = emit_fn_head(emitter, decl->type, name, decl); + String head = c_emit_fn_head(emitter, decl->type, name, decl); const Node* body = decl->payload.fun.body; if (body) { for (size_t i = 0; i < decl->payload.fun.params.count; i++) { @@ -313,7 +313,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { register_emitted(emitter, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } - String fn_body = emit_lambda_body(emitter, body, NULL); + String fn_body = c_emit_lambda_body(emitter, body, NULL); String free_me = fn_body; if (emitter->config.dialect == CDialect_ISPC) { // ISPC hack: This compiler (like seemingly all LLVM-based compilers) has broken handling of the execution mask - it fails to generated masked stores for the entry BB of a function that may be called non-uniformingly @@ -340,7 +340,7 @@ void emit_decl(Emitter* emitter, const Node* decl) { emit_as = term_from_cvalue(name); register_emitted(emitter, decl, emit_as); - String init = to_cvalue(emitter, emit_value(emitter, NULL, decl->payload.constant.value)); + String init = to_cvalue(emitter, c_emit_value(emitter, NULL, decl->payload.constant.value)); emit_global_variable_definition(emitter, AsGlobal, decl_center, decl->type, true, init); return; } @@ -349,8 +349,8 @@ void emit_decl(Emitter* emitter, const Node* decl) { register_emitted_type(emitter, decl, emitted); switch (emitter->config.dialect) { case CDialect_ISPC: - default: print(emitter->type_decls, "\ntypedef %s;", emit_type(emitter, decl->payload.nom_type.body, emitted)); break; - case CDialect_GLSL: emit_nominal_type_body(emitter, format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; + default: print(emitter->type_decls, "\ntypedef %s;", c_emit_type(emitter, decl->payload.nom_type.body, emitted)); break; + case CDialect_GLSL: c_emit_nominal_type_body(emitter, format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; } return; } @@ -453,7 +453,7 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module emitter.total_workgroup_size = emitter.arena->config.specializations.workgroup_size[0]; emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[1]; emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[2]; - print(emitter.type_decls, "\ntypedef %s;\n", emit_type(&emitter, arr_type(arena, (ArrType) { + print(emitter.type_decls, "\ntypedef %s;\n", c_emit_type(&emitter, arr_type(arena, (ArrType) { .size = int32_literal(arena, 3), .element_type = uint32_type(arena) }), "uvec3")); @@ -469,7 +469,7 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) - emit_decl(&emitter, decls.nodes[i]); + c_emit_decl(&emitter, decls.nodes[i]); destroy_printer(emitter.type_decls); destroy_printer(emitter.fn_decls); diff --git a/src/backend/c/emit_c.h b/src/backend/c/emit_c.h index ac82266bb..72bc8636e 100644 --- a/src/backend/c/emit_c.h +++ b/src/backend/c/emit_c.h @@ -9,13 +9,6 @@ #include "arena.h" #include "printer.h" -#define emit_type c_emit_type -#define emit_value c_emit_value -#define emit_instruction c_emit_instruction -#define emit_lambda_body c_emit_lambda_body -#define emit_decl c_emit_decl -#define emit_nominal_type_body c_emit_nominal_type_body - /// SSA-like things, you can read them typedef String CValue; /// non-SSA like things, they represent addresses @@ -65,28 +58,28 @@ CType* lookup_existing_type(Emitter* emitter, const Type*); CValue to_cvalue(Emitter*, CTerm); CAddr deref_term(Emitter*, CTerm); -void emit_decl(Emitter* emitter, const Node* decl); -CType emit_type(Emitter* emitter, const Type*, const char* identifier); -String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn); -void emit_nominal_type_body(Emitter* emitter, String name, const Type* type); +void c_emit_decl(Emitter* emitter, const Node* decl); +CType c_emit_type(Emitter* emitter, const Type*, const char* identifier); +String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn); +void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type); -void emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer); +void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer); -CTerm emit_value(Emitter* emitter, Printer*, const Node* value); -CTerm emit_c_builtin(Emitter*, Builtin); +CTerm c_emit_value(Emitter* emitter, Printer*, const Node* value); +CTerm c_emit_builtin(Emitter*, Builtin); String c_legalize_identifier(Emitter*, String); -String get_record_field_name(const Type* t, size_t i); +String c_get_record_field_name(const Type* t, size_t i); CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term); -CTerm bind_intermediary_result(Emitter*, Printer* p, const Type* t, CTerm term); +CTerm c_bind_intermediary_result(Emitter*, Printer* p, const Type* t, CTerm term); -CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction); +CTerm c_emit_instruction(Emitter* emitter, Printer* p, const Node* instruction); void c_emit_terminator(Emitter* emitter, Printer* p, const Node* terminator); -String emit_lambda_body (Emitter*, const Node*, const Nodes* nested_basic_blocks); +String c_emit_lambda_body(Emitter*, const Node*, const Nodes* nested_basic_blocks); -void emit_pack_code(Printer*, Strings, String dst); -void emit_unpack_code(Printer*, String src, Strings dst); +void c_emit_pack_code(Printer*, Strings, String dst); +void c_emit_unpack_code(Printer*, String src, Strings dst); #define free_tmp_str(s) free((char*) (s)) diff --git a/src/backend/c/emit_c_builtin.c b/src/backend/c/emit_c_builtin.c index ba4e61493..d6b5b6a41 100644 --- a/src/backend/c/emit_c_builtin.c +++ b/src/backend/c/emit_c_builtin.c @@ -18,7 +18,7 @@ static String glsl_builtins[BuiltinsCount] = { [BuiltinPosition] = "gl_Position", }; -CTerm emit_c_builtin(Emitter* emitter, Builtin b) { +CTerm c_emit_builtin(Emitter* emitter, Builtin b) { String name = NULL; switch(emitter->config.dialect) { case CDialect_ISPC: name = ispc_builtins[b]; break; diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index 5503d8041..e5f6c3053 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -18,10 +18,10 @@ static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String g assert(name); names[i] = unique_name(emitter->arena, name); if (init_values) { - CTerm initializer = emit_value(emitter, p, init_values->nodes[i]); - emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); + CTerm initializer = c_emit_value(emitter, p, init_values->nodes[i]); + c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); } else - emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); + c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); } return strings(emitter->arena, types.count, names); } @@ -32,13 +32,13 @@ static void emit_if(Emitter* emitter, Printer* p, If if_) { sub_emiter.phis.selection = ephis; assert(get_abstraction_params(if_.if_true).count == 0); - String true_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_true), NULL); - CValue condition = to_cvalue(emitter, emit_value(emitter, p, if_.condition)); + String true_body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_true), NULL); + CValue condition = to_cvalue(emitter, c_emit_value(emitter, p, if_.condition)); print(p, "\nif (%s) { %s}", condition, true_body); free_tmp_str(true_body); if (if_.if_false) { assert(get_abstraction_params(if_.if_false).count == 0); - String false_body = emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_false), NULL); + String false_body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_false), NULL); print(p, " else {%s}", false_body); free_tmp_str(false_body); } @@ -65,14 +65,14 @@ static void emit_match(Emitter* emitter, Printer* p, Match match) { // We could do GOTO for C, but at the cost of arguably even more noise in the output, and two different codepaths. // I don't think it's quite worth it, just like it's not worth doing some data-flow based solution either. - CValue inspectee = to_cvalue(emitter, emit_value(emitter, p, match.inspect)); + CValue inspectee = to_cvalue(emitter, c_emit_value(emitter, p, match.inspect)); bool first = true; LARRAY(CValue, literals, match.cases.count); for (size_t i = 0; i < match.cases.count; i++) { - literals[i] = to_cvalue(emitter, emit_value(emitter, p, match.literals.nodes[i])); + literals[i] = to_cvalue(emitter, c_emit_value(emitter, p, match.literals.nodes[i])); } for (size_t i = 0; i < match.cases.count; i++) { - String case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match.cases.nodes[i]), NULL); + String case_body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(match.cases.nodes[i]), NULL); print(p, "\n"); if (!first) print(p, "else "); @@ -81,7 +81,7 @@ static void emit_match(Emitter* emitter, Printer* p, Match match) { first = false; } if (match.default_case) { - String default_case_body = emit_lambda_body(&sub_emiter, get_abstraction_body(match.default_case), NULL); + String default_case_body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(match.default_case), NULL); print(p, "\nelse { %s}", default_case_body); free_tmp_str(default_case_body); } @@ -113,7 +113,7 @@ static void emit_loop(Emitter* emitter, Printer* p, Loop loop) { Strings ephis = emit_variable_declarations(emitter, p, "loop_break_phi", NULL, loop.yield_types, true, NULL); sub_emiter.phis.loop_break = ephis; - String body = emit_lambda_body(&sub_emiter, get_abstraction_body(loop.body), NULL); + String body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(loop.body), NULL); print(p, "\nwhile(true) { %s}", body); free_tmp_str(body); @@ -192,13 +192,13 @@ void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* ter if (args.count == 0) { print(block_printer, "\nreturn;"); } else if (args.count == 1) { - print(block_printer, "\nreturn %s;", to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[0]))); + print(block_printer, "\nreturn %s;", to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[0]))); } else { String packed = unique_name(emitter->arena, "pack_return"); LARRAY(CValue, values, args.count); for (size_t i = 0; i < args.count; i++) - values[i] = to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i])); - emit_pack_code(block_printer, strings(emitter->arena, args.count, values), packed); + values[i] = to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[i])); + c_emit_pack_code(block_printer, strings(emitter->arena, args.count, values), packed); print(block_printer, "\nreturn %s;", packed); } break; @@ -208,7 +208,7 @@ void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* ter Phis phis = emitter->phis.selection; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[i]))); break; } @@ -217,7 +217,7 @@ void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* ter Phis phis = emitter->phis.loop_continue; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[i]))); print(block_printer, "\ncontinue;"); break; } @@ -226,7 +226,7 @@ void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* ter Phis phis = emitter->phis.loop_break; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, emit_value(emitter, block_printer, args.nodes[i]))); + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[i]))); print(block_printer, "\nbreak;"); break; } diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index 532377d65..790836441 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -13,7 +13,7 @@ #pragma GCC diagnostic error "-Wswitch" -String get_record_field_name(const Type* t, size_t i) { +String c_get_record_field_name(const Type* t, size_t i) { assert(t->tag == RecordType_TAG); RecordType r = t->payload.record_type; assert(i < r.members.count); @@ -23,7 +23,7 @@ String get_record_field_name(const Type* t, size_t i) { return r.names.strings[i]; } -void emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { +void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { assert(type->tag == RecordType_TAG); Growy* g = new_growy(); Printer* p = open_growy_as_printer(g); @@ -31,8 +31,8 @@ void emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { print(p, "\n%s {", name); indent(p); for (size_t i = 0; i < type->payload.record_type.members.count; i++) { - String member_identifier = get_record_field_name(type, i); - print(p, "\n%s;", emit_type(emitter, type->payload.record_type.members.nodes[i], member_identifier)); + String member_identifier = c_get_record_field_name(type, i); + print(p, "\n%s;", c_emit_type(emitter, type->payload.record_type.members.nodes[i], member_identifier)); } deindent(p); print(p, "\n};\n"); @@ -43,7 +43,7 @@ void emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { destroy_printer(p); } -String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn) { +String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn) { assert(fn_type->tag == FnType_TAG); assert(!fn || fn->type == fn_type); Nodes codom = fn_type->payload.fn_type.return_types; @@ -67,7 +67,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const String param_name; String variable_name = get_value_name_unsafe(fn->payload.fun.params.nodes[i]); param_name = format_string_interned(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); - print(paramp, emit_type(emitter, params.nodes[i]->type, param_name)); + print(paramp, c_emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { print(paramp, ", "); } @@ -79,7 +79,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const print(paramp, ", "); } for (size_t i = 0; i < dom.count; i++) { - print(paramp, emit_type(emitter, dom.nodes[i], "")); + print(paramp, c_emit_type(emitter, dom.nodes[i], "")); if (i + 1 < dom.count) { print(paramp, ", "); } @@ -99,7 +99,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const } free_tmp_str(parameters); - String c_decl = emit_type(emitter, maybe_tuple_helper(emitter->arena, codom), center); + String c_decl = c_emit_type(emitter, maybe_tuple_helper(emitter->arena, codom), center); if (entry_point) { switch (emitter->config.dialect) { case CDialect_C11: @@ -120,7 +120,7 @@ String emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const return c_decl; } -String emit_type(Emitter* emitter, const Type* type, const char* center) { +String c_emit_type(Emitter* emitter, const Type* type, const char* center) { if (center == NULL) center = ""; @@ -216,7 +216,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { emitted = unique_name(emitter->arena, "Record"); String prefixed = format_string_arena(emitter->arena->arena, "struct %s", emitted); - emit_nominal_type_body(emitter, prefixed, type); + c_emit_nominal_type_body(emitter, prefixed, type); // C puts structs in their own namespace so we always need the prefix if (emitter->config.dialect == CDialect_C11) emitted = prefixed; @@ -226,22 +226,22 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { case Type_QualifiedType_TAG: switch (emitter->config.dialect) { default: - return emit_type(emitter, type->payload.qualified_type.type, center); + return c_emit_type(emitter, type->payload.qualified_type.type, center); case CDialect_ISPC: if (type->payload.qualified_type.is_uniform) - return emit_type(emitter, type->payload.qualified_type.type, format_string_arena(emitter->arena->arena, "uniform %s", center)); + return c_emit_type(emitter, type->payload.qualified_type.type, format_string_arena(emitter->arena->arena, "uniform %s", center)); else - return emit_type(emitter, type->payload.qualified_type.type, format_string_arena(emitter->arena->arena, "varying %s", center)); + return c_emit_type(emitter, type->payload.qualified_type.type, format_string_arena(emitter->arena->arena, "varying %s", center)); } case Type_PtrType_TAG: { - CType t = emit_type(emitter, type->payload.ptr_type.pointed_type, format_string_arena(emitter->arena->arena, "* %s", center)); + CType t = c_emit_type(emitter, type->payload.ptr_type.pointed_type, format_string_arena(emitter->arena->arena, "* %s", center)); // we always emit pointers to _uniform_ data, no exceptions if (emitter->config.dialect == CDialect_ISPC) t = format_string_arena(emitter->arena->arena, "uniform %s", t); return t; } case Type_FnType_TAG: { - return emit_fn_head(emitter, type, center, NULL); + return c_emit_fn_head(emitter, type, center, NULL); } case Type_ArrType_TAG: { emitted = unique_name(emitter->arena, "Array"); @@ -251,7 +251,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { const Node* size = type->payload.arr_type.size; if (!size && emitter->config.decay_unsized_arrays) - return emit_type(emitter, type->payload.arr_type.element_type, center); + return c_emit_type(emitter, type->payload.arr_type.element_type, center); print(p, "\n%s {", prefixed); indent(p); @@ -260,7 +260,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { inner_decl_rhs = format_string_arena(emitter->arena->arena, "arr[%zu]", get_int_literal_value(*resolve_to_int_literal(size), false)); else inner_decl_rhs = format_string_arena(emitter->arena->arena, "arr[0]"); - print(p, "\n%s;", emit_type(emitter, type->payload.arr_type.element_type, inner_decl_rhs)); + print(p, "\n%s;", c_emit_type(emitter, type->payload.arr_type.element_type, inner_decl_rhs)); deindent(p); print(p, "\n};\n"); growy_append_bytes(g, 1, (char[]) { '\0' }); @@ -299,7 +299,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { } case CDialect_ISPC: error("Please lower to something else") case CDialect_C11: { - emitted = emit_type(emitter, element_type, NULL); + emitted = c_emit_type(emitter, element_type, NULL); emitted = format_string_arena(emitter->arena->arena, "__attribute__ ((vector_size (%d * sizeof(%s) ))) %s", width, emitted, emitted); break; } @@ -307,7 +307,7 @@ String emit_type(Emitter* emitter, const Type* type, const char* center) { break; } case Type_TypeDeclRef_TAG: { - emit_decl(emitter, type->payload.type_decl_ref.decl); + c_emit_decl(emitter, type->payload.type_decl_ref.decl); emitted = *lookup_existing_type(emitter, type->payload.type_decl_ref.decl); goto type_goes_on_left; } diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index f2a1be32e..0b7132674 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -44,7 +44,7 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e return is_stringy ? StringLit : CharsLit; } else { for (size_t i = 0; i < c.count; i++) { - print(p, to_cvalue(e, emit_value(e, block_printer, c.nodes[i]))); + print(p, to_cvalue(e, c_emit_value(e, block_printer, c.nodes[i]))); if (i + 1 < c.count) print(p, ", "); } @@ -53,7 +53,7 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e } } -CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { +CTerm c_emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { CTerm* found = lookup_existing_term(emitter, value); if (found) return *found; @@ -108,9 +108,9 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { case Value_False_TAG: return term_from_cvalue("false"); case Value_Undef_TAG: { if (emitter->config.dialect == CDialect_GLSL) - return emit_value(emitter, block_printer, get_default_zero_value(emitter->arena, value->payload.undef.type)); + return c_emit_value(emitter, block_printer, get_default_zero_value(emitter->arena, value->payload.undef.type)); String name = unique_name(emitter->arena, "undef"); - emit_variable_declaration(emitter, block_printer, value->type, name, true, NULL); + c_emit_variable_declaration(emitter, block_printer, value->type, name, true, NULL); // emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); emitted = name; break; @@ -137,7 +137,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { } } else { for (size_t i = 0; i < elements.count; i++) { - print(p, "%s", to_cvalue(emitter, emit_value(emitter, block_printer, elements.nodes[i]))); + print(p, "%s", to_cvalue(emitter, c_emit_value(emitter, block_printer, elements.nodes[i]))); if (i + 1 < elements.count) print(p, ", "); } @@ -154,7 +154,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { if (block_printer) { String tmp = unique_name(emitter->arena, "composite"); - print(block_printer, "\n%s = { %s };", emit_type(emitter, value->type, tmp), emitted); + print(block_printer, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); emitted = tmp; } else { // this requires us to end up in the initialisation side of a declaration @@ -167,13 +167,13 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { // If we're C89 (ew) if (!emitter->config.allow_compound_literals) goto no_compound_literals; - emitted = format_string_arena(emitter->arena->arena, "((%s) { %s })", emit_type(emitter, value->type, NULL), emitted); + emitted = format_string_arena(emitter->arena->arena, "((%s) { %s })", c_emit_type(emitter, value->type, NULL), emitted); break; case CDialect_GLSL: if (type->tag != PackType_TAG) goto no_compound_literals; // GLSL doesn't have compound literals, but it does have constructor syntax for vectors - emitted = format_string_arena(emitter->arena->arena, "%s(%s)", emit_type(emitter, value->type, NULL), emitted); + emitted = format_string_arena(emitter->arena->arena, "%s(%s)", c_emit_type(emitter, value->type, NULL), emitted); break; } @@ -211,7 +211,7 @@ CTerm emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { } case Value_RefDecl_TAG: { const Node* decl = value->payload.ref_decl.decl; - emit_decl(emitter, decl); + c_emit_decl(emitter, decl); if (emitter->config.dialect == CDialect_ISPC && decl->tag == GlobalVariable_TAG) { if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !is_decl_builtin(decl)) { @@ -351,20 +351,20 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, Printer* p, const ISe switch (entry->style) { case OsInfix: { - CTerm a = emit_value(emitter, p, operands.nodes[0]); - CTerm b = emit_value(emitter, p, operands.nodes[1]); + CTerm a = c_emit_value(emitter, p, operands.nodes[0]); + CTerm b = c_emit_value(emitter, p, operands.nodes[1]); *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s %s %s", to_cvalue(emitter, a), operator_str, to_cvalue(emitter, b))); break; } case OsPrefix: { - CTerm operand = emit_value(emitter, p, operands.nodes[0]); + CTerm operand = c_emit_value(emitter, p, operands.nodes[0]); *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s%s", operator_str, to_cvalue(emitter, operand))); break; } case OsCall: { LARRAY(CTerm, cops, operands.count); for (size_t i = 0; i < operands.count; i++) - cops[i] = emit_value(emitter, p, operands.nodes[i]); + cops[i] = c_emit_value(emitter, p, operands.nodes[i]); if (operands.count == 1) *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", operator_str, to_cvalue(emitter, cops[0]))); else { @@ -439,26 +439,26 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { break; } case min_op: { - CValue a = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); - CValue b = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[1])); + CValue a = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); + CValue b = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); term = term_from_cvalue(format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, b, a)); break; } case max_op: { - CValue a = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); - CValue b = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[1])); + CValue a = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); + CValue b = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); term = term_from_cvalue(format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, a, b)); break; } case sign_op: { - CValue src = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); + CValue src = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); term = term_from_cvalue(format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); break; } case fma_op: { - CValue a = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[0])); - CValue b = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[1])); - CValue c = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[2])); + CValue a = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[0])); + CValue b = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); + CValue c = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[2])); switch (emitter->config.dialect) { case CDialect_C11: case CDialect_CUDA: { @@ -475,9 +475,9 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { case lshift_op: case rshift_arithm_op: case rshift_logical_op: { - CValue src = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); + CValue src = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); const Node* offset = prim_op->operands.nodes[1]; - CValue c_offset = to_cvalue(emitter, emit_value(emitter, p, offset)); + CValue c_offset = to_cvalue(emitter, c_emit_value(emitter, p, offset)); if (emitter->config.dialect == CDialect_GLSL) { if (get_unqualified_type(offset->type)->payload.int_type.width == IntTy64) c_offset = format_string_arena(arena->arena, "int(%s)", c_offset); @@ -498,35 +498,35 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { } const Node* index = first(prim_op->operands); uint64_t index_literal = get_int_literal_value(*resolve_to_int_literal(index), false); - String member_name = get_record_field_name(t, index_literal); + String member_name = c_get_record_field_name(t, index_literal); term = term_from_cvalue(format_string_arena(emitter->arena->arena, "offsetof(%s, %s)", c_emit_type(emitter, t, NULL), member_name)); break; } case select_op: { assert(prim_op->operands.count == 3); - CValue condition = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[0])); - CValue l = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[1])); - CValue r = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[2])); + CValue condition = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[0])); + CValue l = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); + CValue r = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[2])); term = term_from_cvalue(format_string_arena(emitter->arena->arena, "(%s) ? (%s) : (%s)", condition, l, r)); break; } case convert_op: { - CTerm src = emit_value(emitter, p, first(prim_op->operands)); + CTerm src = c_emit_value(emitter, p, first(prim_op->operands)); const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); if (emitter->config.dialect == CDialect_GLSL) { if (is_glsl_scalar_type(src_type) && is_glsl_scalar_type(dst_type)) { - CType t = emit_type(emitter, dst_type, NULL); + CType t = c_emit_type(emitter, dst_type, NULL); term = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", t, to_cvalue(emitter, src))); } else assert(false); } else { - CType t = emit_type(emitter, dst_type, NULL); + CType t = c_emit_type(emitter, dst_type, NULL); term = term_from_cvalue(format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src))); } break; } case reinterpret_op: { - CTerm src_value = emit_value(emitter, p, first(prim_op->operands)); + CTerm src_value = c_emit_value(emitter, p, first(prim_op->operands)); const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); switch (emitter->config.dialect) { @@ -534,8 +534,8 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { case CDialect_C11: { String src = unique_name(arena, "bitcast_src"); String dst = unique_name(arena, "bitcast_result"); - print(p, "\n%s = %s;", emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); - print(p, "\n%s;", emit_type(emitter, dst_type, dst)); + print(p, "\n%s = %s;", c_emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); + print(p, "\n%s;", c_emit_type(emitter, dst_type, dst)); print(p, "\nmemcpy(&%s, &%s, sizeof(%s));", dst, src, src); return term_from_cvalue(dst); } @@ -564,7 +564,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { } if (conv_fn) { CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, to_cvalue(emitter, src_value))); - return bind_intermediary_result(emitter, p, node->type, converted); + return c_bind_intermediary_result(emitter, p, node->type, converted); } error_print("glsl: unsupported bit cast from "); log_node(ERROR, src_type); @@ -586,16 +586,16 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { break; } CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); - return bind_intermediary_result(emitter, p, node->type, converted); + return c_bind_intermediary_result(emitter, p, node->type, converted); break; } else if (src_type->tag == Float_TAG) { assert(dst_type->tag == Int_TAG); CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "intbits(%s)", to_cvalue(emitter, src_value))); - return bind_intermediary_result(emitter, p, node->type, converted); + return c_bind_intermediary_result(emitter, p, node->type, converted); break; } - CType t = emit_type(emitter, dst_type, NULL); + CType t = c_emit_type(emitter, dst_type, NULL); return term_from_cvalue(format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src_value))); } } @@ -604,7 +604,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { case insert_op: case extract_dynamic_op: case extract_op: { - CValue acc = to_cvalue(emitter, emit_value(emitter, p, first(prim_op->operands))); + CValue acc = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); bool insert = prim_op->op == insert_op; if (insert) { @@ -643,7 +643,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { break; } case Type_ArrType_TAG: { - acc = index_into_array(emitter, t, term_from_cvar(acc), emit_value(emitter, p, index)); + acc = index_into_array(emitter, t, term_from_cvar(acc), c_emit_value(emitter, p, index)); break; } default: @@ -652,7 +652,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { } if (insert) { - print(p, "\n%s = %s;", acc, to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[1]))); + print(p, "\n%s = %s;", acc, to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1]))); break; } @@ -663,8 +663,8 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { String dst = unique_name(arena, "shuffled"); const Node* lhs = prim_op->operands.nodes[0]; const Node* rhs = prim_op->operands.nodes[1]; - String lhs_e = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[0])); - String rhs_e = to_cvalue(emitter, emit_value(emitter, p, prim_op->operands.nodes[1])); + String lhs_e = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[0])); + String rhs_e = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); const Type* lhs_t = lhs->type; const Type* rhs_t = rhs->type; bool lhs_u = deconstruct_qualified_type(&lhs_t); @@ -688,7 +688,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { } case subgroup_assume_uniform_op: { if (emitter->config.dialect != CDialect_ISPC) { - return emit_value(emitter, p, prim_op->operands.nodes[0]); + return c_emit_value(emitter, p, prim_op->operands.nodes[0]); } } case empty_mask_op: @@ -707,7 +707,7 @@ static CTerm emit_ext_instruction(Emitter* emitter, Printer* p, ExtInstr instr) if (strcmp(instr.set, "spirv.core") == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { - CValue value = to_cvalue(emitter, emit_value(emitter, p, first(instr.operands))); + CValue value = to_cvalue(emitter, c_emit_value(emitter, p, first(instr.operands))); switch (emitter->config.dialect) { case CDialect_CUDA: return term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; case CDialect_ISPC: return term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; @@ -753,7 +753,7 @@ static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { print(paramsp, ", "); } for (size_t i = 0; i < args.count; i++) { - print(paramsp, to_cvalue(emitter, emit_value(emitter, p, args.nodes[i]))); + print(paramsp, to_cvalue(emitter, c_emit_value(emitter, p, args.nodes[i]))); if (i + 1 < args.count) print(paramsp, ", "); } @@ -763,12 +763,12 @@ static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { if (callee->tag == FnAddr_TAG) e_callee = get_declaration_name(callee->payload.fn_addr.fn); else - e_callee = to_cvalue(emitter, emit_value(emitter, p, callee)); + e_callee = to_cvalue(emitter, c_emit_value(emitter, p, callee)); String params = printer_growy_unwrap(paramsp); CTerm called = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); - called = bind_intermediary_result(emitter, p, call->type, called); + called = c_bind_intermediary_result(emitter, p, call->type, called); free_tmp_str(params); return called; @@ -776,7 +776,7 @@ static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { IrArena* arena = emitter->arena; - CTerm acc = emit_value(emitter, p, lea.ptr); + CTerm acc = c_emit_value(emitter, p, lea.ptr); const Type* src_qtype = lea.ptr->type; bool uniform = is_qualified_type_uniform(src_qtype); @@ -785,12 +785,12 @@ static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { const IntLiteral* offset_static_value = resolve_to_int_literal(lea.offset); if (!offset_static_value || offset_static_value->value != 0) { - CTerm offset = emit_value(emitter, p, lea.offset); + CTerm offset = c_emit_value(emitter, p, lea.offset); // we sadly need to drop to the value level (aka explicit pointer arithmetic) to do this // this means such code is never going to be legal in GLSL // also the cast is to account for our arrays-in-structs hack const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); - acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &(%s)[%s])", emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); + acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &(%s)[%s])", c_emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); uniform &= is_qualified_type_uniform(lea.offset->type); } @@ -801,7 +801,7 @@ static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { uniform &= is_qualified_type_uniform(selector->type); switch (is_type(pointee_type)) { case ArrType_TAG: { - CTerm index = emit_value(emitter, p, selector); + CTerm index = c_emit_value(emitter, p, selector); acc = term_from_cvar(index_into_array(emitter, pointee_type, acc, index)); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.arr_type.element_type, @@ -820,13 +820,13 @@ static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { // See https://github.com/ispc/ispc/issues/2496 if (emitter->config.dialect == CDialect_ISPC) { String interm = unique_name(arena, "lea_intermediary_ptr_value"); - print(p, "\n%s = %s;", emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); + print(p, "\n%s = %s;", c_emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); acc = term_from_cvalue(interm); } assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a record need to be constant"); size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); - String field_name = get_record_field_name(pointee_type, static_index); + String field_name = c_get_record_field_name(pointee_type, static_index); acc = term_from_cvar(format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.record_type.members.nodes[static_index], @@ -849,7 +849,7 @@ static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { } if (emitter->config.dialect == CDialect_ISPC) - acc = bind_intermediary_result(emitter, p, curr_ptr_type, acc); + acc = c_bind_intermediary_result(emitter, p, curr_ptr_type, acc); return acc; } @@ -857,7 +857,7 @@ static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* type) { String variable_name = unique_name(emitter->arena, "alloca"); CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; - emit_variable_declaration(emitter, p, type, variable_name, true, NULL); + c_emit_variable_declaration(emitter, p, type, variable_name, true, NULL); if (emitter->config.dialect == CDialect_ISPC) { variable = ispc_varying_ptr_helper(emitter, p, type, variable); } @@ -898,7 +898,7 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { } Nodes results2 = instruction->payload.compound_instruction.results; for (size_t i = 0; i < results2.count; i++) { - outputs.results[0] = emit_value(emitter, p, results2.nodes[i]); + outputs.results[0] = c_emit_value(emitter, p, results2.nodes[i]); outputs.binding[0] = NoBinding; } return; @@ -908,9 +908,9 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { case Instruction_LocalAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.local_alloc.type); case Instruction_Load_TAG: { Load payload = instruction->payload.load; - CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, payload.ptr)); + CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, p, payload.ptr)); // we must bind the intermediary result here, otherwise we duplicate the load everwhere it is consumed - return bind_intermediary_result(emitter, p, instruction->type, term_from_cvalue(dereferenced)); + return c_bind_intermediary_result(emitter, p, instruction->type, term_from_cvalue(dereferenced)); } case Instruction_Store_TAG: { Store payload = instruction->payload.store; @@ -918,8 +918,8 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { bool addr_uniform = deconstruct_qualified_type(&addr_type); bool value_uniform = is_qualified_type_uniform(payload.value->type); assert(addr_type->tag == PtrType_TAG); - CAddr dereferenced = deref_term(emitter, emit_value(emitter, p, payload.ptr)); - CValue cvalue = to_cvalue(emitter, emit_value(emitter, p, payload.value)); + CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, p, payload.ptr)); + CValue cvalue = to_cvalue(emitter, c_emit_value(emitter, p, payload.value)); // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this if (emitter->config.dialect == CDialect_ISPC && addr_uniform && is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) cvalue = format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); @@ -942,7 +942,7 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { case Instruction_DebugPrintf_TAG: { String args_list = format_string_interned(emitter->arena, "\"%s\"", instruction->payload.debug_printf.string); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) { - CValue str = to_cvalue(emitter, emit_value(emitter, p, instruction->payload.debug_printf.args.nodes[i])); + CValue str = to_cvalue(emitter, c_emit_value(emitter, p, instruction->payload.debug_printf.args.nodes[i])); if (emitter->config.dialect == CDialect_ISPC && i > 0) str = format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); From ecb81120fa6b630e6a76b4a20ba2e961bfe2a050 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 18:24:06 +0200 Subject: [PATCH 490/693] dump: make it work when a CFG can't be built --- src/shady/print.c | 58 +++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/shady/print.c b/src/shady/print.c index 69e0ce312..fddd295b7 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -238,7 +238,7 @@ static void print_yield_types(PrinterCtx* ctx, Nodes types) { } } -static String emit_abs_body(PrinterCtx* ctx, const CFNode* cfnode); +static String emit_abs_body(PrinterCtx* ctx, const Node* abs); static void print_basic_block(PrinterCtx* ctx, const CFNode* node) { const Node* bb = node->node; @@ -258,39 +258,43 @@ static void print_basic_block(PrinterCtx* ctx, const CFNode* node) { printf(" {"); indent(ctx->printer); printf("\n"); - printf("%s", emit_abs_body(ctx, node)); + printf("%s", emit_abs_body(ctx, bb)); deindent(ctx->printer); printf("\n}"); } -static String emit_abs_body(PrinterCtx* ctx, const CFNode* cfnode) { +static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { Growy* g = new_growy(); Printer* p = open_growy_as_printer(g); - ctx->bb_printers[cfnode->rpo_index] = p; - - emit_node(ctx, get_abstraction_body(cfnode->node)); - - Growy* g2 = new_growy(); - Printer* p2 = open_growy_as_printer(g2); - - size_t count = cfnode->dominates->elements_count; - for (size_t i = 0; i < count; i++) { - const CFNode* dominated = read_list(const CFNode*, cfnode->dominates)[i]; - assert(is_basic_block(dominated->node)); - PrinterCtx bb_ctx = *ctx; - bb_ctx.printer = p2; - print_basic_block(&bb_ctx, dominated); - if (i + 1 < count) - newline(bb_ctx.printer); - } + CFNode* cfnode = ctx->cfg ? cfg_lookup(ctx->cfg, abs) : NULL; + if (cfnode) + ctx->bb_printers[cfnode->rpo_index] = p; + + emit_node(ctx, get_abstraction_body(abs)); + + if (cfnode) { + Growy* g2 = new_growy(); + Printer* p2 = open_growy_as_printer(g2); + size_t count = cfnode->dominates->elements_count; + for (size_t i = 0; i < count; i++) { + const CFNode* dominated = read_list(const CFNode*, cfnode->dominates)[i]; + assert(is_basic_block(dominated->node)); + PrinterCtx bb_ctx = *ctx; + bb_ctx.printer = p2; + print_basic_block(&bb_ctx, dominated); + if (i + 1 < count) + newline(bb_ctx.printer); + } - String bbs = printer_growy_unwrap(p2); - print(p, "%s", bbs); - free((void*) bbs); + String bbs = printer_growy_unwrap(p2); + print(p, "%s", bbs); + free((void*) bbs); + } String s = printer_growy_unwrap(p); String s2 = string(ctx->fn->arena, s); - ctx->bb_printers[cfnode->rpo_index] = NULL; + if (cfnode) + ctx->bb_printers[cfnode->rpo_index] = NULL; free((void*) s); return s2; } @@ -299,11 +303,11 @@ static void print_function(PrinterCtx* ctx, const Node* node) { assert(is_function(node)); PrinterCtx sub_ctx = *ctx; - if (true || node->arena->config.name_bound) { + sub_ctx.fn = node; + if (node->arena->config.name_bound) { CFG* cfg = build_fn_cfg(node); sub_ctx.cfg = cfg; sub_ctx.scheduler = new_scheduler(cfg); - sub_ctx.fn = node; sub_ctx.bb_growies = calloc(sizeof(size_t), cfg->size); sub_ctx.bb_printers = calloc(sizeof(size_t), cfg->size); if (node->arena->config.check_types && node->arena->config.allow_fold) { @@ -323,7 +327,7 @@ static void print_function(PrinterCtx* ctx, const Node* node) { indent(ctx->printer); printf("\n"); - printf("%s", emit_abs_body(ctx, ctx->cfg->entry)); + printf("%s", emit_abs_body(ctx, node)); if (sub_ctx.cfg) { if (sub_ctx.uses) From 1d3e5e8fe744afa51b01e7c04866ae3a2065a93e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 18:24:20 +0200 Subject: [PATCH 491/693] brought back C backend ! --- src/backend/c/emit_c.c | 130 ++++++++-------- src/backend/c/emit_c.h | 44 +++--- src/backend/c/emit_c_control_flow.c | 173 +++++++++++----------- src/backend/c/emit_c_type.c | 2 +- src/backend/c/emit_c_value.c | 220 ++++++++++++++++------------ 5 files changed, 300 insertions(+), 269 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 3556f30f8..0a951a341 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -4,6 +4,8 @@ #include "../shady/ir_private.h" #include "../shady/compile.h" #include "../shady/transform/ir_gen_helpers.h" +#include "../shady/analysis/cfg.h" +#include "../shady/analysis/scheduler.h" #include "shady_cuda_prelude_src.h" #include "shady_cuda_builtins_src.h" @@ -20,6 +22,32 @@ #pragma GCC diagnostic error "-Wswitch" +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + +void register_emitted(Emitter* emitter, FnEmitter* fn, const Node* node, CTerm as) { + //assert(as.value || as.var); + insert_dict(const Node*, CTerm, fn ? fn->emitted_terms : emitter->emitted_terms, node, as); +} + +CTerm* lookup_existing_term(Emitter* emitter, FnEmitter* fn, const Node* node) { + CTerm* found = NULL; + if (fn) + found = find_value_dict(const Node*, CTerm, fn->emitted_terms, node); + if (!found) + found = find_value_dict(const Node*, CTerm, emitter->emitted_terms, node); + return found; +} + +void register_emitted_type(Emitter* emitter, const Node* node, String as) { + insert_dict(const Node*, String, emitter->emitted_types, node, as); +} + +CType* lookup_existing_type(Emitter* emitter, const Type* node) { + CType* found = find_value_dict(const Node*, CType, emitter->emitted_types, node); + return found; +} + CValue to_cvalue(SHADY_UNUSED Emitter* e, CTerm term) { if (term.value) return term.value; @@ -133,31 +161,7 @@ void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const print(block_printer, "\n%s%s;", prefix, decl); } -static void emit_lambda_body_at(Emitter* emitter, Printer* p, const Node* body, const Nodes* bbs) { - assert(is_terminator(body)); - //print(p, "{"); - indent(p); - - c_emit_terminator(emitter, p, body); - - if (bbs && bbs->count > 0) { - assert(emitter->config.dialect != CDialect_GLSL); - error("TODO"); - } - - deindent(p); - print(p, "\n"); -} - -String c_emit_lambda_body(Emitter* emitter, const Node* body, const Nodes* bbs) { - Growy* g = new_growy(); - Printer* p = open_growy_as_printer(g); - emit_lambda_body_at(emitter, p, body, bbs); - growy_append_bytes(g, 1, (char[]) { 0 }); - return printer_growy_unwrap(p); -} - -static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, String decl_center, const Type* type, bool constant, String init) { +void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String name, const Type* type, bool constant, String init) { String prefix = NULL; bool is_fs = emitter->compiler_config->specialization.execution_model == EmFragment; @@ -167,7 +171,7 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S if (as != AsGeneric) warn_print_once(c11_non_generic_as, "warning: standard C does not have address spaces\n"); prefix = ""; if (constant) - decl_center = format_string_arena(emitter->arena->arena, "const %s", decl_center); + name = format_string_arena(emitter->arena->arena, "const %s", name); break; } case CDialect_ISPC: @@ -180,7 +184,7 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S assert(false); // Note: this requires many hacks. prefix = "__device__ "; - decl_center = format_string_arena(emitter->arena->arena, "__shady_private_globals.%s", decl_center); + name = format_string_arena(emitter->arena->arena, "__shady_private_globals.%s", name); break; case AsShared: prefix = "__shared__ "; break; case AsGlobal: { @@ -225,15 +229,15 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S if (emitter->config.dialect == CDialect_ISPC) { bool uniform = is_addr_space_uniform(emitter->arena, as); if (uniform) - decl_center = format_string_arena(emitter->arena->arena, "uniform %s", decl_center); + name = format_string_arena(emitter->arena->arena, "uniform %s", name); else - decl_center = format_string_arena(emitter->arena->arena, "varying %s", decl_center); + name = format_string_arena(emitter->arena->arena, "varying %s", name); } if (init) - print(emitter->fn_decls, "\n%s%s = %s;", prefix, c_emit_type(emitter, type, decl_center), init); + print(emitter->fn_decls, "\n%s%s = %s;", prefix, c_emit_type(emitter, type, name), init); else - print(emitter->fn_decls, "\n%s%s;", prefix, c_emit_type(emitter, type, decl_center)); + print(emitter->fn_decls, "\n%s%s;", prefix, c_emit_type(emitter, type, name)); //if (!has_forward_declarations(emitter->config.dialect) || !init) // return; @@ -245,7 +249,7 @@ static void emit_global_variable_definition(Emitter* emitter, AddressSpace as, S void c_emit_decl(Emitter* emitter, const Node* decl) { assert(is_declaration(decl)); - CTerm* found = lookup_existing_term(emitter, decl); + CTerm* found = lookup_existing_term(emitter, NULL, decl); if (found) return; CType* found2 = lookup_existing_type(emitter, decl); @@ -269,14 +273,14 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { if (is_decl_builtin(decl)) { Builtin b = get_decl_builtin(decl); CTerm t = c_emit_builtin(emitter, b); - register_emitted(emitter, decl, t); + register_emitted(emitter, NULL, decl, t); return; } if (ass == AsOutput && emitter->compiler_config->specialization.execution_model == EmFragment) { int location = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(lookup_annotation(decl, "Location"))), false); CTerm t = term_from_cvar(format_string_interned(emitter->arena, "gl_FragData[%d]", location)); - register_emitted(emitter, decl, t); + register_emitted(emitter, NULL, decl, t); return; } @@ -285,35 +289,44 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { emit_as = term_from_cvar(name); if ((decl->payload.global_variable.address_space == AsPrivate) && emitter->config.dialect == CDialect_CUDA) { if (emitter->use_private_globals) { - register_emitted(emitter, decl, term_from_cvar(format_string_arena(emitter->arena->arena, "__shady_private_globals->%s", name))); + register_emitted(emitter, NULL, decl, term_from_cvar(format_string_arena(emitter->arena->arena, "__shady_private_globals->%s", name))); // HACK return; } emit_as = term_from_cvar(format_string_interned(emitter->arena, "__shady_thread_local_access(%s)", name)); if (init) init = format_string_interned(emitter->arena, "__shady_replicate_thread_local(%s)", init); - register_emitted(emitter, decl, emit_as); + register_emitted(emitter, NULL, decl, emit_as); } - register_emitted(emitter, decl, emit_as); + register_emitted(emitter, NULL, decl, emit_as); AddressSpace as = decl->payload.global_variable.address_space; - emit_global_variable_definition(emitter, as, decl_center, decl_type, false, init); + c_emit_global_variable_definition(emitter, as, decl_center, decl_type, false, init); return; } case Function_TAG: { emit_as = term_from_cvalue(name); - register_emitted(emitter, decl, emit_as); + register_emitted(emitter, NULL, decl, emit_as); String head = c_emit_fn_head(emitter, decl->type, name, decl); const Node* body = decl->payload.fun.body; if (body) { + FnEmitter fn = { + .cfg = build_fn_cfg(decl), + .emitted_terms = new_dict(Node*, CTerm, (HashFn) hash_node, (CmpFn) compare_node), + }; + fn.scheduler = new_scheduler(fn.cfg); + fn.instruction_printers = calloc(sizeof(Printer*), fn.cfg->size); + // for (size_t i = 0; i < fn.cfg->size; i++) + // fn.instruction_printers[i] = open_growy_as_printer(new_growy()); + for (size_t i = 0; i < decl->payload.fun.params.count; i++) { String param_name; String variable_name = get_value_name_unsafe(decl->payload.fun.params.nodes[i]); param_name = format_string_interned(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); - register_emitted(emitter, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); + register_emitted(emitter, &fn, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } - String fn_body = c_emit_lambda_body(emitter, body, NULL); + String fn_body = c_emit_body(emitter, &fn, decl); String free_me = fn_body; if (emitter->config.dialect == CDialect_ISPC) { // ISPC hack: This compiler (like seemingly all LLVM-based compilers) has broken handling of the execution mask - it fails to generated masked stores for the entry BB of a function that may be called non-uniformingly @@ -329,8 +342,15 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { fn_body = format_string_arena(emitter->arena->arena, "\n__shady_prepare_builtins();%s", fn_body); } } - print(emitter->fn_defs, "\n%s { %s }", head, fn_body); + print(emitter->fn_defs, "\n%s { ", head); + indent(emitter->fn_defs); + print(emitter->fn_defs, " %s", fn_body); + deindent(emitter->fn_defs); + print(emitter->fn_defs, "\n}"); free_tmp_str(free_me); + + destroy_dict(fn.emitted_terms); + free(fn.instruction_printers); } print(emitter->fn_decls, "\n%s;", head); @@ -338,10 +358,10 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { } case Constant_TAG: { emit_as = term_from_cvalue(name); - register_emitted(emitter, decl, emit_as); + register_emitted(emitter, NULL, decl, emit_as); String init = to_cvalue(emitter, c_emit_value(emitter, NULL, decl->payload.constant.value)); - emit_global_variable_definition(emitter, AsGlobal, decl_center, decl->type, true, init); + c_emit_global_variable_definition(emitter, AsGlobal, decl_center, decl->type, true, init); return; } case NominalType_TAG: { @@ -358,28 +378,6 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { } } -void register_emitted(Emitter* emitter, const Node* node, CTerm as) { - assert(as.value || as.var); - insert_dict(const Node*, CTerm, emitter->emitted_terms, node, as); -} - -void register_emitted_type(Emitter* emitter, const Node* node, String as) { - insert_dict(const Node*, String, emitter->emitted_types, node, as); -} - -CTerm* lookup_existing_term(Emitter* emitter, const Node* node) { - CTerm* found = find_value_dict(const Node*, CTerm, emitter->emitted_terms, node); - return found; -} - -CType* lookup_existing_type(Emitter* emitter, const Type* node) { - CType* found = find_value_dict(const Node*, CType, emitter->emitted_types, node); - return found; -} - -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); - static Module* run_backend_specific_passes(const CompilerConfig* config, CEmitterConfig* econfig, Module* initial_mod) { IrArena* initial_arena = initial_mod->arena; Module** pmod = &initial_mod; diff --git a/src/backend/c/emit_c.h b/src/backend/c/emit_c.h index 72bc8636e..0e80798af 100644 --- a/src/backend/c/emit_c.h +++ b/src/backend/c/emit_c.h @@ -9,6 +9,9 @@ #include "arena.h" #include "printer.h" +typedef struct CFG_ CFG; +typedef struct Scheduler_ Scheduler; + /// SSA-like things, you can read them typedef String CValue; /// non-SSA like things, they represent addresses @@ -49,37 +52,40 @@ typedef struct { bool need_64b_ext; } Emitter; -void register_emitted(Emitter*, const Node*, CTerm); +typedef struct { + struct Dict* emitted_terms; + Printer** instruction_printers; + CFG* cfg; + Scheduler* scheduler; +} FnEmitter; + +void register_emitted(Emitter*, FnEmitter* fn, const Node*, CTerm); void register_emitted_type(Emitter*, const Type*, String); -CTerm* lookup_existing_term(Emitter* emitter, const Node*); +CTerm* lookup_existing_term(Emitter* emitter, FnEmitter* fn, const Node*); CType* lookup_existing_type(Emitter* emitter, const Type*); +String c_legalize_identifier(Emitter*, String); CValue to_cvalue(Emitter*, CTerm); CAddr deref_term(Emitter*, CTerm); - -void c_emit_decl(Emitter* emitter, const Node* decl); -CType c_emit_type(Emitter* emitter, const Type*, const char* identifier); -String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn); -void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type); - +void c_emit_pack_code(Printer*, Strings, String dst); +void c_emit_unpack_code(Printer*, String src, Strings dst); +CTerm c_bind_intermediary_result(Emitter*, Printer* p, const Type* t, CTerm term); void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer); +CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term); -CTerm c_emit_value(Emitter* emitter, Printer*, const Node* value); +void c_emit_decl(Emitter* emitter, const Node* decl); +void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String name, const Type* type, bool constant, String init); CTerm c_emit_builtin(Emitter*, Builtin); -String c_legalize_identifier(Emitter*, String); +CType c_emit_type(Emitter* emitter, const Type*, const char* identifier); String c_get_record_field_name(const Type* t, size_t i); -CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term); - -CTerm c_bind_intermediary_result(Emitter*, Printer* p, const Type* t, CTerm term); - -CTerm c_emit_instruction(Emitter* emitter, Printer* p, const Node* instruction); -void c_emit_terminator(Emitter* emitter, Printer* p, const Node* terminator); -String c_emit_lambda_body(Emitter*, const Node*, const Nodes* nested_basic_blocks); +String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn); +void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type); -void c_emit_pack_code(Printer*, Strings, String dst); -void c_emit_unpack_code(Printer*, String src, Strings dst); +CTerm c_emit_value(Emitter* emitter, FnEmitter* fn, const Node* value); +CTerm c_emit_mem(Emitter* e, FnEmitter* b, const Node* mem); +String c_emit_body(Emitter*, FnEmitter* fn, const Node*); #define free_tmp_str(s) free((char*) (s)) diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index e5f6c3053..d9d567a8d 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -1,13 +1,39 @@ #include "emit_c.h" #include "../shady/type.h" +#include "../shady/analysis/cfg.h" #include "log.h" #include "portability.h" #include -static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String given_name, Strings* given_names, Nodes types, bool mut, const Nodes* init_values) { +static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_printer, const Node* terminator); + +String c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { + assert(abs && is_abstraction(abs)); + const Node* body = get_abstraction_body(abs); + assert(body && is_terminator(body)); + CFNode* cf_node = cfg_lookup(fn->cfg, abs); + Printer* p = open_growy_as_printer(new_growy()); + fn->instruction_printers[cf_node->rpo_index] = p; + //indent(p); + + emit_terminator(emitter, fn, p, body); + + /*if (bbs && bbs->count > 0) { + assert(emitter->config.dialect != CDialect_GLSL); + error("TODO"); + }*/ + + //deindent(p); + // print(p, "\n"); + + fn->instruction_printers[cf_node->rpo_index] = NULL; + return printer_growy_unwrap(p); +} + +static Strings emit_variable_declarations(Emitter* emitter, FnEmitter* fn, Printer* p, String given_name, Strings* given_names, Nodes types, bool mut, const Nodes* init_values) { if (given_names) assert(given_names->count == types.count); if (init_values) @@ -18,7 +44,7 @@ static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String g assert(name); names[i] = unique_name(emitter->arena, name); if (init_values) { - CTerm initializer = c_emit_value(emitter, p, init_values->nodes[i]); + CTerm initializer = c_emit_value(emitter, fn, init_values->nodes[i]); c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); } else c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); @@ -26,34 +52,42 @@ static Strings emit_variable_declarations(Emitter* emitter, Printer* p, String g return strings(emitter->arena, types.count, names); } -static void emit_if(Emitter* emitter, Printer* p, If if_) { +static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { Emitter sub_emiter = *emitter; - Strings ephis = emit_variable_declarations(emitter, p, "if_phi", NULL, if_.yield_types, true, NULL); + Strings ephis = emit_variable_declarations(emitter, fn, p, "if_phi", NULL, if_.yield_types, true, NULL); sub_emiter.phis.selection = ephis; assert(get_abstraction_params(if_.if_true).count == 0); - String true_body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_true), NULL); - CValue condition = to_cvalue(emitter, c_emit_value(emitter, p, if_.condition)); - print(p, "\nif (%s) { %s}", condition, true_body); + String true_body = c_emit_body(&sub_emiter, fn, if_.if_true); + CValue condition = to_cvalue(emitter, c_emit_value(emitter, fn, if_.condition)); + print(p, "\nif (%s) { ", condition); + indent(p); + print(p, "%s", true_body); + deindent(p); + print(p, "\n}"); free_tmp_str(true_body); if (if_.if_false) { assert(get_abstraction_params(if_.if_false).count == 0); - String false_body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(if_.if_false), NULL); - print(p, " else {%s}", false_body); + String false_body = c_emit_body(&sub_emiter, fn, if_.if_false); + print(p, " else {"); + indent(p); + print(p, "%s", false_body); + deindent(p); + print(p, "\n}"); free_tmp_str(false_body); } Nodes results = get_abstraction_params(if_.tail); for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - c_emit_terminator(emitter, p, get_abstraction_body(if_.tail)); + print(p, "%s", c_emit_body(emitter, fn, if_.tail)); } -static void emit_match(Emitter* emitter, Printer* p, Match match) { +static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) { Emitter sub_emiter = *emitter; - Strings ephis = emit_variable_declarations(emitter, p, "match_phi", NULL, match.yield_types, true, NULL); + Strings ephis = emit_variable_declarations(emitter, fn, p, "match_phi", NULL, match.yield_types, true, NULL); sub_emiter.phis.selection = ephis; // Of course, the sensible thing to do here would be to emit a switch statement. @@ -65,36 +99,44 @@ static void emit_match(Emitter* emitter, Printer* p, Match match) { // We could do GOTO for C, but at the cost of arguably even more noise in the output, and two different codepaths. // I don't think it's quite worth it, just like it's not worth doing some data-flow based solution either. - CValue inspectee = to_cvalue(emitter, c_emit_value(emitter, p, match.inspect)); + CValue inspectee = to_cvalue(emitter, c_emit_value(emitter, fn, match.inspect)); bool first = true; LARRAY(CValue, literals, match.cases.count); for (size_t i = 0; i < match.cases.count; i++) { - literals[i] = to_cvalue(emitter, c_emit_value(emitter, p, match.literals.nodes[i])); + literals[i] = to_cvalue(emitter, c_emit_value(emitter, fn, match.literals.nodes[i])); } for (size_t i = 0; i < match.cases.count; i++) { - String case_body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(match.cases.nodes[i]), NULL); + String case_body = c_emit_body(&sub_emiter, fn, match.cases.nodes[i]); print(p, "\n"); if (!first) print(p, "else "); - print(p, "if (%s == %s) { %s}", inspectee, literals[i], case_body); + print(p, "if (%s == %s) { ", inspectee, literals[i]); + indent(p); + print(p, "%s", case_body); + deindent(p); + print(p, "\n}"); free_tmp_str(case_body); first = false; } if (match.default_case) { - String default_case_body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(match.default_case), NULL); - print(p, "\nelse { %s}", default_case_body); + String default_case_body = c_emit_body(&sub_emiter, fn, match.default_case); + print(p, "\nelse { "); + indent(p); + print(p, "%s", default_case_body); + deindent(p); + print(p, "\n}"); free_tmp_str(default_case_body); } Nodes results = get_abstraction_params(match.tail); for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - c_emit_terminator(emitter, p, get_abstraction_body(match.tail)); + print(p, "%s", c_emit_body(emitter, fn, match.tail)); } -static void emit_loop(Emitter* emitter, Printer* p, Loop loop) { +static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { Emitter sub_emiter = *emitter; Nodes params = get_abstraction_params(loop.body); Nodes variables = params; @@ -105,27 +147,32 @@ static void emit_loop(Emitter* emitter, Printer* p, Loop loop) { arr[i] = unique_name(emitter->arena, "phi"); } Strings param_names = strings(emitter->arena, variables.count, arr); - Strings eparams = emit_variable_declarations(emitter, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop.initial_args); + Strings eparams = emit_variable_declarations(emitter, fn, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop.initial_args); for (size_t i = 0; i < params.count; i++) - register_emitted(&sub_emiter, params.nodes[i], term_from_cvalue(eparams.strings[i])); + register_emitted(&sub_emiter, fn, params.nodes[i], term_from_cvalue(eparams.strings[i])); sub_emiter.phis.loop_continue = eparams; - Strings ephis = emit_variable_declarations(emitter, p, "loop_break_phi", NULL, loop.yield_types, true, NULL); + Strings ephis = emit_variable_declarations(emitter, fn, p, "loop_break_phi", NULL, loop.yield_types, true, NULL); sub_emiter.phis.loop_break = ephis; - String body = c_emit_lambda_body(&sub_emiter, get_abstraction_body(loop.body), NULL); - print(p, "\nwhile(true) { %s}", body); + String body = c_emit_body(&sub_emiter, fn, loop.body); + print(p, "\nwhile(true) { "); + indent(p); + print(p, "%s", body); + deindent(p); + print(p, "\n}"); free_tmp_str(body); Nodes results = get_abstraction_params(loop.tail); for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, results.nodes[i], term_from_cvalue(ephis.strings[i])); + register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - c_emit_terminator(emitter, p, get_abstraction_body(loop.tail)); + print(p, "%s", c_emit_body(emitter, fn, loop.tail)); } -void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* terminator) { +static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_printer, const Node* terminator) { + c_emit_mem(emitter, fn, get_terminator_mem(terminator)); switch (is_terminator(terminator)) { case NotATerminator: assert(false); case Join_TAG: error("this must be lowered away!"); @@ -133,71 +180,21 @@ void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* ter case Branch_TAG: case Switch_TAG: case TailCall_TAG: error("TODO"); - /*case Let_TAG: { - const Node* instruction = get_let_instruction(terminator); - - // we declare N local variables in order to store the result of the instruction - Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, instruction->type); - - LARRAY(CTerm, results, yield_types.count); - LARRAY(InstrResultBinding, bindings, yield_types.count); - InstructionOutputs ioutputs = { - .count = yield_types.count, - .results = results, - .binding = bindings, - }; - emit_instruction(emitter, block_printer, instruction, ioutputs); - - // Nodes vars = terminator->payload.let.variables; - // assert(vars.count == yield_types.count); - for (size_t i = 0; i < yield_types.count; i++) { - bool has_result = results[i].value || results[i].var; - switch (bindings[i]) { - case NoBinding: { - assert(has_result && "unbound results can't be empty"); - register_emitted(emitter, extract_multiple_ret_types_helper(instruction, i), results[i]); - break; - } - case LetBinding: { - String variable_name = get_value_name_unsafe(extract_multiple_ret_types_helper(instruction, i)); - - if (!variable_name) - variable_name = ""; - - String bind_to = unique_name(emitter->arena, variable_name); - - const Type* t = yield_types.nodes[i]; - - if (has_result) - emit_variable_declaration(emitter, block_printer, t, bind_to, false, &results[i]); - else - emit_variable_declaration(emitter, block_printer, t, bind_to, false, NULL); - - register_emitted(emitter, extract_multiple_ret_types_helper(instruction, i), term_from_cvalue(bind_to)); - break; - } - default: assert(false); - } - } - emit_terminator(emitter, block_printer, terminator->payload.let.in); - - break; - }*/ - case If_TAG: return emit_if(emitter, block_printer, terminator->payload.if_instr); - case Match_TAG: return emit_match(emitter, block_printer, terminator->payload.match_instr); - case Loop_TAG: return emit_loop(emitter, block_printer, terminator->payload.loop_instr); + case If_TAG: return emit_if(emitter, fn, block_printer, terminator->payload.if_instr); + case Match_TAG: return emit_match(emitter, fn, block_printer, terminator->payload.match_instr); + case Loop_TAG: return emit_loop(emitter, fn, block_printer, terminator->payload.loop_instr); case Control_TAG: error("TODO") case Terminator_Return_TAG: { Nodes args = terminator->payload.fn_ret.args; if (args.count == 0) { print(block_printer, "\nreturn;"); } else if (args.count == 1) { - print(block_printer, "\nreturn %s;", to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[0]))); + print(block_printer, "\nreturn %s;", to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[0]))); } else { String packed = unique_name(emitter->arena, "pack_return"); LARRAY(CValue, values, args.count); for (size_t i = 0; i < args.count; i++) - values[i] = to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[i])); + values[i] = to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i])); c_emit_pack_code(block_printer, strings(emitter->arena, args.count, values), packed); print(block_printer, "\nreturn %s;", packed); } @@ -208,7 +205,7 @@ void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* ter Phis phis = emitter->phis.selection; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[i]))); + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); break; } @@ -217,7 +214,7 @@ void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* ter Phis phis = emitter->phis.loop_continue; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[i]))); + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); print(block_printer, "\ncontinue;"); break; } @@ -226,7 +223,7 @@ void c_emit_terminator(Emitter* emitter, Printer* block_printer, const Node* ter Phis phis = emitter->phis.loop_break; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, block_printer, args.nodes[i]))); + print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); print(block_printer, "\nbreak;"); break; } diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index 790836441..416408e17 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -99,7 +99,7 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons } free_tmp_str(parameters); - String c_decl = c_emit_type(emitter, maybe_tuple_helper(emitter->arena, codom), center); + String c_decl = c_emit_type(emitter, maybe_multiple_return(emitter->arena, codom), center); if (entry_point) { switch (emitter->config.dialect) { case CDialect_C11: diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 0b7132674..f53747854 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -8,6 +8,7 @@ #include "../shady/type.h" #include "../shady/ir_private.h" #include "../shady/transform/ir_gen_helpers.h" +#include "../shady/analysis/scheduler.h" #include @@ -19,7 +20,9 @@ #pragma GCC diagnostic error "-Wswitch" -static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e, Printer* block_printer, Printer* p, Growy* g, const Node* t, Nodes c) { +static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* instruction); + +static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e, FnEmitter* fn, Printer* p, Growy* g, const Node* t, Nodes c) { if (t->tag == Int_TAG && t->payload.int_type.width == 8) { uint8_t* tmp = malloc(sizeof(uint8_t) * c.count); bool ends_zero = false; @@ -44,7 +47,7 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e return is_stringy ? StringLit : CharsLit; } else { for (size_t i = 0; i < c.count; i++) { - print(p, to_cvalue(e, c_emit_value(e, block_printer, c.nodes[i]))); + print(p, to_cvalue(e, c_emit_value(e, fn, c.nodes[i]))); if (i + 1 < c.count) print(p, ", "); } @@ -53,10 +56,10 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e } } -CTerm c_emit_value(Emitter* emitter, Printer* block_printer, const Node* value) { - CTerm* found = lookup_existing_term(emitter, value); - if (found) return *found; - +static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* value) { + if (is_instruction(value)) + return emit_instruction(emitter, fn, p, value); + String emitted = NULL; switch (is_value(value)) { @@ -108,10 +111,10 @@ CTerm c_emit_value(Emitter* emitter, Printer* block_printer, const Node* value) case Value_False_TAG: return term_from_cvalue("false"); case Value_Undef_TAG: { if (emitter->config.dialect == CDialect_GLSL) - return c_emit_value(emitter, block_printer, get_default_zero_value(emitter->arena, value->payload.undef.type)); + return c_emit_value(emitter, fn, get_default_zero_value(emitter->arena, value->payload.undef.type)); String name = unique_name(emitter->arena, "undef"); - c_emit_variable_declaration(emitter, block_printer, value->type, name, true, NULL); - // emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); + // c_emit_variable_declaration(emitter, block_printer, value->type, name, true, NULL); + c_emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); emitted = name; break; } @@ -124,7 +127,7 @@ CTerm c_emit_value(Emitter* emitter, Printer* block_printer, const Node* value) Printer* p = open_growy_as_printer(g); if (type->tag == ArrType_TAG) { - switch (array_insides_helper(emitter, block_printer, p, g, type, elements)) { + switch (array_insides_helper(emitter, fn, p, g, type, elements)) { case ObjectsList: emitted = growy_data(g); break; @@ -137,7 +140,7 @@ CTerm c_emit_value(Emitter* emitter, Printer* block_printer, const Node* value) } } else { for (size_t i = 0; i < elements.count; i++) { - print(p, "%s", to_cvalue(emitter, c_emit_value(emitter, block_printer, elements.nodes[i]))); + print(p, "%s", to_cvalue(emitter, c_emit_value(emitter, fn, elements.nodes[i]))); if (i + 1 < elements.count) print(p, ", "); } @@ -152,9 +155,9 @@ CTerm c_emit_value(Emitter* emitter, Printer* block_printer, const Node* value) if (type->tag == ArrType_TAG) emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); - if (block_printer) { + if (p) { String tmp = unique_name(emitter->arena, "composite"); - print(block_printer, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); + print(p, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); emitted = tmp; } else { // this requires us to end up in the initialisation side of a declaration @@ -215,12 +218,12 @@ CTerm c_emit_value(Emitter* emitter, Printer* block_printer, const Node* value) if (emitter->config.dialect == CDialect_ISPC && decl->tag == GlobalVariable_TAG) { if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !is_decl_builtin(decl)) { - assert(block_printer && "ISPC backend cannot statically refer to a varying variable"); - return ispc_varying_ptr_helper(emitter, block_printer, decl->type, *lookup_existing_term(emitter, decl)); + assert(fn && "ISPC backend cannot statically refer to a varying variable"); + return ispc_varying_ptr_helper(emitter, fn->instruction_printers[0], decl->type, *lookup_existing_term(emitter, NULL, decl)); } } - return *lookup_existing_term(emitter, decl); + return *lookup_existing_term(emitter, NULL, decl); } } @@ -329,7 +332,7 @@ static const ISelTableEntry isel_table_ispc[PRIMOPS_COUNT] = { [pow_op] = { IsMono, OsCall, "pow" }, }; -static bool emit_using_entry(CTerm* out, Emitter* emitter, Printer* p, const ISelTableEntry* entry, Nodes operands) { +static bool emit_using_entry(CTerm* out, Emitter* emitter, FnEmitter* fn, Printer* p, const ISelTableEntry* entry, Nodes operands) { String operator_str = NULL; switch (entry->isel_mechanism) { case IsNone: return false; @@ -351,20 +354,20 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, Printer* p, const ISe switch (entry->style) { case OsInfix: { - CTerm a = c_emit_value(emitter, p, operands.nodes[0]); - CTerm b = c_emit_value(emitter, p, operands.nodes[1]); + CTerm a = c_emit_value(emitter, fn, operands.nodes[0]); + CTerm b = c_emit_value(emitter, fn, operands.nodes[1]); *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s %s %s", to_cvalue(emitter, a), operator_str, to_cvalue(emitter, b))); break; } case OsPrefix: { - CTerm operand = c_emit_value(emitter, p, operands.nodes[0]); + CTerm operand = c_emit_value(emitter, fn, operands.nodes[0]); *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s%s", operator_str, to_cvalue(emitter, operand))); break; } case OsCall: { LARRAY(CTerm, cops, operands.count); for (size_t i = 0; i < operands.count; i++) - cops[i] = c_emit_value(emitter, p, operands.nodes[i]); + cops[i] = c_emit_value(emitter, fn, operands.nodes[i]); if (operands.count == 1) *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", operator_str, to_cvalue(emitter, cops[0]))); else { @@ -413,7 +416,7 @@ static String index_into_array(Emitter* emitter, const Type* arr_type, CTerm exp return format_string_arena(arena->arena, "(%s.arr[%s])", deref_term(emitter, expr), index2); } -static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { +static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* node) { assert(node->tag == PrimOp_TAG); IrArena* arena = emitter->arena; const PrimOp* prim_op = &node->payload.prim_op; @@ -428,37 +431,37 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { // MATH OPS case fract_op: { CTerm floored; - emit_using_entry(&floored, emitter, p, lookup_entry(emitter, floor_op), prim_op->operands); + emit_using_entry(&floored, emitter, fn, p, lookup_entry(emitter, floor_op), prim_op->operands); term = term_from_cvalue(format_string_arena(arena->arena, "1 - %s", to_cvalue(emitter, floored))); break; } case inv_sqrt_op: { CTerm floored; - emit_using_entry(&floored, emitter, p, lookup_entry(emitter, sqrt_op), prim_op->operands); + emit_using_entry(&floored, emitter, fn, p, lookup_entry(emitter, sqrt_op), prim_op->operands); term = term_from_cvalue(format_string_arena(arena->arena, "1.0f / %s", to_cvalue(emitter, floored))); break; } case min_op: { - CValue a = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); - CValue b = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); + CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); + CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); term = term_from_cvalue(format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, b, a)); break; } case max_op: { - CValue a = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); - CValue b = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); + CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); + CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); term = term_from_cvalue(format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, a, b)); break; } case sign_op: { - CValue src = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); + CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); term = term_from_cvalue(format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); break; } case fma_op: { - CValue a = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[0])); - CValue b = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); - CValue c = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[2])); + CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[0])); + CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); + CValue c = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[2])); switch (emitter->config.dialect) { case CDialect_C11: case CDialect_CUDA: { @@ -475,9 +478,9 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { case lshift_op: case rshift_arithm_op: case rshift_logical_op: { - CValue src = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); + CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); const Node* offset = prim_op->operands.nodes[1]; - CValue c_offset = to_cvalue(emitter, c_emit_value(emitter, p, offset)); + CValue c_offset = to_cvalue(emitter, c_emit_value(emitter, fn, offset)); if (emitter->config.dialect == CDialect_GLSL) { if (get_unqualified_type(offset->type)->payload.int_type.width == IntTy64) c_offset = format_string_arena(arena->arena, "int(%s)", c_offset); @@ -503,14 +506,14 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { break; } case select_op: { assert(prim_op->operands.count == 3); - CValue condition = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[0])); - CValue l = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); - CValue r = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[2])); + CValue condition = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[0])); + CValue l = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); + CValue r = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[2])); term = term_from_cvalue(format_string_arena(emitter->arena->arena, "(%s) ? (%s) : (%s)", condition, l, r)); break; } case convert_op: { - CTerm src = c_emit_value(emitter, p, first(prim_op->operands)); + CTerm src = c_emit_value(emitter, fn, first(prim_op->operands)); const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); if (emitter->config.dialect == CDialect_GLSL) { @@ -526,7 +529,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { break; } case reinterpret_op: { - CTerm src_value = c_emit_value(emitter, p, first(prim_op->operands)); + CTerm src_value = c_emit_value(emitter, fn, first(prim_op->operands)); const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); const Type* dst_type = first(prim_op->type_arguments); switch (emitter->config.dialect) { @@ -604,7 +607,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { case insert_op: case extract_dynamic_op: case extract_op: { - CValue acc = to_cvalue(emitter, c_emit_value(emitter, p, first(prim_op->operands))); + CValue acc = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); bool insert = prim_op->op == insert_op; if (insert) { @@ -643,7 +646,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { break; } case Type_ArrType_TAG: { - acc = index_into_array(emitter, t, term_from_cvar(acc), c_emit_value(emitter, p, index)); + acc = index_into_array(emitter, t, term_from_cvar(acc), c_emit_value(emitter, fn, index)); break; } default: @@ -652,7 +655,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { } if (insert) { - print(p, "\n%s = %s;", acc, to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1]))); + print(p, "\n%s = %s;", acc, to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1]))); break; } @@ -663,8 +666,8 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { String dst = unique_name(arena, "shuffled"); const Node* lhs = prim_op->operands.nodes[0]; const Node* rhs = prim_op->operands.nodes[1]; - String lhs_e = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[0])); - String rhs_e = to_cvalue(emitter, c_emit_value(emitter, p, prim_op->operands.nodes[1])); + String lhs_e = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[0])); + String rhs_e = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); const Type* lhs_t = lhs->type; const Type* rhs_t = rhs->type; bool lhs_u = deconstruct_qualified_type(&lhs_t); @@ -688,7 +691,7 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { } case subgroup_assume_uniform_op: { if (emitter->config.dialect != CDialect_ISPC) { - return c_emit_value(emitter, p, prim_op->operands.nodes[0]); + return c_emit_value(emitter, fn, prim_op->operands.nodes[0]); } } case empty_mask_op: @@ -698,16 +701,17 @@ static CTerm emit_primop(Emitter* emitter, Printer* p, const Node* node) { } if (isel_entry->isel_mechanism != IsNone) - emit_using_entry(&term, emitter, p, isel_entry, prim_op->operands); + emit_using_entry(&term, emitter, fn, p, isel_entry, prim_op->operands); return term; } -static CTerm emit_ext_instruction(Emitter* emitter, Printer* p, ExtInstr instr) { +static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, ExtInstr instr) { + c_emit_mem(emitter, fn, instr.mem); if (strcmp(instr.set, "spirv.core") == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { - CValue value = to_cvalue(emitter, c_emit_value(emitter, p, first(instr.operands))); + CValue value = to_cvalue(emitter, c_emit_value(emitter, fn, first(instr.operands))); switch (emitter->config.dialect) { case CDialect_CUDA: return term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; case CDialect_ISPC: return term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; @@ -738,7 +742,9 @@ static CTerm emit_ext_instruction(Emitter* emitter, Printer* p, ExtInstr instr) } } -static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { +static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* call) { + Call payload = call->payload.call; + c_emit_mem(emitter, fn, payload.mem); Nodes args; if (call->tag == Call_TAG) args = call->payload.call.args; @@ -753,7 +759,7 @@ static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { print(paramsp, ", "); } for (size_t i = 0; i < args.count; i++) { - print(paramsp, to_cvalue(emitter, c_emit_value(emitter, p, args.nodes[i]))); + print(paramsp, to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); if (i + 1 < args.count) print(paramsp, ", "); } @@ -763,7 +769,7 @@ static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { if (callee->tag == FnAddr_TAG) e_callee = get_declaration_name(callee->payload.fn_addr.fn); else - e_callee = to_cvalue(emitter, c_emit_value(emitter, p, callee)); + e_callee = to_cvalue(emitter, c_emit_value(emitter, fn, callee)); String params = printer_growy_unwrap(paramsp); @@ -774,9 +780,9 @@ static CTerm emit_call(Emitter* emitter, Printer* p, const Node* call) { return called; } -static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { +static CTerm emit_lea(Emitter* emitter, FnEmitter* fn, Printer* p, Lea lea) { IrArena* arena = emitter->arena; - CTerm acc = c_emit_value(emitter, p, lea.ptr); + CTerm acc = c_emit_value(emitter, fn, lea.ptr); const Type* src_qtype = lea.ptr->type; bool uniform = is_qualified_type_uniform(src_qtype); @@ -785,7 +791,7 @@ static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { const IntLiteral* offset_static_value = resolve_to_int_literal(lea.offset); if (!offset_static_value || offset_static_value->value != 0) { - CTerm offset = c_emit_value(emitter, p, lea.offset); + CTerm offset = c_emit_value(emitter, fn, lea.offset); // we sadly need to drop to the value level (aka explicit pointer arithmetic) to do this // this means such code is never going to be legal in GLSL // also the cast is to account for our arrays-in-structs hack @@ -801,7 +807,7 @@ static CTerm emit_lea(Emitter* emitter, Printer* p, Lea lea) { uniform &= is_qualified_type_uniform(selector->type); switch (is_type(pointee_type)) { case ArrType_TAG: { - CTerm index = c_emit_value(emitter, p, selector); + CTerm index = c_emit_value(emitter, fn, selector); acc = term_from_cvar(index_into_array(emitter, pointee_type, acc, index)); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.arr_type.element_type, @@ -864,7 +870,7 @@ static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* type) { return variable; } -CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { +static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* instruction) { assert(is_instruction(instruction)); IrArena* a = emitter->arena; @@ -875,51 +881,29 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { case Instruction_GetStackSize_TAG: case Instruction_SetStackSize_TAG: case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); - case Instruction_ExtInstr_TAG: return emit_ext_instruction(emitter, p, instruction->payload.ext_instr); - case Instruction_PrimOp_TAG: return emit_primop(emitter, p, instruction); - case Instruction_Call_TAG: return emit_call(emitter, p, instruction); - /*case Instruction_CompoundInstruction_TAG: { - Nodes instructions = instruction->payload.compound_instruction.instructions; - for (size_t i = 0; i < instructions.count; i++) { - const Node* instruction2 = instructions.nodes[i]; - - // we declare N local variables in order to store the result of the instruction - Nodes yield_types = unwrap_multiple_yield_types(emitter->arena, instruction2->type); - - LARRAY(CTerm, results, yield_types.count); - LARRAY(InstrResultBinding, bindings, yield_types.count); - InstructionOutputs ioutputs = { - .count = yield_types.count, - .results = results, - .binding = bindings, - }; - - emit_instruction(emitter, p, instruction2, ioutputs); - } - Nodes results2 = instruction->payload.compound_instruction.results; - for (size_t i = 0; i < results2.count; i++) { - outputs.results[0] = c_emit_value(emitter, p, results2.nodes[i]); - outputs.binding[0] = NoBinding; - } - return; - }*/ - case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); break; - case Instruction_StackAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.stack_alloc.type); - case Instruction_LocalAlloc_TAG: return emit_alloca(emitter, p, instruction->payload.local_alloc.type); + case Instruction_ExtInstr_TAG: return emit_ext_instruction(emitter, fn, p, instruction->payload.ext_instr); + case Instruction_PrimOp_TAG: return emit_primop(emitter, fn, p, instruction); + case Instruction_Call_TAG: return emit_call(emitter, fn, p, instruction); + case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); return empty_term(); + case Instruction_StackAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.stack_alloc.mem); return emit_alloca(emitter, p, instruction->payload.stack_alloc.type); + case Instruction_LocalAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction->payload.local_alloc.type); + case Instruction_Lea_TAG: return emit_lea(emitter, fn, p, instruction->payload.lea); case Instruction_Load_TAG: { Load payload = instruction->payload.load; - CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, p, payload.ptr)); + c_emit_mem(emitter, fn, payload.mem); + CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, fn, payload.ptr)); // we must bind the intermediary result here, otherwise we duplicate the load everwhere it is consumed return c_bind_intermediary_result(emitter, p, instruction->type, term_from_cvalue(dereferenced)); } case Instruction_Store_TAG: { Store payload = instruction->payload.store; + c_emit_mem(emitter, fn, payload.mem); const Type* addr_type = payload.ptr->type; bool addr_uniform = deconstruct_qualified_type(&addr_type); bool value_uniform = is_qualified_type_uniform(payload.value->type); assert(addr_type->tag == PtrType_TAG); - CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, p, payload.ptr)); - CValue cvalue = to_cvalue(emitter, c_emit_value(emitter, p, payload.value)); + CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, fn, payload.ptr)); + CValue cvalue = to_cvalue(emitter, c_emit_value(emitter, fn, payload.value)); // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this if (emitter->config.dialect == CDialect_ISPC && addr_uniform && is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) cvalue = format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); @@ -927,22 +911,24 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { print(p, "\n%s = %s;", dereferenced, cvalue); return empty_term(); } - case Instruction_Lea_TAG: - return emit_lea(emitter, p, instruction->payload.lea); case Instruction_CopyBytes_TAG: { CopyBytes payload = instruction->payload.copy_bytes; - print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, p, payload.src)), to_cvalue(emitter, c_emit_value(emitter, p, payload.count))); + c_emit_mem(emitter, fn, payload.mem); + print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, fn, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.src)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.count))); return empty_term(); } case Instruction_FillBytes_TAG:{ FillBytes payload = instruction->payload.fill_bytes; - print(p, "\nmemset(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, p, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, p, payload.src)), to_cvalue(emitter, c_emit_value(emitter, p, payload.count))); + c_emit_mem(emitter, fn, payload.mem); + print(p, "\nmemset(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, fn, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.src)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.count))); return empty_term(); } case Instruction_DebugPrintf_TAG: { + DebugPrintf payload = instruction->payload.debug_printf; + c_emit_mem(emitter, fn, payload.mem); String args_list = format_string_interned(emitter->arena, "\"%s\"", instruction->payload.debug_printf.string); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) { - CValue str = to_cvalue(emitter, c_emit_value(emitter, p, instruction->payload.debug_printf.args.nodes[i])); + CValue str = to_cvalue(emitter, c_emit_value(emitter, fn, instruction->payload.debug_printf.args.nodes[i])); if (emitter->config.dialect == CDialect_ISPC && i > 0) str = format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); @@ -964,4 +950,48 @@ CTerm emit_instruction(Emitter* emitter, Printer* p, const Node* instruction) { return empty_term(); } } + + SHADY_UNREACHABLE; +} + +static bool can_appear_at_top_level(const Node* node) { + if (is_instruction(node)) + return false; + return true; +} + +CTerm c_emit_value(Emitter* emitter, FnEmitter* fn_builder, const Node* node) { + CTerm* found = lookup_existing_term(emitter, fn_builder, node); + if (found) return *found; + + CFNode* where = fn_builder ? schedule_instruction(fn_builder->scheduler, node) : NULL; + if (where) { + CTerm emitted = c_emit_value_(emitter, fn_builder, fn_builder->instruction_printers[where->rpo_index], node); + register_emitted(emitter, fn_builder, node, emitted); + return emitted; + } else if (!can_appear_at_top_level(node)) { + if (!fn_builder) { + log_node(ERROR, node); + log_string(ERROR, "cannot appear at top-level"); + exit(-1); + } + // Pick the entry block of the current fn + CTerm emitted = c_emit_value_(emitter, fn_builder, fn_builder->instruction_printers[0], node); + register_emitted(emitter, fn_builder, node, emitted); + return emitted; + } else { + assert(!is_mem(node)); + CTerm emitted = c_emit_value_(emitter, NULL, NULL, node); + register_emitted(emitter, NULL, node, emitted); + return emitted; + } +} + +CTerm c_emit_mem(Emitter* e, FnEmitter* b, const Node* mem) { + assert(is_mem(mem)); + if (mem->tag == AbsMem_TAG) + return empty_term(); + if (is_instruction(mem)) + return c_emit_value(e, b, mem); + error("What sort of mem is this ?"); } From d4fa616a9cf5fdd695510ae10727996739c1a878 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 13 Aug 2024 18:50:36 +0200 Subject: [PATCH 492/693] disable switch if-tree lowering for now --- src/shady/compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index c9c15ea95..d7ce8d5c9 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -71,7 +71,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { //RUN_PASS(opt_stack) RUN_PASS(lower_tailcalls) - RUN_PASS(lower_switch_btree) + //RUN_PASS(lower_switch_btree) RUN_PASS(opt_restructurize) //RUN_PASS(opt_mem2reg) From dbbac98707316f4725f5afa5da513e865cf69f50 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 15 Aug 2024 12:02:32 +0200 Subject: [PATCH 493/693] spv: fix structured control flow --- src/backend/spirv/emit_spv.c | 2 + src/backend/spirv/emit_spv.h | 10 ++- src/backend/spirv/emit_spv_control_flow.c | 94 ++++++++++++++++------- src/shady/analysis/cfg.c | 13 +++- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 28912f537..f0cb3b1e2 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -82,6 +82,7 @@ static void emit_function(Emitter* emitter, const Node* node) { .cfg = build_fn_cfg(node), }; fn_builder.scheduler = new_scheduler(fn_builder.cfg); + fn_builder.per_bb = calloc(sizeof(*fn_builder.per_bb), fn_builder.cfg->size); Nodes params = node->payload.fun.params; for (size_t i = 0; i < params.count; i++) { @@ -133,6 +134,7 @@ static void emit_function(Emitter* emitter, const Node* node) { } destroy_cfg(cfg); + free(fn_builder.per_bb); spvb_define_function(emitter->file_builder, fn_builder.base); } else { diff --git a/src/backend/spirv/emit_spv.h b/src/backend/spirv/emit_spv.h index 343a0dd8b..2c70f0498 100644 --- a/src/backend/spirv/emit_spv.h +++ b/src/backend/spirv/emit_spv.h @@ -9,16 +9,20 @@ typedef struct CFG_ CFG; typedef struct Scheduler_ Scheduler; +typedef SpvbFileBuilder* FileBuilder; +typedef SpvbBasicBlockBuilder* BBBuilder; + typedef struct { SpvbFnBuilder* base; CFG* cfg; Scheduler* scheduler; struct Dict* emitted; + struct { + SpvId continue_id; + BBBuilder continue_builder; + }* per_bb; } FnBuilder; -typedef SpvbFileBuilder* FileBuilder; -typedef SpvbBasicBlockBuilder* BBBuilder; - typedef struct Emitter_ { Module* module; IrArena* arena; diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 0db1157ee..b841a79ad 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -16,20 +16,23 @@ BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb) { return *found; } -static void add_branch_phis(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* dst, Nodes args) { - // because it's forbidden to jump back into the entry block of a function - // (which is actually a Function in this IR, not a BasicBlock) - // we assert that the destination must be an actual BasicBlock - assert(is_basic_block(dst)); - BBBuilder dst_builder = spv_find_basic_block_builder(emitter, dst); +static void add_phis(Emitter* emitter, FnBuilder* fn_builder, SpvId src, BBBuilder dst_builder, Nodes args) { struct List* phis = spbv_get_phis(dst_builder); assert(entries_count_list(phis) == args.count); for (size_t i = 0; i < args.count; i++) { SpvbPhi* phi = read_list(SpvbPhi*, phis)[i]; - spvb_add_phi_source(phi, get_block_builder_id(bb_builder), spv_emit_value(emitter, fn_builder, args.nodes[i])); + spvb_add_phi_source(phi, src, spv_emit_value(emitter, fn_builder, args.nodes[i])); } } +static void add_branch_phis(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* dst, Nodes args) { + // because it's forbidden to jump back into the entry block of a function + // (which is actually a Function in this IR, not a BasicBlock) + // we assert that the destination must be an actual BasicBlock + assert(is_basic_block(dst)); + add_phis(emitter, fn_builder, get_block_builder_id(bb_builder), spv_find_basic_block_builder(emitter, dst), args); +} + static void add_branch_phis_from_jump(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Jump jump) { return add_branch_phis(emitter, fn_builder, bb_builder, jump.target, jump.args); } @@ -76,7 +79,7 @@ static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_bui spvb_switch(bb_builder, inspectee, default_id, match.cases.count * literal_case_entry_size, literals_and_cases); } -static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Loop loop_instr) { +static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* abs, Loop loop_instr) { spv_emit_mem(emitter, fn_builder, loop_instr.mem); SpvId body_id = spv_find_emitted(emitter, fn_builder, loop_instr.body); @@ -84,30 +87,70 @@ static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_buil BBBuilder continue_builder = spvb_begin_bb(fn_builder->base, continue_id); spvb_name(emitter->file_builder, continue_id, "loop_continue"); - SpvId next_id = spv_find_emitted(emitter, fn_builder, loop_instr.tail); + SpvId header_id = spvb_fresh_id(emitter->file_builder); + BBBuilder header_builder = spvb_begin_bb(fn_builder->base, header_id); + spvb_name(emitter->file_builder, header_id, "loop_header"); + + Nodes body_params = get_abstraction_params(loop_instr.body); + LARRAY(SpvbPhi*, loop_continue_phis, body_params.count); + for (size_t i = 0; i < body_params.count; i++) { + SpvId loop_param_type = spv_emit_type(emitter, get_unqualified_type(body_params.nodes[i]->type)); + + SpvId continue_phi_id = spvb_fresh_id(emitter->file_builder); + SpvbPhi* continue_phi = spvb_add_phi(continue_builder, loop_param_type, continue_phi_id); + loop_continue_phis[i] = continue_phi; + + // To get the actual loop parameter, we make a second phi for the nodes that go into the header + // We already know the two edges into the header so we immediately add the Phi sources for it. + SpvId header_phi_id = spvb_fresh_id(emitter->file_builder); + SpvbPhi* header_phi = spvb_add_phi(header_builder, loop_param_type, header_phi_id); + SpvId param_initial_value = spv_emit_value(emitter, fn_builder, loop_instr.initial_args.nodes[i]); + spvb_add_phi_source(header_phi, get_block_builder_id(bb_builder), param_initial_value); + spvb_add_phi_source(header_phi, get_block_builder_id(continue_builder), continue_phi_id); + + BBBuilder body_builder = spv_find_basic_block_builder(emitter, loop_instr.body); + spvb_add_phi_source(read_list(SpvbPhi*, spbv_get_phis(body_builder))[i], get_block_builder_id(header_builder), header_phi_id); + } + + fn_builder->per_bb[cfg_lookup(fn_builder->cfg, abs)->rpo_index].continue_id = continue_id; + fn_builder->per_bb[cfg_lookup(fn_builder->cfg, abs)->rpo_index].continue_builder = continue_builder; + + SpvId tail_id = spv_find_emitted(emitter, fn_builder, loop_instr.tail); // the header block receives the loop merge annotation - spvb_loop_merge(bb_builder, next_id, continue_id, 0, 0, NULL); - spvb_branch(bb_builder, body_id); - add_branch_phis(emitter, fn_builder, bb_builder, loop_instr.body, loop_instr.initial_args); + spvb_loop_merge(header_builder, tail_id, continue_id, 0, 0, NULL); + spvb_branch(header_builder, body_id); + + spvb_add_bb(fn_builder->base, header_builder); // the continue block just jumps back into the header - spvb_branch(continue_builder, body_id); + spvb_branch(continue_builder, header_id); spvb_add_bb(fn_builder->base, continue_builder); + + spvb_branch(bb_builder, header_id); } -static const Node* find_construct(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Structured_constructTag tag) { - CFNode* n = cfg_lookup(fn_builder->cfg, abs); - while (n) { +static CFNode* find_surrounding_structured_construct_node(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Structured_constructTag tag) { + const Node* oabs = abs; + for (CFNode* n = cfg_lookup(fn_builder->cfg, abs); n; oabs = n->node, n = n->idom) { const Node* terminator = get_abstraction_body(n->node); assert(terminator); - if (terminator->tag == tag) - return terminator; - n = n->idom; + if (is_structured_construct(terminator) && get_structured_construct_tail(terminator) == oabs) { + continue; + } + if (terminator->tag == tag) { + printf("structured construct for %d is %d\n", abs->id, n->node->id); + return n; + } } return NULL; } +static const Node* find_construct(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Structured_constructTag tag) { + CFNode* found = find_surrounding_structured_construct_node(emitter, fn_builder, abs, tag); + return found ? get_abstraction_body(found->node) : NULL; +} + void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basic_block_builder, const Node* abs, const Node* terminator) { switch (is_terminator(terminator)) { case Return_TAG: { @@ -156,7 +199,6 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi LARRAY(SpvId, targets, terminator->payload.br_switch.case_jumps.count * 2); for (size_t i = 0; i < terminator->payload.br_switch.case_jumps.count; i++) { add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.br_switch.case_jumps.nodes[i]->payload.jump); - error("TODO finish") } add_branch_phis_from_jump(emitter, fn_builder, basic_block_builder, terminator->payload.br_switch.default_jump->payload.jump); SpvId default_tgt = spv_find_emitted(emitter, fn_builder, terminator->payload.br_switch.default_jump->payload.jump.target); @@ -166,7 +208,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi } case If_TAG: return emit_if(emitter, fn_builder, basic_block_builder, terminator->payload.if_instr); case Match_TAG: return emit_match(emitter, fn_builder, basic_block_builder, terminator->payload.match_instr); - case Loop_TAG: return emit_loop(emitter, fn_builder, basic_block_builder, terminator->payload.loop_instr); + case Loop_TAG: return emit_loop(emitter, fn_builder, basic_block_builder, abs, terminator->payload.loop_instr); case MergeSelection_TAG: { MergeSelection payload = terminator->payload.merge_selection; spv_emit_mem(emitter, fn_builder, payload.mem); @@ -175,19 +217,19 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi construct = find_construct(emitter, fn_builder, abs, Structured_construct_Match_TAG); const Node* tail = get_structured_construct_tail(construct); Nodes args = terminator->payload.merge_selection.args; - for (size_t i = 0; i < args.count; i++) add_branch_phis(emitter, fn_builder, basic_block_builder, tail, args); + assert(tail != abs); spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, tail)); return; } case MergeContinue_TAG: { MergeContinue payload = terminator->payload.merge_continue; spv_emit_mem(emitter, fn_builder, payload.mem); - const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_Loop_TAG); - Loop loop_payload = construct->payload.loop_instr; + CFNode* loop_entry = find_surrounding_structured_construct_node(emitter, fn_builder, abs, Structured_construct_Loop_TAG); + assert(loop_entry); Nodes args = terminator->payload.merge_continue.args; - add_branch_phis(emitter, fn_builder, basic_block_builder, loop_payload.body, args); - spvb_branch(basic_block_builder, spv_find_emitted(emitter, fn_builder, loop_payload.body)); + add_phis(emitter, fn_builder, get_block_builder_id(basic_block_builder), fn_builder->per_bb[loop_entry->rpo_index].continue_builder, args); + spvb_branch(basic_block_builder, fn_builder->per_bb[loop_entry->rpo_index].continue_id); return; } case MergeBreak_TAG: { diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 3af3fe5e9..b53150105 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -390,10 +390,15 @@ void destroy_cfg(CFG* cfg) { static size_t post_order_visit(CFG* cfg, CFNode* n, size_t i) { n->rpo_index = -2; - for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { - CFEdge edge = read_list(CFEdge, n->succ_edges)[j]; - if (edge.dst->rpo_index == SIZE_MAX) - i = post_order_visit(cfg, edge.dst, i); + for (int phase = 0; phase < 2; phase++) { + for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { + CFEdge edge = read_list(CFEdge, n->succ_edges)[j]; + // always visit structured tail edges last + if ((edge.type == StructuredTailEdge) == (phase == 1)) + continue; + if (edge.dst->rpo_index == SIZE_MAX) + i = post_order_visit(cfg, edge.dst, i); + } } n->rpo_index = i - 1; From 607c62549bfea227d7ca65ac3ae0eb0aa87ecf27 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 15 Aug 2024 12:15:45 +0200 Subject: [PATCH 494/693] spv: emit bbs in the order the validator expects --- src/backend/spirv/emit_spv.c | 30 ++++++++++------------- src/backend/spirv/emit_spv_control_flow.c | 15 ++++++------ 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index f0cb3b1e2..e6ecbe866 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -53,9 +53,9 @@ SpvId spv_find_emitted(Emitter* emitter, FnBuilder* fn_builder, const Node* node return *found; } -static void emit_basic_block(Emitter* emitter, FnBuilder* fn_builder, const CFG* cfg, const CFNode* cf_node) { +static void emit_basic_block(Emitter* emitter, FnBuilder* fn_builder, const CFNode* cf_node) { const Node* bb_node = cf_node->node; - assert(is_basic_block(bb_node) || cf_node == cfg->entry); + assert(is_basic_block(bb_node) || cf_node == fn_builder->cfg->entry); const Node* body = get_abstraction_body(bb_node); @@ -69,6 +69,14 @@ static void emit_basic_block(Emitter* emitter, FnBuilder* fn_builder, const CFG* spvb_name(emitter->file_builder, bb_id, name); spv_emit_terminator(emitter, fn_builder, bb_builder, bb_node, body); + + for (size_t i = 0; i < entries_count_list(cf_node->dominates); i++) { + CFNode* dominated = read_list(CFNode*, cf_node->dominates)[i]; + emit_basic_block(emitter, fn_builder, dominated); + } + + if (fn_builder->per_bb[cf_node->rpo_index].continue_builder) + spvb_add_bb(fn_builder->base, fn_builder->per_bb[cf_node->rpo_index].continue_builder); } static void emit_function(Emitter* emitter, const Node* node) { @@ -97,18 +105,15 @@ static void emit_function(Emitter* emitter, const Node* node) { } if (node->payload.fun.body) { - CFG* cfg = build_fn_cfg(node); // reserve a bunch of identifiers for the basic blocks in the CFG - for (size_t i = 0; i < cfg->size; i++) { - CFNode* cfnode = read_list(CFNode*, cfg->contents)[i]; + for (size_t i = 0; i < fn_builder.cfg->size; i++) { + CFNode* cfnode = read_list(CFNode*, fn_builder.cfg->contents)[i]; assert(cfnode); const Node* bb = cfnode->node; assert(is_basic_block(bb) || bb == node); SpvId bb_id = spvb_fresh_id(emitter->file_builder); BBBuilder basic_block_builder = spvb_begin_bb(fn_builder.base, bb_id); insert_dict(const Node*, BBBuilder, emitter->bb_builders, bb, basic_block_builder); - // if (is_cfnode_structural_target(cfnode)) - // continue; // add phis for every non-entry basic block if (i > 0) { assert(is_basic_block(bb) && bb != node); @@ -123,17 +128,8 @@ static void emit_function(Emitter* emitter, const Node* node) { spv_register_emitted(emitter, false, bb, bb_id); } } - // emit the blocks using the dominator tree - for (size_t i = 0; i < cfg->size; i++) { - CFNode* cfnode = cfg->rpo[i]; - if (i == 0) - assert(cfnode == cfg->entry); - // if (is_cfnode_structural_target(cfnode)) - // continue; - emit_basic_block(emitter, &fn_builder, cfg, cfnode); - } + emit_basic_block(emitter, &fn_builder, fn_builder.cfg->entry); - destroy_cfg(cfg); free(fn_builder.per_bb); spvb_define_function(emitter->file_builder, fn_builder.base); diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index b841a79ad..35b45084d 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -112,8 +112,8 @@ static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_buil spvb_add_phi_source(read_list(SpvbPhi*, spbv_get_phis(body_builder))[i], get_block_builder_id(header_builder), header_phi_id); } - fn_builder->per_bb[cfg_lookup(fn_builder->cfg, abs)->rpo_index].continue_id = continue_id; - fn_builder->per_bb[cfg_lookup(fn_builder->cfg, abs)->rpo_index].continue_builder = continue_builder; + fn_builder->per_bb[cfg_lookup(fn_builder->cfg, loop_instr.body)->rpo_index].continue_id = continue_id; + fn_builder->per_bb[cfg_lookup(fn_builder->cfg, loop_instr.body)->rpo_index].continue_builder = continue_builder; SpvId tail_id = spv_find_emitted(emitter, fn_builder, loop_instr.tail); @@ -125,7 +125,6 @@ static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_buil // the continue block just jumps back into the header spvb_branch(continue_builder, header_id); - spvb_add_bb(fn_builder->base, continue_builder); spvb_branch(bb_builder, header_id); } @@ -225,11 +224,13 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi case MergeContinue_TAG: { MergeContinue payload = terminator->payload.merge_continue; spv_emit_mem(emitter, fn_builder, payload.mem); - CFNode* loop_entry = find_surrounding_structured_construct_node(emitter, fn_builder, abs, Structured_construct_Loop_TAG); - assert(loop_entry); + const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_Loop_TAG); + Loop loop_payload = construct->payload.loop_instr; + CFNode* loop_body = cfg_lookup(fn_builder->cfg, loop_payload.body); + assert(loop_body); Nodes args = terminator->payload.merge_continue.args; - add_phis(emitter, fn_builder, get_block_builder_id(basic_block_builder), fn_builder->per_bb[loop_entry->rpo_index].continue_builder, args); - spvb_branch(basic_block_builder, fn_builder->per_bb[loop_entry->rpo_index].continue_id); + add_phis(emitter, fn_builder, get_block_builder_id(basic_block_builder), fn_builder->per_bb[loop_body->rpo_index].continue_builder, args); + spvb_branch(basic_block_builder, fn_builder->per_bb[loop_body->rpo_index].continue_id); return; } case MergeBreak_TAG: { From 18fde87d3362dfc68e8e326a8c63034a57169af9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 15 Aug 2024 16:57:09 +0200 Subject: [PATCH 495/693] fix build on macOS --- src/backend/spirv/CMakeLists.txt | 1 - src/shady/CMakeLists.txt | 1 - src/shady/api/CMakeLists.txt | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/spirv/CMakeLists.txt b/src/backend/spirv/CMakeLists.txt index 9b300f7d8..e99e21ff6 100644 --- a/src/backend/spirv/CMakeLists.txt +++ b/src/backend/spirv/CMakeLists.txt @@ -14,7 +14,6 @@ target_include_directories(shady_spirv PRIVATE $") target_link_libraries(shady_spirv PRIVATE "$") -target_link_libraries(shady_spirv PRIVATE "$") target_link_libraries(shady_spirv PRIVATE "$") target_link_libraries(driver PUBLIC "$") diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index ead1d19c0..164f4d2bb 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -62,7 +62,6 @@ add_subdirectory(internal) target_link_libraries(shady PRIVATE "api") target_link_libraries(shady PRIVATE "common") target_link_libraries(shady PRIVATE "$") -target_link_libraries(shady PRIVATE "$") install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/shady DESTINATION include) #install(TARGETS shady EXPORT shady_export_set ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) diff --git a/src/shady/api/CMakeLists.txt b/src/shady/api/CMakeLists.txt index 943011410..d63fefe47 100644 --- a/src/shady/api/CMakeLists.txt +++ b/src/shady/api/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(api INTERFACE) target_include_directories(api INTERFACE "$" "$" "$") target_include_directories(api INTERFACE "$") +target_link_libraries(api INTERFACE "$") get_target_property(SPIRV_HEADERS_INCLUDE_DIRS SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) From a6a2cd53cbd88833f4c1699e67aabf85ddb7620d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 16 Aug 2024 08:53:40 +0200 Subject: [PATCH 496/693] add sanity check for dictionnaries --- src/common/CMakeLists.txt | 5 +++ src/common/test_dict.c | 91 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/common/test_dict.c diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e26da894d..e1c8da998 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -23,3 +23,8 @@ function(embed_file TYPE NAME SRC) target_include_directories(${NAME} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) endfunction() +if (BUILD_TESTING) + add_executable(test_dict test_dict.c) + target_link_libraries(test_dict PRIVATE common) + add_test(NAME test_dict COMMAND test_dict) +endif () \ No newline at end of file diff --git a/src/common/test_dict.c b/src/common/test_dict.c new file mode 100644 index 000000000..f4e29a4b0 --- /dev/null +++ b/src/common/test_dict.c @@ -0,0 +1,91 @@ +#include "dict.h" +#include "log.h" + +#include +#include +#include + +// purposefully bad hash to make sure the collision handling is solid +KeyHash bad_hash_i32(int* i) { + return *i; +} + +bool compare_i32(int* pa, int* pb) { + return *pa == *pb; +} + +#define TEST_ENTRIES 10000 + +void shuffle(int arr[]) { + for (int i = 0; i < TEST_ENTRIES; i++) { + int a = rand() % TEST_ENTRIES; + int b = rand() % TEST_ENTRIES; + int tmp = arr[a]; + arr[a] = arr[b]; + arr[b] = tmp; + } +} + +int main(int argc, char** argv) { + srand((int) get_time_nano()); + struct Dict* d = new_set(int, (HashFn) bad_hash_i32, (CmpFn) compare_i32); + + int arr[TEST_ENTRIES]; + for (int i = 0; i < TEST_ENTRIES; i++) { + arr[i] = i; + } + + shuffle(arr); + + bool contained[TEST_ENTRIES]; + memset(contained, 0, sizeof(contained)); + + for (int i = 0; i < TEST_ENTRIES; i++) { + bool unique = insert_set_get_result(int, d, arr[i]); + if (!unique) { + error("Entry %d was thought to be already in the dict", arr[i]); + } + contained[arr[i]] = true; + } + + shuffle(arr); + for (int i = 0; i < TEST_ENTRIES; i++) { + assert(contained[arr[i]]); + assert(find_key_dict(int, d, arr[i])); + } + + shuffle(arr); + for (int i = 0; i < rand() % TEST_ENTRIES; i++) { + assert(contained[arr[i]]); + bool removed = remove_dict(int, d, arr[i]); + assert(removed); + contained[arr[i]] = false; + } + + shuffle(arr); + for (int i = 0; i < TEST_ENTRIES; i++) { + assert(!!find_key_dict(int, d, arr[i]) == contained[arr[i]]); + } + + shuffle(arr); + for (int i = 0; i < TEST_ENTRIES; i++) { + assert(!!find_key_dict(int, d, arr[i]) == contained[arr[i]]); + if (!contained[arr[i]]) { + bool unique = insert_set_get_result(int, d, arr[i]); + if (!unique) { + error("Entry %d was thought to be already in the dict", arr[i]); + } + contained[arr[i]] = true; + } + assert(contained[arr[i]]); + } + + shuffle(arr); + for (int i = 0; i < TEST_ENTRIES; i++) { + assert(contained[arr[i]]); + assert(find_key_dict(int, d, arr[i])); + } + + destroy_dict(d); + return 0; +} From 01d2ad92efee8865a1bba68c5b613cfd3bbcb51d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 16 Aug 2024 10:34:01 +0200 Subject: [PATCH 497/693] reconvergence_heuristics are doomed, needs rewrite :s --- src/shady/analysis/cfg_dump.c | 2 +- src/shady/passes/reconvergence_heuristics.c | 24 ++++++++------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 82f16790e..c0c799acb 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -48,7 +48,7 @@ static void dump_cf_node(FILE* output, const CFNode* n) { String abs_name = get_abstraction_name_safe(bb); - print(p, "%s: \n%s: ", abs_name, abs_name); + print(p, "%s: \n%d: ", abs_name, bb->id); print_node_helper(p, body); print(p, "\\l"); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 8def78018..18a2cffcd 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -170,21 +170,13 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); - switch (exiting_node->node->tag) { - case BasicBlock_TAG: { - Node* pre_join_exit_bb = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); - set_abstraction_body(pre_join_exit_bb, jump_helper(arena, exit_helpers[i], empty(arena), get_abstraction_mem(pre_join_exit_bb))); - exit_wrappers[i] = pre_join_exit_bb; - break; - } - default: - assert(false); - } + Node* pre_join_exit_bb = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); + set_abstraction_body(pre_join_exit_bb, jump_helper(arena, exit_helpers[i], empty(arena), get_abstraction_mem(pre_join_exit_bb))); + exit_wrappers[i] = pre_join_exit_bb; } Nodes continue_wrapper_params = recreate_params(rewriter, get_abstraction_params(node)); - Node* continue_wrapper; - continue_wrapper = basic_block(arena, continue_wrapper_params, "continue"); + Node* continue_wrapper = basic_block(arena, continue_wrapper_params, "continue"); const Node* continue_wrapper_body = join(arena, (Join) { .join_point = join_token_continue, .args = continue_wrapper_params, @@ -216,6 +208,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { rewriter->map = clone_dict(rewriter->map); Nodes inner_loop_params = recreate_params(rewriter, get_abstraction_params(node)); register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); + Node* inner_control_case = case_(arena, singleton(join_token_continue)); + register_processed(rewriter, get_abstraction_mem(node), get_abstraction_mem(inner_control_case)); const Node* loop_body = recreate_node_identity(rewriter, get_abstraction_body(node)); // save the context @@ -237,6 +231,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { set_abstraction_body(exit_helpers[i], finish_body_with_join(exit_wrapper_bb, join_token_exit, empty(arena))); } + set_abstraction_body(inner_control_case, loop_body); + destroy_dict(rewriter->map); rewriter->map = old_map; //register_processed_list(rewriter, get_abstraction_params(node), nparams); @@ -253,11 +249,9 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); BodyBuilder* inner_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_outer)); - Node* inner_control_case = case_(arena, singleton(join_token_continue)); - set_abstraction_body(inner_control_case, loop_body); Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); - set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_body, inner_control_results)); + set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); Node* outer_control_case = case_(arena, singleton(join_token_exit)); set_abstraction_body(outer_control_case, jump(arena, (Jump) { .target = loop_outer, From 032fc9325b81a9c541e4b751089176b1a2059903 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 16 Aug 2024 10:56:37 +0200 Subject: [PATCH 498/693] vcc: added a cmake setting for clang name --- vcc/CMakeLists.txt | 3 +++ vcc/vcc_lib.c | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/vcc/CMakeLists.txt b/vcc/CMakeLists.txt index 522b1da0b..6973e0806 100644 --- a/vcc/CMakeLists.txt +++ b/vcc/CMakeLists.txt @@ -5,10 +5,13 @@ else() endif() if (SHADY_ENABLE_VCC) + set (VCC_CLANG_EXECUTABLE_NAME "clang" CACHE STRING "What 'clang' executable Vcc should call into") + add_library(vcc_lib STATIC vcc_lib.c) target_link_libraries(vcc_lib PUBLIC driver api) add_executable(vcc vcc.c) + target_compile_definitions(vcc_lib PRIVATE "VCC_CLANG_EXECUTABLE_NAME=${VCC_CLANG_EXECUTABLE_NAME}") target_link_libraries(vcc PRIVATE api vcc_lib) install(TARGETS vcc_lib vcc EXPORT shady_export_set) diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 9ae8db86a..46d5919cb 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -9,6 +9,10 @@ #include #include +#define STRINGIFY2(x) #x +#define STRINGIFY(x) STRINGIFY2(x) +#define VCC_CLANG STRINGIFY(VCC_CLANG_EXECUTABLE_NAME) + uint32_t hash_murmur(const void* data, size_t size); void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { @@ -42,7 +46,7 @@ void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { } void vcc_check_clang(void) { - int clang_retval = system("clang --version"); + int clang_retval = system(VCC_CLANG" --version"); if (clang_retval != 0) error("clang not present in path or otherwise broken (retval=%d)", clang_retval); } @@ -74,7 +78,7 @@ void destroy_vcc_options(VccConfig vcc_options) { void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* input_filenames) { Growy* g = new_growy(); - growy_append_string(g, "clang"); + growy_append_string(g, VCC_CLANG); String self_path = get_executable_location(); String working_dir = strip_path(self_path); growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options->include_path); From 1cf11fceb43b3ddf4f1d57dea05f8fef79730d86 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 16 Aug 2024 11:42:05 +0200 Subject: [PATCH 499/693] l2s: updates to API --- src/frontend/llvm/l2s.c | 21 ++-- src/frontend/llvm/l2s_instr.c | 166 ++++++++++++-------------------- src/frontend/llvm/l2s_meta.c | 2 +- src/frontend/llvm/l2s_private.h | 8 +- src/frontend/llvm/l2s_value.c | 3 +- 5 files changed, 75 insertions(+), 125 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 5c9ca85d5..02c926c86 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -53,17 +53,18 @@ static const Node* write_bb_tail(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, assert(LLVMGetBasicBlockTerminator(bb) == instr); // LLVMDumpValue(instr); // printf("\n"); - EmittedInstr emitted = convert_instruction(p, fn_ctx, fn_or_bb, b, instr); - if (emitted.terminator) - return finish_body(b, emitted.terminator); - if (!emitted.instruction) + const Node* emitted = convert_instruction(p, fn_ctx, fn_or_bb, b, instr); + if (!emitted) continue; - String names[] = { LLVMGetValueName(instr) }; - Nodes results = bind_instruction_outputs_count(b, emitted.instruction, emitted.result_types.count); - if (emitted.result_types.count == 1) { - const Node* result = first(results); - insert_dict(LLVMValueRef, const Node*, p->map, instr, result); - } + insert_dict(LLVMValueRef, const Node*, p->map, instr, emitted); + if (is_terminator(emitted)) + return finish_body(b, emitted); + //String names[] = { LLVMGetValueName(instr) }; + //Nodes results = bind_instruction_outputs_count(b, emitted.instruction, emitted.result_types.count); + //if (emitted.result_types.count == 1) { + // const Node* result = first(results); + // insert_dict(LLVMValueRef, const Node*, p->map, instr, result); + //} } SHADY_UNREACHABLE; } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 94391e9e7..d4a9f1fb8 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -101,14 +101,14 @@ static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* eleme } /// instr may be an instruction or a constantexpr -EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { +const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { Node* fn = fn_ctx ? fn_ctx->fn : NULL; IrArena* a = get_module_arena(p->dst); int num_ops = LLVMGetNumOperands(instr); size_t num_results = 1; Nodes result_types = empty(a); - const Node* r = NULL; + // const Node* r = NULL; LLVMOpcode opcode; if (LLVMIsAInstruction(instr)) @@ -144,12 +144,10 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, } switch (opcode) { - case LLVMRet: return (EmittedInstr) { - .terminator = fn_ret(a, (Return) { + case LLVMRet: return fn_ret(a, (Return) { .args = num_ops == 0 ? empty(a) : convert_operands(p, num_ops, instr), .mem = bb_mem(b), - }) - }; + }); case LLVMBr: { unsigned n_targets = LLVMGetNumSuccessors(instr); LARRAY(LLVMBasicBlockRef, targets, n_targets); @@ -158,19 +156,15 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, if (LLVMIsConditional(instr)) { assert(n_targets == 2); const Node* condition = convert_value(p, LLVMGetCondition(instr)); - return (EmittedInstr) { - .terminator = branch(a, (Branch) { + return branch(a, (Branch) { .condition = condition, .true_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)), .false_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[1], bb_mem(b)), .mem = bb_mem(b), - }) - }; + }); } else { assert(n_targets == 1); - return (EmittedInstr) { - .terminator = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)) - }; + return convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)); } } case LLVMSwitch: { @@ -183,89 +177,68 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); targets[i] = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3), bb_mem(b)); } - return (EmittedInstr) { - .terminator = br_switch(a, (Switch) { + return br_switch(a, (Switch) { .switch_value = inspectee, .default_jump = default_jump, .case_values = nodes(a, n_targets, literals), .case_jumps = nodes(a, n_targets, targets), .mem = bb_mem(b), - }) - }; + }); } case LLVMIndirectBr: goto unimplemented; case LLVMInvoke: goto unimplemented; - case LLVMUnreachable: return (EmittedInstr) { - .terminator = unreachable(a, (Unreachable) { .mem = bb_mem(b) }) - }; + case LLVMUnreachable: return unreachable(a, (Unreachable) { .mem = bb_mem(b) }); case LLVMCallBr: goto unimplemented; case LLVMFNeg: - r = prim_op_helper(a, neg_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, neg_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMFAdd: case LLVMAdd: - r = prim_op_helper(a, add_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, add_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMSub: case LLVMFSub: - r = prim_op_helper(a, sub_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, sub_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMMul: case LLVMFMul: - r = prim_op_helper(a, mul_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, mul_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMUDiv: case LLVMFDiv: - r = prim_op_helper(a, div_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, div_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMSDiv: { const Type* int_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* signed_t = change_int_t_sign(int_t, true); - r = prim_op_helper(a, div_op, empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)); - r = prim_op_helper(a, reinterpret_op, singleton(int_t), BIND_PREV_R(signed_t)); - break; + return prim_op_helper(a, reinterpret_op, singleton(int_t), singleton(prim_op_helper(a, div_op, empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)))); } case LLVMURem: case LLVMFRem: - r = prim_op_helper(a, mod_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, mod_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMSRem: { const Type* int_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* signed_t = change_int_t_sign(int_t, true); - r = prim_op_helper(a, mod_op, empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)); - r = prim_op_helper(a, reinterpret_op, singleton(int_t), BIND_PREV_R(signed_t)); - break; + return prim_op_helper(a, reinterpret_op, singleton(int_t), singleton(prim_op_helper(a, mod_op, empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)))); } case LLVMShl: - r = prim_op_helper(a, lshift_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, lshift_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMLShr: - r = prim_op_helper(a, rshift_logical_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, rshift_logical_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMAShr: - r = prim_op_helper(a, rshift_arithm_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, rshift_arithm_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMAnd: - r = prim_op_helper(a, and_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, and_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMOr: - r = prim_op_helper(a, or_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, or_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMXor: - r = prim_op_helper(a, xor_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, xor_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMAlloca: { assert(t->tag == PtrType_TAG); const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivate }); - r = first(bind_instruction_outputs_count(b, stack_alloc(a, (StackAlloc) { .type = allocated_t, .mem = bb_mem(b) }), 1)); + const Node* r = first(bind_instruction_outputs_count(b, stack_alloc(a, (StackAlloc) { .type = allocated_t, .mem = bb_mem(b) }), 1)); if (UNTYPED_POINTERS) { const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivate }); r = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), 1)); } - r = prim_op_helper(a, convert_op, singleton(t), singleton(r)); - break; + return prim_op_helper(a, convert_op, singleton(t), singleton(r)); } case LLVMLoad: { Nodes ops = convert_operands(p, num_ops, instr); @@ -277,8 +250,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } - r = load(a, (Load) { .ptr = ptr, .mem = bb_mem(b) }); - break; + return bind_instruction_single(b, load(a, (Load) { .ptr = ptr, .mem = bb_mem(b) })); } case LLVMStore: { num_results = 0; @@ -291,8 +263,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } - r = store(a, (Store) { .ptr = ptr, .value = ops.nodes[0], .mem = bb_mem(b) }); - break; + return bind_instruction_single(b, store(a, (Store) { .ptr = ptr, .value = ops.nodes[0], .mem = bb_mem(b) })); } case LLVMGetElementPtr: { Nodes ops = convert_operands(p, num_ops, instr); @@ -304,7 +275,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } ops = change_node_at_index(a, ops, 0, ptr); - r = lea(a, (Lea) { .ptr = ops.nodes[0], .offset = ops.nodes[1], .indices = nodes(a, ops.count - 2, &ops.nodes[2])}); + const Node* r = lea(a, (Lea) { .ptr = ops.nodes[0], .offset = ops.nodes[1], .indices = nodes(a, ops.count - 2, &ops.nodes[2])}); if (UNTYPED_POINTERS) { const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); @@ -314,12 +285,13 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); r = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), BIND_PREV_R(typed_ptr)); } - break; + return r; } case LLVMTrunc: case LLVMZExt: { const Type* src_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); Nodes ops = convert_operands(p, num_ops, instr); + const Node* r; if (src_t->tag == Bool_TAG) { assert(t->tag == Int_TAG); const Node* zero = int_literal(a, (IntLiteral) { .value = 0, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); @@ -337,8 +309,9 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, r = prim_op_helper(a, convert_op, singleton(unsigned_dst_t), reinterpret_operands(b, ops, unsigned_src_t)); r = prim_op_helper(a, reinterpret_op, singleton(t), BIND_PREV_R(unsigned_dst_t)); } - break; + return r; } case LLVMSExt: { + const Node* r; // reinterpret as signed, convert to change size, reinterpret back to target T const Type* src_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); Nodes ops = convert_operands(p, num_ops, instr); @@ -352,15 +325,14 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* signed_src_t = change_int_t_sign(src_t, true); const Type* signed_dst_t = change_int_t_sign(t, true); r = prim_op_helper(a, convert_op, singleton(signed_dst_t), reinterpret_operands(b, ops, signed_src_t)); - r = prim_op_helper(a, reinterpret_op, singleton(t), BIND_PREV_R(signed_dst_t)); + r = prim_op_helper(a, reinterpret_op, singleton(t), singleton(r)); } - break; + return r; } case LLVMFPToUI: case LLVMFPToSI: case LLVMUIToFP: case LLVMSIToFP: - r = prim_op_helper(a, convert_op, singleton(t), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, convert_op, singleton(t), convert_operands(p, num_ops, instr)); case LLVMFPTrunc: goto unimplemented; case LLVMFPExt: @@ -388,8 +360,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, } else { assert(opcode != LLVMAddrSpaceCast); } - r = prim_op_helper(a, op, singleton(t), singleton(src)); - break; + return prim_op_helper(a, op, singleton(t), singleton(src)); } case LLVMICmp: { Op op; @@ -437,8 +408,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, const Type* signed_t = change_int_t_sign(unsigned_t, true); ops = reinterpret_operands(b, ops, signed_t); } - r = prim_op_helper(a, op, empty(a), ops); - break; + return prim_op_helper(a, op, empty(a), ops); } case LLVMFCmp: { Op op; @@ -471,13 +441,14 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, default: goto unimplemented; } Nodes ops = convert_operands(p, num_ops, instr); - r = prim_op_helper(a, op, empty(a), ops); + return prim_op_helper(a, op, empty(a), ops); break; } case LLVMPHI: assert(false && "We deal with phi nodes before, there shouldn't be one here"); break; case LLVMCall: { + const Node* r; unsigned num_args = LLVMGetNumArgOperands(instr); LLVMValueRef callee = LLVMGetCalledValue(instr); callee = remove_ptr_bitcasts(p, callee); @@ -502,51 +473,39 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, String name = get_string_literal(target->arena, name_node); assert(name); set_value_name((Node*) target, name); - return (EmittedInstr) { 0 }; + return NULL; } if (strcmp(intrinsic, "llvm.dbg.label") == 0) { // TODO - return (EmittedInstr) { 0 }; + return NULL; } if (strcmp(intrinsic, "llvm.dbg.value") == 0) { // TODO - return (EmittedInstr) { 0 }; + return NULL; } if (string_starts_with(intrinsic, "llvm.lifetime")) { // don't care - return (EmittedInstr) { 0 }; + return NULL; } if (string_starts_with(intrinsic, "llvm.experimental.noalias.scope.decl")) { // don't care - return (EmittedInstr) { 0 }; + return NULL; } if (string_starts_with(intrinsic, "llvm.memcpy")) { Nodes ops = convert_operands(p, num_ops, instr); - num_results = 0; - r = copy_bytes(a, (CopyBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2] }); - break; + return bind_instruction_single(b, copy_bytes(a, (CopyBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = bb_mem(b) })); } else if (string_starts_with(intrinsic, "llvm.memset")) { Nodes ops = convert_operands(p, num_ops, instr); - num_results = 0; - r = fill_bytes(a, (FillBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2] }); - break; + return bind_instruction_single(b, fill_bytes(a, (FillBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = bb_mem(b) })); } else if (string_starts_with(intrinsic, "llvm.fmuladd")) { Nodes ops = convert_operands(p, num_ops, instr); - num_results = 1; - r = prim_op_helper(a, fma_op, empty(a), nodes(a, 3, ops.nodes)); - // r = prim_op_helper(a, mul_op, empty(a), nodes(a, 2, ops.nodes)); - // r = prim_op_helper(a, add_op, empty(a), mk_nodes(a, first(BIND_PREV_R(convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))))), ops.nodes[2])); - break; + return prim_op_helper(a, fma_op, empty(a), nodes(a, 3, ops.nodes)); } else if (string_starts_with(intrinsic, "llvm.fabs")) { Nodes ops = convert_operands(p, num_ops, instr); - num_results = 1; - r = prim_op_helper(a, abs_op, empty(a), nodes(a, 1, ops.nodes)); - break; + return prim_op_helper(a, abs_op, empty(a), nodes(a, 1, ops.nodes)); } else if (string_starts_with(intrinsic, "llvm.floor")) { Nodes ops = convert_operands(p, num_ops, instr); - num_results = 1; - r = prim_op_helper(a, floor_op, empty(a), nodes(a, 1, ops.nodes)); - break; + return prim_op_helper(a, floor_op, empty(a), nodes(a, 1, ops.nodes)); } typedef struct { @@ -614,7 +573,8 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, size_t whocares; r = debug_printf(a, (DebugPrintf) { .string = LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), - .args = nodes(a, ops.count - 1, &ops.nodes[1]) + .args = nodes(a, ops.count - 1, &ops.nodes[1]), + .mem = bb_mem(b), }); goto finish; } @@ -635,17 +595,16 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, if (!r) { Nodes ops = convert_operands(p, num_ops, instr); r = call(a, (Call) { - .callee = ops.nodes[num_args], - .args = nodes(a, num_args, ops.nodes), + .callee = ops.nodes[num_args], + .args = nodes(a, num_args, ops.nodes), }); } if (t == unit_type(a)) num_results = 0; - break; + return r; } case LLVMSelect: - r = prim_op_helper(a, select_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, select_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMUserOp1: goto unimplemented; case LLVMUserOp2: @@ -653,11 +612,9 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, case LLVMVAArg: goto unimplemented; case LLVMExtractElement: - r = prim_op_helper(a, extract_dynamic_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, extract_dynamic_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMInsertElement: - r = prim_op_helper(a, insert_op, empty(a), convert_operands(p, num_ops, instr)); - break; + return prim_op_helper(a, insert_op, empty(a), convert_operands(p, num_ops, instr)); case LLVMShuffleVector: { Nodes ops = convert_operands(p, num_ops, instr); unsigned num_indices = LLVMGetNumMaskElements(instr); @@ -665,8 +622,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, for (size_t i = 0; i < num_indices; i++) cindices[i] = uint32_literal(a, LLVMGetMaskValue(instr, i)); ops = concat_nodes(a, ops, nodes(a, num_indices, cindices)); - r = prim_op_helper(a, shuffle_op, empty(a), ops); - break; + return prim_op_helper(a, shuffle_op, empty(a), ops); } case LLVMExtractValue: goto unimplemented; @@ -695,7 +651,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, case LLVMCatchSwitch: goto unimplemented; } - shortcut: + /*shortcut: if (r) { if (num_results == 1) result_types = singleton(convert_type(p, LLVMTypeOf(instr))); @@ -704,7 +660,7 @@ EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, .instruction = r, .result_types = result_types, }; - } + }*/ unimplemented: error_print("Shady: unimplemented LLVM instruction "); diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index b095b53b5..3554dbb8f 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -27,7 +27,7 @@ static const Node* convert_named_tuple_metadata(Parser* p, LLVMValueRef v, Strin String name = LLVMGetValueName(v); if (!name || strlen(name) == 0) name = unique_name(a, node_name); - Node* g = global_var(p->dst, singleton(annotation(a, (Annotation) { .name = "LLVMMetaData" })), NULL, name, AsDebugInfo); + Node* g = global_var(p->dst, singleton(annotation(a, (Annotation) { .name = "LLVMMetaData" })), unit_type(a), name, AsDebugInfo); const Node* r = ref_decl_helper(a, g); insert_dict(LLVMValueRef, const Type*, p->map, v, r); diff --git a/src/frontend/llvm/l2s_private.h b/src/frontend/llvm/l2s_private.h index f530e2c96..3676263de 100644 --- a/src/frontend/llvm/l2s_private.h +++ b/src/frontend/llvm/l2s_private.h @@ -57,12 +57,6 @@ const Node* convert_global(Parser* p, LLVMValueRef global); const Node* convert_function(Parser* p, LLVMValueRef fn); const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); -typedef struct { - const Node* terminator; - const Node* instruction; - Nodes result_types; -} EmittedInstr; - typedef struct { struct List* list; } BBPhis; @@ -74,7 +68,7 @@ typedef struct { } JumpTodo; void convert_jump_finish(Parser* p, FnParseCtx*, JumpTodo todo); -EmittedInstr convert_instruction(Parser* p, FnParseCtx*, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); +const Node* convert_instruction(Parser* p, FnParseCtx*, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc); diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index d80f2a427..a1ca549ad 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -84,8 +84,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { r = ref_decl_helper(a, decl); insert_dict(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = begin_block_pure(a); - EmittedInstr emitted = convert_instruction(p, NULL, NULL, bb, v); - decl->payload.constant.value = bind_last_instruction_and_wrap_in_block(bb, emitted.instruction); + decl->payload.constant.value = yield_value_and_wrap_in_block(bb, convert_instruction(p, NULL, NULL, bb, v)); return r; } case LLVMConstantDataArrayValueKind: { From 759f3c11670ea78c8ec607f3da81e1e05c34b480 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 19 Aug 2024 11:27:50 +0200 Subject: [PATCH 500/693] removed reconvergence heuristics pass --- src/shady/compile.c | 2 +- src/shady/passes/CMakeLists.txt | 1 - src/shady/passes/passes.h | 2 +- src/shady/passes/reconvergence_heuristics.c | 494 -------------------- 4 files changed, 2 insertions(+), 497 deletions(-) delete mode 100644 src/shady/passes/reconvergence_heuristics.c diff --git a/src/shady/compile.c b/src/shady/compile.c index d7ce8d5c9..9d0b54ed4 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -52,7 +52,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { } RUN_PASS(eliminate_inlineable_constants) - RUN_PASS(reconvergence_heuristics) + //RUN_PASS(reconvergence_heuristics) RUN_PASS(lower_cf_instrs) //RUN_PASS(opt_mem2reg) // run because control-flow is now normalized diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index 0efd2349c..71d61141c 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -30,7 +30,6 @@ target_sources(shady PRIVATE opt_inline.c opt_restructure.c opt_demote_alloca.c - reconvergence_heuristics.c specialize_entry_point.c specialize_execution_model.c lower_logical_pointers.c diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 80bd779ae..e8ee859fb 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -17,7 +17,7 @@ RewritePass cleanup; /// Gets rid of structured control flow constructs, and turns them into branches, joins and tailcalls RewritePass lower_cf_instrs; /// Try to identify reconvergence points throughout the program for unstructured control flow programs -RewritePass reconvergence_heuristics; +//RewritePass reconvergence_heuristics; /// @} diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c deleted file mode 100644 index 18a2cffcd..000000000 --- a/src/shady/passes/reconvergence_heuristics.c +++ /dev/null @@ -1,494 +0,0 @@ -#include "shady/pass.h" - -#include "../type.h" -#include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" - -#include "../analysis/cfg.h" -#include "../analysis/looptree.h" -#include "../analysis/free_variables.h" - -#include "list.h" -#include "dict.h" -#include "log.h" -#include "portability.h" -#include "util.h" - -#include - -typedef struct Context_ { - Rewriter rewriter; - const CompilerConfig* config; - const Node* current_fn; - const Node* current_abstraction; - CFG* fwd_cfg; - CFG* rev_cfg; - LoopTree* current_looptree; - struct Dict* live_vars; -} Context; - -static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { - LTNode* lt_node = looptree_lookup(lt, block); - assert(lt_node); - LTNode* parent = lt_node->parent; - assert(parent); - - while (parent) { - if (entries_count_list(parent->cf_nodes) != 1) - return false; - - if (read_list(CFNode*, parent->cf_nodes)[0]->node == entry) - return true; - - parent = parent->parent; - } - - return false; -} - -//TODO: This is massively inefficient. -static void gather_exiting_nodes(LoopTree* lt, const CFNode* entry, const CFNode* block, struct List* exiting_nodes) { - if (!in_loop(lt, entry->node, block->node)) { - append_list(CFNode*, exiting_nodes, block); - return; - } - - for (size_t i = 0; i < entries_count_list(block->dominates); i++) { - const CFNode* target = read_list(CFNode*, block->dominates)[i]; - gather_exiting_nodes(lt, entry, target, exiting_nodes); - } -} - -static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { - const Node* v; - size_t i = 0; - while (dict_iter(free_set, &i, &v, NULL)) { - if (find_key_dict(const Node*, bound_set, v)) - continue; - - log_string(DEBUGVV, "Found variable used outside it's control scope: "); - log_node(DEBUGVV, v); - log_string(DEBUGVV, " (exiting_node:"); - log_node(DEBUGVV, exiting_node); - log_string(DEBUGVV, " )\n"); - - append_list(const Node*, leaking, v); - } -} - -static const Node* process_abstraction(Context* ctx, const Node* node) { - assert(is_abstraction(node)); - Context new_context = *ctx; - ctx = &new_context; - ctx->current_abstraction = node; - Rewriter* rewriter = &ctx->rewriter; - IrArena* arena = rewriter->dst_arena; - - CFNode* current_node = cfg_lookup(ctx->fwd_cfg, node); - LTNode* lt_node = looptree_lookup(ctx->current_looptree, node); - LTNode* loop_header = NULL; - - assert(current_node); - assert(lt_node); - - bool is_loop_entry = false; - if (lt_node->parent && lt_node->parent->type == LF_HEAD) { - if (entries_count_list(lt_node->parent->cf_nodes) == 1) - if (read_list(CFNode*, lt_node->parent->cf_nodes)[0]->node == node) { - loop_header = lt_node->parent; - assert(loop_header->type == LF_HEAD); - assert(entries_count_list(loop_header->cf_nodes) == 1 && "only reducible loops are handled"); - is_loop_entry = true; - } - } - - if (is_loop_entry) { - assert(!is_function(node)); - - struct List* exiting_nodes = new_list(CFNode*); - gather_exiting_nodes(ctx->current_looptree, current_node, current_node, exiting_nodes); - - for (size_t i = 0; i < entries_count_list(exiting_nodes); i++) { - debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(read_list(CFNode*, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); - } - - size_t exiting_nodes_count = entries_count_list(exiting_nodes); - if (exiting_nodes_count > 0) { - Nodes nparams = recreate_params(rewriter, get_abstraction_params(node)); - Node* loop_container = basic_block(arena, nparams, node->payload.basic_block.name); - BodyBuilder* outer_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_container)); - Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); - - CFNode* cf_pre = cfg_lookup(ctx->fwd_cfg, node); - // assert(cf_pre->idom && "cfg entry nodes can't be loop headers anyhow"); - // cf_pre = cf_pre->idom; - CFNodeVariables* pre = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_pre); - - LARRAY(Nodes, exit_param_allocas, exiting_nodes_count); - LARRAY(struct List*, leaking, exiting_nodes_count); - LARRAY(Nodes, exit_fwd_allocas, exiting_nodes_count); - for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; - Nodes exit_param_types = rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); - LARRAY(const Node*, exit_param_allocas_tmp, exit_param_types.count); - for (size_t j = 0; j < exit_param_types.count; j++) - exit_param_allocas_tmp[j] = gen_stack_alloc(outer_bb, get_unqualified_type(exit_param_types.nodes[j])); - exit_param_allocas[i] = nodes(arena, exit_param_types.count, exit_param_allocas_tmp); - - // Search for what's required after the exit but not in scope at the loop header - // this is similar to the LCSSA constraint, but here it's because controls have hard scopes - CFNode* cf_post = cfg_lookup(ctx->fwd_cfg, exiting_node->node); - CFNodeVariables* post = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_post); - leaking[i] = new_list(const Type*); - find_unbound_vars(exiting_node->node, pre->bound_by_dominators_set, post->free_set, leaking[i]); - - size_t leaking_count = entries_count_list(leaking[i]); - LARRAY(const Node*, exit_fwd_allocas_tmp, leaking_count); - for (size_t j = 0; j < leaking_count; j++) - exit_fwd_allocas_tmp[j] = gen_stack_alloc(outer_bb, rewrite_node(rewriter, get_unqualified_type(read_list(const Node*, leaking[i])[j]->type))); - exit_fwd_allocas[i] = nodes(arena, leaking_count, exit_fwd_allocas_tmp); - } - - const Node* exit_destination_alloca = NULL; - if (exiting_nodes_count > 1) - exit_destination_alloca = gen_stack_alloc(outer_bb, int32_type(arena)); - - const Node* join_token_exit = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { - .yield_types = empty(arena) - }), true), "jp_exit"); - - const Node* join_token_continue = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { - .yield_types = inner_yield_types - }), true), "jp_continue"); - - LARRAY(Node*, exit_wrappers, exiting_nodes_count); - LARRAY(Node*, exit_helpers, exiting_nodes_count); - for (size_t i = 0; i < exiting_nodes_count; i++) { - exit_helpers[i] = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_helper_%d", i)); - - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; - assert(exiting_node->node && exiting_node->node->tag != Function_TAG); - Nodes exit_wrapper_params = recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); - - Node* pre_join_exit_bb = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); - set_abstraction_body(pre_join_exit_bb, jump_helper(arena, exit_helpers[i], empty(arena), get_abstraction_mem(pre_join_exit_bb))); - exit_wrappers[i] = pre_join_exit_bb; - } - - Nodes continue_wrapper_params = recreate_params(rewriter, get_abstraction_params(node)); - Node* continue_wrapper = basic_block(arena, continue_wrapper_params, "continue"); - const Node* continue_wrapper_body = join(arena, (Join) { - .join_point = join_token_continue, - .args = continue_wrapper_params, - .mem = get_abstraction_mem(continue_wrapper), - }); - set_abstraction_body(continue_wrapper, continue_wrapper_body); - - // replace the exit nodes by the exit wrappers - LARRAY(const Node*, cached_exits, exiting_nodes_count); - for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; - cached_exits[i] = search_processed(rewriter, exiting_node->node); - if (cached_exits[i]) - remove_dict(const Node*, rewriter->map, exiting_node->node); - register_processed(rewriter, exiting_node->node, exit_wrappers[i]); - } - // ditto for the loop entry and the continue wrapper - const Node* cached_entry = search_processed(rewriter, node); - if (cached_entry) - remove_dict(const Node*, rewriter->map, node); - register_processed(rewriter, node, continue_wrapper); - - // make sure we haven't started rewriting this... - // for (size_t i = 0; i < old_params.count; i++) { - // assert(!search_processed(rewriter, old_params.nodes[i])); - // } - - struct Dict* old_map = rewriter->map; - rewriter->map = clone_dict(rewriter->map); - Nodes inner_loop_params = recreate_params(rewriter, get_abstraction_params(node)); - register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); - Node* inner_control_case = case_(arena, singleton(join_token_continue)); - register_processed(rewriter, get_abstraction_mem(node), get_abstraction_mem(inner_control_case)); - const Node* loop_body = recreate_node_identity(rewriter, get_abstraction_body(node)); - - // save the context - for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; - assert(exiting_node->node && exiting_node->node->tag != Function_TAG); - Nodes exit_wrapper_params = get_abstraction_params(exit_wrappers[i]); - BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_helpers[i])); - - for (size_t j = 0; j < exit_param_allocas[i].count; j++) - gen_store(exit_wrapper_bb, exit_param_allocas[i].nodes[j], exit_wrapper_params.nodes[j]); - if (exiting_nodes_count > 1) - gen_store(exit_wrapper_bb, exit_destination_alloca, int32_literal(arena, i)); - - for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { - gen_store(exit_wrapper_bb, exit_fwd_allocas[i].nodes[j], rewrite_node(rewriter, read_list(const Node*, leaking[i])[j])); - } - - set_abstraction_body(exit_helpers[i], finish_body_with_join(exit_wrapper_bb, join_token_exit, empty(arena))); - } - - set_abstraction_body(inner_control_case, loop_body); - - destroy_dict(rewriter->map); - rewriter->map = old_map; - //register_processed_list(rewriter, get_abstraction_params(node), nparams); - - // restore the old context - for (size_t i = 0; i < exiting_nodes_count; i++) { - remove_dict(const Node*, rewriter->map, read_list(CFNode*, exiting_nodes)[i]->node); - if (cached_exits[i]) - register_processed(rewriter, read_list(CFNode*, exiting_nodes)[i]->node, cached_exits[i]); - } - remove_dict(const Node*, rewriter->map, node); - if (cached_entry) - register_processed(rewriter, node, cached_entry); - - Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); - BodyBuilder* inner_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_outer)); - Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); - - set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); - Node* outer_control_case = case_(arena, singleton(join_token_exit)); - set_abstraction_body(outer_control_case, jump(arena, (Jump) { - .target = loop_outer, - .args = nparams, - .mem = get_abstraction_mem(outer_control_case), - })); - gen_control(outer_bb, empty(arena), outer_control_case); - - LARRAY(const Node*, exit_numbers, exiting_nodes_count); - LARRAY(const Node*, exit_jumps, exiting_nodes_count); - for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; - - Node* exit_bb = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); - BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); - - // recover the context - for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { - const Node* recovered = gen_load(exit_recover_bb, exit_fwd_allocas[i].nodes[j]); - register_processed(rewriter, read_list(const Node*, leaking[i])[j], recovered); - } - - const Node* recreated_exit = rewrite_node(rewriter, exiting_node->node); - - LARRAY(const Node*, recovered_args, exit_param_allocas[i].count); - for (size_t j = 0; j < exit_param_allocas[i].count; j++) - recovered_args[j] = gen_load(exit_recover_bb, exit_param_allocas[i].nodes[j]); - - exit_numbers[i] = int32_literal(arena, i); - set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, nodes(arena, exit_param_allocas[i].count, recovered_args))); - exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena), bb_mem(outer_bb)); - destroy_list(leaking[i]); - } - - const Node* outer_body; - if (exiting_nodes_count == 1) - outer_body = finish_body(outer_bb, exit_jumps[0]); - else { - const Node* loaded_destination = gen_load(outer_bb, exit_destination_alloca); - outer_body = finish_body(outer_bb, br_switch(arena, (Switch) { - .switch_value = loaded_destination, - .default_jump = exit_jumps[0], - .case_values = nodes(arena, exiting_nodes_count, exit_numbers), - .case_jumps = nodes(arena, exiting_nodes_count, exit_jumps), - .mem = bb_mem(outer_bb) - })); - } - set_abstraction_body(loop_container, outer_body); - destroy_list(exiting_nodes); - return loop_container; - } - - destroy_list(exiting_nodes); - } - - return recreate_node_identity(&ctx->rewriter, node); -} - -static const Node* process_node(Context* ctx, const Node* node) { - assert(node); - - Rewriter* r = &ctx->rewriter; - IrArena* a = r->dst_arena; - - Context new_context = *ctx; - - switch (node->tag) { - case Function_TAG: { - ctx = &new_context; - ctx->current_fn = node; - ctx->fwd_cfg = build_cfg(ctx->current_fn, ctx->current_fn, NULL, false); - ctx->rev_cfg = build_cfg(ctx->current_fn, ctx->current_fn, NULL, true); - ctx->current_looptree = build_loop_tree(ctx->fwd_cfg); - ctx->live_vars = compute_cfg_variables_map(ctx->fwd_cfg, CfgVariablesAnalysisFlagDomBoundSet | CfgVariablesAnalysisFlagLiveSet | CfgVariablesAnalysisFlagFreeSet); - - const Node* new = process_abstraction(ctx, node);; - - destroy_cfg(ctx->fwd_cfg); - destroy_cfg(ctx->rev_cfg); - destroy_loop_tree(ctx->current_looptree); - destroy_cfg_variables_map(ctx->live_vars); - return new; - } - case Constant_TAG: { - ctx = &new_context; - ctx->current_fn = NULL; - r = &ctx->rewriter; - break; - } - case BasicBlock_TAG: - if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) - break; - return process_abstraction(ctx, node); - case Branch_TAG: { - Branch payload = node->payload.branch; - if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) - break; - assert(ctx->fwd_cfg); - - CFNode* cfnode = cfg_lookup(ctx->rev_cfg, ctx->current_abstraction); - const Node* idom = NULL; - - LTNode* current_loop = looptree_lookup(ctx->current_looptree, ctx->current_abstraction)->parent; - assert(current_loop); - - if (entries_count_list(current_loop->cf_nodes)) { - bool leaves_loop = false; - CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); - for (size_t i = 0; i < entries_count_list(current_node->succ_edges); i++) { - CFEdge edge = read_list(CFEdge, current_node->succ_edges)[i]; - LTNode* lt_target = looptree_lookup(ctx->current_looptree, edge.dst->node); - - if (lt_target->parent != current_loop) { - leaves_loop = true; - break; - } - } - - if (!leaves_loop) { - const Node* current_loop_head = read_list(CFNode*, current_loop->cf_nodes)[0]->node; - CFG* loop_cfg = build_cfg(ctx->current_fn, current_loop_head, ctx->current_looptree, true); - CFNode* idom_cf = cfg_lookup(loop_cfg, ctx->current_abstraction)->idom; - if (idom_cf) - idom = idom_cf->node; - destroy_cfg(loop_cfg); - } - } else { - idom = cfnode->idom->node; - } - - if (!idom) { - break; - } - - if (cfg_lookup(ctx->fwd_cfg, idom)->idom->node != ctx->current_abstraction) - break; - - assert(is_abstraction(idom) && idom->tag != Function_TAG); - - LTNode* lt_node = looptree_lookup(ctx->current_looptree, ctx->current_abstraction); - LTNode* idom_lt_node = looptree_lookup(ctx->current_looptree, idom); - CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); - - assert(lt_node); - assert(idom_lt_node); - assert(current_node); - - Node* fn = (Node*) find_processed(r, ctx->current_fn); - - //Regular if/then/else case. Control flow joins at the immediate post dominator. - Nodes yield_types; - Nodes exit_args; - - Nodes old_params = get_abstraction_params(idom); - - if (old_params.count == 0) { - yield_types = empty(a); - exit_args = empty(a); - } else { - LARRAY(const Node*, types,old_params.count); - LARRAY(const Node*, inner_args,old_params.count); - - for (size_t j = 0; j < old_params.count; j++) { - //TODO: Is this correct? - assert(old_params.nodes[j]->tag == Param_TAG); - const Node* qualified_type = rewrite_node(r, old_params.nodes[j]->payload.param.type); - //const Node* qualified_type = rewrite_node(rewriter, old_params.nodes[j]->type); - - //This should always contain a qualified type? - //if (contains_qualified_type(types[j])) - types[j] = get_unqualified_type(qualified_type); - - inner_args[j] = param(a, qualified_type, old_params.nodes[j]->payload.param.name); - } - - yield_types = nodes(a, old_params.count, types); - exit_args = nodes(a, old_params.count, inner_args); - } - - const Node* join_token = param(a, qualified_type_helper(join_point_type(a, (JoinPointType) { - .yield_types = yield_types - }), true), "jp_postdom"); - - Node* pre_join = basic_block(a, exit_args, format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); - set_abstraction_body(pre_join, join(a, (Join) { - .join_point = join_token, - .args = exit_args, - .mem = get_abstraction_mem(pre_join), - })); - - const Node* cached = search_processed(r, idom); - if (cached) - remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); - for (size_t i = 0; i < old_params.count; i++) { - assert(!search_processed(r, old_params.nodes[i])); - } - - register_processed(r, idom, pre_join); - - remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); - if (cached) - register_processed(r, idom, cached); - - Node* control_case = case_(a, singleton(join_token)); - const Node* inner_terminator = branch(a, (Branch) { - .mem = get_abstraction_mem(control_case), - .condition = rewrite_node(r, payload.condition), - .true_jump = jump_helper(a, rewrite_node(r, payload.true_jump->payload.jump.target), rewrite_nodes(r, payload.true_jump->payload.jump.args), get_abstraction_mem(control_case)), - .false_jump = jump_helper(a, rewrite_node(r, payload.false_jump->payload.jump.target), rewrite_nodes(r, payload.false_jump->payload.jump.args), get_abstraction_mem(control_case)), - }); - set_abstraction_body(control_case, inner_terminator); - const Node* join_target = rewrite_node(r, idom); - - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); - Nodes results = gen_control(bb, yield_types, control_case); - return finish_body_with_jump(bb, join_target, results); - } - default: break; - } - return recreate_node_identity(r, node); -} - -Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); - - Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), - .config = config, - .current_fn = NULL, - .fwd_cfg = NULL, - .rev_cfg = NULL, - .current_looptree = NULL, - }; - - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); - return dst; -} From 4254c97ce79f80e3f89ad375662542dd24563918 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 19 Aug 2024 12:30:12 +0200 Subject: [PATCH 501/693] made tailcall analysis smarter/lighter --- include/shady/grammar.json | 2 +- src/shady/analysis/callgraph.c | 60 ++++++++++-------------- src/shady/analysis/uses.c | 37 ++++++++++----- src/shady/analysis/uses.h | 3 +- src/shady/passes/cleanup.c | 2 +- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_callf.c | 2 +- src/shady/passes/lower_tailcalls.c | 4 +- src/shady/passes/mark_leaf_functions.c | 2 +- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_inline.c | 2 +- src/shady/print.c | 2 +- src/shady/type.c | 2 +- 13 files changed, 65 insertions(+), 57 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 25a5515ac..97316354c 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -455,7 +455,7 @@ "class": "terminator", "ops": [ { "name": "mem", "class": "mem" }, - { "name": "target", "class": "value" }, + { "name": "callee", "class": "value" }, { "name": "args", "class": "value", "list": true } ] }, diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index 075caa048..ad357e20c 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -1,14 +1,15 @@ #include "callgraph.h" +#include "uses.h" #include "list.h" #include "dict.h" - #include "portability.h" #include "log.h" #include "../visit.h" #include +#include #include KeyHash hash_node(const Node**); @@ -28,7 +29,6 @@ typedef struct { Visitor visitor; CallGraph* graph; CGNode* root; - const Node* abs; } CGVisitor; static const Node* ignore_immediate_fn_addr(const Node* node) { @@ -51,56 +51,38 @@ static void visit_callsite(CGVisitor* visitor, const Node* callee, const Node* i .src_fn = visitor->root, .dst_fn = target, .instr = instr, - .abs = visitor->abs, }; insert_set_get_result(CGEdge, visitor->root->callees, edge); insert_set_get_result(CGEdge, target->callers, edge); } static void search_for_callsites(CGVisitor* visitor, const Node* node) { - assert((visitor->abs && is_abstraction(visitor->abs)) || !visitor->root); + if (is_abstraction(node)) + search_for_callsites(visitor, get_abstraction_body(node)); switch (node->tag) { - case Function_TAG: { - assert(false); - // analyze_fn(visitor->graph, node)->is_address_captured = true; - break; - } - case BasicBlock_TAG: { - const Node* old_abs = visitor->abs; - visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK, node); - visitor->abs = old_abs; - break; - } - case FnAddr_TAG: { - CGNode* callee_node = analyze_fn(visitor->graph, node->payload.fn_addr.fn); - callee_node->is_address_captured = true; - break; - } case Call_TAG: { assert(visitor->root && "calls can only occur in functions"); const Node* callee = node->payload.call.callee; callee = ignore_immediate_fn_addr(callee); if (callee->tag == Function_TAG) visit_callsite(visitor, callee, node); - else { + else visitor->root->calls_indirect = true; - visit_op(&visitor->visitor, NcValue, "callee", callee); - } - visit_ops(&visitor->visitor, NcValue, "args", node->payload.call.args); break; } case TailCall_TAG: { - const Node* callee = node->payload.tail_call.target; + assert(visitor->root && "tail calls can only occur in functions"); + const Node* callee = node->payload.tail_call.callee; callee = ignore_immediate_fn_addr(callee); if (callee->tag == Function_TAG) visit_callsite(visitor, callee, node); else - visit_node(&visitor->visitor, callee); - visit_nodes(&visitor->visitor, node->payload.tail_call.args); + visitor->root->calls_indirect = true; break; } - default: visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK, node); + default: break; } + visit_node_operands(&visitor->visitor, ~NcMem, node); } static CGNode* analyze_fn(CallGraph* graph, const Node* fn) { @@ -121,11 +103,10 @@ static CGNode* analyze_fn(CallGraph* graph, const Node* fn) { }, .graph = graph, .root = new, - .abs = fn, }; - if (fn->payload.fun.body) { - search_for_callsites(&v, fn->payload.fun.body); + if (get_abstraction_body(fn)) { + search_for_callsites(&v, get_abstraction_body(fn)); visit_function_rpo(&v.visitor, fn); } @@ -220,11 +201,22 @@ CallGraph* new_callgraph(Module* mod) { .fn2cgn = new_dict(const Node*, CGNode*, (HashFn) hash_node, (CmpFn) compare_node) }; + const UsesMap* uses = create_module_uses_map(mod, NcType); + Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag == Function_TAG) { - analyze_fn(graph, decl); + CGNode* node = analyze_fn(graph, decl); + + const Use* use = get_first_use(uses, fn_addr_helper(get_module_arena(mod), decl)); + for (;use;use = use->next_use) { + if (use->user->tag == Call_TAG && strcmp(use->operand_name, "callee") == 0) + continue; + if (use->user->tag == TailCall_TAG && strcmp(use->operand_name, "callee") == 0) + continue; + node->is_address_captured = true; + } } else if (decl->tag == GlobalVariable_TAG && decl->payload.global_variable.init) { CGVisitor v = { .visitor = { @@ -232,7 +224,6 @@ CallGraph* new_callgraph(Module* mod) { }, .graph = graph, .root = NULL, - .abs = NULL, }; search_for_callsites(&v, decl->payload.global_variable.init); } else if (decl->tag == Constant_TAG && decl->payload.constant.value) { @@ -242,12 +233,13 @@ CallGraph* new_callgraph(Module* mod) { }, .graph = graph, .root = NULL, - .abs = NULL, }; search_for_callsites(&v, decl->payload.constant.value); } } + destroy_uses_map(uses); + debugv_print("CallGraph: done with CFG build, contains %d nodes\n", entries_count_dict(graph->fn2cgn)); tarjan(graph->fn2cgn); diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index dfbdbbe65..111300708 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -34,6 +34,15 @@ static Use* get_last_use(UsesMap* map, const Node* n) { return use; } +static void uses_visit_node(UsesMapVisitor* v, const Node* n) { + if (!find_key_dict(const Node*, v->seen, n)) { + insert_set_get_result(const Node*, v->seen, n); + UsesMapVisitor nv = *v; + nv.user = n; + visit_node_operands(&nv.v, v->exclude, n); + } +} + static void uses_visit_op(UsesMapVisitor* v, NodeClass class, String op_name, const Node* op) { Use* use = arena_alloc(v->map->a, sizeof(Use)); memset(use, 0, sizeof(Use)); @@ -50,15 +59,10 @@ static void uses_visit_op(UsesMapVisitor* v, NodeClass class, String op_name, co else insert_dict(const Node*, const Use*, v->map->map, op, use); - if (!find_key_dict(const Node*, v->seen, op)) { - insert_set_get_result(const Node*, v->seen, op); - UsesMapVisitor nv = *v; - nv.user = op; - visit_node_operands(&nv.v, v->exclude, op); - } + uses_visit_node(v, op); } -const UsesMap* create_uses_map(const Node* root, NodeClass exclude) { +static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeClass exclude) { UsesMap* uses = calloc(sizeof(UsesMap), 1); *uses = (UsesMap) { .map = new_dict(const Node*, Use*, (HashFn) hash_node, (CmpFn) compare_node), @@ -70,14 +74,25 @@ const UsesMap* create_uses_map(const Node* root, NodeClass exclude) { .map = uses, .exclude = exclude, .seen = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .user = root, }; - insert_set_get_result(const Node*, v.seen, root); - visit_node_operands(&v.v, exclude, root); - destroy_dict(v.seen); + if (root) + uses_visit_node(&v, root); + if (m) { + Nodes nodes = get_module_declarations(m); + for (size_t i = 0; i < nodes.count; i++) + uses_visit_node(&v, nodes.nodes[i]); + } return uses; } +const UsesMap* create_fn_uses_map(const Node* root, NodeClass exclude) { + return create_uses_map_(root, NULL, exclude); +} + +const UsesMap* create_module_uses_map(const Module* m, NodeClass exclude) { + return create_uses_map_(NULL, m, exclude); +} + void destroy_uses_map(const UsesMap* map) { destroy_arena(map->a); destroy_dict(map->map); diff --git a/src/shady/analysis/uses.h b/src/shady/analysis/uses.h index c978431bd..0f74ea28c 100644 --- a/src/shady/analysis/uses.h +++ b/src/shady/analysis/uses.h @@ -9,7 +9,8 @@ typedef struct UsesMap_ UsesMap; -const UsesMap* create_uses_map(const Node* root, NodeClass exclude); +const UsesMap* create_fn_uses_map(const Node* root, NodeClass exclude); +const UsesMap* create_module_uses_map(const Module* m, NodeClass exclude); void destroy_uses_map(const UsesMap*); typedef struct Use_ Use; diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 3dbf4587d..86132793e 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -46,7 +46,7 @@ const Node* process(Context* ctx, const Node* old) { IrArena* a = r->dst_arena; if (old->tag == Function_TAG || old->tag == Constant_TAG) { Context c = *ctx; - c.map = create_uses_map(old, NcType | NcDeclaration); + c.map = create_fn_uses_map(old, NcType | NcDeclaration); const Node* new = recreate_node_identity(&c.rewriter, old); destroy_uses_map(c.map); return new; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index c8cc08a55..4f6646bfb 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -229,7 +229,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Context fn_ctx = *ctx; fn_ctx.cfg = build_fn_cfg(node); - fn_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); + fn_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); fn_ctx.disable_lowering = lookup_annotation(node, "Internal"); ctx = &fn_ctx; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 0f7b165fc..0883204fa 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -134,7 +134,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { // the body of the control is just an immediate tail-call Node* control_case = case_(a, singleton(jp)); const Node* control_body = tail_call(a, (TailCall) { - .target = ncallee, + .callee = ncallee, .args = nargs, .mem = get_abstraction_mem(control_case), }); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index e6fc14f0b..683f15eab 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -101,7 +101,7 @@ static const Node* process(Context* ctx, const Node* old) { case Function_TAG: { Context ctx2 = *ctx; ctx2.cfg = build_fn_cfg(old); - ctx2.uses = create_uses_map(old, (NcDeclaration | NcType)); + ctx2.uses = create_fn_uses_map(old, (NcDeclaration | NcType)); ctx = &ctx2; const Node* entry_point_annotation = lookup_annotation_list(old->payload.fun.annotations, "EntryPoint"); @@ -192,7 +192,7 @@ static const Node* process(Context* ctx, const Node* old) { TailCall payload = old->payload.tail_call; BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, payload.args)); - const Node* target = rewrite_node(&ctx->rewriter, payload.target); + const Node* target = rewrite_node(&ctx->rewriter, payload.callee); target = gen_conversion(bb, uint32_type(a), target); gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), singleton(target)); diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index a66d04366..07a57f8a9 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -103,7 +103,7 @@ static const Node* process(Context* ctx, const Node* node) { CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, node); fn_ctx.is_leaf = is_leaf_fn(ctx, fn_node); fn_ctx.cfg = build_fn_cfg(node); - fn_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); + fn_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); ctx = &fn_ctx; Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index ea0a513b4..45ae347b1 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -191,7 +191,7 @@ static const Node* process(Context* ctx, const Node* old) { case Function_TAG: { Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); Context fun_ctx = *ctx; - fun_ctx.uses = create_uses_map(old, (NcDeclaration | NcType)); + fun_ctx.uses = create_fn_uses_map(old, (NcDeclaration | NcType)); fun_ctx.disable_lowering = lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); if (old->payload.fun.body) set_abstraction_body(fun, rewrite_node(&fun_ctx.rewriter, old->payload.fun.body)); diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index c61f32b86..52c5b0756 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -211,7 +211,7 @@ static const Node* process(Context* ctx, const Node* node) { case TailCall_TAG: { if (!ctx->graph) break; - const Node* ocallee = node->payload.tail_call.target; + const Node* ocallee = node->payload.tail_call.callee; ocallee = ignore_immediate_fn_addr(ocallee); if (ocallee->tag == Function_TAG) { CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); diff --git a/src/shady/print.c b/src/shady/print.c index fddd295b7..158109da1 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -311,7 +311,7 @@ static void print_function(PrinterCtx* ctx, const Node* node) { sub_ctx.bb_growies = calloc(sizeof(size_t), cfg->size); sub_ctx.bb_printers = calloc(sizeof(size_t), cfg->size); if (node->arena->config.check_types && node->arena->config.allow_fold) { - sub_ctx.uses = create_uses_map(node, (NcDeclaration | NcType)); + sub_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); } } ctx = &sub_ctx; diff --git a/src/shady/type.c b/src/shady/type.c index a765db5e7..91a06bac5 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1116,7 +1116,7 @@ const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { const Node* argument = args.nodes[i]; assert(is_value(argument)); } - assert(check_value_call(tail_call.target, get_values_types(arena, tail_call.args)).count == 0); + assert(check_value_call(tail_call.callee, get_values_types(arena, tail_call.args)).count == 0); return noret_type(arena); } From 293c35e401f24ab08bbae29d7df809ca0b04bc0c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 19 Aug 2024 12:30:52 +0200 Subject: [PATCH 502/693] added new free frontier analysis --- src/shady/analysis/CMakeLists.txt | 1 + src/shady/analysis/free_frontier.c | 58 ++++++++++++++++++++++ src/shady/analysis/free_frontier.h | 10 ++++ src/shady/analysis/verify.c | 19 +++---- src/shady/passes/lift_indirect_targets.c | 63 +----------------------- 5 files changed, 80 insertions(+), 71 deletions(-) create mode 100644 src/shady/analysis/free_frontier.c create mode 100644 src/shady/analysis/free_frontier.h diff --git a/src/shady/analysis/CMakeLists.txt b/src/shady/analysis/CMakeLists.txt index a29b92264..2ce91fd17 100644 --- a/src/shady/analysis/CMakeLists.txt +++ b/src/shady/analysis/CMakeLists.txt @@ -2,6 +2,7 @@ target_sources(shady PRIVATE cfg.c cfg_dump.c free_variables.c + free_frontier.c verify.c callgraph.c uses.c diff --git a/src/shady/analysis/free_frontier.c b/src/shady/analysis/free_frontier.c new file mode 100644 index 000000000..73d37ece4 --- /dev/null +++ b/src/shady/analysis/free_frontier.c @@ -0,0 +1,58 @@ +#include "free_frontier.h" + +#include "visit.h" +#include "dict.h" + +typedef struct { + Visitor v; + Scheduler* scheduler; + CFG* cfg; + CFNode* start; + struct Dict* seen; + struct Dict* frontier; +} FreeFrontierVisitor; + +/// Whether 'a' is dominated by 'b' +static bool is_dominated(CFNode* a, CFNode* b) { + while (a) { + if (a == b) + return true; + a = a->idom; + } + return false; +} + +static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { + if (find_key_dict(const Node*, v->seen, node)) + return; + insert_set_get_result(const Node*, v->seen, node); + CFNode* where = schedule_instruction(v->scheduler, node); + if (where) { + FreeFrontierVisitor vv = *v; + if (is_dominated(where, v->start)) { + visit_node_operands(&vv.v, NcAbstraction | NcDeclaration | NcType, node); + } else { + insert_set_get_result(const Node*, v->frontier, node); + } + } +} + +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + +struct Dict* free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs) { + FreeFrontierVisitor ffv = { + .v = { + .visit_node_fn = (VisitNodeFn) visit_free_frontier, + }, + .scheduler = scheduler, + .cfg = cfg, + .start = cfg_lookup(cfg, abs), + .frontier = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .seen = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + }; + if (get_abstraction_body(abs)) + visit_free_frontier(&ffv, get_abstraction_body(abs)); + destroy_dict(ffv.seen); + return ffv.frontier; +} \ No newline at end of file diff --git a/src/shady/analysis/free_frontier.h b/src/shady/analysis/free_frontier.h new file mode 100644 index 000000000..3629667b0 --- /dev/null +++ b/src/shady/analysis/free_frontier.h @@ -0,0 +1,10 @@ +#ifndef SHADY_FREE_FRONTIER_H +#define SHADY_FREE_FRONTIER_H + +#include "shady/ir.h" +#include "cfg.h" +#include "scheduler.h" + +struct Dict* free_frontier(Scheduler* scheduler, CFG*, const Node* abs); + +#endif diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 4fd506085..795afe3c6 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -1,15 +1,15 @@ #include "verify.h" -#include "free_variables.h" +#include "free_frontier.h" #include "cfg.h" + #include "log.h" +#include "dict.h" +#include "list.h" #include "../visit.h" #include "../ir_private.h" #include "../type.h" -#include "dict.h" -#include "list.h" - #include typedef struct { @@ -46,16 +46,16 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { struct List* cfgs = build_cfgs(mod); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; - struct Dict* map = compute_cfg_variables_map(cfg, CfgVariablesAnalysisFlagFreeSet); - CFNodeVariables* entry_vars = *find_value_dict(CFNode*, CFNodeVariables*, map, cfg->entry); - if (entries_count_dict(entry_vars->free_set) > 0) { + Scheduler* scheduler = new_scheduler(cfg); + struct Dict* set = free_frontier(scheduler, cfg, cfg->entry->node); + if (entries_count_dict(set) > 0) { log_string(ERROR, "Leaking variables in "); log_node(ERROR, cfg->entry->node); log_string(ERROR, ":\n"); size_t j = 0; const Node* leaking; - while (dict_iter(entry_vars->free_set, &j, &leaking, NULL)) { + while (dict_iter(set, &j, &leaking, NULL)) { log_node(ERROR, leaking); error_print("\n"); } @@ -64,7 +64,8 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { log_module(ERROR, config, mod); error_die(); } - destroy_cfg_variables_map(map); + destroy_dict(set); + destroy_scheduler(scheduler); destroy_cfg(cfg); } destroy_list(cfgs); diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 4f6646bfb..548255e47 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -11,6 +11,7 @@ #include "../analysis/leak.h" #include "../analysis/verify.h" #include "../analysis/scheduler.h" +#include "../analysis/free_frontier.h" #include "log.h" #include "portability.h" @@ -58,68 +59,6 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, Nodes sp return gen_get_stack_size(builder); } -typedef struct { - Visitor v; - Scheduler* scheduler; - CFG* cfg; - CFNode* start; - struct Dict* frontier; -} FreeFrontierVisitor; - -/// Whether 'a' is dominated by 'b' -static bool is_dominated(CFNode* a, CFNode* b) { - while (a) { - if (a == b) - return true; - a = a->idom; - } - return false; -} - -static struct Dict* free_frontier(Scheduler* scheduler, CFG*, const Node* abs); - -static void copy_node_set(struct Dict* dst, struct Dict* src) { - size_t i = 0, j = 0; - const Node* key; - while (dict_iter(src, &i, &key, NULL)) { - insert_set_get_result(const Node*, dst, key); - } -} - -static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { - CFNode* where = schedule_instruction(v->scheduler, node); - if (where) { - /*if (is_abstraction(node)) { - if (is_dominated(where, v->start)) { - struct Dict* frontier = free_frontier(v->scheduler, v->cfg, node); - copy_node_set(v->frontier, frontier); - destroy_dict(frontier); - } - } else*/ { - FreeFrontierVisitor vv = *v; - if (is_dominated(where, v->start)) { - visit_node_operands(&vv.v, NcAbstraction | NcDeclaration | NcType, node); - } else { - insert_set_get_result(const Node*, v->frontier, node); - } - } - } -} - -static struct Dict* free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs) { - FreeFrontierVisitor ffv = { - .v = { - .visit_node_fn = (VisitNodeFn) visit_free_frontier, - }, - .scheduler = scheduler, - .cfg = cfg, - .start = cfg_lookup(cfg, abs), - .frontier = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - }; - visit_free_frontier(&ffv, get_abstraction_body(abs)); - return ffv.frontier; -} - static Nodes set2nodes(IrArena* a, struct Dict* set) { size_t count = entries_count_dict(set); LARRAY(const Node*, tmp, count); From 4a56ea83bd65ef84b1570c2c5371b776e2843185 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 19 Aug 2024 12:31:36 +0200 Subject: [PATCH 503/693] removed old free_variables analysis --- src/shady/analysis/CMakeLists.txt | 1 - src/shady/analysis/free_variables.c | 225 ---------------------------- src/shady/analysis/free_variables.h | 28 ---- 3 files changed, 254 deletions(-) delete mode 100644 src/shady/analysis/free_variables.c delete mode 100644 src/shady/analysis/free_variables.h diff --git a/src/shady/analysis/CMakeLists.txt b/src/shady/analysis/CMakeLists.txt index 2ce91fd17..a92e52075 100644 --- a/src/shady/analysis/CMakeLists.txt +++ b/src/shady/analysis/CMakeLists.txt @@ -1,7 +1,6 @@ target_sources(shady PRIVATE cfg.c cfg_dump.c - free_variables.c free_frontier.c verify.c callgraph.c diff --git a/src/shady/analysis/free_variables.c b/src/shady/analysis/free_variables.c deleted file mode 100644 index 63fa590dd..000000000 --- a/src/shady/analysis/free_variables.c +++ /dev/null @@ -1,225 +0,0 @@ -#include "free_variables.h" - -#include "log.h" -#include "../visit.h" - -#include "../analysis/cfg.h" - -#include "list.h" -#include "dict.h" - -#include -#include - -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); - -typedef struct { - Visitor visitor; - struct Dict* map; - CFNodeVariables* current_scope; - struct Dict* bound; - struct Dict* live; - CfgVariablesAnalysisFlags flags; -} Context; - -static void copy_set(struct Dict* dst, struct Dict* src) { - size_t j = 0; - const Node* item; - while (dict_iter(src, &j, &item, NULL)) { - insert_set_get_result(const Node*, dst, item); - } -} - -void dump_set(struct Dict* set) { - bool prev = false; - size_t i = 0; - const Node* bound_var; - while (dict_iter(set, &i, &bound_var, NULL)) { - if (prev) { - debugvv_print(", "); - } - log_node(DEBUGVV, bound_var); - prev = true; - } -} - -static void dump_free_variables(Context* ctx, CFNode* cfnode, int depth) { - const Node* abs = cfnode->node; - String abs_name = get_abstraction_name_unsafe(abs); - for (int i = 0; i < depth; i++) - debugvv_print(" "); - if (abs_name) - debugvv_print("%s: ", abs_name); - else - debugvv_print("%%%d: ", abs->id); - debugvv_print("."); - - if (true) { - if(ctx->current_scope->free_set) { - debugvv_print(" Free: ["); - dump_set(ctx->current_scope->free_set); - debugvv_print("]"); - } - if(ctx->current_scope->bound_by_dominators_set) { - debugvv_print(" BoundDom: ["); - dump_set(ctx->current_scope->bound_by_dominators_set); - debugvv_print("]"); - } - if(ctx->bound) { - debugvv_print(" Bound: ["); - dump_set(ctx->bound); - debugvv_print("]"); - } - //if(ctx->live) { - // debugvv_print(" Live: ["); - // dump_set(ctx->live); - // debugvv_print("]"); - //} - } - - debugvv_print("\n"); -} - -static void search_op_for_free_variables(Context* visitor, NodeClass class, String op_name, const Node* node) { - assert(node); - switch (node->tag) { - case Function_TAG: - case BasicBlock_TAG: assert(false); - default: break; - } - if (node->tag == Param_TAG) - insert_set_get_result(const Node*, visitor->live, node); - visit_node_operands(&visitor->visitor, IGNORE_ABSTRACTIONS_MASK, node); -} - -static CFNodeVariables* create_node_variables(CFNode* cfnode) { - CFNodeVariables* v = calloc(sizeof(CFNodeVariables), 1); - *v = (CFNodeVariables) { - .node = cfnode, - }; - return v; -} - -static Context visit_domtree(Context* parent_context, CFNode* cfnode, int depth) { - Context context = *parent_context; - - context.current_scope = create_node_variables(cfnode); - //if (depth > 0) - // context.bound = clone_dict(parent_context->bound); - //else - context.bound = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - context.live = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - - insert_dict(CFNode*, CFNodeVariables*, context.map, cfnode, context.current_scope); - if (context.flags & CfgVariablesAnalysisFlagDomBoundSet) { - if (depth == 0) - context.current_scope->bound_by_dominators_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - else - context.current_scope->bound_by_dominators_set = clone_dict(parent_context->bound); - } - if (context.flags & CfgVariablesAnalysisFlagFreeSet) - context.current_scope->free_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node); - const Node* abs = cfnode->node; - - // Bind parameters - Nodes params = get_abstraction_params(abs); - for (size_t j = 0; j < params.count; j++) { - const Node* param = params.nodes[j]; - bool r = insert_set_get_result(const Node*, context.bound, param); - assert(r); - } - - const Node* body = get_abstraction_body(abs); - if (body) - visit_op(&context.visitor, NcTerminator, "body", body); - - if (context.flags & CfgVariablesAnalysisFlagFreeSet) { - size_t j = 0; - const Node* pfv; - while (dict_iter(context.live, &j, &pfv, NULL)) { - const Node** found = find_key_dict(const Node*, context.bound, pfv); - if (found) - continue; - insert_set_get_result(const Node*, context.current_scope->free_set, pfv); - } - } - - struct Dict* stuff_bound_here = NULL; - // if we want to compute free variables, we need to keep arround a copy of what's bound in this abstraction - // and check the free variables against that rather than the transitively bound set we're computing right after - if (context.flags & CfgVariablesAnalysisFlagFreeSet) - stuff_bound_here = clone_dict(context.bound); - - if (depth > 0) - copy_set(context.bound, parent_context->bound); - - for (size_t i = 0; i < entries_count_list(cfnode->dominates); i++) { - CFNode* child = read_list(CFNode*, cfnode->dominates)[i]; - Context child_context = visit_domtree(&context, child, depth + 1); - // what's live in children is live to us, too - copy_set(context.live, child_context.live); - destroy_dict(child_context.bound); - destroy_dict(child_context.live); - - if (context.flags & CfgVariablesAnalysisFlagFreeSet) { - size_t j = 0; - const Node* pfv; - while (dict_iter(child_context.current_scope->free_set, &j, &pfv, NULL)) { - const Node** found = find_key_dict(const Node*, stuff_bound_here, pfv); - if (found) - continue; - insert_set_get_result(const Node*, context.current_scope->free_set, pfv); - } - } - } - - if (stuff_bound_here) - destroy_dict(stuff_bound_here); - - if (context.flags & CfgVariablesAnalysisFlagBoundSet) - context.current_scope->bound_set = clone_dict(context.bound); - if (context.flags & CfgVariablesAnalysisFlagLiveSet) - context.current_scope->live_set = clone_dict(context.live); - - //dump_free_variables(&context, cfnode, depth); - - return context; -} - -struct Dict* compute_cfg_variables_map(const CFG* cfg, CfgVariablesAnalysisFlags flags) { - Context root_context = { - .visitor = { - .visit_op_fn = (VisitOpFn) search_op_for_free_variables, - }, - .map = new_dict(CFNode*, CFNodeVariables*, (HashFn) hash_ptr, (CmpFn) compare_ptrs), - .flags = flags, - }; - - // debugv_print("Computing free variables for function '%s' ...\n", get_abstraction_name(cfg->entry->node)); - root_context = visit_domtree(&root_context, cfg->entry, 0); - destroy_dict(root_context.bound); - destroy_dict(root_context.live); - return root_context.map; -} - -static void destroy_variables_node(CFNodeVariables* value) { - if (value->bound_by_dominators_set) - destroy_dict(value->bound_by_dominators_set); - if (value->bound_set) - destroy_dict(value->bound_set); - if (value->live_set) - destroy_dict(value->live_set); - if (value->free_set) - destroy_dict(value->free_set); - free((void*) value); -} - -void destroy_cfg_variables_map(struct Dict* map) { - size_t i = 0; - CFNodeVariables* value; - while (dict_iter(map, &i, NULL, &value)) { - destroy_variables_node(value); - } - destroy_dict(map); -} diff --git a/src/shady/analysis/free_variables.h b/src/shady/analysis/free_variables.h deleted file mode 100644 index 9e4e51d17..000000000 --- a/src/shady/analysis/free_variables.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SHADY_FREE_VARIABLES_H -#define SHADY_FREE_VARIABLES_H - -#include "shady/ir.h" - -typedef struct CFG_ CFG; -typedef struct CFNode_ CFNode; - -typedef struct { - CFNode* node; - struct Dict* bound_by_dominators_set; - struct Dict* bound_set; - struct Dict* free_set; - struct Dict* live_set; -} CFNodeVariables; - -typedef enum { - CfgVariablesAnalysisFlagNone = 0, - CfgVariablesAnalysisFlagFreeSet = 0x1, - CfgVariablesAnalysisFlagBoundSet = 0x2, - CfgVariablesAnalysisFlagDomBoundSet = 0x4, - CfgVariablesAnalysisFlagLiveSet = 0x8 -} CfgVariablesAnalysisFlags; - -struct Dict* compute_cfg_variables_map(const CFG* cfg, CfgVariablesAnalysisFlags flags); -void destroy_cfg_variables_map(struct Dict*); - -#endif From 1b97c1104eea7402d7542c60ce9734303f3a22f8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 19 Aug 2024 14:38:26 +0200 Subject: [PATCH 504/693] rewriter: only import Exported decls --- samples/fib.slim | 2 +- src/runtime/runtime_test.c | 2 +- src/shady/internal/scheduler.slim | 32 ++++++++++++------------ src/shady/rewrite.c | 2 +- src/shady/transform/internal_constants.c | 3 ++- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/samples/fib.slim b/samples/fib.slim index ed843cf45..ff21bab31 100644 --- a/samples/fib.slim +++ b/samples/fib.slim @@ -10,7 +10,7 @@ var input u32 subgroup_local_id; @Builtin("SubgroupId") var uniform input u32 subgroup_id; -@EntryPoint("Compute") @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn main() { +@EntryPoint("Compute") @Exported @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn main() { val n = subgroup_local_id % u32 16; debug_printf("fib(%d) = %d from thread %d:%d\n", n, fib(n), subgroup_id, subgroup_local_id); return (); diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 447cc944d..e7eba062d 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -22,7 +22,7 @@ typedef struct { } Args; static const char* default_shader = -"@EntryPoint(\"Compute\") @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn my_kernel(uniform i32 a, uniform ptr global i32 b) {\n" +"@EntryPoint(\"Compute\") @Exported @WorkgroupSize(SUBGROUP_SIZE, 1, 1) fn my_kernel(uniform i32 a, uniform ptr global i32 b) {\n" " val rb = reinterpret[u64](b);\n" " debug_printf(\"hi %d 0x%lx\\n\", a, rb);\n" " return ();\n" diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index 54b46f499..e05d8f083 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -28,17 +28,17 @@ @Internal @Builtin("SubgroupLocalInvocationId") var input u32 subgroup_local_id; -@Internal @Leaf +@Internal fn subgroup_active_mask uniform mask_t() { return (ext_instr["spirv.core", 339, uniform mask_t](3, true)); } -@Internal @Leaf +@Internal fn subgroup_ballot uniform mask_t(varying bool b) { return (ext_instr["spirv.core", 339, uniform mask_t](3, b)); } -@Internal @Leaf +@Internal @Exported fn builtin_init_scheduler() { val init_mask = subgroup_active_mask(); @@ -49,7 +49,7 @@ fn builtin_init_scheduler() { actual_subgroup_size = (ext_instr["spirv.core", 349, varying u32](3, u32 1, 0)); } -@Internal @Leaf +@Internal @Exported fn builtin_entry_join_point uniform JoinPoint() { val init_mask = subgroup_active_mask(); @@ -58,7 +58,7 @@ fn builtin_entry_join_point uniform JoinPoint() { return (jp); } -@Internal @Leaf +@Internal @Exported fn builtin_create_control_point varying JoinPoint(uniform u32 join_destination, varying u32 payload) { val curr_mask = subgroup_active_mask(); val depth = ext_instr["spirv.core", 338, uniform u32](3, scheduler_vector#(subgroup_local_id)#1); @@ -71,7 +71,7 @@ fn builtin_create_control_point varying JoinPoint(uniform u32 join_destination, return (jp); } -@Internal @Leaf +@Internal @Exported fn builtin_fork(varying u32 branch_destination) { val first_branch = ext_instr["spirv.core", 338, uniform u32](3, branch_destination); @@ -106,7 +106,7 @@ fn builtin_fork(varying u32 branch_destination) { } } -@Internal @Leaf +@Internal @Exported fn builtin_yield(uniform u32 resume_target) { resume_at#(subgroup_local_id) = resume_target; // resume_with#(subgroup_local_id) = subgroup_active_mask(); @@ -116,22 +116,22 @@ fn builtin_yield(uniform u32 resume_target) { // bump the cursor // TODO bump it in a smarter way scheduler_cursor = (scheduler_cursor + u32 1) % actual_subgroup_size; - builtin_find_schedulable_leaf(); + builtin_find_schedulable_Exported(); } } -@Internal @Leaf +@Internal @Exported fn builtin_join(varying u32 join_at, varying TreeNode token) { resume_at#(subgroup_local_id) = join_at; scheduler_vector#(subgroup_local_id) = token; // only one thread runs that part if (ext_instr["spirv.core", 333, varying bool](3)) { - builtin_find_schedulable_leaf(); + builtin_find_schedulable_Exported(); } } -@Internal @Leaf +@Internal @Exported fn is_parent bool(varying TreeNode child, varying TreeNode maybe_parent) { val child_mask = child#0; val parent_mask = maybe_parent#0; @@ -141,14 +141,14 @@ fn is_parent bool(varying TreeNode child, varying TreeNode maybe_parent) { return (child_depth >= parent_depth); } -@Internal @Leaf +@Internal @Exported fn forward_distance u32(varying u32 x, varying u32 dst, varying u32 max_mod) { var u32 t = dst - x; t = t % max_mod; return (t); } -@Internal @Leaf +@Internal @Exported fn reduce2 u32(varying u32 a_index, varying u32 b_index) { val a = scheduler_vector#a_index; val b = scheduler_vector#b_index; @@ -163,8 +163,8 @@ fn reduce2 u32(varying u32 a_index, varying u32 b_index) { return (b_index); } -@Internal @Leaf -fn builtin_find_schedulable_leaf() { +@Internal @Exported +fn builtin_find_schedulable_Exported() { var u32 reduced = u32 0; loop (varying u32 i = u32 1) { if (i >= actual_subgroup_size) { break; } @@ -177,7 +177,7 @@ fn builtin_find_schedulable_leaf() { return (); } -@Internal @Leaf +@Internal @Exported fn builtin_get_active_branch mask_t() { val this_thread_branch = scheduler_vector#(subgroup_local_id); val same_dest = resume_at#(subgroup_local_id) == next_fn; diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index ac76890f7..0e316ea9c 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -230,7 +230,7 @@ void rewrite_module(Rewriter* rewriter) { assert(rewriter->dst_module != rewriter->src_module); Nodes old_decls = get_module_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { - if (old_decls.nodes[i]->tag == NominalType_TAG) continue; + if (!lookup_annotation(old_decls.nodes[i], "Exported")) continue; rewrite_op_helper(rewriter, NcDeclaration, "decl", old_decls.nodes[i]); } } diff --git a/src/shady/transform/internal_constants.c b/src/shady/transform/internal_constants.c index 6823f30f4..67cf592de 100644 --- a/src/shady/transform/internal_constants.c +++ b/src/shady/transform/internal_constants.c @@ -7,8 +7,9 @@ void generate_dummy_constants(SHADY_UNUSED const CompilerConfig* config, Module* mod) { IrArena* arena = get_module_arena(mod); + Nodes annotations = mk_nodes(arena, annotation(arena, (Annotation) { .name = "RetainAfterSpecialization" }), annotation(arena, (Annotation) { .name = "Exported" })); #define X(constant_name, T, placeholder) \ - Node* constant_name##_var = constant(mod, singleton(annotation(arena, (Annotation) { .name = "RetainAfterSpecialization" })), T, #constant_name); \ + Node* constant_name##_var = constant(mod, annotations, T, #constant_name); \ constant_name##_var->payload.constant.value = placeholder; INTERNAL_CONSTANTS(X) #undef X From 219aecb33a0b7769fc2468a154324af680c0f922 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 19 Aug 2024 17:22:45 +0200 Subject: [PATCH 505/693] everything mostly works :tm: --- samples/hello_world.slim | 2 +- src/backend/spirv/spirv_lift_globals_ssbo.c | 22 ++++++++++--------- src/frontend/llvm/l2s_postprocess.c | 6 +++--- src/shady/body_builder.c | 2 +- src/shady/config.c | 8 +++++++ src/shady/internal/scheduler.slim | 17 +++++++++------ src/shady/node.c | 2 +- src/shady/passes/lift_indirect_targets.c | 4 ++-- src/shady/passes/lower_alloca.c | 3 ++- src/shady/passes/lower_generic_ptrs.c | 2 +- src/shady/passes/lower_memcpy.c | 24 ++++++++++----------- src/shady/passes/lower_physical_ptrs.c | 2 +- src/shady/passes/lower_subgroup_vars.c | 22 ++++++++++--------- src/shady/passes/lower_tailcalls.c | 20 ++++++++--------- src/shady/passes/opt_restructure.c | 2 +- src/shady/transform/ir_gen_helpers.c | 12 +++++------ 16 files changed, 83 insertions(+), 67 deletions(-) diff --git a/samples/hello_world.slim b/samples/hello_world.slim index 0d71ddfed..952ed3a39 100644 --- a/samples/hello_world.slim +++ b/samples/hello_world.slim @@ -1,4 +1,4 @@ -@EntryPoint("Compute") @WorkgroupSize(64, 1, 1) fn main() { +@Exported @EntryPoint("Compute") @WorkgroupSize(64, 1, 1) fn main() { debug_printf("Hello World\n"); return (); } diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index fc5d5f878..40f9c1c81 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -22,16 +22,18 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Function_TAG: { Node* newfun = recreate_decl_header_identity(r, node); - Context functx = *ctx; - functx.rewriter.map = clone_dict(functx.rewriter.map); - clear_dict(functx.rewriter.map); - register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); - functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); - Node* post_prelude = basic_block(a, empty(a), "post-prelude"); - register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); - set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); - set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); - destroy_dict(functx.rewriter.map); + if (get_abstraction_body(node)) { + Context functx = *ctx; + functx.rewriter.map = clone_dict(functx.rewriter.map); + clear_dict(functx.rewriter.map); + register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); + functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); + Node* post_prelude = basic_block(a, empty(a), "post-prelude"); + register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); + set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); + set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); + destroy_dict(functx.rewriter.map); + } return newfun; } case RefDecl_TAG: { diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index c7edda8ca..32c50a126 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -98,8 +98,8 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, case Constant_TAG: { Node* new = (Node*) recreate_node_identity(r, node); BodyBuilder* bb = begin_block_pure(a); - const Node* value = first(bind_instruction(bb, new->payload.constant.value)); - value = first(bind_instruction(bb, prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)))); + const Node* value = new->payload.constant.value; + value = prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)); new->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(value)); return new; } @@ -150,7 +150,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, .mem = get_abstraction_mem(decl), })); } else - wrap_in_controls(ctx, &controls, decl, node); + wrap_in_controls(&fn_ctx, &controls, decl, node); destroy_cfg(fn_ctx.cfg); return decl; } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 5ffac7638..7be6d810a 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -64,7 +64,7 @@ Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { if (bb->arena->config.check_types) { - assert(is_instruction(instruction) || is_value(instruction)); + assert(is_mem(instruction)); } if (is_mem(instruction) && /* avoid things like ExtInstr with null mem input! */ get_parent_mem(instruction)) bb->mem = instruction; diff --git a/src/shady/config.c b/src/shady/config.c index bb971fbd5..a094bb5c1 100644 --- a/src/shady/config.c +++ b/src/shady/config.c @@ -33,6 +33,14 @@ CompilerConfig default_compiler_config() { } }, + /*.shader_diagnostics = { + .max_top_iterations = 10, + }, + + .printf_trace = { + .god_function = true, + },*/ + .target = default_target_config(), .specialization = { diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index e05d8f083..8742a5a68 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -28,6 +28,9 @@ @Internal @Builtin("SubgroupLocalInvocationId") var input u32 subgroup_local_id; +@Internal @Builtin("SubgroupId") +var uniform input u32 subgroup_id; + @Internal fn subgroup_active_mask uniform mask_t() { return (ext_instr["spirv.core", 339, uniform mask_t](3, true)); @@ -116,7 +119,7 @@ fn builtin_yield(uniform u32 resume_target) { // bump the cursor // TODO bump it in a smarter way scheduler_cursor = (scheduler_cursor + u32 1) % actual_subgroup_size; - builtin_find_schedulable_Exported(); + builtin_find_schedulable_leaf(); } } @@ -127,11 +130,11 @@ fn builtin_join(varying u32 join_at, varying TreeNode token) { // only one thread runs that part if (ext_instr["spirv.core", 333, varying bool](3)) { - builtin_find_schedulable_Exported(); + builtin_find_schedulable_leaf(); } } -@Internal @Exported +@Internal fn is_parent bool(varying TreeNode child, varying TreeNode maybe_parent) { val child_mask = child#0; val parent_mask = maybe_parent#0; @@ -141,14 +144,14 @@ fn is_parent bool(varying TreeNode child, varying TreeNode maybe_parent) { return (child_depth >= parent_depth); } -@Internal @Exported +@Internal fn forward_distance u32(varying u32 x, varying u32 dst, varying u32 max_mod) { var u32 t = dst - x; t = t % max_mod; return (t); } -@Internal @Exported +@Internal fn reduce2 u32(varying u32 a_index, varying u32 b_index) { val a = scheduler_vector#a_index; val b = scheduler_vector#b_index; @@ -163,8 +166,8 @@ fn reduce2 u32(varying u32 a_index, varying u32 b_index) { return (b_index); } -@Internal @Exported -fn builtin_find_schedulable_Exported() { +@Internal +fn builtin_find_schedulable_leaf() { var u32 reduced = u32 0; loop (varying u32 i = u32 1) { if (i >= actual_subgroup_size) { break; } diff --git a/src/shady/node.c b/src/shady/node.c index 64a066b43..b88619760 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -319,8 +319,8 @@ void set_abstraction_body(Node* abs, const Node* body) { body = jump_helper(a, insert->block_entry_block, empty(a), mem); continue; } - assert(mem_abs == abs); } + assert(mem_abs == abs); break; } } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 548255e47..6e6f4b409 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -119,7 +119,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { const Node* payload = param(a, qualified_type_helper(uint32_type(a), false), "sp"); // Keep annotations the same - Nodes annotations = nodes(a, 0, NULL); + Nodes annotations = singleton(annotation(a, (Annotation) { .name = "Exported" })); new_params = prepend_nodes(a, new_params, payload); Node* new_fn = function(ctx->rewriter.dst_module, new_params, name, annotations, nodes(a, 0, NULL)); lifted_cont->lifted_fn = new_fn; @@ -139,7 +139,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { // set_value_name(recovered_value, param_name); if (is_qualified_type_uniform(ovar->type)) - recovered_value = bind_instruction_single(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) })); + recovered_value = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }); register_processed(r, ovar, recovered_value); } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 6bc231e17..3e196b749 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -150,7 +150,8 @@ static const Node* process(Context* ctx, const Node* node) { //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); const Node* lea_instr = lea(a, (Lea) { .ptr = ctx->base_stack_addr_on_entry, .offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)), .indices = empty(a) }); - const Node* slot = first(bind_instruction_named(bb, lea_instr, (String []) { format_string_arena(a->arena, "stack_slot_%d", found_slot->i) })); + //const Node* slot = first(bind_instruction_named(bb, lea_instr, (String []) { format_string_arena(a->arena, "stack_slot_%d", found_slot->i) })); + const Node* slot = lea_instr; const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = gen_reinterpret_cast(bb, ptr_t, slot); //bool last = found_slot->i == ctx->num_slots - 1; diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 30bd91dc6..a6e6b7690 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -149,7 +149,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, empty(a)); - set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(new_fn) })); + set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, (const Node**) cases), default_case); set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) }))); break; diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 42b78d933..ec871321b 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -28,15 +28,15 @@ static const Node* process(Context* ctx, const Node* old) { CopyBytes payload = old->payload.copy_bytes; const Type* word_type = int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); const Node* dst_addr = rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; deconstruct_qualified_type(&dst_addr_type); assert(dst_addr_type->tag == PtrType_TAG); dst_addr_type = ptr_type(a, (PtrType) { - .address_space = dst_addr_type->payload.ptr_type.address_space, - .pointed_type = word_type, + .address_space = dst_addr_type->payload.ptr_type.address_space, + .pointed_type = word_type, }); dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); @@ -45,8 +45,8 @@ static const Node* process(Context* ctx, const Node* old) { deconstruct_qualified_type(&src_addr_type); assert(src_addr_type->tag == PtrType_TAG); src_addr_type = ptr_type(a, (PtrType) { - .address_space = src_addr_type->payload.ptr_type.address_space, - .pointed_type = word_type, + .address_space = src_addr_type->payload.ptr_type.address_space, + .pointed_type = word_type, }); src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); @@ -60,9 +60,9 @@ static const Node* process(Context* ctx, const Node* old) { gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); + set_abstraction_body(true_case, merge_continue(a, (MergeContinue) { .mem = get_abstraction_mem(true_case), .args = singleton(next_index) })); Node* false_case = case_(a, empty(a)); - set_abstraction_body(false_case, merge_break(a, (MergeBreak) {.args = empty(a)})); + set_abstraction_body(false_case, merge_break(a, (MergeBreak) { .mem = get_abstraction_mem(false_case), .args = empty(a) })); gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), true_case, false_case); set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a, (Unreachable) { .mem = bb_mem(loop_bb) }))); gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), loop_case); @@ -76,15 +76,15 @@ static const Node* process(Context* ctx, const Node* old) { assert(src_type->tag == Int_TAG); const Type* word_type = src_type;// int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); const Node* dst_addr = rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; deconstruct_qualified_type(&dst_addr_type); assert(dst_addr_type->tag == PtrType_TAG); dst_addr_type = ptr_type(a, (PtrType) { - .address_space = dst_addr_type->payload.ptr_type.address_space, - .pointed_type = word_type, + .address_space = dst_addr_type->payload.ptr_type.address_space, + .pointed_type = word_type, }); dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); @@ -97,9 +97,9 @@ static const Node* process(Context* ctx, const Node* old) { gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, merge_continue(a, (MergeContinue) {.args = singleton(next_index)})); + set_abstraction_body(true_case, merge_continue(a, (MergeContinue) { .mem = get_abstraction_mem(true_case), .args = singleton(next_index) })); Node* false_case = case_(a, empty(a)); - set_abstraction_body(false_case, merge_break(a, (MergeBreak) {.args = empty(a)})); + set_abstraction_body(false_case, merge_break(a, (MergeBreak) { .mem = get_abstraction_mem(false_case), .args = empty(a) })); gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), true_case, false_case); set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a, (Unreachable) { .mem = bb_mem(loop_bb) }))); gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), loop_case); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 8eb2c8b8c..86a932f0b 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -212,7 +212,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element case RecordType_TAG: { Nodes member_types = element_type->payload.record_type.members; for (size_t i = 0; i < member_types.count; i++) { - const Node* extracted_value = first(bind_instruction(bb, prim_op(a, (PrimOp) { .op = extract_op, .operands = mk_nodes(a, value, int32_literal(a, i)), .type_arguments = empty(a) }))); + const Node* extracted_value = prim_op(a, (PrimOp) { .op = extract_op, .operands = mk_nodes(a, value, int32_literal(a, i)), .type_arguments = empty(a) }); const Node* field_offset = gen_primop_e(bb, offset_of_op, singleton(element_type), singleton(size_t_literal(a, i))); field_offset = bytes_to_words(bb, field_offset); const Node* adjusted_offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, base_offset, field_offset)); diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index bd358fb43..3ebd8b8a7 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -20,16 +20,18 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Function_TAG: { Node* newfun = recreate_decl_header_identity(r, node); - Context functx = *ctx; - functx.rewriter.map = clone_dict(functx.rewriter.map); - clear_dict(functx.rewriter.map); - register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); - functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); - Node* post_prelude = basic_block(a, empty(a), "post-prelude"); - register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); - set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); - set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); - destroy_dict(functx.rewriter.map); + if (get_abstraction_body(node)) { + Context functx = *ctx; + functx.rewriter.map = clone_dict(functx.rewriter.map); + clear_dict(functx.rewriter.map); + register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); + functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); + Node* post_prelude = basic_block(a, empty(a), "post-prelude"); + register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); + set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); + set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); + destroy_dict(functx.rewriter.map); + } return newfun; } case PtrType_TAG: { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 683f15eab..3e8bdc83a 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -336,22 +336,22 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* fn_lit = lower_fn_addr(ctx, decl); - Node* if_true_lam = case_(a, empty(a)); - BodyBuilder* if_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_lam)); + Node* if_true_case = case_(a, empty(a)); + BodyBuilder* if_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); - gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %ul with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); + gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } - gen_call(if_builder, fn_addr_helper(a, find_processed(&ctx->rewriter, decl)), empty(a)); - set_abstraction_body(if_true_lam, finish_body_with_selection_merge(if_builder, empty(a))); + gen_call(if_builder, fn_addr_helper(a, rewrite_node(&ctx->rewriter, decl)), empty(a)); + set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_builder, empty(a))); - Node* case_lam = case_(a, nodes(a, 0, NULL)); - BodyBuilder* case_builder = begin_body_with_mem(a, get_abstraction_mem(case_lam)); - gen_if(case_builder, empty(a), should_run, if_true_lam, NULL); - set_abstraction_body(case_lam, finish_body_with_loop_continue(case_builder, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); + Node* fn_case = case_(a, nodes(a, 0, NULL)); + BodyBuilder* case_builder = begin_body_with_mem(a, get_abstraction_mem(fn_case)); + gen_if(case_builder, empty(a), should_run, if_true_case, NULL); + set_abstraction_body(fn_case, finish_body_with_loop_continue(case_builder, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); append_list(const Node*, literals, fn_lit); - append_list(const Node*, cases, case_lam); + append_list(const Node*, cases, fn_case); } } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 1e121a2be..ebaa3bd47 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -276,7 +276,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { // Wrap the tail in a guarded if, to handle 'far' joins const Node* level_value = gen_load(bb_tail, ctx->level_ptr); - const Node* guard = first(bind_instruction(bb_tail, prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }))); + const Node* guard = prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }); Node* true_case = case_(a, empty(a)); register_processed(r, get_abstraction_mem(get_structured_construct_tail(body)), get_abstraction_mem(true_case)); set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index d27d84fed..14be7bae9 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -21,7 +21,7 @@ Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { Nodes gen_primop(BodyBuilder* bb, Op op, Nodes type_args, Nodes operands) { assert(bb->arena->config.check_types); const Node* instruction = prim_op(bb->arena, (PrimOp) { .op = op, .type_arguments = type_args, .operands = operands }); - return bind_instruction(bb, instruction); + return singleton(instruction); } Nodes gen_primop_c(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { @@ -66,7 +66,7 @@ const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { } const Node* gen_get_stack_base_addr(BodyBuilder* bb) { - return first(bind_instruction(bb, get_stack_base_addr(bb->arena, (GetStackBaseAddr) { .mem = bb_mem(bb) }))); + return get_stack_base_addr(bb->arena, (GetStackBaseAddr) { .mem = bb_mem(bb) }); } const Node* gen_get_stack_size(BodyBuilder* bb) { @@ -79,12 +79,12 @@ void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); - return first(bind_instruction(bb, prim_op(bb->arena, (PrimOp) { .op = reinterpret_op, .operands = singleton(src), .type_arguments = singleton(dst)}))); + return prim_op(bb->arena, (PrimOp) { .op = reinterpret_op, .operands = singleton(src), .type_arguments = singleton(dst)}); } const Node* gen_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); - return first(bind_instruction(bb, prim_op(bb->arena, (PrimOp) { .op = convert_op, .operands = singleton(src), .type_arguments = singleton(dst)}))); + return prim_op(bb->arena, (PrimOp) { .op = convert_op, .operands = singleton(src), .type_arguments = singleton(dst)}); } const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { @@ -113,7 +113,7 @@ const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { } const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Node* index) { - return first(bind_instruction(bb, extract_helper(composite, index))); + return extract_helper(composite, index); } const Node* gen_load(BodyBuilder* bb, const Node* ptr) { @@ -125,7 +125,7 @@ void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { } const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { - return first(bind_instruction(bb, lea(bb->arena, (Lea) { .ptr = base, .offset = offset, .indices = selectors }))); + return lea(bb->arena, (Lea) { .ptr = base, .offset = offset, .indices = selectors }); } const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { From b1a8ad65cbbc37e83f07e7c61cf7b13c4b357818 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 09:44:46 +0200 Subject: [PATCH 506/693] l2s: fixed scf recovery --- src/frontend/llvm/l2s_instr.c | 17 ++++++----------- src/frontend/llvm/l2s_postprocess.c | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index d4a9f1fb8..534b706b6 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -448,7 +448,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B assert(false && "We deal with phi nodes before, there shouldn't be one here"); break; case LLVMCall: { - const Node* r; + const Node* r = NULL; unsigned num_args = LLVMGetNumArgOperands(instr); LLVMValueRef callee = LLVMGetCalledValue(instr); callee = remove_ptr_bitcasts(p, callee); @@ -571,12 +571,8 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B if (ops.count == 0) error("DebugPrintf called without arguments"); size_t whocares; - r = debug_printf(a, (DebugPrintf) { - .string = LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), - .args = nodes(a, ops.count - 1, &ops.nodes[1]), - .mem = bb_mem(b), - }); - goto finish; + gen_debug_printf(b, LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), nodes(a, ops.count - 1, &ops.nodes[1])); + return tuple_helper(a, empty(a)); } error_print("Unrecognised shady instruction '%s'\n", instructionname); @@ -594,13 +590,12 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B if (!r) { Nodes ops = convert_operands(p, num_ops, instr); - r = call(a, (Call) { + r = bind_instruction_single(b, call(a, (Call) { + .mem = bb_mem(b), .callee = ops.nodes[num_args], .args = nodes(a, num_args, ops.nodes), - }); + })); } - if (t == unit_type(a)) - num_results = 0; return r; } case LLVMSelect: diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 32c50a126..c96c01a2d 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -163,7 +163,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, register_processed_list(r, get_abstraction_params(node), nparams); Node* new_bb = (Node*) basic_block(a, nparams, get_abstraction_name_unsafe(node)); register_processed(r, node, new_bb); - wrap_in_controls(ctx, &controls, new_bb, node); + wrap_in_controls(&bb_ctx, &controls, new_bb, node); // new_bb->payload.basic_block.body = wrap_in_controls(ctx, &controls, new_bb->payload.basic_block.body); return new_bb; } From 16c9992e5046edf9e643e083906410f9f1102eac Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 09:45:31 +0200 Subject: [PATCH 507/693] lower_alloca: make fast --- src/shady/passes/lower_alloca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 3e196b749..3670f6b4c 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -66,7 +66,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { default: break; } - visit_node_operands(&vctx->visitor, IGNORE_ABSTRACTIONS_MASK, node); + visit_node_operands(&vctx->visitor, ~NcMem, node); } KeyHash hash_node(Node**); From f5884816ab9a3a7184ebca4200150b3504ea633a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 10:06:17 +0200 Subject: [PATCH 508/693] improve lower_alloca's reliability --- src/shady/analysis/callgraph.c | 1 - src/shady/passes/lower_alloca.c | 3 +-- src/shady/visit.c | 15 ++++++++++++++- src/shady/visit.h | 3 ++- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index ad357e20c..c3b9c6566 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -106,7 +106,6 @@ static CGNode* analyze_fn(CallGraph* graph, const Node* fn) { }; if (get_abstraction_body(fn)) { - search_for_callsites(&v, get_abstraction_body(fn)); visit_function_rpo(&v.visitor, fn); } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 3670f6b4c..0677e2389 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -110,8 +110,7 @@ static const Node* process(Context* ctx, const Node* node) { .members = new_list(const Node*), .prepared_offsets = ctx2.prepared_offsets, }; - search_operand_for_alloca(&vctx, node->payload.fun.body); - visit_function_rpo(&vctx.visitor, node); + visit_function_bodies_rpo(&vctx.visitor, node); vctx.nom_t->payload.nom_type.body = record_type(a, (RecordType) { .members = nodes(a, vctx.num_slots, read_list(const Node*, vctx.members)), diff --git a/src/shady/visit.c b/src/shady/visit.c index a226ffec5..7b2ab0802 100644 --- a/src/shady/visit.c +++ b/src/shady/visit.c @@ -35,13 +35,26 @@ void visit_function_rpo(Visitor* visitor, const Node* function) { assert(function->tag == Function_TAG); CFG* cfg = build_fn_cfg(function); assert(cfg->rpo[0]->node == function); - for (size_t i = 1; i < cfg->size; i++) { + for (size_t i = 0; i < cfg->size; i++) { const Node* node = cfg->rpo[i]->node; visit_node(visitor, node); } destroy_cfg(cfg); } +void visit_function_bodies_rpo(Visitor* visitor, const Node* function) { + assert(function->tag == Function_TAG); + CFG* cfg = build_fn_cfg(function); + assert(cfg->rpo[0]->node == function); + for (size_t i = 0; i < cfg->size; i++) { + const Node* node = cfg->rpo[i]->node; + assert(is_abstraction(node)); + if (get_abstraction_body(node)) + visit_node(visitor, get_abstraction_body(node)); + } + destroy_cfg(cfg); +} + #pragma GCC diagnostic error "-Wswitch" #include "visit_generated.c" diff --git a/src/shady/visit.h b/src/shady/visit.h index 1caf7c1f5..14d14c07f 100644 --- a/src/shady/visit.h +++ b/src/shady/visit.h @@ -21,8 +21,9 @@ void visit_nodes(Visitor* visitor, Nodes nodes); void visit_op(Visitor* visitor, NodeClass, String, const Node*); void visit_ops(Visitor* visitor, NodeClass, String, Nodes nodes); -// visits the abstractions in the function, _except_ for the entry block (ie the function itself) +// visits the abstractions in the function, starting with the entry block (ie the function itself) void visit_function_rpo(Visitor* visitor, const Node* function); +void visit_function_bodies_rpo(Visitor* visitor, const Node* function); // use this in visit_node_operands to avoid visiting nodes in non-rpo order #define IGNORE_ABSTRACTIONS_MASK NcBasic_block | NcDeclaration | NcAbstraction From df5fb57bfd3ba809abffa42fe5a0941ef738d6ec Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 10:06:35 +0200 Subject: [PATCH 509/693] spv: be a bit more conservative on what can be emitted at top level --- src/backend/spirv/emit_spv_value.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 7e7ad2f6e..67f693153 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -566,9 +566,17 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder } static bool can_appear_at_top_level(const Node* node) { - if (is_instruction(node)) - return false; - return true; + switch (node->tag) { + case Undef_TAG: + case Composite_TAG: + case FloatLiteral_TAG: + case IntLiteral_TAG: + case True_TAG: + case False_TAG: + return true; + default: break; + } + return false; } SpvId spv_emit_value(Emitter* emitter, FnBuilder* fn_builder, const Node* node) { From a850c8068482bad9e3bf46db99eef593c842b1eb Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 11:06:23 +0200 Subject: [PATCH 510/693] visitor&uses: provide index in operand list --- src/shady/analysis/scheduler.c | 2 +- src/shady/analysis/uses.c | 5 +++-- src/shady/analysis/uses.h | 1 + src/shady/generator_visit.c | 2 +- src/shady/print.c | 2 +- src/shady/visit.c | 6 +++--- src/shady/visit.h | 4 ++-- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c index 90ed74cd3..cf22491f0 100644 --- a/src/shady/analysis/scheduler.c +++ b/src/shady/analysis/scheduler.c @@ -28,7 +28,7 @@ static void schedule_after(CFNode** scheduled, CFNode* req) { } } -static void visit_operand(Scheduler* s, NodeClass nc, String opname, const Node* op) { +static void visit_operand(Scheduler* s, NodeClass nc, String opname, const Node* op, size_t i) { switch (nc) { // We only care about mem and value dependencies case NcMem: diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index 111300708..29fd43f85 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -43,14 +43,15 @@ static void uses_visit_node(UsesMapVisitor* v, const Node* n) { } } -static void uses_visit_op(UsesMapVisitor* v, NodeClass class, String op_name, const Node* op) { +static void uses_visit_op(UsesMapVisitor* v, NodeClass class, String op_name, const Node* op, size_t i) { Use* use = arena_alloc(v->map->a, sizeof(Use)); memset(use, 0, sizeof(Use)); *use = (Use) { .user = v->user, .operand_class = class, .operand_name = op_name, - .next_use = NULL + .operand_index = i, + .next_use = NULL, }; Use* last_use = get_last_use(v->map, op); diff --git a/src/shady/analysis/uses.h b/src/shady/analysis/uses.h index 0f74ea28c..00e3ce1ac 100644 --- a/src/shady/analysis/uses.h +++ b/src/shady/analysis/uses.h @@ -18,6 +18,7 @@ struct Use_ { const Node* user; NodeClass operand_class; String operand_name; + size_t operand_index; const Use* next_use; }; diff --git a/src/shady/generator_visit.c b/src/shady/generator_visit.c index 3db5df01a..46111c630 100644 --- a/src/shady/generator_visit.c +++ b/src/shady/generator_visit.c @@ -35,7 +35,7 @@ void generate(Growy* g, json_object* src) { if (list) growy_append_formatted(g, "\t\t\tvisit_ops(visitor, Nc%s, \"%s\", payload.%s);\n", class_cap, op_name, op_name); else - growy_append_formatted(g, "\t\t\tvisit_op(visitor, Nc%s, \"%s\", payload.%s);\n", class_cap, op_name, op_name); + growy_append_formatted(g, "\t\t\tvisit_op(visitor, Nc%s, \"%s\", payload.%s, 0);\n", class_cap, op_name, op_name); } free((void*) class_cap); } diff --git a/src/shady/print.c b/src/shady/print.c index 158109da1..faf1e03c0 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1110,7 +1110,7 @@ typedef struct { PrinterCtx* ctx; } PrinterVisitor; -static void print_mem_visitor(PrinterVisitor* ctx, NodeClass nc, String opname, const Node* op) { +static void print_mem_visitor(PrinterVisitor* ctx, NodeClass nc, String opname, const Node* op, size_t i) { if (nc == NcMem) print_mem(ctx->ctx, op); } diff --git a/src/shady/visit.c b/src/shady/visit.c index 7b2ab0802..ad8345b4a 100644 --- a/src/shady/visit.c +++ b/src/shady/visit.c @@ -17,18 +17,18 @@ void visit_nodes(Visitor* visitor, Nodes nodes) { } } -void visit_op(Visitor* visitor, NodeClass op_class, String op_name, const Node* op) { +void visit_op(Visitor* visitor, NodeClass op_class, String op_name, const Node* op, size_t i) { if (!op) return; if (visitor->visit_op_fn) - visitor->visit_op_fn(visitor, op_class, op_name, op); + visitor->visit_op_fn(visitor, op_class, op_name, op, i); else visitor->visit_node_fn(visitor, op); } void visit_ops(Visitor* visitor, NodeClass op_class, String op_name, Nodes ops) { for (size_t i = 0; i < ops.count; i++) - visit_op(visitor, op_class, op_name, ops.nodes[i]); + visit_op(visitor, op_class, op_name, ops.nodes[i], i); } void visit_function_rpo(Visitor* visitor, const Node* function) { diff --git a/src/shady/visit.h b/src/shady/visit.h index 14d14c07f..0926115a0 100644 --- a/src/shady/visit.h +++ b/src/shady/visit.h @@ -5,7 +5,7 @@ typedef struct Visitor_ Visitor; typedef void (*VisitNodeFn)(Visitor*, const Node*); -typedef void (*VisitOpFn)(Visitor*, NodeClass, String, const Node*); +typedef void (*VisitOpFn)(Visitor*, NodeClass, String, const Node*, size_t); struct Visitor_ { VisitNodeFn visit_node_fn; @@ -18,7 +18,7 @@ void visit_module(Visitor* visitor, Module*); void visit_node(Visitor* visitor, const Node*); void visit_nodes(Visitor* visitor, Nodes nodes); -void visit_op(Visitor* visitor, NodeClass, String, const Node*); +void visit_op(Visitor* visitor, NodeClass, String, const Node*, size_t i); void visit_ops(Visitor* visitor, NodeClass, String, Nodes nodes); // visits the abstractions in the function, starting with the entry block (ie the function itself) From ba83d274bb90ab7182d2075b87da0f4e50812f86 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 11:07:03 +0200 Subject: [PATCH 511/693] l2s: rewrite params by hand and remove hack in rewrite.c --- src/frontend/llvm/l2s_postprocess.c | 29 +++++++++++++++-------------- src/shady/rewrite.c | 5 +---- src/shady/rewrite.h | 1 - 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index c96c01a2d..0b03d8f1b 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -75,11 +75,19 @@ bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { bool compare_nodes(Nodes* a, Nodes* b); static Nodes remake_params(Context* ctx, Nodes old) { - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; LARRAY(const Node*, nvars, old.count); for (size_t i = 0; i < old.count; i++) { const Node* node = old.nodes[i]; - nvars[i] = param(a, node->payload.param.type ? qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.param.type), false) : NULL, node->payload.param.name); + const Type* t = NULL; + if (node->payload.param.type) { + if (node->payload.param.type->tag == QualifiedType_TAG) + t = rewrite_node(r, node->payload.param.type); + else + t = qualified_type_helper(rewrite_node(r, node->payload.param.type), false); + } + nvars[i] = param(a, t, node->payload.param.name); assert(nvars[i]->tag == Param_TAG); } return nodes(a, old.count, nvars); @@ -90,10 +98,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, Rewriter* r = &ctx->rewriter; switch (node->tag) { case Param_TAG: { - assert(node->payload.param.type); - if (node->payload.param.type->tag == QualifiedType_TAG) - return param(a, node->payload.param.type ? rewrite_node(&ctx->rewriter, node->payload.param.type) : NULL, node->payload.param.name); - return param(a, qualified_type_helper(rewrite_node(&ctx->rewriter, node->payload.param.type), false), node->payload.param.name); + assert(false); } case Constant_TAG: { Node* new = (Node*) recreate_node_identity(r, node); @@ -116,7 +121,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, fn_ctx.old_fn_or_bb = node; Controls controls; initialize_controls(ctx, &controls, node); - Nodes new_params = recreate_params(&fn_ctx.rewriter, node->payload.fun.params); + Nodes new_params = remake_params(&fn_ctx, node->payload.fun.params); Nodes old_annotations = node->payload.fun.annotations; ParsedAnnotation* an = find_annotation(ctx->p, node); Op primop_intrinsic = PRIMOPS_COUNT; @@ -146,8 +151,8 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, register_processed(&ctx->rewriter, node, decl); if (primop_intrinsic != PRIMOPS_COUNT) { set_abstraction_body(decl, fn_ret(a, (Return) { - .args = singleton(prim_op_helper(a, primop_intrinsic, empty(a), get_abstraction_params(decl))), - .mem = get_abstraction_mem(decl), + .args = singleton(prim_op_helper(a, primop_intrinsic, empty(a), get_abstraction_params(decl))), + .mem = get_abstraction_mem(decl), })); } else wrap_in_controls(&fn_ctx, &controls, decl, node); @@ -159,7 +164,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, bb_ctx.old_fn_or_bb = node; Controls controls; initialize_controls(ctx, &controls, node); - Nodes nparams = recreate_params(&ctx->rewriter, get_abstraction_params(node)); + Nodes nparams = remake_params(ctx, get_abstraction_params(node)); register_processed_list(r, get_abstraction_params(node), nparams); Node* new_bb = (Node*) basic_block(a, nparams, get_abstraction_name_unsafe(node)); register_processed(r, node, new_bb); @@ -304,7 +309,6 @@ static const Node* process_node(Context* ctx, const Node* old) { return process_op(ctx, 0, NULL, old); } - void postprocess(Parser* p, Module* src, Module* dst) { assert(src != dst); Context ctx = { @@ -314,10 +318,7 @@ void postprocess(Parser* p, Module* src, Module* dst) { .controls = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), }; - ctx.rewriter.config.process_params = true; - ctx.rewriter.config.search_map = true; ctx.rewriter.rewrite_op_fn = (RewriteOpFn) process_op; - // ctx.rewriter.config.write_map = false; rewrite_module(&ctx.rewriter); destroy_dict(ctx.controls); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 0e316ea9c..99b30724c 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -243,10 +243,7 @@ const Node* recreate_param(Rewriter* rewriter, const Node* old) { Nodes recreate_params(Rewriter* rewriter, Nodes oparams) { LARRAY(const Node*, nparams, oparams.count); for (size_t i = 0; i < oparams.count; i++) { - if (rewriter->config.process_params) - nparams[i] = rewrite_node(rewriter, oparams.nodes[i]); - else - nparams[i] = recreate_param(rewriter, oparams.nodes[i]); + nparams[i] = recreate_param(rewriter, oparams.nodes[i]); assert(nparams[i]->tag == Param_TAG); } return nodes(rewriter->dst_arena, oparams.count, nparams); diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index f8580dbe9..1dd32d64b 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -33,7 +33,6 @@ struct Rewriter_ { struct { bool search_map; bool write_map; - bool process_params; } config; Rewriter* parent; From 560cd4cd156e0598b1ecc0791f68e09f18420ece Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 11:07:26 +0200 Subject: [PATCH 512/693] bind: don't generate dummy loads --- src/frontend/slim/bind.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 6301a2a6d..5daa66020 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -2,6 +2,7 @@ #include "shady/fe/slim.h" #include "../shady/ir_private.h" +#include "../shady/analysis/uses.h" #include "list.h" #include "log.h" @@ -20,6 +21,7 @@ struct NamedBindEntry_ { typedef struct { Rewriter rewriter; + const UsesMap* uses; const Node* current_function; NamedBindEntry* local_variables; @@ -246,6 +248,25 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { //return bound; } +static bool is_used_as_value(Context* ctx, const Node* node) { + const Use* use = get_first_use(ctx->uses, node); + for (;use;use = use->next_use) { + if (use->operand_class != NcMem) { + if (use->user->tag == ExtInstr_TAG && strcmp(use->user->payload.ext_instr.set, "shady.frontend") == 0) { + if (use->user->payload.ext_instr.opcode == SlimOpAssign && use->operand_index == 0) + continue; + if (use->user->payload.ext_instr.opcode == SlimOpSubscript && use->operand_index == 0) { + const Node* ptr = get_node_address_maybe(ctx, node); + if (ptr) + continue; + } + } + return true; + } + } + return false; +} + static const Node* bind_node(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; @@ -294,6 +315,8 @@ static const Node* bind_node(Context* ctx, const Node* node) { if (strcmp("shady.frontend", payload.set) == 0) { switch ((SlimFrontEndOpCodes) payload.opcode) { case SlimOpDereference: + if (!is_used_as_value(ctx, node)) + return rewrite_node(r, payload.mem); return load(a, (Load) { .ptr = rewrite_node(r, first(payload.operands)), .mem = rewrite_node(r, payload.mem), @@ -325,8 +348,11 @@ static const Node* bind_node(Context* ctx, const Node* node) { } case SlimOpUnbound: { const Node* mem = NULL; - if (payload.mem) + if (payload.mem) { + if (!is_used_as_value(ctx, node)) + return rewrite_node(r, payload.mem); mem = rewrite_node(r, payload.mem); + } Resolved entry = resolve_using_name(ctx, get_string_literal(a, first(payload.operands))); if (entry.is_var) { return load(a, (Load) { .ptr = entry.node, .mem = mem }); @@ -356,9 +382,11 @@ Module* bind_program(SHADY_UNUSED const CompilerConfig* compiler_config, Module* .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) bind_node), .local_variables = NULL, .current_function = NULL, + .uses = create_module_uses_map(src, 0), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); + destroy_uses_map(ctx.uses); return dst; } From a1c1243b741dde1d36ca401b5c617a578bb01b1b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 11:07:38 +0200 Subject: [PATCH 513/693] fixed checkerboard sample --- samples/checkerboard/checkerboard_kernel.slim | 4 ++-- src/frontend/slim/parser.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/samples/checkerboard/checkerboard_kernel.slim b/samples/checkerboard/checkerboard_kernel.slim index 2412b5bfd..937ebd742 100644 --- a/samples/checkerboard/checkerboard_kernel.slim +++ b/samples/checkerboard/checkerboard_kernel.slim @@ -2,9 +2,9 @@ const i32 WIDTH = 256; const i32 HEIGHT = 256; @Builtin("GlobalInvocationId") -uniform input pack[u32; 3] global_id; +var uniform input pack[u32; 3] global_id; -@EntryPoint("Compute") @WorkgroupSize(16, 16, 1) fn checkerboard(uniform ptr global [u8] p) { +@EntryPoint("Compute") @Exported @WorkgroupSize(16, 16, 1) fn checkerboard(uniform ptr global [u8] p) { val thread_id = global_id; val x = reinterpret[i32](thread_id#0); val y = reinterpret[i32](thread_id#1); diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 4dc9689d1..a2c1dce13 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -1084,14 +1084,6 @@ static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { AddressSpace as = NumAddressSpaces; bool uniform = false, logical = false; while (true) { - AddressSpace nas = accept_address_space(ctx); - if (nas != NumAddressSpaces) { - if (as != NumAddressSpaces && as != nas) { - error("Conflicting address spaces for definition: %s and %s.\n", get_address_space_name(as), get_address_space_name(nas)); - } - as = nas; - continue; - } if (accept_token(ctx, logical_tok)) { logical = true; continue; @@ -1100,6 +1092,14 @@ static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { uniform = true; continue; } + AddressSpace nas = accept_address_space(ctx); + if (nas != NumAddressSpaces) { + if (as != NumAddressSpaces && as != nas) { + error("Conflicting address spaces for definition: %s and %s.\n", get_address_space_name(as), get_address_space_name(nas)); + } + as = nas; + continue; + } break; } From 6157a709dc626a45656958fe77a94e51f816b708 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 14:29:43 +0200 Subject: [PATCH 514/693] added dominance checks to the scheduler --- src/shady/analysis/cfg.c | 5 ++--- src/shady/analysis/scheduler.c | 15 ++++++++++++++- test/vcc/CMakeLists.txt | 1 + test/vcc/loop_closed.c | 8 ++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 test/vcc/loop_closed.c diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index b53150105..dd0b26881 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -438,9 +438,8 @@ void compute_domtree(CFG* cfg) { continue; for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { CFEdge e = read_list(CFEdge, n->pred_edges)[j]; - CFNode* pred = e.src; - if (pred->rpo_index < n->rpo_index) { - n->idom = pred; + if (e.src->rpo_index < n->rpo_index) { + n->idom = e.src; goto outer_loop; } } diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c index cf22491f0..0dfe0cf93 100644 --- a/src/shady/analysis/scheduler.c +++ b/src/shady/analysis/scheduler.c @@ -15,6 +15,15 @@ struct Scheduler_ { struct Dict* scheduled; }; +static bool is_dominated(CFNode* a, CFNode* b) { + while (a) { + if (a == b) + return true; + a = a->idom; + } + return false; +} + static void schedule_after(CFNode** scheduled, CFNode* req) { if (!req) return; @@ -23,8 +32,12 @@ static void schedule_after(CFNode** scheduled, CFNode* req) { *scheduled = req; else { // TODO: validate that old post-dominates req - if (req->rpo_index > old->rpo_index) + if (req->rpo_index > old->rpo_index) { + assert(is_dominated(req, old)); *scheduled = req; + } else { + assert(is_dominated(old, req)); + } } } diff --git a/test/vcc/CMakeLists.txt b/test/vcc/CMakeLists.txt index a06d48bda..f47debef7 100644 --- a/test/vcc/CMakeLists.txt +++ b/test/vcc/CMakeLists.txt @@ -9,6 +9,7 @@ endforeach() spv_outputting_test(NAME test/vcc/branch.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/loop.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) +spv_outputting_test(NAME test/vcc/loop_closed.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/goto.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/ternary.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/string.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) diff --git a/test/vcc/loop_closed.c b/test/vcc/loop_closed.c new file mode 100644 index 000000000..4a18c7f28 --- /dev/null +++ b/test/vcc/loop_closed.c @@ -0,0 +1,8 @@ +int square(int num) { + for (int i = 0; i < num; i++) { + if (i == 9) + return i; + num--; + } + return 0; +} From bfd75f73089254017205ae0cf846459d033308bf Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 15:53:42 +0200 Subject: [PATCH 515/693] l2s: use an extinstr to remember scope info --- src/frontend/llvm/l2s.c | 2 - src/frontend/llvm/l2s_instr.c | 15 ++- src/frontend/llvm/l2s_postprocess.c | 153 ++++++++++++++-------------- src/frontend/llvm/l2s_private.h | 1 - src/shady/node_helpers.c | 6 +- src/shady/rewrite.c | 2 +- test/test_builder.c | 2 +- 7 files changed, 93 insertions(+), 88 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 02c926c86..0c13f1fc1 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -266,7 +266,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* .config = config, .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), - .scopes = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), .wrappers_map = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), .annotations_arena = new_arena(), .src = src, @@ -303,7 +302,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* destroy_dict(p.map); destroy_dict(p.annotations); - destroy_dict(p.scopes); destroy_dict(p.wrappers_map); destroy_arena(p.annotations_arena); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 534b706b6..c8835eaee 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -127,10 +127,10 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B assert(fn && fn_or_bb); LLVMMetadataRef dbgloc = LLVMInstructionGetDebugLoc(instr); if (dbgloc) { - Nodes* found = find_value_dict(const Node*, Nodes, p->scopes, fn_or_bb); - if (!found) { + //Nodes* found = find_value_dict(const Node*, Nodes, p->scopes, fn_or_bb); + //if (!found) { Nodes str = scope_to_string(p, dbgloc); - insert_dict(const Node*, Nodes, p->scopes, fn_or_bb, str); + //insert_dict(const Node*, Nodes, p->scopes, fn_or_bb, str); debugv_print("Found a debug location for "); log_node(DEBUGV, fn_or_bb); debugv_print(" "); @@ -139,7 +139,14 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B debugv_print(" -> "); } debugv_print(" (depth= %zu)\n", str.count); - } + bind_instruction_single(b, ext_instr(a, (ExtInstr) { + .set = "shady.scope", + .opcode = 0, + .result_t = unit_type(a), + .mem = bb_mem(b), + .operands = str, + })); + //} } } diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 0b03d8f1b..27a018927 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -23,6 +23,25 @@ typedef struct { Nodes tokens, destinations; } Controls; +static Nodes remake_params(Context* ctx, Nodes old) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + LARRAY(const Node*, nvars, old.count); + for (size_t i = 0; i < old.count; i++) { + const Node* node = old.nodes[i]; + const Type* t = NULL; + if (node->payload.param.type) { + if (node->payload.param.type->tag == QualifiedType_TAG) + t = rewrite_node(r, node->payload.param.type); + else + t = qualified_type_helper(rewrite_node(r, node->payload.param.type), false); + } + nvars[i] = param(a, t, node->payload.param.name); + assert(nvars[i]->tag == Param_TAG); + } + return nodes(a, old.count, nvars); +} + static void initialize_controls(Context* ctx, Controls* controls, const Node* fn_or_bb) { IrArena* a = ctx->rewriter.dst_arena; *controls = (Controls) { @@ -45,13 +64,12 @@ static void wrap_in_controls(Context* ctx, Controls* controls, Node* nabs, const for (size_t i = 0; i < controls->destinations.count; i++) { const Node* token = controls->tokens.nodes[i]; const Node* dst = controls->destinations.nodes[i]; - Nodes o_dst_params = get_abstraction_params(dst); Node* control_case = case_(a, singleton(token)); set_abstraction_body(control_case, jump_helper(a, c, empty(a), get_abstraction_mem(control_case))); Node* c2 = case_(a, empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); - Nodes results = gen_control(bb, get_param_types(a, o_dst_params), control_case); + Nodes results = gen_control(bb, get_param_types(a, get_abstraction_params(dst)), control_case); set_abstraction_body(c2, finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results, bb_mem(bb)))); c = c2; } @@ -74,23 +92,18 @@ bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { bool compare_nodes(Nodes* a, Nodes* b); -static Nodes remake_params(Context* ctx, Nodes old) { - Rewriter* r = &ctx->rewriter; - IrArena* a = r->dst_arena; - LARRAY(const Node*, nvars, old.count); - for (size_t i = 0; i < old.count; i++) { - const Node* node = old.nodes[i]; - const Type* t = NULL; - if (node->payload.param.type) { - if (node->payload.param.type->tag == QualifiedType_TAG) - t = rewrite_node(r, node->payload.param.type); - else - t = qualified_type_helper(rewrite_node(r, node->payload.param.type), false); +static const Nodes* find_scope_info(const Node* abs) { + assert(is_abstraction(abs)); + const Node* terminator = get_abstraction_body(abs); + const Node* mem = get_terminator_mem(terminator); + Nodes* info = NULL; + while (mem) { + if (mem->tag == ExtInstr_TAG && strcmp(mem->payload.ext_instr.set, "shady.scope") == 0) { + info = &mem->payload.ext_instr.operands; } - nvars[i] = param(a, t, node->payload.param.name); - assert(nvars[i]->tag == Param_TAG); + mem = get_parent_mem(mem); } - return nodes(a, old.count, nvars); + return info; } static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Node* node) { @@ -108,13 +121,6 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, new->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(value)); return new; } - case PrimOp_TAG: { - Nodes old_operands = node->payload.prim_op.operands; - switch (node->payload.prim_op.op) { - default: break; - } - break; - } case Function_TAG: { Context fn_ctx = *ctx; fn_ctx.cfg = build_fn_cfg(node); @@ -172,6 +178,12 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, // new_bb->payload.basic_block.body = wrap_in_controls(ctx, &controls, new_bb->payload.basic_block.body); return new_bb; } + case ExtInstr_TAG: { + if (strcmp(node->payload.ext_instr.set, "shady.scope") == 0) { + return rewrite_node(r, node->payload.ext_instr.mem); + } + break; + } case Jump_TAG: { const Node* src = ctx->old_fn_or_bb; const Node* dst = node->payload.jump.target; @@ -180,12 +192,12 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, if (!ctx->config->hacks.recover_structure) break; - Nodes* src_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, src); + const Nodes* src_lexical_scope = find_scope_info(src); bool src_is_wrapper = find_value_dict(const Node*, const Node*, ctx->p->wrappers_map, src); const Node** found_dst_wrapper = find_value_dict(const Node*, const Node*, ctx->p->wrappers_map, dst); if (found_dst_wrapper) dst = *found_dst_wrapper; - Nodes* dst_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, dst); + const Nodes* dst_lexical_scope = find_scope_info(dst); if (src_is_wrapper) { // silent } else if (!src_lexical_scope) { @@ -205,54 +217,51 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, assert(src_cfnode && target_cfnode); CFNode* dom = src_cfnode->idom; while (dom) { - if (dom->node->tag == BasicBlock_TAG || dom->node->tag == Function_TAG) { - debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); - Nodes* dom_lexical_scope = find_value_dict(const Node*, Nodes, ctx->p->scopes, dom->node); - if (!dom_lexical_scope) { - warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); - dom = dom->idom; - continue; - } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { - error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); - } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { - debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); - Controls** found = find_value_dict(const Node, Controls*, ctx->controls, dom->node); - if (found) { - Controls* controls = *found; - const Node* join_token = NULL; - for (size_t i = 0; i < controls->destinations.count; i++) { - if (controls->destinations.nodes[i] == dst) { - join_token = controls->tokens.nodes[i]; - break; - } - } - if (!join_token) { - const Type* jp_type = join_point_type(a, (JoinPointType) { - .yield_types = get_param_types(a, get_abstraction_params(dst)) - }); - join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); - controls->tokens = append_nodes(a, controls->tokens, join_token); - controls->destinations = append_nodes(a, controls->destinations, dst); + debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); + Nodes* dom_lexical_scope = find_scope_info(dom->node); + if (!dom_lexical_scope) { + warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); + dom = dom->idom; + continue; + } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { + error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); + } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { + debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); + Controls** found = find_value_dict(const Node, Controls*, ctx->controls, dom->node); + if (found) { + Controls* controls = *found; + const Node* join_token = NULL; + for (size_t i = 0; i < controls->destinations.count; i++) { + if (controls->destinations.nodes[i] == dst) { + join_token = controls->tokens.nodes[i]; + break; } - Nodes nparams = remake_params(ctx, get_abstraction_params(dst)); - //register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); - Node* wrapper = basic_block(a, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); - wrapper->payload.basic_block.body = join(a, (Join) { - .args = nparams, - .join_point = join_token, - .mem = get_abstraction_mem(wrapper), + } + if (!join_token) { + const Type* jp_type = join_point_type(a, (JoinPointType) { + .yield_types = get_param_types(a, get_abstraction_params(dst)) }); - return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); - } else { - assert(false); + join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); + controls->tokens = append_nodes(a, controls->tokens, join_token); + controls->destinations = append_nodes(a, controls->destinations, dst); } + Nodes nparams = remake_params(ctx, get_abstraction_params(dst)); + register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); + Node* wrapper = basic_block(a, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); + wrapper->payload.basic_block.body = join(a, (Join) { + .args = nparams, + .join_point = join_token, + .mem = get_abstraction_mem(wrapper), + }); + return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); } else { - dom = dom->idom; - continue; + assert(false); } - break; + } else { + dom = dom->idom; + continue; } - dom = dom->idom; + break; } } break; @@ -294,14 +303,6 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, default: break; } - // This is required so we don't wrap jumps that are part of branches! - // if (ctx->old_fn_or_bb && op_class == NcTerminator) { - // Controls** found = find_value_dict(const Node, Controls*, ctx->controls, ctx->old_fn_or_bb); - // assert(found); - // Controls* controls = *found; - // return wrap_in_controls(ctx, controls, recreate_node_identity(&ctx->rewriter, node)); - // } - return recreate_node_identity(&ctx->rewriter, node); } diff --git a/src/frontend/llvm/l2s_private.h b/src/frontend/llvm/l2s_private.h index 3676263de..a4d42b09e 100644 --- a/src/frontend/llvm/l2s_private.h +++ b/src/frontend/llvm/l2s_private.h @@ -18,7 +18,6 @@ typedef struct { LLVMContextRef ctx; struct Dict* map; struct Dict* annotations; - struct Dict* scopes; struct Dict* wrappers_map; Arena* annotations_arena; LLVMModuleRef src; diff --git a/src/shady/node_helpers.c b/src/shady/node_helpers.c index 885e617f8..7ca4114d3 100644 --- a/src/shady/node_helpers.c +++ b/src/shady/node_helpers.c @@ -9,7 +9,7 @@ const Node* get_parent_mem(const Node* mem) { switch (is_mem(mem)) { case NotAMem: return NULL; case Mem_AbsMem_TAG: - return mem; + return NULL; case Mem_Call_TAG: mem = mem->payload.call.mem; return mem; @@ -61,10 +61,10 @@ const Node* get_parent_mem(const Node* mem) { const Node* get_original_mem(const Node* mem) { while (true) { const Node* nmem = get_parent_mem(mem); - if (nmem != mem) { + if (nmem) { mem = nmem; continue; } - return nmem; + return mem; } } diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 99b30724c..e0f179ab4 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -176,7 +176,7 @@ static const Node* search_processed_(const Rewriter* ctx, const Node* old, bool } const Node* search_processed(const Rewriter* ctx, const Node* old) { - return search_processed_(ctx, old, false); + return search_processed_(ctx, old, true); } const Node* find_processed(const Rewriter* ctx, const Node* old) { diff --git a/test/test_builder.c b/test/test_builder.c index 4b88dc584..457b3725f 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -105,7 +105,7 @@ static void test_body_builder_impure_block(IrArena* a) { bool found_store = false; const Node* mem = get_terminator_mem(return_terminator); - while (mem->tag != AbsMem_TAG) { + while (mem) { if (mem->tag == Store_TAG) found_store = true; mem = get_parent_mem(mem); From c5747ac4b5bb2136416d021da42478e4246e4e0f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 20 Aug 2024 16:31:54 +0200 Subject: [PATCH 516/693] l2s: removed wrapper blocks and deal with phis directly --- src/frontend/llvm/l2s.c | 27 ++++++++++++++++----------- src/frontend/llvm/l2s_instr.c | 32 +++++++++----------------------- 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 0c13f1fc1..3b3a3ee14 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -110,8 +110,6 @@ static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { .instr = instr, .nbb = nbb, }; - //append_list(TodoBB, p->todo_bbs, todo); - //return nbb; return todo; } } @@ -120,9 +118,7 @@ const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); if (found) return *found; - TodoBB todo = prepare_bb(p, fn_ctx, bb); - todo.nbb->payload.basic_block.body = write_bb_tail(p, fn_ctx, todo.nbb, todo.bb, todo.instr); - return todo.nbb; + assert(false); } const Node* convert_function(Parser* p, LLVMValueRef fn) { @@ -172,16 +168,25 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { const Node* r = fn_addr_helper(a, f); insert_dict(LLVMValueRef, const Node*, p->map, fn, r); - if (LLVMCountBasicBlocks(fn) > 0) { + size_t bb_count = LLVMCountBasicBlocks(fn); + if (bb_count > 0) { LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); - f->payload.fun.body = write_bb_tail(p, &fn_parse_ctx, f, first_bb, LLVMGetFirstInstruction(first_bb)); - } - while (entries_count_list(fn_parse_ctx.jumps_todo) > 0) { - JumpTodo todo = pop_last_list(JumpTodo, fn_parse_ctx.jumps_todo); - convert_jump_finish(p, &fn_parse_ctx, todo); + LLVMBasicBlockRef bb = LLVMGetNextBasicBlock(first_bb); + LARRAY(TodoBB, todo, bb_count); + size_t i = 1; + for (;bb; bb = LLVMGetNextBasicBlock(bb)) { + assert(i < bb_count); + todo[i++] = prepare_bb(p, &fn_parse_ctx, bb); + } + + set_abstraction_body(f, write_bb_tail(p, &fn_parse_ctx, f, first_bb, LLVMGetFirstInstruction(first_bb))); + for (size_t i = 1; i < bb_count; i++) { + todo[i].nbb->payload.basic_block.body = write_bb_tail(p, &fn_parse_ctx, todo[i].nbb, todo[i].bb, todo[i].instr); + } } + { size_t i = 0; struct List* phis_list; diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index c8835eaee..f75316aae 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -56,23 +56,9 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { return v; } -static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef dst, const Node* mem) { - IrArena* a = fn_or_bb->arena; - Node* wrapper_bb = basic_block(a, empty(a), NULL); - JumpTodo todo = { - .wrapper = wrapper_bb, - .src = fn_or_bb, - .dst = dst, - }; - append_list(JumpTodo, fn_ctx->jumps_todo, todo); - const Node* dst2 = convert_basic_block(p, fn_ctx, dst); - insert_dict(Node*, const Node*, p->wrappers_map, wrapper_bb, dst2); - return jump_helper(a, wrapper_bb, empty(a), mem); -} - -void convert_jump_finish(Parser* p, FnParseCtx* fn_ctx, JumpTodo todo) { +static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, LLVMBasicBlockRef dst, const Node* mem) { IrArena* a = fn_ctx->fn->arena; - const Node* dst_bb = convert_basic_block(p, fn_ctx, todo.dst); + const Node* dst_bb = convert_basic_block(p, fn_ctx, dst); BBPhis* phis = find_value_dict(const Node*, BBPhis, fn_ctx->phis, dst_bb); assert(phis); size_t params_count = entries_count_list(phis->list); @@ -80,7 +66,7 @@ void convert_jump_finish(Parser* p, FnParseCtx* fn_ctx, JumpTodo todo) { for (size_t i = 0; i < params_count; i++) { LLVMValueRef phi = read_list(LLVMValueRef, phis->list)[i]; for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { - if (convert_basic_block(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == todo.src) { + if (convert_basic_block(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == src) { params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); goto next; } @@ -88,7 +74,7 @@ void convert_jump_finish(Parser* p, FnParseCtx* fn_ctx, JumpTodo todo) { assert(false && "failed to find the appropriate source"); next: continue; } - todo.wrapper->payload.basic_block.body = jump_helper(a, dst_bb, nodes(a, params_count, params), get_abstraction_mem(todo.wrapper)); + return jump_helper(a, dst_bb, nodes(a, params_count, params), mem); } static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* element_type) { @@ -165,24 +151,24 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Node* condition = convert_value(p, LLVMGetCondition(instr)); return branch(a, (Branch) { .condition = condition, - .true_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)), - .false_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[1], bb_mem(b)), + .true_jump = convert_jump(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)), + .false_jump = convert_jump(p, fn_ctx, fn_or_bb, targets[1], bb_mem(b)), .mem = bb_mem(b), }); } else { assert(n_targets == 1); - return convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)); + return convert_jump(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)); } } case LLVMSwitch: { const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); - const Node* default_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, 1), bb_mem(b)); + const Node* default_jump = convert_jump(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, 1), bb_mem(b)); int n_targets = LLVMGetNumOperands(instr) / 2 - 1; LARRAY(const Node*, targets, n_targets); LARRAY(const Node*, literals, n_targets); for (size_t i = 0; i < n_targets; i++) { literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); - targets[i] = convert_jump_lazy(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3), bb_mem(b)); + targets[i] = convert_jump(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3), bb_mem(b)); } return br_switch(a, (Switch) { .switch_value = inspectee, From 90425bd43f25fe779ddd2c0624aede3ff667ac3b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 21 Aug 2024 09:29:33 +0200 Subject: [PATCH 517/693] l2s: removed wrappers map --- src/frontend/llvm/l2s.c | 2 -- src/frontend/llvm/l2s_postprocess.c | 8 +------- src/frontend/llvm/l2s_private.h | 1 - 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 3b3a3ee14..a3e53d9a2 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -271,7 +271,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* .config = config, .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), - .wrappers_map = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), .annotations_arena = new_arena(), .src = src, .dst = dirty, @@ -307,7 +306,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* destroy_dict(p.map); destroy_dict(p.annotations); - destroy_dict(p.wrappers_map); destroy_arena(p.annotations_arena); LLVMContextDispose(context); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 27a018927..98b44d10a 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -193,14 +193,8 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, if (!ctx->config->hacks.recover_structure) break; const Nodes* src_lexical_scope = find_scope_info(src); - bool src_is_wrapper = find_value_dict(const Node*, const Node*, ctx->p->wrappers_map, src); - const Node** found_dst_wrapper = find_value_dict(const Node*, const Node*, ctx->p->wrappers_map, dst); - if (found_dst_wrapper) - dst = *found_dst_wrapper; const Nodes* dst_lexical_scope = find_scope_info(dst); - if (src_is_wrapper) { - // silent - } else if (!src_lexical_scope) { + if (!src_lexical_scope) { warn_print("Failed to find jump source node "); log_node(WARN, src); warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); diff --git a/src/frontend/llvm/l2s_private.h b/src/frontend/llvm/l2s_private.h index a4d42b09e..cec75ea2f 100644 --- a/src/frontend/llvm/l2s_private.h +++ b/src/frontend/llvm/l2s_private.h @@ -18,7 +18,6 @@ typedef struct { LLVMContextRef ctx; struct Dict* map; struct Dict* annotations; - struct Dict* wrappers_map; Arena* annotations_arena; LLVMModuleRef src; Module* dst; From ecc31d0ced7e1108bfca827eaf7a7986604884fe Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 21 Aug 2024 10:14:02 +0200 Subject: [PATCH 518/693] l2s: refactor the control wrapping code to make decisions prior to rewriting --- src/frontend/llvm/l2s_postprocess.c | 254 +++++++++++++++------------- src/shady/analysis/cfg.c | 9 +- src/shady/analysis/cfg.h | 1 + 3 files changed, 144 insertions(+), 120 deletions(-) diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 98b44d10a..00619d6c8 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -2,7 +2,9 @@ #include "portability.h" #include "dict.h" +#include "list.h" #include "log.h" +#include "arena.h" #include "../shady/rewrite.h" #include "../shady/type.h" @@ -14,9 +16,9 @@ typedef struct { Rewriter rewriter; const CompilerConfig* config; Parser* p; - CFG* cfg; - const Node* old_fn_or_bb; + Arena* arena; struct Dict* controls; + struct Dict* jump2wrapper; } Context; typedef struct { @@ -42,39 +44,49 @@ static Nodes remake_params(Context* ctx, Nodes old) { return nodes(a, old.count, nvars); } -static void initialize_controls(Context* ctx, Controls* controls, const Node* fn_or_bb) { +static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { + Controls** found = find_value_dict(const Node, Controls*, ctx->controls, fn_or_bb); + if (found) + return *found; IrArena* a = ctx->rewriter.dst_arena; + Controls* controls = arena_alloc(ctx->arena, sizeof(Controls)); *controls = (Controls) { .destinations = empty(a), .tokens = empty(a), }; insert_dict(const Node*, Controls*, ctx->controls, fn_or_bb, controls); + return controls; } -static void wrap_in_controls(Context* ctx, Controls* controls, Node* nabs, const Node* oabs) { +static void wrap_in_controls(Context* ctx, Node* nabs, const Node* oabs) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; const Node* obody = get_abstraction_body(oabs); if (!obody) return; - // const Node* mem = get_abstraction_mem(nabs); - Node* c = case_(a, empty(a)); - register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); - set_abstraction_body(c, rewrite_node(r, obody)); - for (size_t i = 0; i < controls->destinations.count; i++) { - const Node* token = controls->tokens.nodes[i]; - const Node* dst = controls->destinations.nodes[i]; - Node* control_case = case_(a, singleton(token)); - set_abstraction_body(control_case, jump_helper(a, c, empty(a), get_abstraction_mem(control_case))); - Node* c2 = case_(a, empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); - Nodes results = gen_control(bb, get_param_types(a, get_abstraction_params(dst)), control_case); - set_abstraction_body(c2, finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results, bb_mem(bb)))); - c = c2; + Controls** found = find_value_dict(const Node, Controls*, ctx->controls, oabs); + if (found) { + Controls* controls = *found; + Node* c = case_(a, empty(a)); + register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); + set_abstraction_body(c, rewrite_node(r, obody)); + for (size_t i = 0; i < controls->destinations.count; i++) { + const Node* token = controls->tokens.nodes[i]; + const Node* dst = controls->destinations.nodes[i]; + Node* control_case = case_(a, singleton(token)); + set_abstraction_body(control_case, jump_helper(a, c, empty(a), get_abstraction_mem(control_case))); + + Node* c2 = case_(a, empty(a)); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); + Nodes results = gen_control(bb, get_param_types(a, get_abstraction_params(dst)), control_case); + set_abstraction_body(c2, finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results, bb_mem(bb)))); + c = c2; + } + const Node* body = jump_helper(a, c, empty(a), get_abstraction_mem(nabs)); + return set_abstraction_body(nabs, body); } - const Node* body = jump_helper(a, c, empty(a), get_abstraction_mem(nabs)); - return set_abstraction_body(nabs, body); + return set_abstraction_body(nabs, rewrite_node(r, obody)); } KeyHash hash_node(Node**); @@ -90,8 +102,6 @@ bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { return true; } -bool compare_nodes(Nodes* a, Nodes* b); - static const Nodes* find_scope_info(const Node* abs) { assert(is_abstraction(abs)); const Node* terminator = get_abstraction_body(abs); @@ -106,7 +116,96 @@ static const Nodes* find_scope_info(const Node* abs) { return info; } -static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, const Node* node) { +bool compare_nodes(Nodes* a, Nodes* b); + +static void process_edge(Context* ctx, CFG* cfg, CFEdge edge) { + assert(edge.type == JumpEdge && edge.jump); + const Node* src = edge.src->node; + const Node* dst = edge.dst->node; + + IrArena* a = ctx->rewriter.dst_arena; + // if (!ctx->config->hacks.recover_structure) + // break; + const Nodes* src_lexical_scope = find_scope_info(src); + const Nodes* dst_lexical_scope = find_scope_info(dst); + if (!src_lexical_scope) { + warn_print("Failed to find jump source node "); + log_node(WARN, src); + warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); + } else if (!dst_lexical_scope) { + warn_print("Failed to find jump target node "); + log_node(WARN, dst); + warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); + } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { + debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name_safe(src), get_abstraction_name_safe(dst)); + + CFNode* src_cfnode = cfg_lookup(cfg, src); + assert(src_cfnode->node); + CFNode* target_cfnode = cfg_lookup(cfg, dst); + assert(src_cfnode && target_cfnode); + CFNode* dom = src_cfnode->idom; + while (dom) { + debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); + Nodes* dom_lexical_scope = find_scope_info(dom->node); + if (!dom_lexical_scope) { + warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); + dom = dom->idom; + continue; + } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { + error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); + } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { + debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); + + Controls* controls = get_or_create_controls(ctx, dom->node); + const Node* join_token = NULL; + for (size_t i = 0; i < controls->destinations.count; i++) { + if (controls->destinations.nodes[i] == dst) { + join_token = controls->tokens.nodes[i]; + break; + } + } + + if (!join_token) { + const Type* jp_type = join_point_type(a, (JoinPointType) { + .yield_types = get_param_types(a, get_abstraction_params(dst)) + }); + join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); + controls->tokens = append_nodes(a, controls->tokens, join_token); + controls->destinations = append_nodes(a, controls->destinations, dst); + } + Nodes nparams = remake_params(ctx, get_abstraction_params(dst)); + register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); + + Node* wrapper = basic_block(a, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); + wrapper->payload.basic_block.body = join(a, (Join) { + .args = nparams, + .join_point = join_token, + .mem = get_abstraction_mem(wrapper), + }); + + insert_dict(const Node*, const Node*, ctx->jump2wrapper, edge.jump, wrapper); + // return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); + } else { + dom = dom->idom; + continue; + } + break; + } + } +} + +static void prepare_function(Context* ctx, const Node* old_fn) { + CFG* cfg = build_fn_cfg(old_fn); + for (size_t i = 0; i < cfg->size; i++) { + CFNode* n = cfg->rpo[i]; + for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { + process_edge(ctx, cfg, read_list(CFEdge, n->succ_edges)[j]); + } + } + destroy_cfg(cfg); +} + +static const Node* process_node(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (node->tag) { @@ -122,12 +221,9 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, return new; } case Function_TAG: { - Context fn_ctx = *ctx; - fn_ctx.cfg = build_fn_cfg(node); - fn_ctx.old_fn_or_bb = node; - Controls controls; - initialize_controls(ctx, &controls, node); - Nodes new_params = remake_params(&fn_ctx, node->payload.fun.params); + prepare_function(ctx, node); + + Nodes new_params = remake_params(ctx, node->payload.fun.params); Nodes old_annotations = node->payload.fun.annotations; ParsedAnnotation* an = find_annotation(ctx->p, node); Op primop_intrinsic = PRIMOPS_COUNT; @@ -151,8 +247,8 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, old_annotations = append_nodes(a, old_annotations, an->payload); an = an->next; } - register_processed_list(&fn_ctx.rewriter, node->payload.fun.params, new_params); - Nodes new_annotations = rewrite_nodes(&fn_ctx.rewriter, old_annotations); + register_processed_list(r, node->payload.fun.params, new_params); + Nodes new_annotations = rewrite_nodes(r, old_annotations); Node* decl = function(ctx->rewriter.dst_module, new_params, get_abstraction_name(node), new_annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); register_processed(&ctx->rewriter, node, decl); if (primop_intrinsic != PRIMOPS_COUNT) { @@ -161,23 +257,19 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, .mem = get_abstraction_mem(decl), })); } else - wrap_in_controls(&fn_ctx, &controls, decl, node); - destroy_cfg(fn_ctx.cfg); + wrap_in_controls(ctx, decl, node); return decl; } case BasicBlock_TAG: { - Context bb_ctx = *ctx; - bb_ctx.old_fn_or_bb = node; - Controls controls; - initialize_controls(ctx, &controls, node); Nodes nparams = remake_params(ctx, get_abstraction_params(node)); register_processed_list(r, get_abstraction_params(node), nparams); Node* new_bb = (Node*) basic_block(a, nparams, get_abstraction_name_unsafe(node)); register_processed(r, node, new_bb); - wrap_in_controls(&bb_ctx, &controls, new_bb, node); + wrap_in_controls(ctx, new_bb, node); // new_bb->payload.basic_block.body = wrap_in_controls(ctx, &controls, new_bb->payload.basic_block.body); return new_bb; } + // Eliminate now-useless scope instructions case ExtInstr_TAG: { if (strcmp(node->payload.ext_instr.set, "shady.scope") == 0) { return rewrite_node(r, node->payload.ext_instr.mem); @@ -185,79 +277,9 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, break; } case Jump_TAG: { - const Node* src = ctx->old_fn_or_bb; - const Node* dst = node->payload.jump.target; - assert(src && dst); - rewrite_node(&ctx->rewriter, dst); - - if (!ctx->config->hacks.recover_structure) - break; - const Nodes* src_lexical_scope = find_scope_info(src); - const Nodes* dst_lexical_scope = find_scope_info(dst); - if (!src_lexical_scope) { - warn_print("Failed to find jump source node "); - log_node(WARN, src); - warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); - } else if (!dst_lexical_scope) { - warn_print("Failed to find jump target node "); - log_node(WARN, dst); - warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); - } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { - debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name_safe(src), get_abstraction_name_safe(dst)); - - CFNode* src_cfnode = cfg_lookup(ctx->cfg, src); - assert(src_cfnode->node); - CFNode* target_cfnode = cfg_lookup(ctx->cfg, dst); - assert(src_cfnode && target_cfnode); - CFNode* dom = src_cfnode->idom; - while (dom) { - debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); - Nodes* dom_lexical_scope = find_scope_info(dom->node); - if (!dom_lexical_scope) { - warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); - dom = dom->idom; - continue; - } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { - error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); - } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { - debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); - Controls** found = find_value_dict(const Node, Controls*, ctx->controls, dom->node); - if (found) { - Controls* controls = *found; - const Node* join_token = NULL; - for (size_t i = 0; i < controls->destinations.count; i++) { - if (controls->destinations.nodes[i] == dst) { - join_token = controls->tokens.nodes[i]; - break; - } - } - if (!join_token) { - const Type* jp_type = join_point_type(a, (JoinPointType) { - .yield_types = get_param_types(a, get_abstraction_params(dst)) - }); - join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); - controls->tokens = append_nodes(a, controls->tokens, join_token); - controls->destinations = append_nodes(a, controls->destinations, dst); - } - Nodes nparams = remake_params(ctx, get_abstraction_params(dst)); - register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); - Node* wrapper = basic_block(a, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); - wrapper->payload.basic_block.body = join(a, (Join) { - .args = nparams, - .join_point = join_token, - .mem = get_abstraction_mem(wrapper), - }); - return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); - } else { - assert(false); - } - } else { - dom = dom->idom; - continue; - } - break; - } - } + const Node** found = find_value_dict(const Node*, const Node*, ctx->jump2wrapper, node); + if (found) + return jump_helper(a, *found, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); break; } case GlobalVariable_TAG: { @@ -300,22 +322,22 @@ static const Node* process_op(Context* ctx, NodeClass op_class, String op_name, return recreate_node_identity(&ctx->rewriter, node); } -static const Node* process_node(Context* ctx, const Node* old) { - return process_op(ctx, 0, NULL, old); -} - void postprocess(Parser* p, Module* src, Module* dst) { assert(src != dst); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = p->config, .p = p, + .arena = new_arena(), .controls = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), + .jump2wrapper = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), }; - ctx.rewriter.rewrite_op_fn = (RewriteOpFn) process_op; + ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; rewrite_module(&ctx.rewriter); destroy_dict(ctx.controls); + destroy_dict(ctx.jump2wrapper); + destroy_arena(ctx.arena); destroy_rewriter(&ctx.rewriter); } diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index dd0b26881..a2dffdf32 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -103,7 +103,7 @@ static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { } /// Adds an edge to somewhere inside a basic block -static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFEdgeType type) { +static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFEdgeType type, const Node* j) { assert(is_abstraction(src) && is_abstraction(dst)); assert(!is_function(dst)); if (ctx->lt && !in_loop(ctx->lt, ctx->entry, dst)) @@ -118,13 +118,14 @@ static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFE .type = type, .src = src_node, .dst = dst_node, + .jump = j, }; append_list(CFEdge, src_node->succ_edges, edge); append_list(CFEdge, dst_node->pred_edges, edge); } static void add_structural_dominance_edge(CfgBuildContext* ctx, CFNode* parent, const Node* dst, CFEdgeType type) { - add_edge(ctx, parent->node, dst, type); + add_edge(ctx, parent->node, dst, type, NULL); insert_set_get_result(const Node*, parent->structurally_dominates, dst); } @@ -132,7 +133,7 @@ static void add_jump_edge(CfgBuildContext* ctx, const Node* src, const Node* j) assert(j->tag == Jump_TAG); const Node* target = j->payload.jump.target; if (target->tag == BasicBlock_TAG) - add_edge(ctx, src, target, JumpEdge); + add_edge(ctx, src, target, JumpEdge, j); } #pragma GCC diagnostic error "-Wswitch" @@ -164,7 +165,7 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { case Join_TAG: { CFNode** dst = find_value_dict(const Node*, CFNode*, ctx->join_point_values, terminator->payload.join.join_point); if (dst) - add_edge(ctx, node->node, (*dst)->node, StructuredLeaveBodyEdge); + add_edge(ctx, node->node, (*dst)->node, StructuredLeaveBodyEdge, NULL); return; } case If_TAG: diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index 5e6a35ad8..05aa9ec99 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -20,6 +20,7 @@ typedef struct { CFEdgeType type; CFNode* src; CFNode* dst; + const Node* jump; } CFEdge; struct CFNode_ { From 0c605f4494ffdaa03af850051f1a96ed1600b14d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 21 Aug 2024 11:13:02 +0200 Subject: [PATCH 519/693] l2s: rewrite according to domtree --- src/frontend/llvm/l2s_postprocess.c | 61 +++++++++++++++++++---------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 00619d6c8..9581ad348 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -10,6 +10,8 @@ #include "../shady/type.h" #include "../shady/ir_private.h" #include "../shady/analysis/cfg.h" +#include "../shady/analysis/scheduler.h" +#include "../shady/analysis/free_frontier.h" #include "../shady/transform/ir_gen_helpers.h" typedef struct { @@ -58,19 +60,40 @@ static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { return controls; } -static void wrap_in_controls(Context* ctx, Node* nabs, const Node* oabs) { +static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oabs) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; const Node* obody = get_abstraction_body(oabs); if (!obody) return; + CFNode* n = cfg_lookup(cfg, oabs); + size_t num_dom = entries_count_list(n->dominates); + LARRAY(Node*, nbbs, num_dom); + for (size_t i = 0; i < num_dom; i++) { + CFNode* dominated = read_list(CFNode*, n->dominates)[i]; + const Node* obb = dominated->node; + assert(obb->tag == BasicBlock_TAG); + Nodes nparams = remake_params(ctx, get_abstraction_params(obb)); + register_processed_list(r, get_abstraction_params(obb), nparams); + nbbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(obb)); + register_processed(r, obb, nbbs[i]); + } + + // We introduce a dummy case now because we don't know yet whether the body of the abstraction will be wrapped + Node* c = case_(a, empty(a)); + register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); + + for (size_t i = 0; i < num_dom; i++) { + CFNode* dominated = read_list(CFNode*, n->dominates)[i]; + const Node* obb = dominated->node; + wrap_in_controls(ctx, cfg, nbbs[i], obb); + } + + set_abstraction_body(c, rewrite_node(r, obody)); Controls** found = find_value_dict(const Node, Controls*, ctx->controls, oabs); if (found) { Controls* controls = *found; - Node* c = case_(a, empty(a)); - register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); - set_abstraction_body(c, rewrite_node(r, obody)); for (size_t i = 0; i < controls->destinations.count; i++) { const Node* token = controls->tokens.nodes[i]; const Node* dst = controls->destinations.nodes[i]; @@ -83,10 +106,10 @@ static void wrap_in_controls(Context* ctx, Node* nabs, const Node* oabs) { set_abstraction_body(c2, finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results, bb_mem(bb)))); c = c2; } - const Node* body = jump_helper(a, c, empty(a), get_abstraction_mem(nabs)); - return set_abstraction_body(nabs, body); } - return set_abstraction_body(nabs, rewrite_node(r, obody)); + + const Node* body = jump_helper(a, c, empty(a), get_abstraction_mem(nabs)); + set_abstraction_body(nabs, body); } KeyHash hash_node(Node**); @@ -118,7 +141,7 @@ static const Nodes* find_scope_info(const Node* abs) { bool compare_nodes(Nodes* a, Nodes* b); -static void process_edge(Context* ctx, CFG* cfg, CFEdge edge) { +static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge edge) { assert(edge.type == JumpEdge && edge.jump); const Node* src = edge.src->node; const Node* dst = edge.dst->node; @@ -194,15 +217,15 @@ static void process_edge(Context* ctx, CFG* cfg, CFEdge edge) { } } -static void prepare_function(Context* ctx, const Node* old_fn) { - CFG* cfg = build_fn_cfg(old_fn); +static void prepare_function(Context* ctx, CFG* cfg, const Node* old_fn) { + Scheduler* scheduler = new_scheduler(cfg); for (size_t i = 0; i < cfg->size; i++) { CFNode* n = cfg->rpo[i]; for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { - process_edge(ctx, cfg, read_list(CFEdge, n->succ_edges)[j]); + process_edge(ctx, cfg, scheduler, read_list(CFEdge, n->succ_edges)[j]); } } - destroy_cfg(cfg); + destroy_scheduler(scheduler); } static const Node* process_node(Context* ctx, const Node* node) { @@ -221,7 +244,8 @@ static const Node* process_node(Context* ctx, const Node* node) { return new; } case Function_TAG: { - prepare_function(ctx, node); + CFG* cfg = build_fn_cfg(node); + prepare_function(ctx, cfg, node); Nodes new_params = remake_params(ctx, node->payload.fun.params); Nodes old_annotations = node->payload.fun.annotations; @@ -257,17 +281,12 @@ static const Node* process_node(Context* ctx, const Node* node) { .mem = get_abstraction_mem(decl), })); } else - wrap_in_controls(ctx, decl, node); + wrap_in_controls(ctx, cfg, decl, node); + destroy_cfg(cfg); return decl; } case BasicBlock_TAG: { - Nodes nparams = remake_params(ctx, get_abstraction_params(node)); - register_processed_list(r, get_abstraction_params(node), nparams); - Node* new_bb = (Node*) basic_block(a, nparams, get_abstraction_name_unsafe(node)); - register_processed(r, node, new_bb); - wrap_in_controls(ctx, new_bb, node); - // new_bb->payload.basic_block.body = wrap_in_controls(ctx, &controls, new_bb->payload.basic_block.body); - return new_bb; + assert(false); } // Eliminate now-useless scope instructions case ExtInstr_TAG: { From 6aea21b8ef7f47200ccca5769801604506242360 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 21 Aug 2024 16:37:17 +0200 Subject: [PATCH 520/693] removed scope stuff from l2s_postprocess --- src/frontend/llvm/l2s_meta.c | 2 +- src/frontend/llvm/l2s_postprocess.c | 228 +--------------------------- 2 files changed, 8 insertions(+), 222 deletions(-) diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index 3554dbb8f..7dc7887b1 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -109,7 +109,7 @@ Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { while (true) { if (!scope) break; - str = prepend_nodes(a, str, convert_metadata(p, scope)); + str = prepend_nodes(a, str, uint32_literal(a, convert_metadata(p, scope)->id)); // LLVMDumpValue(LLVMMetadataAsValue(p->ctx, scope)); // printf("\n"); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 9581ad348..c9d40558f 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -8,25 +8,17 @@ #include "../shady/rewrite.h" #include "../shady/type.h" -#include "../shady/ir_private.h" -#include "../shady/analysis/cfg.h" -#include "../shady/analysis/scheduler.h" -#include "../shady/analysis/free_frontier.h" -#include "../shady/transform/ir_gen_helpers.h" + +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); typedef struct { Rewriter rewriter; const CompilerConfig* config; Parser* p; Arena* arena; - struct Dict* controls; - struct Dict* jump2wrapper; } Context; -typedef struct { - Nodes tokens, destinations; -} Controls; - static Nodes remake_params(Context* ctx, Nodes old) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; @@ -46,188 +38,6 @@ static Nodes remake_params(Context* ctx, Nodes old) { return nodes(a, old.count, nvars); } -static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { - Controls** found = find_value_dict(const Node, Controls*, ctx->controls, fn_or_bb); - if (found) - return *found; - IrArena* a = ctx->rewriter.dst_arena; - Controls* controls = arena_alloc(ctx->arena, sizeof(Controls)); - *controls = (Controls) { - .destinations = empty(a), - .tokens = empty(a), - }; - insert_dict(const Node*, Controls*, ctx->controls, fn_or_bb, controls); - return controls; -} - -static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oabs) { - Rewriter* r = &ctx->rewriter; - IrArena* a = r->dst_arena; - const Node* obody = get_abstraction_body(oabs); - if (!obody) - return; - - CFNode* n = cfg_lookup(cfg, oabs); - size_t num_dom = entries_count_list(n->dominates); - LARRAY(Node*, nbbs, num_dom); - for (size_t i = 0; i < num_dom; i++) { - CFNode* dominated = read_list(CFNode*, n->dominates)[i]; - const Node* obb = dominated->node; - assert(obb->tag == BasicBlock_TAG); - Nodes nparams = remake_params(ctx, get_abstraction_params(obb)); - register_processed_list(r, get_abstraction_params(obb), nparams); - nbbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(obb)); - register_processed(r, obb, nbbs[i]); - } - - // We introduce a dummy case now because we don't know yet whether the body of the abstraction will be wrapped - Node* c = case_(a, empty(a)); - register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); - - for (size_t i = 0; i < num_dom; i++) { - CFNode* dominated = read_list(CFNode*, n->dominates)[i]; - const Node* obb = dominated->node; - wrap_in_controls(ctx, cfg, nbbs[i], obb); - } - - set_abstraction_body(c, rewrite_node(r, obody)); - Controls** found = find_value_dict(const Node, Controls*, ctx->controls, oabs); - if (found) { - Controls* controls = *found; - for (size_t i = 0; i < controls->destinations.count; i++) { - const Node* token = controls->tokens.nodes[i]; - const Node* dst = controls->destinations.nodes[i]; - Node* control_case = case_(a, singleton(token)); - set_abstraction_body(control_case, jump_helper(a, c, empty(a), get_abstraction_mem(control_case))); - - Node* c2 = case_(a, empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); - Nodes results = gen_control(bb, get_param_types(a, get_abstraction_params(dst)), control_case); - set_abstraction_body(c2, finish_body(bb, jump_helper(a, rewrite_node(&ctx->rewriter, dst), results, bb_mem(bb)))); - c = c2; - } - } - - const Node* body = jump_helper(a, c, empty(a), get_abstraction_mem(nabs)); - set_abstraction_body(nabs, body); -} - -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); - -bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { - if (scope.count <= parentMaybe.count) - return false; - for (size_t i = 0; i < parentMaybe.count; i++) { - if (scope.nodes[i] != parentMaybe.nodes[i]) - return false; - } - return true; -} - -static const Nodes* find_scope_info(const Node* abs) { - assert(is_abstraction(abs)); - const Node* terminator = get_abstraction_body(abs); - const Node* mem = get_terminator_mem(terminator); - Nodes* info = NULL; - while (mem) { - if (mem->tag == ExtInstr_TAG && strcmp(mem->payload.ext_instr.set, "shady.scope") == 0) { - info = &mem->payload.ext_instr.operands; - } - mem = get_parent_mem(mem); - } - return info; -} - -bool compare_nodes(Nodes* a, Nodes* b); - -static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge edge) { - assert(edge.type == JumpEdge && edge.jump); - const Node* src = edge.src->node; - const Node* dst = edge.dst->node; - - IrArena* a = ctx->rewriter.dst_arena; - // if (!ctx->config->hacks.recover_structure) - // break; - const Nodes* src_lexical_scope = find_scope_info(src); - const Nodes* dst_lexical_scope = find_scope_info(dst); - if (!src_lexical_scope) { - warn_print("Failed to find jump source node "); - log_node(WARN, src); - warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); - } else if (!dst_lexical_scope) { - warn_print("Failed to find jump target node "); - log_node(WARN, dst); - warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); - } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { - debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name_safe(src), get_abstraction_name_safe(dst)); - - CFNode* src_cfnode = cfg_lookup(cfg, src); - assert(src_cfnode->node); - CFNode* target_cfnode = cfg_lookup(cfg, dst); - assert(src_cfnode && target_cfnode); - CFNode* dom = src_cfnode->idom; - while (dom) { - debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); - Nodes* dom_lexical_scope = find_scope_info(dom->node); - if (!dom_lexical_scope) { - warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); - dom = dom->idom; - continue; - } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { - error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); - } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { - debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); - - Controls* controls = get_or_create_controls(ctx, dom->node); - const Node* join_token = NULL; - for (size_t i = 0; i < controls->destinations.count; i++) { - if (controls->destinations.nodes[i] == dst) { - join_token = controls->tokens.nodes[i]; - break; - } - } - - if (!join_token) { - const Type* jp_type = join_point_type(a, (JoinPointType) { - .yield_types = get_param_types(a, get_abstraction_params(dst)) - }); - join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); - controls->tokens = append_nodes(a, controls->tokens, join_token); - controls->destinations = append_nodes(a, controls->destinations, dst); - } - Nodes nparams = remake_params(ctx, get_abstraction_params(dst)); - register_processed_list(&ctx->rewriter, get_abstraction_params(dst), nparams); - - Node* wrapper = basic_block(a, nparams, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); - wrapper->payload.basic_block.body = join(a, (Join) { - .args = nparams, - .join_point = join_token, - .mem = get_abstraction_mem(wrapper), - }); - - insert_dict(const Node*, const Node*, ctx->jump2wrapper, edge.jump, wrapper); - // return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); - } else { - dom = dom->idom; - continue; - } - break; - } - } -} - -static void prepare_function(Context* ctx, CFG* cfg, const Node* old_fn) { - Scheduler* scheduler = new_scheduler(cfg); - for (size_t i = 0; i < cfg->size; i++) { - CFNode* n = cfg->rpo[i]; - for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { - process_edge(ctx, cfg, scheduler, read_list(CFEdge, n->succ_edges)[j]); - } - } - destroy_scheduler(scheduler); -} - static const Node* process_node(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; @@ -244,9 +54,6 @@ static const Node* process_node(Context* ctx, const Node* node) { return new; } case Function_TAG: { - CFG* cfg = build_fn_cfg(node); - prepare_function(ctx, cfg, node); - Nodes new_params = remake_params(ctx, node->payload.fun.params); Nodes old_annotations = node->payload.fun.annotations; ParsedAnnotation* an = find_annotation(ctx->p, node); @@ -280,30 +87,13 @@ static const Node* process_node(Context* ctx, const Node* node) { .args = singleton(prim_op_helper(a, primop_intrinsic, empty(a), get_abstraction_params(decl))), .mem = get_abstraction_mem(decl), })); - } else - wrap_in_controls(ctx, cfg, decl, node); - destroy_cfg(cfg); + } else if (get_abstraction_body(node)) + set_abstraction_body(decl, rewrite_node(r, get_abstraction_body(node))); return decl; } - case BasicBlock_TAG: { - assert(false); - } - // Eliminate now-useless scope instructions - case ExtInstr_TAG: { - if (strcmp(node->payload.ext_instr.set, "shady.scope") == 0) { - return rewrite_node(r, node->payload.ext_instr.mem); - } - break; - } - case Jump_TAG: { - const Node** found = find_value_dict(const Node*, const Node*, ctx->jump2wrapper, node); - if (found) - return jump_helper(a, *found, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); - break; - } case GlobalVariable_TAG: { - if (lookup_annotation(node, "LLVMMetaData")) - return NULL; + // if (lookup_annotation(node, "LLVMMetaData")) + // return NULL; AddressSpace as = node->payload.global_variable.address_space; const Node* old_init = node->payload.global_variable.init; Nodes annotations = rewrite_nodes(r, node->payload.global_variable.annotations); @@ -348,15 +138,11 @@ void postprocess(Parser* p, Module* src, Module* dst) { .config = p->config, .p = p, .arena = new_arena(), - .controls = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), - .jump2wrapper = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), }; ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; rewrite_module(&ctx.rewriter); - destroy_dict(ctx.controls); - destroy_dict(ctx.jump2wrapper); destroy_arena(ctx.arena); destroy_rewriter(&ctx.rewriter); } From a45c6bd81b02e2046c39b49e9468b89bdd0a69ff Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 21 Aug 2024 16:37:40 +0200 Subject: [PATCH 521/693] added lift_everything pass --- src/shady/passes/lift_everything.c | 101 +++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/shady/passes/lift_everything.c diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c new file mode 100644 index 000000000..daf12926c --- /dev/null +++ b/src/shady/passes/lift_everything.c @@ -0,0 +1,101 @@ +#include "shady/pass.h" + +#include "../ir_private.h" +#include "../type.h" +#include "../transform/ir_gen_helpers.h" +#include "../analysis/cfg.h" +#include "../analysis/scheduler.h" +#include "../analysis/free_frontier.h" + +#include "log.h" +#include "dict.h" +#include "portability.h" + +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + + +typedef struct { + Rewriter rewriter; + struct Dict* lift; + CFG* cfg; + Scheduler* scheduler; +} Context; + +static const Node* process(Context* ctx, const Node* node) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + switch (node->tag) { + case Function_TAG: { + Context fn_ctx = *ctx; + fn_ctx.cfg = build_fn_cfg(node); + fn_ctx.scheduler = new_scheduler(fn_ctx.cfg); + + Node* new_fn = recreate_decl_header_identity(r, node); + recreate_decl_body_identity(&fn_ctx.rewriter, node, new_fn); + + destroy_scheduler(fn_ctx.scheduler); + destroy_cfg(fn_ctx.cfg); + return new_fn; + } + case BasicBlock_TAG: { + struct Dict* frontier = free_frontier(ctx->scheduler, ctx->cfg, node); + // insert_dict(const Node*, Dict*, ctx->lift, node, frontier); + + Nodes additional_args = empty(a); + Nodes new_params = recreate_params(r, get_abstraction_params(node)); + register_processed_list(r, get_abstraction_params(node), new_params); + size_t i = 0; + const Node* value; + + Context bb_ctx = *ctx; + bb_ctx.rewriter = create_children_rewriter(&ctx->rewriter); + + while (dict_iter(frontier, &i, &value, NULL)) { + if (is_value(value)) { + additional_args = append_nodes(a, additional_args, value); + const Type* t = rewrite_node(r, value->type); + const Node* p = param(a, t, NULL); + new_params = append_nodes(a, new_params, p); + register_processed(&bb_ctx.rewriter, value, p); + } + } + + destroy_dict(frontier); + insert_dict(const Node*, Nodes, ctx->lift, node, additional_args); + Node* new_bb = basic_block(a, new_params, get_abstraction_name_unsafe(node)); + register_processed(r, node, new_bb); + set_abstraction_body(new_bb, rewrite_node(&bb_ctx.rewriter, get_abstraction_body(node))); + return new_bb; + } + case Jump_TAG: { + Jump payload = node->payload.jump; + rewrite_node(r, payload.target); + + Nodes* additional_args = find_value_dict(const Node*, Nodes, ctx->lift, payload.target); + assert(additional_args); + return jump(a, (Jump) { + .mem = rewrite_node(r, payload.mem), + .target = rewrite_node(r, payload.target), + .args = concat_nodes(a, rewrite_nodes(r, payload.args), rewrite_nodes(r, *additional_args)) + }); + } + default: break; + } + + return recreate_node_identity(&ctx->rewriter, node); +} + +Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); + Module* dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .lift = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), + }; + rewrite_module(&ctx.rewriter); + destroy_dict(ctx.lift); + destroy_rewriter(&ctx.rewriter); + return dst; +} From 1278dd7a2168b7a091270e7dd99cffcf0d8f2901 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 21 Aug 2024 16:37:56 +0200 Subject: [PATCH 522/693] added a pass turning shady.scope into control blocks --- src/shady/passes/scope2control.c | 329 +++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 src/shady/passes/scope2control.c diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c new file mode 100644 index 000000000..ab2fe0509 --- /dev/null +++ b/src/shady/passes/scope2control.c @@ -0,0 +1,329 @@ +#include "shady/pass.h" + +#include "portability.h" +#include "dict.h" +#include "list.h" +#include "log.h" +#include "arena.h" +#include "util.h" + +#include "../rewrite.h" +#include "../type.h" +#include "../ir_private.h" +#include "../analysis/cfg.h" +#include "../analysis/scheduler.h" +#include "../analysis/free_frontier.h" +#include "../transform/ir_gen_helpers.h" + +#include + +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + +typedef struct { + Rewriter rewriter; + const CompilerConfig* config; + Arena* arena; + struct Dict* controls; + struct Dict* jump2wrapper; +} Context; + +typedef struct { + const Node* wrapper; +} Wrapped; + +typedef struct { + Node* wrapper; + const Node* token; + const Node* destination; +} AddControl; + +typedef struct { + struct Dict* control_destinations; +} Controls; + +static Nodes remake_params(Context* ctx, Nodes old) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + LARRAY(const Node*, nvars, old.count); + for (size_t i = 0; i < old.count; i++) { + const Node* node = old.nodes[i]; + const Type* t = NULL; + if (node->payload.param.type) { + if (node->payload.param.type->tag == QualifiedType_TAG) + t = rewrite_node(r, node->payload.param.type); + else + t = qualified_type_helper(rewrite_node(r, node->payload.param.type), false); + } + nvars[i] = param(a, t, node->payload.param.name); + assert(nvars[i]->tag == Param_TAG); + } + return nodes(a, old.count, nvars); +} + +/// Whether 'a' is dominated by 'b' +static bool is_dominated(CFNode* a, CFNode* b) { + while (a) { + if (a == b) + return true; + a = a->idom; + } + return false; +} + +static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { + Controls** found = find_value_dict(const Node, Controls*, ctx->controls, fn_or_bb); + if (found) + return *found; + IrArena* a = ctx->rewriter.dst_arena; + Controls* controls = arena_alloc(ctx->arena, sizeof(Controls)); + *controls = (Controls) { + .control_destinations = new_dict(const Node*, AddControl, (HashFn) hash_node, (CmpFn) compare_node), + }; + insert_dict(const Node*, Controls*, ctx->controls, fn_or_bb, controls); + return controls; +} + +static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oabs) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + const Node* obody = get_abstraction_body(oabs); + if (!obody) + return; + + CFNode* n = cfg_lookup(cfg, oabs); + size_t num_dom = entries_count_list(n->dominates); + LARRAY(Node*, nbbs, num_dom); + for (size_t i = 0; i < num_dom; i++) { + CFNode* dominated = read_list(CFNode*, n->dominates)[i]; + const Node* obb = dominated->node; + assert(obb->tag == BasicBlock_TAG); + Nodes nparams = remake_params(ctx, get_abstraction_params(obb)); + register_processed_list(r, get_abstraction_params(obb), nparams); + nbbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(obb)); + register_processed(r, obb, nbbs[i]); + } + + // We introduce a dummy case now because we don't know yet whether the body of the abstraction will be wrapped + Node* c = case_(a, empty(a)); + Node* oc = c; + register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); + + for (size_t k = 0; k < num_dom; k++) { + CFNode* dominated = read_list(CFNode*, n->dominates)[k]; + const Node* obb = dominated->node; + wrap_in_controls(ctx, cfg, nbbs[k], obb); + } + + Controls* controls = get_or_create_controls(ctx, oabs); + + set_abstraction_body(oc, rewrite_node(r, obody)); + + size_t i = 0; + AddControl add_control; + while(dict_iter(controls->control_destinations, &i, NULL, &add_control)) { + const Node* dst = add_control.destination; + Node* control_case = case_(a, singleton(add_control.token)); + set_abstraction_body(control_case, jump_helper(a, c, empty(a), get_abstraction_mem(control_case))); + + Node* c2 = case_(a, empty(a)); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); + const Type* jp_type = add_control.token->type; + deconstruct_qualified_type(&jp_type); + assert(jp_type->tag == JoinPointType_TAG); + Nodes results = gen_control(bb, jp_type->payload.join_point_type.yield_types, control_case); + + c = c2; + set_abstraction_body(c2, finish_body(bb, jump_helper(a, find_processed(r, dst), results, bb_mem(bb)))); + } + + const Node* body = jump_helper(a, c, empty(a), get_abstraction_mem(nabs)); + set_abstraction_body(nabs, body); +} + +bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { + if (scope.count <= parentMaybe.count) + return false; + for (size_t i = 0; i < parentMaybe.count; i++) { + if (scope.nodes[i] != parentMaybe.nodes[i]) + return false; + } + return true; +} + +static const Nodes* find_scope_info(const Node* abs) { + assert(is_abstraction(abs)); + const Node* terminator = get_abstraction_body(abs); + const Node* mem = get_terminator_mem(terminator); + Nodes* info = NULL; + while (mem) { + if (mem->tag == ExtInstr_TAG && strcmp(mem->payload.ext_instr.set, "shady.scope") == 0) { + if (!info || info->count > mem->payload.ext_instr.operands.count) + info = &mem->payload.ext_instr.operands; + } + mem = get_parent_mem(mem); + } + return info; +} + +bool compare_nodes(Nodes* a, Nodes* b); + +static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge edge) { + assert(edge.type == JumpEdge && edge.jump); + const Node* src = edge.src->node; + const Node* dst = edge.dst->node; + + Rewriter* r = &ctx->rewriter; + IrArena* a = ctx->rewriter.dst_arena; + // if (!ctx->config->hacks.recover_structure) + // break; + const Nodes* src_lexical_scope = find_scope_info(src); + const Nodes* dst_lexical_scope = find_scope_info(dst); + if (!src_lexical_scope) { + warn_print("Failed to find jump source node "); + log_node(WARN, src); + warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); + } else if (!dst_lexical_scope) { + warn_print("Failed to find jump target node "); + log_node(WARN, dst); + warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); + } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { + debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name_safe(src), get_abstraction_name_safe(dst)); + + CFNode* src_cfnode = cfg_lookup(cfg, src); + assert(src_cfnode->node); + CFNode* target_cfnode = cfg_lookup(cfg, dst); + assert(src_cfnode && target_cfnode); + CFNode* dom = src_cfnode->idom; + while (dom) { + debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); + Nodes* dom_lexical_scope = find_scope_info(dom->node); + if (!dom_lexical_scope) { + warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); + dom = dom->idom; + continue; + } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { + error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); + } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { + debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); + + Controls* controls = get_or_create_controls(ctx, dom->node); + AddControl* found = find_value_dict(const Node, AddControl, controls->control_destinations, dst); + Wrapped wrapped; + if (found) { + wrapped.wrapper = found->wrapper; + } else { + Nodes wrapper_params = remake_params(ctx, get_abstraction_params(dst)); + Nodes join_args = wrapper_params; + Nodes yield_types = rewrite_nodes(r, strip_qualifiers(a, get_param_types(a, get_abstraction_params(dst)))); + + const Type* jp_type = join_point_type(a, (JoinPointType) { + .yield_types = yield_types + }); + const Node* join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); + + Node* wrapper = basic_block(a, wrapper_params, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); + wrapper->payload.basic_block.body = join(a, (Join) { + .args = join_args, + .join_point = join_token, + .mem = get_abstraction_mem(wrapper), + }); + + AddControl add_control = { + .destination = dst, + .token = join_token, + .wrapper = wrapper, + }; + wrapped.wrapper = wrapper; + insert_dict(const Node*, AddControl, controls->control_destinations, dst, add_control); + } + + insert_dict(const Node*, Wrapped, ctx->jump2wrapper, edge.jump, wrapped); + // return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); + } else { + dom = dom->idom; + continue; + } + break; + } + } +} + +static void prepare_function(Context* ctx, CFG* cfg, const Node* old_fn) { + Scheduler* scheduler = new_scheduler(cfg); + for (size_t i = 0; i < cfg->size; i++) { + CFNode* n = cfg->rpo[i]; + for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { + process_edge(ctx, cfg, scheduler, read_list(CFEdge, n->succ_edges)[j]); + } + } + destroy_scheduler(scheduler); +} + +static const Node* process_node(Context* ctx, const Node* node) { + IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + switch (node->tag) { + case Function_TAG: { + CFG* cfg = build_fn_cfg(node); + prepare_function(ctx, cfg, node); + Node* decl = recreate_decl_header_identity(r, node); + wrap_in_controls(ctx, cfg, decl, node); + destroy_cfg(cfg); + return decl; + } + case BasicBlock_TAG: { + assert(false); + } + // Eliminate now-useless scope instructions + case ExtInstr_TAG: { + if (strcmp(node->payload.ext_instr.set, "shady.scope") == 0) { + return rewrite_node(r, node->payload.ext_instr.mem); + } + break; + } + case Jump_TAG: { + Wrapped* found = find_value_dict(const Node*, Wrapped, ctx->jump2wrapper, node); + if (found) + return jump_helper(a, found->wrapper, rewrite_nodes(r, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); + break; + } + default: break; + } + + return recreate_node_identity(&ctx->rewriter, node); +} + +Module* scope2control(const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); + Module* dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .config = config, + .arena = new_arena(), + .controls = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), + .jump2wrapper = new_dict(const Node*, Wrapped, (HashFn) hash_node, (CmpFn) compare_node), + }; + + ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; + + size_t i = 0; + Controls controls; + while (dict_iter(ctx.controls, &i, NULL, &controls)) { + size_t j = 0; + AddControl add_control; + // while (dict_iter(controls.control_destinations, &j, NULL, &add_control)) { + // destroy_list(add_control.lift); + // } + destroy_dict(controls.control_destinations); + } + + rewrite_module(&ctx.rewriter); + destroy_dict(ctx.controls); + destroy_dict(ctx.jump2wrapper); + destroy_arena(ctx.arena); + destroy_rewriter(&ctx.rewriter); + + return dst; +} From 9e633b773d2fc16764bc2cb1699e0e2afdbd0422 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 21 Aug 2024 18:29:10 +0200 Subject: [PATCH 523/693] re-engineered CFG analysis 'works' --- include/shady/config.h | 4 + src/backend/spirv/emit_spv.c | 2 +- src/shady/analysis/cfg.c | 167 +++++++++++++++++------ src/shady/analysis/cfg.h | 32 ++++- src/shady/analysis/cfg_dump.c | 11 +- src/shady/analysis/free_frontier.c | 15 +- src/shady/analysis/looptree.c | 2 +- src/shady/analysis/scheduler.c | 13 +- src/shady/analysis/verify.c | 4 +- src/shady/compile.c | 5 + src/shady/passes/CMakeLists.txt | 2 + src/shady/passes/lift_everything.c | 7 + src/shady/passes/lift_indirect_targets.c | 1 + src/shady/passes/passes.h | 3 + src/shady/passes/scope2control.c | 10 -- src/shady/type.c | 27 +++- test/vcc/loop_closed.c | 11 +- vcc/vcc_lib.c | 1 + 18 files changed, 219 insertions(+), 98 deletions(-) diff --git a/include/shady/config.h b/include/shady/config.h index cf245efc0..35ace8a7a 100644 --- a/include/shady/config.h +++ b/include/shady/config.h @@ -65,6 +65,10 @@ struct CompilerConfig_ { uint8_t minor; } target_spirv_version; + struct { + bool has_scope_annotations; + } input_cf; + struct { bool emulate_generic_ptrs; bool emulate_physical_memory; diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index e6ecbe866..893945068 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -107,7 +107,7 @@ static void emit_function(Emitter* emitter, const Node* node) { if (node->payload.fun.body) { // reserve a bunch of identifiers for the basic blocks in the CFG for (size_t i = 0; i < fn_builder.cfg->size; i++) { - CFNode* cfnode = read_list(CFNode*, fn_builder.cfg->contents)[i]; + CFNode* cfnode = fn_builder.cfg->rpo[i]; assert(cfnode); const Node* bb = cfnode->node; assert(is_basic_block(bb) || bb == node); diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index a2dffdf32..bdca321cc 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -14,14 +14,14 @@ #pragma GCC diagnostic error "-Wswitch" -struct List* build_cfgs(Module* mod) { +struct List* build_cfgs(Module* mod, CFGBuildConfig config) { struct List* cfgs = new_list(CFG*); Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag != Function_TAG) continue; - CFG* cfg = build_fn_cfg(decl); + CFG* cfg = build_cfg(decl, decl, config); append_list(CFG*, cfgs, cfg); } @@ -37,12 +37,19 @@ typedef struct { const Node* entry; LoopTree* lt; struct Dict* nodes; - struct List* queue; struct List* contents; + bool include_structured_tails; + + const Node* selection_construct_tail; + const Node* loop_construct_head; + const Node* loop_construct_tail; + struct Dict* join_point_values; } CfgBuildContext; +static void process_cf_node(CfgBuildContext* ctx, CFNode* node); + CFNode* cfg_lookup(CFG* cfg, const Node* abs) { CFNode** found = find_value_dict(const Node*, CFNode*, cfg->map, abs); if (found) { @@ -78,7 +85,7 @@ static CFNode* get_or_enqueue(CfgBuildContext* ctx, const Node* abs) { new->node = abs; assert(abs && new->node); insert_dict(const Node*, CFNode*, ctx->nodes, abs, new); - append_list(Node*, ctx->queue, new); + process_cf_node(ctx, new); append_list(Node*, ctx->contents, new); return new; } @@ -163,38 +170,63 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { return; } case Join_TAG: { - CFNode** dst = find_value_dict(const Node*, CFNode*, ctx->join_point_values, terminator->payload.join.join_point); + const Node** dst = find_value_dict(const Node*, const Node*, ctx->join_point_values, terminator->payload.join.join_point); if (dst) - add_edge(ctx, node->node, (*dst)->node, StructuredLeaveBodyEdge, NULL); + add_edge(ctx, node->node, *dst, StructuredLeaveBodyEdge, NULL); return; } - case If_TAG: - add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); + case If_TAG: { + CfgBuildContext if_ctx = *ctx; + if_ctx.selection_construct_tail = get_structured_construct_tail(terminator); + add_structural_dominance_edge(&if_ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); if (terminator->payload.if_instr.if_false) - add_structural_dominance_edge(ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + add_structural_dominance_edge(&if_ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge); + else + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredLeaveBodyEdge); + + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; - case Match_TAG: + } case Match_TAG: { + CfgBuildContext match_ctx = *ctx; + match_ctx.selection_construct_tail = get_structured_construct_tail(terminator); for (size_t i = 0; i < terminator->payload.match_instr.cases.count; i++) - add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + add_structural_dominance_edge(&match_ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); + add_structural_dominance_edge(&match_ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; - case Loop_TAG: - add_structural_dominance_edge(ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + } case Loop_TAG: { + CfgBuildContext loop_ctx = *ctx; + loop_ctx.loop_construct_head = terminator->payload.loop_instr.body; + loop_ctx.loop_construct_tail = get_structured_construct_tail(terminator); + add_structural_dominance_edge(&loop_ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; - case Control_TAG: - add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); + } case Control_TAG: { const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); - CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); - insert_dict(const Node*, CFNode*, ctx->join_point_values, param, let_tail_cfnode); - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + //CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); + const Node* tail = get_structured_construct_tail(terminator); + insert_dict(const Node*, const Node*, ctx->join_point_values, param, tail); + add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + return; + } case MergeSelection_TAG: { + assert(ctx->selection_construct_tail); + add_structural_dominance_edge(ctx, node, ctx->selection_construct_tail, StructuredLeaveBodyEdge); + return; + } + case MergeContinue_TAG:{ + assert(ctx->loop_construct_head); + add_structural_dominance_edge(ctx, node, ctx->loop_construct_head, StructuredLoopContinue); return; - case MergeSelection_TAG: - case MergeContinue_TAG: + } case MergeBreak_TAG: { - return; // TODO i guess + assert(ctx->loop_construct_tail); + add_structural_dominance_edge(ctx, node, ctx->loop_construct_tail, StructuredLeaveBodyEdge); + return; } case TailCall_TAG: case Return_TAG: @@ -284,6 +316,8 @@ static void validate_cfg(CFG* cfg) { case JumpEdge: num_jumps++; break; + case StructuredLoopContinue: + break; case StructuredEnterBodyEdge: structured_body_uses += 1; break; @@ -315,7 +349,19 @@ static void validate_cfg(CFG* cfg) { } } -CFG* build_cfg(const Node* function, const Node* entry, LoopTree* lt, bool flipped) { +static void mark_reachable(CFNode* n) { + if (!n->reachable) { + n->reachable = true; + for (size_t i = 0; i < entries_count_list(n->succ_edges); i++) { + CFEdge e = read_list(CFEdge, n->succ_edges)[i]; + if (e.type == StructuredTailEdge) + continue; + mark_reachable(e.dst); + } + } +} + +CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { assert(function && function->tag == Function_TAG); assert(is_abstraction(entry)); Arena* arena = new_arena(); @@ -324,29 +370,31 @@ CFG* build_cfg(const Node* function, const Node* entry, LoopTree* lt, bool flipp .arena = arena, .function = function, .entry = entry, - .lt = lt, + .lt = config.lt, .nodes = new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), - .join_point_values = new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), - .queue = new_list(CFNode*), + .join_point_values = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), .contents = new_list(CFNode*), + .include_structured_tails = config.include_structured_tails, }; CFNode* entry_node = get_or_enqueue(&context, entry); + mark_reachable(entry_node); + //process_cf_node(&context, entry_node); - while (entries_count_list(context.queue) > 0) { - CFNode* this = pop_last_list(CFNode*, context.queue); - process_cf_node(&context, this); - } + //while (entries_count_list(context.queue) > 0) { + // CFNode* this = pop_last_list(CFNode*, context.queue); + // process_cf_node(&context, this); + //} - destroy_list(context.queue); destroy_dict(context.join_point_values); CFG* cfg = calloc(sizeof(CFG), 1); *cfg = (CFG) { .arena = arena, + .config = config, .entry = entry_node, .size = entries_count_list(context.contents), - .flipped = flipped, + .flipped = config.flipped, .contents = context.contents, .map = context.nodes, .rpo = NULL @@ -354,7 +402,7 @@ CFG* build_cfg(const Node* function, const Node* entry, LoopTree* lt, bool flipp validate_cfg(cfg); - if (flipped) + if (config.flipped) flip_cfg(cfg); compute_rpo(cfg); @@ -395,7 +443,7 @@ static size_t post_order_visit(CFG* cfg, CFNode* n, size_t i) { for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { CFEdge edge = read_list(CFEdge, n->succ_edges)[j]; // always visit structured tail edges last - if ((edge.type == StructuredTailEdge) == (phase == 1)) + if ((edge.type == StructuredTailEdge) == (phase == 0)) continue; if (edge.dst->rpo_index == SIZE_MAX) i = post_order_visit(cfg, edge.dst, i); @@ -408,8 +456,16 @@ static size_t post_order_visit(CFG* cfg, CFNode* n, size_t i) { } void compute_rpo(CFG* cfg) { + /*cfg->reachable_size = 0; + for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { + CFNode* n = read_list(CFNode*, cfg->contents)[i]; + if (n->reachable) + cfg->reachable_size++; + }*/ + cfg->reachable_size = cfg->size; + cfg->rpo = malloc(sizeof(const CFNode*) * cfg->size); - size_t index = post_order_visit(cfg, cfg->entry, cfg->size); + size_t index = post_order_visit(cfg, cfg->entry, cfg->reachable_size); assert(index == 0); // debug_print("RPO: "); @@ -432,11 +488,31 @@ CFNode* least_common_ancestor(CFNode* i, CFNode* j) { return i; } +bool cfg_is_dominated(CFNode* a, CFNode* b) { + while (a) { + if (a == b) + return true; + if (a->structured_idom) + a = a->structured_idom; + else + a = a->idom; + } + return false; +} + void compute_domtree(CFG* cfg) { for (size_t i = 0; i < cfg->size; i++) { CFNode* n = read_list(CFNode*, cfg->contents)[i]; - if (n == cfg->entry) + if (n == cfg->entry/* || !n->reachable*/) continue; + CFNode* structured_idom = NULL; + for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { + CFEdge e = read_list(CFEdge, n->pred_edges)[j]; + if (e.type == StructuredTailEdge) { + structured_idom = n->structured_idom = e.src; + continue; + } + } for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { CFEdge e = read_list(CFEdge, n->pred_edges)[j]; if (e.src->rpo_index < n->rpo_index) { @@ -444,6 +520,9 @@ void compute_domtree(CFG* cfg) { goto outer_loop; } } + if (structured_idom) { + continue; + } error("no idom found"); outer_loop:; } @@ -453,11 +532,13 @@ void compute_domtree(CFG* cfg) { todo = false; for (size_t i = 0; i < cfg->size; i++) { CFNode* n = read_list(CFNode*, cfg->contents)[i]; - if (n == cfg->entry) + if (n == cfg->entry || n->structured_idom) continue; CFNode* new_idom = NULL; for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { CFEdge e = read_list(CFEdge, n->pred_edges)[j]; + if (e.type == StructuredTailEdge) + continue; CFNode* p = e.src; new_idom = new_idom ? least_common_ancestor(new_idom, p) : p; } @@ -470,12 +551,12 @@ void compute_domtree(CFG* cfg) { } for (size_t i = 0; i < cfg->size; i++) { - CFNode* n = read_list(CFNode*, cfg->contents)[i]; + CFNode* n = cfg->rpo[i]; n->dominates = new_list(CFNode*); } for (size_t i = 0; i < cfg->size; i++) { - CFNode* n = read_list(CFNode*, cfg->contents)[i]; - if (n == cfg->entry) + CFNode* n = cfg->rpo[i]; + if (!n->idom) continue; append_list(CFNode*, n->idom->dominates, n); } diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index 05aa9ec99..e1ecdbace 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -8,6 +8,7 @@ typedef struct CFNode_ CFNode; typedef enum { JumpEdge, StructuredEnterBodyEdge, + StructuredLoopContinue, StructuredLeaveBodyEdge, /// Join points might leak, and as a consequence, there might be no static edge to the /// tail of the enclosing let, which would make it look like dead code. @@ -26,6 +27,8 @@ typedef struct { struct CFNode_ { const Node* node; + bool reachable; + /** @brief Edges where this node is the source * * @ref List of @ref CFEdge @@ -43,6 +46,7 @@ struct CFNode_ { // set by compute_domtree CFNode* idom; + CFNode* structured_idom; /** @brief All Nodes directly dominated by this CFNode. * @@ -53,9 +57,19 @@ struct CFNode_ { }; typedef struct Arena_ Arena; +typedef struct LoopTree_ LoopTree; + +typedef struct { + bool include_structured_tails; + LoopTree* lt; + bool flipped; +} CFGBuildConfig; + typedef struct CFG_ { Arena* arena; + CFGBuildConfig config; size_t size; + bool flipped; /** @@ -70,24 +84,30 @@ typedef struct CFG_ { CFNode* entry; // set by compute_rpo + size_t reachable_size; CFNode** rpo; } CFG; /** * @returns @ref List of @ref CFG* */ -struct List* build_cfgs(Module*); - -typedef struct LoopTree_ LoopTree; +struct List* build_cfgs(Module*, CFGBuildConfig); /** Construct the CFG starting in node. */ -CFG* build_cfg(const Node* fn, const Node* entry, LoopTree* lt, bool flipped); +CFG* build_cfg(const Node* fn, const Node* entry, CFGBuildConfig); /** Construct the CFG starting in node. * Dominance will only be computed with respect to the nodes reachable by @p entry. */ -#define build_fn_cfg(node) build_cfg(node, node, NULL, false) + +static inline CFGBuildConfig forward_cfg_build(bool include_structured_tails) { + return (CFGBuildConfig) { + .include_structured_tails = include_structured_tails, + }; +} + +#define build_fn_cfg(node) build_cfg(node, node, forward_cfg_build(true)) /** Construct the CFG stating in Node. * Dominance will only be computed with respect to the nodes reachable by @p entry. @@ -99,6 +119,8 @@ CFNode* cfg_lookup(CFG* cfg, const Node* abs); void compute_rpo(CFG*); void compute_domtree(CFG*); +bool cfg_is_dominated(CFNode* a, CFNode* b); + bool is_cfnode_structural_target(CFNode*); CFNode* least_common_ancestor(CFNode* i, CFNode* j); diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index c0c799acb..7afe5bbfb 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -52,6 +52,7 @@ static void dump_cf_node(FILE* output, const CFNode* n) { print_node_helper(p, body); print(p, "\\l"); + print(p, "rpo: %d, idom: %s, sdom: %s", n->rpo_index, n->idom ? get_abstraction_name_safe(n->idom->node) : "null", n->structured_idom ? get_abstraction_name_safe(n->structured_idom->node) : "null"); String label = printer_growy_unwrap(p); fprintf(output, "bb_%zu [nojustify=true, label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); @@ -82,14 +83,16 @@ static void dump_cfg(FILE* output, CFG* cfg) { CFEdge edge = read_list(CFEdge, bb_node->succ_edges)[j]; const CFNode* target_node = edge.dst; String edge_color = "black"; + String edge_style = "solid"; switch (edge.type) { case StructuredEnterBodyEdge: edge_color = "blue"; break; case StructuredLeaveBodyEdge: edge_color = "red"; break; - case StructuredTailEdge: edge_color = "darkred"; break; + case StructuredTailEdge: edge_style = "dashed"; break; + case StructuredLoopContinue: edge_style = "dotted"; break; default: break; } - fprintf(output, "bb_%zu -> bb_%zu [color=\"%s\"];\n", (size_t) (src_node), (size_t) (target_node), edge_color); + fprintf(output, "bb_%zu -> bb_%zu [color=\"%s\", style=\"%s\"];\n", (size_t) (src_node), (size_t) (target_node), edge_color, edge_style); } } fprintf(output, "}\n"); @@ -118,7 +121,7 @@ void dump_cfgs(FILE* output, Module* mod) { output = stderr; fprintf(output, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod); + struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; dump_cfg(output, cfg); @@ -156,7 +159,7 @@ void dump_domtree_cfg(Printer* p, CFG* s) { void dump_domtree_module(Printer* p, Module* mod) { print(p, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod); + struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; dump_domtree_cfg(p, cfg); diff --git a/src/shady/analysis/free_frontier.c b/src/shady/analysis/free_frontier.c index 73d37ece4..9f8655926 100644 --- a/src/shady/analysis/free_frontier.c +++ b/src/shady/analysis/free_frontier.c @@ -12,16 +12,6 @@ typedef struct { struct Dict* frontier; } FreeFrontierVisitor; -/// Whether 'a' is dominated by 'b' -static bool is_dominated(CFNode* a, CFNode* b) { - while (a) { - if (a == b) - return true; - a = a->idom; - } - return false; -} - static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { if (find_key_dict(const Node*, v->seen, node)) return; @@ -29,10 +19,11 @@ static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { CFNode* where = schedule_instruction(v->scheduler, node); if (where) { FreeFrontierVisitor vv = *v; - if (is_dominated(where, v->start)) { + if (cfg_is_dominated(where, v->start)) { visit_node_operands(&vv.v, NcAbstraction | NcDeclaration | NcType, node); } else { - insert_set_get_result(const Node*, v->frontier, node); + if (!is_abstraction(node)) + insert_set_get_result(const Node*, v->frontier, node); } } } diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index dfead5844..6250e531a 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -284,7 +284,7 @@ void dump_loop_trees(FILE* output, Module* mod) { output = stderr; fprintf(output, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod); + struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; LoopTree* lt = build_loop_tree(cfg); diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c index 0dfe0cf93..8af8e878f 100644 --- a/src/shady/analysis/scheduler.c +++ b/src/shady/analysis/scheduler.c @@ -15,15 +15,6 @@ struct Scheduler_ { struct Dict* scheduled; }; -static bool is_dominated(CFNode* a, CFNode* b) { - while (a) { - if (a == b) - return true; - a = a->idom; - } - return false; -} - static void schedule_after(CFNode** scheduled, CFNode* req) { if (!req) return; @@ -33,10 +24,10 @@ static void schedule_after(CFNode** scheduled, CFNode* req) { else { // TODO: validate that old post-dominates req if (req->rpo_index > old->rpo_index) { - assert(is_dominated(req, old)); + assert(cfg_is_dominated(req, old)); *scheduled = req; } else { - assert(is_dominated(old, req)); + assert(cfg_is_dominated(old, req)); } } } diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 795afe3c6..3774568e1 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -43,7 +43,7 @@ static void verify_same_arena(Module* mod) { } static void verify_scoping(const CompilerConfig* config, Module* mod) { - struct List* cfgs = build_cfgs(mod); + struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; Scheduler* scheduler = new_scheduler(cfg); @@ -136,7 +136,7 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { } static void verify_bodies(const CompilerConfig* config, Module* mod) { - struct List* cfgs = build_cfgs(mod); + struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; diff --git a/src/shady/compile.c b/src/shady/compile.c index 9d0b54ed4..fe7919bfe 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -47,6 +47,11 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { // we don't want to mess with the original module *pmod = import(config, *pmod); + if (config->input_cf.has_scope_annotations) { + RUN_PASS(lift_everything) + RUN_PASS(scope2control) + } + if (config->dynamic_scheduling) { add_scheduler_source(config, *pmod); } diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index 71d61141c..351d3ebdf 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -34,4 +34,6 @@ target_sources(shady PRIVATE specialize_execution_model.c lower_logical_pointers.c lower_entrypoint_args.c + scope2control.c + lift_everything.c ) diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index daf12926c..3662b1934 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -23,6 +23,13 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { + while (ctx->rewriter.parent) { + Context* parent_ctx = (Context*) ctx->rewriter.parent; + if (parent_ctx->cfg) + ctx = parent_ctx; + else + break; + } Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; switch (node->tag) { diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 6e6f4b409..805d9da8a 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -94,6 +94,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { const Node* item = frontier.nodes[i]; + assert(is_value(item)); debugv_print("%%%d", item->id); if (i + 1 < recover_context_size) debugv_print(", "); diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index e8ee859fb..adf7d5d38 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -16,6 +16,9 @@ RewritePass cleanup; /// Gets rid of structured control flow constructs, and turns them into branches, joins and tailcalls RewritePass lower_cf_instrs; +/// Uses shady.scope annotations to insert control blocks +RewritePass scope2control; +RewritePass lift_everything; /// Try to identify reconvergence points throughout the program for unstructured control flow programs //RewritePass reconvergence_heuristics; diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index ab2fe0509..dabfadbdf 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -61,16 +61,6 @@ static Nodes remake_params(Context* ctx, Nodes old) { return nodes(a, old.count, nvars); } -/// Whether 'a' is dominated by 'b' -static bool is_dominated(CFNode* a, CFNode* b) { - while (a) { - if (a == b) - return true; - a = a->idom; - } - return false; -} - static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { Controls** found = find_value_dict(const Node, Controls*, ctx->controls, fn_or_bb); if (found) diff --git a/src/shady/type.c b/src/shady/type.c index 91a06bac5..06a1c3d10 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -39,6 +39,8 @@ bool is_subtype(const Type* supertype, const Type* type) { case RecordType_TAG: { const Nodes* supermembers = &supertype->payload.record_type.members; const Nodes* members = &type->payload.record_type.members; + if (supermembers->count != members->count) + return false; for (size_t i = 0; i < members->count; i++) { if (!is_subtype(supermembers->nodes[i], members->nodes[i])) return false; @@ -442,18 +444,33 @@ const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { } const Type* check_type_composite(IrArena* arena, Composite composite) { - assert(is_data_type(composite.type)); - Nodes expected_member_types = get_composite_type_element_types(composite.type); + if (composite.type) { + assert(is_data_type(composite.type)); + Nodes expected_member_types = get_composite_type_element_types(composite.type); + bool is_uniform = true; + assert(composite.contents.count == expected_member_types.count); + for (size_t i = 0; i < composite.contents.count; i++) { + const Type* element_type = composite.contents.nodes[i]->type; + is_uniform &= deconstruct_qualified_type(&element_type); + assert(is_subtype(expected_member_types.nodes[i], element_type)); + } + return qualified_type(arena, (QualifiedType) { + .is_uniform = is_uniform, + .type = composite.type + }); + } bool is_uniform = true; - assert(composite.contents.count == expected_member_types.count); + LARRAY(const Type*, member_ts, composite.contents.count); for (size_t i = 0; i < composite.contents.count; i++) { const Type* element_type = composite.contents.nodes[i]->type; is_uniform &= deconstruct_qualified_type(&element_type); - assert(is_subtype(expected_member_types.nodes[i], element_type)); + member_ts[i] = element_type; } return qualified_type(arena, (QualifiedType) { .is_uniform = is_uniform, - .type = composite.type + .type = record_type(arena, (RecordType) { + .members = nodes(arena, composite.contents.count, member_ts) + }) }); } diff --git a/test/vcc/loop_closed.c b/test/vcc/loop_closed.c index 4a18c7f28..a2f897231 100644 --- a/test/vcc/loop_closed.c +++ b/test/vcc/loop_closed.c @@ -1,8 +1,11 @@ -int square(int num) { - for (int i = 0; i < num; i++) { +int square(int i) { + while (1) { if (i == 9) return i; - num--; + // if (i % 3 == 0) { + // i-=2; + // continue; + // } + i--; } - return 0; } diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 46d5919cb..211c662be 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -58,6 +58,7 @@ VccConfig vcc_init_config(CompilerConfig* compiler_config) { // magic! compiler_config->hacks.recover_structure = true; + compiler_config->input_cf.has_scope_annotations = true; String self_path = get_executable_location(); String working_dir = strip_path(self_path); From 22b60791e48861c6ad425a1442a63c10eaf97b80 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 21 Aug 2024 20:40:21 +0200 Subject: [PATCH 524/693] everything 'works' --- include/shady/config.h | 1 + src/backend/spirv/emit_spv.c | 2 +- src/frontend/llvm/l2s.c | 1 + src/frontend/llvm/l2s_instr.c | 1 + src/shady/analysis/cfg.c | 22 ++++++++++++---------- src/shady/config.c | 1 + src/shady/passes/cleanup.c | 2 +- src/shady/passes/lift_everything.c | 19 +++++++++++-------- src/shady/passes/scope2control.c | 1 + src/shady/rewrite.c | 1 + test/test_builder.c | 12 ++++++++++-- 11 files changed, 41 insertions(+), 22 deletions(-) diff --git a/include/shady/config.h b/include/shady/config.h index 35ace8a7a..d2faf016a 100644 --- a/include/shady/config.h +++ b/include/shady/config.h @@ -47,6 +47,7 @@ struct ArenaConfig_ { /// 'folding' optimisations - happen in the constructors directly struct { + bool inline_single_use_bbs; bool fold_static_control_flow; bool delete_unreachable_structured_cases; bool weaken_non_leaking_allocas; diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 893945068..a2047a77d 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -64,7 +64,7 @@ static void emit_basic_block(Emitter* emitter, FnBuilder* fn_builder, const CFNo SpvId bb_id = get_block_builder_id(bb_builder); spvb_add_bb(fn_builder->base, bb_builder); - String name = get_abstraction_name_unsafe(bb_node); + String name = get_abstraction_name_safe(bb_node); if (name) spvb_name(emitter->file_builder, bb_id, name); diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index a3e53d9a2..a49e3b622 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -263,6 +263,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* ArenaConfig aconfig = default_arena_config(&config->target); aconfig.check_types = false; aconfig.allow_fold = false; + aconfig.optimisations.inline_single_use_bbs = false; IrArena* arena = new_ir_arena(&aconfig); Module* dirty = new_module(arena, "dirty"); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index f75316aae..e4b78f0ef 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -109,6 +109,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B #define BIND_PREV_R(t) bind_instruction_outputs_count(b, r, 1) //if (LLVMIsATerminatorInst(instr)) { + //if (LLVMIsAInstruction(instr) && !LLVMIsATerminatorInst(instr)) { if (LLVMIsAInstruction(instr)) { assert(fn && fn_or_bb); LLVMMetadataRef dbgloc = LLVMInstructionGetDebugLoc(instr); diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index bdca321cc..73703a233 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -176,6 +176,8 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { return; } case If_TAG: { + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); CfgBuildContext if_ctx = *ctx; if_ctx.selection_construct_tail = get_structured_construct_tail(terminator); add_structural_dominance_edge(&if_ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); @@ -184,34 +186,32 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { else add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredLeaveBodyEdge); - if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; } case Match_TAG: { + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); CfgBuildContext match_ctx = *ctx; match_ctx.selection_construct_tail = get_structured_construct_tail(terminator); for (size_t i = 0; i < terminator->payload.match_instr.cases.count; i++) add_structural_dominance_edge(&match_ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); add_structural_dominance_edge(&match_ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); - if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; } case Loop_TAG: { + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); CfgBuildContext loop_ctx = *ctx; loop_ctx.loop_construct_head = terminator->payload.loop_instr.body; loop_ctx.loop_construct_tail = get_structured_construct_tail(terminator); add_structural_dominance_edge(&loop_ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); - if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; } case Control_TAG: { + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); //CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); const Node* tail = get_structured_construct_tail(terminator); insert_dict(const Node*, const Node*, ctx->join_point_values, param, tail); add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); - if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; } case MergeSelection_TAG: { assert(ctx->selection_construct_tail); @@ -492,10 +492,12 @@ bool cfg_is_dominated(CFNode* a, CFNode* b) { while (a) { if (a == b) return true; - if (a->structured_idom) + if (a->idom) + a = a->idom; + else if (a->structured_idom) a = a->structured_idom; else - a = a->idom; + break; } return false; } diff --git a/src/shady/config.c b/src/shady/config.c index a094bb5c1..12503ec08 100644 --- a/src/shady/config.c +++ b/src/shady/config.c @@ -69,6 +69,7 @@ ArenaConfig default_arena_config(const TargetConfig* target) { .check_op_classes = true, .optimisations = { + .inline_single_use_bbs = true, .fold_static_control_flow = true, .delete_unreachable_structured_cases = true, }, diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 86132793e..09ccc1055 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -55,7 +55,7 @@ const Node* process(Context* ctx, const Node* old) { switch (old->tag) { case BasicBlock_TAG: { size_t uses = count_calls(ctx->map, old); - if (uses <= 1) { + if (uses <= 1 && a->config.optimisations.inline_single_use_bbs) { log_string(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name_safe(old), uses); return NULL; } diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index 3662b1934..9fa3a6c8d 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -23,13 +23,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - while (ctx->rewriter.parent) { - Context* parent_ctx = (Context*) ctx->rewriter.parent; - if (parent_ctx->cfg) - ctx = parent_ctx; - else - break; - } Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; switch (node->tag) { @@ -71,7 +64,17 @@ static const Node* process(Context* ctx, const Node* node) { destroy_dict(frontier); insert_dict(const Node*, Nodes, ctx->lift, node, additional_args); Node* new_bb = basic_block(a, new_params, get_abstraction_name_unsafe(node)); - register_processed(r, node, new_bb); + + Context* fn_ctx = ctx; + while (fn_ctx->rewriter.parent) { + Context* parent_ctx = (Context*) ctx->rewriter.parent; + if (parent_ctx->cfg) + fn_ctx = parent_ctx; + else + break; + } + + register_processed(&fn_ctx->rewriter, node, new_bb); set_abstraction_body(new_bb, rewrite_node(&bb_ctx.rewriter, get_abstraction_body(node))); return new_bb; } diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index dabfadbdf..9339b866a 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -286,6 +286,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Module* scope2control(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + aconfig.optimisations.inline_single_use_bbs = true; IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index e0f179ab4..34969aa3d 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -80,6 +80,7 @@ const Node* rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNo return found; const Node* rewritten = fn(rewriter, node); + // assert(rewriter->dst_arena == rewritten->arena); if (is_declaration(node)) return rewritten; if (rewriter->config.write_map && should_memoize(node)) { diff --git a/test/test_builder.c b/test/test_builder.c index 457b3725f..a11fb531a 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -62,14 +62,22 @@ static void test_body_builder_fun_body(IrArena* a) { CFG* cfg = build_fn_cfg(fun); const Node* mem = get_terminator_mem(return_terminator); do { - mem = get_original_mem(mem); + const Node* omem = get_original_mem(mem); + if (!omem) + break; + mem = omem; CHECK(mem->tag == AbsMem_TAG, exit(-1)); CFNode* n = cfg_lookup(cfg, mem->payload.abs_mem.abs); if (n->idom) { mem = get_terminator_mem(get_abstraction_body(n->idom->node)); continue; } - } while (false); + if (n->structured_idom) { + mem = get_terminator_mem(get_abstraction_body(n->structured_idom->node)); + continue; + } + break; + } while (1); mem = get_original_mem(mem); CHECK(mem == get_abstraction_mem(fun), exit(-1)); destroy_cfg(cfg); From baab2c56617aa2a1170b022dd45290a6f8ebc231 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 11:10:18 +0200 Subject: [PATCH 525/693] new version of the loop heuristic wip --- src/frontend/llvm/l2s_instr.c | 2 +- src/shady/analysis/cfg.c | 16 +- src/shady/analysis/cfg.h | 11 +- src/shady/analysis/looptree.c | 2 +- src/shady/compile.c | 5 + src/shady/passes/CMakeLists.txt | 1 + src/shady/passes/lift_everything.c | 2 +- src/shady/passes/lower_fill.c | 9 +- src/shady/passes/passes.h | 1 + src/shady/passes/scope2control.c | 13 +- src/shady/passes/scope_heuristic.c | 246 +++++++++++++++++++++++++++++ test/vcc/loop_for_simple.c | 10 ++ test/vcc/loop_two_backedges.c | 10 ++ vcc/vcc_lib.c | 3 +- 14 files changed, 312 insertions(+), 19 deletions(-) create mode 100644 src/shady/passes/scope_heuristic.c create mode 100644 test/vcc/loop_for_simple.c create mode 100644 test/vcc/loop_two_backedges.c diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index e4b78f0ef..caaa4e3ab 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -110,7 +110,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B //if (LLVMIsATerminatorInst(instr)) { //if (LLVMIsAInstruction(instr) && !LLVMIsATerminatorInst(instr)) { - if (LLVMIsAInstruction(instr)) { + if (LLVMIsAInstruction(instr) && p->config->hacks.recover_structure) { assert(fn && fn_or_bb); LLVMMetadataRef dbgloc = LLVMInstructionGetDebugLoc(instr); if (dbgloc) { diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 73703a233..7b3e0ad81 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -90,17 +90,19 @@ static CFNode* get_or_enqueue(CfgBuildContext* ctx, const Node* abs) { return new; } -static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { +static bool in_loop(LoopTree* lt, const Node* fn, const Node* loopentry, const Node* block) { LTNode* lt_node = looptree_lookup(lt, block); assert(lt_node); LTNode* parent = lt_node->parent; assert(parent); while (parent) { - if (entries_count_list(parent->cf_nodes) != 1) - return false; + // we're not in a loop like we're expected to + if (entries_count_list(parent->cf_nodes) == 0 && loopentry == fn) + return true; - if (read_list(CFNode*, parent->cf_nodes)[0]->node == entry) + // we are in the loop we were expected to + if (entries_count_list(parent->cf_nodes) == 1 && read_list(CFNode*, parent->cf_nodes)[0]->node == loopentry) return true; parent = parent->parent; @@ -113,7 +115,7 @@ static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFEdgeType type, const Node* j) { assert(is_abstraction(src) && is_abstraction(dst)); assert(!is_function(dst)); - if (ctx->lt && !in_loop(ctx->lt, ctx->entry, dst)) + if (ctx->lt && !in_loop(ctx->lt, ctx->function, ctx->entry, dst)) return; if (ctx->lt && dst == ctx->entry) { return; @@ -205,13 +207,13 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_structural_dominance_edge(&loop_ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); return; } case Control_TAG: { - if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); //CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); const Node* tail = get_structured_construct_tail(terminator); insert_dict(const Node*, const Node*, ctx->join_point_values, param, tail); add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); + if (ctx->include_structured_tails) + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); return; } case MergeSelection_TAG: { assert(ctx->selection_construct_tail); diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index e1ecdbace..fb62faf36 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -106,6 +106,13 @@ static inline CFGBuildConfig forward_cfg_build(bool include_structured_tails) { .include_structured_tails = include_structured_tails, }; } +static inline CFGBuildConfig flipped_cfg_build(bool include_structured_tails) { + return (CFGBuildConfig) { + .include_structured_tails = include_structured_tails, + .lt = NULL, + .flipped = true, + }; +} #define build_fn_cfg(node) build_cfg(node, node, forward_cfg_build(true)) @@ -113,13 +120,13 @@ static inline CFGBuildConfig forward_cfg_build(bool include_structured_tails) { * Dominance will only be computed with respect to the nodes reachable by @p entry. * This CFG will contain post dominance information instead of regular dominance! */ -#define build_fn_cfg_flipped(node) build_cfg(node, node, NULL, true) +#define build_fn_cfg_flipped(node) build_cfg(node, node, flipped_cfg_build(true)) CFNode* cfg_lookup(CFG* cfg, const Node* abs); void compute_rpo(CFG*); void compute_domtree(CFG*); -bool cfg_is_dominated(CFNode* a, CFNode* b); +bool cfg_is_dominated(CFNode* dominated, CFNode* by); bool is_cfnode_structural_target(CFNode*); diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index 6250e531a..834eda698 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -259,7 +259,7 @@ static void dump_lt_node(FILE* f, const LTNode* n) { for (size_t i = 0; i < entries_count_list(n->cf_nodes); i++) { const Node* bb = read_list(const CFNode*, n->cf_nodes)[i]->node; - fprintf(f, "%s_%d;\n", get_abstraction_name(bb), extra_uniqueness++); + fprintf(f, "bb_%d[label=\"%s\"];\n", extra_uniqueness++, get_abstraction_name_safe(bb)); } for (size_t i = 0; i < entries_count_list(n->lf_children); i++) { diff --git a/src/shady/compile.c b/src/shady/compile.c index fe7919bfe..b1b1838a9 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -46,8 +46,13 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { // we don't want to mess with the original module *pmod = import(config, *pmod); + log_string(DEBUG, "After import:\n"); + log_module(DEBUG, config, *pmod); if (config->input_cf.has_scope_annotations) { + if (config->hacks.restructure_everything) { + RUN_PASS(scope_heuristic) + } RUN_PASS(lift_everything) RUN_PASS(scope2control) } diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index 351d3ebdf..4ae78486a 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -36,4 +36,5 @@ target_sources(shady PRIVATE lower_entrypoint_args.c scope2control.c lift_everything.c + scope_heuristic.c ) diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index 9fa3a6c8d..c6cb081e5 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -67,7 +67,7 @@ static const Node* process(Context* ctx, const Node* node) { Context* fn_ctx = ctx; while (fn_ctx->rewriter.parent) { - Context* parent_ctx = (Context*) ctx->rewriter.parent; + Context* parent_ctx = (Context*) fn_ctx->rewriter.parent; if (parent_ctx->cfg) fn_ctx = parent_ctx; else diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index 98d7e1937..408a599e2 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -12,12 +12,13 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { case Fill_TAG: { - const Type* composite_t = rewrite_node(&ctx->rewriter, node->payload.fill.type); + const Type* composite_t = rewrite_node(r, node->payload.fill.type); size_t actual_size = get_int_literal_value(*resolve_to_int_literal(get_fill_type_size(composite_t)), false); - const Node* value = rewrite_node(&ctx->rewriter, node->payload.fill.value); + const Node* value = rewrite_node(r, node->payload.fill.value); LARRAY(const Node*, copies, actual_size); for (size_t i = 0; i < actual_size; i++) { copies[i] = value; @@ -27,7 +28,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return recreate_node_identity(r, node); } Module* lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index adf7d5d38..5758febff 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -19,6 +19,7 @@ RewritePass lower_cf_instrs; /// Uses shady.scope annotations to insert control blocks RewritePass scope2control; RewritePass lift_everything; +RewritePass scope_heuristic; /// Try to identify reconvergence points throughout the program for unstructured control flow programs //RewritePass reconvergence_heuristics; diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 9339b866a..8e6287f81 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -182,8 +182,12 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed CFNode* src_cfnode = cfg_lookup(cfg, src); assert(src_cfnode->node); - CFNode* target_cfnode = cfg_lookup(cfg, dst); - assert(src_cfnode && target_cfnode); + CFNode* dst_cfnode = cfg_lookup(cfg, dst); + assert(src_cfnode && dst_cfnode); + + // if(!cfg_is_dominated(dst_cfnode, src_cfnode)) + // return; + CFNode* dom = src_cfnode->idom; while (dom) { debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); @@ -195,6 +199,11 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { + // if (cfg_is_dominated(target_cfnode, dom)) { + if (!cfg_is_dominated(dom, dst_cfnode) && dst_cfnode != dom) { + // assert(false); + } + debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); Controls* controls = get_or_create_controls(ctx, dom->node); diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c new file mode 100644 index 000000000..ed3c1a307 --- /dev/null +++ b/src/shady/passes/scope_heuristic.c @@ -0,0 +1,246 @@ +#include "shady/pass.h" + +#include "../ir_private.h" +#include "../type.h" +#include "../analysis/cfg.h" +#include "../analysis/looptree.h" +#include "../transform/ir_gen_helpers.h" + +#include "log.h" +#include "list.h" +#include "portability.h" + +typedef struct { + Rewriter rewriter; + CFG* cfg; + Nodes* depth_per_rpo; +} Context; + +static Nodes to_ids(IrArena* a, Nodes in) { + LARRAY(const Node*, arr, in.count); + for (size_t i = 0; i < in.count; i++) + arr[i] = uint32_literal(a, in.nodes[i]->id); + return nodes(a, in.count, arr); +} + +static void visit_looptree_prepend(IrArena* a, Nodes* arr, LTNode* node, Nodes prefix) { + if (node->type == LF_HEAD) { + for (size_t i = 0; i < entries_count_list(node->lf_children); i++) { + LTNode* n = read_list(LTNode*, node->lf_children)[i]; + visit_looptree_prepend(a, arr, n, prefix); + } + } else { + for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { + CFNode* n = read_list(CFNode*, node->cf_nodes)[i]; + arr[n->rpo_index] = concat_nodes(a, prefix, arr[n->rpo_index]); + } + assert(node->lf_children); + } +} + +static bool is_nested(LTNode* a, LTNode* in) { + assert(a->type == LF_HEAD && in->type == LF_HEAD); + while (a) { + if (a == in) + return true; + a = a->parent; + } + return false; +} + +static void paint_dominated_up_to_postdom(CFNode* n, IrArena* a, Nodes* arr, const Node* postdom, const Node* prefix) { + if (n->node == postdom) + return; + + for (size_t i = 0; i < entries_count_list(n->dominates); i++) { + CFNode* dominated = read_list(CFNode*, n->dominates)[i]; + paint_dominated_up_to_postdom(dominated, a, arr, postdom, prefix); + } + + arr[n->rpo_index] = prepend_nodes(a, arr[n->rpo_index], prefix); +} + +static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* flipped, LoopTree* lt) { + for (size_t i = 0; i < entries_count_list(n->dominates); i++) { + CFNode* dominated = read_list(CFNode*, n->dominates)[i]; + visit_acyclic_cfg_domtree(dominated, a, arr, flipped, lt); + } + + CFNode* src = n; + + if (entries_count_list(src->succ_edges) < 2) + return; // no divergence, no bother + + CFNode* f_src = cfg_lookup(flipped, src->node); + CFNode* f_src_ipostdom = f_src->idom; + if (!f_src_ipostdom) + return; + + // your post-dominator can't be yourself... can it ? + assert(f_src_ipostdom->node != src->node); + + LTNode* src_lt = looptree_lookup(lt, src->node); + LTNode* pst_lt = looptree_lookup(lt, f_src_ipostdom->node); + assert(src_lt->type == LF_LEAF && pst_lt->type == LF_LEAF); + if (src_lt->parent == pst_lt->parent) { + log_string(DEBUGVV, "We have a candidate for reconvergence: a branch starts at %d and ends at %d\n", src->node->id, f_src_ipostdom->node->id); + paint_dominated_up_to_postdom(n, a, arr, f_src_ipostdom->node, n->node); + } +} + +static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, LoopTree* lt, LTNode* node) { + if (node->type == LF_HEAD) { + Nodes surrounding = empty(a); + for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { + CFNode* n = read_list(CFNode*, node->cf_nodes)[i]; + surrounding = append_nodes(a, surrounding, n->node); + } + + for (size_t i = 0; i < entries_count_list(node->lf_children); i++) { + LTNode* n = read_list(LTNode*, node->lf_children)[i]; + visit_looptree(a, arr, fn, flipped, lt, n); + } + + visit_looptree_prepend(a, arr, node, surrounding); + + assert(surrounding.count < 2); + //if (surrounding.count == 1) { + CFG* sub_cfg = build_cfg(fn, surrounding.count == 1 ? surrounding.nodes[0] : fn, (CFGBuildConfig) { + .include_structured_tails = true, + .lt = lt + }); + + visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, lt); + + destroy_cfg(sub_cfg); + //} + } else { + /*for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { + CFNode* src = read_list(CFNode*, node->cf_nodes)[i]; + + if (entries_count_list(src->succ_edges) < 2) + continue; // no divergence, no bother + + CFNode* f_src = cfg_lookup(flipped, src->node); + CFNode* f_src_ipostdom = f_src->idom; + if (!f_src_ipostdom) + continue; + + // your post-dominator can't be yourself... can it ? + assert(f_src_ipostdom->node != src->node); + + LTNode* src_lt = looptree_lookup(lt, src->node); + LTNode* pst_lt = looptree_lookup(lt, f_src_ipostdom->node); + assert(src_lt->type == LF_LEAF && pst_lt->type == LF_LEAF); + if (src_lt->parent == pst_lt->parent) { + log_string(DEBUGVV, "We have a candidate for reconvergence: a branch starts at %d and ends at %d\n", src->node->id, f_src_ipostdom->node->id); + } + } + assert(node->lf_children);*/ + } +} + +static bool loop_depth(LTNode* a) { + int i = 0; + while (a) { + if (entries_count_list(a->cf_nodes) > 0) + i++; + else { + assert(!a->parent); + } + a = a->parent; + } + return i; +} + +static Nodes* compute_scope_depth(IrArena* a, CFG* cfg, CFG* flipped, LoopTree* lt) { + Nodes* arr = calloc(sizeof(Nodes), cfg->size); + for (size_t i = 0; i < cfg->size; i++) + arr[i] = empty(a); + + visit_looptree(a, arr, cfg->entry->node, flipped, lt, lt->root); + + /*for (size_t i = 0; i < cfg->size; i++) { + CFNode* src = cfg->rpo[i]; + if (entries_count_list(src->succ_edges) < 2) + continue; // no divergence, no bother + + CFNode* f_src = cfg_lookup(flipped, src->node); + CFNode* f_src_ipostdom = f_src->idom; + if (!f_src_ipostdom) + continue; + + // your post-dominator can't be yourself... can it ? + assert(f_src_ipostdom->node != src->node); + + LTNode* src_lt = looptree_lookup(lt, src->node); + LTNode* pst_lt = looptree_lookup(lt, f_src_ipostdom->node); + assert(src_lt->type == LF_LEAF && pst_lt->type == LF_LEAF); + if (src_lt->parent == pst_lt->parent) { + log_string(DEBUGVV, "We have a candidate for reconvergence: a branch starts at %d and ends at %d\n", src->node->id, f_src_ipostdom->node->id); + } + }*/ + + // we don't want to cause problems by holding onto pointless references... + for (size_t i = 0; i < cfg->size; i++) + arr[i] = to_ids(a, arr[i]); + + return arr; +} + +static const Node* process(Context* ctx, const Node* node) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + switch (node->tag) { + case Function_TAG: { + Context fn_ctx = *ctx; + fn_ctx.cfg = build_fn_cfg(node); + CFG* flipped = build_fn_cfg_flipped(node); + LoopTree* lt = build_loop_tree(fn_ctx.cfg); + fn_ctx.depth_per_rpo = compute_scope_depth(a, fn_ctx.cfg, flipped, lt); + Node* new_fn = recreate_decl_header_identity(r, node); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); + gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), empty(a)); + register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + set_abstraction_body(new_fn, finish_body(bb, rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); + destroy_loop_tree(lt); + destroy_cfg(flipped); + destroy_cfg(fn_ctx.cfg); + free(ctx->depth_per_rpo); + return new_fn; + } + case BasicBlock_TAG: { + Nodes nparams = recreate_params(r, get_abstraction_params(node)); + register_processed_list(r, get_abstraction_params(node), nparams); + Node* new_bb = basic_block(a, nparams, get_abstraction_name_unsafe(node)); + register_processed(r, node, new_bb); + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_bb)); + CFNode* n = cfg_lookup(ctx->cfg, node); + /*Nodes path = empty(a); + while (n->idom) { + path = prepend_nodes(a, path, uint32_literal(a, n->idom->rpo_index)); + n = n->idom; + } + gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), path);*/ + gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); + register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + set_abstraction_body(new_bb, finish_body(bb, rewrite_node(r, get_abstraction_body(node)))); + return new_bb; + } + default: break; + } + + return recreate_node_identity(&ctx->rewriter, node); +} + +Module* scope_heuristic(SHADY_UNUSED const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); + Module* dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + }; + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + return dst; +} diff --git a/test/vcc/loop_for_simple.c b/test/vcc/loop_for_simple.c new file mode 100644 index 000000000..d5f6250a6 --- /dev/null +++ b/test/vcc/loop_for_simple.c @@ -0,0 +1,10 @@ +int square(int num) { + for (int i = 0; i < num; i++) { + // if (i == 9) + // break; + // if (i % 2 == 0) + // continue; + num--; + } + return 0; +} diff --git a/test/vcc/loop_two_backedges.c b/test/vcc/loop_two_backedges.c new file mode 100644 index 000000000..1bb67537a --- /dev/null +++ b/test/vcc/loop_two_backedges.c @@ -0,0 +1,10 @@ +int square(int i) { + while (1) { + i--; + if (i % 2 == 0) { + i -= 3; + continue; + } + } + return 0; +} diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 211c662be..6b2873de3 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -57,7 +57,8 @@ VccConfig vcc_init_config(CompilerConfig* compiler_config) { }; // magic! - compiler_config->hacks.recover_structure = true; + //compiler_config->hacks.recover_structure = true; + compiler_config->hacks.restructure_everything = true; compiler_config->input_cf.has_scope_annotations = true; String self_path = get_executable_location(); From d02b6d5a318063ebb09398079f432a0982f420d5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 11:37:53 +0200 Subject: [PATCH 526/693] scope_heuristic: cleanup --- src/shady/passes/scope_heuristic.c | 78 ++++++------------------------ 1 file changed, 14 insertions(+), 64 deletions(-) diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index ed3c1a307..e8c3ab9d3 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -104,39 +104,14 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, visit_looptree_prepend(a, arr, node, surrounding); assert(surrounding.count < 2); - //if (surrounding.count == 1) { - CFG* sub_cfg = build_cfg(fn, surrounding.count == 1 ? surrounding.nodes[0] : fn, (CFGBuildConfig) { - .include_structured_tails = true, - .lt = lt - }); + CFG* sub_cfg = build_cfg(fn, surrounding.count == 1 ? surrounding.nodes[0] : fn, (CFGBuildConfig) { + .include_structured_tails = true, + .lt = lt + }); - visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, lt); + visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, lt); - destroy_cfg(sub_cfg); - //} - } else { - /*for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { - CFNode* src = read_list(CFNode*, node->cf_nodes)[i]; - - if (entries_count_list(src->succ_edges) < 2) - continue; // no divergence, no bother - - CFNode* f_src = cfg_lookup(flipped, src->node); - CFNode* f_src_ipostdom = f_src->idom; - if (!f_src_ipostdom) - continue; - - // your post-dominator can't be yourself... can it ? - assert(f_src_ipostdom->node != src->node); - - LTNode* src_lt = looptree_lookup(lt, src->node); - LTNode* pst_lt = looptree_lookup(lt, f_src_ipostdom->node); - assert(src_lt->type == LF_LEAF && pst_lt->type == LF_LEAF); - if (src_lt->parent == pst_lt->parent) { - log_string(DEBUGVV, "We have a candidate for reconvergence: a branch starts at %d and ends at %d\n", src->node->id, f_src_ipostdom->node->id); - } - } - assert(node->lf_children);*/ + destroy_cfg(sub_cfg); } } @@ -153,38 +128,23 @@ static bool loop_depth(LTNode* a) { return i; } -static Nodes* compute_scope_depth(IrArena* a, CFG* cfg, CFG* flipped, LoopTree* lt) { +static Nodes* compute_scope_depth(IrArena* a, CFG* cfg) { + CFG* flipped = build_fn_cfg_flipped(cfg->entry->node); + LoopTree* lt = build_loop_tree(cfg); + Nodes* arr = calloc(sizeof(Nodes), cfg->size); for (size_t i = 0; i < cfg->size; i++) arr[i] = empty(a); visit_looptree(a, arr, cfg->entry->node, flipped, lt, lt->root); - /*for (size_t i = 0; i < cfg->size; i++) { - CFNode* src = cfg->rpo[i]; - if (entries_count_list(src->succ_edges) < 2) - continue; // no divergence, no bother - - CFNode* f_src = cfg_lookup(flipped, src->node); - CFNode* f_src_ipostdom = f_src->idom; - if (!f_src_ipostdom) - continue; - - // your post-dominator can't be yourself... can it ? - assert(f_src_ipostdom->node != src->node); - - LTNode* src_lt = looptree_lookup(lt, src->node); - LTNode* pst_lt = looptree_lookup(lt, f_src_ipostdom->node); - assert(src_lt->type == LF_LEAF && pst_lt->type == LF_LEAF); - if (src_lt->parent == pst_lt->parent) { - log_string(DEBUGVV, "We have a candidate for reconvergence: a branch starts at %d and ends at %d\n", src->node->id, f_src_ipostdom->node->id); - } - }*/ - // we don't want to cause problems by holding onto pointless references... for (size_t i = 0; i < cfg->size; i++) arr[i] = to_ids(a, arr[i]); + destroy_loop_tree(lt); + destroy_cfg(flipped); + return arr; } @@ -195,16 +155,12 @@ static const Node* process(Context* ctx, const Node* node) { case Function_TAG: { Context fn_ctx = *ctx; fn_ctx.cfg = build_fn_cfg(node); - CFG* flipped = build_fn_cfg_flipped(node); - LoopTree* lt = build_loop_tree(fn_ctx.cfg); - fn_ctx.depth_per_rpo = compute_scope_depth(a, fn_ctx.cfg, flipped, lt); + fn_ctx.depth_per_rpo = compute_scope_depth(a, fn_ctx.cfg); Node* new_fn = recreate_decl_header_identity(r, node); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), empty(a)); register_processed(r, get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new_fn, finish_body(bb, rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); - destroy_loop_tree(lt); - destroy_cfg(flipped); destroy_cfg(fn_ctx.cfg); free(ctx->depth_per_rpo); return new_fn; @@ -216,12 +172,6 @@ static const Node* process(Context* ctx, const Node* node) { register_processed(r, node, new_bb); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_bb)); CFNode* n = cfg_lookup(ctx->cfg, node); - /*Nodes path = empty(a); - while (n->idom) { - path = prepend_nodes(a, path, uint32_literal(a, n->idom->rpo_index)); - n = n->idom; - } - gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), path);*/ gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); register_processed(r, get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new_bb, finish_body(bb, rewrite_node(r, get_abstraction_body(node)))); From 03399e84c2a921fd210d5a4e8b002a0c39e17db4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 11:46:41 +0200 Subject: [PATCH 527/693] scope_heuristics: more reliably deal with loops by making their headers less nested --- src/shady/passes/scope_heuristic.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index e8c3ab9d3..cf4a45190 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -101,15 +101,25 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, visit_looptree(a, arr, fn, flipped, lt, n); } + if (entries_count_list(node->cf_nodes) > 0) + surrounding = prepend_nodes(a, surrounding, string_lit_helper(a, unique_name(a, "loop_body"))); + visit_looptree_prepend(a, arr, node, surrounding); + // Remove one level of scoping for the loop headers (forcing reconvergence) + for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { + CFNode* n = read_list(CFNode*, node->cf_nodes)[i]; + Nodes old = arr[n->rpo_index]; + assert(old.count > 1); + arr[n->rpo_index] = nodes(a, old.count - 1, &old.nodes[0]); + } - assert(surrounding.count < 2); + assert(entries_count_list(node->cf_nodes) < 2); CFG* sub_cfg = build_cfg(fn, surrounding.count == 1 ? surrounding.nodes[0] : fn, (CFGBuildConfig) { .include_structured_tails = true, .lt = lt }); - visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, lt); + // visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, lt); destroy_cfg(sub_cfg); } @@ -129,21 +139,22 @@ static bool loop_depth(LTNode* a) { } static Nodes* compute_scope_depth(IrArena* a, CFG* cfg) { - CFG* flipped = build_fn_cfg_flipped(cfg->entry->node); + //CFG* flipped = build_fn_cfg_flipped(cfg->entry->node); LoopTree* lt = build_loop_tree(cfg); Nodes* arr = calloc(sizeof(Nodes), cfg->size); for (size_t i = 0; i < cfg->size; i++) arr[i] = empty(a); - visit_looptree(a, arr, cfg->entry->node, flipped, lt, lt->root); + //visit_looptree(a, arr, cfg->entry->node, flipped, lt, lt->root); + visit_looptree(a, arr, cfg->entry->node, NULL, lt, lt->root); // we don't want to cause problems by holding onto pointless references... for (size_t i = 0; i < cfg->size; i++) arr[i] = to_ids(a, arr[i]); destroy_loop_tree(lt); - destroy_cfg(flipped); + //destroy_cfg(flipped); return arr; } From 9758e72c511aa3f7de1c08a0ac6776d9dcf0d694 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 12:51:13 +0200 Subject: [PATCH 528/693] fix a couple memory safety issues --- src/shady/analysis/uses.c | 1 + src/shady/node.c | 6 ++++-- src/shady/print.c | 17 ++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index 29fd43f85..364628716 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -83,6 +83,7 @@ static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeCl for (size_t i = 0; i < nodes.count; i++) uses_visit_node(&v, nodes.nodes[i]); } + destroy_dict(v.seen); return uses; } diff --git a/src/shady/node.c b/src/shady/node.c index b88619760..e69b5cc6f 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -315,8 +315,10 @@ void set_abstraction_body(Node* abs, const Node* body) { BodyBuilder* insert = mem_abs->payload.basic_block.insert; if (insert && mem_abs != abs) { const Node* mem = insert->block_entry_mem; - set_abstraction_body((Node*) insert->block_entry_block, finish_block_body(insert, body)); - body = jump_helper(a, insert->block_entry_block, empty(a), mem); + const Node* block = insert->block_entry_block; + set_abstraction_body((Node*) block, finish_block_body(insert, body)); + body = jump_helper(a, block, empty(a), mem); + // mem_abs->payload.basic_block.insert = NULL; continue; } } diff --git a/src/shady/print.c b/src/shady/print.c index faf1e03c0..f91ff6347 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -320,14 +320,16 @@ static void print_function(PrinterCtx* ctx, const Node* node) { print_param_list(ctx, node->payload.fun.params, NULL); if (!get_abstraction_body(node)) { printf(";"); - return; - } + } else { + printf(" {"); + indent(ctx->printer); + printf("\n"); - printf(" {"); - indent(ctx->printer); - printf("\n"); + printf("%s", emit_abs_body(ctx, node)); - printf("%s", emit_abs_body(ctx, node)); + deindent(ctx->printer); + printf("\n}"); + } if (sub_ctx.cfg) { if (sub_ctx.uses) @@ -337,9 +339,6 @@ static void print_function(PrinterCtx* ctx, const Node* node) { destroy_cfg(sub_ctx.cfg); destroy_scheduler(sub_ctx.scheduler); } - - deindent(ctx->printer); - printf("\n}"); } static void print_nodes(PrinterCtx* ctx, Nodes nodes) { From 7e8b3aee869597336fc8847938b70d054af09cb1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 16:07:00 +0200 Subject: [PATCH 529/693] printer QOL improvements --- src/shady/analysis/cfg_dump.c | 42 ++++++++++++++++++++++++++++++----- src/shady/print.c | 3 +++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 7afe5bbfb..d0639f8ea 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -33,6 +33,21 @@ static void print_node_helper(Printer* p, const Node* n) { free((void*)label); } +static const Nodes* find_scope_info(const Node* abs) { + assert(is_abstraction(abs)); + const Node* terminator = get_abstraction_body(abs); + const Node* mem = get_terminator_mem(terminator); + Nodes* info = NULL; + while (mem) { + if (mem->tag == ExtInstr_TAG && strcmp(mem->payload.ext_instr.set, "shady.scope") == 0) { + if (!info || info->count > mem->payload.ext_instr.operands.count) + info = &mem->payload.ext_instr.operands; + } + mem = get_parent_mem(mem); + } + return info; +} + static void dump_cf_node(FILE* output, const CFNode* n) { const Node* bb = n->node; const Node* body = get_abstraction_body(bb); @@ -40,8 +55,14 @@ static void dump_cf_node(FILE* output, const CFNode* n) { return; String color = "black"; - if (is_basic_block(bb)) - color = "blue"; + switch (body->tag) { + case If_TAG: color = "blue"; break; + case Loop_TAG: color = "red"; break; + case Control_TAG: color = "orange"; break; + case Return_TAG: color = "teal"; break; + case Unreachable_TAG: color = "teal"; break; + default: break; + } Growy* g = new_growy(); Printer* p = open_growy_as_printer(g); @@ -50,8 +71,19 @@ static void dump_cf_node(FILE* output, const CFNode* n) { print(p, "%s: \n%d: ", abs_name, bb->id); - print_node_helper(p, body); - print(p, "\\l"); + if (getenv("SHADY_CFG_SCOPE_ONLY")) { + const Nodes* scope = find_scope_info(bb); + if (scope) { + for (size_t i = 0; i < scope->count; i++) { + print(p, "%d", scope->nodes[i]->id); + if (i + 1 < scope->count) + print(p, ", "); + } + } + } else { + print_node_helper(p, body); + print(p, "\\l"); + } print(p, "rpo: %d, idom: %s, sdom: %s", n->rpo_index, n->idom ? get_abstraction_name_safe(n->idom->node) : "null", n->structured_idom ? get_abstraction_name_safe(n->structured_idom->node) : "null"); String label = printer_growy_unwrap(p); @@ -88,7 +120,7 @@ static void dump_cfg(FILE* output, CFG* cfg) { case StructuredEnterBodyEdge: edge_color = "blue"; break; case StructuredLeaveBodyEdge: edge_color = "red"; break; case StructuredTailEdge: edge_style = "dashed"; break; - case StructuredLoopContinue: edge_style = "dotted"; break; + case StructuredLoopContinue: edge_style = "dotted"; edge_color = "orange"; break; default: break; } diff --git a/src/shady/print.c b/src/shady/print.c index f91ff6347..a59df0f24 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1151,7 +1151,10 @@ static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op) void print_node_operand(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, const Node* op) { print_operand_name_helper(ctx, name); + if (op_class == NcBasic_block) + print(ctx->printer, BYELLOW); print_operand_helper(ctx, op_class, op); + print(ctx->printer, RESET); } void print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, Nodes ops) { From a6ef11d050b8410cbe737302916a92f4c25d80d4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 16:07:14 +0200 Subject: [PATCH 530/693] scope2control: deal with uniform values --- src/shady/passes/scope2control.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 8e6287f81..c873c398b 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -123,6 +123,12 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab assert(jp_type->tag == JoinPointType_TAG); Nodes results = gen_control(bb, jp_type->payload.join_point_type.yield_types, control_case); + Nodes original_params = get_abstraction_params(dst); + for (size_t j = 0; j < results.count; j++) { + if (is_qualified_type_uniform(original_params.nodes[j]->type)) + results = change_node_at_index(a, results, j, gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(results.nodes[j]))); + } + c = c2; set_abstraction_body(c2, finish_body(bb, jump_helper(a, find_processed(r, dst), results, bb_mem(bb)))); } From 8d0a3b26a57b633efb0aaf7b8c75edbaacef02b5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 16:07:34 +0200 Subject: [PATCH 531/693] scope_heuristics: improved --- src/shady/passes/scope_heuristic.c | 37 +++++++++++++++++------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index cf4a45190..aaa7c58b3 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -60,10 +60,14 @@ static void paint_dominated_up_to_postdom(CFNode* n, IrArena* a, Nodes* arr, con arr[n->rpo_index] = prepend_nodes(a, arr[n->rpo_index], prefix); } -static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* flipped, LoopTree* lt) { +static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* flipped, LTNode* loop, LoopTree* lt) { + LTNode* ltn = looptree_lookup(lt, n->node); + if (ltn->parent != loop) + return; + for (size_t i = 0; i < entries_count_list(n->dominates); i++) { CFNode* dominated = read_list(CFNode*, n->dominates)[i]; - visit_acyclic_cfg_domtree(dominated, a, arr, flipped, lt); + visit_acyclic_cfg_domtree(dominated, a, arr, flipped, loop, lt); } CFNode* src = n; @@ -91,9 +95,11 @@ static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* fl static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, LoopTree* lt, LTNode* node) { if (node->type == LF_HEAD) { Nodes surrounding = empty(a); + bool is_loop = false; for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { CFNode* n = read_list(CFNode*, node->cf_nodes)[i]; surrounding = append_nodes(a, surrounding, n->node); + is_loop = true; } for (size_t i = 0; i < entries_count_list(node->lf_children); i++) { @@ -101,7 +107,15 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, visit_looptree(a, arr, fn, flipped, lt, n); } - if (entries_count_list(node->cf_nodes) > 0) + assert(entries_count_list(node->cf_nodes) < 2); + CFG* sub_cfg = build_cfg(fn, is_loop ? read_list(CFNode*, node->cf_nodes)[0]->node : fn, (CFGBuildConfig) { + .include_structured_tails = true, + .lt = lt + }); + + visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, node, lt); + + if (is_loop > 0) surrounding = prepend_nodes(a, surrounding, string_lit_helper(a, unique_name(a, "loop_body"))); visit_looptree_prepend(a, arr, node, surrounding); @@ -113,14 +127,6 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, arr[n->rpo_index] = nodes(a, old.count - 1, &old.nodes[0]); } - assert(entries_count_list(node->cf_nodes) < 2); - CFG* sub_cfg = build_cfg(fn, surrounding.count == 1 ? surrounding.nodes[0] : fn, (CFGBuildConfig) { - .include_structured_tails = true, - .lt = lt - }); - - // visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, lt); - destroy_cfg(sub_cfg); } } @@ -139,22 +145,21 @@ static bool loop_depth(LTNode* a) { } static Nodes* compute_scope_depth(IrArena* a, CFG* cfg) { - //CFG* flipped = build_fn_cfg_flipped(cfg->entry->node); + CFG* flipped = build_fn_cfg_flipped(cfg->entry->node); LoopTree* lt = build_loop_tree(cfg); Nodes* arr = calloc(sizeof(Nodes), cfg->size); for (size_t i = 0; i < cfg->size; i++) arr[i] = empty(a); - //visit_looptree(a, arr, cfg->entry->node, flipped, lt, lt->root); - visit_looptree(a, arr, cfg->entry->node, NULL, lt, lt->root); + visit_looptree(a, arr, cfg->entry->node, flipped, lt, lt->root); // we don't want to cause problems by holding onto pointless references... for (size_t i = 0; i < cfg->size; i++) arr[i] = to_ids(a, arr[i]); destroy_loop_tree(lt); - //destroy_cfg(flipped); + destroy_cfg(flipped); return arr; } @@ -173,7 +178,7 @@ static const Node* process(Context* ctx, const Node* node) { register_processed(r, get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new_fn, finish_body(bb, rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); destroy_cfg(fn_ctx.cfg); - free(ctx->depth_per_rpo); + free(fn_ctx.depth_per_rpo); return new_fn; } case BasicBlock_TAG: { From 1d8bce5d0b08df506e5edba2979cfa2add1d970c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 16:53:39 +0200 Subject: [PATCH 532/693] lift_everything: actually don't lift structured targets --- src/shady/analysis/cfg.c | 6 +- src/shady/passes/lift_everything.c | 4 + src/shady/passes/reconvergence_heuristics.c | 0 .../acyclic_simple_with_arg.slim | 158 ++++++++++++++++++ 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 src/shady/passes/reconvergence_heuristics.c create mode 100644 test/reconvergence_heuristics/acyclic_simple_with_arg.slim diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 7b3e0ad81..362edf51d 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -478,7 +478,11 @@ void compute_rpo(CFG* cfg) { } bool is_cfnode_structural_target(CFNode* cfn) { - return entries_count_list(cfn->pred_edges) == 1 && read_list(CFEdge, cfn->pred_edges)[0].type != JumpEdge; + for (size_t i = 0; i < entries_count_list(cfn->pred_edges); i++) { + if (read_list(CFEdge, cfn->pred_edges)[0].type != JumpEdge) + return true; + } + return false; } CFNode* least_common_ancestor(CFNode* i, CFNode* j) { diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index c6cb081e5..a2f6536c0 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -39,6 +39,9 @@ static const Node* process(Context* ctx, const Node* node) { return new_fn; } case BasicBlock_TAG: { + CFNode* n = cfg_lookup(ctx->cfg, node); + if (is_cfnode_structural_target(n)) + break; struct Dict* frontier = free_frontier(ctx->scheduler, ctx->cfg, node); // insert_dict(const Node*, Dict*, ctx->lift, node, frontier); @@ -76,6 +79,7 @@ static const Node* process(Context* ctx, const Node* node) { register_processed(&fn_ctx->rewriter, node, new_bb); set_abstraction_body(new_bb, rewrite_node(&bb_ctx.rewriter, get_abstraction_body(node))); + destroy_rewriter(&bb_ctx.rewriter); return new_bb; } case Jump_TAG: { diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c new file mode 100644 index 000000000..e69de29bb diff --git a/test/reconvergence_heuristics/acyclic_simple_with_arg.slim b/test/reconvergence_heuristics/acyclic_simple_with_arg.slim new file mode 100644 index 000000000..e3967d59a --- /dev/null +++ b/test/reconvergence_heuristics/acyclic_simple_with_arg.slim @@ -0,0 +1,158 @@ +@Exported @Restructure +fn f1 i32(varying bool b) { + jump bb1(); + + cont bb1() { + branch(b, bb2(), bb3()); + } + + cont bb2() { + jump bb4(); + } + + cont bb3() { + jump bb4(); + } + + cont bb4() { + return (3); + } +} + +@Exported @Restructure +fn f2 i32(varying bool b) { + jump bb1(); + + cont bb1() { + branch(b, bb2(), bb3()); + } + + cont bb2() { + jump bb4(5); + } + + cont bb3() { + jump bb4(4); + } + + cont bb4(varying i32 r) { + return (r); + } +} + +@Exported @Restructure +fn g i32(varying bool b) { + branch(b, bb1(), bb2()); + + cont bb1() { + jump bb3(); + } + + cont bb2 () { + jump bb3(); + } + + cont bb3() { + jump bb4(); + } + + cont bb4() { + return (9); + } +} + +@Exported @Restructure +fn hfixed i32(varying bool b) { + branch(b, bb1(), bb2()); + + cont bb1() { + branch(b, bb3(), bb4b()); + } + + cont bb2 () { + jump bb4(); + } + + cont bb3() { + jump bb5(); + } + + cont bb4() { + jump bb5(); + } + + cont bb4b() { + jump bb5(); + } + + cont bb5() { + return (9); + } +} + +@Exported @Restructure +fn hnot1 i32(varying bool b) { + val not_b = ! b; + + branch(not_b, bb1(), bb2()); + + cont bb1 () { + jump bb3(); + } + + cont bb2() { + jump bb3(); + } + + cont bb3() { + return (9); + } +} + +@Exported @Restructure +fn hnot2 i32(varying bool b) { + branch(b, bb1(), bb2()); + + cont bb1() { + val not_b = ! b; + + branch(not_b, bb3(), bb4b()); + } + + cont bb2 () { + jump bb4(); + } + + cont bb3() { + jump bb5(); + } + + cont bb4() { + jump bb5(); + } + + cont bb4b() { + jump bb5(); + } + + cont bb5() { + return (9); + } +} + +@Exported @Restructure +fn i i32(varying bool b) { + branch(b, bb1(), bb2()); + + cont bb1() { + jump bb2(); + } + + cont bb2 () { + jump bb3(); + } + + cont bb3() { + return (0); + } +} From 0566bdfba4a2e44c40ec724702f7f40a0abb2d9d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 16:54:12 +0200 Subject: [PATCH 533/693] fix memory leak in body_builder --- src/shady/body_builder.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 7be6d810a..c2df299fa 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -224,6 +224,7 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { IrArena* arena = bb->arena; assert(!bb->mem && !bb->block_entry_mem && entries_count_list(bb->stack) == 0); + cancel_body(bb); return maybe_tuple_helper(arena, values); } From cdd486aba15b25460ef75a302dc97c91ab7fbf66 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 16:55:00 +0200 Subject: [PATCH 534/693] re-added old reconvergence heuristics pass --- src/shady/compile.c | 9 +- src/shady/passes/CMakeLists.txt | 1 + src/shady/passes/passes.h | 2 +- src/shady/passes/reconvergence_heuristics.c | 498 ++++++++++++++++++ test/CMakeLists.txt | 1 + test/reconvergence_heuristics/acyclic1.slim | 14 +- test/reconvergence_heuristics/acyclic2.slim | 2 +- .../acyclic_evil.slim | 2 +- .../acyclic_simple_with_arg.slim | 156 +----- test/reconvergence_heuristics/loops1.slim | 8 +- test/reconvergence_heuristics/loops2.slim | 4 +- .../multi_exit_loop.slim | 4 +- .../nested_loops.slim | 2 +- 13 files changed, 533 insertions(+), 170 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index b1b1838a9..92fcc6563 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -50,16 +50,17 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { log_module(DEBUG, config, *pmod); if (config->input_cf.has_scope_annotations) { - if (config->hacks.restructure_everything) { - RUN_PASS(scope_heuristic) - } + // RUN_PASS(scope_heuristic) RUN_PASS(lift_everything) RUN_PASS(scope2control) + } else { + RUN_PASS(lift_everything) + RUN_PASS(reconvergence_heuristics) } if (config->dynamic_scheduling) { add_scheduler_source(config, *pmod); - } + } RUN_PASS(eliminate_inlineable_constants) //RUN_PASS(reconvergence_heuristics) diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index 4ae78486a..d9125f631 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -37,4 +37,5 @@ target_sources(shady PRIVATE scope2control.c lift_everything.c scope_heuristic.c + reconvergence_heuristics.c ) diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 5758febff..159511c1d 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -21,7 +21,7 @@ RewritePass scope2control; RewritePass lift_everything; RewritePass scope_heuristic; /// Try to identify reconvergence points throughout the program for unstructured control flow programs -//RewritePass reconvergence_heuristics; +RewritePass reconvergence_heuristics; /// @} diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index e69de29bb..11d6b75f8 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -0,0 +1,498 @@ +#include "shady/pass.h" + +#include "../type.h" +#include "../ir_private.h" +#include "../transform/ir_gen_helpers.h" + +#include "../analysis/cfg.h" +#include "../analysis/looptree.h" + +#include "list.h" +#include "dict.h" +#include "log.h" +#include "portability.h" +#include "util.h" + +#include + +typedef struct Context_ { + Rewriter rewriter; + const CompilerConfig* config; + const Node* current_fn; + const Node* current_abstraction; + CFG* fwd_cfg; + CFG* rev_cfg; + LoopTree* current_looptree; +} Context; + +static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { + LTNode* lt_node = looptree_lookup(lt, block); + assert(lt_node); + LTNode* parent = lt_node->parent; + assert(parent); + + while (parent) { + if (entries_count_list(parent->cf_nodes) != 1) + return false; + + if (read_list(CFNode*, parent->cf_nodes)[0]->node == entry) + return true; + + parent = parent->parent; + } + + return false; +} + +//TODO: This is massively inefficient. +static void gather_exiting_nodes(LoopTree* lt, const CFNode* entry, const CFNode* block, struct List* exiting_nodes) { + if (!in_loop(lt, entry->node, block->node)) { + append_list(CFNode*, exiting_nodes, block); + return; + } + + for (size_t i = 0; i < entries_count_list(block->dominates); i++) { + const CFNode* target = read_list(CFNode*, block->dominates)[i]; + gather_exiting_nodes(lt, entry, target, exiting_nodes); + } +} + +static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { + const Node* v; + size_t i = 0; + while (dict_iter(free_set, &i, &v, NULL)) { + if (find_key_dict(const Node*, bound_set, v)) + continue; + + log_string(DEBUGVV, "Found variable used outside it's control scope: "); + log_node(DEBUGVV, v); + log_string(DEBUGVV, " (exiting_node:"); + log_node(DEBUGVV, exiting_node); + log_string(DEBUGVV, " )\n"); + + append_list(const Node*, leaking, v); + } +} + +static const Node* process_abstraction(Context* ctx, const Node* node) { + assert(is_abstraction(node)); + Context new_context = *ctx; + ctx = &new_context; + ctx->current_abstraction = node; + Rewriter* rewriter = &ctx->rewriter; + IrArena* arena = rewriter->dst_arena; + + CFNode* current_node = cfg_lookup(ctx->fwd_cfg, node); + LTNode* lt_node = looptree_lookup(ctx->current_looptree, node); + LTNode* loop_header = NULL; + + assert(current_node); + assert(lt_node); + + bool is_loop_entry = false; + if (lt_node->parent && lt_node->parent->type == LF_HEAD) { + if (entries_count_list(lt_node->parent->cf_nodes) == 1) + if (read_list(CFNode*, lt_node->parent->cf_nodes)[0]->node == node) { + loop_header = lt_node->parent; + assert(loop_header->type == LF_HEAD); + assert(entries_count_list(loop_header->cf_nodes) == 1 && "only reducible loops are handled"); + is_loop_entry = true; + } + } + + if (is_loop_entry) { + assert(!is_function(node)); + + struct List* exiting_nodes = new_list(CFNode*); + gather_exiting_nodes(ctx->current_looptree, current_node, current_node, exiting_nodes); + + for (size_t i = 0; i < entries_count_list(exiting_nodes); i++) { + debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(read_list(CFNode*, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); + } + + size_t exiting_nodes_count = entries_count_list(exiting_nodes); + if (exiting_nodes_count > 0) { + Nodes nparams = recreate_params(rewriter, get_abstraction_params(node)); + Node* loop_container = basic_block(arena, nparams, node->payload.basic_block.name); + BodyBuilder* outer_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_container)); + Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); + + CFNode* cf_pre = cfg_lookup(ctx->fwd_cfg, node); + // assert(cf_pre->idom && "cfg entry nodes can't be loop headers anyhow"); + // cf_pre = cf_pre->idom; + // CFNodeVariables* pre = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_pre); + + LARRAY(Nodes, exit_param_allocas, exiting_nodes_count); + LARRAY(struct List*, leaking, exiting_nodes_count); + LARRAY(Nodes, exit_fwd_allocas, exiting_nodes_count); + for (size_t i = 0; i < exiting_nodes_count; i++) { + CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + Nodes exit_param_types = rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); + LARRAY(const Node*, exit_param_allocas_tmp, exit_param_types.count); + for (size_t j = 0; j < exit_param_types.count; j++) + exit_param_allocas_tmp[j] = gen_stack_alloc(outer_bb, get_unqualified_type(exit_param_types.nodes[j])); + exit_param_allocas[i] = nodes(arena, exit_param_types.count, exit_param_allocas_tmp); + + // Search for what's required after the exit but not in scope at the loop header + // this is similar to the LCSSA constraint, but here it's because controls have hard scopes + CFNode* cf_post = cfg_lookup(ctx->fwd_cfg, exiting_node->node); + // CFNodeVariables* post = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_post); + leaking[i] = new_list(const Type*); + // find_unbound_vars(exiting_node->node, pre->bound_by_dominators_set, post->free_set, leaking[i]); + + size_t leaking_count = entries_count_list(leaking[i]); + LARRAY(const Node*, exit_fwd_allocas_tmp, leaking_count); + for (size_t j = 0; j < leaking_count; j++) + exit_fwd_allocas_tmp[j] = gen_stack_alloc(outer_bb, rewrite_node(rewriter, get_unqualified_type(read_list(const Node*, leaking[i])[j]->type))); + exit_fwd_allocas[i] = nodes(arena, leaking_count, exit_fwd_allocas_tmp); + } + + const Node* exit_destination_alloca = NULL; + if (exiting_nodes_count > 1) + exit_destination_alloca = gen_stack_alloc(outer_bb, int32_type(arena)); + + const Node* join_token_exit = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { + .yield_types = empty(arena) + }), true), "jp_exit"); + + const Node* join_token_continue = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { + .yield_types = inner_yield_types + }), true), "jp_continue"); + + LARRAY(Node*, exit_wrappers, exiting_nodes_count); + LARRAY(Node*, exit_helpers, exiting_nodes_count); + for (size_t i = 0; i < exiting_nodes_count; i++) { + exit_helpers[i] = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_helper_%d", i)); + + CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + assert(exiting_node->node && exiting_node->node->tag != Function_TAG); + Nodes exit_wrapper_params = recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); + + Node* pre_join_exit_bb = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); + set_abstraction_body(pre_join_exit_bb, jump_helper(arena, exit_helpers[i], empty(arena), get_abstraction_mem(pre_join_exit_bb))); + exit_wrappers[i] = pre_join_exit_bb; + } + + Nodes continue_wrapper_params = recreate_params(rewriter, get_abstraction_params(node)); + Node* continue_wrapper = basic_block(arena, continue_wrapper_params, "continue"); + const Node* continue_wrapper_body = join(arena, (Join) { + .join_point = join_token_continue, + .args = continue_wrapper_params, + .mem = get_abstraction_mem(continue_wrapper), + }); + set_abstraction_body(continue_wrapper, continue_wrapper_body); + + // replace the exit nodes by the exit wrappers + LARRAY(const Node*, cached_exits, exiting_nodes_count); + for (size_t i = 0; i < exiting_nodes_count; i++) { + CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + cached_exits[i] = search_processed(rewriter, exiting_node->node); + if (cached_exits[i]) + remove_dict(const Node*, rewriter->map, exiting_node->node); + register_processed(rewriter, exiting_node->node, exit_wrappers[i]); + } + // ditto for the loop entry and the continue wrapper + const Node* cached_entry = search_processed(rewriter, node); + if (cached_entry) + remove_dict(const Node*, rewriter->map, node); + register_processed(rewriter, node, continue_wrapper); + + // make sure we haven't started rewriting this... + // for (size_t i = 0; i < old_params.count; i++) { + // assert(!search_processed(rewriter, old_params.nodes[i])); + // } + + struct Dict* old_map = rewriter->map; + rewriter->map = clone_dict(rewriter->map); + Nodes inner_loop_params = recreate_params(rewriter, get_abstraction_params(node)); + register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); + Node* inner_control_case = case_(arena, singleton(join_token_continue)); + register_processed(rewriter, get_abstraction_mem(node), get_abstraction_mem(inner_control_case)); + const Node* loop_body = recreate_node_identity(rewriter, get_abstraction_body(node)); + + // save the context + for (size_t i = 0; i < exiting_nodes_count; i++) { + CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + assert(exiting_node->node && exiting_node->node->tag != Function_TAG); + Nodes exit_wrapper_params = get_abstraction_params(exit_wrappers[i]); + BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_helpers[i])); + + for (size_t j = 0; j < exit_param_allocas[i].count; j++) + gen_store(exit_wrapper_bb, exit_param_allocas[i].nodes[j], exit_wrapper_params.nodes[j]); + if (exiting_nodes_count > 1) + gen_store(exit_wrapper_bb, exit_destination_alloca, int32_literal(arena, i)); + + for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { + gen_store(exit_wrapper_bb, exit_fwd_allocas[i].nodes[j], rewrite_node(rewriter, read_list(const Node*, leaking[i])[j])); + } + + set_abstraction_body(exit_helpers[i], finish_body_with_join(exit_wrapper_bb, join_token_exit, empty(arena))); + } + + set_abstraction_body(inner_control_case, loop_body); + + destroy_dict(rewriter->map); + rewriter->map = old_map; + //register_processed_list(rewriter, get_abstraction_params(node), nparams); + + // restore the old context + for (size_t i = 0; i < exiting_nodes_count; i++) { + remove_dict(const Node*, rewriter->map, read_list(CFNode*, exiting_nodes)[i]->node); + if (cached_exits[i]) + register_processed(rewriter, read_list(CFNode*, exiting_nodes)[i]->node, cached_exits[i]); + } + remove_dict(const Node*, rewriter->map, node); + if (cached_entry) + register_processed(rewriter, node, cached_entry); + + Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); + BodyBuilder* inner_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_outer)); + Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); + + set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); + Node* outer_control_case = case_(arena, singleton(join_token_exit)); + set_abstraction_body(outer_control_case, jump(arena, (Jump) { + .target = loop_outer, + .args = nparams, + .mem = get_abstraction_mem(outer_control_case), + })); + gen_control(outer_bb, empty(arena), outer_control_case); + + LARRAY(const Node*, exit_numbers, exiting_nodes_count); + LARRAY(const Node*, exit_jumps, exiting_nodes_count); + for (size_t i = 0; i < exiting_nodes_count; i++) { + CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + + Node* exit_bb = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); + BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); + + // recover the context + for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { + const Node* recovered = gen_load(exit_recover_bb, exit_fwd_allocas[i].nodes[j]); + register_processed(rewriter, read_list(const Node*, leaking[i])[j], recovered); + } + + const Node* recreated_exit = rewrite_node(rewriter, exiting_node->node); + + LARRAY(const Node*, recovered_args, exit_param_allocas[i].count); + for (size_t j = 0; j < exit_param_allocas[i].count; j++) + recovered_args[j] = gen_load(exit_recover_bb, exit_param_allocas[i].nodes[j]); + + exit_numbers[i] = int32_literal(arena, i); + set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, nodes(arena, exit_param_allocas[i].count, recovered_args))); + exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena), bb_mem(outer_bb)); + destroy_list(leaking[i]); + } + + const Node* outer_body; + if (exiting_nodes_count == 1) + outer_body = finish_body(outer_bb, exit_jumps[0]); + else { + const Node* loaded_destination = gen_load(outer_bb, exit_destination_alloca); + outer_body = finish_body(outer_bb, br_switch(arena, (Switch) { + .switch_value = loaded_destination, + .default_jump = exit_jumps[0], + .case_values = nodes(arena, exiting_nodes_count, exit_numbers), + .case_jumps = nodes(arena, exiting_nodes_count, exit_jumps), + .mem = bb_mem(outer_bb) + })); + } + set_abstraction_body(loop_container, outer_body); + destroy_list(exiting_nodes); + return loop_container; + } + + destroy_list(exiting_nodes); + } + + return recreate_node_identity(&ctx->rewriter, node); +} + +static const Node* process_node(Context* ctx, const Node* node) { + assert(node); + + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + + Context new_context = *ctx; + + switch (node->tag) { + case Function_TAG: { + ctx = &new_context; + ctx->current_fn = NULL; + if (!(lookup_annotation(node, "Restructure") || ctx->config->hacks.restructure_everything)) + break; + + ctx->current_fn = node; + ctx->fwd_cfg = build_fn_cfg(ctx->current_fn); + ctx->rev_cfg = build_fn_cfg_flipped(ctx->current_fn); + ctx->current_looptree = build_loop_tree(ctx->fwd_cfg); + + const Node* new = process_abstraction(ctx, node);; + + destroy_cfg(ctx->fwd_cfg); + destroy_cfg(ctx->rev_cfg); + destroy_loop_tree(ctx->current_looptree); + return new; + } + case Constant_TAG: { + ctx = &new_context; + ctx->current_fn = NULL; + r = &ctx->rewriter; + break; + } + case BasicBlock_TAG: + if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) + break; + return process_abstraction(ctx, node); + case Branch_TAG: { + Branch payload = node->payload.branch; + if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) + break; + assert(ctx->fwd_cfg); + + CFNode* cfnode = cfg_lookup(ctx->rev_cfg, ctx->current_abstraction); + const Node* idom = NULL; + + LTNode* current_loop = looptree_lookup(ctx->current_looptree, ctx->current_abstraction)->parent; + assert(current_loop); + + if (entries_count_list(current_loop->cf_nodes)) { + bool leaves_loop = false; + CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); + for (size_t i = 0; i < entries_count_list(current_node->succ_edges); i++) { + CFEdge edge = read_list(CFEdge, current_node->succ_edges)[i]; + LTNode* lt_target = looptree_lookup(ctx->current_looptree, edge.dst->node); + + if (lt_target->parent != current_loop) { + leaves_loop = true; + break; + } + } + + if (!leaves_loop) { + const Node* current_loop_head = read_list(CFNode*, current_loop->cf_nodes)[0]->node; + CFG* loop_cfg = build_cfg(ctx->current_fn, current_loop_head, (CFGBuildConfig) { + .include_structured_tails = true, + .lt = ctx->current_looptree, + .flipped = true + }); + CFNode* idom_cf = cfg_lookup(loop_cfg, ctx->current_abstraction)->idom; + if (idom_cf) + idom = idom_cf->node; + destroy_cfg(loop_cfg); + } + } else { + idom = cfnode->idom->node; + } + + if (!idom) { + break; + } + + if (cfg_lookup(ctx->fwd_cfg, idom)->idom->node != ctx->current_abstraction) + break; + + assert(is_abstraction(idom) && idom->tag != Function_TAG); + + LTNode* lt_node = looptree_lookup(ctx->current_looptree, ctx->current_abstraction); + LTNode* idom_lt_node = looptree_lookup(ctx->current_looptree, idom); + CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); + + assert(lt_node); + assert(idom_lt_node); + assert(current_node); + + Node* fn = (Node*) find_processed(r, ctx->current_fn); + + //Regular if/then/else case. Control flow joins at the immediate post dominator. + Nodes yield_types; + Nodes exit_args; + + Nodes old_params = get_abstraction_params(idom); + + if (old_params.count == 0) { + yield_types = empty(a); + exit_args = empty(a); + } else { + LARRAY(const Node*, types,old_params.count); + LARRAY(const Node*, inner_args,old_params.count); + + for (size_t j = 0; j < old_params.count; j++) { + //TODO: Is this correct? + assert(old_params.nodes[j]->tag == Param_TAG); + const Node* qualified_type = rewrite_node(r, old_params.nodes[j]->payload.param.type); + //const Node* qualified_type = rewrite_node(rewriter, old_params.nodes[j]->type); + + //This should always contain a qualified type? + //if (contains_qualified_type(types[j])) + types[j] = get_unqualified_type(qualified_type); + + inner_args[j] = param(a, qualified_type, old_params.nodes[j]->payload.param.name); + } + + yield_types = nodes(a, old_params.count, types); + exit_args = nodes(a, old_params.count, inner_args); + } + + const Node* join_token = param(a, qualified_type_helper(join_point_type(a, (JoinPointType) { + .yield_types = yield_types + }), true), "jp_postdom"); + + Node* pre_join = basic_block(a, exit_args, format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); + set_abstraction_body(pre_join, join(a, (Join) { + .join_point = join_token, + .args = exit_args, + .mem = get_abstraction_mem(pre_join), + })); + + const Node* cached = search_processed(r, idom); + if (cached) + remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); + for (size_t i = 0; i < old_params.count; i++) { + assert(!search_processed(r, old_params.nodes[i])); + } + + register_processed(r, idom, pre_join); + + remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); + if (cached) + register_processed(r, idom, cached); + + Node* control_case = case_(a, singleton(join_token)); + const Node* inner_terminator = branch(a, (Branch) { + .mem = get_abstraction_mem(control_case), + .condition = rewrite_node(r, payload.condition), + .true_jump = jump_helper(a, rewrite_node(r, payload.true_jump->payload.jump.target), rewrite_nodes(r, payload.true_jump->payload.jump.args), get_abstraction_mem(control_case)), + .false_jump = jump_helper(a, rewrite_node(r, payload.false_jump->payload.jump.target), rewrite_nodes(r, payload.false_jump->payload.jump.args), get_abstraction_mem(control_case)), + }); + set_abstraction_body(control_case, inner_terminator); + const Node* join_target = rewrite_node(r, idom); + + BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); + Nodes results = gen_control(bb, yield_types, control_case); + return finish_body_with_jump(bb, join_target, results); + } + default: break; + } + return recreate_node_identity(r, node); +} + +Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); + Module* dst = new_module(a, get_module_name(src)); + + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .config = config, + .current_fn = NULL, + .fwd_cfg = NULL, + .rev_cfg = NULL, + .current_looptree = NULL, + }; + + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + return dst; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0b546f404..e3159cf2d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -35,6 +35,7 @@ if (BUILD_TESTING) list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic1.slim) list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic2.slim) list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic_evil.slim) + list(APPEND BASIC_TESTS reconvergence_heuristics/acyclic_simple_with_arg.slim) list(APPEND BASIC_TESTS reconvergence_heuristics/loops1.slim) list(APPEND BASIC_TESTS reconvergence_heuristics/loops2.slim) list(APPEND BASIC_TESTS reconvergence_heuristics/multi_exit_loop.slim) diff --git a/test/reconvergence_heuristics/acyclic1.slim b/test/reconvergence_heuristics/acyclic1.slim index 0f4993c08..e3967d59a 100644 --- a/test/reconvergence_heuristics/acyclic1.slim +++ b/test/reconvergence_heuristics/acyclic1.slim @@ -1,4 +1,4 @@ -@Restructure +@Exported @Restructure fn f1 i32(varying bool b) { jump bb1(); @@ -19,7 +19,7 @@ fn f1 i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn f2 i32(varying bool b) { jump bb1(); @@ -40,7 +40,7 @@ fn f2 i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn g i32(varying bool b) { branch(b, bb1(), bb2()); @@ -61,7 +61,7 @@ fn g i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn hfixed i32(varying bool b) { branch(b, bb1(), bb2()); @@ -90,7 +90,7 @@ fn hfixed i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn hnot1 i32(varying bool b) { val not_b = ! b; @@ -109,7 +109,7 @@ fn hnot1 i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn hnot2 i32(varying bool b) { branch(b, bb1(), bb2()); @@ -140,7 +140,7 @@ fn hnot2 i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn i i32(varying bool b) { branch(b, bb1(), bb2()); diff --git a/test/reconvergence_heuristics/acyclic2.slim b/test/reconvergence_heuristics/acyclic2.slim index d3c7c8c8a..187508c7d 100644 --- a/test/reconvergence_heuristics/acyclic2.slim +++ b/test/reconvergence_heuristics/acyclic2.slim @@ -1,4 +1,4 @@ -@Restructure +@Exported @Restructure fn h1 i32(varying bool b) { branch(b, bb1(), bb2()); diff --git a/test/reconvergence_heuristics/acyclic_evil.slim b/test/reconvergence_heuristics/acyclic_evil.slim index 0cb16b328..db34620e5 100644 --- a/test/reconvergence_heuristics/acyclic_evil.slim +++ b/test/reconvergence_heuristics/acyclic_evil.slim @@ -1,4 +1,4 @@ -@Restructure +@Exported @Restructure fn f i32(varying bool b) { jump A(); diff --git a/test/reconvergence_heuristics/acyclic_simple_with_arg.slim b/test/reconvergence_heuristics/acyclic_simple_with_arg.slim index e3967d59a..8c66ec657 100644 --- a/test/reconvergence_heuristics/acyclic_simple_with_arg.slim +++ b/test/reconvergence_heuristics/acyclic_simple_with_arg.slim @@ -1,158 +1,20 @@ @Exported @Restructure -fn f1 i32(varying bool b) { +fn f1 i32(varying bool b, varying i32 i) { jump bb1(); cont bb1() { - branch(b, bb2(), bb3()); + branch(b, bb2(i), bb3(6, 6)); } - cont bb2() { - jump bb4(); + cont bb2(varying i32 j) { + jump bb4(j); } - cont bb3() { - jump bb4(); + cont bb3(uniform i32 x, uniform i32 y) { + jump bb4(x + y); } - cont bb4() { - return (3); + cont bb4(varying i32 l) { + return (l + i); } -} - -@Exported @Restructure -fn f2 i32(varying bool b) { - jump bb1(); - - cont bb1() { - branch(b, bb2(), bb3()); - } - - cont bb2() { - jump bb4(5); - } - - cont bb3() { - jump bb4(4); - } - - cont bb4(varying i32 r) { - return (r); - } -} - -@Exported @Restructure -fn g i32(varying bool b) { - branch(b, bb1(), bb2()); - - cont bb1() { - jump bb3(); - } - - cont bb2 () { - jump bb3(); - } - - cont bb3() { - jump bb4(); - } - - cont bb4() { - return (9); - } -} - -@Exported @Restructure -fn hfixed i32(varying bool b) { - branch(b, bb1(), bb2()); - - cont bb1() { - branch(b, bb3(), bb4b()); - } - - cont bb2 () { - jump bb4(); - } - - cont bb3() { - jump bb5(); - } - - cont bb4() { - jump bb5(); - } - - cont bb4b() { - jump bb5(); - } - - cont bb5() { - return (9); - } -} - -@Exported @Restructure -fn hnot1 i32(varying bool b) { - val not_b = ! b; - - branch(not_b, bb1(), bb2()); - - cont bb1 () { - jump bb3(); - } - - cont bb2() { - jump bb3(); - } - - cont bb3() { - return (9); - } -} - -@Exported @Restructure -fn hnot2 i32(varying bool b) { - branch(b, bb1(), bb2()); - - cont bb1() { - val not_b = ! b; - - branch(not_b, bb3(), bb4b()); - } - - cont bb2 () { - jump bb4(); - } - - cont bb3() { - jump bb5(); - } - - cont bb4() { - jump bb5(); - } - - cont bb4b() { - jump bb5(); - } - - cont bb5() { - return (9); - } -} - -@Exported @Restructure -fn i i32(varying bool b) { - branch(b, bb1(), bb2()); - - cont bb1() { - jump bb2(); - } - - cont bb2 () { - jump bb3(); - } - - cont bb3() { - return (0); - } -} +} \ No newline at end of file diff --git a/test/reconvergence_heuristics/loops1.slim b/test/reconvergence_heuristics/loops1.slim index a516375f7..cb5d435e3 100644 --- a/test/reconvergence_heuristics/loops1.slim +++ b/test/reconvergence_heuristics/loops1.slim @@ -1,4 +1,4 @@ -@Restructure +@Exported @Restructure fn exitingloop_controlblock varying i32(varying bool b) { jump pre_entry(); @@ -27,7 +27,7 @@ fn exitingloop_controlblock varying i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn exitingloop_function varying i32(varying bool b) { jump entry(); @@ -52,7 +52,7 @@ fn exitingloop_function varying i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn exitingloop_values varying i32(varying i32 n) { var i32 r = n + 0; var i32 k = 0; @@ -76,7 +76,7 @@ fn exitingloop_values varying i32(varying i32 n) { } } -@Restructure +@Exported @Restructure fn exitingloop_values_from_loop varying i32(varying i32 n) { var i32 r = n + 0; var i32 k = 0; diff --git a/test/reconvergence_heuristics/loops2.slim b/test/reconvergence_heuristics/loops2.slim index e82fd979c..15113ac67 100644 --- a/test/reconvergence_heuristics/loops2.slim +++ b/test/reconvergence_heuristics/loops2.slim @@ -1,4 +1,4 @@ -@Restructure +@Exported @Restructure fn minimal_loop varying i32(varying bool b) { jump entry(); @@ -15,7 +15,7 @@ fn minimal_loop varying i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn reconverge_inside_loop varying i32(varying bool b) { jump entry(); diff --git a/test/reconvergence_heuristics/multi_exit_loop.slim b/test/reconvergence_heuristics/multi_exit_loop.slim index 348d802ca..2d9f37b10 100644 --- a/test/reconvergence_heuristics/multi_exit_loop.slim +++ b/test/reconvergence_heuristics/multi_exit_loop.slim @@ -1,4 +1,4 @@ -@Restructure +@Exported @Restructure fn loop_with_two_exits varying i32(varying bool b) { jump entry(); @@ -23,7 +23,7 @@ fn loop_with_two_exits varying i32(varying bool b) { } } -@Restructure +@Exported @Restructure fn loop_with_two_exits_and_values varying i32(varying bool b) { jump entry(); diff --git a/test/reconvergence_heuristics/nested_loops.slim b/test/reconvergence_heuristics/nested_loops.slim index d2bbf3ff4..2b9727092 100644 --- a/test/reconvergence_heuristics/nested_loops.slim +++ b/test/reconvergence_heuristics/nested_loops.slim @@ -1,4 +1,4 @@ -@Restructure +@Exported @Restructure fn f i32(varying bool b, varying i32 i) { jump A(); From 626c6b1f6fde4b40e5ff6b4960080735ef44f062 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 16:55:14 +0200 Subject: [PATCH 535/693] scope2control: fix memory leaks --- src/shady/passes/scope2control.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index c873c398b..53a105073 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -314,18 +314,19 @@ Module* scope2control(const CompilerConfig* config, Module* src) { ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; + rewrite_module(&ctx.rewriter); + size_t i = 0; - Controls controls; + Controls* controls; while (dict_iter(ctx.controls, &i, NULL, &controls)) { - size_t j = 0; - AddControl add_control; + //size_t j = 0; + //AddControl add_control; // while (dict_iter(controls.control_destinations, &j, NULL, &add_control)) { // destroy_list(add_control.lift); // } - destroy_dict(controls.control_destinations); + destroy_dict(controls->control_destinations); } - rewrite_module(&ctx.rewriter); destroy_dict(ctx.controls); destroy_dict(ctx.jump2wrapper); destroy_arena(ctx.arena); From 8e50902a58615d9fd8fda2b6d36d6b918fd3eb3c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 17:01:48 +0200 Subject: [PATCH 536/693] remove lifting logic from reconvergence_heuristics (handled by lift_everything) --- src/shady/passes/reconvergence_heuristics.c | 33 +-------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 11d6b75f8..46755fe25 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -117,14 +117,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { BodyBuilder* outer_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_container)); Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); - CFNode* cf_pre = cfg_lookup(ctx->fwd_cfg, node); - // assert(cf_pre->idom && "cfg entry nodes can't be loop headers anyhow"); - // cf_pre = cf_pre->idom; - // CFNodeVariables* pre = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_pre); - LARRAY(Nodes, exit_param_allocas, exiting_nodes_count); - LARRAY(struct List*, leaking, exiting_nodes_count); - LARRAY(Nodes, exit_fwd_allocas, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; Nodes exit_param_types = rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); @@ -132,19 +125,6 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t j = 0; j < exit_param_types.count; j++) exit_param_allocas_tmp[j] = gen_stack_alloc(outer_bb, get_unqualified_type(exit_param_types.nodes[j])); exit_param_allocas[i] = nodes(arena, exit_param_types.count, exit_param_allocas_tmp); - - // Search for what's required after the exit but not in scope at the loop header - // this is similar to the LCSSA constraint, but here it's because controls have hard scopes - CFNode* cf_post = cfg_lookup(ctx->fwd_cfg, exiting_node->node); - // CFNodeVariables* post = *find_value_dict(CFNode*, CFNodeVariables*, ctx->live_vars, cf_post); - leaking[i] = new_list(const Type*); - // find_unbound_vars(exiting_node->node, pre->bound_by_dominators_set, post->free_set, leaking[i]); - - size_t leaking_count = entries_count_list(leaking[i]); - LARRAY(const Node*, exit_fwd_allocas_tmp, leaking_count); - for (size_t j = 0; j < leaking_count; j++) - exit_fwd_allocas_tmp[j] = gen_stack_alloc(outer_bb, rewrite_node(rewriter, get_unqualified_type(read_list(const Node*, leaking[i])[j]->type))); - exit_fwd_allocas[i] = nodes(arena, leaking_count, exit_fwd_allocas_tmp); } const Node* exit_destination_alloca = NULL; @@ -208,7 +188,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); Node* inner_control_case = case_(arena, singleton(join_token_continue)); register_processed(rewriter, get_abstraction_mem(node), get_abstraction_mem(inner_control_case)); - const Node* loop_body = recreate_node_identity(rewriter, get_abstraction_body(node)); + const Node* loop_body = rewrite_node(rewriter, get_abstraction_body(node)); // save the context for (size_t i = 0; i < exiting_nodes_count; i++) { @@ -222,10 +202,6 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (exiting_nodes_count > 1) gen_store(exit_wrapper_bb, exit_destination_alloca, int32_literal(arena, i)); - for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { - gen_store(exit_wrapper_bb, exit_fwd_allocas[i].nodes[j], rewrite_node(rewriter, read_list(const Node*, leaking[i])[j])); - } - set_abstraction_body(exit_helpers[i], finish_body_with_join(exit_wrapper_bb, join_token_exit, empty(arena))); } @@ -266,12 +242,6 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Node* exit_bb = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); - // recover the context - for (size_t j = 0; j < exit_fwd_allocas[i].count; j++) { - const Node* recovered = gen_load(exit_recover_bb, exit_fwd_allocas[i].nodes[j]); - register_processed(rewriter, read_list(const Node*, leaking[i])[j], recovered); - } - const Node* recreated_exit = rewrite_node(rewriter, exiting_node->node); LARRAY(const Node*, recovered_args, exit_param_allocas[i].count); @@ -281,7 +251,6 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { exit_numbers[i] = int32_literal(arena, i); set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, nodes(arena, exit_param_allocas[i].count, recovered_args))); exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena), bb_mem(outer_bb)); - destroy_list(leaking[i]); } const Node* outer_body; From f89a0aa8d25110540bba2bb8596c39863e3762a8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 18:26:19 +0200 Subject: [PATCH 537/693] re-added lcssa pass --- src/shady/analysis/cfg.c | 2 +- src/shady/compile.c | 2 +- src/shady/passes/CMakeLists.txt | 1 + src/shady/passes/lcssa.c | 207 +++++++++++++++++++++++++++++ src/shady/passes/lift_everything.c | 23 ++-- src/shady/passes/passes.h | 1 + 6 files changed, 225 insertions(+), 11 deletions(-) create mode 100644 src/shady/passes/lcssa.c diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 362edf51d..c36f61787 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -479,7 +479,7 @@ void compute_rpo(CFG* cfg) { bool is_cfnode_structural_target(CFNode* cfn) { for (size_t i = 0; i < entries_count_list(cfn->pred_edges); i++) { - if (read_list(CFEdge, cfn->pred_edges)[0].type != JumpEdge) + if (read_list(CFEdge, cfn->pred_edges)[i].type != JumpEdge) return true; } return false; diff --git a/src/shady/compile.c b/src/shady/compile.c index 92fcc6563..ef14c67c2 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -54,7 +54,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lift_everything) RUN_PASS(scope2control) } else { - RUN_PASS(lift_everything) + RUN_PASS(lcssa) RUN_PASS(reconvergence_heuristics) } diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index d9125f631..a48c25ac6 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -38,4 +38,5 @@ target_sources(shady PRIVATE lift_everything.c scope_heuristic.c reconvergence_heuristics.c + lcssa.c ) diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c new file mode 100644 index 000000000..3265479ee --- /dev/null +++ b/src/shady/passes/lcssa.c @@ -0,0 +1,207 @@ +#include "shady/ir.h" +#include "shady/pass.h" + +#include "../rewrite.h" +#include "../ir_private.h" +#include "../analysis/cfg.h" +#include "../analysis/scheduler.h" +#include "../analysis/looptree.h" +#include "../analysis/uses.h" +#include "../analysis/leak.h" +#include "../analysis/free_frontier.h" + +#include "portability.h" +#include "log.h" +#include "dict.h" + +typedef struct Context_ { + Rewriter rewriter; + const CompilerConfig* config; + const Node* current_fn; + CFG* cfg; + Scheduler* scheduler; + LoopTree* loop_tree; + struct Dict* lifted_arguments; +} Context; + +static bool is_child(const LTNode* maybe_parent, const LTNode* child) { + const LTNode* n = child; + while (n) { + if (n == maybe_parent) + return true; + n = n->parent; + } + return NULL; +} + +static const LTNode* get_loop(const LTNode* n) { + const LTNode* p = n->parent; + if (p && p->type == LF_HEAD) + return p; + return NULL; +} + +static String loop_name(const LTNode* n) { + if (n && n->type == LF_HEAD && entries_count_list(n->cf_nodes) > 0) { + return get_abstraction_name(read_list(CFNode*, n->cf_nodes)[0]->node); + } + return ""; +} + +void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, Nodes* lparams, Nodes* nargs) { + IrArena* a = ctx->rewriter.dst_arena; + assert(old->tag == BasicBlock_TAG); + + const LTNode* bb_loop = get_loop(looptree_lookup(ctx->loop_tree, old)); + + *nparams = empty(a); + *lparams = empty(a); + *nargs = empty(a); + + struct Dict* fvs = free_frontier(ctx->scheduler, ctx->cfg, old); + const Node* fv; + for (size_t i = 0; dict_iter(fvs, &i, &fv, NULL);) { + const CFNode* defining_cf_node = schedule_instruction(ctx->scheduler, fv); + assert(defining_cf_node); + const LTNode* defining_loop = get_loop(looptree_lookup(ctx->loop_tree, defining_cf_node->node)); + if (!is_child(defining_loop, bb_loop)) { + // that's it, that variable is leaking ! + log_string(DEBUGV, "lcssa: "); + log_node(DEBUGV, fv); + log_string(DEBUGV, " (%%%d) is used outside of the loop that defines it %s %s\n", fv->id, loop_name(defining_loop), loop_name(bb_loop)); + const Node* narg = rewrite_node(&ctx->rewriter, fv); + const Node* nparam = param(a, narg->type, "lcssa_phi"); + *nparams = append_nodes(a, *nparams, nparam); + *lparams = append_nodes(a, *lparams, fv); + *nargs = append_nodes(a, *nargs, narg); + } + } + destroy_dict(fvs); + + if (nparams->count > 0) + insert_dict(const Node*, Nodes, ctx->lifted_arguments, old, *nparams); +} + +const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* body) { + IrArena* a = ctx->rewriter.dst_arena; + Context ctx2 = *ctx; + ctx = &ctx2; + + if (!ctx->cfg) { + error_print("LCSSA: Trying to process an abstraction that's not part of a function ('%s')!", get_abstraction_name(old)); + log_module(ERROR, ctx->config, ctx->rewriter.src_module); + error_die(); + } + const CFNode* n = cfg_lookup(ctx->cfg, old); + + size_t children_count = 0; + LARRAY(const Node*, old_children, entries_count_list(n->dominates)); + for (size_t i = 0; i < entries_count_list(n->dominates); i++) { + CFNode* c = read_list(CFNode*, n->dominates)[i]; + if (is_cfnode_structural_target(c)) + continue; + old_children[children_count++] = c->node; + } + + LARRAY(Node*, new_children, children_count); + LARRAY(Nodes, lifted_params, children_count); + LARRAY(Nodes, new_params, children_count); + for (size_t i = 0; i < children_count; i++) { + Nodes nargs; + find_liftable_loop_values(ctx, old_children[i], &new_params[i], &lifted_params[i], &nargs); + Nodes nparams = recreate_params(&ctx->rewriter, get_abstraction_params(old_children[i])); + new_children[i] = basic_block(a, concat_nodes(a, nparams, new_params[i]), get_abstraction_name(old_children[i])); + register_processed(&ctx->rewriter, old_children[i], new_children[i]); + register_processed_list(&ctx->rewriter, get_abstraction_params(old_children[i]), nparams); + insert_dict(const Node*, Nodes, ctx->lifted_arguments, old_children[i], nargs); + } + + const Node* new = rewrite_node(&ctx->rewriter, body); + + ctx->rewriter.map = clone_dict(ctx->rewriter.map); + + for (size_t i = 0; i < children_count; i++) { + for (size_t j = 0; j < lifted_params[i].count; j++) { + remove_dict(const Node*, ctx->rewriter.map, lifted_params[i].nodes[j]); + } + register_processed_list(&ctx->rewriter, lifted_params[i], new_params[i]); + new_children[i]->payload.basic_block.body = process_abstraction_body(ctx, old_children[i], get_abstraction_body(old_children[i])); + } + + destroy_dict(ctx->rewriter.map); + + return new; +} + +const Node* process_node(Context* ctx, const Node* old) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + + switch (old->tag) { + case NominalType_TAG: + case GlobalVariable_TAG: + case Constant_TAG: { + Context not_a_fn_ctx = *ctx; + ctx = ¬_a_fn_ctx; + ctx->cfg = NULL; + return recreate_node_identity(&ctx->rewriter, old); + } + case Function_TAG: { + Context fn_ctx = *ctx; + ctx = &fn_ctx; + + ctx->current_fn = old; + ctx->cfg = build_fn_cfg(old); + ctx->scheduler = new_scheduler(ctx->cfg); + ctx->loop_tree = build_loop_tree(ctx->cfg); + + Node* new = recreate_decl_header_identity(&ctx->rewriter, old); + new->payload.fun.body = process_abstraction_body(ctx, old, get_abstraction_body(old)); + + destroy_loop_tree(ctx->loop_tree); + destroy_scheduler(ctx->scheduler); + destroy_cfg(ctx->cfg); + return new; + } + case Jump_TAG: { + Jump payload = old->payload.jump; + Nodes nargs = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); + Nodes* lifted_args = find_value_dict(const Node*, Nodes, ctx->lifted_arguments, old->payload.jump.target); + if (lifted_args) { + nargs = concat_nodes(a, nargs, *lifted_args); + } + return jump(a, (Jump) { + .target = rewrite_node(&ctx->rewriter, old->payload.jump.target), + .args = nargs, + .mem = rewrite_node(r, payload.mem), + }); + } + case BasicBlock_TAG: { + assert(false); + } + default: break; + } + + return recreate_node_identity(&ctx->rewriter, old); +} + +KeyHash hash_node(Node**); +bool compare_node(Node**, Node**); + +Module* lcssa(const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); + Module* dst = new_module(a, get_module_name(src)); + + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .config = config, + .current_fn = NULL, + .lifted_arguments = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node) + }; + + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + destroy_dict(ctx.lifted_arguments); + return dst; +} diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index a2f6536c0..c43fbfbf9 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -14,7 +14,6 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); - typedef struct { Rewriter rewriter; struct Dict* lift; @@ -103,13 +102,19 @@ static const Node* process(Context* ctx, const Node* node) { Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); IrArena* a = new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); - Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .lift = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), - }; - rewrite_module(&ctx.rewriter); - destroy_dict(ctx.lift); - destroy_rewriter(&ctx.rewriter); + bool todo = true; + Module* dst; + while (todo) { + todo = false; + dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .lift = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), + }; + rewrite_module(&ctx.rewriter); + destroy_dict(ctx.lift); + destroy_rewriter(&ctx.rewriter); + src = dst; + } return dst; } diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 159511c1d..1e3f0bd1e 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -19,6 +19,7 @@ RewritePass lower_cf_instrs; /// Uses shady.scope annotations to insert control blocks RewritePass scope2control; RewritePass lift_everything; +RewritePass lcssa; RewritePass scope_heuristic; /// Try to identify reconvergence points throughout the program for unstructured control flow programs RewritePass reconvergence_heuristics; From 7f19baf83ccf79a53b79fefcee64fe6db86c535b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 18:26:41 +0200 Subject: [PATCH 538/693] reconvergence_heuristics: rename idom to postdom --- src/shady/passes/reconvergence_heuristics.c | 32 ++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 46755fe25..be87516d1 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -75,7 +75,7 @@ static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, } static const Node* process_abstraction(Context* ctx, const Node* node) { - assert(is_abstraction(node)); + assert(node && is_abstraction(node)); Context new_context = *ctx; ctx = &new_context; ctx->current_abstraction = node; @@ -321,7 +321,7 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(ctx->fwd_cfg); CFNode* cfnode = cfg_lookup(ctx->rev_cfg, ctx->current_abstraction); - const Node* idom = NULL; + const Node* post_dominator = NULL; LTNode* current_loop = looptree_lookup(ctx->current_looptree, ctx->current_abstraction)->parent; assert(current_loop); @@ -348,24 +348,24 @@ static const Node* process_node(Context* ctx, const Node* node) { }); CFNode* idom_cf = cfg_lookup(loop_cfg, ctx->current_abstraction)->idom; if (idom_cf) - idom = idom_cf->node; + post_dominator = idom_cf->node; destroy_cfg(loop_cfg); } } else { - idom = cfnode->idom->node; + post_dominator = cfnode->idom->node; } - if (!idom) { + if (!post_dominator) { break; } - if (cfg_lookup(ctx->fwd_cfg, idom)->idom->node != ctx->current_abstraction) + if (cfg_lookup(ctx->fwd_cfg, post_dominator)->idom->node != ctx->current_abstraction) break; - assert(is_abstraction(idom) && idom->tag != Function_TAG); + assert(is_abstraction(post_dominator) && post_dominator->tag != Function_TAG); LTNode* lt_node = looptree_lookup(ctx->current_looptree, ctx->current_abstraction); - LTNode* idom_lt_node = looptree_lookup(ctx->current_looptree, idom); + LTNode* idom_lt_node = looptree_lookup(ctx->current_looptree, post_dominator); CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); assert(lt_node); @@ -378,7 +378,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes yield_types; Nodes exit_args; - Nodes old_params = get_abstraction_params(idom); + Nodes old_params = get_abstraction_params(post_dominator); if (old_params.count == 0) { yield_types = empty(a); @@ -408,25 +408,25 @@ static const Node* process_node(Context* ctx, const Node* node) { .yield_types = yield_types }), true), "jp_postdom"); - Node* pre_join = basic_block(a, exit_args, format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(idom))); + Node* pre_join = basic_block(a, exit_args, format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(post_dominator))); set_abstraction_body(pre_join, join(a, (Join) { .join_point = join_token, .args = exit_args, .mem = get_abstraction_mem(pre_join), })); - const Node* cached = search_processed(r, idom); + const Node* cached = search_processed(r, post_dominator); if (cached) - remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); + remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); for (size_t i = 0; i < old_params.count; i++) { assert(!search_processed(r, old_params.nodes[i])); } - register_processed(r, idom, pre_join); + register_processed(r, post_dominator, pre_join); - remove_dict(const Node*, is_declaration(idom) ? r->decls_map : r->map, idom); + remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); if (cached) - register_processed(r, idom, cached); + register_processed(r, post_dominator, cached); Node* control_case = case_(a, singleton(join_token)); const Node* inner_terminator = branch(a, (Branch) { @@ -436,7 +436,7 @@ static const Node* process_node(Context* ctx, const Node* node) { .false_jump = jump_helper(a, rewrite_node(r, payload.false_jump->payload.jump.target), rewrite_nodes(r, payload.false_jump->payload.jump.args), get_abstraction_mem(control_case)), }); set_abstraction_body(control_case, inner_terminator); - const Node* join_target = rewrite_node(r, idom); + const Node* join_target = rewrite_node(r, post_dominator); BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); Nodes results = gen_control(bb, yield_types, control_case); From f86ccba44ee7c3a8c90b44fcce75d4930bfbded5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 22 Aug 2024 18:26:57 +0200 Subject: [PATCH 539/693] print: use BB names --- src/shady/print.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shady/print.c b/src/shady/print.c index a59df0f24..63d0dd660 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1087,6 +1087,7 @@ static bool print_node_impl(PrinterCtx* ctx, const Node* node) { else printf("%%%d", node->id); printf(RESET); + return true; } else { print_node_generated(ctx, node); } From dca4d83eea4fda2082f7301367abc80a5f017799 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 23 Aug 2024 11:42:21 +0200 Subject: [PATCH 540/693] fixed reconvergence heuristics not inserting joins properly --- src/shady/passes/reconvergence_heuristics.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index be87516d1..18f267238 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -424,10 +424,6 @@ static const Node* process_node(Context* ctx, const Node* node) { register_processed(r, post_dominator, pre_join); - remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); - if (cached) - register_processed(r, post_dominator, cached); - Node* control_case = case_(a, singleton(join_token)); const Node* inner_terminator = branch(a, (Branch) { .mem = get_abstraction_mem(control_case), @@ -436,6 +432,11 @@ static const Node* process_node(Context* ctx, const Node* node) { .false_jump = jump_helper(a, rewrite_node(r, payload.false_jump->payload.jump.target), rewrite_nodes(r, payload.false_jump->payload.jump.args), get_abstraction_mem(control_case)), }); set_abstraction_body(control_case, inner_terminator); + + remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); + if (cached) + register_processed(r, post_dominator, cached); + const Node* join_target = rewrite_node(r, post_dominator); BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); @@ -449,6 +450,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + aconfig.optimisations.inline_single_use_bbs = true; IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); From 80204bb669a270ab3d1f9b4b0b478a42bda7f727 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 27 Aug 2024 10:09:58 +0200 Subject: [PATCH 541/693] config: move relevant options to input_cf section --- include/shady/config.h | 4 ++-- samples/aobench/ao_main.c | 2 +- src/driver/cli.c | 5 +++-- src/frontend/llvm/l2s_instr.c | 2 +- src/shady/compile.c | 2 +- src/shady/passes/reconvergence_heuristics.c | 6 +++--- vcc/vcc_lib.c | 2 +- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/shady/config.h b/include/shady/config.h index d2faf016a..fc58f6681 100644 --- a/include/shady/config.h +++ b/include/shady/config.h @@ -67,6 +67,8 @@ struct CompilerConfig_ { } target_spirv_version; struct { + bool restructure_with_heuristics; + bool add_scope_annotations; bool has_scope_annotations; } input_cf; @@ -83,8 +85,6 @@ struct CompilerConfig_ { struct { bool spv_shuffle_instead_of_broadcast_first; bool force_join_point_lifting; - bool restructure_everything; - bool recover_structure; } hacks; struct { diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 8571635e4..8bdf76639 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -149,7 +149,7 @@ int main(int argc, char **argv) { .runtime_config = default_runtime_config(), }; - args.compiler_config.hacks.restructure_everything = true; + args.compiler_config.input_cf.restructure_with_heuristics = true; cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.compiler_config, &argc, argv); diff --git a/src/driver/cli.c b/src/driver/cli.c index 3adebef91..e0a5c6426 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -91,8 +91,9 @@ F(config->logging.print_internal, print-internal) \ F(config->logging.print_generated, print-builtin) \ F(config->logging.print_generated, print-generated) \ F(config->optimisations.inline_everything, inline-everything) \ -F(config->hacks.restructure_everything, restructure-everything) \ -F(config->hacks.recover_structure, recover-structure) \ +F(config->input_cf.restructure_with_heuristics, restructure-everything) \ +F(config->input_cf.add_scope_annotations, add-scope-annotations) \ +F(config->input_cf.has_scope_annotations, has-scope-annotations) \ static IntSizes parse_int_size(String argv) { if (strcmp(argv, "8") == 0) diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index caaa4e3ab..5128df0db 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -110,7 +110,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B //if (LLVMIsATerminatorInst(instr)) { //if (LLVMIsAInstruction(instr) && !LLVMIsATerminatorInst(instr)) { - if (LLVMIsAInstruction(instr) && p->config->hacks.recover_structure) { + if (LLVMIsAInstruction(instr) && p->config->input_cf.add_scope_annotations) { assert(fn && fn_or_bb); LLVMMetadataRef dbgloc = LLVMInstructionGetDebugLoc(instr); if (dbgloc) { diff --git a/src/shady/compile.c b/src/shady/compile.c index ef14c67c2..8fbd7ddaa 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -53,7 +53,7 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { // RUN_PASS(scope_heuristic) RUN_PASS(lift_everything) RUN_PASS(scope2control) - } else { + } else if (config->input_cf.restructure_with_heuristics) { RUN_PASS(lcssa) RUN_PASS(reconvergence_heuristics) } diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 18f267238..4c1c06493 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -289,7 +289,7 @@ static const Node* process_node(Context* ctx, const Node* node) { case Function_TAG: { ctx = &new_context; ctx->current_fn = NULL; - if (!(lookup_annotation(node, "Restructure") || ctx->config->hacks.restructure_everything)) + if (!(lookup_annotation(node, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) break; ctx->current_fn = node; @@ -311,12 +311,12 @@ static const Node* process_node(Context* ctx, const Node* node) { break; } case BasicBlock_TAG: - if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) + if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) break; return process_abstraction(ctx, node); case Branch_TAG: { Branch payload = node->payload.branch; - if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->hacks.restructure_everything)) + if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) break; assert(ctx->fwd_cfg); diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 6b2873de3..5f915676e 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -58,7 +58,7 @@ VccConfig vcc_init_config(CompilerConfig* compiler_config) { // magic! //compiler_config->hacks.recover_structure = true; - compiler_config->hacks.restructure_everything = true; + compiler_config->input_cf.add_scope_annotations = true; compiler_config->input_cf.has_scope_annotations = true; String self_path = get_executable_location(); From 540a06a0b5dda2955a6aa9d4d1f422117794b052 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 27 Aug 2024 11:23:42 +0200 Subject: [PATCH 542/693] slim: added line info to parser and errors --- src/common/log.c | 9 +- src/common/log.h | 2 + src/frontend/slim/parser.c | 306 ++++++++++++++++++++++--------------- src/frontend/slim/token.c | 34 +++-- src/frontend/slim/token.h | 6 + 5 files changed, 224 insertions(+), 133 deletions(-) diff --git a/src/common/log.c b/src/common/log.c index 5cdcffbd3..2bb1b652b 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -1,7 +1,6 @@ #include "log.h" #include -#include LogLevel shady_log_level = INFO; @@ -13,10 +12,14 @@ void set_log_level(LogLevel l) { shady_log_level = l; } +void log_fmtv(LogLevel level, const char* format, va_list args) { + if (level <= shady_log_level) + vfprintf(stderr, format, args); +} + void log_string(LogLevel level, const char* format, ...) { va_list args; va_start(args, format); - if (level <= shady_log_level) - vfprintf(stderr, format, args); + log_fmtv(level, format, args); va_end(args); } diff --git a/src/common/log.h b/src/common/log.h index 74f131abf..d596023eb 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -2,6 +2,7 @@ #define SHADY_LOG_H #include +#include typedef struct Node_ Node; typedef struct Module_ Module; @@ -17,6 +18,7 @@ typedef enum LogLevel_ { LogLevel get_log_level(); void set_log_level(LogLevel); +void log_fmtv(LogLevel level, const char* format, va_list args); void log_string(LogLevel level, const char* format, ...); void log_node(LogLevel level, const Node* node); typedef struct CompilerConfig_ CompilerConfig; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index a2c1dce13..0f8bc873c 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -55,11 +55,86 @@ INFIX_OPERATORS() #define ctxparams SHADY_UNUSED ParserConfig config, SHADY_UNUSED const char* contents, SHADY_UNUSED Module* mod, SHADY_UNUSED IrArena* arena, SHADY_UNUSED Tokenizer* tokenizer #define ctx config, contents, mod, arena, tokenizer -#define expect(condition) expect_impl(condition, #condition) -static void expect_impl(bool condition, const char* err) { +static void error_with_loc(ctxparams) { + Loc loc = current_loc(tokenizer); + size_t startline = loc.line - 2; + if (startline < 1) startline = 1; + size_t endline = startline + 5; + + int numdigits = 1; + int e = endline; + while (e >= 10) { + numdigits++; + e /= 10; + } + LARRAY(char, digits, numdigits); + // char* digits = malloc(sizeof(char) * numdigits); + + size_t line = 1; + size_t len = strlen(contents); + for (size_t i = 0; i < len; i++) { + if (line >= startline && line <= endline) { + log_string(ERROR, "%c", contents[i]); + } + if (contents[i] == '\n') { + if (line == loc.line) { + for (size_t digit = 0; digit < numdigits; digit++) { + log_string(ERROR, " "); + } + log_string(ERROR, " "); + for (size_t j = 1; j < loc.column; j++) { + log_string(ERROR, " "); + } + log_string(ERROR, "^"); + log_string(ERROR, "\n"); + } + line++; + + if (line >= startline && line <= endline) { + size_t l = line, digit; + for (digit = 0; digit < numdigits; digit++) { + if (l == 0) + break; + digits[numdigits - 1 - digit] = (char) ('0' + (l % 10)); + l /= 10; + } + for (; digit < numdigits; digit++) { + digits[numdigits - 1 - digit] = (char) ' '; + } + for (digit = 0; digit < numdigits; digit++) { + log_string(ERROR, "%c", digits[numdigits - 1 - digit]); + } + log_string(ERROR, ": "); + } + } + } + log_string(ERROR, "At %d:%d, ", loc.line, loc.column); +} + +#define syntax_error(condition) syntax_error_impl(ctx, condition) +#define syntax_error_fmt(condition, ...) syntax_error_impl(ctx, condition, __VA_ARGS__) +static void syntax_error_impl(ctxparams, const char* format, ...) { + va_list args; + va_start(args, format); + error_with_loc(ctx); + log_fmtv(ERROR, format, args); + log_string(ERROR, "\n"); + exit(-4); + va_end(args); +} + +#define expect(condition, format, ...) expect_impl(ctx, condition, format) +#define expect_fmt(condition, format, ...) expect_impl(ctx, condition, format, __VA_ARGS__) +static void expect_impl(ctxparams, bool condition, const char* format, ...) { if (!condition) { - error_print("expected to parse: %s\n", err); + va_list args; + va_start(args, format); + error_with_loc(ctx); + log_string(ERROR, "expected "); + log_fmtv(ERROR, format, args); + log_string(ERROR, "\n"); exit(-4); + va_end(args); } } @@ -128,14 +203,14 @@ static const Node* accept_numerical_literal(ctxparams) { switch (tok.tag) { case hex_lit_tok: if (negate) - error("hexadecimal literals can't start with '-'"); + syntax_error("hexadecimal literals can't start with '-'"); case dec_lit_tok: { next_token(tokenizer); break; } default: { if (negate || num_type) - error("expected numerical literal"); + syntax_error("expected numerical literal"); return NULL; } } @@ -161,7 +236,7 @@ static Nodes accept_type_arguments(ctxparams) { if (accept_token(ctx, lsbracket_tok)) { while (true) { const Type* t = accept_unqualified_type(ctx); - expect(t); + expect(t, "unqualified type"); ty_args = append_nodes(arena, ty_args, t); if (accept_token(ctx, comma_tok)) continue; @@ -205,23 +280,23 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { if (op != PRIMOPS_COUNT) { if (!bb) - error("can't have primops here"); + syntax_error("primops cannot be used outside of a function"); return bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = op, .type_arguments = accept_type_arguments(ctx), .operands = expect_operands(ctx, bb) })); } else if (strcmp(id, "ext_instr") == 0) { - expect(accept_token(ctx, lsbracket_tok)); + expect(accept_token(ctx, lsbracket_tok), "'['"); const Node* set = accept_value(ctx, NULL); - assert(set->tag == StringLiteral_TAG); - expect(accept_token(ctx, comma_tok)); + expect(set->tag == StringLiteral_TAG, "string literal"); + expect(accept_token(ctx, comma_tok), "','"); const Node* opcode = accept_value(ctx, NULL); - assert(opcode->tag == UntypedNumber_TAG); - expect(accept_token(ctx, comma_tok)); + expect(opcode->tag == UntypedNumber_TAG, "number"); + expect(accept_token(ctx, comma_tok), "','"); const Type* type = accept_qualified_type(ctx); - expect(type); - expect(accept_token(ctx, rsbracket_tok)); + expect(type, "type"); + expect(accept_token(ctx, rsbracket_tok), "]"); Nodes ops = expect_operands(ctx, bb); return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { .result_t = type, @@ -233,7 +308,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { } else if (strcmp(id, "alloca") == 0) { const Node* type = first(accept_type_arguments(ctx)); Nodes ops = expect_operands(ctx, bb); - expect(ops.count == 0); + expect(ops.count == 0, "no operands"); return bind_instruction_single(bb, stack_alloc(arena, (StackAlloc) { .type = type, .mem = bb_mem(bb), @@ -281,7 +356,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { append_list(const Node*, elements, atom); while (!accept_token(ctx, rpar_tok)) { - expect(accept_token(ctx, comma_tok)); + expect(accept_token(ctx, comma_tok), "','"); const Node* element = expect_operand(ctx, bb); append_list(const Node*, elements, element); } @@ -295,7 +370,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { case composite_tok: { next_token(tokenizer); const Type* elem_type = accept_unqualified_type(ctx); - expect(elem_type); + expect(elem_type, "composite data type"); Nodes elems = expect_operands(ctx, bb); return composite_helper(arena, elem_type, elems); } @@ -328,22 +403,18 @@ static const Type* accept_unqualified_type(ctxparams) { return mask_type(arena); } else if (accept_token(ctx, ptr_tok)) { AddressSpace as = accept_address_space(ctx); - if (as == NumAddressSpaces) { - error("expected address space qualifier"); - } + expect(as != NumAddressSpaces, "address space"); const Type* elem_type = accept_unqualified_type(ctx); - expect(elem_type); + expect(elem_type, "data type"); return ptr_type(arena, (PtrType) { .address_space = as, .pointed_type = elem_type, }); } else if (accept_token(ctx, ref_tok)) { AddressSpace as = accept_address_space(ctx); - if (as == NumAddressSpaces) { - error("expected address space qualifier"); - } + expect(as != NumAddressSpaces, "address space"); const Type* elem_type = accept_unqualified_type(ctx); - expect(elem_type); + expect(elem_type, "data type"); return ptr_type(arena, (PtrType) { .address_space = as, .pointed_type = elem_type, @@ -351,44 +422,44 @@ static const Type* accept_unqualified_type(ctxparams) { }); } else if (config.front_end && accept_token(ctx, lsbracket_tok)) { const Type* elem_type = accept_unqualified_type(ctx); - expect(elem_type); + expect(elem_type, "type"); const Node* size = NULL; - if(accept_token(ctx, semi_tok)) { + if (accept_token(ctx, semi_tok)) { size = accept_value(ctx, NULL); - expect(size); + expect(size, "value"); } - expect(accept_token(ctx, rsbracket_tok)); + expect(accept_token(ctx, rsbracket_tok), "']'"); return arr_type(arena, (ArrType) { .element_type = elem_type, .size = size }); } else if (accept_token(ctx, pack_tok)) { - expect(accept_token(ctx, lsbracket_tok)); + expect(accept_token(ctx, lsbracket_tok), "'['"); const Type* elem_type = accept_unqualified_type(ctx); - expect(elem_type); + expect(elem_type, "packed element type"); const Node* size = NULL; - expect(accept_token(ctx, semi_tok)); + expect(accept_token(ctx, semi_tok), "';'"); size = accept_numerical_literal(ctx); - expect(size && size->tag == UntypedNumber_TAG); - expect(accept_token(ctx, rsbracket_tok)); + expect(size && size->tag == UntypedNumber_TAG, "number"); + expect(accept_token(ctx, rsbracket_tok), "']'"); return pack_type(arena, (PackType) { .element_type = elem_type, .width = strtoll(size->payload.untyped_number.plaintext, NULL, 10) }); } else if (accept_token(ctx, struct_tok)) { - expect(accept_token(ctx, lbracket_tok)); + expect(accept_token(ctx, lbracket_tok), "'{'"); struct List* names = new_list(String); struct List* types = new_list(const Type*); while (true) { if (accept_token(ctx, rbracket_tok)) break; const Type* elem = accept_unqualified_type(ctx); - expect(elem); + expect(elem, "struct member type"); String id = accept_identifier(ctx); - expect(id); + expect(id, "struct member name"); append_list(String, names, id); append_list(const Type*, types, elem); - expect(accept_token(ctx, semi_tok)); + expect(accept_token(ctx, semi_tok), "';'"); } Nodes elem_types = nodes(arena, entries_count_list(types), read_list(const Type*, types)); Strings names2 = strings(arena, entries_count_list(names), read_list(String, names)); @@ -421,7 +492,7 @@ static const Type* accept_maybe_qualified_type(ctxparams) { DivergenceQualifier qualifier = accept_uniformity_qualifier(ctx); const Type* unqualified = accept_unqualified_type(ctx); if (qualifier != Unknown) - expect(unqualified && "we read a uniformity qualifier and expected a type to follow"); + expect(unqualified, "unqualified type"); if (qualifier == Unknown) return unqualified; else @@ -433,7 +504,7 @@ static const Type* accept_qualified_type(ctxparams) { if (qualifier == Unknown) return NULL; const Type* unqualified = accept_unqualified_type(ctx); - expect(unqualified); + expect(unqualified, "unqualified type"); return qualified_type(arena, (QualifiedType) { .is_uniform = qualifier == Uniform, .type = unqualified }); } @@ -443,12 +514,12 @@ static const Node* accept_operand(ctxparams, BodyBuilder* bb) { static const Node* expect_operand(ctxparams, BodyBuilder* bb) { const Node* operand = accept_operand(ctx, bb); - expect(operand); + expect(operand, "value operand"); return operand; } static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_values, BodyBuilder* bb) { - expect(accept_token(ctx, lpar_tok)); + expect(accept_token(ctx, lpar_tok), "'('"); struct List* params = new_list(Node*); struct List* default_vals = default_values ? new_list(Node*) : NULL; @@ -458,15 +529,15 @@ static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_value next: { const Type* qtype = accept_qualified_type(ctx); - expect(qtype); + expect(qtype, "qualified type"); const char* id = accept_identifier(ctx); - expect(id); + expect(id, "parameter name"); const Node* node = param(arena, qtype, id); append_list(Node*, params, node); if (default_values) { - expect(accept_token(ctx, equal_tok)); + expect(accept_token(ctx, equal_tok), "'='"); const Node* default_val = accept_operand(ctx, bb); append_list(const Node*, default_vals, default_val); } @@ -514,7 +585,7 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { assert(bb); if (accept_token(ctx, minus_tok)) { const Node* expr = accept_primary_expr(ctx, bb); - expect(expr); + expect(expr, "expression"); if (expr->tag == IntLiteral_TAG) { return int_literal(arena, (IntLiteral) { // We always treat that value like an signed integer, because it makes no sense to negate an unsigned number ! @@ -528,18 +599,18 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { } } else if (accept_token(ctx, unary_excl_tok)) { const Node* expr = accept_primary_expr(ctx, bb); - expect(expr); + expect(expr, "expression"); return bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = not_op, .operands = singleton(expr), })); } else if (accept_token(ctx, star_tok)) { const Node* expr = accept_primary_expr(ctx, bb); - expect(expr); + expect(expr, "expression"); return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpDereference, .operands = singleton(expr), .mem = bb_mem(bb) })); } else if (accept_token(ctx, infix_and_tok)) { const Node* expr = accept_primary_expr(ctx, bb); - expect(expr); + expect(expr, "expression"); return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), @@ -563,7 +634,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) next_token(tokenizer); const Node* rhs = accept_expr(ctx, bb, precedence - 1); - expect(rhs); + expect(rhs, "expression"); Op primop_op; if (is_primop_op(infix, &primop_op)) { expr = bind_instruction_single(bb, prim_op(arena, (PrimOp) { @@ -591,7 +662,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) })); break; } - default: error("unknown infix operator") + default: syntax_error("unknown infix operator"); } continue; } @@ -616,8 +687,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) } static Nodes expect_operands(ctxparams, BodyBuilder* bb) { - if (!accept_token(ctx, lpar_tok)) - error("Expected left parenthesis") + expect(accept_token(ctx, lpar_tok), "'('"); struct List* list = new_list(Node*); @@ -626,11 +696,11 @@ static Nodes expect_operands(ctxparams, BodyBuilder* bb) { const Node* val = accept_operand(ctx, bb); if (!val) { if (expect) - error("expected value but got none") + syntax_error("expected value but got none"); else if (accept_token(ctx, rpar_tok)) break; else - error("Expected value or closing parenthesis") + syntax_error("Expected value or ')'"); } append_list(Node*, list, val); @@ -640,7 +710,7 @@ static Nodes expect_operands(ctxparams, BodyBuilder* bb) { else if (accept_token(ctx, rpar_tok)) break; else - error("Expected comma or closing parenthesis") + syntax_error("Expected ',' or ')'"); } Nodes final = nodes(arena, list->elements_count, (const Node**) list->alloc); @@ -664,10 +734,10 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { case if_tok: { next_token(tokenizer); Nodes yield_types = accept_types(ctx, 0, NeverQualified); - expect(accept_token(ctx, lpar_tok)); + expect(accept_token(ctx, lpar_tok), "'('"); const Node* condition = accept_operand(ctx, bb); - expect(condition); - expect(accept_token(ctx, rpar_tok)); + expect(condition, "condition value"); + expect(accept_token(ctx, rpar_tok), "')'"); const Node* (*merge)(const Node*) = config.front_end ? make_selection_merge : NULL; Node* true_case = case_(arena, nodes(arena, 0, NULL)); @@ -697,13 +767,13 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { case control_tok: { next_token(tokenizer); Nodes yield_types = accept_types(ctx, 0, NeverQualified); - expect(accept_token(ctx, lpar_tok)); + expect(accept_token(ctx, lpar_tok), "'('"); String str = accept_identifier(ctx); - expect(str); + expect(str, "control parameter name"); const Node* jp = param(arena, join_point_type(arena, (JoinPointType) { .yield_types = yield_types, }), str); - expect(accept_token(ctx, rpar_tok)); + expect(accept_token(ctx, rpar_tok), "')'"); Node* control_case = case_(arena, singleton(jp)); set_abstraction_body(control_case, expect_body(ctx, get_abstraction_mem(control_case), NULL)); return maybe_tuple_helper(arena, gen_control(bb, yield_types, control_case)); @@ -717,7 +787,7 @@ static const Node* accept_instruction(ctxparams, BodyBuilder* bb) { const Node* instr = accept_expr(ctx, bb, max_precedence()); if (instr) - expect(accept_token(ctx, semi_tok) && "Non-control flow instructions must be followed by a semicolon"); + expect(accept_token(ctx, semi_tok), "';'"); if (!instr) instr = accept_control_flow_instruction(ctx, bb); return instr; @@ -727,7 +797,7 @@ static void expect_identifiers(ctxparams, Strings* out_strings) { struct List* list = new_list(const char*); while (true) { const char* id = accept_identifier(ctx); - expect(id); + expect(id, "identifier"); append_list(const char*, list, id); @@ -747,9 +817,9 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* while (true) { const Type* type = accept_unqualified_type(ctx); - expect(type); + expect(type, "type"); const char* id = accept_identifier(ctx); - expect(id); + expect(id, "identifier"); append_list(const char*, tlist, type); append_list(const char*, slist, id); @@ -777,13 +847,13 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { Strings ids; if (accept_token(ctx, val_tok)) { expect_identifiers(ctx, &ids); - expect(accept_token(ctx, equal_tok)); + expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); gen_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(bb->arena), prepend_nodes(bb->arena, strings2nodes(bb->arena, ids), instruction)); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); - expect(accept_token(ctx, equal_tok)); + expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); gen_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(bb->arena), prepend_nodes(bb->arena, concat_nodes(bb->arena, strings2nodes(bb->arena, ids), types), instruction)); } else { @@ -796,7 +866,7 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { static const Node* expect_jump(ctxparams, BodyBuilder* bb) { String target = accept_identifier(ctx); - expect(target); + expect(target, "jump target name"); Nodes args = expect_operands(ctx, bb); const Node* tgt = make_unbound(arena, bb_mem(bb), target); bind_instruction_single(bb, tgt); @@ -817,14 +887,14 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { case branch_tok: { next_token(tokenizer); - expect(accept_token(ctx, lpar_tok)); + expect(accept_token(ctx, lpar_tok), "'('"); const Node* condition = accept_value(ctx, bb); - expect(condition); - expect(accept_token(ctx, comma_tok)); + expect(condition, "branch condition value"); + expect(accept_token(ctx, comma_tok), "','"); const Node* true_target = expect_jump(ctx, bb); - expect(accept_token(ctx, comma_tok)); + expect(accept_token(ctx, comma_tok), "','"); const Node* false_target = expect_jump(ctx, bb); - expect(accept_token(ctx, rpar_tok)); + expect(accept_token(ctx, rpar_tok), "')'"); return branch(arena, (Branch) { .condition = condition, @@ -836,10 +906,10 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { case switch_tok: { next_token(tokenizer); - expect(accept_token(ctx, lpar_tok)); + expect(accept_token(ctx, lpar_tok), "'('"); const Node* inspectee = accept_value(ctx, bb); - expect(inspectee); - expect(accept_token(ctx, comma_tok)); + expect(inspectee, "value"); + expect(accept_token(ctx, comma_tok), "','"); Nodes values = empty(arena); Nodes cases = empty(arena); const Node* default_jump; @@ -848,16 +918,16 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { default_jump = expect_jump(ctx, bb); break; } - expect(accept_token(ctx, case_tok)); + expect(accept_token(ctx, case_tok), "'case'"); const Node* value = accept_value(ctx, bb); - expect(value); - expect(accept_token(ctx, comma_tok) && 1); + expect(value, "case value"); + expect(accept_token(ctx, comma_tok), "','"); const Node* j = expect_jump(ctx, bb); - expect(accept_token(ctx, comma_tok) && true); + expect(accept_token(ctx, comma_tok), "','"); values = append_nodes(arena, values, value); cases = append_nodes(arena, cases, j); } - expect(accept_token(ctx, rpar_tok)); + expect(accept_token(ctx, rpar_tok), "')'"); return br_switch(arena, (Switch) { .switch_value = first(values), @@ -901,9 +971,9 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { } case join_tok: { next_token(tokenizer); - expect(accept_token(ctx, lpar_tok)); + expect(accept_token(ctx, lpar_tok), "'('"); const Node* jp = accept_operand(ctx, bb); - expect(accept_token(ctx, rpar_tok)); + expect(accept_token(ctx, rpar_tok), "')'"); Nodes args = expect_operands(ctx, bb); return join(arena, (Join) { .join_point = jp, @@ -913,8 +983,8 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { } case unreachable_tok: { next_token(tokenizer); - expect(accept_token(ctx, lpar_tok)); - expect(accept_token(ctx, rpar_tok)); + expect(accept_token(ctx, lpar_tok), "'('"); + expect(accept_token(ctx, rpar_tok), "')'"); return unreachable(arena, (Unreachable) { .mem = bb_mem(bb) }); } default: break; @@ -923,7 +993,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { } static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator(const Node*)) { - expect(accept_token(ctx, lbracket_tok)); + expect(accept_token(ctx, lbracket_tok), "'['"); BodyBuilder* bb = begin_body_with_mem(arena, mem); while (true) { @@ -936,13 +1006,13 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t const Node* terminator = accept_terminator(ctx, terminator_bb); if (terminator) - expect(accept_token(ctx, semi_tok)); + expect(accept_token(ctx, semi_tok), "';'"); if (!terminator) { if (default_terminator) terminator = default_terminator(bb_mem(terminator_bb)); else - error("expected terminator: return, jump, branch ..."); + syntax_error("expected terminator: return, jump, branch ..."); } set_abstraction_body(terminator_case, finish_body(terminator_bb, terminator)); @@ -968,7 +1038,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t } gen_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), concat_nodes(arena, ids, conts)); - expect(accept_token(ctx, rbracket_tok)); + expect(accept_token(ctx, rbracket_tok), "']'"); set_abstraction_body(cont_wrapper_case, finish_body_with_jump(cont_wrapper_bb, terminator_case, empty(arena))); return finish_body_with_jump(bb, cont_wrapper_case, empty(arena)); @@ -984,7 +1054,7 @@ static Nodes accept_annotations(ctxparams) { if (accept_token(ctx, lpar_tok)) { const Node* first_value = accept_value(ctx, NULL); if (!first_value) { - expect(accept_token(ctx, rpar_tok)); + expect(accept_token(ctx, rpar_tok), "value"); goto no_params; } @@ -995,7 +1065,7 @@ static Nodes accept_annotations(ctxparams) { append_list(const Node*, values, first_value); while (true) { const Node* next_value = accept_value(ctx, NULL); - expect(next_value); + expect(next_value, "value"); append_list(const Node*, values, next_value); if (accept_token(ctx, comma_tok)) continue; @@ -1013,14 +1083,14 @@ static Nodes accept_annotations(ctxparams) { }); } - expect(accept_token(ctx, rpar_tok)); + expect(accept_token(ctx, rpar_tok), "')'"); } else { no_params: annot = annotation(arena, (Annotation) { .name = id, }); } - expect(annot); + expect(annot, "annotation"); append_list(const Node*, list, annot); continue; } @@ -1038,13 +1108,13 @@ static const Node* accept_const(ctxparams, Nodes annotations) { const Type* type = accept_unqualified_type(ctx); const char* id = accept_identifier(ctx); - expect(id); - expect(accept_token(ctx, equal_tok)); + expect(id, "constant name"); + expect(accept_token(ctx, equal_tok), "'='"); BodyBuilder* bb = begin_block_pure(arena); const Node* definition = accept_expr(ctx, bb, max_precedence()); - expect(definition); + expect(definition, "expression"); - expect(accept_token(ctx, semi_tok)); + expect(accept_token(ctx, semi_tok), "';'"); Node* cnst = constant(mod, annotations, type, id); cnst->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(definition)); @@ -1061,9 +1131,9 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { return NULL; const char* name = accept_identifier(ctx); - expect(name); + expect(name, "function name"); Nodes types = accept_types(ctx, comma_tok, MaybeQualified); - expect(curr_token(tokenizer).tag == lpar_tok); + expect(curr_token(tokenizer).tag == lpar_tok, "')'"); Nodes parameters; expect_parameters(ctx, ¶meters, NULL, NULL); @@ -1071,10 +1141,7 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { if (!accept_token(ctx, semi_tok)) set_abstraction_body(fn, expect_body(ctx, get_abstraction_mem(fn), types.count == 0 ? make_return_void : NULL)); - const Node* declaration = fn; - expect(declaration); - - return declaration; + return fn; } static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { @@ -1095,7 +1162,7 @@ static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { AddressSpace nas = accept_address_space(ctx); if (nas != NumAddressSpaces) { if (as != NumAddressSpaces && as != nas) { - error("Conflicting address spaces for definition: %s and %s.\n", get_address_space_name(as), get_address_space_name(nas)); + syntax_error_fmt("Conflicting address spaces for definition: %s and %s", get_address_space_name(as), get_address_space_name(nas)); } as = nas; continue; @@ -1104,14 +1171,14 @@ static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { } if (as == NumAddressSpaces) { - error("Address space required for global variable declaration.\n"); + syntax_error("Address space required for global variable declaration."); } if (uniform) { if (as == AsInput) as = AsUInput; else { - error("'uniform' can only be used with 'input' currently.\n"); + syntax_error("'uniform' can only be used with 'input'"); } } @@ -1122,17 +1189,17 @@ static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { } const Type* type = accept_unqualified_type(ctx); - expect(type); + expect(type, "global variable type"); const char* id = accept_identifier(ctx); - expect(id); + expect(id, "global variable name"); const Node* initial_value = NULL; if (accept_token(ctx, equal_tok)) { initial_value = accept_value(ctx, NULL); - expect(initial_value); + expect_fmt(initial_value, "value for global variable '%s'", id); } - expect(accept_token(ctx, semi_tok)); + expect(accept_token(ctx, semi_tok), "';'"); Node* gv = global_var(mod, annotations, type, id, as); gv->payload.global_variable.init = initial_value; @@ -1144,15 +1211,15 @@ static const Node* accept_nominal_type_decl(ctxparams, Nodes annotations) { return NULL; const char* id = accept_identifier(ctx); - expect(id); + expect(id, "nominal type name"); - expect(accept_token(ctx, equal_tok)); + expect(accept_token(ctx, equal_tok), "'='"); Node* nom = nominal_type(mod, annotations, id); nom->payload.nom_type.body = accept_unqualified_type(ctx); - expect(nom->payload.nom_type.body); + expect(nom->payload.nom_type.body, "nominal type body"); - expect(accept_token(ctx, semi_tok)); + expect(accept_token(ctx, semi_tok), "';'"); return nom; } @@ -1173,14 +1240,13 @@ void slim_parse_string(ParserConfig config, const char* contents, Module* mod) { if (!decl) decl = accept_nominal_type_decl(ctx, annotations); if (decl) { - debugv_print("decl parsed : "); - log_node(DEBUGV, decl); - debugv_print("\n"); + log_string(DEBUGVV, "decl parsed : "); + log_node(DEBUGVV, decl); + log_string(DEBUGVV, "\n"); continue; } - error_print("No idea what to parse here... (tok=(tag = %s, pos = %zu))\n", token_tags[token.tag], token.start); - exit(-3); + syntax_error("expected a declaration"); } destroy_tokenizer(tokenizer); diff --git a/src/frontend/slim/token.c b/src/frontend/slim/token.c index a20c78e47..0b90c5ce2 100644 --- a/src/frontend/slim/token.c +++ b/src/frontend/slim/token.c @@ -37,6 +37,8 @@ typedef struct Tokenizer_ { const size_t source_size; size_t pos; + size_t line; + size_t last_line_pos; Token current; } Tokenizer; @@ -50,7 +52,8 @@ Tokenizer* new_tokenizer(const char* source) { Tokenizer tokenizer = (Tokenizer) { .source = source, .source_size = strlen(source), - .pos = 0 + .pos = 0, + .line = 1, }; memcpy(alloc, &tokenizer, sizeof(Tokenizer)); next_token(alloc); @@ -65,7 +68,7 @@ static bool in_bounds(Tokenizer* tokenizer, size_t offset_to_slice) { return (tokenizer->pos + offset_to_slice) <= tokenizer->source_size; } -const char whitespace[] = { ' ', '\t', '\n', '\r' }; +const char whitespace[] = { ' ', '\t', '\r' }; static inline bool is_alpha(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } static inline bool is_digit(char c) { return c >= '0' && c <= '9'; } @@ -75,7 +78,11 @@ static inline bool can_make_up_identifier(char c) { return can_start_identifier( static void eat_whitespace_and_comments(Tokenizer* tokenizer) { while (tokenizer->pos < tokenizer->source_size) { - if (is_whitespace(tokenizer->source[tokenizer->pos])) { + if (tokenizer->source[tokenizer->pos] == '\n') { + tokenizer->line++; + tokenizer->pos++; + tokenizer->last_line_pos = tokenizer->pos; + } else if (is_whitespace(tokenizer->source[tokenizer->pos])) { tokenizer->pos++; } else if (tokenizer->pos + 2 <= tokenizer->source_size && tokenizer->source[tokenizer->pos] == '/' && tokenizer->source[tokenizer->pos + 1] == '/') { while (tokenizer->pos < tokenizer->source_size) { @@ -195,16 +202,23 @@ Token next_token(Tokenizer* tokenizer) { token.end = token.start + token_size; tokenizer->current = token; - debugvv_print("Token parsed: (tag = %s, pos = %zu", token_tags[token.tag], token.start); - if (token.tag == identifier_tok || token.tag == string_lit_tok) { - debugvv_print(", str="); - for (size_t i = token.start; i < token.end; i++) - debugvv_print("%c", tokenizer->source[i]); - } - debugvv_print(")\n"); + // debugvv_print("Token parsed: (tag = %s, pos = %zu", token_tags[token.tag], token.start); + // if (token.tag == identifier_tok || token.tag == string_lit_tok) { + // debugvv_print(", str="); + // for (size_t i = token.start; i < token.end; i++) + // debugvv_print("%c", tokenizer->source[i]); + // } + // debugvv_print(")\n"); return token; } +Loc current_loc(Tokenizer* tokenizer) { + return (Loc) { + .line = tokenizer->line, + .column = tokenizer->pos - tokenizer->last_line_pos + }; +} + Token curr_token(Tokenizer* tokenizer) { return tokenizer->current; } diff --git a/src/frontend/slim/token.h b/src/frontend/slim/token.h index 8afa155e9..454b51bb5 100644 --- a/src/frontend/slim/token.h +++ b/src/frontend/slim/token.h @@ -120,6 +120,12 @@ typedef struct { size_t end; } Token; +typedef struct { + size_t line, column; +} Loc; + +Loc current_loc(Tokenizer* tokenizer); + Token curr_token(Tokenizer* tokenizer); Token next_token(Tokenizer* tokenizer); From e5a159dbb567b7ccde263a8173585a94729d8c0e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 09:09:14 +0200 Subject: [PATCH 543/693] fixed lower_workgroups pass --- src/shady/passes/lower_workgroups.c | 74 +++++++++++++++++++---------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 64ee49139..9ceecdfcd 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -17,6 +17,16 @@ typedef struct { bool is_entry_point; } Context; +static void add_bounds_check(BodyBuilder* bb, const Node* i, const Node* max) { + IrArena* a = bb->arena; + Node* out_of_bounds_case = case_(a, empty(a)); + set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) { + .args = empty(a), + .mem = get_abstraction_mem(out_of_bounds_case) + })); + gen_if(bb, empty(a), gen_primop_e(bb, gte_op, empty(a), mk_nodes(a, i, max)), out_of_bounds_case, NULL); +} + static const Node* process(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; @@ -61,6 +71,7 @@ static const Node* process(Context* ctx, const Node* node) { Nodes nparams = recreate_params(&ctx->rewriter, node->payload.fun.params); Node* inner = function(m, nparams, format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, empty(a)); register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); + register_processed(&ctx->rewriter, get_abstraction_mem(node), get_abstraction_mem(inner)); set_abstraction_body(inner, recreate_node_identity(&ctx->rewriter, node->payload.fun.body)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(wrapper)); @@ -91,7 +102,30 @@ static const Node* process(Context* ctx, const Node* node) { num_subgroups_literals[dim] = uint32_literal(a, num_subgroups[dim]); } - BodyBuilder* bb2 = begin_block_with_side_effects(a, bb_mem(bb)); + Node* cases[6]; + BodyBuilder* builders[6]; + for (int scope = 0; scope < 2; scope++) { + const Node** params; + const Node** maxes; + if (scope == 1) { + params = subgroup_id; + maxes = num_subgroups_literals; + } else if (scope == 0) { + params = workgroup_id; + maxes = num_workgroups; + } else + assert(false); + for (int dim = 0; dim < 3; dim++) { + Node* loop_body = case_(a, singleton(params[dim])); + cases[scope * 3 + dim] = loop_body; + BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_body)); + builders[scope * 3 + dim] = loop_bb; + add_bounds_check(loop_bb, params[dim], maxes[dim]); + } + } + + // BodyBuilder* bb2 = begin_block_with_side_effects(a, bb_mem(builders[5])); + BodyBuilder* bb2 = builders[5]; // write the workgroup ID gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); // write the local ID @@ -107,39 +141,31 @@ static const Node* process(Context* ctx, const Node* node) { global_id[dim] = gen_primop_e(bb2, add_op, empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, empty(a), mk_nodes(a, uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID - - bind_instruction(bb2, call(a, (Call) { .callee = fn_addr_helper(a, inner), .args = wparams })); - const Node* instr = yield_values_and_wrap_in_block(bb2, empty(a)); + gen_call(bb2, fn_addr_helper(a, inner), wparams); // Wrap in 3 loops for iterating over subgroups, then again for workgroups - for (int scope = 0; scope < 2; scope++) { + for (unsigned scope = 1; scope < 2; scope--) { const Node** params; - const Node** maxes; if (scope == 0) { - params = subgroup_id; - maxes = num_subgroups_literals; - } else if (scope == 1) { params = workgroup_id; - maxes = num_workgroups; + } else if (scope == 1) { + params = subgroup_id; } else assert(false); - for (int dim = 0; dim < 3; dim++) { - Node* loop_body = case_(a, singleton(params[dim])); - BodyBuilder* body_bb = begin_body_with_mem(a, get_abstraction_mem(loop_body)); - Node* out_of_bounds_case = case_(a, empty(a)); - set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) {.args = empty(a), .mem = get_abstraction_mem(out_of_bounds_case)})); - gen_if(body_bb, empty(a), gen_primop_e(body_bb, gte_op, empty(a), mk_nodes(a, params[dim], maxes[dim])), out_of_bounds_case, NULL); - bind_instruction(body_bb, instr); - - BodyBuilder* bb3 = begin_block_with_side_effects(a, NULL); - set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) {.args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1))))}))); - gen_loop(bb3, empty(a), singleton(uint32_literal(a, 0)), loop_body); - instr = yield_values_and_wrap_in_block(bb3, empty(a)); + for (unsigned dim = 2; dim < 3; dim--) { + size_t depth = scope * 3 + dim; + Node* loop_body = cases[depth]; + BodyBuilder* body_bb = builders[depth]; + + set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) { + .args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1)))), + .mem = bb_mem(body_bb) + }))); + gen_loop(depth > 0 ? builders[depth - 1] : bb, empty(a), singleton(uint32_literal(a, 0)), loop_body); } } - bind_instruction(bb, instr); - set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = empty(a) }))); + set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) }))); return wrapper; } return recreate_node_identity(&ctx2.rewriter, node); From 1e4414e1d84d16ab88ee3064261cf8ed52bc3e1f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 09:15:30 +0200 Subject: [PATCH 544/693] c: fix composite emission --- src/backend/c/emit_c_value.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index f53747854..84bb45cfb 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -124,6 +124,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No Nodes elements = value->payload.composite.contents; Growy* g = new_growy(); + Printer* p2 = p; Printer* p = open_growy_as_printer(g); if (type->tag == ArrType_TAG) { @@ -155,9 +156,9 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No if (type->tag == ArrType_TAG) emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); - if (p) { + if (p2) { String tmp = unique_name(emitter->arena, "composite"); - print(p, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); + print(p2, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); emitted = tmp; } else { // this requires us to end up in the initialisation side of a declaration From 2f635261b0bbffc705e19d615376ac6814f962bf Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 09:48:16 +0200 Subject: [PATCH 545/693] c/ispc: fix various codegen issues --- src/backend/c/emit_c.c | 1 + src/backend/c/emit_c_type.c | 12 ++++++++---- src/backend/c/emit_c_value.c | 36 ++++++++++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 0a951a341..2c4e653fc 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -108,6 +108,7 @@ static bool has_forward_declarations(CDialect dialect) { /// hack for ISPC: there is no nice way to get a set of varying pointers (instead of a "pointer to a varying") pointing to a varying global CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term) { String interm = unique_name(emitter->arena, "intermediary_ptr_value"); + assert(ptr_type->tag == PtrType_TAG); const Type* ut = qualified_type_helper(ptr_type, true); const Type* vt = qualified_type_helper(ptr_type, false); String lhs = c_emit_type(emitter, vt, interm); diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index 416408e17..1cd54f864 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -209,10 +209,10 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { } break; case Type_RecordType_TAG: { - if (type->payload.record_type.members.count == 0) { - emitted = "void"; - break; - } + //if (type->payload.record_type.members.count == 0) { + // emitted = "void"; + // break; + //} emitted = unique_name(emitter->arena, "Record"); String prefixed = format_string_arena(emitter->arena->arena, "struct %s", emitted); @@ -224,6 +224,10 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { break; } case Type_QualifiedType_TAG: + if (type->payload.qualified_type.type == unit_type(emitter->arena)) { + emitted = "void"; + break; + } switch (emitter->config.dialect) { default: return c_emit_type(emitter, type->payload.qualified_type.type, center); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 84bb45cfb..fe7a3db72 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -775,7 +775,10 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* String params = printer_growy_unwrap(paramsp); CTerm called = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); - called = c_bind_intermediary_result(emitter, p, call->type, called); + if (call->type != empty_multiple_return_type(emitter->arena)) + called = c_bind_intermediary_result(emitter, p, call->type, called); + // else + // called = empty_term(); free_tmp_str(params); return called; @@ -861,12 +864,20 @@ static CTerm emit_lea(Emitter* emitter, FnEmitter* fn, Printer* p, Lea lea) { return acc; } -static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* type) { +static const Type* get_allocated_type(const Node* alloc) { + switch (alloc->tag) { + case Instruction_StackAlloc_TAG: return alloc->payload.stack_alloc.type; + case Instruction_LocalAlloc_TAG: return alloc->payload.local_alloc.type; + default: assert(false); return NULL; + } +} + +static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* instr) { String variable_name = unique_name(emitter->arena, "alloca"); CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; - c_emit_variable_declaration(emitter, p, type, variable_name, true, NULL); + c_emit_variable_declaration(emitter, p, get_allocated_type(instr), variable_name, true, NULL); if (emitter->config.dialect == CDialect_ISPC) { - variable = ispc_varying_ptr_helper(emitter, p, type, variable); + variable = ispc_varying_ptr_helper(emitter, p, get_unqualified_type(instr->type), variable); } return variable; } @@ -886,8 +897,8 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case Instruction_PrimOp_TAG: return emit_primop(emitter, fn, p, instruction); case Instruction_Call_TAG: return emit_call(emitter, fn, p, instruction); case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); return empty_term(); - case Instruction_StackAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.stack_alloc.mem); return emit_alloca(emitter, p, instruction->payload.stack_alloc.type); - case Instruction_LocalAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction->payload.local_alloc.type); + case Instruction_StackAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); + case Instruction_LocalAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); case Instruction_Lea_TAG: return emit_lea(emitter, fn, p, instruction->payload.lea); case Instruction_Load_TAG: { Load payload = instruction->payload.load; @@ -955,9 +966,18 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const SHADY_UNREACHABLE; } -static bool can_appear_at_top_level(const Node* node) { +static bool can_appear_at_top_level(Emitter* emitter, const Node* node) { if (is_instruction(node)) return false; + if (emitter->config.dialect == CDialect_ISPC) { + if (node->tag == RefDecl_TAG) { + const Node* decl = node->payload.ref_decl.decl; + if (decl->tag == GlobalVariable_TAG) + if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !is_decl_builtin(decl)) + //if (is_value(node) && !is_qualified_type_uniform(node->type)) + return false; + } + } return true; } @@ -970,7 +990,7 @@ CTerm c_emit_value(Emitter* emitter, FnEmitter* fn_builder, const Node* node) { CTerm emitted = c_emit_value_(emitter, fn_builder, fn_builder->instruction_printers[where->rpo_index], node); register_emitted(emitter, fn_builder, node, emitted); return emitted; - } else if (!can_appear_at_top_level(node)) { + } else if (!can_appear_at_top_level(emitter, node)) { if (!fn_builder) { log_node(ERROR, node); log_string(ERROR, "cannot appear at top-level"); From 7b10dc1cd9be98f3afc0254ebbc3b527e2b3e0e8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 10:09:31 +0200 Subject: [PATCH 546/693] c: fix some memory leaks --- src/backend/c/emit_c.c | 4 ++-- src/backend/c/emit_c_control_flow.c | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 2c4e653fc..b6edd501a 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -328,7 +328,6 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { } String fn_body = c_emit_body(emitter, &fn, decl); - String free_me = fn_body; if (emitter->config.dialect == CDialect_ISPC) { // ISPC hack: This compiler (like seemingly all LLVM-based compilers) has broken handling of the execution mask - it fails to generated masked stores for the entry BB of a function that may be called non-uniformingly // therefore we must tell ISPC to please, pretty please, mask everything by branching on what the mask should be @@ -348,8 +347,9 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { print(emitter->fn_defs, " %s", fn_body); deindent(emitter->fn_defs); print(emitter->fn_defs, "\n}"); - free_tmp_str(free_me); + destroy_scheduler(fn.scheduler); + destroy_cfg(fn.cfg); destroy_dict(fn.emitted_terms); free(fn.instruction_printers); } diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index d9d567a8d..d7bf036d4 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -30,7 +30,10 @@ String c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { // print(p, "\n"); fn->instruction_printers[cf_node->rpo_index] = NULL; - return printer_growy_unwrap(p); + String s2 = printer_growy_unwrap(p); + String s = string(emitter->arena, s2); + free((void*)s2); + return s; } static Strings emit_variable_declarations(Emitter* emitter, FnEmitter* fn, Printer* p, String given_name, Strings* given_names, Nodes types, bool mut, const Nodes* init_values) { @@ -65,7 +68,6 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { print(p, "%s", true_body); deindent(p); print(p, "\n}"); - free_tmp_str(true_body); if (if_.if_false) { assert(get_abstraction_params(if_.if_false).count == 0); String false_body = c_emit_body(&sub_emiter, fn, if_.if_false); @@ -74,7 +76,6 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { print(p, "%s", false_body); deindent(p); print(p, "\n}"); - free_tmp_str(false_body); } Nodes results = get_abstraction_params(if_.tail); @@ -115,7 +116,6 @@ static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) print(p, "%s", case_body); deindent(p); print(p, "\n}"); - free_tmp_str(case_body); first = false; } if (match.default_case) { @@ -125,7 +125,6 @@ static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) print(p, "%s", default_case_body); deindent(p); print(p, "\n}"); - free_tmp_str(default_case_body); } Nodes results = get_abstraction_params(match.tail); @@ -161,7 +160,6 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { print(p, "%s", body); deindent(p); print(p, "\n}"); - free_tmp_str(body); Nodes results = get_abstraction_params(loop.tail); for (size_t i = 0; i < ephis.count; i++) { From 9dd490a3b4b0b2bfacf3bdbd750682e1f0911d25 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 10:33:15 +0200 Subject: [PATCH 547/693] aobench: fix ispc path --- samples/aobench/ao_main.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 8bdf76639..1c4279756 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -66,9 +66,7 @@ typedef struct { extern Vec3u builtin_NumWorkgroups; void render_ispc(TEXEL_T* img, int w, int h, int nsubsamples) { - struct timespec ts; - timespec_get(&ts, TIME_UTC); - uint64_t tsn = timespec_to_nano(ts); + uint64_t tsn = get_time_nano(); Ctx ctx = get_init_context(); init_scene(&ctx); for (size_t i = 0; i < WIDTH; i++) { @@ -84,9 +82,7 @@ void render_ispc(TEXEL_T* img, int w, int h, int nsubsamples) { builtin_NumWorkgroups.z = 1; aobench_kernel(img); - struct timespec tp; - timespec_get(&tp, TIME_UTC); - uint64_t tpn = timespec_to_nano(tp); + uint64_t tpn = get_time_nano(); info_print("ispc rendering took %d us\n", (tpn - tsn) / 1000); } #endif From 9b0cae25a4b65e43a8e7f25dd6a94f26701db1db Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 10:33:36 +0200 Subject: [PATCH 548/693] c: make sure to emit bodies recursively _first_ --- src/backend/c/emit_c_control_flow.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index d7bf036d4..d0229ae23 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -62,6 +62,8 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { assert(get_abstraction_params(if_.if_true).count == 0); String true_body = c_emit_body(&sub_emiter, fn, if_.if_true); + String false_body = if_.if_false ? c_emit_body(&sub_emiter, fn, if_.if_false) : NULL; + String tail = c_emit_body(emitter, fn, if_.tail); CValue condition = to_cvalue(emitter, c_emit_value(emitter, fn, if_.condition)); print(p, "\nif (%s) { ", condition); indent(p); @@ -70,7 +72,6 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { print(p, "\n}"); if (if_.if_false) { assert(get_abstraction_params(if_.if_false).count == 0); - String false_body = c_emit_body(&sub_emiter, fn, if_.if_false); print(p, " else {"); indent(p); print(p, "%s", false_body); @@ -83,7 +84,7 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - print(p, "%s", c_emit_body(emitter, fn, if_.tail)); + print(p, "%s", tail); } static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) { @@ -103,23 +104,25 @@ static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) CValue inspectee = to_cvalue(emitter, c_emit_value(emitter, fn, match.inspect)); bool first = true; LARRAY(CValue, literals, match.cases.count); + LARRAY(String, bodies, match.cases.count); + String default_case_body = c_emit_body(&sub_emiter, fn, match.default_case); + String tail = c_emit_body(emitter, fn, match.tail); for (size_t i = 0; i < match.cases.count; i++) { literals[i] = to_cvalue(emitter, c_emit_value(emitter, fn, match.literals.nodes[i])); + bodies[i] = c_emit_body(&sub_emiter, fn, match.cases.nodes[i]); } for (size_t i = 0; i < match.cases.count; i++) { - String case_body = c_emit_body(&sub_emiter, fn, match.cases.nodes[i]); print(p, "\n"); if (!first) print(p, "else "); print(p, "if (%s == %s) { ", inspectee, literals[i]); indent(p); - print(p, "%s", case_body); + print(p, "%s", bodies[i]); deindent(p); print(p, "\n}"); first = false; } if (match.default_case) { - String default_case_body = c_emit_body(&sub_emiter, fn, match.default_case); print(p, "\nelse { "); indent(p); print(p, "%s", default_case_body); @@ -132,7 +135,7 @@ static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - print(p, "%s", c_emit_body(emitter, fn, match.tail)); + print(p, "%s", tail); } static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { @@ -155,6 +158,7 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { sub_emiter.phis.loop_break = ephis; String body = c_emit_body(&sub_emiter, fn, loop.body); + String tail = c_emit_body(emitter, fn, loop.tail); print(p, "\nwhile(true) { "); indent(p); print(p, "%s", body); @@ -166,7 +170,7 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - print(p, "%s", c_emit_body(emitter, fn, loop.tail)); + print(p, "%s", tail); } static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_printer, const Node* terminator) { From 967eb9b597c2da7e88602ef1beada6e6b39307e5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 10:34:03 +0200 Subject: [PATCH 549/693] c: move some fns about --- src/backend/c/emit_c.c | 30 ++++++++++++------------------ src/backend/c/emit_c_value.c | 12 ++++++++++++ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index b6edd501a..f0ee5af6f 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -116,24 +116,6 @@ CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Ty return term_from_cvalue(interm); } -CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { - String bind_to = unique_name(emitter->arena, ""); - c_emit_variable_declaration(emitter, p, t, bind_to, false, &term); - return term_from_cvalue(bind_to); -} - -void c_emit_pack_code(Printer* p, Strings src, String dst) { - for (size_t i = 0; i < src.count; i++) { - print(p, "\n%s->_%d = %s", dst, src.strings[i], i); - } -} - -void c_emit_unpack_code(Printer* p, String src, Strings dst) { - for (size_t i = 0; i < dst.count; i++) { - print(p, "\n%s = %s->_%d", dst.strings[i], src, i); - } -} - void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer) { assert((mut || initializer != NULL) && "unbound results are only allowed when creating a mutable local variable"); @@ -162,6 +144,18 @@ void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const print(block_printer, "\n%s%s;", prefix, decl); } +void c_emit_pack_code(Printer* p, Strings src, String dst) { + for (size_t i = 0; i < src.count; i++) { + print(p, "\n%s->_%d = %s", dst, src.strings[i], i); + } +} + +void c_emit_unpack_code(Printer* p, String src, Strings dst) { + for (size_t i = 0; i < dst.count; i++) { + print(p, "\n%s = %s->_%d", dst.strings[i], src, i); + } +} + void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String name, const Type* type, bool constant, String init) { String prefix = NULL; diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index fe7a3db72..170aaf1e3 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -232,6 +232,18 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No return term_from_cvalue(emitted); } +CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { + if (is_term_empty(term)) + return term; + if (t == empty_multiple_return_type(emitter->arena)) { + print(p, "%s;", to_cvalue(emitter, term)); + return empty_term(); + } + String bind_to = unique_name(emitter->arena, ""); + c_emit_variable_declaration(emitter, p, t, bind_to, false, &term); + return term_from_cvalue(bind_to); +} + static const Type* get_first_op_scalar_type(Nodes ops) { const Type* t = first(ops)->type; deconstruct_qualified_type(&t); From 0880a2251ccd6151e8f4e9541d83bfde9875a600 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 10:34:15 +0200 Subject: [PATCH 550/693] c: always bind primops for now --- src/backend/c/emit_c_value.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 170aaf1e3..8c1caa6f1 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -579,8 +579,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } } if (conv_fn) { - CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, to_cvalue(emitter, src_value))); - return c_bind_intermediary_result(emitter, p, node->type, converted); + return term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, to_cvalue(emitter, src_value))); } error_print("glsl: unsupported bit cast from "); log_node(ERROR, src_type); @@ -601,14 +600,10 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case FloatTy64: n = "doublebits"; break; } - CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); - return c_bind_intermediary_result(emitter, p, node->type, converted); - break; + return term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); } else if (src_type->tag == Float_TAG) { assert(dst_type->tag == Int_TAG); - CTerm converted = term_from_cvalue(format_string_arena(emitter->arena->arena, "intbits(%s)", to_cvalue(emitter, src_value))); - return c_bind_intermediary_result(emitter, p, node->type, converted); - break; + return term_from_cvalue(format_string_arena(emitter->arena->arena, "intbits(%s)", to_cvalue(emitter, src_value))); } CType t = c_emit_type(emitter, dst_type, NULL); @@ -787,10 +782,7 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* String params = printer_growy_unwrap(paramsp); CTerm called = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); - if (call->type != empty_multiple_return_type(emitter->arena)) - called = c_bind_intermediary_result(emitter, p, call->type, called); - // else - // called = empty_term(); + called = c_bind_intermediary_result(emitter, p, call->type, called); free_tmp_str(params); return called; @@ -906,7 +898,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case Instruction_SetStackSize_TAG: case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); case Instruction_ExtInstr_TAG: return emit_ext_instruction(emitter, fn, p, instruction->payload.ext_instr); - case Instruction_PrimOp_TAG: return emit_primop(emitter, fn, p, instruction); + case Instruction_PrimOp_TAG: return c_bind_intermediary_result(emitter, p, instruction->type, emit_primop(emitter, fn, p, instruction)); case Instruction_Call_TAG: return emit_call(emitter, fn, p, instruction); case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); return empty_term(); case Instruction_StackAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); @@ -916,8 +908,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const Load payload = instruction->payload.load; c_emit_mem(emitter, fn, payload.mem); CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, fn, payload.ptr)); - // we must bind the intermediary result here, otherwise we duplicate the load everwhere it is consumed - return c_bind_intermediary_result(emitter, p, instruction->type, term_from_cvalue(dereferenced)); + return term_from_cvalue(dereferenced); } case Instruction_Store_TAG: { Store payload = instruction->payload.store; From 07680fb383a54549688d951775298ce14a88651a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 10:34:23 +0200 Subject: [PATCH 551/693] aobench: disable vectorisation --- samples/aobench/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/aobench/CMakeLists.txt b/samples/aobench/CMakeLists.txt index f8baed4ca..ce5f18ced 100644 --- a/samples/aobench/CMakeLists.txt +++ b/samples/aobench/CMakeLists.txt @@ -4,7 +4,7 @@ elseif(NOT TARGET runtime) message("Runtime component unavailable. Skipping aobench sample.") else() add_executable(aobench_host ao_host.c ao_main.c) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMAND vcc ARGS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp --only-run-clang -O3 -o ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMENT ao.comp.c.ll DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ao.c) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMAND vcc ARGS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp --only-run-clang -O3 -fno-slp-vectorize -fno-vectorize -o ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll COMMENT ao.comp.c.ll DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ao.comp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ao.c) set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/ao_main.c APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ao.comp.c.ll) add_custom_command(TARGET aobench_host POST_BUILD From 2cc07952c36e8256aa68f21c2ef680192cda15b8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 31 Aug 2024 21:41:51 +0200 Subject: [PATCH 552/693] fold: fix broken match folding rule --- src/shady/fold.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shady/fold.c b/src/shady/fold.c index 75b2726a4..8859abc6f 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -422,6 +422,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { .literals = nodes(arena, new_cases_count, literals), .cases = nodes(arena, new_cases_count, cases), .tail = payload.tail, + .mem = payload.mem, }); } default: break; From f6eeb5657386db9f534f227fc525b15da81df7c8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 1 Sep 2024 08:45:04 +0200 Subject: [PATCH 553/693] move opt_restructure to the end of the pipeline --- include/shady/ir.h | 15 ++++ src/shady/body_builder.c | 39 ++++++++++ src/shady/compile.c | 3 +- src/shady/passes/lower_generic_ptrs.c | 63 +++++++++------ src/shady/passes/lower_memcpy.c | 47 ++++++++---- src/shady/passes/lower_physical_ptrs.c | 2 +- src/shady/passes/lower_stack.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_tailcalls.c | 101 ++++++++++++++++++------- 9 files changed, 205 insertions(+), 69 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index bb69a3997..e0a23eadd 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -296,6 +296,21 @@ Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, Node*); Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, Node*); Nodes gen_loop(BodyBuilder*, Nodes, Nodes, Node*); + +struct begin_control_r { + Nodes results; + Node* case_; + const Node* jp; +} begin_control(BodyBuilder*, Nodes); + +struct begin_loop_helper_r { + Nodes results; + Node* loop_body; + Nodes params; + const Node* continue_jp; + const Node* break_jp; +} begin_loop_helper(BodyBuilder*, Nodes, Nodes, Nodes); + Nodes gen_control(BodyBuilder*, Nodes, Node*); const Node* bb_mem(BodyBuilder*); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index c2df299fa..139275e7f 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -322,6 +322,45 @@ Nodes gen_control(BodyBuilder* bb, Nodes yield_types, Node* body) { }); } +struct begin_control_r begin_control(BodyBuilder* bb, Nodes yield_types) { + IrArena* a = bb->arena; + const Type* jp_type = qualified_type(a, (QualifiedType) { + .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), + .is_uniform = true + }); + const Node* jp = param(a, jp_type, NULL); + Node* c = case_(a, singleton(jp)); + return (struct begin_control_r) { + .results = gen_control(bb, yield_types, c), + .case_ = c, + .jp = jp + }; +} + +struct begin_loop_helper_r begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes arg_types, Nodes initial_values) { + assert(arg_types.count == initial_values.count); + IrArena* a = bb->arena; + struct begin_control_r outer_control = begin_control(bb, yield_types); + BodyBuilder* outer_control_case_builder = begin_body_with_mem(a, get_abstraction_mem(outer_control.case_)); + LARRAY(const Node*, params, arg_types.count); + for (size_t i = 0; i < arg_types.count; i++) { + params[i] = param(a, qualified_type_helper(arg_types.nodes[i], false), NULL); + } + Node* loop_header = case_(a, nodes(a, arg_types.count, params)); + set_abstraction_body(outer_control.case_, finish_body_with_jump(outer_control_case_builder, loop_header, initial_values)); + BodyBuilder* loop_header_builder = begin_body_with_mem(a, get_abstraction_mem(loop_header)); + struct begin_control_r inner_control = begin_control(loop_header_builder, arg_types); + set_abstraction_body(loop_header, finish_body_with_jump(loop_header_builder, loop_header, inner_control.results)); + + return (struct begin_loop_helper_r) { + .results = outer_control.results, + .params = nodes(a, arg_types.count, params), + .loop_body = inner_control.case_, + .break_jp = outer_control.jp, + .continue_jp = inner_control.jp, + }; +} + void cancel_body(BodyBuilder* bb) { for (size_t i = 0; i < entries_count_list(bb->stack); i++) { StackEntry entry = read_list(StackEntry, bb->stack)[i]; diff --git a/src/shady/compile.c b/src/shady/compile.c index 8fbd7ddaa..a7c400cb7 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -83,7 +83,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_tailcalls) //RUN_PASS(lower_switch_btree) - RUN_PASS(opt_restructurize) //RUN_PASS(opt_mem2reg) if (config->specialization.entry_point) @@ -118,6 +117,8 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_nullptr) RUN_PASS(normalize_builtins) + RUN_PASS(opt_restructurize) + return CompilationNoError; } diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index a6e6b7690..d7b3a515c 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -93,64 +93,83 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo params = append_nodes(a, params, value_param); break; } - Node* new_fn = function(ctx->rewriter.dst_module, params, name, singleton(annotation(a, (Annotation) { .name = "Generated" })), return_ts); + Node* new_fn = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); insert_dict(String, const Node*, ctx->fns, name, new_fn); size_t max_tag = sizeof(generic_ptr_tags) / sizeof(generic_ptr_tags[0]); switch (which) { case LoadFn: { + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); + gen_comment(bb, "Generated generic ptr store"); + struct begin_control_r r = begin_control(bb, singleton(t)); + const Node* final_loaded_value = first(r.results); + LARRAY(const Node*, literals, max_tag); - LARRAY(Node*, cases, max_tag); + LARRAY(const Node*, jumps, max_tag); for (size_t tag = 0; tag < max_tag; tag++) { literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { - cases[tag] = case_(a, empty(a)); - set_abstraction_body(cases[tag], unreachable(a, (Unreachable) { .mem = get_abstraction_mem(cases[tag]) })); + Node* tag_case = case_(a, empty(a)); + set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(tag_case) })); + jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); continue; } - cases[tag] = case_(a, empty(a)); - BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(cases[tag])); + Node* tag_case = case_(a, empty(a)); + BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); - set_abstraction_body(cases[tag], finish_body_with_selection_merge(case_bb, singleton(loaded_value))); + set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, singleton(loaded_value))); + jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); } - - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); - gen_comment(bb, "Generated generic ptr store"); // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, empty(a)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); - const Node* loaded_value = first(gen_match(bb, singleton(t), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, (const Node**) cases), default_case)); - set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = singleton(loaded_value), .mem = bb_mem(bb) }))); + set_abstraction_body(r.case_, br_switch(a, (Switch) { + .mem = get_abstraction_mem(r.case_), + .switch_value = extracted_tag, + .case_values = nodes(a, max_tag, literals), + .case_jumps = nodes(a, max_tag, jumps), + .default_jump = jump_helper(a, default_case, empty(a), get_abstraction_mem(r.case_)) + })); + set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = singleton(final_loaded_value), .mem = bb_mem(bb) }))); break; } case StoreFn: { + BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); + gen_comment(bb, "Generated generic ptr store"); + struct begin_control_r r = begin_control(bb, empty(a)); + LARRAY(const Node*, literals, max_tag); - LARRAY(Node*, cases, max_tag); + LARRAY(const Node*, jumps, max_tag); for (size_t tag = 0; tag < max_tag; tag++) { literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { - cases[tag] = case_(a, empty(a)); - set_abstraction_body(cases[tag], unreachable(a, (Unreachable) { .mem = get_abstraction_mem(cases[tag]) })); + Node* tag_case = case_(a, empty(a)); + set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(tag_case) })); + jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); continue; } - cases[tag] = case_(a, empty(a)); - BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(cases[tag])); + Node* tag_case = case_(a, empty(a)); + BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); - set_abstraction_body(cases[tag], finish_body_with_selection_merge(case_bb, empty(a))); + set_abstraction_body(tag_case, finish_body_with_selection_merge(case_bb, empty(a))); + jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); } - - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); - gen_comment(bb, "Generated generic ptr store"); // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, empty(a)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); - gen_match(bb, empty(a), extracted_tag, nodes(a, max_tag, literals), nodes(a, max_tag, (const Node**) cases), default_case); + set_abstraction_body(r.case_, br_switch(a, (Switch) { + .mem = get_abstraction_mem(r.case_), + .switch_value = extracted_tag, + .case_values = nodes(a, max_tag, literals), + .case_jumps = nodes(a, max_tag, jumps), + .default_jump = jump_helper(a, default_case, empty(a), get_abstraction_mem(r.case_)) + })); set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) }))); break; } diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index ec871321b..3da7d3b74 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -53,19 +53,28 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, payload.count)); const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num_in_bytes)); - const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memcpy_i"); - Node* loop_case = case_(a, singleton(index)); + struct begin_loop_helper_r l = begin_loop_helper(bb, empty(a), singleton(uint32_type(a)), singleton( uint32_literal(a, 0))); + + const Node* index = first(l.params); + set_value_name(index, "memcpy_i"); + Node* loop_case = l.loop_body; BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, empty(a))); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); + Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, merge_continue(a, (MergeContinue) { .mem = get_abstraction_mem(true_case), .args = singleton(next_index) })); + set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = singleton(next_index) })); Node* false_case = case_(a, empty(a)); - set_abstraction_body(false_case, merge_break(a, (MergeBreak) { .mem = get_abstraction_mem(false_case), .args = empty(a) })); - gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), true_case, false_case); - set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a, (Unreachable) { .mem = bb_mem(loop_bb) }))); - gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), loop_case); + set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = get_abstraction_mem(false_case), .args = empty(a) })); + + set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { + .mem = bb_mem(loop_bb), + .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), + .true_jump = jump_helper(a, true_case, empty(a), bb_mem(loop_bb)), + .false_jump = jump_helper(a, false_case, empty(a), bb_mem(loop_bb)), + }))); + return yield_values_and_wrap_in_block(bb, empty(a)); } case FillBytes_TAG: { @@ -89,20 +98,28 @@ static const Node* process(Context* ctx, const Node* old) { dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); const Node* num = rewrite_node(&ctx->rewriter, payload.count); - const Node* num_in_bytes = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); + const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); + + struct begin_loop_helper_r l = begin_loop_helper(bb, empty(a), singleton(uint32_type(a)), singleton( uint32_literal(a, 0))); - const Node* index = param(a, qualified_type_helper(uint32_type(a), false), "memset_i"); - Node* loop_case = case_(a, singleton(index)); + const Node* index = first(l.params); + set_value_name(index, "memset_i"); + Node* loop_case = l.loop_body; BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); + Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, merge_continue(a, (MergeContinue) { .mem = get_abstraction_mem(true_case), .args = singleton(next_index) })); + set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = singleton(next_index) })); Node* false_case = case_(a, empty(a)); - set_abstraction_body(false_case, merge_break(a, (MergeBreak) { .mem = get_abstraction_mem(false_case), .args = empty(a) })); - gen_if(loop_bb, empty(a), gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_bytes)), true_case, false_case); - set_abstraction_body(loop_case, finish_body(loop_bb, unreachable(a, (Unreachable) { .mem = bb_mem(loop_bb) }))); - gen_loop(bb, empty(a), singleton(uint32_literal(a, 0)), loop_case); + set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = get_abstraction_mem(false_case), .args = empty(a) })); + + set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { + .mem = bb_mem(loop_bb), + .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), + .true_jump = jump_helper(a, true_case, empty(a), bb_mem(loop_bb)), + .false_jump = jump_helper(a, false_case, empty(a), bb_mem(loop_bb)), + }))); return yield_values_and_wrap_in_block(bb, empty(a)); } default: break; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 86a932f0b..9e1b64b5a 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -273,7 +273,7 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un Nodes return_ts = ser ? empty(a) : singleton(return_value_t); String name = format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", get_address_space_name(as), uniform_address ? "uniform" : "varying", name_type_safe(a, element_type)); - Node* fun = function(ctx->rewriter.dst_module, params, name, singleton(annotation(a, (Annotation) { .name = "Generated" })), return_ts); + Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); insert_dict(const Node*, Node*, cache, element_type, fun); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index d330d7cb0..885036a8d 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -41,7 +41,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { Nodes params = push ? singleton(value_param) : empty(a); Nodes return_ts = push ? empty(a) : singleton(qualified_t); String name = format_string_arena(a->arena, "generated_%s_%s", push ? "push" : "pop", name_type_safe(a, element_type)); - Node* fun = function(ctx->rewriter.dst_module, params, name, singleton(annotation(a, (Annotation) { .name = "Generated" })), return_ts); + Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); insert_dict(const Node*, Node*, cache, element_type, fun); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index e7f8e07e3..c5c26ee07 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -119,7 +119,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod else { const Node* src_param = param(a, qualified_type_helper(t, false), "src"); fn = function(m, singleton(src_param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), - singleton(annotation(a, (Annotation) { .name = "Generated"})), singleton(qualified_type_helper(t, true))); + mk_nodes(a, annotation(a, (Annotation) { .name = "Generated"}), annotation(a, (Annotation) { .name = "Leaf" })), singleton(qualified_type_helper(t, true))); insert_dict(const Node*, Node*, ctx->fns, t, fn); build_fn_body(ctx, fn, scope, src_param, t); } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 3e8bdc83a..488d6b3d9 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -80,7 +80,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { gen_call(bb, jump_fn, singleton(fn_addr)); if (!*ctx->top_dispatcher_fn) { - *ctx->top_dispatcher_fn = function(ctx->rewriter.dst_module, nodes(a, 0, NULL), "top_dispatcher", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" }), annotation(a, (Annotation) { .name = "Structured" })), nodes(a, 0, NULL)); + *ctx->top_dispatcher_fn = function(ctx->rewriter.dst_module, nodes(a, 0, NULL), "top_dispatcher", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), nodes(a, 0, NULL)); } gen_call(bb, fn_addr_helper(a, *ctx->top_dispatcher_fn), empty(a)); @@ -268,13 +268,20 @@ void generate_top_level_dispatch_fn(Context* ctx) { assert((*ctx->top_dispatcher_fn)->tag == Function_TAG); IrArena* a = ctx->rewriter.dst_arena; + BodyBuilder* dispatcher_body_builder = begin_body_with_mem(a, get_abstraction_mem(*ctx->top_dispatcher_fn)); + bool count_iterations = ctx->config->shader_diagnostics.max_top_iterations > 0; const Node* iterations_count_param = NULL; - if (count_iterations) - iterations_count_param = param(a, qualified_type(a, (QualifiedType) { .type = int32_type(a), .is_uniform = true }), "iterations"); + // if (count_iterations) + // iterations_count_param = param(a, qualified_type(a, (QualifiedType) { .type = int32_type(a), .is_uniform = true }), "iterations"); - Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL)); + // Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL)); + // gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a), loop_inside_case); + struct begin_loop_helper_r l = begin_loop_helper(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_type(a)) : empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a)); + Node* loop_inside_case = l.loop_body; + if (count_iterations) + iterations_count_param = first(l.params); BodyBuilder* loop_body_builder = begin_body_with_mem(a, get_abstraction_mem(loop_inside_case)); const Node* next_function = gen_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); @@ -296,15 +303,28 @@ void generate_top_level_dispatch_fn(Context* ctx) { iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, 1))); if (ctx->config->shader_diagnostics.max_top_iterations > 0) { + struct begin_control_r c = begin_control(loop_body_builder, empty(a)); const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); - Node* true_case = case_(a, empty(a)); - const Node* break_terminator = merge_break(a, (MergeBreak) { .args = empty(a), .mem = get_abstraction_mem(true_case) }); - set_abstraction_body(true_case, break_terminator); - gen_if(loop_body_builder, empty(a), bail_condition, true_case, NULL); + Node* bail_case = case_(a, empty(a)); + const Node* break_terminator = join(a, (Join) { .args = empty(a), .join_point = l.break_jp, .mem = get_abstraction_mem(bail_case) }); + set_abstraction_body(bail_case, break_terminator); + Node* proceed_case = case_(a, empty(a)); + set_abstraction_body(proceed_case, join(a, (Join) { + .join_point = c.jp, + .mem = get_abstraction_mem(proceed_case), + .args = empty(a), + })); + set_abstraction_body(c.case_, branch(a, (Branch) { + .mem = get_abstraction_mem(c.case_), + .condition = bail_condition, + .true_jump = jump_helper(a, bail_case, empty(a), get_abstraction_mem(c.case_)), + .false_jump = jump_helper(a, proceed_case, empty(a), get_abstraction_mem(c.case_)), + })); + // gen_if(loop_body_builder, empty(a), bail_condition, bail_case, NULL); } struct List* literals = new_list(const Node*); - struct List* cases = new_list(const Node*); + struct List* jumps = new_list(const Node*); // Build 'zero' case (exits the program) Node* zero_case_lam = case_(a, nodes(a, 0, NULL)); @@ -315,17 +335,29 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } - set_abstraction_body(zero_if_true_lam, finish_body_with_loop_break(zero_if_case_builder, empty(a))); - gen_if(zero_case_builder, empty(a), should_run, zero_if_true_lam, NULL); + set_abstraction_body(zero_if_true_lam, finish_body_with_join(zero_if_case_builder, l.break_jp, empty(a))); + // gen_if(zero_case_builder, empty(a), should_run, zero_if_true_lam, NULL); + + // set_abstraction_body(zero_case_lam, finish_body_with_join(zero_case_builder, l.continue_jp, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); + Node* zero_if_false = case_(a, empty(a)); + BodyBuilder* zero_false_builder = begin_body_with_mem(a, get_abstraction_mem(zero_if_false)); if (ctx->config->printf_trace.god_function) { - const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); - gen_debug_printf(zero_case_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); + const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, zero_false_builder, BuiltinSubgroupId); + gen_debug_printf(zero_false_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } + set_abstraction_body(zero_if_false, finish_body_with_join(zero_false_builder, l.continue_jp, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); + + set_abstraction_body(zero_case_lam, branch(a, (Branch) { + .mem = get_abstraction_mem(zero_case_lam), + .condition = should_run, + .true_jump = jump_helper(a, zero_if_true_lam, empty(a), get_abstraction_mem(zero_case_lam)), + .false_jump = jump_helper(a, zero_if_false, empty(a), get_abstraction_mem(zero_case_lam)), + })); - set_abstraction_body(zero_case_lam, finish_body_with_loop_continue(zero_case_builder, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); const Node* zero_lit = uint64_literal(a, 0); append_list(const Node*, literals, zero_lit); - append_list(const Node*, cases, zero_case_lam); + const Node* zero_jump = jump_helper(a, zero_case_lam, empty(a), bb_mem(loop_body_builder)); + append_list(const Node*, jumps, zero_jump); Nodes old_decls = get_module_declarations(ctx->rewriter.src_module); for (size_t i = 0; i < old_decls.count; i++) { @@ -343,29 +375,42 @@ void generate_top_level_dispatch_fn(Context* ctx) { gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } gen_call(if_builder, fn_addr_helper(a, rewrite_node(&ctx->rewriter, decl)), empty(a)); - set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_builder, empty(a))); + set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, empty(a))); + + Node* if_false = case_(a, empty(a)); + set_abstraction_body(if_false, join(a, (Join) { + .mem = get_abstraction_mem(if_false), + .join_point = l.continue_jp, + .args = count_iterations ? singleton(iteration_count_plus_one) : empty(a) + })); Node* fn_case = case_(a, nodes(a, 0, NULL)); - BodyBuilder* case_builder = begin_body_with_mem(a, get_abstraction_mem(fn_case)); - gen_if(case_builder, empty(a), should_run, if_true_case, NULL); - set_abstraction_body(fn_case, finish_body_with_loop_continue(case_builder, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); + set_abstraction_body(fn_case, branch(a, (Branch) { + .mem = get_abstraction_mem(fn_case), + .condition = should_run, + .true_jump = jump_helper(a, if_true_case, empty(a), get_abstraction_mem(fn_case)), + .false_jump = jump_helper(a, if_false, empty(a), get_abstraction_mem(fn_case)), + })); append_list(const Node*, literals, fn_lit); - append_list(const Node*, cases, fn_case); + const Node* j = jump_helper(a, fn_case, empty(a), bb_mem(loop_body_builder)); + append_list(const Node*, jumps, j); } } Node* default_case = case_(a, nodes(a, 0, NULL)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); - gen_match(loop_body_builder, empty(a), next_function, nodes(a, entries_count_list(literals), read_list(const Node*, literals)), nodes(a, entries_count_list(cases), read_list(const Node*, cases)), default_case); - - destroy_list(literals); - destroy_list(cases); - set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, unreachable(a, (Unreachable) { .mem = bb_mem(loop_body_builder) }))); + set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, br_switch(a, (Switch) { + .mem = bb_mem(loop_body_builder), + .switch_value = next_function, + .case_values = nodes(a, entries_count_list(literals), read_list(const Node*, literals)), + .case_jumps = nodes(a, entries_count_list(jumps), read_list(const Node*, jumps)), + .default_jump = jump_helper(a, default_case, empty(a), bb_mem(loop_body_builder)) + }))); - BodyBuilder* dispatcher_body_builder = begin_body_with_mem(a, get_abstraction_mem(*ctx->top_dispatcher_fn)); - gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : nodes(a, 0, NULL), loop_inside_case); + destroy_list(literals); + destroy_list(jumps); if (ctx->config->printf_trace.god_function) gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", empty(a)); @@ -386,7 +431,7 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) struct Dict* ptrs = new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); - Node* init_fn = function(dst, nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" }), annotation(a, (Annotation) { .name = "Structured" })), nodes(a, 0, NULL)); + Node* init_fn = function(dst, nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), nodes(a, 0, NULL)); set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = empty(a), .mem = get_abstraction_mem(init_fn) })); FnPtr next_fn_ptr = 1; From e8d557a8e4da5a2daa6ab43fc2ccc5fcdca0c1bc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 1 Sep 2024 16:53:21 +0200 Subject: [PATCH 554/693] lower_generic_globals: avoid creating an useless constant --- src/shady/passes/lower_generic_globals.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index fdcc11444..fb4697e5b 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -12,24 +12,29 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - IrArena* a = ctx->rewriter.dst_arena; + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; switch (node->tag) { + case RefDecl_TAG: { + // make sure we rewrite the decl first, and then look if it rewrote the ref to it! + rewrite_node(r, node->payload.ref_decl.decl); + const Node* f = search_processed(r, node); + if (f) return f; + break; + } case GlobalVariable_TAG: { if (node->payload.global_variable.address_space == AsGeneric) { AddressSpace dst_as = AsGlobal; const Type* t = rewrite_node(&ctx->rewriter, node->payload.global_variable.type); Node* new_global = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations), t, node->payload.global_variable.name, dst_as); + register_processed(&ctx->rewriter, node, new_global); const Type* dst_t = ptr_type(a, (PtrType) { .pointed_type = t, .address_space = AsGeneric }); - Nodes decl_annotations = singleton(annotation(a, (Annotation) { .name = "Generated" })); - Node* constant_decl = constant(ctx->rewriter.dst_module, decl_annotations, dst_t, - format_string_interned(a, "%s_generic", get_declaration_name(node))); - const Node* result = constant_decl; - constant_decl->payload.constant.value = prim_op_helper(a, convert_op, singleton(dst_t), singleton(ref_decl_helper(a, new_global))); - register_processed(&ctx->rewriter, node, result); - new_global->payload.global_variable.init = rewrite_node(&ctx->rewriter, node->payload.global_variable.init); - return result; + const Node* converted = prim_op_helper(a, convert_op, singleton(dst_t), singleton(ref_decl_helper(a, new_global))); + register_processed(&ctx->rewriter, ref_decl_helper(node->arena, node), converted); + return new_global; } + break; } default: break; } From 801bfc7655b1bd6e33e4ec00bd562b356e44ad58 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 1 Sep 2024 16:53:51 +0200 Subject: [PATCH 555/693] lower_generic_ptrs: fix write path --- src/shady/passes/lower_generic_ptrs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index d7b3a515c..f303fee5d 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -155,7 +155,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); - set_abstraction_body(tag_case, finish_body_with_selection_merge(case_bb, empty(a))); + set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, empty(a))); jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); } // extracted_tag = nptr >> (64 - 2), for example From 1626e02bf7a2364221f859aff131783a11e4df06 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 08:29:52 +0200 Subject: [PATCH 556/693] fix some asan issues --- src/backend/spirv/emit_spv.c | 3 +-- src/shady/passes/lower_tailcalls.c | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index a2047a77d..6c31660cd 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -130,8 +130,6 @@ static void emit_function(Emitter* emitter, const Node* node) { } emit_basic_block(emitter, &fn_builder, fn_builder.cfg->entry); - free(fn_builder.per_bb); - spvb_define_function(emitter->file_builder, fn_builder.base); } else { Growy* g = new_growy(); @@ -142,6 +140,7 @@ static void emit_function(Emitter* emitter, const Node* node) { spvb_declare_function(emitter->file_builder, fn_builder.base); } + free(fn_builder.per_bb); destroy_scheduler(fn_builder.scheduler); destroy_cfg(fn_builder.cfg); destroy_dict(fn_builder.emitted); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 488d6b3d9..36d8397da 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -328,7 +328,6 @@ void generate_top_level_dispatch_fn(Context* ctx) { // Build 'zero' case (exits the program) Node* zero_case_lam = case_(a, nodes(a, 0, NULL)); - BodyBuilder* zero_case_builder = begin_body_with_mem(a, get_abstraction_mem(zero_case_lam)); Node* zero_if_true_lam = case_(a, empty(a)); BodyBuilder* zero_if_case_builder = begin_body_with_mem(a, get_abstraction_mem(zero_if_true_lam)); if (ctx->config->printf_trace.god_function) { @@ -336,9 +335,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } set_abstraction_body(zero_if_true_lam, finish_body_with_join(zero_if_case_builder, l.break_jp, empty(a))); - // gen_if(zero_case_builder, empty(a), should_run, zero_if_true_lam, NULL); - // set_abstraction_body(zero_case_lam, finish_body_with_join(zero_case_builder, l.continue_jp, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); Node* zero_if_false = case_(a, empty(a)); BodyBuilder* zero_false_builder = begin_body_with_mem(a, get_abstraction_mem(zero_if_false)); if (ctx->config->printf_trace.god_function) { From c73082c29f6d5ce65220cab6bf41371dec21a5ca Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 09:10:43 +0200 Subject: [PATCH 557/693] mem2reg2: fix broken syntax --- test/opt/mem2reg2.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/opt/mem2reg2.slim b/test/opt/mem2reg2.slim index 098475494..8d81902a7 100644 --- a/test/opt/mem2reg2.slim +++ b/test/opt/mem2reg2.slim @@ -1,7 +1,7 @@ @Exported fn f varying i32(varying i32 x) { var i32 i = 0; - branch ((x > 0), t, j); + branch ((x > 0), t(), j()); cont t() { i = x; From baacb844ac783f9e9b73c638ea60ed2161413b07 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 09:11:04 +0200 Subject: [PATCH 558/693] added simplistic mem2reg opt --- src/shady/passes/CMakeLists.txt | 1 + src/shady/passes/cleanup.c | 9 ++- src/shady/passes/opt_mem2reg.c | 102 ++++++++++++++++++++++++++++++++ src/shady/passes/passes.h | 2 +- 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/shady/passes/opt_mem2reg.c diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index a48c25ac6..3aa57b10b 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -30,6 +30,7 @@ target_sources(shady PRIVATE opt_inline.c opt_restructure.c opt_demote_alloca.c + opt_mem2reg.c specialize_entry_point.c specialize_execution_model.c lower_logical_pointers.c diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 09ccc1055..a87f47462 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -100,6 +100,7 @@ bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { } OptPass opt_demote_alloca; +OptPass opt_mem2reg; RewritePass import; Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { @@ -110,11 +111,17 @@ Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { size_t r = 0; Module* m = src; do { + todo = false; debugv_print("Cleanup round %d\n", r); + if (getenv("SHADY_DUMP_CLEAN_ROUNDS")) log_module(DEBUGVV, config, m); - todo = false; todo |= opt_demote_alloca(config, &m); + + if (getenv("SHADY_DUMP_CLEAN_ROUNDS")) + log_module(DEBUGVV, config, m); + todo |= opt_mem2reg(config, &m); + if (getenv("SHADY_DUMP_CLEAN_ROUNDS")) log_module(DEBUGVV, config, m); todo |= simplify(config, &m); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c new file mode 100644 index 000000000..2d291addb --- /dev/null +++ b/src/shady/passes/opt_mem2reg.c @@ -0,0 +1,102 @@ +#include "shady/pass.h" + +#include "../ir_private.h" +#include "../type.h" +#include "../transform/ir_gen_helpers.h" + +#include "log.h" +#include "portability.h" + +typedef struct { + Rewriter rewriter; + bool* todo; +} Context; + +static const Node* get_ptr_source(const Node* ptr) { + while (true) { + switch (ptr->tag) { + case Lea_TAG: { + ptr = ptr->payload.lea.ptr; + break; + } + case PrimOp_TAG: { + PrimOp payload = ptr->payload.prim_op; + switch (payload.op) { + case reinterpret_op: + case convert_op: { + const Node* src = first(payload.operands); + if (get_unqualified_type(src->type)->tag == PtrType_TAG) { + ptr = src; + continue; + } + break; + } + default: break; + } + break; + } + default: break; + } + return ptr; + } +} + +static const Node* get_last_stored_value(const Node* ptr, const Node* mem) { + while (mem) { + switch (mem->tag) { + case Store_TAG: { + Store payload = mem->payload.store; + if (payload.ptr == ptr) + return payload.value; + } + default: break; + } + mem = get_parent_mem(mem); + } + return NULL; +} + +static const Node* process(Context* ctx, const Node* node) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + switch (node->tag) { + case Load_TAG: { + Load payload = node->payload.load; + const Node* src = get_ptr_source(payload.ptr); + if (src->tag != StackAlloc_TAG) + break; + // for now, only simplify loads from non-leaking allocas + const Node* ovalue = get_last_stored_value(payload.ptr, payload.mem); + if (ovalue) { + *ctx->todo = true; + const Node* value = rewrite_node(r, ovalue); + if (is_qualified_type_uniform(node->type)) + value = prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)); + return mem_and_value(a, (MemAndValue) { .mem = rewrite_node(r, payload.mem), .value = value }); + } + } + default: break; + } + + return recreate_node_identity(r, node); +} + +OptPass opt_mem2reg; + +bool opt_mem2reg(SHADY_UNUSED const CompilerConfig* config, Module** m) { + Module* src = *m; + IrArena* a = get_module_arena(src); + + Module* dst = NULL; + bool todo = false; + dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .todo = &todo + }; + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + assert(dst); + *m = dst; + return todo; +} diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 1e3f0bd1e..0f76a0aa2 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -105,7 +105,7 @@ RewritePass eliminate_inlineable_constants; RewritePass mark_leaf_functions; /// In addition, also inlines function calls according to heuristics RewritePass opt_inline; -RewritePass opt_mem2reg; +OptPass opt_mem2reg; RewritePass opt_stack; RewritePass opt_restructurize; From 652e134e303cb62ee11ec8a550413c625bbff612 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 09:11:22 +0200 Subject: [PATCH 559/693] fix opt_demote_alloca --- src/shady/passes/opt_demote_alloca.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 45ae347b1..d5427690b 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -47,6 +47,8 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca for (;use; use = use->next_use) { if (is_abstraction(use->user) && use->operand_class == NcParam) continue; + if (use->operand_class == NcMem) + continue; else if (use->user->tag == Load_TAG) { //if (get_pointer_type_element(ptr_type) != slice_type) // k->reinterpreted = true; From 50ac9413a50d0e319228222a002ffe00b2bbc30a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 09:45:47 +0200 Subject: [PATCH 560/693] improved fixedpoint opt --- src/shady/compile.c | 5 +---- src/shady/passes/cleanup.c | 31 +++++++++++++++++++--------- src/shady/passes/opt_demote_alloca.c | 15 +++++++------- src/shady/passes/opt_restructure.c | 2 ++ test/opt/mem2reg2.slim | 2 +- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index a7c400cb7..2e12e23c0 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -62,11 +62,9 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { add_scheduler_source(config, *pmod); } - RUN_PASS(eliminate_inlineable_constants) - //RUN_PASS(reconvergence_heuristics) + RUN_PASS(eliminate_inlineable_constants) RUN_PASS(lower_cf_instrs) - //RUN_PASS(opt_mem2reg) // run because control-flow is now normalized RUN_PASS(setup_stack_frames) if (!config->hacks.force_join_point_lifting) RUN_PASS(mark_leaf_functions) @@ -75,7 +73,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(opt_inline) RUN_PASS(lift_indirect_targets) - //RUN_PASS(opt_mem2reg) // run because we can now weaken non-leaking allocas RUN_PASS(specialize_execution_model) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index a87f47462..0d13c4fbe 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -57,6 +57,7 @@ const Node* process(Context* ctx, const Node* old) { size_t uses = count_calls(ctx->map, old); if (uses <= 1 && a->config.optimisations.inline_single_use_bbs) { log_string(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name_safe(old), uses); + *ctx->todo = true; return NULL; } break; @@ -103,29 +104,39 @@ OptPass opt_demote_alloca; OptPass opt_mem2reg; RewritePass import; -Module* cleanup(SHADY_UNUSED const CompilerConfig* config, Module* const src) { +static void apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPass pass, String pass_name) { + bool changed = pass(config, m); + *todo |= changed; + + if (getenv("SHADY_DUMP_CLEAN_ROUNDS") && changed) { + log_string(DEBUGVV, "%s changed something:\n", pass_name); + log_module(DEBUGVV, config, *m); + } +} + +#define APPLY_OPT(pass_name) apply_opt_impl(config, &todo, &m, pass_name, #pass_name); + +Module* cleanup(const CompilerConfig* config, Module* const src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); if (!aconfig.check_types) return src; bool todo; size_t r = 0; Module* m = src; + bool changed_at_all = false; do { todo = false; debugv_print("Cleanup round %d\n", r); - if (getenv("SHADY_DUMP_CLEAN_ROUNDS")) - log_module(DEBUGVV, config, m); - todo |= opt_demote_alloca(config, &m); + APPLY_OPT(opt_demote_alloca); + APPLY_OPT(opt_mem2reg); + APPLY_OPT(simplify); - if (getenv("SHADY_DUMP_CLEAN_ROUNDS")) - log_module(DEBUGVV, config, m); - todo |= opt_mem2reg(config, &m); + changed_at_all |= todo; - if (getenv("SHADY_DUMP_CLEAN_ROUNDS")) - log_module(DEBUGVV, config, m); - todo |= simplify(config, &m); r++; } while (todo); + if (changed_at_all) + debugv_print("After %d rounds of cleanup:\n", r); return import(config, m); } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index d5427690b..c8e199840 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -23,7 +23,7 @@ typedef struct Context_ { const CompilerConfig* config; Arena* arena; struct Dict* alloca_info; - bool todo; + bool* todo; } Context; typedef struct { @@ -164,14 +164,14 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t // debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); if (!k->leaks) { if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { - ctx->todo |= true; + *ctx->todo |= true; const Node* new = undef(a, (Undef) { .type = get_unqualified_type(rewrite_node(r, old->type)) }); new = mem_and_value(a, (MemAndValue) { .value = new, .mem = nmem }); k->new = new; return new; } if (!k->non_logical_use && get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { - ctx->todo |= true; + *ctx->todo |= old->tag != LocalAlloc_TAG; const Node* new = local_alloc(a, (LocalAlloc) { .type = rewrite_node(r, old_type), .mem = nmem }); k->new = new; return new; @@ -214,7 +214,7 @@ static const Node* process(Context* ctx, const Node* old) { if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { if (k.src_alloca->new == rewrite_node(r, payload.ptr)) break; - ctx->todo |= true; + *ctx->todo |= true; BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* data = gen_load(bb, k.src_alloca->new); data = gen_reinterpret_cast(bb, access_type, data); @@ -232,7 +232,7 @@ static const Node* process(Context* ctx, const Node* old) { if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { if (k.src_alloca->new == rewrite_node(r, payload.ptr)) break; - ctx->todo |= true; + *ctx->todo |= true; BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.value)); gen_store(bb, k.src_alloca->new, data); @@ -252,6 +252,7 @@ KeyHash hash_node(const Node**); bool compare_node(const Node**, const Node**); bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { + bool todo = false; Module* src = *m; IrArena* a = get_module_arena(src); Module* dst = new_module(a, get_module_name(src)); @@ -260,12 +261,12 @@ bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { .config = config, .arena = new_arena(), .alloca_info = new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), - .todo = false + .todo = &todo }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); destroy_dict(ctx.alloca_info); destroy_arena(ctx.arena); *m = dst; - return ctx.todo; + return todo; } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index ebaa3bd47..02c7725eb 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -205,6 +205,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { case Branch_TAG: { Branch payload = body->payload.branch; const Node* condition = rewrite_node(&ctx->rewriter, payload.condition); + rewrite_node(r, payload.mem); Node* true_case = case_(a, empty(a)); set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, get_abstraction_mem(true_case), make_selection_merge_case(a))); @@ -219,6 +220,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { case Switch_TAG: { Switch payload = body->payload.br_switch; const Node* switch_value = rewrite_node(r, payload.switch_value); + rewrite_node(r, payload.mem); Node* default_case = case_(a, empty(a)); set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, get_abstraction_mem(default_case), make_selection_merge_case(a))); diff --git a/test/opt/mem2reg2.slim b/test/opt/mem2reg2.slim index 8d81902a7..7b288fb60 100644 --- a/test/opt/mem2reg2.slim +++ b/test/opt/mem2reg2.slim @@ -17,7 +17,7 @@ fn f varying i32(varying i32 x) { @Exported fn g varying i32(varying i32 x) { var i32 i = 0; - branch ((x > 0), t, j); + branch ((x > 0), t(), j()); cont t() { i = x; From 2e2695318d69f4cd4bc5e00e68691244507b3025 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 10:09:37 +0200 Subject: [PATCH 561/693] cfg: deal with structured edges better --- src/shady/analysis/cfg.c | 45 ++++++++++++++++++++++++---------------- src/shady/analysis/cfg.h | 2 ++ 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index c36f61787..b74dd43d5 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -112,8 +112,9 @@ static bool in_loop(LoopTree* lt, const Node* fn, const Node* loopentry, const N } /// Adds an edge to somewhere inside a basic block -static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFEdgeType type, const Node* j) { +static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFEdgeType type, const Node* term) { assert(is_abstraction(src) && is_abstraction(dst)); + assert(term && is_terminator(term)); assert(!is_function(dst)); if (ctx->lt && !in_loop(ctx->lt, ctx->function, ctx->entry, dst)) return; @@ -121,6 +122,8 @@ static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFE return; } + const Node* j = term->tag == Jump_TAG ? term : NULL; + CFNode* src_node = get_or_enqueue(ctx, src); CFNode* dst_node = get_or_enqueue(ctx, dst); CFEdge edge = { @@ -128,13 +131,18 @@ static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFE .src = src_node, .dst = dst_node, .jump = j, + .terminator = term, }; append_list(CFEdge, src_node->succ_edges, edge); append_list(CFEdge, dst_node->pred_edges, edge); } -static void add_structural_dominance_edge(CfgBuildContext* ctx, CFNode* parent, const Node* dst, CFEdgeType type) { - add_edge(ctx, parent->node, dst, type, NULL); +static void add_structural_edge(CfgBuildContext* ctx, CFNode* parent, const Node* dst, CFEdgeType type, const Node* term) { + add_edge(ctx, parent->node, dst, type, term); +} + +static void add_structural_dominance_edge(CfgBuildContext* ctx, CFNode* parent, const Node* dst, CFEdgeType type, const Node* term) { + add_edge(ctx, parent->node, dst, type, term); insert_set_get_result(const Node*, parent->structurally_dominates, dst); } @@ -174,60 +182,60 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { case Join_TAG: { const Node** dst = find_value_dict(const Node*, const Node*, ctx->join_point_values, terminator->payload.join.join_point); if (dst) - add_edge(ctx, node->node, *dst, StructuredLeaveBodyEdge, NULL); + add_edge(ctx, node->node, *dst, StructuredLeaveBodyEdge, terminator); return; } case If_TAG: { if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); CfgBuildContext if_ctx = *ctx; if_ctx.selection_construct_tail = get_structured_construct_tail(terminator); - add_structural_dominance_edge(&if_ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge); + add_structural_edge(&if_ctx, node, terminator->payload.if_instr.if_true, StructuredEnterBodyEdge, terminator); if (terminator->payload.if_instr.if_false) - add_structural_dominance_edge(&if_ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge); + add_structural_edge(&if_ctx, node, terminator->payload.if_instr.if_false, StructuredEnterBodyEdge, terminator); else - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredLeaveBodyEdge); + add_structural_edge(ctx, node, get_structured_construct_tail(terminator), StructuredLeaveBodyEdge, terminator); return; } case Match_TAG: { if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); CfgBuildContext match_ctx = *ctx; match_ctx.selection_construct_tail = get_structured_construct_tail(terminator); for (size_t i = 0; i < terminator->payload.match_instr.cases.count; i++) - add_structural_dominance_edge(&match_ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge); - add_structural_dominance_edge(&match_ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge); + add_structural_edge(&match_ctx, node, terminator->payload.match_instr.cases.nodes[i], StructuredEnterBodyEdge, terminator); + add_structural_edge(&match_ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge, terminator); return; } case Loop_TAG: { if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); CfgBuildContext loop_ctx = *ctx; loop_ctx.loop_construct_head = terminator->payload.loop_instr.body; loop_ctx.loop_construct_tail = get_structured_construct_tail(terminator); - add_structural_dominance_edge(&loop_ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge); + add_structural_edge(&loop_ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge, terminator); return; } case Control_TAG: { const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); //CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); const Node* tail = get_structured_construct_tail(terminator); insert_dict(const Node*, const Node*, ctx->join_point_values, param, tail); - add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge); + add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge, terminator); if (ctx->include_structured_tails) - add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge); + add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); return; } case MergeSelection_TAG: { assert(ctx->selection_construct_tail); - add_structural_dominance_edge(ctx, node, ctx->selection_construct_tail, StructuredLeaveBodyEdge); + add_structural_edge(ctx, node, ctx->selection_construct_tail, StructuredLeaveBodyEdge, terminator); return; } case MergeContinue_TAG:{ assert(ctx->loop_construct_head); - add_structural_dominance_edge(ctx, node, ctx->loop_construct_head, StructuredLoopContinue); + add_structural_edge(ctx, node, ctx->loop_construct_head, StructuredLoopContinue, terminator); return; } case MergeBreak_TAG: { assert(ctx->loop_construct_tail); - add_structural_dominance_edge(ctx, node, ctx->loop_construct_tail, StructuredLeaveBodyEdge); + add_structural_edge(ctx, node, ctx->loop_construct_tail, StructuredLeaveBodyEdge, terminator); return; } case TailCall_TAG: @@ -518,6 +526,7 @@ void compute_domtree(CFG* cfg) { CFEdge e = read_list(CFEdge, n->pred_edges)[j]; if (e.type == StructuredTailEdge) { structured_idom = n->structured_idom = e.src; + n->structured_idom_edge = e; continue; } } diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index fb62faf36..f16132c70 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -22,6 +22,7 @@ typedef struct { CFNode* src; CFNode* dst; const Node* jump; + const Node* terminator; } CFEdge; struct CFNode_ { @@ -47,6 +48,7 @@ struct CFNode_ { // set by compute_domtree CFNode* idom; CFNode* structured_idom; + CFEdge structured_idom_edge; /** @brief All Nodes directly dominated by this CFNode. * From 80fe794a23b5af483c1af81aad0e51b9264e224e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 10:09:59 +0200 Subject: [PATCH 562/693] opt_demote_alloca: stronger against dead stores --- src/shady/passes/opt_demote_alloca.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index c8e199840..8b43b78e5 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -28,8 +28,12 @@ typedef struct Context_ { typedef struct { const Type* type; + /// Set when the alloca is used in a way the analysis cannot follow + /// Allocation must be left alone in such cases! bool leaks; + /// Set when the alloca is read from. bool read_from; + /// Set when the alloca is used in a manner forbidden by logical pointer rules bool non_logical_use; const Node* new; } AllocaInfo; @@ -66,36 +70,18 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca switch (payload.op) { case reinterpret_op: { k->non_logical_use = true; + visit_ptr_uses(use->user, slice_type, k, map); continue; } case convert_op: { if (first(payload.type_arguments)->tag == PtrType_TAG) { k->non_logical_use = true; + visit_ptr_uses(use->user, slice_type, k, map); } else { k->leaks = true; } continue; } - /*case reinterpret_op: { - debugvv_print("demote_alloca leak analysis: following reinterpret instr: "); - log_node(DEBUGVV, use->user); - debugvv_print(".\n"); - visit_ptr_uses(use->user, slice_type, k, map); - continue; - } - case convert_op: { - if (first(payload.type_arguments)->tag == PtrType_TAG) { - // this is a ptr-ptr conversion, which means it's a Generic-non generic conversion - // these are fine, just track them - debugvv_print("demote_alloca leak analysis: following conversion instr: "); - log_node(DEBUGVV, use->user); - debugvv_print(".\n"); - visit_ptr_uses(use->user, slice_type, k, map); - continue; - } - k->leaks = true; - continue; - }*/ default: break; } if (has_primop_got_side_effects(payload.op)) @@ -163,7 +149,7 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t // log_node(DEBUGV, old); // debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); if (!k->leaks) { - if (!k->read_from && !k->non_logical_use/* this should include killing dead stores! */) { + if (!k->read_from/* this should include killing dead stores! */) { *ctx->todo |= true; const Node* new = undef(a, (Undef) { .type = get_unqualified_type(rewrite_node(r, old->type)) }); new = mem_and_value(a, (MemAndValue) { .value = new, .mem = nmem }); From bda535c2d45eda4990eaabf262834e91102ee9b9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 10:10:20 +0200 Subject: [PATCH 563/693] mem2reg: allow searching in dominators --- src/shady/passes/opt_mem2reg.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 2d291addb..4446a84de 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -1,14 +1,18 @@ +#include + #include "shady/pass.h" #include "../ir_private.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" +#include "../analysis/cfg.h" #include "log.h" #include "portability.h" typedef struct { Rewriter rewriter; + CFG* cfg; bool* todo; } Context; @@ -41,9 +45,18 @@ static const Node* get_ptr_source(const Node* ptr) { } } -static const Node* get_last_stored_value(const Node* ptr, const Node* mem) { +static const Node* get_last_stored_value(Context* ctx, const Node* ptr, const Node* mem) { while (mem) { switch (mem->tag) { + case AbsMem_TAG: { + const Node* abs = mem->payload.abs_mem.abs; + CFNode* n = cfg_lookup(ctx->cfg, abs); + if (entries_count_list(n->pred_edges) == 1) { + CFEdge e = read_list(CFEdge, n->pred_edges)[0]; + mem = get_terminator_mem(e.terminator); + continue; + } + } case Store_TAG: { Store payload = mem->payload.store; if (payload.ptr == ptr) @@ -60,13 +73,21 @@ static const Node* process(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; switch (node->tag) { + case Function_TAG: { + Node* new = recreate_decl_header_identity(r, node); + Context fun_ctx = *ctx; + fun_ctx.cfg = build_fn_cfg(node); + recreate_decl_body_identity(&fun_ctx.rewriter, node, new); + destroy_cfg(fun_ctx.cfg); + return new; + } case Load_TAG: { Load payload = node->payload.load; const Node* src = get_ptr_source(payload.ptr); if (src->tag != StackAlloc_TAG) break; // for now, only simplify loads from non-leaking allocas - const Node* ovalue = get_last_stored_value(payload.ptr, payload.mem); + const Node* ovalue = get_last_stored_value(ctx, payload.ptr, payload.mem); if (ovalue) { *ctx->todo = true; const Node* value = rewrite_node(r, ovalue); From a3980b537be08d5252e51a01cae0f04f2941b1fb Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 14:20:57 +0200 Subject: [PATCH 564/693] remove redudant search_processed calls from all passes --- src/backend/spirv/spirv_map_entrypoint_args.c | 4 ---- src/frontend/slim/bind.c | 5 ----- src/frontend/slim/infer.c | 11 ----------- src/frontend/slim/normalize.c | 2 -- src/shady/passes/eliminate_constants.c | 3 --- src/shady/passes/lift_indirect_targets.c | 3 --- src/shady/passes/lower_alloca.c | 3 --- src/shady/passes/lower_callf.c | 2 -- src/shady/passes/lower_cf_instrs.c | 6 ------ src/shady/passes/lower_decay_ptrs.c | 3 --- src/shady/passes/lower_entrypoint_args.c | 4 ---- src/shady/passes/lower_generic_ptrs.c | 3 --- src/shady/passes/lower_int64.c | 3 --- src/shady/passes/lower_lea.c | 3 --- src/shady/passes/lower_logical_pointers.c | 3 --- src/shady/passes/lower_mask.c | 3 --- src/shady/passes/lower_memcpy.c | 3 --- src/shady/passes/lower_memory_layout.c | 3 --- src/shady/passes/lower_physical_ptrs.c | 3 --- src/shady/passes/lower_stack.c | 3 --- src/shady/passes/lower_subgroup_ops.c | 4 ---- src/shady/passes/lower_tailcalls.c | 3 --- src/shady/passes/mark_leaf_functions.c | 4 ---- src/shady/passes/normalize_builtins.c | 3 --- src/shady/passes/opt_demote_alloca.c | 3 --- src/shady/passes/opt_inline.c | 6 ------ src/shady/passes/opt_restructure.c | 4 ---- src/shady/passes/setup_stack_frames.c | 3 --- src/shady/passes/specialize_entry_point.c | 4 ---- src/shady/passes/specialize_execution_model.c | 4 ---- 30 files changed, 111 deletions(-) diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index 7e6f52532..4ff784fab 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -30,10 +30,6 @@ static const Node* rewrite_args_type(Rewriter* rewriter, const Node* old_type) { } static const Node* process(Context* ctx, const Node* node) { - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - switch (node->tag) { case GlobalVariable_TAG: if (lookup_annotation(node, "EntryPointArgs")) { diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 5daa66020..36e14cf93 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -270,11 +270,6 @@ static bool is_used_as_value(Context* ctx, const Node* node) { static const Node* bind_node(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; - if (node == NULL) - return NULL; - - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; // in case the node is an l-value, we load it // const Node* lhs = get_node_address_safe(ctx, node); diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index b5ac1a186..07206ef8a 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -85,10 +85,6 @@ static const Node* infer_type(Context* ctx, const Type* type) { static const Node* infer_decl(Context* ctx, const Node* node) { assert(is_declaration(node)); - const Node* already_done = search_processed(&ctx->rewriter, node); - if (already_done) - return already_done; - if (lookup_annotation(node, "SkipOnInfer")) return NULL; @@ -591,13 +587,6 @@ static const Node* process(Context* src_ctx, const Node* node) { IrArena* a = ctx.rewriter.dst_arena; - const Node* found = search_processed(&src_ctx->rewriter, node); - if (found) { - //if (expect) - // assert(is_subtype(expect, found->type)); - return found; - } - if (is_type(node)) { assert(expected_type == NULL); return infer_type(&ctx, node); diff --git a/src/frontend/slim/normalize.c b/src/frontend/slim/normalize.c index 490971d2e..e9f5b3c57 100644 --- a/src/frontend/slim/normalize.c +++ b/src/frontend/slim/normalize.c @@ -87,8 +87,6 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str } static const Node* process_node(Context* ctx, const Node* node) { - if (node == NULL) return NULL; - const Node* already_done = search_processed(&ctx->rewriter, node); if (already_done) return already_done; diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 80737e945..247c27939 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -10,9 +10,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 805d9da8a..a527ed9bb 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -156,9 +156,6 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { } static const Node* process_node(Context* ctx, const Node* node) { - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 0677e2389..b321e7375 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -73,9 +73,6 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); static const Node* process(Context* ctx, const Node* node) { - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; Module* m = r->dst_module; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 0883204fa..ce224f6b7 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -19,8 +19,6 @@ typedef struct Context_ { } Context; static const Node* lower_callf_process(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; IrArena* a = ctx->rewriter.dst_arena; Module* m = ctx->rewriter.dst_module; Rewriter* r = &ctx->rewriter; diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 34e19f1ff..765d1dff8 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -18,13 +18,7 @@ typedef struct Context_ { CFG* cfg; } Context; -static const Node* process_node(Context* ctx, const Node* node); - static const Node* process_node(Context* ctx, const Node* node) { - const Node* already_done = search_processed(&ctx->rewriter, node); - if (already_done) - return already_done; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index fcb46f4ba..6abe1040f 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -13,9 +13,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - IrArena* arena = ctx->rewriter.dst_arena; switch (node->tag) { diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 74826b142..776cb91b7 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -75,10 +75,6 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const } static const Node* process(Context* ctx, const Node* node) { - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - switch (node->tag) { case Function_TAG: if (lookup_annotation(node, "EntryPoint") && node->payload.fun.params.count > 0) { diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index f303fee5d..1a8f2857c 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -178,9 +178,6 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo } static const Node* process(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; Module* m = ctx->rewriter.dst_module; diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 05f9c06f3..17dbeee9e 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -33,9 +33,6 @@ static void extract_low_hi_halves_list(BodyBuilder* bb, Nodes src, const Node** } static const Node* process(Context* ctx, const Node* node) { - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 8ea6594c8..593d6012d 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -99,9 +99,6 @@ static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* p } static const Node* process(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index b7c24cd8a..6d88a5fa0 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -42,9 +42,6 @@ static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node } static const Node* process(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index beb1f48e6..198a84f30 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -14,9 +14,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 3da7d3b74..3295cc7a7 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -16,9 +16,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; Module* m = r->dst_module; diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 77f0d5a54..2eced9181 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -13,9 +13,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; switch (old->tag) { diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 9e1b64b5a..70e2f40b3 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -291,9 +291,6 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un } static const Node* process_node(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 885036a8d..4834f115d 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -90,9 +90,6 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { } static const Node* process_node(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index c5c26ee07..3ccf7c1e1 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -128,10 +128,6 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod } static const Node* process(Context* ctx, const Node* node) { - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (node->tag) { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 36d8397da..6b4f445cc 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -92,9 +92,6 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { } static const Node* process(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; switch (old->tag) { diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index 07a57f8a9..eb917d6ed 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -93,10 +93,6 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { static const Node* process(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - switch (node->tag) { case Function_TAG: { Context fn_ctx = *ctx; diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 7eec9ef0a..1eed369f2 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -52,9 +52,6 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { } static const Node* process(Context* ctx, const Node* node) { - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 8b43b78e5..7c29c9f90 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -169,9 +169,6 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t } static const Node* process(Context* ctx, const Node* old) { - const Node* found = search_processed(&ctx->rewriter, old); - if (found) return found; - Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 52c5b0756..9bea6bf69 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -130,12 +130,6 @@ static const Node* inline_call(Context* ctx, const Node* ocallee, const Node* nm } static const Node* process(Context* ctx, const Node* node) { - if (!node) - return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) - return found; - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; assert(a != node->arena); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 02c7725eb..7f45ab4f5 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -322,13 +322,9 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { static const Node* process(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; - if (!node) return NULL; assert(a != node->arena); assert(node->arena == ctx->rewriter.src_arena); - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - if (is_declaration(node)) { String name = get_declaration_name(node); Nodes decls = get_module_declarations(ctx->rewriter.dst_module); diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index afe056f8f..d94c17af7 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -21,9 +21,6 @@ typedef struct Context_ { } Context; static const Node* process(Context* ctx, const Node* node) { - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (node->tag) { diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 839e96310..3fdf0106e 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -15,10 +15,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index d88623508..f72dee56e 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -15,10 +15,6 @@ typedef struct { } Context; static const Node* process(Context* ctx, const Node* node) { - if (!node) return NULL; - const Node* found = search_processed(&ctx->rewriter, node); - if (found) return found; - IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { case Constant_TAG: { From a96244e76fe4c3534f29a795848a6dfb03efc734 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 14:30:01 +0200 Subject: [PATCH 565/693] changed signature of search_processed --- src/backend/spirv/emit_spv_type.c | 3 --- src/frontend/slim/normalize.c | 4 +-- src/shady/passes/lower_generic_globals.c | 4 +-- src/shady/passes/reconvergence_heuristics.c | 8 +++--- src/shady/rewrite.c | 29 ++++++++++++--------- src/shady/rewrite.h | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 5f4da5a87..fdb63fe80 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -40,9 +40,6 @@ SpvStorageClass spv_emit_addr_space(Emitter* emitter, AddressSpace address_space } static const Node* rewrite_normalize(Rewriter* rewriter, const Node* node) { - const Node* found = search_processed(rewriter, node); - if (found) return found; - if (!is_type(node)) { register_processed(rewriter, node, node); return node; diff --git a/src/frontend/slim/normalize.c b/src/frontend/slim/normalize.c index e9f5b3c57..708164273 100644 --- a/src/frontend/slim/normalize.c +++ b/src/frontend/slim/normalize.c @@ -87,9 +87,9 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str } static const Node* process_node(Context* ctx, const Node* node) { - const Node* already_done = search_processed(&ctx->rewriter, node); + const Node** already_done = search_processed(&ctx->rewriter, node); if (already_done) - return already_done; + return *already_done; Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index fb4697e5b..7f5b0af5d 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -18,8 +18,8 @@ static const Node* process(Context* ctx, const Node* node) { case RefDecl_TAG: { // make sure we rewrite the decl first, and then look if it rewrote the ref to it! rewrite_node(r, node->payload.ref_decl.decl); - const Node* f = search_processed(r, node); - if (f) return f; + const Node** f = search_processed(r, node); + if (f) return *f; break; } case GlobalVariable_TAG: { diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 4c1c06493..bbaa3bd3b 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -166,13 +166,13 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(const Node*, cached_exits, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; - cached_exits[i] = search_processed(rewriter, exiting_node->node); + cached_exits[i] = *search_processed(rewriter, exiting_node->node); if (cached_exits[i]) remove_dict(const Node*, rewriter->map, exiting_node->node); register_processed(rewriter, exiting_node->node, exit_wrappers[i]); } // ditto for the loop entry and the continue wrapper - const Node* cached_entry = search_processed(rewriter, node); + const Node* cached_entry = *search_processed(rewriter, node); if (cached_entry) remove_dict(const Node*, rewriter->map, node); register_processed(rewriter, node, continue_wrapper); @@ -415,11 +415,11 @@ static const Node* process_node(Context* ctx, const Node* node) { .mem = get_abstraction_mem(pre_join), })); - const Node* cached = search_processed(r, post_dominator); + const Node* cached = *search_processed(r, post_dominator); if (cached) remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); for (size_t i = 0; i < old_params.count; i++) { - assert(!search_processed(r, old_params.nodes[i])); + assert(!*search_processed(r, old_params.nodes[i])); } register_processed(r, post_dominator, pre_join); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 34969aa3d..315aeea13 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -72,12 +72,12 @@ const Node* rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNo assert(rewriter->rewrite_fn); if (!node) return NULL; - const Node* found = NULL; + const Node** found = NULL; if (rewriter->config.search_map) { found = search_processed(rewriter, node); } if (found) - return found; + return *found; const Node* rewritten = fn(rewriter, node); // assert(rewriter->dst_arena == rewritten->arena); @@ -110,12 +110,12 @@ const Node* rewrite_op_with_fn(Rewriter* rewriter, NodeClass class, String op_na assert(rewriter->rewrite_op_fn); if (!node) return NULL; - const Node* found = NULL; + const Node** found = NULL; if (rewriter->config.search_map) { found = search_processed(rewriter, node); } if (found) - return found; + return *found; const Node* rewritten = fn(rewriter, class, op_name, node); if (is_declaration(node)) @@ -157,17 +157,17 @@ static Nodes rewrite_ops_helper(Rewriter* rewriter, NodeClass class, String op_n return rewrite_nodes_with_fn(rewriter, old_nodes, rewriter->rewrite_fn); } -static const Node* search_processed_(const Rewriter* ctx, const Node* old, bool deep) { +static const Node** search_processed_(const Rewriter* ctx, const Node* old, bool deep) { if (is_declaration(old)) { const Node** found = find_value_dict(const Node*, const Node*, ctx->decls_map, old); - return found ? *found : NULL; + return found ? found : NULL; } while (ctx) { assert(ctx->map && "this rewriter has no processed cache"); const Node** found = find_value_dict(const Node*, const Node*, ctx->map, old); if (found) - return *found; + return found; if (deep) ctx = ctx->parent; else @@ -176,34 +176,37 @@ static const Node* search_processed_(const Rewriter* ctx, const Node* old, bool return NULL; } -const Node* search_processed(const Rewriter* ctx, const Node* old) { +const Node** search_processed(const Rewriter* ctx, const Node* old) { return search_processed_(ctx, old, true); } const Node* find_processed(const Rewriter* ctx, const Node* old) { - const Node* found = search_processed(ctx, old); + const Node** found = search_processed(ctx, old); assert(found && "this node was supposed to have been processed before"); - return found; + return *found; } void register_processed(Rewriter* ctx, const Node* old, const Node* new) { assert(old->arena == ctx->src_arena); assert(new ? new->arena == ctx->dst_arena : true); #ifndef NDEBUG - const Node* found = search_processed_(ctx, old, false); + const Node** found = search_processed_(ctx, old, false); if (found) { // this can happen and is typically harmless // ie: when rewriting a jump into a loop, the outer jump cannot be finished until the loop body is rebuilt // and therefore the back-edge jump inside the loop will be rebuilt while the outer one isn't done. // as long as there is no conflict, this is correct, but this might hide perf hazards if we fail to cache things - if (found == new) + if (*found == new) return; error_print("Trying to replace "); log_node(ERROR, old); error_print(" with "); log_node(ERROR, new); error_print(" but there was already "); - log_node(ERROR, found); + if (*found) + log_node(ERROR, *found); + else + log_string(ERROR, "NULL"); error_print("\n"); error("The same node got processed twice !"); } diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index 1dd32d64b..9240c5074 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -66,7 +66,7 @@ Node* clone_bb_head(Rewriter*, const Node* bb); //const Node* rebind_let(Rewriter*, const Node* ninstruction, const Node* ocase); /// Looks up if the node was already processed -const Node* search_processed(const Rewriter*, const Node*); +const Node** search_processed(const Rewriter*, const Node*); /// Same as search_processed but asserts if it fails to find a mapping const Node* find_processed(const Rewriter*, const Node*); void register_processed(Rewriter*, const Node*, const Node*); From 4ad3d1efd333506b5ae59ef9a6a79630ed167825 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 14:36:09 +0200 Subject: [PATCH 566/693] added opt to eliminate trivial control blocks --- src/shady/analysis/leak.c | 3 ++- src/shady/passes/cleanup.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/shady/analysis/leak.c b/src/shady/analysis/leak.c index 179b0e007..762e2873b 100644 --- a/src/shady/analysis/leak.c +++ b/src/shady/analysis/leak.c @@ -43,7 +43,8 @@ bool is_control_static(const UsesMap* map, const Node* control) { } const Node* get_control_for_jp(const UsesMap* map, const Node* jp) { - assert(is_param(jp)); + if (!is_param(jp)) + return NULL; const Node* abs = jp->payload.param.abs; assert(is_abstraction(abs)); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 0d13c4fbe..d24bc2827 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -1,6 +1,7 @@ #include "shady/pass.h" #include "../analysis/uses.h" +#include "../analysis/leak.h" #include "../ir_private.h" #include "../type.h" @@ -74,6 +75,36 @@ const Node* process(Context* ctx, const Node* old) { } break; } + case Control_TAG: { + Control payload = old->payload.control; + if (is_control_static(ctx->map, old)) { + const Node* control_inside = payload.inside; + const Node* term = get_abstraction_body(control_inside); + if (term->tag == Join_TAG) { + Join payload_join = term->payload.join; + if (payload_join.join_point == first(get_abstraction_params(control_inside))) { + // if we immediately consume the join point and it's never leaked, this control block does nothing and can be eliminated + register_processed(r, get_abstraction_mem(control_inside), rewrite_node(r, payload.mem)); + register_processed(r, control_inside, NULL); + *ctx->todo = true; + return rewrite_node(r, term); + } + } + } + break; + } + case Join_TAG: { + Join payload = old->payload.join; + const Node* control = get_control_for_jp(ctx->map, payload.join_point); + if (control) { + Control old_control_payload = control->payload.control; + // there was a control but now there is not anymore - jump to the tail! + if (rewrite_node(r, old_control_payload.inside) == NULL) { + return jump_helper(a, rewrite_node(r, old_control_payload.tail), rewrite_nodes(r, payload.args), rewrite_node(r, payload.mem)); + } + } + break; + } case Load_TAG: { if (!is_used_as_value(ctx->map, old)) return rewrite_node(r, old->payload.load.mem); From 7e8d5d9976d2dbdec3045ee48b5b96fbff1bdae1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 2 Sep 2024 17:17:13 +0200 Subject: [PATCH 567/693] fix broken multi-word int serdes --- src/shady/passes/lower_physical_ptrs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 70e2f40b3..c1405ea92 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -82,7 +82,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { - const Node* word = gen_load(bb, gen_lea(bb, arr, zero, singleton(base_offset))); + const Node* word = gen_load(bb, gen_lea(bb, arr, zero, singleton(offset))); word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded word = first(gen_primop(bb, lshift_op, empty(a), mk_nodes(a, word, shift))); // shift it acc = gen_primop_e(bb, or_op, empty(a), mk_nodes(a, acc, word)); @@ -189,7 +189,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* word = value; word = first(gen_primop(bb, rshift_logical_op, empty(a), mk_nodes(a, word, shift))); // shift it word = gen_conversion(bb, int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }), word); // widen/truncate the word we want to store - gen_store(bb, gen_lea(bb, arr, zero, singleton(base_offset)), word); + gen_store(bb, gen_lea(bb, arr, zero, singleton(offset)), word); offset = first(gen_primop(bb, add_op, empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); shift = first(gen_primop(bb, add_op, empty(a), mk_nodes(a, shift, word_bitwidth))); From 5beef4f8a134bdf5aa6041a52a337af33cf9cd66 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 3 Sep 2024 11:37:08 +0200 Subject: [PATCH 568/693] split Lea in PtrArrayElementOffset and PtrCompositeElement --- include/shady/ir.h | 1 + include/shady/primops.json | 13 ++- src/backend/c/emit_c_value.c | 125 +++++++++++--------- src/backend/spirv/emit_spv_value.c | 27 ++--- src/frontend/llvm/l2s_annotations.c | 4 +- src/frontend/llvm/l2s_instr.c | 4 +- src/frontend/slim/bind.c | 2 +- src/frontend/slim/infer.c | 12 -- src/frontend/spirv/s2s.c | 6 +- src/shady/compile.c | 2 +- src/shady/constructors.c | 14 +++ src/shady/fold.c | 47 +++++--- src/shady/node.c | 20 ++-- src/shady/passes/lower_alloca.c | 4 +- src/shady/passes/lower_lea.c | 133 +++++++++++++--------- src/shady/passes/lower_logical_pointers.c | 16 ++- src/shady/passes/normalize_builtins.c | 6 +- src/shady/passes/opt_demote_alloca.c | 4 +- src/shady/passes/opt_mem2reg.c | 8 +- src/shady/transform/ir_gen_helpers.c | 2 +- src/shady/type.c | 22 +++- src/shady/type.h | 4 +- src/shady/type_helpers.c | 6 +- 23 files changed, 283 insertions(+), 199 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index e0a23eadd..82fc54bbb 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -263,6 +263,7 @@ const Node* annotation_value_helper(IrArena* a, String n, const Node* v); // instructions const Node* prim_op_helper(IrArena*, Op, Nodes, Nodes); +const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); const Node* compound_instruction(IrArena* arena, Nodes instructions, Nodes results); // terminators diff --git a/include/shady/primops.json b/include/shady/primops.json index bd0529e64..177b04418 100644 --- a/include/shady/primops.json +++ b/include/shady/primops.json @@ -272,12 +272,19 @@ ] }, { - "name": "Lea", + "name": "PtrCompositeElement", "class": ["instruction", "value"], "ops": [ { "name": "ptr", "class": "value" }, - { "name": "offset", "class": "value" }, - { "name": "indices", "class": "value", "list": true } + { "name": "index", "class": "value" } + ] + }, + { + "name": "PtrArrayElementOffset", + "class": ["instruction", "value"], + "ops": [ + { "name": "ptr", "class": "value" }, + { "name": "offset", "class": "value" } ] }, { diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 8c1caa6f1..e4bf99290 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -788,7 +788,73 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* return called; } -static CTerm emit_lea(Emitter* emitter, FnEmitter* fn, Printer* p, Lea lea) { +static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer* p, PtrCompositeElement lea) { + IrArena* arena = emitter->arena; + CTerm acc = c_emit_value(emitter, fn, lea.ptr); + + const Type* src_qtype = lea.ptr->type; + bool uniform = is_qualified_type_uniform(src_qtype); + const Type* curr_ptr_type = get_unqualified_type(src_qtype); + assert(curr_ptr_type->tag == PtrType_TAG); + + const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); + const Node* selector = lea.index; + uniform &= is_qualified_type_uniform(selector->type); + switch (is_type(pointee_type)) { + case ArrType_TAG: { + CTerm index = c_emit_value(emitter, fn, selector); + acc = term_from_cvar(index_into_array(emitter, pointee_type, acc, index)); + curr_ptr_type = ptr_type(arena, (PtrType) { + .pointed_type = pointee_type->payload.arr_type.element_type, + .address_space = curr_ptr_type->payload.ptr_type.address_space + }); + break; + } + case TypeDeclRef_TAG: { + pointee_type = get_nominal_type_body(pointee_type); + SHADY_FALLTHROUGH + } + case RecordType_TAG: { + // yet another ISPC bug and workaround + // ISPC cannot deal with subscripting if you've done pointer arithmetic (!) inside the expression + // so hum we just need to introduce a temporary variable to hold the pointer expression so far, and go again from there + // See https://github.com/ispc/ispc/issues/2496 + if (emitter->config.dialect == CDialect_ISPC) { + String interm = unique_name(arena, "lea_intermediary_ptr_value"); + print(p, "\n%s = %s;", c_emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); + acc = term_from_cvalue(interm); + } + + assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a record need to be constant"); + size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); + String field_name = c_get_record_field_name(pointee_type, static_index); + acc = term_from_cvar(format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); + curr_ptr_type = ptr_type(arena, (PtrType) { + .pointed_type = pointee_type->payload.record_type.members.nodes[static_index], + .address_space = curr_ptr_type->payload.ptr_type.address_space + }); + break; + } + case Type_PackType_TAG: { + size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); + String suffixes = "xyzw"; + acc = term_from_cvar(format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); + curr_ptr_type = ptr_type(arena, (PtrType) { + .pointed_type = pointee_type->payload.pack_type.element_type, + .address_space = curr_ptr_type->payload.ptr_type.address_space + }); + break; + } + default: error("lea can't work on this"); + } + + // if (emitter->config.dialect == CDialect_ISPC) + // acc = c_bind_intermediary_result(emitter, p, curr_ptr_type, acc); + + return acc; +} + +static CTerm emit_ptr_array_element_offset(Emitter* emitter, FnEmitter* fn, Printer* p, PtrArrayElementOffset lea) { IrArena* arena = emitter->arena; CTerm acc = c_emit_value(emitter, fn, lea.ptr); @@ -808,60 +874,6 @@ static CTerm emit_lea(Emitter* emitter, FnEmitter* fn, Printer* p, Lea lea) { uniform &= is_qualified_type_uniform(lea.offset->type); } - //t = t->payload.ptr_type.pointed_type; - for (size_t i = 0; i < lea.indices.count; i++) { - const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); - const Node* selector = lea.indices.nodes[i]; - uniform &= is_qualified_type_uniform(selector->type); - switch (is_type(pointee_type)) { - case ArrType_TAG: { - CTerm index = c_emit_value(emitter, fn, selector); - acc = term_from_cvar(index_into_array(emitter, pointee_type, acc, index)); - curr_ptr_type = ptr_type(arena, (PtrType) { - .pointed_type = pointee_type->payload.arr_type.element_type, - .address_space = curr_ptr_type->payload.ptr_type.address_space - }); - break; - } - case TypeDeclRef_TAG: { - pointee_type = get_nominal_type_body(pointee_type); - SHADY_FALLTHROUGH - } - case RecordType_TAG: { - // yet another ISPC bug and workaround - // ISPC cannot deal with subscripting if you've done pointer arithmetic (!) inside the expression - // so hum we just need to introduce a temporary variable to hold the pointer expression so far, and go again from there - // See https://github.com/ispc/ispc/issues/2496 - if (emitter->config.dialect == CDialect_ISPC) { - String interm = unique_name(arena, "lea_intermediary_ptr_value"); - print(p, "\n%s = %s;", c_emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); - acc = term_from_cvalue(interm); - } - - assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a record need to be constant"); - size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); - String field_name = c_get_record_field_name(pointee_type, static_index); - acc = term_from_cvar(format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); - curr_ptr_type = ptr_type(arena, (PtrType) { - .pointed_type = pointee_type->payload.record_type.members.nodes[static_index], - .address_space = curr_ptr_type->payload.ptr_type.address_space - }); - break; - } - case Type_PackType_TAG: { - size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); - String suffixes = "xyzw"; - acc = term_from_cvar(format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); - curr_ptr_type = ptr_type(arena, (PtrType) { - .pointed_type = pointee_type->payload.pack_type.element_type, - .address_space = curr_ptr_type->payload.ptr_type.address_space - }); - break; - } - default: error("lea can't work on this"); - } - } - if (emitter->config.dialect == CDialect_ISPC) acc = c_bind_intermediary_result(emitter, p, curr_ptr_type, acc); @@ -903,7 +915,8 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); return empty_term(); case Instruction_StackAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); case Instruction_LocalAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); - case Instruction_Lea_TAG: return emit_lea(emitter, fn, p, instruction->payload.lea); + case Instruction_PtrArrayElementOffset_TAG: return emit_ptr_array_element_offset(emitter, fn, p, instruction->payload.ptr_array_element_offset); + case Instruction_PtrCompositeElement_TAG: return emit_ptr_composite_element(emitter, fn, p, instruction->payload.ptr_composite_element); case Instruction_Load_TAG: { Load payload = instruction->payload.load; c_emit_mem(emitter, fn, payload.mem); diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 67f693153..26d1a58c1 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -427,22 +427,19 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui spvb_store(bb_builder, eval, eptr, operands_count, operands); return 0; } - case Lea_TAG: { - Lea payload = instruction->payload.lea; + case Instruction_PtrCompositeElement_TAG: { + PtrCompositeElement payload = instruction->payload.ptr_composite_element; SpvId base = spv_emit_value(emitter, fn_builder, payload.ptr); - - LARRAY(SpvId, indices, payload.indices.count); - for (size_t i = 0; i < payload.indices.count; i++) - indices[i] = payload.indices.nodes[i] ? spv_emit_value(emitter, fn_builder, payload.indices.nodes[i]) : 0; - - const IntLiteral* known_offset = resolve_to_int_literal(payload.offset); - if (known_offset && known_offset->value == 0) { - const Type* target_type = instruction->type; - return spvb_access_chain(bb_builder, spv_emit_type(emitter, target_type), base, payload.indices.count, indices); - } else { - const Type* target_type = instruction->type; - return spvb_ptr_access_chain(bb_builder, spv_emit_type(emitter, target_type), base, spv_emit_value(emitter, fn_builder, payload.offset), payload.indices.count, indices); - } + const Type* target_type = instruction->type; + SpvId index = spv_emit_value(emitter, fn_builder, payload.index); + return spvb_access_chain(bb_builder, spv_emit_type(emitter, target_type), base, 1, &index); + } + case Instruction_PtrArrayElementOffset_TAG: { + PtrArrayElementOffset payload = instruction->payload.ptr_array_element_offset; + SpvId base = spv_emit_value(emitter, fn_builder, payload.ptr); + const Type* target_type = instruction->type; + SpvId offset = spv_emit_value(emitter, fn_builder, payload.offset); + return spvb_ptr_access_chain(bb_builder, spv_emit_type(emitter, target_type), base, offset, 0, NULL); } case Instruction_DebugPrintf_TAG: { DebugPrintf payload = instruction->payload.debug_printf; diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 7397219a3..34ed653e9 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -42,8 +42,8 @@ static const Node* look_past_stuff(const Node* thing) { default: assert(false); } } - if (thing->tag == Lea_TAG) { - thing = thing->payload.lea.ptr; + if (thing->tag == PtrCompositeElement_TAG) { + thing = thing->payload.ptr_composite_element.ptr; } return thing; } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 5128df0db..77a8c147a 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -269,13 +269,13 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); } ops = change_node_at_index(a, ops, 0, ptr); - const Node* r = lea(a, (Lea) { .ptr = ops.nodes[0], .offset = ops.nodes[1], .indices = nodes(a, ops.count - 2, &ops.nodes[2])}); + const Node* r = lea_helper(a, ops.nodes[0], ops.nodes[1], nodes(a, ops.count - 2, &ops.nodes[2])); if (UNTYPED_POINTERS) { const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); bool idk; //element_t = qualified_type_helper(element_t, false); - enter_composite(&element_t, &idk, nodes(a, ops.count - 2, &ops.nodes[2]), true); + enter_composite_indices(&element_t, &idk, nodes(a, ops.count - 2, &ops.nodes[2]), true); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); r = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), BIND_PREV_R(typed_ptr)); } diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 36e14cf93..847d76d26 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -101,7 +101,7 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { const Node* index = rewrite_node(&ctx->rewriter, payload.operands.nodes[1]); return mem_and_value(a, (MemAndValue) { .mem = rewrite_node(r, payload.mem), - .value = lea(a, (Lea) { .ptr = src_ptr, .offset = int32_literal(a, 0), .indices = singleton(index) }), + .value = ptr_composite_element(a, (PtrCompositeElement) { .ptr = src_ptr, .index = index }), }); } else if (payload.opcode == SlimOpDereference) { assert(payload.operands.count == 1); diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 07206ef8a..9b94801ee 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -517,18 +517,6 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* case PrimOp_TAG: return infer_primop(ctx, node, expected_type); case Call_TAG: return infer_indirect_call(ctx, node, expected_type); case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); - case Instruction_Lea_TAG: { - Lea payload = node->payload.lea; - const Node* ptr = infer(ctx, payload.ptr, NULL); - const Node* offset = infer(ctx, payload.offset, NULL); - Nodes indices = infer_nodes(ctx, payload.indices); - - const Type* src_ptr = remove_uniformity_qualifier(ptr->type); - const Type* base_datatype = src_ptr; - assert(base_datatype->tag == PtrType_TAG); - - return lea(a, (Lea) { .ptr = ptr, .offset = offset, .indices = indices }); - } case Instruction_Load_TAG: { return load(a, (Load) { .ptr = infer(ctx, node->payload.load.ptr, NULL), .mem = infer(ctx, node->payload.load.mem, NULL) }); } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index b10b9dedd..925820efc 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1000,11 +1000,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < num_indices; i++) indices[i] = get_def_ssa_value(parser, instruction[indices_start + i]); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, lea(a, (Lea) { - .ptr = ptr, - .offset = offset, - .indices = nodes(a, num_indices, indices), - }), 1)); + parser->defs[result].node = lea_helper(a, ptr, offset, nodes(a, num_indices, indices)); break; } case SpvOpCompositeExtract: { diff --git a/src/shady/compile.c b/src/shady/compile.c index 2e12e23c0..1427c636e 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -88,12 +88,12 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lower_logical_pointers) RUN_PASS(lower_mask) - RUN_PASS(lower_memcpy) RUN_PASS(lower_subgroup_ops) if (config->lower.emulate_physical_memory) { RUN_PASS(lower_alloca) } RUN_PASS(lower_stack) + RUN_PASS(lower_memcpy) RUN_PASS(lower_lea) RUN_PASS(lower_generic_globals) if (config->lower.emulate_generic_ptrs) { diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 716c36c40..adb295283 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -246,6 +246,20 @@ const Node* prim_op_helper(IrArena* a, Op op, Nodes types, Nodes operands) { }); } +const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes indices) { + const Node* lea = ptr_array_element_offset(a, (PtrArrayElementOffset) { + .ptr = ptr, + .offset = offset, + }); + for (size_t i = 0; i < indices.count; i++) { + lea = ptr_composite_element(a, (PtrCompositeElement) { + .ptr = lea, + .index = indices.nodes[i], + }); + } + return lea; +} + const Node* jump_helper(IrArena* a, const Node* dst, Nodes args, const Node* mem) { return jump(a, (Jump) { .target = dst, diff --git a/src/shady/fold.c b/src/shady/fold.c index 8859abc6f..c840255bd 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -215,18 +215,13 @@ static inline const Node* resolve_ptr_source(const Node* ptr) { } break; } - case Lea_TAG: { - Lea payload = def->payload.lea; - if (!is_zero(payload.offset)) - goto outer_break; - for (size_t i = 0; i < payload.indices.count; i++) { - if (!is_zero(payload.indices.nodes[i])) - goto outer_break; + case PtrCompositeElement_TAG: { + PtrCompositeElement payload = def->payload.ptr_composite_element; + if (is_zero(payload.index)) { + distance++; + ptr = payload.ptr; + continue; } - distance++; - ptr = payload.ptr; - continue; - outer_break: break; } default: break; @@ -276,12 +271,20 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { r = store(arena, payload); break; } - case Lea_TAG: { - Lea payload = node->payload.lea; + case PtrCompositeElement_TAG: { + PtrCompositeElement payload = node->payload.ptr_composite_element; + const Node* nptr = simplify_ptr_operand(arena, payload.ptr); + if (!nptr) break; + payload.ptr = nptr; + r = ptr_composite_element(arena, payload); + break; + } + case PtrArrayElementOffset_TAG: { + PtrArrayElementOffset payload = node->payload.ptr_array_element_offset; const Node* nptr = simplify_ptr_operand(arena, payload.ptr); if (!nptr) break; payload.ptr = nptr; - r = lea(arena, payload); + r = ptr_array_element_offset(arena, payload); break; } default: return node; @@ -332,8 +335,14 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { return mem_and_value(arena, (MemAndValue) { .value = tuple_helper(arena, empty(arena)), .mem = node->payload.store.mem }); break; } - case Lea_TAG: { - Lea payload = node->payload.lea; + case PtrArrayElementOffset_TAG: { + PtrArrayElementOffset payload = node->payload.ptr_array_element_offset; + if (payload.ptr->tag == Undef_TAG) + return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + break; + } + case PtrCompositeElement_TAG: { + PtrCompositeElement payload = node->payload.ptr_composite_element; if (payload.ptr->tag == Undef_TAG) return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); break; @@ -374,6 +383,12 @@ const Node* fold_node(IrArena* arena, const Node* node) { node = fold_simplify_ptr_operand(node); switch (node->tag) { case PrimOp_TAG: node = fold_prim_op(arena, node); break; + case PtrArrayElementOffset_TAG: { + PtrArrayElementOffset payload = node->payload.ptr_array_element_offset; + if (is_zero(payload.offset)) + return payload.ptr; + break; + } case Branch_TAG: { Branch payload = node->payload.branch; if (arena->config.optimisations.fold_static_control_flow) { diff --git a/src/shady/node.c b/src/shady/node.c index e69b5cc6f..59242c797 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -83,18 +83,12 @@ const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { while (true) { ptr = resolve_node_to_definition(ptr, config); switch (ptr->tag) { - case Lea_TAG: { - Lea lea = ptr->payload.lea; - if (!is_zero(lea.offset)) - goto outer_break; - for (size_t i = 0; i < lea.indices.count; i++) { - if (!is_zero(lea.indices.nodes[i])) - goto outer_break; - } - ptr = lea.ptr; + case PtrArrayElementOffset_TAG: break; + case PtrCompositeElement_TAG: { + PtrCompositeElement payload = ptr->payload.ptr_composite_element; + if (!is_zero(payload.index)) + break; continue; - outer_break: - break; } case PrimOp_TAG: { switch (ptr->payload.prim_op.op) { @@ -240,7 +234,7 @@ const char* get_string_literal(IrArena* arena, const Node* node) { const Node* decl = node->payload.ref_decl.decl; return get_string_literal(arena, decl); } - case Lea_TAG: { + /*case Lea_TAG: { Lea lea = node->payload.lea; if (lea.indices.count == 3 && is_zero(lea.offset) && is_zero(first(lea.indices))) { const Node* ref = lea.ptr; @@ -252,7 +246,7 @@ const char* get_string_literal(IrArena* arena, const Node* node) { return get_string_literal(arena, decl->payload.global_variable.init); } break; - } + }*/ case StringLiteral_TAG: return node->payload.string_lit.string; case Composite_TAG: { Nodes contents = node->payload.composite.contents; diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index b321e7375..4b0eafba8 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -145,9 +145,7 @@ static const Node* process(Context* ctx, const Node* node) { //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); - const Node* lea_instr = lea(a, (Lea) { .ptr = ctx->base_stack_addr_on_entry, .offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)), .indices = empty(a) }); - //const Node* slot = first(bind_instruction_named(bb, lea_instr, (String []) { format_string_arena(a->arena, "stack_slot_%d", found_slot->i) })); - const Node* slot = lea_instr; + const Node* slot = ptr_array_element_offset(a, (PtrArrayElementOffset) { .ptr = ctx->base_stack_addr_on_entry, .offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)) }); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = gen_reinterpret_cast(bb, ptr_t, slot); //bool last = found_slot->i == ctx->num_slots - 1; diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 593d6012d..9a26b6d93 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -26,7 +26,62 @@ static bool is_as_emulated(SHADY_UNUSED Context* ctx, AddressSpace as) { } } -static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* pointer_type, const Node* base, const Node* offset, Nodes indices) { +static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* pointer_type, const Node* base, const Node* index) { + IrArena* a = ctx->rewriter.dst_arena; + const Type* emulated_ptr_t = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); + assert(pointer_type->tag == PtrType_TAG); + + const Node* ptr = base; + + assert(pointer_type->tag == PtrType_TAG); + const Type* pointed_type = pointer_type->payload.ptr_type.pointed_type; + switch (pointed_type->tag) { + case ArrType_TAG: { + const Type* element_type = pointed_type->payload.arr_type.element_type; + + const Node* element_t_size = gen_primop_e(bb, size_of_op, singleton(element_type), empty(a)); + + const Node* new_index = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, index); + const Node* physical_offset = gen_primop_ce(bb, mul_op, 2, (const Node* []) {new_index, element_t_size}); + + ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, physical_offset }); + + pointer_type = ptr_type(a, (PtrType) { + .pointed_type = element_type, + .address_space = pointer_type->payload.ptr_type.address_space + }); + break; + } + case TypeDeclRef_TAG: { + const Node* nom_decl = pointed_type->payload.type_decl_ref.decl; + assert(nom_decl && nom_decl->tag == NominalType_TAG); + pointed_type = nom_decl->payload.nom_type.body; + SHADY_FALLTHROUGH + } + case RecordType_TAG: { + Nodes member_types = pointed_type->payload.record_type.members; + + const IntLiteral* selector_value = resolve_to_int_literal(index); + assert(selector_value && "selector value must be known for LEA into a record"); + size_t n = selector_value->value; + assert(n < member_types.count); + + const Node* offset_of = gen_primop_e(bb, offset_of_op, singleton(pointed_type), singleton(uint64_literal(a, n))); + ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, offset_of }); + + pointer_type = ptr_type(a, (PtrType) { + .pointed_type = member_types.nodes[n], + .address_space = pointer_type->payload.ptr_type.address_space + }); + break; + } + default: error("cannot index into this") + } + + return ptr; +} + +static const Node* lower_ptr_offset(Context* ctx, BodyBuilder* bb, const Type* pointer_type, const Node* base, const Node* offset) { IrArena* a = ctx->rewriter.dst_arena; const Type* emulated_ptr_t = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); assert(pointer_type->tag == PtrType_TAG); @@ -48,53 +103,6 @@ static const Node* lower_ptr_arithm(Context* ctx, BodyBuilder* bb, const Type* p ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, physical_offset}); } - for (size_t i = 0; i < indices.count; i++) { - assert(pointer_type->tag == PtrType_TAG); - const Type* pointed_type = pointer_type->payload.ptr_type.pointed_type; - switch (pointed_type->tag) { - case ArrType_TAG: { - const Type* element_type = pointed_type->payload.arr_type.element_type; - - const Node* element_t_size = gen_primop_e(bb, size_of_op, singleton(element_type), empty(a)); - - const Node* new_index = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, indices.nodes[i]); - const Node* physical_offset = gen_primop_ce(bb, mul_op, 2, (const Node* []) {new_index, element_t_size}); - - ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, physical_offset }); - - pointer_type = ptr_type(a, (PtrType) { - .pointed_type = element_type, - .address_space = pointer_type->payload.ptr_type.address_space - }); - break; - } - case TypeDeclRef_TAG: { - const Node* nom_decl = pointed_type->payload.type_decl_ref.decl; - assert(nom_decl && nom_decl->tag == NominalType_TAG); - pointed_type = nom_decl->payload.nom_type.body; - SHADY_FALLTHROUGH - } - case RecordType_TAG: { - Nodes member_types = pointed_type->payload.record_type.members; - - const IntLiteral* selector_value = resolve_to_int_literal(indices.nodes[i]); - assert(selector_value && "selector value must be known for LEA into a record"); - size_t n = selector_value->value; - assert(n < member_types.count); - - const Node* offset_of = gen_primop_e(bb, offset_of_op, singleton(pointed_type), singleton(uint64_literal(a, n))); - ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, offset_of }); - - pointer_type = ptr_type(a, (PtrType) { - .pointed_type = member_types.nodes[n], - .address_space = pointer_type->payload.ptr_type.address_space - }); - break; - } - default: error("cannot index into this") - } - } - return ptr; } @@ -105,8 +113,31 @@ static const Node* process(Context* ctx, const Node* old) { const Type* emulated_ptr_t = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); switch (old->tag) { - case Lea_TAG: { - Lea lea = old->payload.lea; + case PtrArrayElementOffset_TAG: { + PtrArrayElementOffset lea = old->payload.ptr_array_element_offset; + const Node* old_base = lea.ptr; + const Type* old_base_ptr_t = old_base->type; + deconstruct_qualified_type(&old_base_ptr_t); + assert(old_base_ptr_t->tag == PtrType_TAG); + const Node* old_result_t = old->type; + deconstruct_qualified_type(&old_result_t); + bool must_lower = false; + // we have to lower generic pointers if we emulate them using ints + must_lower |= ctx->config->lower.emulate_generic_ptrs && old_base_ptr_t->payload.ptr_type.address_space == AsGeneric; + must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference && is_as_emulated(ctx, old_base_ptr_t->payload.ptr_type.address_space); + if (!must_lower) + break; + BodyBuilder* bb = begin_block_pure(a); + // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); + const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, rewrite_node(r, lea.ptr)); + const Type* new_base_t = rewrite_node(&ctx->rewriter, old_base_ptr_t); + const Node* result = lower_ptr_offset(ctx, bb, new_base_t, cast_base, rewrite_node(r, lea.offset)); + const Type* new_ptr_t = rewrite_node(&ctx->rewriter, old_result_t); + const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); + return yield_values_and_wrap_in_block(bb, singleton(cast_result)); + } + case PtrCompositeElement_TAG: { + PtrCompositeElement lea = old->payload.ptr_composite_element; const Node* old_base = lea.ptr; const Type* old_base_ptr_t = old_base->type; deconstruct_qualified_type(&old_base_ptr_t); @@ -123,7 +154,7 @@ static const Node* process(Context* ctx, const Node* old) { // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, rewrite_node(r, lea.ptr)); const Type* new_base_t = rewrite_node(&ctx->rewriter, old_base_ptr_t); - const Node* result = lower_ptr_arithm(ctx, bb, new_base_t, cast_base, rewrite_node(r, lea.offset), rewrite_nodes(r, lea.indices)); + const Node* result = lower_ptr_index(ctx, bb, new_base_t, cast_base, rewrite_node(r, lea.index)); const Type* new_ptr_t = rewrite_node(&ctx->rewriter, old_result_t); const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); return yield_values_and_wrap_in_block(bb, singleton(cast_result)); diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 6d88a5fa0..e8871f0eb 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -53,7 +53,7 @@ static const Node* process(Context* ctx, const Node* old) { payload.pointed_type = rewrite_node(r, payload.pointed_type); return ptr_type(a, payload); } - case Lea_TAG: { + /*case PtrArrayElementOffset_TAG: { Lea payload = old->payload.lea; const Type* optr_t = payload.ptr->type; deconstruct_qualified_type(&optr_t); @@ -65,6 +65,20 @@ static const Node* process(Context* ctx, const Node* old) { if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); return bind_last_instruction_and_wrap_in_block(bb, lea(a, (Lea) { .ptr = ptr, .offset = rewrite_node(r, payload.offset), .indices = rewrite_nodes(r, payload.indices)})); + }*/ + // TODO: we actually want to match stuff that has a ptr as an input operand. + case PtrCompositeElement_TAG: { + PtrCompositeElement payload = old->payload.ptr_composite_element; + const Type* optr_t = payload.ptr->type; + deconstruct_qualified_type(&optr_t); + assert(optr_t->tag == PtrType_TAG); + const Type* expected_type = rewrite_node(r, optr_t); + const Node* ptr = rewrite_node(r, payload.ptr); + const Type* actual_type = get_unqualified_type(ptr->type); + BodyBuilder* bb = begin_block_pure(a); + if (expected_type != actual_type) + ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); + return bind_last_instruction_and_wrap_in_block(bb, ptr_composite_element(a, (PtrCompositeElement) { .ptr = ptr, .index = rewrite_node(r, payload.index)})); } case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 1eed369f2..41adef082 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -36,11 +36,11 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { break; } case RefDecl_TAG: return get_req_cast(ctx, src->payload.ref_decl.decl); - case Lea_TAG: { - const Type* src_req_cast = get_req_cast(ctx, src->payload.lea.ptr); + case PtrCompositeElement_TAG: { + const Type* src_req_cast = get_req_cast(ctx, src->payload.ptr_composite_element.ptr); if (src_req_cast) { bool u = deconstruct_qualified_type(&src_req_cast); - enter_composite(&src_req_cast, &u, src->payload.lea.indices, false); + enter_composite(&src_req_cast, &u, src->payload.ptr_composite_element.index, false); return src_req_cast; } break; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 7c29c9f90..bdc3aef7f 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -86,12 +86,12 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca } if (has_primop_got_side_effects(payload.op)) k->leaks = true; - } else if (use->user->tag == Lea_TAG) { + } /*else if (use->user->tag == Lea_TAG) { // TODO: follow where those derived pointers are used and establish whether they leak themselves // use slice_type to keep track of the expected type for the relevant sub-object k->leaks = true; continue; - } else if (use->user->tag == Composite_TAG) { + } */else if (use->user->tag == Composite_TAG) { // todo... // note: if a composite literal containing our POI (pointer-of-interest) is extracted from, folding ops simplify this to the original POI // so we don't need to be so clever here I think diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 4446a84de..0662219d9 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -19,10 +19,10 @@ typedef struct { static const Node* get_ptr_source(const Node* ptr) { while (true) { switch (ptr->tag) { - case Lea_TAG: { - ptr = ptr->payload.lea.ptr; - break; - } + // case Lea_TAG: { + // ptr = ptr->payload.lea.ptr; + // break; + // } case PrimOp_TAG: { PrimOp payload = ptr->payload.prim_op; switch (payload.op) { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 14be7bae9..80a8f1ac8 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -125,7 +125,7 @@ void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { } const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { - return lea(bb->arena, (Lea) { .ptr = base, .offset = offset, .indices = selectors }); + return lea_helper(bb->arena, base, offset, selectors); } const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { diff --git a/src/shady/type.c b/src/shady/type.c index 06a1c3d10..cffafd1e9 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -776,7 +776,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* t = source->type; bool uniform = deconstruct_qualified_type(&t); - enter_composite(&t, &uniform, indices, true); + enter_composite_indices(&t, &uniform, indices, true); if (prim_op.op == insert_op) { const Node* inserted_data = prim_op.operands.nodes[1]; @@ -1045,7 +1045,7 @@ const Type* check_type_store(IrArena* a, Store store) { return empty_multiple_return_type(a); } -const Type* check_type_lea(IrArena* a, Lea lea) { +const Type* check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffset lea) { const Type* base_ptr_type = lea.ptr->type; bool uniform = deconstruct_qualified_type(&base_ptr_type); assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); @@ -1062,7 +1062,23 @@ const Type* check_type_lea(IrArena* a, Lea lea) { assert(offset_is_zero || is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); uniform &= offset_uniform; - enter_composite(&pointee_type, &uniform, lea.indices, true); + return qualified_type(a, (QualifiedType) { + .is_uniform = uniform, + .type = ptr_type(a, (PtrType) { + .pointed_type = pointee_type, + .address_space = base_ptr_type->payload.ptr_type.address_space, + .is_reference = base_ptr_type->payload.ptr_type.is_reference + }) + }); +} + +const Type* check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea) { + const Type* base_ptr_type = lea.ptr->type; + bool uniform = deconstruct_qualified_type(&base_ptr_type); + assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); + const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; + + enter_composite(&pointee_type, &uniform, lea.index, true); return qualified_type(a, (QualifiedType) { .is_uniform = uniform, diff --git a/src/shady/type.h b/src/shady/type.h index 2ddc7f65a..aeeb81a65 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -35,8 +35,8 @@ Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); /// Returns the (possibly qualified) pointee type from a (possibly qualified) ptr type const Type* get_pointee_type(IrArena*, const Type*); -void step_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); -void enter_composite(const Type** datatype, bool* u, Nodes indices, bool allow_entering_pack); +void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); +void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack); /// Collects the annotated types in the list of variables /// NB: this is different from get_values_types, that function uses node.type, whereas this one uses node.payload.var.type diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 099ba9be2..2f24f35ee 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -49,7 +49,7 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { return type; } -void step_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack) { +void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack) { const Type* current_type = *datatype; if (selector->arena->config.check_types) { @@ -98,10 +98,10 @@ void step_composite(const Type** datatype, bool* uniform, const Node* selector, *datatype = current_type; } -void enter_composite(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack) { +void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack) { for(size_t i = 0; i < indices.count; i++) { const Node* selector = indices.nodes[i]; - step_composite(datatype, uniform, selector, allow_entering_pack); + enter_composite(datatype, uniform, selector, allow_entering_pack); } } From 046dba77da9345acde793b5141b4649871aeb563 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 3 Sep 2024 12:15:09 +0200 Subject: [PATCH 569/693] fix mem2reg (i am big dumb) --- src/shady/passes/opt_mem2reg.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 0662219d9..324446ca2 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -16,13 +16,25 @@ typedef struct { bool* todo; } Context; +typedef struct { + const Node* src; + Nodes indices; +}; + static const Node* get_ptr_source(const Node* ptr) { + IrArena* a = ptr->arena; while (true) { switch (ptr->tag) { - // case Lea_TAG: { - // ptr = ptr->payload.lea.ptr; - // break; - // } + case PtrCompositeElement_TAG: { + PtrCompositeElement payload = ptr->payload.ptr_composite_element; + ptr = payload.ptr; + break; + } + case PtrArrayElementOffset_TAG: { + PtrArrayElementOffset payload = ptr->payload.ptr_array_element_offset; + ptr = payload.ptr; + break; + } case PrimOp_TAG: { PrimOp payload = ptr->payload.prim_op; switch (payload.op) { @@ -45,7 +57,8 @@ static const Node* get_ptr_source(const Node* ptr) { } } -static const Node* get_last_stored_value(Context* ctx, const Node* ptr, const Node* mem) { +static const Node* get_last_stored_value(Context* ctx, const Node* ptr, const Node* mem, const Type* expected_type) { + const Node* ptr_source = get_ptr_source(ptr); while (mem) { switch (mem->tag) { case AbsMem_TAG: { @@ -56,11 +69,15 @@ static const Node* get_last_stored_value(Context* ctx, const Node* ptr, const No mem = get_terminator_mem(e.terminator); continue; } + break; } case Store_TAG: { Store payload = mem->payload.store; if (payload.ptr == ptr) return payload.value; + if (get_ptr_source(payload.ptr) == ptr_source) + return NULL; + break; } default: break; } @@ -84,10 +101,10 @@ static const Node* process(Context* ctx, const Node* node) { case Load_TAG: { Load payload = node->payload.load; const Node* src = get_ptr_source(payload.ptr); - if (src->tag != StackAlloc_TAG) + if (src->tag != LocalAlloc_TAG) break; // for now, only simplify loads from non-leaking allocas - const Node* ovalue = get_last_stored_value(ctx, payload.ptr, payload.mem); + const Node* ovalue = get_last_stored_value(ctx, payload.ptr, payload.mem, get_unqualified_type(node->type)); if (ovalue) { *ctx->todo = true; const Node* value = rewrite_node(r, ovalue); From 61580d1fdd0c2dbbf7e91b3798f80bf47e70db61 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 3 Sep 2024 12:59:21 +0200 Subject: [PATCH 570/693] fix reconvergence_heuristics --- src/shady/passes/reconvergence_heuristics.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index bbaa3bd3b..8813eecf0 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -163,16 +163,16 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { set_abstraction_body(continue_wrapper, continue_wrapper_body); // replace the exit nodes by the exit wrappers - LARRAY(const Node*, cached_exits, exiting_nodes_count); + LARRAY(const Node**, cached_exits, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; - cached_exits[i] = *search_processed(rewriter, exiting_node->node); + cached_exits[i] = search_processed(rewriter, exiting_node->node); if (cached_exits[i]) remove_dict(const Node*, rewriter->map, exiting_node->node); register_processed(rewriter, exiting_node->node, exit_wrappers[i]); } // ditto for the loop entry and the continue wrapper - const Node* cached_entry = *search_processed(rewriter, node); + const Node** cached_entry = search_processed(rewriter, node); if (cached_entry) remove_dict(const Node*, rewriter->map, node); register_processed(rewriter, node, continue_wrapper); @@ -215,11 +215,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t i = 0; i < exiting_nodes_count; i++) { remove_dict(const Node*, rewriter->map, read_list(CFNode*, exiting_nodes)[i]->node); if (cached_exits[i]) - register_processed(rewriter, read_list(CFNode*, exiting_nodes)[i]->node, cached_exits[i]); + register_processed(rewriter, read_list(CFNode*, exiting_nodes)[i]->node, *cached_exits[i]); } remove_dict(const Node*, rewriter->map, node); if (cached_entry) - register_processed(rewriter, node, cached_entry); + register_processed(rewriter, node, *cached_entry); Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); BodyBuilder* inner_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_outer)); @@ -415,11 +415,11 @@ static const Node* process_node(Context* ctx, const Node* node) { .mem = get_abstraction_mem(pre_join), })); - const Node* cached = *search_processed(r, post_dominator); + const Node** cached = search_processed(r, post_dominator); if (cached) remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); for (size_t i = 0; i < old_params.count; i++) { - assert(!*search_processed(r, old_params.nodes[i])); + assert(!search_processed(r, old_params.nodes[i])); } register_processed(r, post_dominator, pre_join); @@ -435,7 +435,7 @@ static const Node* process_node(Context* ctx, const Node* node) { remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); if (cached) - register_processed(r, post_dominator, cached); + register_processed(r, post_dominator, *cached); const Node* join_target = rewrite_node(r, post_dominator); From 5b0161a02d1e1a1282d6b7b8f5242723370ee82e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 3 Sep 2024 13:01:19 +0200 Subject: [PATCH 571/693] fix API that C++ hates --- include/shady/ir.h | 10 ++++++---- src/shady/body_builder.c | 18 +++++++++--------- src/shady/passes/lower_generic_ptrs.c | 4 ++-- src/shady/passes/lower_memcpy.c | 4 ++-- src/shady/passes/lower_tailcalls.c | 4 ++-- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 82fc54bbb..ac867604e 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -298,19 +298,21 @@ Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, Node*); Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, Node*); Nodes gen_loop(BodyBuilder*, Nodes, Nodes, Node*); -struct begin_control_r { +typedef struct { Nodes results; Node* case_; const Node* jp; -} begin_control(BodyBuilder*, Nodes); +} begin_control_t; +begin_control_t begin_control(BodyBuilder*, Nodes); -struct begin_loop_helper_r { +typedef struct { Nodes results; Node* loop_body; Nodes params; const Node* continue_jp; const Node* break_jp; -} begin_loop_helper(BodyBuilder*, Nodes, Nodes, Nodes); +} begin_loop_helper_t; +begin_loop_helper_t begin_loop_helper(BodyBuilder*, Nodes, Nodes, Nodes); Nodes gen_control(BodyBuilder*, Nodes, Node*); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 139275e7f..c3d8d3956 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -322,7 +322,7 @@ Nodes gen_control(BodyBuilder* bb, Nodes yield_types, Node* body) { }); } -struct begin_control_r begin_control(BodyBuilder* bb, Nodes yield_types) { +begin_control_t begin_control(BodyBuilder* bb, Nodes yield_types) { IrArena* a = bb->arena; const Type* jp_type = qualified_type(a, (QualifiedType) { .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), @@ -330,17 +330,17 @@ struct begin_control_r begin_control(BodyBuilder* bb, Nodes yield_types) { }); const Node* jp = param(a, jp_type, NULL); Node* c = case_(a, singleton(jp)); - return (struct begin_control_r) { - .results = gen_control(bb, yield_types, c), - .case_ = c, - .jp = jp + return (begin_control_t) { + .results = gen_control(bb, yield_types, c), + .case_ = c, + .jp = jp }; } -struct begin_loop_helper_r begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes arg_types, Nodes initial_values) { +begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes arg_types, Nodes initial_values) { assert(arg_types.count == initial_values.count); IrArena* a = bb->arena; - struct begin_control_r outer_control = begin_control(bb, yield_types); + begin_control_t outer_control = begin_control(bb, yield_types); BodyBuilder* outer_control_case_builder = begin_body_with_mem(a, get_abstraction_mem(outer_control.case_)); LARRAY(const Node*, params, arg_types.count); for (size_t i = 0; i < arg_types.count; i++) { @@ -349,10 +349,10 @@ struct begin_loop_helper_r begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Node* loop_header = case_(a, nodes(a, arg_types.count, params)); set_abstraction_body(outer_control.case_, finish_body_with_jump(outer_control_case_builder, loop_header, initial_values)); BodyBuilder* loop_header_builder = begin_body_with_mem(a, get_abstraction_mem(loop_header)); - struct begin_control_r inner_control = begin_control(loop_header_builder, arg_types); + begin_control_t inner_control = begin_control(loop_header_builder, arg_types); set_abstraction_body(loop_header, finish_body_with_jump(loop_header_builder, loop_header, inner_control.results)); - return (struct begin_loop_helper_r) { + return (begin_loop_helper_t) { .results = outer_control.results, .params = nodes(a, arg_types.count, params), .loop_body = inner_control.case_, diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 1a8f2857c..7a74d355e 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -101,7 +101,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo case LoadFn: { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); - struct begin_control_r r = begin_control(bb, singleton(t)); + begin_control_t r = begin_control(bb, singleton(t)); const Node* final_loaded_value = first(r.results); LARRAY(const Node*, literals, max_tag); @@ -139,7 +139,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo case StoreFn: { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); - struct begin_control_r r = begin_control(bb, empty(a)); + begin_control_t r = begin_control(bb, empty(a)); LARRAY(const Node*, literals, max_tag); LARRAY(const Node*, jumps, max_tag); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 3295cc7a7..66b8eb3db 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -50,7 +50,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, payload.count)); const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num_in_bytes)); - struct begin_loop_helper_r l = begin_loop_helper(bb, empty(a), singleton(uint32_type(a)), singleton( uint32_literal(a, 0))); + begin_loop_helper_t l = begin_loop_helper(bb, empty(a), singleton(uint32_type(a)), singleton( uint32_literal(a, 0))); const Node* index = first(l.params); set_value_name(index, "memcpy_i"); @@ -97,7 +97,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num = rewrite_node(&ctx->rewriter, payload.count); const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); - struct begin_loop_helper_r l = begin_loop_helper(bb, empty(a), singleton(uint32_type(a)), singleton( uint32_literal(a, 0))); + begin_loop_helper_t l = begin_loop_helper(bb, empty(a), singleton(uint32_type(a)), singleton( uint32_literal(a, 0))); const Node* index = first(l.params); set_value_name(index, "memset_i"); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 6b4f445cc..c042dc9b5 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -275,7 +275,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { // Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL)); // gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a), loop_inside_case); - struct begin_loop_helper_r l = begin_loop_helper(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_type(a)) : empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a)); + begin_loop_helper_t l = begin_loop_helper(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_type(a)) : empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a)); Node* loop_inside_case = l.loop_body; if (count_iterations) iterations_count_param = first(l.params); @@ -300,7 +300,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, 1))); if (ctx->config->shader_diagnostics.max_top_iterations > 0) { - struct begin_control_r c = begin_control(loop_body_builder, empty(a)); + begin_control_t c = begin_control(loop_body_builder, empty(a)); const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); Node* bail_case = case_(a, empty(a)); const Node* break_terminator = join(a, (Join) { .args = empty(a), .join_point = l.break_jp, .mem = get_abstraction_mem(bail_case) }); From 61c447bacfcf54f3e4b9b7bba8097b8675ac7056 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 3 Sep 2024 13:41:51 +0200 Subject: [PATCH 572/693] ignore llvm.var.annotation --- src/frontend/llvm/l2s_instr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 77a8c147a..aa7b4822b 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -485,6 +485,10 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B // don't care return NULL; } + if (string_starts_with(intrinsic, "llvm.var.annotation")) { + // don't care + return NULL; + } if (string_starts_with(intrinsic, "llvm.memcpy")) { Nodes ops = convert_operands(p, num_ops, instr); return bind_instruction_single(b, copy_bytes(a, (CopyBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = bb_mem(b) })); From ece27130edbf3697c2f5017e20d7a4d84d8b895d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 3 Sep 2024 15:11:06 +0200 Subject: [PATCH 573/693] prepare lift_indirect_targets --- src/shady/passes/lift_indirect_targets.c | 8 +++++--- src/shady/rewrite.c | 15 ++++++++++++--- src/shady/rewrite.h | 2 ++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index a527ed9bb..ad9284e55 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -90,6 +90,10 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { destroy_scheduler(scheduler); + Context lifting_ctx = *ctx; + lifting_ctx.rewriter = create_decl_rewriter(&ctx->rewriter); + Rewriter* r = &lifting_ctx.rewriter; + Nodes ovariables = get_abstraction_params(liftee); debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { @@ -112,9 +116,6 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { lifted_cont->save_values = frontier; insert_dict(const Node*, LiftedCont*, ctx->lifted, liftee, lifted_cont); - Context lifting_ctx = *ctx; - lifting_ctx.rewriter = create_children_rewriter(&ctx->rewriter); - Rewriter* r = &lifting_ctx.rewriter; register_processed_list(r, ovariables, new_params); const Node* payload = param(a, qualified_type_helper(uint32_type(a), false), "sp"); @@ -146,6 +147,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { } register_processed(r, get_abstraction_mem(liftee), bb_mem(bb)); + register_processed(r, liftee, new_fn); const Node* substituted = rewrite_node(r, obody); destroy_rewriter(r); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 315aeea13..e1266ef82 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -24,13 +24,15 @@ Rewriter create_rewriter_base(Module* src, Module* dst) { .write_map = true, }, .map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .own_decls = true, + .decls_map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .parent = NULL, }; } Rewriter create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn) { Rewriter r = create_rewriter_base(src, dst); r.rewrite_fn = fn; - r.decls_map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); return r; } @@ -38,14 +40,13 @@ Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn) { Rewriter r = create_rewriter_base(src, dst); r.config.write_map = false; r.rewrite_op_fn = fn; - r.decls_map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); return r; } void destroy_rewriter(Rewriter* r) { assert(r->map); destroy_dict(r->map); - if (!r->parent) + if (r->own_decls) destroy_dict(r->decls_map); } @@ -57,6 +58,14 @@ Rewriter create_children_rewriter(Rewriter* parent) { Rewriter r = *parent; r.map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); r.parent = parent; + r.own_decls = false; + return r; +} + +Rewriter create_decl_rewriter(Rewriter* parent) { + Rewriter r = *parent; + r.map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + r.own_decls = false; return r; } diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index 9240c5074..fa2760bcf 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -38,6 +38,7 @@ struct Rewriter_ { Rewriter* parent; struct Dict* map; + bool own_decls; struct Dict* decls_map; }; @@ -47,6 +48,7 @@ Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn); Rewriter create_importer(Module* src, Module* dst); Rewriter create_children_rewriter(Rewriter* parent); +Rewriter create_decl_rewriter(Rewriter* parent); void destroy_rewriter(Rewriter*); void rewrite_module(Rewriter*); From e79683cf696f03eed0d9c0d56000f9e8de62818f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 12:22:55 +0200 Subject: [PATCH 574/693] eliminate 0-sized memcpy from generated code --- src/shady/generator_constructors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 5d0a697b5..9c49b98b6 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -37,7 +37,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { if (list) { growy_append_formatted(g, "\t\t\tsize_t ops_count = node->payload.%s.%s.count;\n", snake_name, op_name); growy_append_formatted(g, "\t\t\tLARRAY(const Node*, ops, ops_count);\n"); - growy_append_formatted(g, "\t\t\tmemcpy(ops, node->payload.%s.%s.nodes, sizeof(const Node*) * ops_count);\n", snake_name, op_name); + growy_append_formatted(g, "\t\t\tif (ops_count > 0) memcpy(ops, node->payload.%s.%s.nodes, sizeof(const Node*) * ops_count);\n", snake_name, op_name); growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < ops_count; i++) {\n"); growy_append_formatted(g, "\t\t\tconst Node** pop = &ops[i];\n"); extra = "\t"; From 1ca1ce769286fef9d7951653d485af65aa12e9b4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 14:26:34 +0200 Subject: [PATCH 575/693] hacky fix for lift_indirect_targets --- src/shady/analysis/free_frontier.c | 14 ++++++++++++-- src/shady/passes/lift_indirect_targets.c | 5 ++++- src/shady/passes/lower_tailcalls.c | 6 +++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/shady/analysis/free_frontier.c b/src/shady/analysis/free_frontier.c index 9f8655926..d332b397d 100644 --- a/src/shady/analysis/free_frontier.c +++ b/src/shady/analysis/free_frontier.c @@ -22,8 +22,18 @@ static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { if (cfg_is_dominated(where, v->start)) { visit_node_operands(&vv.v, NcAbstraction | NcDeclaration | NcType, node); } else { - if (!is_abstraction(node)) - insert_set_get_result(const Node*, v->frontier, node); + if (is_abstraction(node)) { + struct Dict* other_ff = free_frontier(v->scheduler, v->cfg, node); + size_t i = 0; + const Node* f; + while (dict_iter(other_ff, &i, &f, NULL)) { + insert_set_get_result(const Node*, v->frontier, f); + } + destroy_dict(other_ff); + } + if (is_value(node)) { + insert_set_get_result(const Node*, v->frontier, node); + } } } } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index ad9284e55..be8edaefb 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -98,7 +98,10 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { const Node* item = frontier.nodes[i]; - assert(is_value(item)); + if (!is_value(item)) { + //lambda_lift() + continue; + } debugv_print("%%%d", item->id); if (i + 1 < recover_context_size) debugv_print(", "); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index c042dc9b5..1a29d007f 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -141,11 +141,11 @@ static const Node* process(Context* ctx, const Node* old) { const Node* old_param = old->payload.fun.params.nodes[i]; const Type* new_param_type = rewrite_node(&ctx->rewriter, get_unqualified_type(old_param->type)); const Node* popped = gen_pop_value_stack(bb, new_param_type); - if (old_param->payload.param.name) - set_value_name((Node*) popped, old_param->payload.param.name); // TODO use the uniform stack instead ? or no ? if (is_qualified_type_uniform(old_param->type)) - popped = first(bind_instruction_named(bb, prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = empty(a), .operands = singleton(popped) }), &old_param->payload.param.name)); + popped = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = empty(a), .operands = singleton(popped) }); + if (old_param->payload.param.name) + set_value_name((Node*) popped, old_param->payload.param.name); register_processed(&ctx->rewriter, old_param, popped); } register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); From 23aefdb60ddd44dbfe673d29429d9963b90c85d3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 15:22:22 +0200 Subject: [PATCH 576/693] l2s: robustly deal with funny BB orders on-disk --- src/frontend/llvm/l2s.c | 95 ++++++++++++++++++++++----------- src/frontend/llvm/l2s_instr.c | 4 +- src/frontend/llvm/l2s_private.h | 12 ++++- 3 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index a49e3b622..634c2adcd 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -44,38 +44,34 @@ int vcc_get_linked_major_llvm_version() { #error "wat" #endif -static const Node* write_bb_tail(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef bb, LLVMValueRef first_instr) { - BodyBuilder* b = begin_body_with_mem(fn_or_bb->arena, get_abstraction_mem(fn_or_bb)); +static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { + bb_ctx->builder = begin_body_with_mem(bb_ctx->nbb->arena, get_abstraction_mem(bb_ctx->nbb)); LLVMValueRef instr; - for (instr = first_instr; instr; instr = LLVMGetNextInstruction(instr)) { + LLVMBasicBlockRef bb = bb_ctx->bb; + for (instr = bb_ctx->instr; instr; instr = LLVMGetNextInstruction(instr)) { bool last = instr == LLVMGetLastInstruction(bb); if (last) assert(LLVMGetBasicBlockTerminator(bb) == instr); // LLVMDumpValue(instr); // printf("\n"); - const Node* emitted = convert_instruction(p, fn_ctx, fn_or_bb, b, instr); + if (LLVMIsATerminatorInst(instr)) + return; + const Node* emitted = convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr); if (!emitted) continue; insert_dict(LLVMValueRef, const Node*, p->map, instr, emitted); - if (is_terminator(emitted)) - return finish_body(b, emitted); - //String names[] = { LLVMGetValueName(instr) }; - //Nodes results = bind_instruction_outputs_count(b, emitted.instruction, emitted.result_types.count); - //if (emitted.result_types.count == 1) { - // const Node* result = first(results); - // insert_dict(LLVMValueRef, const Node*, p->map, instr, result); - //} } + log_string(ERROR, "Reached end of LLVM basic block without encountering a terminator!"); SHADY_UNREACHABLE; } -typedef struct { - LLVMBasicBlockRef bb; - LLVMValueRef instr; - Node* nbb; -} TodoBB; +static void write_bb_tail(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { + LLVMBasicBlockRef bb = bb_ctx->bb; + LLVMValueRef instr = LLVMGetLastInstruction(bb); + set_abstraction_body(bb_ctx->nbb, finish_body(bb_ctx->builder, convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr))); +} -static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { +static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); if (get_log_level() >= DEBUG) @@ -105,20 +101,42 @@ static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { Node* nbb = basic_block(a, params, name); insert_dict(LLVMValueRef, const Node*, p->map, bb, nbb); insert_dict(const Node*, struct List*, fn_ctx->phis, nbb, phis); - TodoBB todo = { + *ctx = (BBParseCtx) { .bb = bb, .instr = instr, .nbb = nbb, }; - return todo; } } -const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { +static BBParseCtx* get_bb_ctx(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { + BBParseCtx** found = find_value_dict(LLVMValueRef, BBParseCtx*, fn_ctx->bbs, bb); + if (found) return *found; + + BBParseCtx* ctx = arena_alloc(p->annotations_arena, sizeof(BBParseCtx)); + prepare_bb(p, fn_ctx, ctx, bb); + insert_dict(LLVMBasicBlockRef, BBParseCtx*, fn_ctx->bbs, bb, ctx); + + return ctx; +} + +const Node* convert_basic_block_header(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); if (found) return *found; - assert(false); + BBParseCtx* ctx = get_bb_ctx(p, fn_ctx, bb); + return ctx->nbb; +} + +const Node* convert_basic_block_body(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { + BBParseCtx* ctx = get_bb_ctx(p, fn_ctx, bb); + if (ctx->translated) + return ctx->nbb; + + ctx->translated = true; + write_bb_body(p, fn_ctx, ctx); + write_bb_tail(p, fn_ctx, ctx); + return ctx->nbb; } const Node* convert_function(Parser* p, LLVMValueRef fn) { @@ -163,6 +181,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { FnParseCtx fn_parse_ctx = { .fn = f, .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), + .bbs = new_dict(LLVMBasicBlockRef, BBParseCtx*, (HashFn) hash_ptr, (CmpFn) compare_ptrs), .jumps_todo = new_list(JumpTodo), }; const Node* r = fn_addr_helper(a, f); @@ -173,18 +192,33 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); - LLVMBasicBlockRef bb = LLVMGetNextBasicBlock(first_bb); - LARRAY(TodoBB, todo, bb_count); - size_t i = 1; - for (;bb; bb = LLVMGetNextBasicBlock(bb)) { + //LLVMBasicBlockRef bb = LLVMGetNextBasicBlock(first_bb); + //LARRAY(BBParseCtx, bbs, bb_count); + //bbs[0] = (BBParseCtx) { + BBParseCtx bb0 = { + .nbb = f, + .bb = first_bb, + .instr = LLVMGetFirstInstruction(first_bb), + }; + //BBParseCtx* bb0p = &bbs[0]; + BBParseCtx* bb0p = &bb0; + insert_dict(LLVMBasicBlockRef, BBParseCtx*, fn_parse_ctx.bbs, first_bb, bb0p); + + write_bb_body(p, &fn_parse_ctx, &bb0); + write_bb_tail(p, &fn_parse_ctx, &bb0); + + /*for (size_t i = 1;bb; bb = LLVMGetNextBasicBlock(bb)) { assert(i < bb_count); - todo[i++] = prepare_bb(p, &fn_parse_ctx, bb); + prepare_bb(p, &fn_parse_ctx, &bbs[i++], bb); } - set_abstraction_body(f, write_bb_tail(p, &fn_parse_ctx, f, first_bb, LLVMGetFirstInstruction(first_bb))); - for (size_t i = 1; i < bb_count; i++) { - todo[i].nbb->payload.basic_block.body = write_bb_tail(p, &fn_parse_ctx, todo[i].nbb, todo[i].bb, todo[i].instr); + for (size_t i = 0; i < bb_count; i++) { + write_bb_body(p, &fn_parse_ctx, &bbs[i]); } + + for (size_t i = 0; i < bb_count; i++) { + write_bb_tail(p, &fn_parse_ctx, &bbs[i]); + }*/ } { @@ -195,6 +229,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { } } destroy_dict(fn_parse_ctx.phis); + destroy_dict(fn_parse_ctx.bbs); destroy_list(fn_parse_ctx.jumps_todo); return r; diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index aa7b4822b..b34cb6349 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -58,7 +58,7 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, LLVMBasicBlockRef dst, const Node* mem) { IrArena* a = fn_ctx->fn->arena; - const Node* dst_bb = convert_basic_block(p, fn_ctx, dst); + const Node* dst_bb = convert_basic_block_body(p, fn_ctx, dst); BBPhis* phis = find_value_dict(const Node*, BBPhis, fn_ctx->phis, dst_bb); assert(phis); size_t params_count = entries_count_list(phis->list); @@ -66,7 +66,7 @@ static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, for (size_t i = 0; i < params_count; i++) { LLVMValueRef phi = read_list(LLVMValueRef, phis->list)[i]; for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { - if (convert_basic_block(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == src) { + if (convert_basic_block_header(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == src) { params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); goto next; } diff --git a/src/frontend/llvm/l2s_private.h b/src/frontend/llvm/l2s_private.h index cec75ea2f..3ef8a4a2c 100644 --- a/src/frontend/llvm/l2s_private.h +++ b/src/frontend/llvm/l2s_private.h @@ -23,9 +23,18 @@ typedef struct { Module* dst; } Parser; +typedef struct { + LLVMBasicBlockRef bb; + LLVMValueRef instr; + Node* nbb; + BodyBuilder* builder; + bool translated; +} BBParseCtx; + typedef struct { Node* fn; struct Dict* phis; + struct Dict* bbs; struct List* jumps_todo; } FnParseCtx; @@ -53,7 +62,8 @@ const Type* convert_type(Parser* p, LLVMTypeRef t); const Node* convert_metadata(Parser* p, LLVMMetadataRef meta); const Node* convert_global(Parser* p, LLVMValueRef global); const Node* convert_function(Parser* p, LLVMValueRef fn); -const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); +const Node* convert_basic_block_header(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); +const Node* convert_basic_block_body(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); typedef struct { struct List* list; From cdd1cf4ab65ae6cf333f8ce7aec5ae91759ce205 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 15:30:13 +0200 Subject: [PATCH 577/693] fix Match merges being emitted wrong in SPIR-V mode --- src/backend/spirv/emit_spv_control_flow.c | 31 +++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 35b45084d..494e159dc 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -129,7 +129,12 @@ static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_buil spvb_branch(bb_builder, header_id); } -static CFNode* find_surrounding_structured_construct_node(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Structured_constructTag tag) { +typedef enum { + SelectionConstruct, + LoopConstruct, +} Construct; + +static CFNode* find_surrounding_structured_construct_node(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Construct construct) { const Node* oabs = abs; for (CFNode* n = cfg_lookup(fn_builder->cfg, abs); n; oabs = n->node, n = n->idom) { const Node* terminator = get_abstraction_body(n->node); @@ -137,16 +142,19 @@ static CFNode* find_surrounding_structured_construct_node(Emitter* emitter, FnBu if (is_structured_construct(terminator) && get_structured_construct_tail(terminator) == oabs) { continue; } - if (terminator->tag == tag) { - printf("structured construct for %d is %d\n", abs->id, n->node->id); + if (construct == LoopConstruct && terminator->tag == Loop_TAG) return n; - } + if (construct == SelectionConstruct && terminator->tag == If_TAG) + return n; + if (construct == SelectionConstruct && terminator->tag == Match_TAG) + return n; + } return NULL; } -static const Node* find_construct(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Structured_constructTag tag) { - CFNode* found = find_surrounding_structured_construct_node(emitter, fn_builder, abs, tag); +static const Node* find_construct(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Construct construct) { + CFNode* found = find_surrounding_structured_construct_node(emitter, fn_builder, abs, construct); return found ? get_abstraction_body(found->node) : NULL; } @@ -211,9 +219,8 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi case MergeSelection_TAG: { MergeSelection payload = terminator->payload.merge_selection; spv_emit_mem(emitter, fn_builder, payload.mem); - const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_If_TAG); - if (!construct) - construct = find_construct(emitter, fn_builder, abs, Structured_construct_Match_TAG); + const Node* construct = find_construct(emitter, fn_builder, abs, SelectionConstruct); + assert(construct); const Node* tail = get_structured_construct_tail(construct); Nodes args = terminator->payload.merge_selection.args; add_branch_phis(emitter, fn_builder, basic_block_builder, tail, args); @@ -224,7 +231,8 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi case MergeContinue_TAG: { MergeContinue payload = terminator->payload.merge_continue; spv_emit_mem(emitter, fn_builder, payload.mem); - const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_Loop_TAG); + const Node* construct = find_construct(emitter, fn_builder, abs, LoopConstruct); + assert(construct); Loop loop_payload = construct->payload.loop_instr; CFNode* loop_body = cfg_lookup(fn_builder->cfg, loop_payload.body); assert(loop_body); @@ -236,7 +244,8 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi case MergeBreak_TAG: { MergeBreak payload = terminator->payload.merge_break; spv_emit_mem(emitter, fn_builder, payload.mem); - const Node* construct = find_construct(emitter, fn_builder, abs, Structured_construct_Loop_TAG); + const Node* construct = find_construct(emitter, fn_builder, abs, LoopConstruct); + assert(construct); Loop loop_payload = construct->payload.loop_instr; Nodes args = terminator->payload.merge_break.args; add_branch_phis(emitter, fn_builder, basic_block_builder, loop_payload.tail, args); From 4038683da7d541284c2c61060d44962214b93a80 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 16:25:21 +0200 Subject: [PATCH 578/693] add 'static' to loose functions in vec_mat.h --- vcc-std/include/shady_mat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vcc-std/include/shady_mat.h b/vcc-std/include/shady_mat.h index bdaabce7d..4500fed96 100644 --- a/vcc-std/include/shady_mat.h +++ b/vcc-std/include/shady_mat.h @@ -164,7 +164,7 @@ static const Mat3f identity_mat3f = { 0, 0, 1, }; -Mat3f transpose_mat3f(Mat3f src) { +static Mat3f transpose_mat3f(Mat3f src) { return (Mat3f) { src.m00, src.m10, src.m20, src.m01, src.m11, src.m21, @@ -172,7 +172,7 @@ Mat3f transpose_mat3f(Mat3f src) { }; } -Mat3f mul_mat3f(Mat3f l, Mat3f r) { +static Mat3f mul_mat3f(Mat3f l, Mat3f r) { Mat3f dst = { 0 }; #define a(i, j) m##i##j #define t(bc, br, i) l.a(i, br) * r.a(bc, i) From bc760e002ad81b40cad26972ce692c2b3ef64b35 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 16:41:51 +0200 Subject: [PATCH 579/693] cfg: improved configuration mechanism --- src/shady/analysis/cfg.c | 46 +++++++++++++++++------------------ src/shady/analysis/cfg.h | 22 ++++++++++++----- src/shady/analysis/cfg_dump.c | 4 +-- src/shady/analysis/looptree.c | 2 +- src/shady/analysis/verify.c | 4 +-- src/shady/print.c | 3 ++- 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index b74dd43d5..f68b922f6 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -35,11 +35,10 @@ typedef struct { Arena* arena; const Node* function; const Node* entry; - LoopTree* lt; struct Dict* nodes; struct List* contents; - bool include_structured_tails; + CFGBuildConfig config; const Node* selection_construct_tail; const Node* loop_construct_head; @@ -116,9 +115,9 @@ static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFE assert(is_abstraction(src) && is_abstraction(dst)); assert(term && is_terminator(term)); assert(!is_function(dst)); - if (ctx->lt && !in_loop(ctx->lt, ctx->function, ctx->entry, dst)) + if (ctx->config.lt && !in_loop(ctx->config.lt, ctx->function, ctx->entry, dst)) return; - if (ctx->lt && dst == ctx->entry) { + if (ctx->config.lt && dst == ctx->entry) { return; } @@ -179,14 +178,8 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_jump_edge(ctx, abs, terminator->payload.br_switch.default_jump); return; } - case Join_TAG: { - const Node** dst = find_value_dict(const Node*, const Node*, ctx->join_point_values, terminator->payload.join.join_point); - if (dst) - add_edge(ctx, node->node, *dst, StructuredLeaveBodyEdge, terminator); - return; - } case If_TAG: { - if (ctx->include_structured_tails) + if (ctx->config.include_structured_tails) add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); CfgBuildContext if_ctx = *ctx; if_ctx.selection_construct_tail = get_structured_construct_tail(terminator); @@ -198,7 +191,7 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { return; } case Match_TAG: { - if (ctx->include_structured_tails) + if (ctx->config.include_structured_tails) add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); CfgBuildContext match_ctx = *ctx; match_ctx.selection_construct_tail = get_structured_construct_tail(terminator); @@ -207,7 +200,7 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_structural_edge(&match_ctx, node, terminator->payload.match_instr.default_case, StructuredEnterBodyEdge, terminator); return; } case Loop_TAG: { - if (ctx->include_structured_tails) + if (ctx->config.include_structured_tails) add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); CfgBuildContext loop_ctx = *ctx; loop_ctx.loop_construct_head = terminator->payload.loop_instr.body; @@ -220,22 +213,30 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { const Node* tail = get_structured_construct_tail(terminator); insert_dict(const Node*, const Node*, ctx->join_point_values, param, tail); add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge, terminator); - if (ctx->include_structured_tails) + if (ctx->config.include_structured_tails) add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); return; + } case Join_TAG: { + if (ctx->config.include_structured_exits) { + const Node** dst = find_value_dict(const Node*, const Node*, ctx->join_point_values, terminator->payload.join.join_point); + if (dst) + add_edge(ctx, node->node, *dst, StructuredLeaveBodyEdge, terminator); + } + return; } case MergeSelection_TAG: { assert(ctx->selection_construct_tail); - add_structural_edge(ctx, node, ctx->selection_construct_tail, StructuredLeaveBodyEdge, terminator); + if (ctx->config.include_structured_exits) + add_structural_edge(ctx, node, ctx->selection_construct_tail, StructuredLeaveBodyEdge, terminator); return; - } - case MergeContinue_TAG:{ + } case MergeContinue_TAG:{ assert(ctx->loop_construct_head); - add_structural_edge(ctx, node, ctx->loop_construct_head, StructuredLoopContinue, terminator); + if (ctx->config.include_structured_exits) + add_structural_edge(ctx, node, ctx->loop_construct_head, StructuredLoopContinue, terminator); return; - } - case MergeBreak_TAG: { + } case MergeBreak_TAG: { assert(ctx->loop_construct_tail); - add_structural_edge(ctx, node, ctx->loop_construct_tail, StructuredLeaveBodyEdge, terminator); + if (ctx->config.include_structured_exits) + add_structural_edge(ctx, node, ctx->loop_construct_tail, StructuredLeaveBodyEdge, terminator); return; } case TailCall_TAG: @@ -380,11 +381,10 @@ CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { .arena = arena, .function = function, .entry = entry, - .lt = config.lt, .nodes = new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), .join_point_values = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), .contents = new_list(CFNode*), - .include_structured_tails = config.include_structured_tails, + .config = config, }; CFNode* entry_node = get_or_enqueue(&context, entry); diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index f16132c70..897472e52 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -62,6 +62,7 @@ typedef struct Arena_ Arena; typedef struct LoopTree_ LoopTree; typedef struct { + bool include_structured_exits; bool include_structured_tails; LoopTree* lt; bool flipped; @@ -103,26 +104,35 @@ CFG* build_cfg(const Node* fn, const Node* entry, CFGBuildConfig); * Dominance will only be computed with respect to the nodes reachable by @p entry. */ -static inline CFGBuildConfig forward_cfg_build(bool include_structured_tails) { +static inline CFGBuildConfig default_forward_cfg_build(void) { return (CFGBuildConfig) { - .include_structured_tails = include_structured_tails, + .include_structured_exits = true, + .include_structured_tails = true, }; } -static inline CFGBuildConfig flipped_cfg_build(bool include_structured_tails) { + +static inline CFGBuildConfig structured_scope_cfg_build(void) { + return (CFGBuildConfig) { + .include_structured_exits = false, + .include_structured_tails = true, + }; +} + +static inline CFGBuildConfig flipped_cfg_build(void) { return (CFGBuildConfig) { - .include_structured_tails = include_structured_tails, + //.include_structured_tails = include_structured_tails, .lt = NULL, .flipped = true, }; } -#define build_fn_cfg(node) build_cfg(node, node, forward_cfg_build(true)) +#define build_fn_cfg(node) build_cfg(node, node, default_forward_cfg_build()) /** Construct the CFG stating in Node. * Dominance will only be computed with respect to the nodes reachable by @p entry. * This CFG will contain post dominance information instead of regular dominance! */ -#define build_fn_cfg_flipped(node) build_cfg(node, node, flipped_cfg_build(true)) +#define build_fn_cfg_flipped(node) build_cfg(node, node, flipped_cfg_build()) CFNode* cfg_lookup(CFG* cfg, const Node* abs); void compute_rpo(CFG*); diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index d0639f8ea..c55dd78bb 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -153,7 +153,7 @@ void dump_cfgs(FILE* output, Module* mod) { output = stderr; fprintf(output, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); + struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; dump_cfg(output, cfg); @@ -191,7 +191,7 @@ void dump_domtree_cfg(Printer* p, CFG* s) { void dump_domtree_module(Printer* p, Module* mod) { print(p, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); + struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; dump_domtree_cfg(p, cfg); diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index 834eda698..72f5197ea 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -284,7 +284,7 @@ void dump_loop_trees(FILE* output, Module* mod) { output = stderr; fprintf(output, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); + struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; LoopTree* lt = build_loop_tree(cfg); diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 3774568e1..353534b89 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -43,7 +43,7 @@ static void verify_same_arena(Module* mod) { } static void verify_scoping(const CompilerConfig* config, Module* mod) { - struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); + struct List* cfgs = build_cfgs(mod, structured_scope_cfg_build()); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; Scheduler* scheduler = new_scheduler(cfg); @@ -136,7 +136,7 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { } static void verify_bodies(const CompilerConfig* config, Module* mod) { - struct List* cfgs = build_cfgs(mod, forward_cfg_build(true)); + struct List* cfgs = build_cfgs(mod, structured_scope_cfg_build()); for (size_t i = 0; i < entries_count_list(cfgs); i++) { CFG* cfg = read_list(CFG*, cfgs)[i]; diff --git a/src/shady/print.c b/src/shady/print.c index 63d0dd660..72c903fc4 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -305,7 +305,8 @@ static void print_function(PrinterCtx* ctx, const Node* node) { PrinterCtx sub_ctx = *ctx; sub_ctx.fn = node; if (node->arena->config.name_bound) { - CFG* cfg = build_fn_cfg(node); + CFGBuildConfig cfg_config = structured_scope_cfg_build(); + CFG* cfg = build_cfg(node, node, cfg_config); sub_ctx.cfg = cfg; sub_ctx.scheduler = new_scheduler(cfg); sub_ctx.bb_growies = calloc(sizeof(size_t), cfg->size); From b6c74430dbee3a68903ef071d443ef882266dff8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 17:52:14 +0200 Subject: [PATCH 580/693] added a pass to remove critical edges --- src/shady/compile.c | 4 ++- src/shady/passes/CMakeLists.txt | 1 + src/shady/passes/passes.h | 1 + src/shady/passes/remove_critical_edges.c | 40 ++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/shady/passes/remove_critical_edges.c diff --git a/src/shady/compile.c b/src/shady/compile.c index 1427c636e..4d6ccb44e 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -54,7 +54,9 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(lift_everything) RUN_PASS(scope2control) } else if (config->input_cf.restructure_with_heuristics) { - RUN_PASS(lcssa) + RUN_PASS(remove_critical_edges) + // RUN_PASS(lcssa) + RUN_PASS(lift_everything) RUN_PASS(reconvergence_heuristics) } diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index 3aa57b10b..227396f77 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -40,4 +40,5 @@ target_sources(shady PRIVATE scope_heuristic.c reconvergence_heuristics.c lcssa.c + remove_critical_edges.c ) diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 0f76a0aa2..4bf46eda9 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -19,6 +19,7 @@ RewritePass lower_cf_instrs; /// Uses shady.scope annotations to insert control blocks RewritePass scope2control; RewritePass lift_everything; +RewritePass remove_critical_edges; RewritePass lcssa; RewritePass scope_heuristic; /// Try to identify reconvergence points throughout the program for unstructured control flow programs diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c new file mode 100644 index 000000000..025d1cf2c --- /dev/null +++ b/src/shady/passes/remove_critical_edges.c @@ -0,0 +1,40 @@ +#include "shady/pass.h" + +#include "../ir_private.h" +#include "../type.h" +#include "../transform/ir_gen_helpers.h" + +#include "log.h" +#include "portability.h" + +typedef struct { + Rewriter rewriter; +} Context; + +static const Node* process(Context* ctx, const Node* node) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + switch (node->tag) { + case Jump_TAG: { + Jump payload = node->payload.jump; + Node* new_block = basic_block(a, empty(a), NULL); + set_abstraction_body(new_block, jump_helper(a, rewrite_node(r, payload.target), rewrite_nodes(r, payload.args), get_abstraction_mem(new_block))); + return jump_helper(a, new_block, empty(a), rewrite_node(r, payload.mem)); + } + default: break; + } + + return recreate_node_identity(r, node); +} + +Module* remove_critical_edges(SHADY_UNUSED const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + IrArena* a = new_ir_arena(&aconfig); + Module* dst = new_module(a, get_module_name(src)); + Context ctx = { + .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + }; + rewrite_module(&ctx.rewriter); + destroy_rewriter(&ctx.rewriter); + return dst; +} From 7abfe93ee1ada6fda3c337ebddd5804981cf11a6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 17:52:28 +0200 Subject: [PATCH 581/693] cleaned up reconvergence_heuristics, fix uniform params --- src/shady/passes/reconvergence_heuristics.c | 80 ++++++++++++++------- 1 file changed, 55 insertions(+), 25 deletions(-) diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 8813eecf0..82210b872 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -18,6 +18,7 @@ typedef struct Context_ { Rewriter rewriter; const CompilerConfig* config; + Arena* arena; const Node* current_fn; const Node* current_abstraction; CFG* fwd_cfg; @@ -74,6 +75,18 @@ static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, } } +typedef struct { + const Node* alloca; + bool uniform; +} ExitValue; + +typedef struct { + ExitValue* params; + size_t params_count; + + Node* wrapper; +} Exit; + static const Node* process_abstraction(Context* ctx, const Node* node) { assert(node && is_abstraction(node)); Context new_context = *ctx; @@ -117,14 +130,20 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { BodyBuilder* outer_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_container)); Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); - LARRAY(Nodes, exit_param_allocas, exiting_nodes_count); + LARRAY(Exit, exits, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; Nodes exit_param_types = rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); - LARRAY(const Node*, exit_param_allocas_tmp, exit_param_types.count); - for (size_t j = 0; j < exit_param_types.count; j++) - exit_param_allocas_tmp[j] = gen_stack_alloc(outer_bb, get_unqualified_type(exit_param_types.nodes[j])); - exit_param_allocas[i] = nodes(arena, exit_param_types.count, exit_param_allocas_tmp); + + ExitValue* exit_params = arena_alloc(ctx->arena, sizeof(ExitValue) * exit_param_types.count); + for (size_t j = 0; j < exit_param_types.count; j++) { + exit_params[j].alloca = gen_stack_alloc(outer_bb, get_unqualified_type(exit_param_types.nodes[j])); + exit_params[j].uniform = is_qualified_type_uniform(exit_param_types.nodes[j]); + } + exits[i] = (Exit) { + .params = exit_params, + .params_count = exit_param_types.count, + }; } const Node* exit_destination_alloca = NULL; @@ -139,18 +158,13 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .yield_types = inner_yield_types }), true), "jp_continue"); - LARRAY(Node*, exit_wrappers, exiting_nodes_count); - LARRAY(Node*, exit_helpers, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { - exit_helpers[i] = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_helper_%d", i)); - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); - Node* pre_join_exit_bb = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); - set_abstraction_body(pre_join_exit_bb, jump_helper(arena, exit_helpers[i], empty(arena), get_abstraction_mem(pre_join_exit_bb))); - exit_wrappers[i] = pre_join_exit_bb; + Node* wrapper = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); + exits[i].wrapper = wrapper; } Nodes continue_wrapper_params = recreate_params(rewriter, get_abstraction_params(node)); @@ -169,7 +183,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { cached_exits[i] = search_processed(rewriter, exiting_node->node); if (cached_exits[i]) remove_dict(const Node*, rewriter->map, exiting_node->node); - register_processed(rewriter, exiting_node->node, exit_wrappers[i]); + register_processed(rewriter, exiting_node->node, exits[i].wrapper); } // ditto for the loop entry and the continue wrapper const Node** cached_entry = search_processed(rewriter, node); @@ -194,15 +208,16 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); - Nodes exit_wrapper_params = get_abstraction_params(exit_wrappers[i]); - BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_helpers[i])); + Nodes exit_wrapper_params = get_abstraction_params(exits[i].wrapper); + BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(exits[i].wrapper)); - for (size_t j = 0; j < exit_param_allocas[i].count; j++) - gen_store(exit_wrapper_bb, exit_param_allocas[i].nodes[j], exit_wrapper_params.nodes[j]); + for (size_t j = 0; j < exits[i].params_count; j++) + gen_store(exit_wrapper_bb, exits[i].params[j].alloca, exit_wrapper_params.nodes[j]); + // Set the destination if there's more than one option if (exiting_nodes_count > 1) gen_store(exit_wrapper_bb, exit_destination_alloca, int32_literal(arena, i)); - set_abstraction_body(exit_helpers[i], finish_body_with_join(exit_wrapper_bb, join_token_exit, empty(arena))); + set_abstraction_body(exits[i].wrapper, finish_body_with_join(exit_wrapper_bb, join_token_exit, empty(arena))); } set_abstraction_body(inner_control_case, loop_body); @@ -224,7 +239,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); BodyBuilder* inner_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_outer)); Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); - + // make sure what was uniform still is + for (size_t j = 0; j < inner_control_results.count; j++) { + if (is_qualified_type_uniform(nparams.nodes[j]->type)) + inner_control_results = change_node_at_index(arena, inner_control_results, j, prim_op_helper(arena, subgroup_assume_uniform_op, empty(arena), singleton(inner_control_results.nodes[j]))); + } set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); Node* outer_control_case = case_(arena, singleton(join_token_exit)); set_abstraction_body(outer_control_case, jump(arena, (Jump) { @@ -244,12 +263,15 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { const Node* recreated_exit = rewrite_node(rewriter, exiting_node->node); - LARRAY(const Node*, recovered_args, exit_param_allocas[i].count); - for (size_t j = 0; j < exit_param_allocas[i].count; j++) - recovered_args[j] = gen_load(exit_recover_bb, exit_param_allocas[i].nodes[j]); + LARRAY(const Node*, recovered_args, exits[i].params_count); + for (size_t j = 0; j < exits[i].params_count; j++) { + recovered_args[j] = gen_load(exit_recover_bb, exits[i].params[j].alloca); + if (exits[i].params[j].uniform) + recovered_args[j] = prim_op_helper(arena, subgroup_assume_uniform_op, empty(arena), singleton(recovered_args[j])); + } exit_numbers[i] = int32_literal(arena, i); - set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, nodes(arena, exit_param_allocas[i].count, recovered_args))); + set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, nodes(arena, exits[i].params_count, recovered_args))); exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena), bb_mem(outer_bb)); } @@ -379,12 +401,13 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes exit_args; Nodes old_params = get_abstraction_params(post_dominator); + LARRAY(bool, uniform_param, old_params.count); if (old_params.count == 0) { yield_types = empty(a); exit_args = empty(a); } else { - LARRAY(const Node*, types,old_params.count); + LARRAY(const Node*, types, old_params.count); LARRAY(const Node*, inner_args,old_params.count); for (size_t j = 0; j < old_params.count; j++) { @@ -396,7 +419,7 @@ static const Node* process_node(Context* ctx, const Node* node) { //This should always contain a qualified type? //if (contains_qualified_type(types[j])) types[j] = get_unqualified_type(qualified_type); - + uniform_param[j] = is_qualified_type_uniform(qualified_type); inner_args[j] = param(a, qualified_type, old_params.nodes[j]->payload.param.name); } @@ -441,6 +464,11 @@ static const Node* process_node(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); Nodes results = gen_control(bb, yield_types, control_case); + // make sure what was uniform still is + for (size_t j = 0; j < old_params.count; j++) { + if (uniform_param[j]) + results = change_node_at_index(a, results, j, prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(results.nodes[j]))); + } return finish_body_with_jump(bb, join_target, results); } default: break; @@ -461,9 +489,11 @@ Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { .fwd_cfg = NULL, .rev_cfg = NULL, .current_looptree = NULL, + .arena = new_arena(), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); + destroy_arena(ctx.arena); return dst; } From 25001c055cd6802a75f83c84354b758b614e4b14 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 11 Sep 2024 20:36:09 +0200 Subject: [PATCH 582/693] make generic address tags 3-bit wide and reserve 000 and 111 for Global --- src/shady/passes/lower_generic_ptrs.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 7a74d355e..fec30259e 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -19,9 +19,15 @@ typedef struct { const CompilerConfig* config; } Context; -static AddressSpace generic_ptr_tags[4] = { AsGlobal, AsShared, AsSubgroup, AsPrivate }; +static AddressSpace generic_ptr_tags[8] = { + [0x0] = AsGlobal, + [0x1] = AsShared, + [0x2] = AsSubgroup, + [0x3] = AsPrivate, + [0x7] = AsGlobal +}; -static size_t generic_ptr_tag_bitwidth = 2; +static size_t generic_ptr_tag_bitwidth = 3; static AddressSpace get_addr_space_from_tag(size_t tag) { size_t max_tag = sizeof(generic_ptr_tags) / sizeof(generic_ptr_tags[0]); @@ -61,6 +67,9 @@ static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t } static bool allowed(Context* ctx, AddressSpace as) { + // some tags aren't in use + if (as == AsGeneric) + return false; // if an address space is logical-only, or isn't allowed at all in the module, we can skip emitting a case for it. if (!ctx->rewriter.dst_arena->config.address_spaces[as].physical || !ctx->rewriter.dst_arena->config.address_spaces[as].allowed) return false; From c963dfff0859ded8047e8194358965f8d35f4577 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 12 Sep 2024 15:01:45 +0200 Subject: [PATCH 583/693] fix broken global variable initialisation --- src/frontend/llvm/l2s_annotations.c | 18 ++++++++++++++++-- src/shady/passes/lower_physical_ptrs.c | 8 +++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 34ed653e9..342245fa1 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -48,6 +48,18 @@ static const Node* look_past_stuff(const Node* thing) { return thing; } +static bool is_io_as(AddressSpace as) { + switch (as) { + case AsInput: + case AsUInput: + case AsOutput: + case AsUniform: + case AsUniformConstant: return true; + default: break; + } + return false; +} + void process_llvm_annotations(Parser* p, LLVMValueRef global) { IrArena* a = get_module_arena(p->dst); const Type* t = convert_type(p, LLVMGlobalGetValueType(global)); @@ -132,11 +144,13 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { }); } else if (strcmp(keyword, "extern") == 0) { assert(target->tag == GlobalVariable_TAG); - ((Node*) target)->payload.global_variable.init = NULL; + AddressSpace as = convert_llvm_address_space(strtol(strtok(NULL, "::"), NULL, 10)); + if (is_io_as(as)) + ((Node*) target)->payload.global_variable.init = NULL; add_annotation(p, target, (ParsedAnnotation) { .payload = annotation_value(a, (AnnotationValue) { .name = "AddressSpace", - .value = int32_literal(a, convert_llvm_address_space(strtol(strtok(NULL, "::"), NULL, 10))) + .value = int32_literal(a, as) }) }); } else { diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index c1405ea92..217473a07 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -430,15 +430,17 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect } static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, BodyBuilder* bb) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; IrArena* oa = ctx->rewriter.src_arena; for (size_t i = 0; i < collected.count; i++) { const Node* old_decl = collected.nodes[i]; assert(old_decl->tag == GlobalVariable_TAG); const Node* old_init = old_decl->payload.global_variable.init; if (old_init) { - error("TODO: reimplement") - // const Node* old_store = store(oa, (Store) { .ptr = ref_decl_helper(oa, old_decl), .value = old_init, bb_mem(bb) }); - // bind_instruction(bb, rewrite_node(&ctx->rewriter, old_store)); + const Node* value = rewrite_node(r, old_init); + const Node* fn = gen_serdes_fn(ctx, get_unqualified_type(value->type), false, true, old_decl->payload.global_variable.address_space); + gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, rewrite_node(r, ref_decl_helper(oa, old_decl)), value)); } } } From f2c7f46fc02e2cca650aa8faf4527e14178eff94 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 12 Sep 2024 15:01:59 +0200 Subject: [PATCH 584/693] fix broken lowering in lower_physical_ptrs --- src/shady/passes/lower_physical_ptrs.c | 42 ++++++++++++-------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 217473a07..56155145b 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -54,13 +54,13 @@ static const Node** get_emulated_as_word_array(Context* ctx, AddressSpace as) { } } -static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type* element_type, const Node* arr, const Node* base_offset) { +static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type* element_type, const Node* arr, const Node* address) { IrArena* a = ctx->rewriter.dst_arena; const CompilerConfig* config = ctx->config; const Node* zero = size_t_literal(a, 0); switch (element_type->tag) { case Bool_TAG: { - const Node* logical_ptr = gen_lea(bb, arr, zero, singleton(base_offset)); + const Node* logical_ptr = gen_lea(bb, arr, zero, singleton(address)); const Node* value = gen_load(bb, logical_ptr); return gen_primop_ce(bb, neq_op, 2, (const Node*[]) {value, int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size })}); } @@ -68,7 +68,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type case AsGlobal: { // TODO: add a per-as size configuration const Type* ptr_int_t = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false }); - const Node* unsigned_int = gen_deserialisation(ctx, bb, ptr_int_t, arr, base_offset); + const Node* unsigned_int = gen_deserialisation(ctx, bb, ptr_int_t, arr, address); return gen_reinterpret_cast(bb, element_type, unsigned_int); } default: error("TODO") @@ -78,7 +78,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* acc = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); size_t length_in_bytes = int_size_in_bytes(element_type->payload.int_type.width); size_t word_size_in_bytes = int_size_in_bytes(a->config.memory.word_size); - const Node* offset = base_offset; + const Node* offset = bytes_to_words(bb, address); const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { @@ -96,14 +96,14 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* widened = acc; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, uint32_type(a), acc); - gen_debug_printf(bb, template, mk_nodes(a, widened, base_offset)); + gen_debug_printf(bb, template, mk_nodes(a, widened, address)); } acc = gen_reinterpret_cast(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = element_type->payload.int_type.is_signed }), acc);\ return acc; } case Float_TAG: { const Type* unsigned_int_t = int_type(a, (Int) {.width = float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); - const Node* unsigned_int = gen_deserialisation(ctx, bb, unsigned_int_t, arr, base_offset); + const Node* unsigned_int = gen_deserialisation(ctx, bb, unsigned_int_t, arr, address); return gen_reinterpret_cast(bb, element_type, unsigned_int); } case TypeDeclRef_TAG: @@ -115,8 +115,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type LARRAY(const Node*, loaded, member_types.count); for (size_t i = 0; i < member_types.count; i++) { const Node* field_offset = gen_primop_e(bb, offset_of_op, singleton(element_type), singleton(size_t_literal(a, i))); - field_offset = bytes_to_words(bb, field_offset); - const Node* adjusted_offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, base_offset, field_offset)); + const Node* adjusted_offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, address, field_offset)); loaded[i] = gen_deserialisation(ctx, bb, member_types.nodes[i], arr, adjusted_offset); } return composite_helper(a, element_type, nodes(a, member_types.count, loaded)); @@ -132,7 +131,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type size_t components_count = get_int_literal_value(*resolve_to_int_literal(size), 0); const Type* component_type = get_fill_type_element_type(element_type); LARRAY(const Node*, components, components_count); - const Node* offset = base_offset; + const Node* offset = address; for (size_t i = 0; i < components_count; i++) { components[i] = gen_deserialisation(ctx, bb, component_type, arr, offset); offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, singleton(component_type), empty(a)))); @@ -143,13 +142,13 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type } } -static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element_type, const Node* arr, const Node* base_offset, const Node* value) { +static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element_type, const Node* arr, const Node* address, const Node* value) { IrArena* a = ctx->rewriter.dst_arena; const CompilerConfig* config = ctx->config; const Node* zero = size_t_literal(a, 0); switch (element_type->tag) { case Bool_TAG: { - const Node* logical_ptr = gen_lea(bb, arr, zero, singleton(base_offset)); + const Node* logical_ptr = gen_lea(bb, arr, zero, singleton(address)); const Node* zero_b = int_literal(a, (IntLiteral) { .value = 1, .width = a->config.memory.word_size }); const Node* one_b = int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size }); const Node* int_value = gen_primop_ce(bb, select_op, 3, (const Node*[]) { value, one_b, zero_b }); @@ -160,7 +159,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element case AsGlobal: { const Type* ptr_int_t = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false }); const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, singleton(ptr_int_t), singleton(value)); - return gen_serialisation(ctx, bb, ptr_int_t, arr, base_offset, unsigned_value); + return gen_serialisation(ctx, bb, ptr_int_t, arr, address, unsigned_value); } default: error("TODO") } @@ -173,7 +172,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element // const Node* acc = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); size_t length_in_bytes = int_size_in_bytes(element_type->payload.int_type.width); size_t word_size_in_bytes = int_size_in_bytes(a->config.memory.word_size); - const Node* offset = base_offset; + const Node* offset = bytes_to_words(bb, address); const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { @@ -200,22 +199,21 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* widened = value; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, uint32_type(a), value); - gen_debug_printf(bb, template, mk_nodes(a, widened, base_offset)); + gen_debug_printf(bb, template, mk_nodes(a, widened, address)); } return; } case Float_TAG: { const Type* unsigned_int_t = int_type(a, (Int) {.width = float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, singleton(unsigned_int_t), singleton(value)); - return gen_serialisation(ctx, bb, unsigned_int_t, arr, base_offset, unsigned_value); + return gen_serialisation(ctx, bb, unsigned_int_t, arr, address, unsigned_value); } case RecordType_TAG: { Nodes member_types = element_type->payload.record_type.members; for (size_t i = 0; i < member_types.count; i++) { const Node* extracted_value = prim_op(a, (PrimOp) { .op = extract_op, .operands = mk_nodes(a, value, int32_literal(a, i)), .type_arguments = empty(a) }); const Node* field_offset = gen_primop_e(bb, offset_of_op, singleton(element_type), singleton(size_t_literal(a, i))); - field_offset = bytes_to_words(bb, field_offset); - const Node* adjusted_offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, base_offset, field_offset)); + const Node* adjusted_offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, address, field_offset)); gen_serialisation(ctx, bb, member_types.nodes[i], arr, adjusted_offset, extracted_value); } return; @@ -223,7 +221,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element case TypeDeclRef_TAG: { const Node* nom = element_type->payload.type_decl_ref.decl; assert(nom && nom->tag == NominalType_TAG); - gen_serialisation(ctx, bb, nom->payload.nom_type.body, arr, base_offset, value); + gen_serialisation(ctx, bb, nom->payload.nom_type.body, arr, address, value); return; } case ArrType_TAG: @@ -236,7 +234,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element } size_t components_count = get_int_literal_value(*resolve_to_int_literal(size), 0); const Type* component_type = get_fill_type_element_type(element_type); - const Node* offset = base_offset; + const Node* offset = address; for (size_t i = 0; i < components_count; i++) { gen_serialisation(ctx, bb, component_type, arr, offset, gen_extract(bb, value, singleton(int32_literal(a, i)))); offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, singleton(component_type), empty(a)))); @@ -277,13 +275,12 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un insert_dict(const Node*, Node*, cache, element_type, fun); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); - const Node* address = bytes_to_words(bb, address_param); const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { - gen_serialisation(ctx, bb, element_type, base, address, value_param); + gen_serialisation(ctx, bb, element_type, base, address_param, value_param); set_abstraction_body(fun, finish_body_with_return(bb, empty(a))); } else { - const Node* loaded_value = gen_deserialisation(ctx, bb, element_type, base, address); + const Node* loaded_value = gen_deserialisation(ctx, bb, element_type, base, address_param); assert(loaded_value); set_abstraction_body(fun, finish_body_with_return(bb, singleton(loaded_value))); } @@ -413,7 +410,6 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect // after lower_memory_layout, optimisations will eliminate this and resolve to a value BodyBuilder* bb = begin_block_pure(a); const Node* offset = gen_primop_e(bb, offset_of_op, singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), singleton(size_t_literal(a, i))); - // const Node* offset_in_words = bytes_to_words(bb, offset); new_address->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(offset)); register_processed(&ctx->rewriter, decl, new_address); From 3bd459b0a00d7af831d38fbdc0dff8c0c6f236c6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 12 Sep 2024 22:00:27 +0200 Subject: [PATCH 585/693] work towards fixing fn_pointers --- src/frontend/llvm/l2s.c | 2 ++ src/frontend/llvm/l2s_instr.c | 6 +++- src/shady/fold.c | 16 +++++++++++ src/shady/passes/lower_tailcalls.c | 43 ++++++++++++++++++++-------- src/shady/transform/ir_gen_helpers.c | 2 +- 5 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 634c2adcd..5b194409d 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -185,6 +185,8 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { .jumps_todo = new_list(JumpTodo), }; const Node* r = fn_addr_helper(a, f); + r = prim_op_helper(a, reinterpret_op, singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = unit_type(a) })), singleton(r)); + //r = prim_op_helper(a, convert_op, singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = unit_type(a) })), singleton(r)); insert_dict(LLVMValueRef, const Node*, p->map, fn, r); size_t bb_count = LLVMCountBasicBlocks(fn); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index b34cb6349..416c55f2b 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -445,6 +445,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Node* r = NULL; unsigned num_args = LLVMGetNumArgOperands(instr); LLVMValueRef callee = LLVMGetCalledValue(instr); + LLVMTypeRef callee_type = LLVMGetCalledFunctionType(instr); callee = remove_ptr_bitcasts(p, callee); assert(num_args + 1 == num_ops); String intrinsic = NULL; @@ -590,7 +591,10 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B Nodes ops = convert_operands(p, num_ops, instr); r = bind_instruction_single(b, call(a, (Call) { .mem = bb_mem(b), - .callee = ops.nodes[num_args], + .callee = prim_op_helper(a, reinterpret_op, singleton(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = convert_type(p, callee_type) + })), singleton(ops.nodes[num_args])), .args = nodes(a, num_args, ops.nodes), })); } diff --git a/src/shady/fold.c b/src/shady/fold.c index c840255bd..f06bfc55a 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -287,6 +287,22 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { r = ptr_array_element_offset(arena, payload); break; } + case Call_TAG: { + Call payload = node->payload.call; + const Node* nptr = simplify_ptr_operand(arena, payload.callee); + if (!nptr) break; + payload.callee = nptr; + r = call(arena, payload); + break; + } + case TailCall_TAG: { + TailCall payload = node->payload.tail_call; + const Node* nptr = simplify_ptr_operand(arena, payload.callee); + if (!nptr) break; + payload.callee = nptr; + r = tail_call(arena, payload); + break; + } default: return node; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 1a29d007f..bcfa3254e 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -36,22 +36,35 @@ typedef struct Context_ { static const Node* process(Context* ctx, const Node* old); -static const Node* fn_ptr_as_value(IrArena* a, FnPtr ptr) { - return uint32_literal(a, ptr); +static const Type* lowered_fn_type(Context* ctx) { + IrArena* a = ctx->rewriter.dst_arena; + return int_type_helper(a, false, ctx->config->target.memory.ptr_size); } -static const Node* lower_fn_addr(Context* ctx, const Node* the_function) { +static const Node* fn_ptr_as_value(Context* ctx, FnPtr ptr) { IrArena* a = ctx->rewriter.dst_arena; + return int_literal(a, (IntLiteral) { + .is_signed = false, + .width = ctx->config->target.memory.ptr_size, + .value = ptr + }); +} + +static FnPtr get_fn_ptr(Context* ctx, const Node* the_function) { assert(the_function->arena == ctx->rewriter.src_arena); assert(the_function->tag == Function_TAG); FnPtr* found = find_value_dict(const Node*, FnPtr, ctx->assigned_fn_ptrs, the_function); - if (found) return fn_ptr_as_value(a, *found); + if (found) return *found; FnPtr ptr = (*ctx->next_fn_ptr)++; bool r = insert_dict_and_get_result(const Node*, FnPtr, ctx->assigned_fn_ptrs, the_function, ptr); assert(r); - return fn_ptr_as_value(a, ptr); + return ptr; +} + +static const Node* lower_fn_addr(Context* ctx, const Node* the_function) { + return fn_ptr_as_value(ctx, get_fn_ptr(ctx, the_function)); } /// Turn a function into a top-level entry point, calling into the top dispatch function. @@ -75,8 +88,8 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { // Initialise next_fn/next_mask to the entry function const Node* jump_fn = access_decl(&ctx->rewriter, "builtin_fork"); - const Node* fn_addr = lower_fn_addr(ctx, old); - fn_addr = gen_conversion(bb, uint32_type(a), fn_addr); + const Node* fn_addr = uint32_literal(a, get_fn_ptr(ctx, old)); + // fn_addr = gen_conversion(bb, lowered_fn_type(ctx), fn_addr); gen_call(bb, jump_fn, singleton(fn_addr)); if (!*ctx->top_dispatcher_fn) { @@ -171,14 +184,20 @@ static const Node* process(Context* ctx, const Node* old) { ExtInstr payload = old->payload.ext_instr; if (strcmp(payload.set, "shady.internal") == 0) { String callee_name = NULL; + Nodes args = rewrite_nodes(r, payload.operands); switch ((ShadyJoinPointOpcodes ) payload.opcode) { - case ShadyOpDefaultJoinPoint: callee_name = "builtin_entry_join_point"; break; - case ShadyOpCreateJoinPoint: callee_name = "builtin_create_control_point"; break; + case ShadyOpDefaultJoinPoint: + callee_name = "builtin_entry_join_point"; + break; + case ShadyOpCreateJoinPoint: + callee_name = "builtin_create_control_point"; + args = change_node_at_index(a, args, 0, prim_op_helper(a, convert_op, singleton(uint32_type(a)), singleton(args.nodes[0]))); + break; } return call(a, (Call) { .mem = rewrite_node(r, payload.mem), .callee = access_decl(r, callee_name), - .args = rewrite_nodes(r, payload.operands), + .args = args, }); } break; @@ -360,7 +379,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { if (lookup_annotation(decl, "Leaf")) continue; - const Node* fn_lit = lower_fn_addr(ctx, decl); + const Node* fn_lit = uint32_literal(a, get_fn_ptr(ctx, decl)); Node* if_true_case = case_(a, empty(a)); BodyBuilder* if_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); @@ -369,7 +388,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } gen_call(if_builder, fn_addr_helper(a, rewrite_node(&ctx->rewriter, decl)), empty(a)); - set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, empty(a))); + set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); Node* if_false = case_(a, empty(a)); set_abstraction_body(if_false, join(a, (Join) { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 80a8f1ac8..e89576697 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -141,7 +141,7 @@ void gen_comment(BodyBuilder* bb, String str) { } void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { - bind_instruction(bb, debug_printf(bb->arena, (DebugPrintf) { .string = pattern, .args = args, .mem = bb_mem(bb) })); + bind_instruction_single(bb, debug_printf(bb->arena, (DebugPrintf) { .string = pattern, .args = args, .mem = bb_mem(bb) })); } const Node* get_builtin(Module* m, Builtin b) { From 595cde36afb700351d5b039d8e541e1fdcb34191 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 23 Sep 2024 20:39:23 +0200 Subject: [PATCH 586/693] fix inconsistent types in l2s_instr --- src/frontend/llvm/l2s_instr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 416c55f2b..ec0869b2e 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -59,12 +59,12 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, LLVMBasicBlockRef dst, const Node* mem) { IrArena* a = fn_ctx->fn->arena; const Node* dst_bb = convert_basic_block_body(p, fn_ctx, dst); - BBPhis* phis = find_value_dict(const Node*, BBPhis, fn_ctx->phis, dst_bb); + struct List* phis = *find_value_dict(const Node*, struct List*, fn_ctx->phis, dst_bb); assert(phis); - size_t params_count = entries_count_list(phis->list); + size_t params_count = entries_count_list(phis); LARRAY(const Node*, params, params_count); for (size_t i = 0; i < params_count; i++) { - LLVMValueRef phi = read_list(LLVMValueRef, phis->list)[i]; + LLVMValueRef phi = read_list(LLVMValueRef, phis)[i]; for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { if (convert_basic_block_header(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == src) { params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); From 51d43f6a47cddc60838e80bccc96773777b00ba0 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Tue, 24 Sep 2024 11:22:00 +0200 Subject: [PATCH 587/693] remove compile.h, move it's functionality elsewhere --- include/shady/pass.h | 6 ++++++ src/backend/c/emit_c.c | 2 +- src/backend/spirv/emit_spv.c | 2 +- src/frontend/slim/slim_driver.c | 4 +++- src/shady/compile.c | 25 +++++++++++++++++++++++-- src/shady/compile.h | 19 ------------------- src/shady/passes/cleanup.c | 12 ------------ 7 files changed, 34 insertions(+), 36 deletions(-) delete mode 100644 src/shady/compile.h diff --git a/include/shady/pass.h b/include/shady/pass.h index e2bfc7c22..8556600f6 100644 --- a/include/shady/pass.h +++ b/include/shady/pass.h @@ -7,5 +7,11 @@ typedef Module* (RewritePass)(const CompilerConfig* config, Module* src); typedef bool (OptPass)(const CompilerConfig* config, Module** m); +void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name); +#define RUN_PASS(pass_name) run_pass_impl(config, pmod, initial_arena, pass_name, #pass_name); + +void apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPass pass, String pass_name); +#define APPLY_OPT(pass_name) apply_opt_impl(config, &todo, &m, pass_name, #pass_name); + #endif diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index f0ee5af6f..0a736edf6 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -2,8 +2,8 @@ #include "../shady/type.h" #include "../shady/ir_private.h" -#include "../shady/compile.h" #include "../shady/transform/ir_gen_helpers.h" +#include "../shady/passes/passes.h" #include "../shady/analysis/cfg.h" #include "../shady/analysis/scheduler.h" diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 6c31660cd..67879935c 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -4,8 +4,8 @@ #include "../shady/ir_private.h" #include "../shady/analysis/cfg.h" +#include "../shady/passes/passes.h" #include "../shady/type.h" -#include "../shady/compile.h" #include "list.h" #include "dict.h" diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index 67e565e02..fd8af59d3 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -1,9 +1,11 @@ -#include "compile.h" #include "parser.h" #include "shady/pass.h" #include "../shady/transform/internal_constants.h" +#include "../shady/passes/passes.h" + +#include "log.h" /// Removes all Unresolved nodes and replaces them with the appropriate decl/value RewritePass bind_program; diff --git a/src/shady/compile.c b/src/shady/compile.c index 4d6ccb44e..1d94aa3d6 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -1,11 +1,16 @@ +#include "ir_private.h" #include "shady/driver.h" -#include "compile.h" +#include "shady/ir.h" + +#include "passes/passes.h" +#include "analysis/verify.h" #include "../frontend/slim/parser.h" #include "shady_scheduler_src.h" #include "transform/internal_constants.h" -#include "ir_private.h" + #include "util.h" +#include "log.h" #include @@ -19,6 +24,12 @@ void add_scheduler_source(const CompilerConfig* config, Module* dst) { destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); } +#ifdef NDEBUG +#define SHADY_RUN_VERIFY 0 +#else +#define SHADY_RUN_VERIFY 1 +#endif + void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name) { Module* old_mod = NULL; old_mod = *pmod; @@ -41,6 +52,16 @@ void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial config->hooks.after_pass.fn(config->hooks.after_pass.uptr, pass_name, *pmod); } +void apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPass pass, String pass_name) { + bool changed = pass(config, m); + *todo |= changed; + + if (getenv("SHADY_DUMP_CLEAN_ROUNDS") && changed) { + log_string(DEBUGVV, "%s changed something:\n", pass_name); + log_module(DEBUGVV, config, *m); + } +} + CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { IrArena* initial_arena = (*pmod)->arena; diff --git a/src/shady/compile.h b/src/shady/compile.h deleted file mode 100644 index d71f08647..000000000 --- a/src/shady/compile.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SHADY_COMPILE_H -#define SHADY_COMPILE_H - -#include "shady/ir.h" -#include "passes/passes.h" -#include "log.h" -#include "analysis/verify.h" - -#ifdef NDEBUG -#define SHADY_RUN_VERIFY 0 -#else -#define SHADY_RUN_VERIFY 1 -#endif - -void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name); - -#define RUN_PASS(pass_name) run_pass_impl(config, pmod, initial_arena, pass_name, #pass_name); - -#endif diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index d24bc2827..24c081ced 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -135,18 +135,6 @@ OptPass opt_demote_alloca; OptPass opt_mem2reg; RewritePass import; -static void apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPass pass, String pass_name) { - bool changed = pass(config, m); - *todo |= changed; - - if (getenv("SHADY_DUMP_CLEAN_ROUNDS") && changed) { - log_string(DEBUGVV, "%s changed something:\n", pass_name); - log_module(DEBUGVV, config, *m); - } -} - -#define APPLY_OPT(pass_name) apply_opt_impl(config, &todo, &m, pass_name, #pass_name); - Module* cleanup(const CompilerConfig* config, Module* const src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); if (!aconfig.check_types) From cf12c7222df2884df7cb269f210dce66766ffd44 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Tue, 24 Sep 2024 11:22:15 +0200 Subject: [PATCH 588/693] apply lower_cf_instrs in slim driver --- src/frontend/slim/slim_driver.c | 1 + src/shady/compile.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index fd8af59d3..276f6bfda 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -39,6 +39,7 @@ Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, co RUN_PASS(normalize_builtins) RUN_PASS(infer_program) + RUN_PASS(lower_cf_instrs) destroy_ir_arena(initial_arena); return *pmod; diff --git a/src/shady/compile.c b/src/shady/compile.c index 1d94aa3d6..ae642bd0f 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -87,7 +87,6 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { RUN_PASS(eliminate_inlineable_constants) - RUN_PASS(lower_cf_instrs) RUN_PASS(setup_stack_frames) if (!config->hacks.force_join_point_lifting) RUN_PASS(mark_leaf_functions) From 180611282a053da80d14c8cbe2ee4684337030eb Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Tue, 24 Sep 2024 11:22:28 +0200 Subject: [PATCH 589/693] restored mem2reg test functionality --- src/driver/slim.c | 7 ---- test/opt/CMakeLists.txt | 4 +- test/opt/mem2reg_should_fail.slim | 1 + test/opt/opt_oracle.c | 69 ++++++++++++++++++++++--------- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/driver/slim.c b/src/driver/slim.c index 99954698d..38d4668fd 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -6,17 +6,10 @@ #include "util.h" #include "portability.h" -#include - -#ifndef HOOK_STUFF -#define HOOK_STUFF -#endif - int main(int argc, char** argv) { platform_specific_terminal_init_extras(); DriverConfig args = default_driver_config(); - HOOK_STUFF cli_parse_driver_arguments(&args, &argc, argv); cli_parse_common_args(&argc, argv); cli_parse_compiler_config_args(&args.config, &argc, argv); diff --git a/test/opt/CMakeLists.txt b/test/opt/CMakeLists.txt index 6029ae600..f6537f26d 100644 --- a/test/opt/CMakeLists.txt +++ b/test/opt/CMakeLists.txt @@ -3,8 +3,8 @@ target_link_libraries(opt_oracle PRIVATE driver) add_test(NAME "mem2reg1" COMMAND opt_oracle ${CMAKE_CURRENT_SOURCE_DIR}/mem2reg1.slim --no-dynamic-scheduling) set_property(TEST "mem2reg1" PROPERTY ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0") -add_test(NAME "mem2reg2" COMMAND opt_oracle ${CMAKE_CURRENT_SOURCE_DIR}/mem2reg2.slim --no-dynamic-scheduling) -set_property(TEST "mem2reg2" PROPERTY ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0") +# add_test(NAME "mem2reg2" COMMAND opt_oracle ${CMAKE_CURRENT_SOURCE_DIR}/mem2reg2.slim --no-dynamic-scheduling) +# set_property(TEST "mem2reg2" PROPERTY ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0") add_test(NAME "mem2reg3" COMMAND opt_oracle ${CMAKE_CURRENT_SOURCE_DIR}/mem2reg3.slim --no-dynamic-scheduling) set_property(TEST "mem2reg3" PROPERTY ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0") diff --git a/test/opt/mem2reg_should_fail.slim b/test/opt/mem2reg_should_fail.slim index 32fd526f0..b41d9e4c3 100644 --- a/test/opt/mem2reg_should_fail.slim +++ b/test/opt/mem2reg_should_fail.slim @@ -1,5 +1,6 @@ fn leak(varying ptr private i32 p); +@Exported fn f varying f32(varying i32 x) { var i32 i = 42; leak(&i); diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 893aa9994..42772f76c 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -2,9 +2,11 @@ #include "shady/driver.h" #include "shady/print.h" +#include "../shady/passes/passes.h" #include "../shady/visit.h" #include "log.h" +#include "portability.h" #include #include @@ -27,24 +29,22 @@ static void search_for_memstuff(Visitor* v, const Node* n) { default: break; } - visit_node_operands(v, NcDeclaration, n); + visit_node_operands(v, ~(NcMem | NcDeclaration | NcTerminator), n); } -static void after_pass(void* uptr, String pass_name, Module* mod) { - if (strcmp(pass_name, "opt_mem2reg") == 0) { - Visitor v = {.visit_node_fn = search_for_memstuff}; - visit_module(&v, mod); - if (expect_memstuff != found_memstuff) { - error_print("Expected "); - if (!expect_memstuff) - error_print("no more "); - error_print("memory primops in the output.\n"); - dump_module(mod); - exit(-1); - } +static void check_module(Module* mod) { + Visitor v = { .visit_node_fn = search_for_memstuff }; + visit_module(&v, mod); + if (expect_memstuff != found_memstuff) { + error_print("Expected "); + if (!expect_memstuff) + error_print("no more "); + error_print("memory primops in the output.\n"); dump_module(mod); - exit(0); + exit(-1); } + dump_module(mod); + exit(0); } static void cli_parse_oracle_args(int* pargc, char** argv) { @@ -63,11 +63,42 @@ static void cli_parse_oracle_args(int* pargc, char** argv) { cli_pack_remaining_args(pargc, argv); } -static void hook(DriverConfig* args, int* pargc, char** argv) { - args->config.hooks.after_pass.fn = after_pass; - cli_parse_oracle_args(pargc, argv); +static Module* oracle_passes(const CompilerConfig* config, Module* initial_mod) { + IrArena* initial_arena = get_module_arena(initial_mod); + Module** pmod = &initial_mod; + + RUN_PASS(cleanup) + check_module(*pmod); + + return *pmod; } -#define HOOK_STUFF hook(&args, &argc, argv); +int main(int argc, char** argv) { + platform_specific_terminal_init_extras(); + + DriverConfig args = default_driver_config(); + cli_parse_driver_arguments(&args, &argc, argv); + cli_parse_common_args(&argc, argv); + cli_parse_compiler_config_args(&args.config, &argc, argv); + cli_parse_oracle_args(&argc, argv); + cli_parse_input_files(args.input_filenames, &argc, argv); + + ArenaConfig aconfig = default_arena_config(&args.config.target); + aconfig.optimisations.weaken_non_leaking_allocas = true; + IrArena* arena = new_ir_arena(&aconfig); + Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one + + ShadyErrorCodes err = driver_load_source_files(&args, mod); + if (err) + exit(err); + + Module* mod2 = oracle_passes(&args.config, mod); + destroy_ir_arena(get_module_arena(mod2)); + + if (err) + exit(err); + info_print("Compilation successful\n"); -#include "../../src/driver/slim.c" \ No newline at end of file + destroy_ir_arena(arena); + destroy_driver_config(&args); +} \ No newline at end of file From 6f97e79efc3bd264de9893a7c9f4613b4ae04a73 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Tue, 24 Sep 2024 11:22:53 +0200 Subject: [PATCH 590/693] comment out broken Vcc test --- test/vcc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vcc/CMakeLists.txt b/test/vcc/CMakeLists.txt index f47debef7..b0fca7fce 100644 --- a/test/vcc/CMakeLists.txt +++ b/test/vcc/CMakeLists.txt @@ -9,7 +9,7 @@ endforeach() spv_outputting_test(NAME test/vcc/branch.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/loop.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) -spv_outputting_test(NAME test/vcc/loop_closed.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) +# spv_outputting_test(NAME test/vcc/loop_closed.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/goto.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/ternary.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) spv_outputting_test(NAME test/vcc/string.c COMPILER vcc EXTRA_ARGS ${VCC_TEST_ARGS}) From 536ebda3f65f274f147a3feca31651d6ffcb8330 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Tue, 24 Sep 2024 11:37:42 +0200 Subject: [PATCH 591/693] remove unused declaration tripping up SWIG --- include/shady/ir.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index ac867604e..9f3239d81 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -264,7 +264,6 @@ const Node* annotation_value_helper(IrArena* a, String n, const Node* v); // instructions const Node* prim_op_helper(IrArena*, Op, Nodes, Nodes); const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); -const Node* compound_instruction(IrArena* arena, Nodes instructions, Nodes results); // terminators const Node* jump_helper(IrArena* a, const Node* dst, Nodes args, const Node* mem); From 7560752bf05f08e340c91f9771b8bd223ac2057b Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Tue, 24 Sep 2024 11:41:44 +0200 Subject: [PATCH 592/693] fix infinite loop in chase_ptr_to_source --- src/shady/node.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shady/node.c b/src/shady/node.c index 59242c797..0b5c66af3 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -88,6 +88,7 @@ const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { PtrCompositeElement payload = ptr->payload.ptr_composite_element; if (!is_zero(payload.index)) break; + ptr = payload.ptr; continue; } case PrimOp_TAG: { From cc3f49ea7a1a89806dd7b73d6360ed215b10e443 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 15:03:34 +0200 Subject: [PATCH 593/693] add shd_ prefix to arena.h and list.h --- src/backend/spirv/emit_spv.c | 4 +- src/backend/spirv/emit_spv_control_flow.c | 6 +- src/backend/spirv/spirv_builder.c | 28 +++--- src/common/arena.c | 6 +- src/common/arena.h | 6 +- src/common/list.c | 36 +++---- src/common/list.h | 34 +++---- src/common/util.c | 2 +- src/driver/cli.c | 6 +- src/driver/driver.c | 6 +- src/frontend/llvm/l2s.c | 16 +-- src/frontend/llvm/l2s_annotations.c | 2 +- src/frontend/llvm/l2s_instr.c | 4 +- src/frontend/llvm/l2s_postprocess.c | 4 +- src/frontend/slim/bind.c | 2 +- src/frontend/slim/parser.c | 92 ++++++++--------- src/frontend/spirv/s2s.c | 10 +- src/runtime/runtime.c | 28 +++--- src/runtime/runtime_program.c | 2 +- src/runtime/runtime_test.c | 2 +- src/runtime/vulkan/vk_runtime_device.c | 6 +- src/runtime/vulkan/vk_runtime_program.c | 8 +- src/shady/analysis/callgraph.c | 12 +-- src/shady/analysis/cfg.c | 104 ++++++++++---------- src/shady/analysis/cfg_dump.c | 28 +++--- src/shady/analysis/looptree.c | 104 ++++++++++---------- src/shady/analysis/uses.c | 6 +- src/shady/analysis/verify.c | 12 +-- src/shady/body_builder.c | 24 ++--- src/shady/constructors.c | 2 +- src/shady/generator/import_spv_defs.c | 26 ++--- src/shady/ir.c | 20 ++-- src/shady/module.c | 14 +-- src/shady/passes/lcssa.c | 10 +- src/shady/passes/lower_alloca.c | 10 +- src/shady/passes/lower_switch_btree.c | 4 +- src/shady/passes/lower_tailcalls.c | 20 ++-- src/shady/passes/opt_demote_alloca.c | 6 +- src/shady/passes/opt_mem2reg.c | 4 +- src/shady/passes/opt_restructure.c | 26 ++--- src/shady/passes/reconvergence_heuristics.c | 58 +++++------ src/shady/passes/scope2control.c | 16 +-- src/shady/passes/scope_heuristic.c | 36 +++---- src/shady/print.c | 2 +- vcc/vcc.c | 4 +- 45 files changed, 423 insertions(+), 435 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 67879935c..df65ed061 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -70,8 +70,8 @@ static void emit_basic_block(Emitter* emitter, FnBuilder* fn_builder, const CFNo spv_emit_terminator(emitter, fn_builder, bb_builder, bb_node, body); - for (size_t i = 0; i < entries_count_list(cf_node->dominates); i++) { - CFNode* dominated = read_list(CFNode*, cf_node->dominates)[i]; + for (size_t i = 0; i < shd_list_count(cf_node->dominates); i++) { + CFNode* dominated = shd_read_list(CFNode*, cf_node->dominates)[i]; emit_basic_block(emitter, fn_builder, dominated); } diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 494e159dc..d5b141fc5 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -18,9 +18,9 @@ BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb) { static void add_phis(Emitter* emitter, FnBuilder* fn_builder, SpvId src, BBBuilder dst_builder, Nodes args) { struct List* phis = spbv_get_phis(dst_builder); - assert(entries_count_list(phis) == args.count); + assert(shd_list_count(phis) == args.count); for (size_t i = 0; i < args.count; i++) { - SpvbPhi* phi = read_list(SpvbPhi*, phis)[i]; + SpvbPhi* phi = shd_read_list(SpvbPhi*, phis)[i]; spvb_add_phi_source(phi, src, spv_emit_value(emitter, fn_builder, args.nodes[i])); } } @@ -109,7 +109,7 @@ static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_buil spvb_add_phi_source(header_phi, get_block_builder_id(continue_builder), continue_phi_id); BBBuilder body_builder = spv_find_basic_block_builder(emitter, loop_instr.body); - spvb_add_phi_source(read_list(SpvbPhi*, spbv_get_phis(body_builder))[i], get_block_builder_id(header_builder), header_phi_id); + spvb_add_phi_source(shd_read_list(SpvbPhi*, spbv_get_phis(body_builder))[i], get_block_builder_id(header_builder), header_phi_id); } fn_builder->per_bb[cfg_lookup(fn_builder->cfg, loop_instr.body)->rpo_index].continue_id = continue_id; diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index 7eee49eda..0454275a0 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -508,7 +508,7 @@ SpvbFnBuilder* spvb_begin_fn(SpvbFileBuilder* file_builder, SpvId fn_id, SpvId f .fn_type = fn_type, .fn_ret_type = fn_ret_type, .file_builder = file_builder, - .bbs = new_list(SpvbBasicBlockBuilder*), + .bbs = shd_new_list(SpvbBasicBlockBuilder*), .variables = new_growy(), .header = new_growy(), }; @@ -551,11 +551,11 @@ void spvb_declare_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_buil // Includes stuff like OpFunctionParameters copy_section(fn_builder->header); - assert(entries_count_list(fn_builder->bbs) == 0 && "declared functions must be empty"); + assert(shd_list_count(fn_builder->bbs) == 0 && "declared functions must be empty"); op(SpvOpFunctionEnd, 1); - destroy_list(fn_builder->bbs); + shd_destroy_list(fn_builder->bbs); destroy_growy(fn_builder->header); destroy_growy(fn_builder->variables); free(fn_builder); @@ -596,7 +596,7 @@ void spvb_define_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_build bool first = true; for (size_t i = 0; i < fn_builder->bbs->elements_count; i++) { op(SpvOpLabel, 2); - SpvbBasicBlockBuilder* bb = read_list(SpvbBasicBlockBuilder*, fn_builder->bbs)[i]; + SpvbBasicBlockBuilder* bb = shd_read_list(SpvbBasicBlockBuilder*, fn_builder->bbs)[i]; ref_id(bb->label); if (first) { @@ -606,26 +606,26 @@ void spvb_define_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_build } for (size_t j = 0; j < bb->phis->elements_count; j++) { - SpvbPhi* phi = read_list(SpvbPhi*, bb->phis)[j]; + SpvbPhi* phi = shd_read_list(SpvbPhi*, bb->phis)[j]; op(SpvOpPhi, 3 + 2 * phi->preds->elements_count); ref_id(phi->type); ref_id(phi->value); assert(phi->preds->elements_count != 0); for (size_t k = 0; k < phi->preds->elements_count; k++) { - SpvbPhiSrc* pred = &read_list(SpvbPhiSrc, phi->preds)[k]; + SpvbPhiSrc* pred = &shd_read_list(SpvbPhiSrc, phi->preds)[k]; ref_id(pred->value); ref_id(pred->basic_block); } - destroy_list(phi->preds); + shd_destroy_list(phi->preds); free(phi); } copy_section(bb->instructions_section); copy_section(bb->terminator_section); - destroy_list(bb->phis); + shd_destroy_list(bb->phis); destroy_growy(bb->instructions_section); destroy_growy(bb->terminator_section); free(bb); @@ -633,7 +633,7 @@ void spvb_define_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_build op(SpvOpFunctionEnd, 1); - destroy_list(fn_builder->bbs); + shd_destroy_list(fn_builder->bbs); destroy_growy(fn_builder->header); destroy_growy(fn_builder->variables); free(fn_builder); @@ -645,7 +645,7 @@ SpvbBasicBlockBuilder* spvb_begin_bb(SpvbFnBuilder* fn_builder, SpvId label) { *bbb = (SpvbBasicBlockBuilder) { .fn_builder = fn_builder, .label = label, - .phis = new_list(SpvbPhi*), + .phis = shd_new_list(SpvbPhi*), .instructions_section = new_growy(), .terminator_section = new_growy(), }; @@ -657,7 +657,7 @@ SpvbFnBuilder* spvb_get_fn_builder(SpvbBasicBlockBuilder* bb_builder) { } void spvb_add_bb(SpvbFnBuilder* fn_builder, SpvbBasicBlockBuilder* bb_builder) { - append_list(SpvbBasicBlockBuilder*, fn_builder->bbs, bb_builder); + shd_list_append(SpvbBasicBlockBuilder*, fn_builder->bbs, bb_builder); } SpvId get_block_builder_id(SpvbBasicBlockBuilder* basic_block_builder) { @@ -665,16 +665,16 @@ SpvId get_block_builder_id(SpvbBasicBlockBuilder* basic_block_builder) { } SpvbPhi* spvb_add_phi(SpvbBasicBlockBuilder* bb_builder, SpvId type, SpvId id) { SpvbPhi* phi = malloc(sizeof(SpvbPhi)); - phi->preds = new_list(SpvbPhiSrc); + phi->preds = shd_new_list(SpvbPhiSrc); phi->value = id; phi->type = type; - append_list(SpvbPhi*, bb_builder->phis, phi); + shd_list_append(SpvbPhi*, bb_builder->phis, phi); return phi; } void spvb_add_phi_source(SpvbPhi* phi, SpvId source_block, SpvId value) { SpvbPhiSrc op = { .value = value, .basic_block = source_block }; - append_list(SpvbPhi, phi->preds, op); + shd_list_append(SpvbPhi, phi->preds, op); } struct List* spbv_get_phis(SpvbBasicBlockBuilder* bb_builder) { diff --git a/src/common/arena.c b/src/common/arena.c index 0cc81f621..3b9133401 100644 --- a/src/common/arena.c +++ b/src/common/arena.c @@ -19,7 +19,7 @@ inline static size_t round_up(size_t a, size_t b) { return divided * b; } -Arena* new_arena() { +Arena* shd_new_arena() { Arena* arena = malloc(sizeof(Arena)); *arena = (Arena) { .nblocks = 0, @@ -32,7 +32,7 @@ Arena* new_arena() { return arena; } -void destroy_arena(Arena* arena) { +void shd_destroy_arena(Arena* arena) { for (int i = 0; i < arena->nblocks; i++) { free(arena->blocks[i]); } @@ -54,7 +54,7 @@ static void* new_block(Arena* arena, size_t size) { return allocated; } -void* arena_alloc(Arena* arena, size_t size) { +void* shd_arena_alloc(Arena* arena, size_t size) { size = round_up(size, (size_t) sizeof(max_align_t)); if (size == 0) return NULL; diff --git a/src/common/arena.h b/src/common/arena.h index baa16f5ae..ddcee2e42 100644 --- a/src/common/arena.h +++ b/src/common/arena.h @@ -5,8 +5,8 @@ typedef struct Arena_ Arena; -Arena* new_arena(); -void destroy_arena(Arena* arena); -void* arena_alloc(Arena* arena, size_t size); +Arena* shd_new_arena(); +void shd_destroy_arena(Arena* arena); +void* shd_arena_alloc(Arena* arena, size_t size); #endif diff --git a/src/common/list.c b/src/common/list.c index da2f67fc0..5c344073b 100644 --- a/src/common/list.c +++ b/src/common/list.c @@ -6,7 +6,7 @@ #include "portability.h" -struct List* new_list_impl(size_t elem_size) { +struct List* shd_new_list_impl(size_t elem_size) { struct List* list = (struct List*) malloc(sizeof (struct List)); *list = (struct List) { .elements_count = 0, @@ -17,21 +17,21 @@ struct List* new_list_impl(size_t elem_size) { return list; } -void destroy_list(struct List* list) { +void shd_destroy_list(struct List* list) { free(list->alloc); free(list); } -size_t entries_count_list(struct List* list) { +size_t shd_list_count(struct List* list) { return list->elements_count; } -void grow_list(struct List* list) { +static void grow_list(struct List* list) { list->space = list->space * 2; list->alloc = realloc(list->alloc, list->space * list->element_size); } -void append_list_impl(struct List* list, void* element) { +void shd_list_append_impl(struct List* list, void* element) { if (list->elements_count == list->space) grow_list(list); size_t element_size = list->element_size; @@ -39,14 +39,14 @@ void append_list_impl(struct List* list, void* element) { list->elements_count++; } -void* pop_list_impl(struct List* list) { +void* shd_list_pop_impl(struct List* list) { assert(list->elements_count > 0); list->elements_count--; void* last = (void*) ((size_t)(list->alloc) + list->elements_count * list->element_size); return last; } -void add_list_impl(struct List* list, size_t index, void* element) { +void shd_list_insert_impl(struct List* list, size_t index, void* element) { size_t old_elements_count = list->elements_count; if (list->elements_count == list->space) grow_list(list); @@ -61,20 +61,7 @@ void add_list_impl(struct List* list, size_t index, void* element) { list->elements_count++; } -void delete_list_impl(struct List* list, size_t index) { - size_t old_elements_count = list->elements_count; - - size_t element_size = list->element_size; - - void* hole_at = (void*) ((size_t) list->alloc + element_size * index); - void* fill_with = (void*) ((size_t) list->alloc + element_size * (index + 1)); - size_t amount = old_elements_count - index; - memmove(hole_at, fill_with, element_size * amount); - - list->elements_count--; -} - -void* remove_list_impl(struct List* list, size_t index) { +void* shd_list_remove_impl(struct List* list, size_t index, bool move_to_end) { size_t old_elements_count = list->elements_count; size_t element_size = list->element_size; @@ -83,16 +70,19 @@ void* remove_list_impl(struct List* list, size_t index) { void* hole_at = (void*) ((size_t) list->alloc + element_size * index); void* fill_with = (void*) ((size_t) list->alloc + element_size * (index + 1)); size_t amount = old_elements_count - index; - memcpy(&temp, hole_at, element_size); + if (move_to_end) + memcpy(&temp, hole_at, element_size); memmove(hole_at, fill_with, element_size * amount); list->elements_count--; + if (!move_to_end) + return NULL; void* end = (void*) ((size_t) list->alloc + element_size * list->elements_count); memcpy(end, &temp, element_size); return end; } -void clear_list(struct List* list) { +void shd_clear_list(struct List* list) { list->elements_count = 0; } diff --git a/src/common/list.h b/src/common/list.h index 2ddca75bd..bd837f6ab 100644 --- a/src/common/list.h +++ b/src/common/list.h @@ -2,6 +2,7 @@ #define SHADY_LIST_H #include +#include struct List { size_t elements_count; @@ -10,31 +11,28 @@ struct List { void* alloc; }; -#define new_list(T) new_list_impl(sizeof(T)) -struct List* new_list_impl(size_t elem_size); +#define shd_new_list(T) shd_new_list_impl(sizeof(T)) +struct List* shd_new_list_impl(size_t elem_size); -void destroy_list(struct List* list); +void shd_destroy_list(struct List* list); -size_t entries_count_list(struct List* list); +size_t shd_list_count(struct List* list); -#define append_list(T, list, element) append_list_impl(list, (void*) &(element)) -void append_list_impl(struct List* list, void* element); +#define shd_list_append(T, list, element) shd_list_append_impl(list, (void*) &(element)) +void shd_list_append_impl(struct List* list, void* element); -#define pop_last_list(T, list) * ((T*) pop_list_impl(list)) -#define remove_last_list(T, list) (pop_list_impl(list)) -void* pop_list_impl(struct List* list); +#define shd_list_pop(T, list) * ((T*) shd_list_pop_impl(list)) +void* shd_list_pop_impl(struct List* list); -void clear_list(struct List* list); +void shd_clear_list(struct List* list); -#define add_list(T, list, i, e) add_list_impl(list, i, (void*) &(e)) -void add_list_impl(struct List* list, size_t index, void* element); +#define shd_list_insert(T, list, i, e) shd_list_insert_impl(list, i, (void*) &(e)) +void shd_list_insert_impl(struct List* list, size_t index, void* element); -#define delete_list(T, list, i) delete_list_impl(list, index) -void delete_list_impl(struct List* list, size_t index); +#define shd_list_delete(T, list, i) shd_list_remove_impl(list, index, false) +#define shd_list_remove(T, list, i) *((T*) shd_list_remove_impl(list, i, true)) +void* shd_list_remove_impl(struct List* list, size_t index, bool); -#define remove_list(T, list, i) *((T*) remove_list_impl(list, i)) -void* remove_list_impl(struct List* list, size_t index); - -#define read_list(T, list) ((T*) (list)->alloc) +#define shd_read_list(T, list) ((T*) (list)->alloc) #endif diff --git a/src/common/util.c b/src/common/util.c index 955ae0678..21c85a06a 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -160,7 +160,7 @@ void format_string_internal(const char* str, va_list args, void* uptr, void call typedef struct { Arena* a; char** result; } InternInArenaPayload; static void intern_in_arena(InternInArenaPayload* uptr, size_t len, char* tmp) { - char* interned = (char*) arena_alloc(uptr->a, len + 1); + char* interned = (char*) shd_arena_alloc(uptr->a, len + 1); strncpy(interned, tmp, len); interned[len] = '\0'; *uptr->result = interned; diff --git a/src/driver/cli.c b/src/driver/cli.c index e0a5c6426..606d6f40f 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -195,7 +195,7 @@ void cli_parse_input_files(struct List* list, int* pargc, char** argv) { for (int i = 1; i < argc; i++) { if (argv[i] == NULL) continue; - append_list(const char*, list, argv[i]); + shd_list_append(const char*, list, argv[i]); argv[i] = NULL; } @@ -207,7 +207,7 @@ DriverConfig default_driver_config() { return (DriverConfig) { .config = default_compiler_config(), .target = TgtAuto, - .input_filenames = new_list(const char*), + .input_filenames = shd_new_list(const char*), .output_filename = NULL, .cfg_output_filename = NULL, .shd_output_filename = NULL, @@ -216,7 +216,7 @@ DriverConfig default_driver_config() { } void destroy_driver_config(DriverConfig* config) { - destroy_list(config->input_filenames); + shd_destroy_list(config->input_filenames); } void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { diff --git a/src/driver/driver.c b/src/driver/driver.c index a1ca54ef5..756b72fe4 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -94,15 +94,15 @@ ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* conf } ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { - if (entries_count_list(args->input_filenames) == 0) { + if (shd_list_count(args->input_filenames) == 0) { error_print("Missing input file. See --help for proper usage"); return MissingInputArg; } - size_t num_source_files = entries_count_list(args->input_filenames); + size_t num_source_files = shd_list_count(args->input_filenames); for (size_t i = 0; i < num_source_files; i++) { Module* m; - int err = driver_load_source_file_from_filename(&args->config, read_list(const char*, args->input_filenames)[i], read_list(const char*, args->input_filenames)[i], &m); + int err = driver_load_source_file_from_filename(&args->config, shd_read_list(const char*, args->input_filenames)[i], shd_read_list(const char*, args->input_filenames)[i], &m); if (err) return err; link_module(mod, m); diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 5b194409d..4e9ed316b 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -77,7 +77,7 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic if (get_log_level() >= DEBUG) LLVMDumpValue((LLVMValueRef)bb); - struct List* phis = new_list(LLVMValueRef); + struct List* phis = shd_new_list(LLVMValueRef); Nodes params = empty(a); LLVMValueRef instr = LLVMGetFirstInstruction(bb); while (instr) { @@ -85,7 +85,7 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic case LLVMPHI: { const Node* nparam = param(a, qualified_type_helper(convert_type(p, LLVMTypeOf(instr)), false), "phi"); insert_dict(LLVMValueRef, const Node*, p->map, instr, nparam); - append_list(LLVMValueRef, phis, instr); + shd_list_append(LLVMValueRef, phis, instr); params = append_nodes(a, params, nparam); break; } @@ -113,7 +113,7 @@ static BBParseCtx* get_bb_ctx(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef b BBParseCtx** found = find_value_dict(LLVMValueRef, BBParseCtx*, fn_ctx->bbs, bb); if (found) return *found; - BBParseCtx* ctx = arena_alloc(p->annotations_arena, sizeof(BBParseCtx)); + BBParseCtx* ctx = shd_arena_alloc(p->annotations_arena, sizeof(BBParseCtx)); prepare_bb(p, fn_ctx, ctx, bb); insert_dict(LLVMBasicBlockRef, BBParseCtx*, fn_ctx->bbs, bb, ctx); @@ -182,7 +182,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { .fn = f, .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), .bbs = new_dict(LLVMBasicBlockRef, BBParseCtx*, (HashFn) hash_ptr, (CmpFn) compare_ptrs), - .jumps_todo = new_list(JumpTodo), + .jumps_todo = shd_new_list(JumpTodo), }; const Node* r = fn_addr_helper(a, f); r = prim_op_helper(a, reinterpret_op, singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = unit_type(a) })), singleton(r)); @@ -227,12 +227,12 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { size_t i = 0; struct List* phis_list; while (dict_iter(fn_parse_ctx.phis, &i, NULL, &phis_list)) { - destroy_list(phis_list); + shd_destroy_list(phis_list); } } destroy_dict(fn_parse_ctx.phis); destroy_dict(fn_parse_ctx.bbs); - destroy_list(fn_parse_ctx.jumps_todo); + shd_destroy_list(fn_parse_ctx.jumps_todo); return r; } @@ -309,7 +309,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* .config = config, .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), - .annotations_arena = new_arena(), + .annotations_arena = shd_new_arena(), .src = src, .dst = dirty, }; @@ -344,7 +344,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* destroy_dict(p.map); destroy_dict(p.annotations); - destroy_arena(p.annotations_arena); + shd_destroy_arena(p.annotations_arena); LLVMContextDispose(context); diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 342245fa1..5fa0c799b 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -12,7 +12,7 @@ ParsedAnnotation* find_annotation(Parser* p, const Node* n) { void add_annotation(Parser* p, const Node* n, ParsedAnnotation a) { ParsedAnnotation* found = find_value_dict(const Node*, ParsedAnnotation, p->annotations, n); if (found) { - ParsedAnnotation* data = arena_alloc(p->annotations_arena, sizeof(a)); + ParsedAnnotation* data = shd_arena_alloc(p->annotations_arena, sizeof(a)); *data = a; while (found->next) found = found->next; diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index ec0869b2e..1704acec4 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -61,10 +61,10 @@ static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, const Node* dst_bb = convert_basic_block_body(p, fn_ctx, dst); struct List* phis = *find_value_dict(const Node*, struct List*, fn_ctx->phis, dst_bb); assert(phis); - size_t params_count = entries_count_list(phis); + size_t params_count = shd_list_count(phis); LARRAY(const Node*, params, params_count); for (size_t i = 0; i < params_count; i++) { - LLVMValueRef phi = read_list(LLVMValueRef, phis)[i]; + LLVMValueRef phi = shd_read_list(LLVMValueRef, phis)[i]; for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { if (convert_basic_block_header(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == src) { params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index c9d40558f..f9a03d317 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -137,12 +137,12 @@ void postprocess(Parser* p, Module* src, Module* dst) { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = p->config, .p = p, - .arena = new_arena(), + .arena = shd_new_arena(), }; ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; rewrite_module(&ctx.rewriter); - destroy_arena(ctx.arena); + shd_destroy_arena(ctx.arena); destroy_rewriter(&ctx.rewriter); } diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 847d76d26..ab6bd47df 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -73,7 +73,7 @@ static Resolved resolve_using_name(Context* ctx, const char* name) { static void add_binding(Context* ctx, bool is_var, String name, const Node* node) { assert(name); - NamedBindEntry* entry = arena_alloc(ctx->rewriter.dst_arena->arena, sizeof(NamedBindEntry)); + NamedBindEntry* entry = shd_arena_alloc(ctx->rewriter.dst_arena->arena, sizeof(NamedBindEntry)); *entry = (NamedBindEntry) { .name = string(ctx->rewriter.dst_arena, name), .is_var = is_var, diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 0f8bc873c..4eace6bcd 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -352,17 +352,17 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { if (curr_token(tokenizer).tag == rpar_tok) { next_token(tokenizer); } else { - struct List* elements = new_list(const Node*); - append_list(const Node*, elements, atom); + struct List* elements = shd_new_list(const Node*); + shd_list_append(const Node*, elements, atom); while (!accept_token(ctx, rpar_tok)) { expect(accept_token(ctx, comma_tok), "','"); const Node* element = expect_operand(ctx, bb); - append_list(const Node*, elements, element); + shd_list_append(const Node*, elements, element); } - Nodes tcontents = nodes(arena, entries_count_list(elements), read_list(const Node*, elements)); - destroy_list(elements); + Nodes tcontents = nodes(arena, shd_list_count(elements), shd_read_list(const Node*, elements)); + shd_destroy_list(elements); atom = tuple_helper(arena, tcontents); } return atom; @@ -448,8 +448,8 @@ static const Type* accept_unqualified_type(ctxparams) { }); } else if (accept_token(ctx, struct_tok)) { expect(accept_token(ctx, lbracket_tok), "'{'"); - struct List* names = new_list(String); - struct List* types = new_list(const Type*); + struct List* names = shd_new_list(String); + struct List* types = shd_new_list(const Type*); while (true) { if (accept_token(ctx, rbracket_tok)) break; @@ -457,14 +457,14 @@ static const Type* accept_unqualified_type(ctxparams) { expect(elem, "struct member type"); String id = accept_identifier(ctx); expect(id, "struct member name"); - append_list(String, names, id); - append_list(const Type*, types, elem); + shd_list_append(String, names, id); + shd_list_append(const Type*, types, elem); expect(accept_token(ctx, semi_tok), "';'"); } - Nodes elem_types = nodes(arena, entries_count_list(types), read_list(const Type*, types)); - Strings names2 = strings(arena, entries_count_list(names), read_list(String, names)); - destroy_list(names); - destroy_list(types); + Nodes elem_types = nodes(arena, shd_list_count(types), shd_read_list(const Type*, types)); + Strings names2 = strings(arena, shd_list_count(names), shd_read_list(String, names)); + shd_destroy_list(names); + shd_destroy_list(types); return record_type(arena, (RecordType) { .names = names2, .members = elem_types, @@ -520,8 +520,8 @@ static const Node* expect_operand(ctxparams, BodyBuilder* bb) { static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_values, BodyBuilder* bb) { expect(accept_token(ctx, lpar_tok), "'('"); - struct List* params = new_list(Node*); - struct List* default_vals = default_values ? new_list(Node*) : NULL; + struct List* params = shd_new_list(Node*); + struct List* default_vals = default_values ? shd_new_list(Node*) : NULL; while (true) { if (accept_token(ctx, rpar_tok)) @@ -534,12 +534,12 @@ static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_value expect(id, "parameter name"); const Node* node = param(arena, qtype, id); - append_list(Node*, params, node); + shd_list_append(Node*, params, node); if (default_values) { expect(accept_token(ctx, equal_tok), "'='"); const Node* default_val = accept_operand(ctx, bb); - append_list(const Node*, default_vals, default_val); + shd_list_append(const Node*, default_vals, default_val); } if (accept_token(ctx, comma_tok)) @@ -547,19 +547,19 @@ static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_value } } - size_t count = entries_count_list(params); - *parameters = nodes(arena, count, read_list(const Node*, params)); - destroy_list(params); + size_t count = shd_list_count(params); + *parameters = nodes(arena, count, shd_read_list(const Node*, params)); + shd_destroy_list(params); if (default_values) { - *default_values = nodes(arena, count, read_list(const Node*, default_vals)); - destroy_list(default_vals); + *default_values = nodes(arena, count, shd_read_list(const Node*, default_vals)); + shd_destroy_list(default_vals); } } typedef enum { MustQualified, MaybeQualified, NeverQualified } Qualified; static Nodes accept_types(ctxparams, TokenTag separator, Qualified qualified) { - struct List* tmp = new_list(Type*); + struct List* tmp = shd_new_list(Type*); while (true) { const Type* type; switch (qualified) { @@ -570,14 +570,14 @@ static Nodes accept_types(ctxparams, TokenTag separator, Qualified qualified) { if (!type) break; - append_list(Type*, tmp, type); + shd_list_append(Type*, tmp, type); if (separator != 0) accept_token(ctx, separator); } Nodes types2 = nodes(arena, tmp->elements_count, (const Type**) tmp->alloc); - destroy_list(tmp); + shd_destroy_list(tmp); return types2; } @@ -689,7 +689,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) static Nodes expect_operands(ctxparams, BodyBuilder* bb) { expect(accept_token(ctx, lpar_tok), "'('"); - struct List* list = new_list(Node*); + struct List* list = shd_new_list(Node*); bool expect = false; while (true) { @@ -703,7 +703,7 @@ static Nodes expect_operands(ctxparams, BodyBuilder* bb) { syntax_error("Expected value or ')'"); } - append_list(Node*, list, val); + shd_list_append(Node*, list, val); if (accept_token(ctx, comma_tok)) expect = true; @@ -714,7 +714,7 @@ static Nodes expect_operands(ctxparams, BodyBuilder* bb) { } Nodes final = nodes(arena, list->elements_count, (const Node**) list->alloc); - destroy_list(list); + shd_destroy_list(list); return final; } @@ -794,12 +794,12 @@ static const Node* accept_instruction(ctxparams, BodyBuilder* bb) { } static void expect_identifiers(ctxparams, Strings* out_strings) { - struct List* list = new_list(const char*); + struct List* list = shd_new_list(const char*); while (true) { const char* id = accept_identifier(ctx); expect(id, "identifier"); - append_list(const char*, list, id); + shd_list_append(const char*, list, id); if (accept_token(ctx, comma_tok)) continue; @@ -808,12 +808,12 @@ static void expect_identifiers(ctxparams, Strings* out_strings) { } *out_strings = strings(arena, list->elements_count, (const char**) list->alloc); - destroy_list(list); + shd_destroy_list(list); } static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* out_types) { - struct List* slist = new_list(const char*); - struct List* tlist = new_list(const char*); + struct List* slist = shd_new_list(const char*); + struct List* tlist = shd_new_list(const char*); while (true) { const Type* type = accept_unqualified_type(ctx); @@ -821,8 +821,8 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* const char* id = accept_identifier(ctx); expect(id, "identifier"); - append_list(const char*, tlist, type); - append_list(const char*, slist, id); + shd_list_append(const char*, tlist, type); + shd_list_append(const char*, slist, id); if (accept_token(ctx, comma_tok)) continue; @@ -832,8 +832,8 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* *out_strings = strings(arena, slist->elements_count, (const char**) slist->alloc); *out_types = nodes(arena, tlist->elements_count, (const Node**) tlist->alloc); - destroy_list(slist); - destroy_list(tlist); + shd_destroy_list(slist); + shd_destroy_list(tlist); } static Nodes strings2nodes(IrArena* a, Strings strings) { @@ -1045,7 +1045,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t } static Nodes accept_annotations(ctxparams) { - struct List* list = new_list(const Node*); + struct List* list = shd_new_list(const Node*); while (true) { if (accept_token(ctx, at_tok)) { @@ -1061,21 +1061,21 @@ static Nodes accept_annotations(ctxparams) { // TODO: AnnotationCompound ? if (curr_token(tokenizer).tag == comma_tok) { next_token(tokenizer); - struct List* values = new_list(const Node*); - append_list(const Node*, values, first_value); + struct List* values = shd_new_list(const Node*); + shd_list_append(const Node*, values, first_value); while (true) { const Node* next_value = accept_value(ctx, NULL); expect(next_value, "value"); - append_list(const Node*, values, next_value); + shd_list_append(const Node*, values, next_value); if (accept_token(ctx, comma_tok)) continue; else break; } annot = annotation_values(arena, (AnnotationValues) { .name = id, - .values = nodes(arena, entries_count_list(values), read_list(const Node*, values)) + .values = nodes(arena, shd_list_count(values), shd_read_list(const Node*, values)) }); - destroy_list(values); + shd_destroy_list(values); } else { annot = annotation_value(arena, (AnnotationValue) { .name = id, @@ -1091,14 +1091,14 @@ static Nodes accept_annotations(ctxparams) { }); } expect(annot, "annotation"); - append_list(const Node*, list, annot); + shd_list_append(const Node*, list, annot); continue; } break; } - Nodes annotations = nodes(arena, entries_count_list(list), read_list(const Node*, list)); - destroy_list(list); + Nodes annotations = nodes(arena, shd_list_count(list), shd_read_list(const Node*, list)); + shd_destroy_list(list); return annotations; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 925820efc..0674c9918 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -100,7 +100,7 @@ typedef struct { SpvDef* get_definition_by_id(SpvParser* parser, size_t id); SpvDef* new_def(SpvParser* parser) { - SpvDef* interned = arena_alloc(parser->decorations_arena, sizeof(SpvDef)); + SpvDef* interned = shd_arena_alloc(parser->decorations_arena, sizeof(SpvDef)); SpvDef empty = {0}; memcpy(interned, &empty, sizeof(SpvDef)); return interned; @@ -111,7 +111,7 @@ void add_decoration(SpvParser* parser, SpvId id, SpvDeco decoration) { while (tgt_def->next_decoration) { tgt_def = &tgt_def->next_decoration->payload; } - SpvDeco* interned = arena_alloc(parser->decorations_arena, sizeof(SpvDeco)); + SpvDeco* interned = shd_arena_alloc(parser->decorations_arena, sizeof(SpvDeco)); memcpy(interned, &decoration, sizeof(SpvDeco)); tgt_def->next_decoration = interned; } @@ -923,7 +923,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { SpvId argument_value = instruction[3 + i * 2 + 0]; SpvId predecessor_block = instruction[3 + i * 2 + 1]; - SpvPhiArgs* new = arena_alloc(parser->decorations_arena, sizeof(SpvPhiArgs)); + SpvPhiArgs* new = shd_arena_alloc(parser->decorations_arena, sizeof(SpvPhiArgs)); *new = (SpvPhiArgs) { .predecessor = predecessor_block, .arg_i = parser->fun_arg_i, @@ -1350,7 +1350,7 @@ S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const .mod = *dst, .arena = get_module_arena(*dst), - .decorations_arena = new_arena(), + .decorations_arena = shd_new_arena(), .phi_arguments = new_dict(SpvId, SpvPhiArgs*, (HashFn) hash_spvid, (CmpFn) compare_spvid), }; @@ -1366,7 +1366,7 @@ S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const } destroy_dict(parser.phi_arguments); - destroy_arena(parser.decorations_arena); + shd_destroy_arena(parser.decorations_arena); free(parser.defs); return S2S_Success; diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 690c3df0d..72d48bcc5 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -10,14 +10,14 @@ Runtime* initialize_runtime(RuntimeConfig config) { Runtime* runtime = malloc(sizeof(Runtime)); memset(runtime, 0, sizeof(Runtime)); runtime->config = config; - runtime->backends = new_list(Backend*); - runtime->devices = new_list(Device*); - runtime->programs = new_list(Program*); + runtime->backends = shd_new_list(Backend*); + runtime->devices = shd_new_list(Device*); + runtime->programs = shd_new_list(Program*); #if VK_BACKEND_PRESENT Backend* vk_backend = initialize_vk_backend(runtime); CHECK(vk_backend, goto init_fail_free); - append_list(Backend*, runtime->backends, vk_backend); + shd_list_append(Backend*, runtime->backends, vk_backend); #endif #if CUDA_BACKEND_PRESENT Backend* cuda_backend = initialize_cuda_backend(runtime); @@ -38,31 +38,31 @@ void shutdown_runtime(Runtime* runtime) { if (!runtime) return; // TODO force wait outstanding dispatches ? - for (size_t i = 0; i < entries_count_list(runtime->devices); i++) { - Device* dev = read_list(Device*, runtime->devices)[i]; + for (size_t i = 0; i < shd_list_count(runtime->devices); i++) { + Device* dev = shd_read_list(Device*, runtime->devices)[i]; dev->cleanup(dev); } - destroy_list(runtime->devices); + shd_destroy_list(runtime->devices); - for (size_t i = 0; i < entries_count_list(runtime->programs); i++) { - unload_program(read_list(Program*, runtime->programs)[i]); + for (size_t i = 0; i < shd_list_count(runtime->programs); i++) { + unload_program(shd_read_list(Program*, runtime->programs)[i]); } - destroy_list(runtime->programs); + shd_destroy_list(runtime->programs); - for (size_t i = 0; i < entries_count_list(runtime->backends); i++) { - Backend* bk = read_list(Backend*, runtime->backends)[i]; + for (size_t i = 0; i < shd_list_count(runtime->backends); i++) { + Backend* bk = shd_read_list(Backend*, runtime->backends)[i]; bk->cleanup(bk); } free(runtime); } size_t device_count(Runtime* r) { - return entries_count_list(r->devices); + return shd_list_count(r->devices); } Device* get_device(Runtime* r, size_t i) { assert(i < device_count(r)); - return read_list(Device*, r->devices)[i]; + return shd_read_list(Device*, r->devices)[i]; } Device* get_an_device(Runtime* r) { diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index 25740fef8..db4f0828b 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -20,7 +20,7 @@ Program* new_program_from_module(Runtime* runtime, const CompilerConfig* base_co program->module = mod; // TODO split the compilation pipeline into generic and non-generic parts - append_list(Program*, runtime->programs, program); + shd_list_append(Program*, runtime->programs, program); return program; } diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index e7eba062d..7f31a1edb 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -50,7 +50,7 @@ int main(int argc, char* argv[]) { IrArena* arena = NULL; ArenaConfig aconfig = default_arena_config(&args.driver_config.config.target); arena = new_ir_arena(&aconfig); - if (entries_count_list(args.driver_config.input_filenames) == 0) { + if (shd_list_count(args.driver_config.input_filenames) == 0) { Module* module; driver_load_source_file(&args.driver_config.config, SrcSlim, strlen(default_shader), default_shader, "runtime_test", &module); program = new_program_from_module(runtime, &args.driver_config.config, module); diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index 91d499439..91988e9de 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -326,17 +326,17 @@ bool probe_vkr_devices(VkrBackend* runtime) { .launch_kernel = (Command*(*)(Device*, Program*, String, int, int, int, int, void**, ExtraKernelOptions*)) vkr_launch_kernel, .can_import_host_memory = (bool(*)(Device*)) vkr_can_import_host_memory, }; - append_list(Device*, runtime->base.runtime->devices, device); + shd_list_append(Device*, runtime->base.runtime->devices, device); } } - if (entries_count_list(runtime->base.runtime->devices) == 0 && !runtime->base.runtime->config.allow_no_devices) { + if (shd_list_count(runtime->base.runtime->devices) == 0 && !runtime->base.runtime->config.allow_no_devices) { error_print("No __suitable__ vulkan devices found!\n"); error_print("This is caused by running on weird hardware configurations. Hardware support might get better in the future.\n"); return false; } - info_print("Found %d usable devices\n", entries_count_list(runtime->base.runtime->devices)); + info_print("Found %d usable devices\n", shd_list_count(runtime->base.runtime->devices)); return true; } diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 0b3efbd5a..ea3121f92 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -106,7 +106,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay int set = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(lookup_annotation(decl, "DescriptorSet"))), false); int binding = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(lookup_annotation(decl, "DescriptorBinding"))), false); - ProgramResourceInfo* res_info = arena_alloc(program->arena, sizeof(ProgramResourceInfo)); + ProgramResourceInfo* res_info = shd_arena_alloc(program->arena, sizeof(ProgramResourceInfo)); *res_info = (ProgramResourceInfo) { .is_bound = true, .as = as, @@ -125,7 +125,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay member_t = get_pointee_type(member_t->arena, member_t); TypeMemLayout layout = get_mem_layout(program->specialized_module->arena, member_t); - ProgramResourceInfo* constant_res_info = arena_alloc(program->arena, sizeof(ProgramResourceInfo)); + ProgramResourceInfo* constant_res_info = shd_arena_alloc(program->arena, sizeof(ProgramResourceInfo)); *constant_res_info = (ProgramResourceInfo) { .parent = res_info, .as = as, @@ -485,7 +485,7 @@ static VkrSpecProgram* create_specialized_program(SpecProgramKey key, VkrDevice* spec_program->key = key; spec_program->device = device; spec_program->specialized_module = key.base->module; - spec_program->arena = new_arena(); + spec_program->arena = shd_new_arena(); CHECK(compile_specialized_program(spec_program), return NULL); CHECK(extract_layout(spec_program), return NULL); @@ -525,6 +525,6 @@ void destroy_specialized_program(VkrSpecProgram* spec) { } free(spec->resources.resources); vkDestroyDescriptorPool(spec->device->device, spec->descriptor_pool, NULL); - destroy_arena(spec->arena); + shd_destroy_arena(spec->arena); free(spec); } diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index c3b9c6566..b514c7ca9 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -132,7 +132,7 @@ static void strongconnect(CGNode* v, int* index, struct List* stack) { v->tarjan.index = *index; v->tarjan.lowlink = *index; (*index)++; - append_list(const Node*, stack, v); + shd_list_append(const Node*, stack, v); v->tarjan.on_stack = true; // Consider successors of v @@ -158,13 +158,13 @@ static void strongconnect(CGNode* v, int* index, struct List* stack) { // If v is a root node, pop the stack and generate an SCC if (v->tarjan.lowlink == v->tarjan.index) { - LARRAY(CGNode*, scc, entries_count_list(stack)); + LARRAY(CGNode*, scc, shd_list_count(stack)); size_t scc_size = 0; { CGNode* w; - assert(entries_count_list(stack) > 0); + assert(shd_list_count(stack) > 0); do { - w = pop_last_list(CGNode*, stack); + w = shd_list_pop(CGNode*, stack); w->tarjan.on_stack = false; scc[scc_size++] = w; } while (v != w); @@ -182,7 +182,7 @@ static void strongconnect(CGNode* v, int* index, struct List* stack) { static void tarjan(struct Dict* verts) { int index = 0; - struct List* stack = new_list(CGNode*); + struct List* stack = shd_new_list(CGNode*); size_t iter = 0; CGNode* n; @@ -191,7 +191,7 @@ static void tarjan(struct Dict* verts) { strongconnect(n, &index, stack); } - destroy_list(stack); + shd_destroy_list(stack); } CallGraph* new_callgraph(Module* mod) { diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index f68b922f6..4b6c23dbb 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -15,14 +15,14 @@ #pragma GCC diagnostic error "-Wswitch" struct List* build_cfgs(Module* mod, CFGBuildConfig config) { - struct List* cfgs = new_list(CFG*); + struct List* cfgs = shd_new_list(CFG*); Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag != Function_TAG) continue; CFG* cfg = build_cfg(decl, decl, config); - append_list(CFG*, cfgs, cfg); + shd_list_append(CFG*, cfgs, cfg); } return cfgs; @@ -62,10 +62,10 @@ CFNode* cfg_lookup(CFG* cfg, const Node* abs) { } static CFNode* new_cfnode(Arena* a) { - CFNode* new = arena_alloc(a, sizeof(CFNode)); + CFNode* new = shd_arena_alloc(a, sizeof(CFNode)); *new = (CFNode) { - .succ_edges = new_list(CFEdge), - .pred_edges = new_list(CFEdge), + .succ_edges = shd_new_list(CFEdge), + .pred_edges = shd_new_list(CFEdge), .rpo_index = SIZE_MAX, .idom = NULL, .dominates = NULL, @@ -85,7 +85,7 @@ static CFNode* get_or_enqueue(CfgBuildContext* ctx, const Node* abs) { assert(abs && new->node); insert_dict(const Node*, CFNode*, ctx->nodes, abs, new); process_cf_node(ctx, new); - append_list(Node*, ctx->contents, new); + shd_list_append(Node*, ctx->contents, new); return new; } @@ -97,11 +97,11 @@ static bool in_loop(LoopTree* lt, const Node* fn, const Node* loopentry, const N while (parent) { // we're not in a loop like we're expected to - if (entries_count_list(parent->cf_nodes) == 0 && loopentry == fn) + if (shd_list_count(parent->cf_nodes) == 0 && loopentry == fn) return true; // we are in the loop we were expected to - if (entries_count_list(parent->cf_nodes) == 1 && read_list(CFNode*, parent->cf_nodes)[0]->node == loopentry) + if (shd_list_count(parent->cf_nodes) == 1 && shd_read_list(CFNode*, parent->cf_nodes)[0]->node == loopentry) return true; parent = parent->parent; @@ -132,8 +132,8 @@ static void add_edge(CfgBuildContext* ctx, const Node* src, const Node* dst, CFE .jump = j, .terminator = term, }; - append_list(CFEdge, src_node->succ_edges, edge); - append_list(CFEdge, dst_node->pred_edges, edge); + shd_list_append(CFEdge, src_node->succ_edges, edge); + shd_list_append(CFEdge, dst_node->pred_edges, edge); } static void add_structural_edge(CfgBuildContext* ctx, CFNode* parent, const Node* dst, CFEdgeType type, const Node* term) { @@ -258,29 +258,29 @@ static void flip_cfg(CFG* cfg) { cfg->entry = NULL; for (size_t i = 0; i < cfg->size; i++) { - CFNode* cur = read_list(CFNode*, cfg->contents)[i]; + CFNode* cur = shd_read_list(CFNode*, cfg->contents)[i]; struct List* tmp = cur->succ_edges; cur->succ_edges = cur->pred_edges; cur->pred_edges = tmp; - for (size_t j = 0; j < entries_count_list(cur->succ_edges); j++) { - CFEdge* edge = &read_list(CFEdge, cur->succ_edges)[j]; + for (size_t j = 0; j < shd_list_count(cur->succ_edges); j++) { + CFEdge* edge = &shd_read_list(CFEdge, cur->succ_edges)[j]; CFNode* tmp2 = edge->dst; edge->dst = edge->src; edge->src = tmp2; } - for (size_t j = 0; j < entries_count_list(cur->pred_edges); j++) { - CFEdge* edge = &read_list(CFEdge, cur->pred_edges)[j]; + for (size_t j = 0; j < shd_list_count(cur->pred_edges); j++) { + CFEdge* edge = &shd_read_list(CFEdge, cur->pred_edges)[j]; CFNode* tmp2 = edge->dst; edge->dst = edge->src; edge->src = tmp2; } - if (entries_count_list(cur->pred_edges) == 0) { + if (shd_list_count(cur->pred_edges) == 0) { if (cfg->entry != NULL) { if (cfg->entry->node) { CFNode* new_entry = new_cfnode(cfg->arena); @@ -289,8 +289,8 @@ static void flip_cfg(CFG* cfg) { .src = new_entry, .dst = cfg->entry }; - append_list(CFEdge, new_entry->succ_edges, prev_entry_edge); - append_list(CFEdge, cfg->entry->pred_edges, prev_entry_edge); + shd_list_append(CFEdge, new_entry->succ_edges, prev_entry_edge); + shd_list_append(CFEdge, cfg->entry->pred_edges, prev_entry_edge); cfg->entry = new_entry; } @@ -299,8 +299,8 @@ static void flip_cfg(CFG* cfg) { .src = cfg->entry, .dst = cur }; - append_list(CFEdge, cfg->entry->succ_edges, new_edge); - append_list(CFEdge, cur->pred_edges, new_edge); + shd_list_append(CFEdge, cfg->entry->succ_edges, new_edge); + shd_list_append(CFEdge, cur->pred_edges, new_edge); } else { cfg->entry = cur; } @@ -310,19 +310,19 @@ static void flip_cfg(CFG* cfg) { assert(cfg->entry); if (!cfg->entry->node) { cfg->size += 1; - append_list(Node*, cfg->contents, cfg->entry); + shd_list_append(Node*, cfg->contents, cfg->entry); } } static void validate_cfg(CFG* cfg) { for (size_t i = 0; i < cfg->size; i++) { - CFNode* node = read_list(CFNode*, cfg->contents)[i]; + CFNode* node = shd_read_list(CFNode*, cfg->contents)[i]; size_t structured_body_uses = 0; size_t num_jumps = 0; size_t num_exits = 0; bool is_tail = false; - for (size_t j = 0; j < entries_count_list(node->pred_edges); j++) { - CFEdge edge = read_list(CFEdge, node->pred_edges)[j]; + for (size_t j = 0; j < shd_list_count(node->pred_edges); j++) { + CFEdge edge = shd_read_list(CFEdge, node->pred_edges)[j]; switch (edge.type) { case JumpEdge: num_jumps++; @@ -363,8 +363,8 @@ static void validate_cfg(CFG* cfg) { static void mark_reachable(CFNode* n) { if (!n->reachable) { n->reachable = true; - for (size_t i = 0; i < entries_count_list(n->succ_edges); i++) { - CFEdge e = read_list(CFEdge, n->succ_edges)[i]; + for (size_t i = 0; i < shd_list_count(n->succ_edges); i++) { + CFEdge e = shd_read_list(CFEdge, n->succ_edges)[i]; if (e.type == StructuredTailEdge) continue; mark_reachable(e.dst); @@ -375,7 +375,7 @@ static void mark_reachable(CFNode* n) { CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { assert(function && function->tag == Function_TAG); assert(is_abstraction(entry)); - Arena* arena = new_arena(); + Arena* arena = shd_new_arena(); CfgBuildContext context = { .arena = arena, @@ -383,7 +383,7 @@ CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { .entry = entry, .nodes = new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), .join_point_values = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .contents = new_list(CFNode*), + .contents = shd_new_list(CFNode*), .config = config, }; @@ -403,7 +403,7 @@ CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { .arena = arena, .config = config, .entry = entry_node, - .size = entries_count_list(context.contents), + .size = shd_list_count(context.contents), .flipped = config.flipped, .contents = context.contents, .map = context.nodes, @@ -424,25 +424,25 @@ CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { void destroy_cfg(CFG* cfg) { bool entry_destroyed = false; for (size_t i = 0; i < cfg->size; i++) { - CFNode* node = read_list(CFNode*, cfg->contents)[i]; + CFNode* node = shd_read_list(CFNode*, cfg->contents)[i]; entry_destroyed |= node == cfg->entry; - destroy_list(node->pred_edges); - destroy_list(node->succ_edges); + shd_destroy_list(node->pred_edges); + shd_destroy_list(node->succ_edges); if (node->dominates) - destroy_list(node->dominates); + shd_destroy_list(node->dominates); if (node->structurally_dominates) destroy_dict(node->structurally_dominates); } if (!entry_destroyed) { - destroy_list(cfg->entry->pred_edges); - destroy_list(cfg->entry->succ_edges); + shd_destroy_list(cfg->entry->pred_edges); + shd_destroy_list(cfg->entry->succ_edges); if (cfg->entry->dominates) - destroy_list(cfg->entry->dominates); + shd_destroy_list(cfg->entry->dominates); } destroy_dict(cfg->map); - destroy_arena(cfg->arena); + shd_destroy_arena(cfg->arena); free(cfg->rpo); - destroy_list(cfg->contents); + shd_destroy_list(cfg->contents); free(cfg); } @@ -450,8 +450,8 @@ static size_t post_order_visit(CFG* cfg, CFNode* n, size_t i) { n->rpo_index = -2; for (int phase = 0; phase < 2; phase++) { - for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { - CFEdge edge = read_list(CFEdge, n->succ_edges)[j]; + for (size_t j = 0; j < shd_list_count(n->succ_edges); j++) { + CFEdge edge = shd_read_list(CFEdge, n->succ_edges)[j]; // always visit structured tail edges last if ((edge.type == StructuredTailEdge) == (phase == 0)) continue; @@ -486,8 +486,8 @@ void compute_rpo(CFG* cfg) { } bool is_cfnode_structural_target(CFNode* cfn) { - for (size_t i = 0; i < entries_count_list(cfn->pred_edges); i++) { - if (read_list(CFEdge, cfn->pred_edges)[i].type != JumpEdge) + for (size_t i = 0; i < shd_list_count(cfn->pred_edges); i++) { + if (shd_read_list(CFEdge, cfn->pred_edges)[i].type != JumpEdge) return true; } return false; @@ -518,20 +518,20 @@ bool cfg_is_dominated(CFNode* a, CFNode* b) { void compute_domtree(CFG* cfg) { for (size_t i = 0; i < cfg->size; i++) { - CFNode* n = read_list(CFNode*, cfg->contents)[i]; + CFNode* n = shd_read_list(CFNode*, cfg->contents)[i]; if (n == cfg->entry/* || !n->reachable*/) continue; CFNode* structured_idom = NULL; - for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { - CFEdge e = read_list(CFEdge, n->pred_edges)[j]; + for (size_t j = 0; j < shd_list_count(n->pred_edges); j++) { + CFEdge e = shd_read_list(CFEdge, n->pred_edges)[j]; if (e.type == StructuredTailEdge) { structured_idom = n->structured_idom = e.src; n->structured_idom_edge = e; continue; } } - for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { - CFEdge e = read_list(CFEdge, n->pred_edges)[j]; + for (size_t j = 0; j < shd_list_count(n->pred_edges); j++) { + CFEdge e = shd_read_list(CFEdge, n->pred_edges)[j]; if (e.src->rpo_index < n->rpo_index) { n->idom = e.src; goto outer_loop; @@ -548,12 +548,12 @@ void compute_domtree(CFG* cfg) { while (todo) { todo = false; for (size_t i = 0; i < cfg->size; i++) { - CFNode* n = read_list(CFNode*, cfg->contents)[i]; + CFNode* n = shd_read_list(CFNode*, cfg->contents)[i]; if (n == cfg->entry || n->structured_idom) continue; CFNode* new_idom = NULL; - for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { - CFEdge e = read_list(CFEdge, n->pred_edges)[j]; + for (size_t j = 0; j < shd_list_count(n->pred_edges); j++) { + CFEdge e = shd_read_list(CFEdge, n->pred_edges)[j]; if (e.type == StructuredTailEdge) continue; CFNode* p = e.src; @@ -569,12 +569,12 @@ void compute_domtree(CFG* cfg) { for (size_t i = 0; i < cfg->size; i++) { CFNode* n = cfg->rpo[i]; - n->dominates = new_list(CFNode*); + n->dominates = shd_new_list(CFNode*); } for (size_t i = 0; i < cfg->size; i++) { CFNode* n = cfg->rpo[i]; if (!n->idom) continue; - append_list(CFNode*, n->idom->dominates, n); + shd_list_append(CFNode*, n->idom->dominates, n); } } diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index c55dd78bb..72b0bd713 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -103,16 +103,16 @@ static void dump_cfg(FILE* output, CFG* cfg) { const Node* entry = cfg->entry->node; fprintf(output, "subgraph cluster_%d {\n", entry->id); fprintf(output, "label = \"%s\";\n", get_abstraction_name_safe(entry)); - for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { - const CFNode* n = read_list(const CFNode*, cfg->contents)[i]; + for (size_t i = 0; i < shd_list_count(cfg->contents); i++) { + const CFNode* n = shd_read_list(const CFNode*, cfg->contents)[i]; dump_cf_node(output, n); } - for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { - const CFNode* bb_node = read_list(const CFNode*, cfg->contents)[i]; + for (size_t i = 0; i < shd_list_count(cfg->contents); i++) { + const CFNode* bb_node = shd_read_list(const CFNode*, cfg->contents)[i]; const CFNode* src_node = bb_node; - for (size_t j = 0; j < entries_count_list(bb_node->succ_edges); j++) { - CFEdge edge = read_list(CFEdge, bb_node->succ_edges)[j]; + for (size_t j = 0; j < shd_list_count(bb_node->succ_edges); j++) { + CFEdge edge = shd_read_list(CFEdge, bb_node->succ_edges)[j]; const CFNode* target_node = edge.dst; String edge_color = "black"; String edge_style = "solid"; @@ -154,12 +154,12 @@ void dump_cfgs(FILE* output, Module* mod) { fprintf(output, "digraph G {\n"); struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); - for (size_t i = 0; i < entries_count_list(cfgs); i++) { - CFG* cfg = read_list(CFG*, cfgs)[i]; + for (size_t i = 0; i < shd_list_count(cfgs); i++) { + CFG* cfg = shd_read_list(CFG*, cfgs)[i]; dump_cfg(output, cfg); destroy_cfg(cfg); } - destroy_list(cfgs); + shd_destroy_list(cfgs); fprintf(output, "}\n"); } @@ -176,8 +176,8 @@ static void dump_domtree_cfnode(Printer* p, CFNode* idom) { else print(p, "bb_%zu [label=\"%%%d\", shape=box];\n", (size_t) idom, idom->node->id); - for (size_t i = 0; i < entries_count_list(idom->dominates); i++) { - CFNode* child = read_list(CFNode*, idom->dominates)[i]; + for (size_t i = 0; i < shd_list_count(idom->dominates); i++) { + CFNode* child = shd_read_list(CFNode*, idom->dominates)[i]; dump_domtree_cfnode(p, child); print(p, "bb_%zu -> bb_%zu;\n", (size_t) (idom), (size_t) (child)); } @@ -192,12 +192,12 @@ void dump_domtree_cfg(Printer* p, CFG* s) { void dump_domtree_module(Printer* p, Module* mod) { print(p, "digraph G {\n"); struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); - for (size_t i = 0; i < entries_count_list(cfgs); i++) { - CFG* cfg = read_list(CFG*, cfgs)[i]; + for (size_t i = 0; i < shd_list_count(cfgs); i++) { + CFG* cfg = shd_read_list(CFG*, cfgs)[i]; dump_domtree_cfg(p, cfg); destroy_cfg(cfg); } - destroy_list(cfgs); + shd_destroy_list(cfgs); print(p, "}\n"); } diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index 72f5197ea..a3a2d1c67 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -30,11 +30,11 @@ LTNode* new_lf_node(int type, LTNode* parent, int depth, struct List* cf_nodes) LTNode* n = calloc(sizeof(LTNode), 1); n->parent = parent; n->type = type; - n->lf_children = new_list(LTNode*); + n->lf_children = shd_new_list(LTNode*); n->cf_nodes = cf_nodes; n->depth = depth; if (parent) { - append_list(LTNode*, parent->lf_children, n); + shd_list_append(LTNode*, parent->lf_children, n); } return n; } @@ -51,8 +51,8 @@ LTNode* new_lf_node(int type, LTNode* parent, int depth, struct List* cf_nodes) static bool is_leaf(LoopTreeBuilder* ltb, const CFNode* n, size_t num) { if (num == 1) { struct List* succ_edges = n->succ_edges; - for (size_t i = 0; i < entries_count_list(succ_edges); i++) { - CFEdge e = read_list(CFEdge, succ_edges)[i]; + for (size_t i = 0; i < shd_list_count(succ_edges); i++) { + CFEdge e = shd_read_list(CFEdge, succ_edges)[i]; CFNode* succ = e.dst; if (!is_head(ltb, succ) && n == succ) return false; @@ -70,7 +70,7 @@ static int visit(LoopTreeBuilder* ltb, const CFNode* n, int counter) { ltb->states[n->rpo_index].dfs = counter; ltb->states[n->rpo_index].low_link = counter; // push it - append_list(const CFNode*, ltb->stack, n); + shd_list_append(const CFNode*, ltb->stack, n); on_stack(ltb, n) = true; return counter + 1; } @@ -78,8 +78,8 @@ static int visit(LoopTreeBuilder* ltb, const CFNode* n, int counter) { static int walk_scc(LoopTreeBuilder* ltb, const CFNode* cur, LTNode* parent, int depth, int scc_counter) { scc_counter = visit(ltb, cur, scc_counter); - for (size_t succi = 0; succi < entries_count_list(cur->succ_edges); succi++) { - CFEdge succe = read_list(CFEdge, cur->succ_edges)[succi]; + for (size_t succi = 0; succi < shd_list_count(cur->succ_edges); succi++) { + CFEdge succe = shd_read_list(CFEdge, cur->succ_edges)[succi]; CFNode* succ = succe.dst; if (is_head(ltb, succ)) continue; // this is a backedge @@ -93,30 +93,30 @@ static int walk_scc(LoopTreeBuilder* ltb, const CFNode* cur, LTNode* parent, int // root of SCC if (lowlink(ltb, cur) == dfs(ltb, cur)) { - struct List* heads = new_list(const CFNode*); + struct List* heads = shd_new_list(const CFNode*); // mark all cf_nodes in current SCC (all cf_nodes from back to cur on the stack) as 'in_scc' - size_t num = 0, e = entries_count_list(ltb->stack); + size_t num = 0, e = shd_list_count(ltb->stack); size_t b = e - 1; do { - in_scc(ltb, read_list(const CFNode*, ltb->stack)[b]) = true; + in_scc(ltb, shd_read_list(const CFNode*, ltb->stack)[b]) = true; ++num; - } while (read_list(const CFNode*, ltb->stack)[b--] != cur); + } while (shd_read_list(const CFNode*, ltb->stack)[b--] != cur); // for all cf_nodes in current SCC for (size_t i = ++b; i != e; i++) { - const CFNode* n = read_list(const CFNode*, ltb->stack)[i]; + const CFNode* n = shd_read_list(const CFNode*, ltb->stack)[i]; if (ltb->s->entry == n) { - append_list(const CFNode*, heads, n); // entries are axiomatically heads + shd_list_append(const CFNode*, heads, n); // entries are axiomatically heads } else { - for (size_t j = 0; j < entries_count_list(n->pred_edges); j++) { - assert(n == read_list(CFEdge, n->pred_edges)[j].dst); - const CFNode* pred = read_list(CFEdge, n->pred_edges)[j].src; + for (size_t j = 0; j < shd_list_count(n->pred_edges); j++) { + assert(n == shd_read_list(CFEdge, n->pred_edges)[j].dst); + const CFNode* pred = shd_read_list(CFEdge, n->pred_edges)[j].src; // all backedges are also inducing heads // but do not yet mark them globally as head -- we are still running through the SCC if (!in_scc(ltb, pred)) { - append_list(const CFNode*, heads, n); + shd_list_append(const CFNode*, heads, n); break; } } @@ -124,7 +124,7 @@ static int walk_scc(LoopTreeBuilder* ltb, const CFNode* cur, LTNode* parent, int } if (is_leaf(ltb, cur, num)) { - assert(entries_count_list(heads) == 1); + assert(shd_list_count(heads) == 1); new_lf_node(LF_LEAF, parent, depth, heads); } else { new_lf_node(LF_HEAD, parent, depth, heads); @@ -132,13 +132,13 @@ static int walk_scc(LoopTreeBuilder* ltb, const CFNode* cur, LTNode* parent, int // reset in_scc and on_stack flags for (size_t i = b; i != e; ++i) { - in_scc(ltb, read_list(const CFNode*, ltb->stack)[i]) = false; - on_stack(ltb, read_list(const CFNode*, ltb->stack)[i]) = false; + in_scc(ltb, shd_read_list(const CFNode*, ltb->stack)[i]) = false; + on_stack(ltb, shd_read_list(const CFNode*, ltb->stack)[i]) = false; } // pop whole SCC - while (entries_count_list(ltb->stack) != b) { - pop_last_list(const CFNode*, ltb->stack); + while (shd_list_count(ltb->stack) != b) { + shd_list_pop(const CFNode*, ltb->stack); } } @@ -153,22 +153,22 @@ static void clear_set(LoopTreeBuilder* ltb) { static void recurse(LoopTreeBuilder* ltb, LTNode* parent, struct List* heads, int depth) { assert(parent->type == LF_HEAD); size_t cur_new_child = 0; - for (size_t i = 0; i < entries_count_list(heads); i++) { - const CFNode* head = read_list(const CFNode*, heads)[i]; + for (size_t i = 0; i < shd_list_count(heads); i++) { + const CFNode* head = shd_read_list(const CFNode*, heads)[i]; clear_set(ltb); walk_scc(ltb, head, parent, depth, 0); - for (size_t e = entries_count_list(parent->lf_children); cur_new_child != e; ++cur_new_child) { - struct List* new_child_nodes = read_list(LTNode*, parent->lf_children)[cur_new_child]->cf_nodes; - for (size_t j = 0; j < entries_count_list(new_child_nodes); j++) { - CFNode* head2 = read_list(CFNode*, new_child_nodes)[j]; + for (size_t e = shd_list_count(parent->lf_children); cur_new_child != e; ++cur_new_child) { + struct List* new_child_nodes = shd_read_list(LTNode*, parent->lf_children)[cur_new_child]->cf_nodes; + for (size_t j = 0; j < shd_list_count(new_child_nodes); j++) { + CFNode* head2 = shd_read_list(CFNode*, new_child_nodes)[j]; is_head(ltb, head2) = true; } } } - for (size_t i = 0; i < entries_count_list(parent->lf_children); i++) { - LTNode* node = read_list(LTNode*, parent->lf_children)[i]; + for (size_t i = 0; i < shd_list_count(parent->lf_children); i++) { + LTNode* node = shd_read_list(LTNode*, parent->lf_children)[i]; if (node->type == LF_HEAD) recurse(ltb, node, node->cf_nodes, depth + 1); } @@ -176,12 +176,12 @@ static void recurse(LoopTreeBuilder* ltb, LTNode* parent, struct List* heads, in static void build_map_recursive(struct Dict* map, LTNode* n) { if (n->type == LF_LEAF) { - assert(entries_count_list(n->cf_nodes) == 1); - const Node* node = read_list(CFNode*, n->cf_nodes)[0]->node; + assert(shd_list_count(n->cf_nodes) == 1); + const Node* node = shd_read_list(CFNode*, n->cf_nodes)[0]->node; insert_dict(const Node*, LTNode*, map, node, n); } else { - for (size_t i = 0; i < entries_count_list(n->lf_children); i++) { - LTNode* child = read_list(LTNode*, n->lf_children)[i]; + for (size_t i = 0; i < shd_list_count(n->lf_children); i++) { + LTNode* child = shd_read_list(LTNode*, n->lf_children)[i]; build_map_recursive(map, child); } } @@ -208,18 +208,18 @@ LoopTree* build_loop_tree(CFG* s) { LoopTreeBuilder ltb = { .states = states, .s = s, - .stack = new_list(const CFNode*), + .stack = shd_new_list(const CFNode*), }; LoopTree* lt = calloc(sizeof(LoopTree), 1); - struct List* empty_list = new_list(CFNode*); + struct List* empty_list = shd_new_list(CFNode*); lt->root = new_lf_node(LF_HEAD, NULL, 0, empty_list); const CFNode* entry = s->entry; - struct List* global_heads = new_list(const CFNode*); - append_list(const CFNode*, global_heads, entry); + struct List* global_heads = shd_new_list(const CFNode*); + shd_list_append(const CFNode*, global_heads, entry); recurse(<b, lt->root, global_heads, 1); - destroy_list(global_heads); - destroy_list(ltb.stack); + shd_destroy_list(global_heads); + shd_destroy_list(ltb.stack); lt->map = new_dict(const Node*, LTNode*, (HashFn) hash_node, (CmpFn) compare_node); build_map_recursive(lt->map, lt->root); @@ -228,11 +228,11 @@ LoopTree* build_loop_tree(CFG* s) { } static void destroy_lt_node(LTNode* n) { - for (size_t i = 0; i < entries_count_list(n->lf_children); i++) { - destroy_lt_node(read_list(LTNode*, n->lf_children)[i]); + for (size_t i = 0; i < shd_list_count(n->lf_children); i++) { + destroy_lt_node(shd_read_list(LTNode*, n->lf_children)[i]); } - destroy_list(n->lf_children); - destroy_list(n->cf_nodes); + shd_destroy_list(n->lf_children); + shd_destroy_list(n->cf_nodes); free(n); } @@ -247,7 +247,7 @@ static int extra_uniqueness = 0; static void dump_lt_node(FILE* f, const LTNode* n) { if (n->type == LF_HEAD) { fprintf(f, "subgraph cluster_%d {\n", extra_uniqueness++); - if (entries_count_list(n->cf_nodes) == 0) { + if (shd_list_count(n->cf_nodes) == 0) { fprintf(f, "label = \"%s\";\n", "Entry"); } else { fprintf(f, "label = \"%s\";\n", "LoopHead"); @@ -257,13 +257,13 @@ static void dump_lt_node(FILE* f, const LTNode* n) { fprintf(f, "label = \"%s\";\n", "Leaf"); } - for (size_t i = 0; i < entries_count_list(n->cf_nodes); i++) { - const Node* bb = read_list(const CFNode*, n->cf_nodes)[i]->node; + for (size_t i = 0; i < shd_list_count(n->cf_nodes); i++) { + const Node* bb = shd_read_list(const CFNode*, n->cf_nodes)[i]->node; fprintf(f, "bb_%d[label=\"%s\"];\n", extra_uniqueness++, get_abstraction_name_safe(bb)); } - for (size_t i = 0; i < entries_count_list(n->lf_children); i++) { - const LTNode* child = read_list(const LTNode*, n->lf_children)[i]; + for (size_t i = 0; i < shd_list_count(n->lf_children); i++) { + const LTNode* child = shd_read_list(const LTNode*, n->lf_children)[i]; dump_lt_node(f, child); } @@ -285,14 +285,14 @@ void dump_loop_trees(FILE* output, Module* mod) { fprintf(output, "digraph G {\n"); struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); - for (size_t i = 0; i < entries_count_list(cfgs); i++) { - CFG* cfg = read_list(CFG*, cfgs)[i]; + for (size_t i = 0; i < shd_list_count(cfgs); i++) { + CFG* cfg = shd_read_list(CFG*, cfgs)[i]; LoopTree* lt = build_loop_tree(cfg); dump_loop_tree(output, lt); destroy_loop_tree(lt); destroy_cfg(cfg); } - destroy_list(cfgs); + shd_destroy_list(cfgs); fprintf(output, "}\n"); } diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index 364628716..b4eed1139 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -44,7 +44,7 @@ static void uses_visit_node(UsesMapVisitor* v, const Node* n) { } static void uses_visit_op(UsesMapVisitor* v, NodeClass class, String op_name, const Node* op, size_t i) { - Use* use = arena_alloc(v->map->a, sizeof(Use)); + Use* use = shd_arena_alloc(v->map->a, sizeof(Use)); memset(use, 0, sizeof(Use)); *use = (Use) { .user = v->user, @@ -67,7 +67,7 @@ static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeCl UsesMap* uses = calloc(sizeof(UsesMap), 1); *uses = (UsesMap) { .map = new_dict(const Node*, Use*, (HashFn) hash_node, (CmpFn) compare_node), - .a = new_arena(), + .a = shd_new_arena(), }; UsesMapVisitor v = { @@ -96,7 +96,7 @@ const UsesMap* create_module_uses_map(const Module* m, NodeClass exclude) { } void destroy_uses_map(const UsesMap* map) { - destroy_arena(map->a); + shd_destroy_arena(map->a); destroy_dict(map->map); free((void*) map); } diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 353534b89..c61b1daf9 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -44,8 +44,8 @@ static void verify_same_arena(Module* mod) { static void verify_scoping(const CompilerConfig* config, Module* mod) { struct List* cfgs = build_cfgs(mod, structured_scope_cfg_build()); - for (size_t i = 0; i < entries_count_list(cfgs); i++) { - CFG* cfg = read_list(CFG*, cfgs)[i]; + for (size_t i = 0; i < shd_list_count(cfgs); i++) { + CFG* cfg = shd_read_list(CFG*, cfgs)[i]; Scheduler* scheduler = new_scheduler(cfg); struct Dict* set = free_frontier(scheduler, cfg, cfg->entry->node); if (entries_count_dict(set) > 0) { @@ -68,7 +68,7 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { destroy_scheduler(scheduler); destroy_cfg(cfg); } - destroy_list(cfgs); + shd_destroy_list(cfgs); } static void verify_nominal_node(const Node* fn, const Node* n) { @@ -137,8 +137,8 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { static void verify_bodies(const CompilerConfig* config, Module* mod) { struct List* cfgs = build_cfgs(mod, structured_scope_cfg_build()); - for (size_t i = 0; i < entries_count_list(cfgs); i++) { - CFG* cfg = read_list(CFG*, cfgs)[i]; + for (size_t i = 0; i < shd_list_count(cfgs); i++) { + CFG* cfg = shd_read_list(CFG*, cfgs)[i]; for (size_t j = 0; j < cfg->size; j++) { CFNode* n = cfg->rpo[j]; @@ -149,7 +149,7 @@ static void verify_bodies(const CompilerConfig* config, Module* mod) { destroy_cfg(cfg); } - destroy_list(cfgs); + shd_destroy_list(cfgs); Nodes decls = get_module_declarations(mod); for (size_t i = 0; i < decls.count; i++) { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index c3d8d3956..dc4a142c7 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -26,7 +26,7 @@ BodyBuilder* begin_body_with_mem(IrArena* a, const Node* mem) { BodyBuilder* bb = malloc(sizeof(BodyBuilder)); *bb = (BodyBuilder) { .arena = a, - .stack = new_list(StackEntry), + .stack = shd_new_list(StackEntry), .mem = mem, }; return bb; @@ -92,9 +92,9 @@ Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, s static const Node* build_body(BodyBuilder* bb, const Node* terminator) { IrArena* a = bb->arena; - size_t stack_size = entries_count_list(bb->stack); + size_t stack_size = shd_list_count(bb->stack); for (size_t i = stack_size - 1; i < stack_size; i--) { - StackEntry entry = read_list(StackEntry, bb->stack)[i]; + StackEntry entry = shd_read_list(StackEntry, bb->stack)[i]; const Node* t2 = terminator; switch (entry.structured.tag) { case NotAStructured_construct: error("") @@ -123,7 +123,7 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { const Node* finish_body(BodyBuilder* bb, const Node* terminator) { assert(bb->mem && !bb->block_entry_mem); terminator = build_body(bb, terminator); - destroy_list(bb->stack); + shd_destroy_list(bb->stack); free(bb); return terminator; } @@ -180,7 +180,7 @@ const Node* finish_body_with_jump(BodyBuilder* bb, const Node* target, Nodes arg const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { IrArena* a = bb->arena; - if (!bb->tail_block && entries_count_list(bb->stack) == 0) { + if (!bb->tail_block && shd_list_count(bb->stack) == 0) { const Node* last_mem = bb_mem(bb); cancel_body(bb); if (last_mem) @@ -206,13 +206,13 @@ const Node* yield_values_and_wrap_in_block(BodyBuilder* bb, Nodes values) { const Node* finish_block_body(BodyBuilder* bb, const Node* terminator) { assert(bb->block_entry_mem); terminator = build_body(bb, terminator); - destroy_list(bb->stack); + shd_destroy_list(bb->stack); free(bb); return terminator; } const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* instruction) { - size_t stack_size = entries_count_list(bb->stack); + size_t stack_size = shd_list_count(bb->stack); if (stack_size == 0) { cancel_body(bb); return instruction; @@ -223,7 +223,7 @@ const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { IrArena* arena = bb->arena; - assert(!bb->mem && !bb->block_entry_mem && entries_count_list(bb->stack) == 0); + assert(!bb->mem && !bb->block_entry_mem && shd_list_count(bb->stack) == 0); cancel_body(bb); return maybe_tuple_helper(arena, values); } @@ -271,7 +271,7 @@ Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constru } } bb->mem = get_abstraction_mem(tail); - append_list(StackEntry , bb->stack, entry); + shd_list_append(StackEntry , bb->stack, entry); bb->tail_block = tail; return entry.vars; } @@ -362,12 +362,12 @@ begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes } void cancel_body(BodyBuilder* bb) { - for (size_t i = 0; i < entries_count_list(bb->stack); i++) { - StackEntry entry = read_list(StackEntry, bb->stack)[i]; + for (size_t i = 0; i < shd_list_count(bb->stack); i++) { + StackEntry entry = shd_read_list(StackEntry, bb->stack)[i]; // if (entry.structured.tag != NotAStructured_construct) // destroy_list(entry.structured.stack); } - destroy_list(bb->stack); + shd_destroy_list(bb->stack); //destroy_list(bb->stack_stack); free(bb); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index adb295283..6d7335fdf 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -51,7 +51,7 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { assert(is_type(node.type)); // place the node in the arena and return it - Node* alloc = (Node*) arena_alloc(arena->arena, sizeof(Node)); + Node* alloc = (Node*) shd_arena_alloc(arena->arena, sizeof(Node)); *alloc = node; alloc->id = allocate_node_id(arena, alloc); insert_set_get_result(const Node*, arena->node_set, alloc); diff --git a/src/shady/generator/import_spv_defs.c b/src/shady/generator/import_spv_defs.c index 3b6318008..cb840e5e3 100644 --- a/src/shady/generator/import_spv_defs.c +++ b/src/shady/generator/import_spv_defs.c @@ -69,7 +69,7 @@ void apply_instruction_filter(json_object* filter, json_object* instruction, jso json_object_object_foreach(filter_name, match_name, subfilter) { if (strcmp(name, match_name) == 0) { found = true; - append_list(json_object*, pending, subfilter); + shd_list_append(json_object*, pending, subfilter); } } if (!found) @@ -89,15 +89,15 @@ void apply_instruction_filter(json_object* filter, json_object* instruction, jso json_object* apply_instruction_filters(json_object* filter, json_object* instruction) { json_object* instantiated_filter = json_object_new_object(); - struct List* pending = new_list(json_object*); + struct List* pending = shd_new_list(json_object*); apply_instruction_filter(filter, instruction, instantiated_filter, pending); - while(entries_count_list(pending) > 0) { - json_object* pending_filter = read_list(json_object*, pending)[0]; - remove_list(json_object*, pending, 0); + while(shd_list_count(pending) > 0) { + json_object* pending_filter = shd_read_list(json_object*, pending)[0]; + shd_list_remove(json_object*, pending, 0); apply_instruction_filter(pending_filter, instruction, instantiated_filter, pending); continue; } - destroy_list(pending); + shd_destroy_list(pending); return instantiated_filter; } @@ -121,7 +121,7 @@ void apply_operand_filter(json_object* filter, json_object* operand, json_object json_object_object_foreach(filter_name, match_name, subfilter) { if (strcmp(name, match_name) == 0) { found = true; - append_list(json_object*, pending, subfilter); + shd_list_append(json_object*, pending, subfilter); } } if (!found) @@ -137,7 +137,7 @@ void apply_operand_filter(json_object* filter, json_object* operand, json_object json_object_object_foreach(filter_kind, match_name, subfilter) { if (strcmp(kind, match_name) == 0) { found = true; - append_list(json_object*, pending, subfilter); + shd_list_append(json_object*, pending, subfilter); } } if (!found) @@ -154,15 +154,15 @@ void apply_operand_filter(json_object* filter, json_object* operand, json_object json_object* apply_operand_filters(json_object* filter, json_object* operand) { //fprintf(stderr, "building filter for %s\n", json_object_to_json_string(operand)); json_object* instantiated_filter = json_object_new_object(); - struct List* pending = new_list(json_object*); + struct List* pending = shd_new_list(json_object*); apply_operand_filter(filter, operand, instantiated_filter, pending); - while(entries_count_list(pending) > 0) { - json_object* pending_filter = read_list(json_object*, pending)[0]; - remove_list(json_object*, pending, 0); + while(shd_list_count(pending) > 0) { + json_object* pending_filter = shd_read_list(json_object*, pending)[0]; + shd_list_remove(json_object*, pending, 0); apply_operand_filter(pending_filter, operand, instantiated_filter, pending); continue; } - destroy_list(pending); + shd_destroy_list(pending); //fprintf(stderr, "done: %s\n", json_object_to_json_string(instantiated_filter)); return instantiated_filter; } diff --git a/src/shady/ir.c b/src/shady/ir.c index 8a7d8ea95..f5d4373ee 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -25,10 +25,10 @@ bool compare_node(const Node** a, const Node** b); IrArena* new_ir_arena(const ArenaConfig* config) { IrArena* arena = malloc(sizeof(IrArena)); *arena = (IrArena) { - .arena = new_arena(), + .arena = shd_new_arena(), .config = *config, - .modules = new_list(Module*), + .modules = shd_new_list(Module*), .node_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), .string_set = new_set(const char*, (HashFn) hash_string, (CmpFn) compare_string), @@ -46,16 +46,16 @@ const Node* get_node_by_id(const IrArena* a, NodeId id) { } void destroy_ir_arena(IrArena* arena) { - for (size_t i = 0; i < entries_count_list(arena->modules); i++) { - destroy_module(read_list(Module*, arena->modules)[i]); + for (size_t i = 0; i < shd_list_count(arena->modules); i++) { + destroy_module(shd_read_list(Module*, arena->modules)[i]); } - destroy_list(arena->modules); + shd_destroy_list(arena->modules); destroy_dict(arena->strings_set); destroy_dict(arena->string_set); destroy_dict(arena->nodes_set); destroy_dict(arena->node_set); - destroy_arena(arena->arena); + shd_destroy_arena(arena->arena); destroy_growy(arena->ids); free(arena); } @@ -80,7 +80,7 @@ Nodes nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { Nodes nodes; nodes.count = count; - nodes.nodes = arena_alloc(arena->arena, sizeof(Node*) * count); + nodes.nodes = shd_arena_alloc(arena->arena, sizeof(Node*) * count); for (size_t i = 0; i < count; i++) nodes.nodes[i] = in_nodes[i]; @@ -99,7 +99,7 @@ Strings strings(IrArena* arena, size_t count, const char* in_strs[]) { Strings strings; strings.count = count; - strings.strings = arena_alloc(arena->arena, sizeof(const char*) * count); + strings.strings = shd_arena_alloc(arena->arena, sizeof(const char*) * count); for (size_t i = 0; i < count; i++) strings.strings[i] = in_strs[i]; @@ -173,7 +173,7 @@ static const char* string_impl(IrArena* arena, size_t size, const char* zero_ter if (found) return *found; - char* new_str = (char*) arena_alloc(arena->arena, strlen(zero_terminated) + 1); + char* new_str = (char*) shd_arena_alloc(arena->arena, strlen(zero_terminated) + 1); strncpy(new_str, zero_terminated, size); new_str[size] = '\0'; @@ -266,5 +266,5 @@ bool compare_string(const char** a, const char** b) { } Nodes list_to_nodes(IrArena* arena, struct List* list) { - return nodes(arena, entries_count_list(list), read_list(const Node*, list)); + return nodes(arena, shd_list_count(list), shd_read_list(const Node*, list)); } diff --git a/src/shady/module.c b/src/shady/module.c index 7416d46be..e222783ae 100644 --- a/src/shady/module.c +++ b/src/shady/module.c @@ -6,13 +6,13 @@ #include Module* new_module(IrArena* arena, String name) { - Module* m = arena_alloc(arena->arena, sizeof(Module)); + Module* m = shd_arena_alloc(arena->arena, sizeof(Module)); *m = (Module) { .arena = arena, .name = string(arena, name), - .decls = new_list(Node*), + .decls = shd_new_list(Node*), }; - append_list(Module*, arena->modules, m); + shd_list_append(Module*, arena->modules, m); return m; } @@ -25,15 +25,15 @@ String get_module_name(const Module* m) { } Nodes get_module_declarations(const Module* m) { - size_t count = entries_count_list(m->decls); - const Node** start = read_list(const Node*, m->decls); + size_t count = shd_list_count(m->decls); + const Node** start = shd_read_list(const Node*, m->decls); return nodes(get_module_arena(m), count, start); } void register_decl_module(Module* m, Node* node) { assert(is_declaration(node)); assert(!get_declaration(m, get_declaration_name(node)) && "duplicate declaration"); - append_list(Node*, m->decls, node); + shd_list_append(Node*, m->decls, node); } Node* get_declaration(const Module* m, String name) { @@ -46,5 +46,5 @@ Node* get_declaration(const Module* m, String name) { } void destroy_module(Module* m) { - destroy_list(m->decls); + shd_destroy_list(m->decls); } diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 3265479ee..de3d05288 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -42,8 +42,8 @@ static const LTNode* get_loop(const LTNode* n) { } static String loop_name(const LTNode* n) { - if (n && n->type == LF_HEAD && entries_count_list(n->cf_nodes) > 0) { - return get_abstraction_name(read_list(CFNode*, n->cf_nodes)[0]->node); + if (n && n->type == LF_HEAD && shd_list_count(n->cf_nodes) > 0) { + return get_abstraction_name(shd_read_list(CFNode*, n->cf_nodes)[0]->node); } return ""; } @@ -95,9 +95,9 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* const CFNode* n = cfg_lookup(ctx->cfg, old); size_t children_count = 0; - LARRAY(const Node*, old_children, entries_count_list(n->dominates)); - for (size_t i = 0; i < entries_count_list(n->dominates); i++) { - CFNode* c = read_list(CFNode*, n->dominates)[i]; + LARRAY(const Node*, old_children, shd_list_count(n->dominates)); + for (size_t i = 0; i < shd_list_count(n->dominates); i++) { + CFNode* c = shd_read_list(CFNode*, n->dominates)[i]; if (is_cfnode_structural_target(c)) continue; old_children[children_count++] = c->node; diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 4b0eafba8..cf30a8d62 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -54,8 +54,8 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); assert(is_data_type(element_type)); - const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, singleton(type_decl_ref_helper(a, vctx->nom_t)), singleton(int32_literal(a, entries_count_list(vctx->members)))); - append_list(const Type*, vctx->members, element_type); + const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, singleton(type_decl_ref_helper(a, vctx->nom_t)), singleton(int32_literal(a, shd_list_count(vctx->members)))); + shd_list_append(const Type*, vctx->members, element_type); StackSlot slot = { vctx->num_slots, slot_offset, element_type, AsPrivate }; insert_dict(const Node*, StackSlot, vctx->prepared_offsets, node, slot); @@ -104,17 +104,17 @@ static const Node* process(Context* ctx, const Node* node) { .bb = bb, .nom_t = nom_t, .num_slots = 0, - .members = new_list(const Node*), + .members = shd_new_list(const Node*), .prepared_offsets = ctx2.prepared_offsets, }; visit_function_bodies_rpo(&vctx.visitor, node); vctx.nom_t->payload.nom_type.body = record_type(a, (RecordType) { - .members = nodes(a, vctx.num_slots, read_list(const Node*, vctx.members)), + .members = nodes(a, vctx.num_slots, shd_read_list(const Node*, vctx.members)), .names = strings(a, 0, NULL), .special = 0 }); - destroy_list(vctx.members); + shd_destroy_list(vctx.members); ctx2.num_slots = vctx.num_slots; ctx2.frame_size = gen_primop_e(bb, size_of_op, singleton(type_decl_ref_helper(a, vctx.nom_t)), empty(a)); ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 636a87c6e..23e78503f 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -144,10 +144,10 @@ static const Node* process(Context* ctx, const Node* node) { // TODO or maybe do that in fold() assert(cases.count > 0); - Arena* arena = new_arena(); + Arena* arena = shd_new_arena(); TreeNode* root = NULL; for (size_t i = 0; i < literals.count; i++) { - TreeNode* t = arena_alloc(arena, sizeof(TreeNode)); + TreeNode* t = shd_arena_alloc(arena, sizeof(TreeNode)); t->key = get_int_literal_value(*resolve_to_int_literal(literals.nodes[i]), false); t->lam = cases.nodes[i]; root = insert(root, t); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index bcfa3254e..0d36679eb 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -339,8 +339,8 @@ void generate_top_level_dispatch_fn(Context* ctx) { // gen_if(loop_body_builder, empty(a), bail_condition, bail_case, NULL); } - struct List* literals = new_list(const Node*); - struct List* jumps = new_list(const Node*); + struct List* literals = shd_new_list(const Node*); + struct List* jumps = shd_new_list(const Node*); // Build 'zero' case (exits the program) Node* zero_case_lam = case_(a, nodes(a, 0, NULL)); @@ -368,9 +368,9 @@ void generate_top_level_dispatch_fn(Context* ctx) { })); const Node* zero_lit = uint64_literal(a, 0); - append_list(const Node*, literals, zero_lit); + shd_list_append(const Node*, literals, zero_lit); const Node* zero_jump = jump_helper(a, zero_case_lam, empty(a), bb_mem(loop_body_builder)); - append_list(const Node*, jumps, zero_jump); + shd_list_append(const Node*, jumps, zero_jump); Nodes old_decls = get_module_declarations(ctx->rewriter.src_module); for (size_t i = 0; i < old_decls.count; i++) { @@ -405,9 +405,9 @@ void generate_top_level_dispatch_fn(Context* ctx) { .false_jump = jump_helper(a, if_false, empty(a), get_abstraction_mem(fn_case)), })); - append_list(const Node*, literals, fn_lit); + shd_list_append(const Node*, literals, fn_lit); const Node* j = jump_helper(a, fn_case, empty(a), bb_mem(loop_body_builder)); - append_list(const Node*, jumps, j); + shd_list_append(const Node*, jumps, j); } } @@ -417,13 +417,13 @@ void generate_top_level_dispatch_fn(Context* ctx) { set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, br_switch(a, (Switch) { .mem = bb_mem(loop_body_builder), .switch_value = next_function, - .case_values = nodes(a, entries_count_list(literals), read_list(const Node*, literals)), - .case_jumps = nodes(a, entries_count_list(jumps), read_list(const Node*, jumps)), + .case_values = nodes(a, shd_list_count(literals), shd_read_list(const Node*, literals)), + .case_jumps = nodes(a, shd_list_count(jumps), shd_read_list(const Node*, jumps)), .default_jump = jump_helper(a, default_case, empty(a), bb_mem(loop_body_builder)) }))); - destroy_list(literals); - destroy_list(jumps); + shd_destroy_list(literals); + shd_destroy_list(jumps); if (ctx->config->printf_trace.god_function) gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", empty(a)); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index bdc3aef7f..9f4e61163 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -140,7 +140,7 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t const Node* nmem = rewrite_node(r, old->tag == StackAlloc_TAG ? old->payload.stack_alloc.mem : old->payload.local_alloc.mem); - AllocaInfo* k = arena_alloc(ctx->arena, sizeof(AllocaInfo)); + AllocaInfo* k = shd_arena_alloc(ctx->arena, sizeof(AllocaInfo)); *k = (AllocaInfo) { .type = rewrite_node(r, old_type) }; assert(ctx->uses); visit_ptr_uses(old, old_type, k, ctx->uses); @@ -242,14 +242,14 @@ bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, - .arena = new_arena(), + .arena = shd_new_arena(), .alloca_info = new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), .todo = &todo }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); destroy_dict(ctx.alloca_info); - destroy_arena(ctx.arena); + shd_destroy_arena(ctx.arena); *m = dst; return todo; } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 324446ca2..a54475dfe 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -64,8 +64,8 @@ static const Node* get_last_stored_value(Context* ctx, const Node* ptr, const No case AbsMem_TAG: { const Node* abs = mem->payload.abs_mem.abs; CFNode* n = cfg_lookup(ctx->cfg, abs); - if (entries_count_list(n->pred_edges) == 1) { - CFEdge e = read_list(CFEdge, n->pred_edges)[0]; + if (shd_list_count(n->pred_edges) == 1) { + CFEdge e = shd_read_list(CFEdge, n->pred_edges)[0]; mem = get_terminator_mem(e.terminator); continue; } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 7f45ab4f5..1665e0416 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -136,10 +136,10 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, BodyBuilder* bb = begin_body_with_mem(a, mem); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); - append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); + shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); - append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); + shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; for (size_t i = 0; i < oargs.count; i++) { nparams[i] = param(a, rewrite_node(&ctx->rewriter, oparams.nodes[i]->type), "arg"); @@ -158,8 +158,8 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, // forget we rewrote all that destroy_dict(tmp_processed); - pop_list_impl(ctx->cleanup_stack); - pop_list_impl(ctx->cleanup_stack); + shd_list_pop_impl(ctx->cleanup_stack); + shd_list_pop_impl(ctx->cleanup_stack); if (dfs_entry.loop_header) { // Use the structured target as the body of a loop @@ -337,7 +337,7 @@ static const Node* process(Context* ctx, const Node* node) { if (node->tag == Function_TAG) { Node* new = recreate_decl_header_identity(&ctx->rewriter, node); - size_t alloc_stack_size_now = entries_count_list(ctx->cleanup_stack); + size_t alloc_stack_size_now = shd_list_count(ctx->cleanup_stack); Context ctx2 = *ctx; ctx2.dfs_stack = NULL; @@ -355,7 +355,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.lower = true; BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); - append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); + shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); const Node* ptr = gen_local_alloc(bb, int32_type(a)); set_value_name(ptr, "cf_depth"); gen_store(bb, ptr, int32_literal(a, 0)); @@ -363,14 +363,14 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.fn = new; struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); - append_list(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); + shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new, finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. - pop_list_impl(ctx->cleanup_stack); - pop_list_impl(ctx->cleanup_stack); + shd_list_pop_impl(ctx->cleanup_stack); + shd_list_pop_impl(ctx->cleanup_stack); destroy_dict(tmp_processed); } @@ -378,8 +378,8 @@ static const Node* process(Context* ctx, const Node* node) { // new->payload.fun.annotations = append_nodes(arena, new->payload.fun.annotations, annotation(arena, (Annotation) { .name = "Leaf" })); // if we did a longjmp, we might have orphaned a few of those - while (alloc_stack_size_now < entries_count_list(ctx->cleanup_stack)) { - TmpAllocCleanupClosure cj = pop_last_list(TmpAllocCleanupClosure, ctx->cleanup_stack); + while (alloc_stack_size_now < shd_list_count(ctx->cleanup_stack)) { + TmpAllocCleanupClosure cj = shd_list_pop(TmpAllocCleanupClosure, ctx->cleanup_stack); cj.fn(cj.payload); } @@ -421,10 +421,10 @@ Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .cleanup_stack = new_list(TmpAllocCleanupClosure), + .cleanup_stack = shd_new_list(TmpAllocCleanupClosure), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_list(ctx.cleanup_stack); + shd_destroy_list(ctx.cleanup_stack); return dst; } diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 82210b872..552ad1259 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -33,10 +33,10 @@ static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { assert(parent); while (parent) { - if (entries_count_list(parent->cf_nodes) != 1) + if (shd_list_count(parent->cf_nodes) != 1) return false; - if (read_list(CFNode*, parent->cf_nodes)[0]->node == entry) + if (shd_read_list(CFNode*, parent->cf_nodes)[0]->node == entry) return true; parent = parent->parent; @@ -48,12 +48,12 @@ static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { //TODO: This is massively inefficient. static void gather_exiting_nodes(LoopTree* lt, const CFNode* entry, const CFNode* block, struct List* exiting_nodes) { if (!in_loop(lt, entry->node, block->node)) { - append_list(CFNode*, exiting_nodes, block); + shd_list_append(CFNode*, exiting_nodes, block); return; } - for (size_t i = 0; i < entries_count_list(block->dominates); i++) { - const CFNode* target = read_list(CFNode*, block->dominates)[i]; + for (size_t i = 0; i < shd_list_count(block->dominates); i++) { + const CFNode* target = shd_read_list(CFNode*, block->dominates)[i]; gather_exiting_nodes(lt, entry, target, exiting_nodes); } } @@ -71,7 +71,7 @@ static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, log_node(DEBUGVV, exiting_node); log_string(DEBUGVV, " )\n"); - append_list(const Node*, leaking, v); + shd_list_append(const Node*, leaking, v); } } @@ -104,11 +104,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { bool is_loop_entry = false; if (lt_node->parent && lt_node->parent->type == LF_HEAD) { - if (entries_count_list(lt_node->parent->cf_nodes) == 1) - if (read_list(CFNode*, lt_node->parent->cf_nodes)[0]->node == node) { + if (shd_list_count(lt_node->parent->cf_nodes) == 1) + if (shd_read_list(CFNode*, lt_node->parent->cf_nodes)[0]->node == node) { loop_header = lt_node->parent; assert(loop_header->type == LF_HEAD); - assert(entries_count_list(loop_header->cf_nodes) == 1 && "only reducible loops are handled"); + assert(shd_list_count(loop_header->cf_nodes) == 1 && "only reducible loops are handled"); is_loop_entry = true; } } @@ -116,14 +116,14 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (is_loop_entry) { assert(!is_function(node)); - struct List* exiting_nodes = new_list(CFNode*); + struct List* exiting_nodes = shd_new_list(CFNode*); gather_exiting_nodes(ctx->current_looptree, current_node, current_node, exiting_nodes); - for (size_t i = 0; i < entries_count_list(exiting_nodes); i++) { - debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(read_list(CFNode*, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); + for (size_t i = 0; i < shd_list_count(exiting_nodes); i++) { + debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(shd_read_list(CFNode *, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); } - size_t exiting_nodes_count = entries_count_list(exiting_nodes); + size_t exiting_nodes_count = shd_list_count(exiting_nodes); if (exiting_nodes_count > 0) { Nodes nparams = recreate_params(rewriter, get_abstraction_params(node)); Node* loop_container = basic_block(arena, nparams, node->payload.basic_block.name); @@ -132,10 +132,10 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(Exit, exits, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; Nodes exit_param_types = rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); - ExitValue* exit_params = arena_alloc(ctx->arena, sizeof(ExitValue) * exit_param_types.count); + ExitValue* exit_params = shd_arena_alloc(ctx->arena, sizeof(ExitValue) * exit_param_types.count); for (size_t j = 0; j < exit_param_types.count; j++) { exit_params[j].alloca = gen_stack_alloc(outer_bb, get_unqualified_type(exit_param_types.nodes[j])); exit_params[j].uniform = is_qualified_type_uniform(exit_param_types.nodes[j]); @@ -159,7 +159,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { }), true), "jp_continue"); for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); @@ -179,7 +179,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { // replace the exit nodes by the exit wrappers LARRAY(const Node**, cached_exits, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; cached_exits[i] = search_processed(rewriter, exiting_node->node); if (cached_exits[i]) remove_dict(const Node*, rewriter->map, exiting_node->node); @@ -206,7 +206,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { // save the context for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = get_abstraction_params(exits[i].wrapper); BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(exits[i].wrapper)); @@ -228,9 +228,9 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { // restore the old context for (size_t i = 0; i < exiting_nodes_count; i++) { - remove_dict(const Node*, rewriter->map, read_list(CFNode*, exiting_nodes)[i]->node); + remove_dict(const Node*, rewriter->map, shd_read_list(CFNode *, exiting_nodes)[i]->node); if (cached_exits[i]) - register_processed(rewriter, read_list(CFNode*, exiting_nodes)[i]->node, *cached_exits[i]); + register_processed(rewriter, shd_read_list(CFNode*, exiting_nodes)[i]->node, *cached_exits[i]); } remove_dict(const Node*, rewriter->map, node); if (cached_entry) @@ -256,7 +256,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(const Node*, exit_numbers, exiting_nodes_count); LARRAY(const Node*, exit_jumps, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { - CFNode* exiting_node = read_list(CFNode*, exiting_nodes)[i]; + CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; Node* exit_bb = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); @@ -289,11 +289,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { })); } set_abstraction_body(loop_container, outer_body); - destroy_list(exiting_nodes); + shd_destroy_list(exiting_nodes); return loop_container; } - destroy_list(exiting_nodes); + shd_destroy_list(exiting_nodes); } return recreate_node_identity(&ctx->rewriter, node); @@ -348,11 +348,11 @@ static const Node* process_node(Context* ctx, const Node* node) { LTNode* current_loop = looptree_lookup(ctx->current_looptree, ctx->current_abstraction)->parent; assert(current_loop); - if (entries_count_list(current_loop->cf_nodes)) { + if (shd_list_count(current_loop->cf_nodes)) { bool leaves_loop = false; CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); - for (size_t i = 0; i < entries_count_list(current_node->succ_edges); i++) { - CFEdge edge = read_list(CFEdge, current_node->succ_edges)[i]; + for (size_t i = 0; i < shd_list_count(current_node->succ_edges); i++) { + CFEdge edge = shd_read_list(CFEdge, current_node->succ_edges)[i]; LTNode* lt_target = looptree_lookup(ctx->current_looptree, edge.dst->node); if (lt_target->parent != current_loop) { @@ -362,7 +362,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } if (!leaves_loop) { - const Node* current_loop_head = read_list(CFNode*, current_loop->cf_nodes)[0]->node; + const Node* current_loop_head = shd_read_list(CFNode*, current_loop->cf_nodes)[0]->node; CFG* loop_cfg = build_cfg(ctx->current_fn, current_loop_head, (CFGBuildConfig) { .include_structured_tails = true, .lt = ctx->current_looptree, @@ -489,11 +489,11 @@ Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { .fwd_cfg = NULL, .rev_cfg = NULL, .current_looptree = NULL, - .arena = new_arena(), + .arena = shd_new_arena(), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_arena(ctx.arena); + shd_destroy_arena(ctx.arena); return dst; } diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 53a105073..f90013ee4 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -66,7 +66,7 @@ static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { if (found) return *found; IrArena* a = ctx->rewriter.dst_arena; - Controls* controls = arena_alloc(ctx->arena, sizeof(Controls)); + Controls* controls = shd_arena_alloc(ctx->arena, sizeof(Controls)); *controls = (Controls) { .control_destinations = new_dict(const Node*, AddControl, (HashFn) hash_node, (CmpFn) compare_node), }; @@ -82,10 +82,10 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab return; CFNode* n = cfg_lookup(cfg, oabs); - size_t num_dom = entries_count_list(n->dominates); + size_t num_dom = shd_list_count(n->dominates); LARRAY(Node*, nbbs, num_dom); for (size_t i = 0; i < num_dom; i++) { - CFNode* dominated = read_list(CFNode*, n->dominates)[i]; + CFNode* dominated = shd_read_list(CFNode*, n->dominates)[i]; const Node* obb = dominated->node; assert(obb->tag == BasicBlock_TAG); Nodes nparams = remake_params(ctx, get_abstraction_params(obb)); @@ -100,7 +100,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); for (size_t k = 0; k < num_dom; k++) { - CFNode* dominated = read_list(CFNode*, n->dominates)[k]; + CFNode* dominated = shd_read_list(CFNode*, n->dominates)[k]; const Node* obb = dominated->node; wrap_in_controls(ctx, cfg, nbbs[k], obb); } @@ -258,8 +258,8 @@ static void prepare_function(Context* ctx, CFG* cfg, const Node* old_fn) { Scheduler* scheduler = new_scheduler(cfg); for (size_t i = 0; i < cfg->size; i++) { CFNode* n = cfg->rpo[i]; - for (size_t j = 0; j < entries_count_list(n->succ_edges); j++) { - process_edge(ctx, cfg, scheduler, read_list(CFEdge, n->succ_edges)[j]); + for (size_t j = 0; j < shd_list_count(n->succ_edges); j++) { + process_edge(ctx, cfg, scheduler, shd_read_list(CFEdge, n->succ_edges)[j]); } } destroy_scheduler(scheduler); @@ -307,7 +307,7 @@ Module* scope2control(const CompilerConfig* config, Module* src) { Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, - .arena = new_arena(), + .arena = shd_new_arena(), .controls = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), .jump2wrapper = new_dict(const Node*, Wrapped, (HashFn) hash_node, (CmpFn) compare_node), }; @@ -329,7 +329,7 @@ Module* scope2control(const CompilerConfig* config, Module* src) { destroy_dict(ctx.controls); destroy_dict(ctx.jump2wrapper); - destroy_arena(ctx.arena); + shd_destroy_arena(ctx.arena); destroy_rewriter(&ctx.rewriter); return dst; diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index aaa7c58b3..55f42d2c5 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -25,13 +25,13 @@ static Nodes to_ids(IrArena* a, Nodes in) { static void visit_looptree_prepend(IrArena* a, Nodes* arr, LTNode* node, Nodes prefix) { if (node->type == LF_HEAD) { - for (size_t i = 0; i < entries_count_list(node->lf_children); i++) { - LTNode* n = read_list(LTNode*, node->lf_children)[i]; + for (size_t i = 0; i < shd_list_count(node->lf_children); i++) { + LTNode* n = shd_read_list(LTNode*, node->lf_children)[i]; visit_looptree_prepend(a, arr, n, prefix); } } else { - for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { - CFNode* n = read_list(CFNode*, node->cf_nodes)[i]; + for (size_t i = 0; i < shd_list_count(node->cf_nodes); i++) { + CFNode* n = shd_read_list(CFNode*, node->cf_nodes)[i]; arr[n->rpo_index] = concat_nodes(a, prefix, arr[n->rpo_index]); } assert(node->lf_children); @@ -52,8 +52,8 @@ static void paint_dominated_up_to_postdom(CFNode* n, IrArena* a, Nodes* arr, con if (n->node == postdom) return; - for (size_t i = 0; i < entries_count_list(n->dominates); i++) { - CFNode* dominated = read_list(CFNode*, n->dominates)[i]; + for (size_t i = 0; i < shd_list_count(n->dominates); i++) { + CFNode* dominated = shd_read_list(CFNode*, n->dominates)[i]; paint_dominated_up_to_postdom(dominated, a, arr, postdom, prefix); } @@ -65,14 +65,14 @@ static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* fl if (ltn->parent != loop) return; - for (size_t i = 0; i < entries_count_list(n->dominates); i++) { - CFNode* dominated = read_list(CFNode*, n->dominates)[i]; + for (size_t i = 0; i < shd_list_count(n->dominates); i++) { + CFNode* dominated = shd_read_list(CFNode*, n->dominates)[i]; visit_acyclic_cfg_domtree(dominated, a, arr, flipped, loop, lt); } CFNode* src = n; - if (entries_count_list(src->succ_edges) < 2) + if (shd_list_count(src->succ_edges) < 2) return; // no divergence, no bother CFNode* f_src = cfg_lookup(flipped, src->node); @@ -96,19 +96,19 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, if (node->type == LF_HEAD) { Nodes surrounding = empty(a); bool is_loop = false; - for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { - CFNode* n = read_list(CFNode*, node->cf_nodes)[i]; + for (size_t i = 0; i < shd_list_count(node->cf_nodes); i++) { + CFNode* n = shd_read_list(CFNode*, node->cf_nodes)[i]; surrounding = append_nodes(a, surrounding, n->node); is_loop = true; } - for (size_t i = 0; i < entries_count_list(node->lf_children); i++) { - LTNode* n = read_list(LTNode*, node->lf_children)[i]; + for (size_t i = 0; i < shd_list_count(node->lf_children); i++) { + LTNode* n = shd_read_list(LTNode*, node->lf_children)[i]; visit_looptree(a, arr, fn, flipped, lt, n); } - assert(entries_count_list(node->cf_nodes) < 2); - CFG* sub_cfg = build_cfg(fn, is_loop ? read_list(CFNode*, node->cf_nodes)[0]->node : fn, (CFGBuildConfig) { + assert(shd_list_count(node->cf_nodes) < 2); + CFG* sub_cfg = build_cfg(fn, is_loop ? shd_read_list(CFNode*, node->cf_nodes)[0]->node : fn, (CFGBuildConfig) { .include_structured_tails = true, .lt = lt }); @@ -120,8 +120,8 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, visit_looptree_prepend(a, arr, node, surrounding); // Remove one level of scoping for the loop headers (forcing reconvergence) - for (size_t i = 0; i < entries_count_list(node->cf_nodes); i++) { - CFNode* n = read_list(CFNode*, node->cf_nodes)[i]; + for (size_t i = 0; i < shd_list_count(node->cf_nodes); i++) { + CFNode* n = shd_read_list(CFNode*, node->cf_nodes)[i]; Nodes old = arr[n->rpo_index]; assert(old.count > 1); arr[n->rpo_index] = nodes(a, old.count - 1, &old.nodes[0]); @@ -134,7 +134,7 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, static bool loop_depth(LTNode* a) { int i = 0; while (a) { - if (entries_count_list(a->cf_nodes) > 0) + if (shd_list_count(a->cf_nodes) > 0) i++; else { assert(!a->parent); diff --git a/src/shady/print.c b/src/shady/print.c index 72c903fc4..11002e0b0 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -277,7 +277,7 @@ static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { Printer* p2 = open_growy_as_printer(g2); size_t count = cfnode->dominates->elements_count; for (size_t i = 0; i < count; i++) { - const CFNode* dominated = read_list(const CFNode*, cfnode->dominates)[i]; + const CFNode* dominated = shd_read_list(const CFNode*, cfnode->dominates)[i]; assert(is_basic_block(dominated->node)); PrinterCtx bb_ctx = *ctx; bb_ctx.printer = p2; diff --git a/vcc/vcc.c b/vcc/vcc.c index 82f01ca04..77356a731 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -20,7 +20,7 @@ int main(int argc, char** argv) { cli_parse_vcc_args(&vcc_options, &argc, argv); cli_parse_input_files(args.input_filenames, &argc, argv); - if (entries_count_list(args.input_filenames) == 0) { + if (shd_list_count(args.input_filenames) == 0) { error_print("Missing input file. See --help for proper usage"); exit(MissingInputArg); } @@ -32,7 +32,7 @@ int main(int argc, char** argv) { if (vcc_options.only_run_clang) vcc_options.tmp_filename = format_string_new("%s", args.output_filename); - vcc_run_clang(&vcc_options, entries_count_list(args.input_filenames), read_list(String, args.input_filenames)); + vcc_run_clang(&vcc_options, shd_list_count(args.input_filenames), shd_read_list(String, args.input_filenames)); if (!vcc_options.only_run_clang) { Module* mod = vcc_parse_back_into_module(&args.config, &vcc_options, "my_module"); From 780dd9d5468a91f26c59c098238eb052cd18975c Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 15:14:34 +0200 Subject: [PATCH 594/693] add shd_ prefix to dict.h --- src/backend/c/emit_c.c | 22 ++++----- src/backend/spirv/emit_spv.c | 30 ++++++------ src/backend/spirv/emit_spv_control_flow.c | 2 +- src/backend/spirv/spirv_builder.c | 14 +++--- src/backend/spirv/spirv_lift_globals_ssbo.c | 6 +-- src/common/dict.c | 53 +++++++++++---------- src/common/dict.h | 52 ++++++++++---------- src/common/test_dict.c | 18 +++---- src/frontend/llvm/l2s.c | 48 +++++++++---------- src/frontend/llvm/l2s_annotations.c | 6 +-- src/frontend/llvm/l2s_instr.c | 2 +- src/frontend/llvm/l2s_meta.c | 4 +- src/frontend/llvm/l2s_type.c | 4 +- src/frontend/llvm/l2s_value.c | 6 +-- src/frontend/spirv/s2s.c | 12 ++--- src/runtime/vulkan/vk_runtime_device.c | 8 ++-- src/runtime/vulkan/vk_runtime_program.c | 4 +- src/shady/analysis/callgraph.c | 32 ++++++------- src/shady/analysis/cfg.c | 24 +++++----- src/shady/analysis/free_frontier.c | 18 +++---- src/shady/analysis/looptree.c | 8 ++-- src/shady/analysis/scheduler.c | 8 ++-- src/shady/analysis/uses.c | 16 +++---- src/shady/analysis/verify.c | 16 +++---- src/shady/constructors.c | 6 +-- src/shady/generator_node.c | 2 +- src/shady/ir.c | 34 ++++++------- src/shady/node.c | 2 +- src/shady/passes/lcssa.c | 20 ++++---- src/shady/passes/lift_everything.c | 12 ++--- src/shady/passes/lift_indirect_targets.c | 16 +++---- src/shady/passes/lower_alloca.c | 10 ++-- src/shady/passes/lower_cf_instrs.c | 14 +++--- src/shady/passes/lower_generic_ptrs.c | 8 ++-- src/shady/passes/lower_nullptr.c | 8 ++-- src/shady/passes/lower_physical_ptrs.c | 20 ++++---- src/shady/passes/lower_stack.c | 12 ++--- src/shady/passes/lower_subgroup_ops.c | 8 ++-- src/shady/passes/lower_subgroup_vars.c | 6 +-- src/shady/passes/lower_tailcalls.c | 8 ++-- src/shady/passes/mark_leaf_functions.c | 16 +++---- src/shady/passes/opt_demote_alloca.c | 8 ++-- src/shady/passes/opt_inline.c | 16 +++---- src/shady/passes/opt_restructure.c | 10 ++-- src/shady/passes/reconvergence_heuristics.c | 20 ++++---- src/shady/passes/scope2control.c | 28 +++++------ src/shady/print.c | 10 ++-- src/shady/rewrite.c | 20 ++++---- vcc/vcc_lib.c | 4 +- 49 files changed, 366 insertions(+), 365 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 0a736edf6..6ad49c4a6 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -27,24 +27,24 @@ bool compare_node(Node**, Node**); void register_emitted(Emitter* emitter, FnEmitter* fn, const Node* node, CTerm as) { //assert(as.value || as.var); - insert_dict(const Node*, CTerm, fn ? fn->emitted_terms : emitter->emitted_terms, node, as); + shd_dict_insert(const Node*, CTerm, fn ? fn->emitted_terms : emitter->emitted_terms, node, as); } CTerm* lookup_existing_term(Emitter* emitter, FnEmitter* fn, const Node* node) { CTerm* found = NULL; if (fn) - found = find_value_dict(const Node*, CTerm, fn->emitted_terms, node); + found = shd_dict_find_value(const Node*, CTerm, fn->emitted_terms, node); if (!found) - found = find_value_dict(const Node*, CTerm, emitter->emitted_terms, node); + found = shd_dict_find_value(const Node*, CTerm, emitter->emitted_terms, node); return found; } void register_emitted_type(Emitter* emitter, const Node* node, String as) { - insert_dict(const Node*, String, emitter->emitted_types, node, as); + shd_dict_insert(const Node*, String, emitter->emitted_types, node, as); } CType* lookup_existing_type(Emitter* emitter, const Type* node) { - CType* found = find_value_dict(const Node*, CType, emitter->emitted_types, node); + CType* found = shd_dict_find_value(const Node*, CType, emitter->emitted_types, node); return found; } @@ -307,7 +307,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { if (body) { FnEmitter fn = { .cfg = build_fn_cfg(decl), - .emitted_terms = new_dict(Node*, CTerm, (HashFn) hash_node, (CmpFn) compare_node), + .emitted_terms = shd_new_dict(Node*, CTerm, (HashFn) hash_node, (CmpFn) compare_node), }; fn.scheduler = new_scheduler(fn.cfg); fn.instruction_printers = calloc(sizeof(Printer*), fn.cfg->size); @@ -344,7 +344,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { destroy_scheduler(fn.scheduler); destroy_cfg(fn.cfg); - destroy_dict(fn.emitted_terms); + shd_destroy_dict(fn.emitted_terms); free(fn.instruction_printers); } @@ -437,8 +437,8 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module .type_decls = open_growy_as_printer(type_decls_g), .fn_decls = open_growy_as_printer(fn_decls_g), .fn_defs = open_growy_as_printer(fn_defs_g), - .emitted_terms = new_dict(Node*, CTerm, (HashFn) hash_node, (CmpFn) compare_node), - .emitted_types = new_dict(Node*, String, (HashFn) hash_node, (CmpFn) compare_node), + .emitted_terms = shd_new_dict(Node*, CTerm, (HashFn) hash_node, (CmpFn) compare_node), + .emitted_types = shd_new_dict(Node*, String, (HashFn) hash_node, (CmpFn) compare_node), }; // builtins magic (hack) for CUDA @@ -525,8 +525,8 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module destroy_growy(fn_decls_g); destroy_growy(fn_defs_g); - destroy_dict(emitter.emitted_types); - destroy_dict(emitter.emitted_terms); + shd_destroy_dict(emitter.emitted_types); + shd_destroy_dict(emitter.emitted_terms); *output_size = growy_size(final) - 1; *output = growy_deconstruct(final); diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index df65ed061..25f2609d6 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -36,15 +36,15 @@ void spv_register_emitted(Emitter* emitter, FnBuilder* fn_builder, const Node* n spvb_name(emitter->file_builder, id, name); } struct Dict* map = fn_builder ? fn_builder->emitted : emitter->global_node_ids; - insert_dict_and_get_result(struct Node*, SpvId, map, node, id); + shd_dict_insert_get_result(struct Node*, SpvId, map, node, id); } SpvId* spv_search_emitted(Emitter* emitter, FnBuilder* fn_builder, const Node* node) { SpvId* found = NULL; if (fn_builder) - found = find_value_dict(const Node*, SpvId, fn_builder->emitted, node); + found = shd_dict_find_value(const Node*, SpvId, fn_builder->emitted, node); if (!found) - found = find_value_dict(const Node*, SpvId, emitter->global_node_ids, node); + found = shd_dict_find_value(const Node*, SpvId, emitter->global_node_ids, node); return found; } @@ -86,7 +86,7 @@ static void emit_function(Emitter* emitter, const Node* node) { SpvId fn_id = spv_find_emitted(emitter, NULL, node); FnBuilder fn_builder = { .base = spvb_begin_fn(emitter->file_builder, fn_id, spv_emit_type(emitter, fn_type), spv_types_to_codom(emitter, node->payload.fun.return_types)), - .emitted = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), + .emitted = shd_new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), .cfg = build_fn_cfg(node), }; fn_builder.scheduler = new_scheduler(fn_builder.cfg); @@ -113,7 +113,7 @@ static void emit_function(Emitter* emitter, const Node* node) { assert(is_basic_block(bb) || bb == node); SpvId bb_id = spvb_fresh_id(emitter->file_builder); BBBuilder basic_block_builder = spvb_begin_bb(fn_builder.base, bb_id); - insert_dict(const Node*, BBBuilder, emitter->bb_builders, bb, basic_block_builder); + shd_dict_insert(const Node*, BBBuilder, emitter->bb_builders, bb, basic_block_builder); // add phis for every non-entry basic block if (i > 0) { assert(is_basic_block(bb) && bb != node); @@ -143,11 +143,11 @@ static void emit_function(Emitter* emitter, const Node* node) { free(fn_builder.per_bb); destroy_scheduler(fn_builder.scheduler); destroy_cfg(fn_builder.cfg); - destroy_dict(fn_builder.emitted); + shd_destroy_dict(fn_builder.emitted); } SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { - SpvId* existing = find_value_dict(const Node*, SpvId, emitter->global_node_ids, decl); + SpvId* existing = shd_dict_find_value(const Node*, SpvId, emitter->global_node_ids, decl); if (existing) return *existing; @@ -304,12 +304,12 @@ static void emit_decls(Emitter* emitter, Nodes declarations) { } SpvId spv_get_extended_instruction_set(Emitter* emitter, const char* name) { - SpvId* found = find_value_dict(const char*, SpvId, emitter->extended_instruction_sets, name); + SpvId* found = shd_dict_find_value(const char*, SpvId, emitter->extended_instruction_sets, name); if (found) return *found; SpvId new = spvb_extended_import(emitter->file_builder, name); - insert_dict(const char*, SpvId, emitter->extended_instruction_sets, name, new); + shd_dict_insert(const char*, SpvId, emitter->extended_instruction_sets, name, new); return new; } @@ -343,12 +343,12 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, .arena = arena, .configuration = config, .file_builder = file_builder, - .global_node_ids = new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), - .bb_builders = new_dict(Node*, BBBuilder, (HashFn) hash_node, (CmpFn) compare_node), + .global_node_ids = shd_new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), + .bb_builders = shd_new_dict(Node*, BBBuilder, (HashFn) hash_node, (CmpFn) compare_node), .num_entry_pts = 0, }; - emitter.extended_instruction_sets = new_dict(const char*, SpvId, (HashFn) hash_string, (CmpFn) compare_string); + emitter.extended_instruction_sets = shd_new_dict(const char*, SpvId, (HashFn) hash_string, (CmpFn) compare_string); emitter.void_t = spvb_void_type(emitter.file_builder); @@ -366,9 +366,9 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, *output_size = spvb_finish(file_builder, output); // cleanup the emitter - destroy_dict(emitter.global_node_ids); - destroy_dict(emitter.bb_builders); - destroy_dict(emitter.extended_instruction_sets); + shd_destroy_dict(emitter.global_node_ids); + shd_destroy_dict(emitter.bb_builders); + shd_destroy_dict(emitter.extended_instruction_sets); if (new_mod) *new_mod = mod; diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index d5b141fc5..ce7c2208f 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -11,7 +11,7 @@ #include BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb) { - BBBuilder* found = find_value_dict(const Node*, BBBuilder, emitter->bb_builders, bb); + BBBuilder* found = shd_dict_find_value(const Node*, BBBuilder, emitter->bb_builders, bb); assert(found); return *found; } diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index 0454275a0..7b8a2a42d 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -93,7 +93,7 @@ struct SpvbFileBuilder_ { struct Dict* extensions_set; }; -static KeyHash hash_u32(uint32_t* p) { return hash_murmur(p, sizeof(uint32_t)); } +static KeyHash hash_u32(uint32_t* p) { return shd_hash_murmur(p, sizeof(uint32_t)); } static bool compare_u32s(uint32_t* a, uint32_t* b) { return *a == *b; } KeyHash hash_string(const char** string); @@ -116,8 +116,8 @@ SpvbFileBuilder* spvb_begin() { .fn_decls = new_growy(), .fn_defs = new_growy(), - .capabilities_set = new_set(SpvCapability, (HashFn) hash_u32, (CmpFn) compare_u32s), - .extensions_set = new_set(const char*, (HashFn) hash_string, (CmpFn) compare_string), + .capabilities_set = shd_new_set(SpvCapability, (HashFn) hash_u32, (CmpFn) compare_u32s), + .extensions_set = shd_new_set(const char*, (HashFn) hash_string, (CmpFn) compare_string), .memory_model = SpvMemoryModelGLSL450, }; @@ -191,8 +191,8 @@ size_t spvb_finish(SpvbFileBuilder* file_builder, char** output) { destroy_growy(file_builder->extensions); destroy_growy(file_builder->capabilities); - destroy_dict(file_builder->capabilities_set); - destroy_dict(file_builder->extensions_set); + shd_destroy_dict(file_builder->capabilities_set); + shd_destroy_dict(file_builder->extensions_set); free(file_builder); @@ -223,7 +223,7 @@ void spvb_set_addressing_model(SpvbFileBuilder* file_builder, SpvAddressingModel #define target_data file_builder->capabilities void spvb_capability(SpvbFileBuilder* file_builder, SpvCapability cap) { - if (insert_set_get_result(SpvCapability, file_builder->capabilities_set, cap)) { + if (shd_set_insert_get_result(SpvCapability, file_builder->capabilities_set, cap)) { op(SpvOpCapability, 2); literal_int(cap); } @@ -232,7 +232,7 @@ void spvb_capability(SpvbFileBuilder* file_builder, SpvCapability cap) { #define target_data file_builder->extensions void spvb_extension(SpvbFileBuilder* file_builder, const char* name) { - if (insert_set_get_result(char*, file_builder->extensions_set, name)) { + if (shd_set_insert_get_result(char*, file_builder->extensions_set, name)) { op(SpvOpExtension, 1 + div_roundup(strlen(name) + 1, 4)); literal_name(name); } diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 40f9c1c81..93646a2cc 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -24,15 +24,15 @@ static const Node* process(Context* ctx, const Node* node) { Node* newfun = recreate_decl_header_identity(r, node); if (get_abstraction_body(node)) { Context functx = *ctx; - functx.rewriter.map = clone_dict(functx.rewriter.map); - clear_dict(functx.rewriter.map); + functx.rewriter.map = shd_clone_dict(functx.rewriter.map); + shd_dict_clear(functx.rewriter.map); register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, empty(a), "post-prelude"); register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); - destroy_dict(functx.rewriter.map); + shd_destroy_dict(functx.rewriter.map); } return newfun; } diff --git a/src/common/dict.c b/src/common/dict.c index bf8afc622..51f7723e0 100644 --- a/src/common/dict.c +++ b/src/common/dict.c @@ -89,7 +89,7 @@ static void dump_dict_keys(struct Dict* dict) { } #endif -struct Dict* new_dict_impl(size_t key_size, size_t value_size, size_t key_align, size_t value_align, KeyHash (*hash_fn)(void*), bool (*cmp_fn) (void*, void*)) { +struct Dict* shd_new_dict_impl(size_t key_size, size_t value_size, size_t key_align, size_t value_align, KeyHash (*hash_fn)(void*), bool (*cmp_fn) (void*, void*)) { // offset of key is obviously zero size_t value_offset = align_offset(key_size, value_align); size_t tag_offset = align_offset(value_offset + value_size, alignof(struct BucketTag)); @@ -123,7 +123,7 @@ struct Dict* new_dict_impl(size_t key_size, size_t value_size, size_t key_align, return dict; } -struct Dict* clone_dict(struct Dict* source) { +struct Dict* shd_clone_dict(struct Dict* source) { struct Dict* dict = (struct Dict*) malloc(sizeof(struct Dict)); *dict = (struct Dict) { .entries_count = source->entries_count, @@ -150,22 +150,22 @@ struct Dict* clone_dict(struct Dict* source) { return dict; } -void destroy_dict(struct Dict* dict) { +void shd_destroy_dict(struct Dict* dict) { free(dict->alloc); free(dict); } -void clear_dict(struct Dict* dict) { +void shd_dict_clear(struct Dict* dict) { dict->entries_count = 0; dict->thombstones_count = 0; memset(dict->alloc, 0, dict->bucket_entry_size * dict->size); } -size_t entries_count_dict(struct Dict* dict) { +size_t shd_dict_count(struct Dict* dict) { return dict->entries_count; } -void* find_key_dict_impl(struct Dict* dict, void* key) { +void* shd_dict_find_impl(struct Dict* dict, void* key) { #ifdef GOBLIB_DICT_DEBUG_PARANOID validate_hashmap_integrity(dict); #endif @@ -196,15 +196,15 @@ void* find_key_dict_impl(struct Dict* dict, void* key) { return NULL; } -void* find_value_dict_impl(struct Dict* dict, void* key) { - void* found = find_key_dict_impl(dict, key); +void* shd_dict_find_value_impl(struct Dict* dict, void* key) { + void* found = shd_dict_find_impl(dict, key); if (found) return (void*) ((size_t)found + dict->value_offset); return NULL; } -bool remove_dict_impl(struct Dict* dict, void* key) { - void* found = find_key_dict_impl(dict, key); +bool shd_dict_remove_impl(struct Dict* dict, void* key) { + void* found = shd_dict_find_impl(dict, key); if (found) { struct BucketTag* tag = (void *) (((size_t) found) + dict->tag_offset); assert(tag->is_present && !tag->is_thombstone); @@ -217,21 +217,22 @@ bool remove_dict_impl(struct Dict* dict, void* key) { return false; } -bool insert_dict_impl(struct Dict* dict, void* key, void* value, void** out_ptr); -bool insert_dict_and_get_result_impl(struct Dict* dict, void* key, void* value) { +static bool dict_insert(struct Dict* dict, void* key, void* value, void** out_ptr); + +bool shd_dict_insert_impl(struct Dict* dict, void* key, void* value) { void* dont_care; - return insert_dict_impl(dict, key, value, &dont_care); + return dict_insert(dict, key, value, &dont_care); } -void* insert_dict_and_get_key_impl(struct Dict* dict, void* key, void* value) { +void* shd_dict_insert_get_key_impl(struct Dict* dict, void* key, void* value) { void* do_care; - insert_dict_impl(dict, key, value, &do_care); + dict_insert(dict, key, value, &do_care); return do_care; } -void* insert_dict_and_get_value_impl(struct Dict* dict, void* key, void* value) { +void* shd_dict_insert_get_value_impl(struct Dict* dict, void* key, void* value) { void* do_care; - insert_dict_impl(dict, key, value, &do_care); + dict_insert(dict, key, value, &do_care); return (void*) ((size_t)do_care + dict->value_offset); } @@ -245,14 +246,14 @@ static void rehash(struct Dict* dict, void* old_alloc, size_t old_size) { if (tag->is_present) { void* key = (void*) bucket; void* value = (void*) (bucket + dict->value_offset); - bool fresh = insert_dict_and_get_result_impl(dict, key, value); + bool fresh = shd_dict_insert_impl(dict, key, value); assert(fresh); } } } static void grow_and_rehash(struct Dict* dict) { - size_t old_entries_count = entries_count_dict(dict); + size_t old_entries_count = shd_dict_count(dict); void* old_alloc = dict->alloc; size_t old_size = dict->size; @@ -268,12 +269,12 @@ static void grow_and_rehash(struct Dict* dict) { #ifdef GOBLIB_DICT_DEBUG assert(dict_count_sanity(dict) == entries_count_dict(dict)); #endif - assert(old_entries_count == entries_count_dict(dict)); + assert(old_entries_count == shd_dict_count(dict)); free(old_alloc); } -bool insert_dict_impl(struct Dict* dict, void* key, void* value, void** out_ptr) { +static bool dict_insert(struct Dict* dict, void* key, void* value, void** out_ptr) { float load_factor = (float) (dict->entries_count + dict->thombstones_count) / (float) dict->size; if (load_factor > 0.6) grow_and_rehash(dict); @@ -358,7 +359,7 @@ bool insert_dict_impl(struct Dict* dict, void* key, void* value, void** out_ptr) return mode == Inserting; } -bool dict_iter(struct Dict* dict, size_t* iterator_state, void* key, void* value) { +bool shd_dict_iter(struct Dict* dict, size_t* iterator_state, void* key, void* value) { bool found_something = false; while (!found_something) { if (*iterator_state >= dict->size) { @@ -383,7 +384,7 @@ bool dict_iter(struct Dict* dict, size_t* iterator_state, void* key, void* value #include "murmur3.h" -KeyHash hash_murmur(const void* data, size_t size) { +KeyHash shd_hash_murmur(const void* data, size_t size) { int32_t out[4]; MurmurHash3_x64_128(data, (int) size, 0x1234567, &out); @@ -395,10 +396,10 @@ KeyHash hash_murmur(const void* data, size_t size) { return final; } -KeyHash hash_ptr(void** p) { - return hash_murmur(p, sizeof(void*)); +KeyHash shd_hash_ptr(void** p) { + return shd_hash_murmur(p, sizeof(void*)); } -bool compare_ptrs(void** a, void** b) { +bool shd_compare_ptrs(void** a, void** b) { return *a == *b; } diff --git a/src/common/dict.h b/src/common/dict.h index 3d91e3f6e..b4bb79f3a 100644 --- a/src/common/dict.h +++ b/src/common/dict.h @@ -14,41 +14,41 @@ typedef bool (*CmpFn)(void*, void*); struct Dict; -#define new_dict(K, T, hash, cmp) new_dict_impl(sizeof(K), sizeof(T), alignof(K), alignof(T), hash, cmp) -#define new_set(K, hash, cmp) new_dict_impl(sizeof(K), 0, alignof(K), 0, hash, cmp) -struct Dict* new_dict_impl(size_t key_size, size_t value_size, size_t key_align, size_t value_align, KeyHash (*)(void*), bool (*)(void*, void*)); +#define shd_new_dict(K, T, hash, cmp) shd_new_dict_impl(sizeof(K), sizeof(T), alignof(K), alignof(T), hash, cmp) +#define shd_new_set(K, hash, cmp) shd_new_dict_impl(sizeof(K), 0, alignof(K), 0, hash, cmp) +struct Dict* shd_new_dict_impl(size_t key_size, size_t value_size, size_t key_align, size_t value_align, KeyHash (* hash_fn)(void*), bool (* cmp_fn)(void*, void*)); -struct Dict* clone_dict(struct Dict*); -void destroy_dict(struct Dict*); -void clear_dict(struct Dict*); +struct Dict* shd_clone_dict(struct Dict* source); +void shd_destroy_dict(struct Dict* dict); +void shd_dict_clear(struct Dict* dict); -bool dict_iter(struct Dict*, size_t* iterator_state, void* key, void* value); +bool shd_dict_iter(struct Dict* dict, size_t* iterator_state, void* key, void* value); -size_t entries_count_dict(struct Dict*); +size_t shd_dict_count(struct Dict* dict); -#define find_value_dict(K, T, dict, key) (T*) find_value_dict_impl(dict, (void*) (&(key))) -#define find_key_dict(K, dict, key) (K*) find_key_dict_impl(dict, (void*) (&(key))) -void* find_key_dict_impl(struct Dict*, void*); -void* find_value_dict_impl(struct Dict*, void*); +#define shd_dict_find_value(K, T, dict, key) (T*) shd_dict_find_value_impl(dict, (void*) (&(key))) +#define shd_dict_find_key(K, dict, key) (K*) shd_dict_find_impl(dict, (void*) (&(key))) +void* shd_dict_find_impl(struct Dict*, void*); +void* shd_dict_find_value_impl(struct Dict*, void*); -#define remove_dict(K, dict, key) remove_dict_impl(dict, (void*) (&(key))) -bool remove_dict_impl(struct Dict* dict, void* key); +#define shd_dict_remove(K, dict, key) shd_dict_remove_impl(dict, (void*) (&(key))) +bool shd_dict_remove_impl(struct Dict* dict, void* key); -#define insert_dict_and_get_value(K, V, dict, key, value) *(V*) insert_dict_and_get_value_impl(dict, (void*) (&(key)), (void*) (&(value))) -#define insert_dict(K, V, dict, key, value) insert_dict_and_get_value_impl(dict, (void*) (&(key)), (void*) (&(value))) -void* insert_dict_and_get_value_impl(struct Dict*, void* key, void* value); +#define shd_dict_insert_get_value(K, V, dict, key, value) *(V*) shd_dict_insert_get_value_impl(dict, (void*) (&(key)), (void*) (&(value))) +#define shd_dict_insert(K, V, dict, key, value) shd_dict_insert_get_value_impl(dict, (void*) (&(key)), (void*) (&(value))) +void* shd_dict_insert_get_value_impl(struct Dict*, void* key, void* value); -#define insert_dict_and_get_key(K, V, dict, key, value) *(K*) insert_dict_and_get_key_impl(dict, (void*) (&(key)), (void*) (&(value))) -#define insert_set_get_key(K, dict, key) *(K*) insert_dict_and_get_key_impl(dict, (void*) (&(key)), NULL) -void* insert_dict_and_get_key_impl(struct Dict*, void* key, void* value); +#define shd_dict_insert_get_key(K, V, dict, key, value) *(K*) shd_dict_insert_get_key_impl(dict, (void*) (&(key)), (void*) (&(value))) +#define shd_set_insert_get_key(K, dict, key) *(K*) shd_dict_insert_get_key_impl(dict, (void*) (&(key)), NULL) +void* shd_dict_insert_get_key_impl(struct Dict*, void* key, void* value); -#define insert_dict_and_get_result(K, V, dict, key, value) insert_dict_and_get_result_impl(dict, (void*) (&(key)), (void*) (&(value))) -#define insert_set_get_result(K, dict, key) insert_dict_and_get_result_impl(dict, (void*) (&(key)), NULL) -bool insert_dict_and_get_result_impl(struct Dict*, void* key, void* value); +#define shd_dict_insert_get_result(K, V, dict, key, value) shd_dict_insert_impl(dict, (void*) (&(key)), (void*) (&(value))) +#define shd_set_insert_get_result(K, dict, key) shd_dict_insert_impl(dict, (void*) (&(key)), NULL) +bool shd_dict_insert_impl(struct Dict*, void* key, void* value); -KeyHash hash_murmur(const void* data, size_t size); +KeyHash shd_hash_murmur(const void* data, size_t size); -KeyHash hash_ptr(void**); -bool compare_ptrs(void**, void**); +KeyHash shd_hash_ptr(void**); +bool shd_compare_ptrs(void**, void**); #endif diff --git a/src/common/test_dict.c b/src/common/test_dict.c index f4e29a4b0..d1b2095c7 100644 --- a/src/common/test_dict.c +++ b/src/common/test_dict.c @@ -28,7 +28,7 @@ void shuffle(int arr[]) { int main(int argc, char** argv) { srand((int) get_time_nano()); - struct Dict* d = new_set(int, (HashFn) bad_hash_i32, (CmpFn) compare_i32); + struct Dict* d = shd_new_set(int, (HashFn) bad_hash_i32, (CmpFn) compare_i32); int arr[TEST_ENTRIES]; for (int i = 0; i < TEST_ENTRIES; i++) { @@ -41,7 +41,7 @@ int main(int argc, char** argv) { memset(contained, 0, sizeof(contained)); for (int i = 0; i < TEST_ENTRIES; i++) { - bool unique = insert_set_get_result(int, d, arr[i]); + bool unique = shd_set_insert_get_result(int, d, arr[i]); if (!unique) { error("Entry %d was thought to be already in the dict", arr[i]); } @@ -51,27 +51,27 @@ int main(int argc, char** argv) { shuffle(arr); for (int i = 0; i < TEST_ENTRIES; i++) { assert(contained[arr[i]]); - assert(find_key_dict(int, d, arr[i])); + assert(shd_dict_find_key(int, d, arr[i])); } shuffle(arr); for (int i = 0; i < rand() % TEST_ENTRIES; i++) { assert(contained[arr[i]]); - bool removed = remove_dict(int, d, arr[i]); + bool removed = shd_dict_remove(int, d, arr[i]); assert(removed); contained[arr[i]] = false; } shuffle(arr); for (int i = 0; i < TEST_ENTRIES; i++) { - assert(!!find_key_dict(int, d, arr[i]) == contained[arr[i]]); + assert(!!shd_dict_find_key(int, d, arr[i]) == contained[arr[i]]); } shuffle(arr); for (int i = 0; i < TEST_ENTRIES; i++) { - assert(!!find_key_dict(int, d, arr[i]) == contained[arr[i]]); + assert(!!shd_dict_find_key(int, d, arr[i]) == contained[arr[i]]); if (!contained[arr[i]]) { - bool unique = insert_set_get_result(int, d, arr[i]); + bool unique = shd_set_insert_get_result(int, d, arr[i]); if (!unique) { error("Entry %d was thought to be already in the dict", arr[i]); } @@ -83,9 +83,9 @@ int main(int argc, char** argv) { shuffle(arr); for (int i = 0; i < TEST_ENTRIES; i++) { assert(contained[arr[i]]); - assert(find_key_dict(int, d, arr[i])); + assert(shd_dict_find_key(int, d, arr[i])); } - destroy_dict(d); + shd_destroy_dict(d); return 0; } diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 4e9ed316b..ae62aff0a 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -22,7 +22,7 @@ static KeyHash hash_opaque_ptr(OpaqueRef* pvalue) { if (!pvalue) return 0; size_t ptr = *(size_t*) pvalue; - return hash_murmur(&ptr, sizeof(size_t)); + return shd_hash_murmur(&ptr, sizeof(size_t)); } static bool cmp_opaque_ptr(OpaqueRef* a, OpaqueRef* b) { @@ -59,7 +59,7 @@ static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { const Node* emitted = convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr); if (!emitted) continue; - insert_dict(LLVMValueRef, const Node*, p->map, instr, emitted); + shd_dict_insert(LLVMValueRef, const Node*, p->map, instr, emitted); } log_string(ERROR, "Reached end of LLVM basic block without encountering a terminator!"); SHADY_UNREACHABLE; @@ -84,7 +84,7 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic switch (LLVMGetInstructionOpcode(instr)) { case LLVMPHI: { const Node* nparam = param(a, qualified_type_helper(convert_type(p, LLVMTypeOf(instr)), false), "phi"); - insert_dict(LLVMValueRef, const Node*, p->map, instr, nparam); + shd_dict_insert(LLVMValueRef, const Node*, p->map, instr, nparam); shd_list_append(LLVMValueRef, phis, instr); params = append_nodes(a, params, nparam); break; @@ -99,8 +99,8 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic if (strlen(name) == 0) name = NULL; Node* nbb = basic_block(a, params, name); - insert_dict(LLVMValueRef, const Node*, p->map, bb, nbb); - insert_dict(const Node*, struct List*, fn_ctx->phis, nbb, phis); + shd_dict_insert(LLVMValueRef, const Node*, p->map, bb, nbb); + shd_dict_insert(const Node*, struct List*, fn_ctx->phis, nbb, phis); *ctx = (BBParseCtx) { .bb = bb, .instr = instr, @@ -110,18 +110,18 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic } static BBParseCtx* get_bb_ctx(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { - BBParseCtx** found = find_value_dict(LLVMValueRef, BBParseCtx*, fn_ctx->bbs, bb); + BBParseCtx** found = shd_dict_find_value(LLVMValueRef, BBParseCtx*, fn_ctx->bbs, bb); if (found) return *found; BBParseCtx* ctx = shd_arena_alloc(p->annotations_arena, sizeof(BBParseCtx)); prepare_bb(p, fn_ctx, ctx, bb); - insert_dict(LLVMBasicBlockRef, BBParseCtx*, fn_ctx->bbs, bb, ctx); + shd_dict_insert(LLVMBasicBlockRef, BBParseCtx*, fn_ctx->bbs, bb, ctx); return ctx; } const Node* convert_basic_block_header(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { - const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); + const Node** found = shd_dict_find_value(LLVMValueRef, const Node*, p->map, bb); if (found) return *found; BBParseCtx* ctx = get_bb_ctx(p, fn_ctx, bb); @@ -149,7 +149,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { return NULL; } - const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, fn); + const Node** found = shd_dict_find_value(LLVMValueRef, const Node*, p->map, fn); if (found) return *found; IrArena* a = get_module_arena(p->dst); debug_print("Converting function: %s\n", LLVMGetValueName(fn)); @@ -159,7 +159,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { LLVMTypeRef ot = LLVMTypeOf(oparam); const Type* t = convert_type(p, ot); const Node* nparam = param(a, qualified_type_helper(t, false), LLVMGetValueName(oparam)); - insert_dict(LLVMValueRef, const Node*, p->map, oparam, nparam); + shd_dict_insert(LLVMValueRef, const Node*, p->map, oparam, nparam); params = append_nodes(a, params, nparam); if (oparam == LLVMGetLastParam(fn)) break; @@ -180,19 +180,19 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { Node* f = function(p->dst, params, LLVMGetValueName(fn), annotations, fn_type->payload.fn_type.return_types); FnParseCtx fn_parse_ctx = { .fn = f, - .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), - .bbs = new_dict(LLVMBasicBlockRef, BBParseCtx*, (HashFn) hash_ptr, (CmpFn) compare_ptrs), + .phis = shd_new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), + .bbs = shd_new_dict(LLVMBasicBlockRef, BBParseCtx*, (HashFn) shd_hash_ptr, (CmpFn) shd_compare_ptrs), .jumps_todo = shd_new_list(JumpTodo), }; const Node* r = fn_addr_helper(a, f); r = prim_op_helper(a, reinterpret_op, singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = unit_type(a) })), singleton(r)); //r = prim_op_helper(a, convert_op, singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = unit_type(a) })), singleton(r)); - insert_dict(LLVMValueRef, const Node*, p->map, fn, r); + shd_dict_insert(LLVMValueRef, const Node*, p->map, fn, r); size_t bb_count = LLVMCountBasicBlocks(fn); if (bb_count > 0) { LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); - insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); + shd_dict_insert(LLVMValueRef, const Node*, p->map, first_bb, f); //LLVMBasicBlockRef bb = LLVMGetNextBasicBlock(first_bb); //LARRAY(BBParseCtx, bbs, bb_count); @@ -204,7 +204,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { }; //BBParseCtx* bb0p = &bbs[0]; BBParseCtx* bb0p = &bb0; - insert_dict(LLVMBasicBlockRef, BBParseCtx*, fn_parse_ctx.bbs, first_bb, bb0p); + shd_dict_insert(LLVMBasicBlockRef, BBParseCtx*, fn_parse_ctx.bbs, first_bb, bb0p); write_bb_body(p, &fn_parse_ctx, &bb0); write_bb_tail(p, &fn_parse_ctx, &bb0); @@ -226,19 +226,19 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { { size_t i = 0; struct List* phis_list; - while (dict_iter(fn_parse_ctx.phis, &i, NULL, &phis_list)) { + while (shd_dict_iter(fn_parse_ctx.phis, &i, NULL, &phis_list)) { shd_destroy_list(phis_list); } } - destroy_dict(fn_parse_ctx.phis); - destroy_dict(fn_parse_ctx.bbs); + shd_destroy_dict(fn_parse_ctx.phis); + shd_destroy_dict(fn_parse_ctx.bbs); shd_destroy_list(fn_parse_ctx.jumps_todo); return r; } const Node* convert_global(Parser* p, LLVMValueRef global) { - const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, global); + const Node** found = shd_dict_find_value(LLVMValueRef, const Node*, p->map, global); if (found) return *found; IrArena* a = get_module_arena(p->dst); @@ -281,7 +281,7 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { assert(decl && is_declaration(decl)); const Node* r = ref_decl_helper(a, decl); - insert_dict(LLVMValueRef, const Node*, p->map, global, r); + shd_dict_insert(LLVMValueRef, const Node*, p->map, global, r); return r; } @@ -307,8 +307,8 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* Parser p = { .ctx = context, .config = config, - .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), - .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), + .map = shd_new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), + .annotations = shd_new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations_arena = shd_new_arena(), .src = src, .dst = dirty, @@ -342,8 +342,8 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* verify_module(config, *dst); destroy_ir_arena(arena); - destroy_dict(p.map); - destroy_dict(p.annotations); + shd_destroy_dict(p.map); + shd_destroy_dict(p.annotations); shd_destroy_arena(p.annotations_arena); LLVMContextDispose(context); diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 5fa0c799b..cf484ecab 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -6,11 +6,11 @@ #include ParsedAnnotation* find_annotation(Parser* p, const Node* n) { - return find_value_dict(const Node*, ParsedAnnotation, p->annotations, n); + return shd_dict_find_value(const Node*, ParsedAnnotation, p->annotations, n); } void add_annotation(Parser* p, const Node* n, ParsedAnnotation a) { - ParsedAnnotation* found = find_value_dict(const Node*, ParsedAnnotation, p->annotations, n); + ParsedAnnotation* found = shd_dict_find_value(const Node*, ParsedAnnotation, p->annotations, n); if (found) { ParsedAnnotation* data = shd_arena_alloc(p->annotations_arena, sizeof(a)); *data = a; @@ -18,7 +18,7 @@ void add_annotation(Parser* p, const Node* n, ParsedAnnotation a) { found = found->next; found->next = data; } else { - insert_dict(const Node*, ParsedAnnotation, p->annotations, n, a); + shd_dict_insert(const Node*, ParsedAnnotation, p->annotations, n, a); } } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 1704acec4..e98ee0fa9 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -59,7 +59,7 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, LLVMBasicBlockRef dst, const Node* mem) { IrArena* a = fn_ctx->fn->arena; const Node* dst_bb = convert_basic_block_body(p, fn_ctx, dst); - struct List* phis = *find_value_dict(const Node*, struct List*, fn_ctx->phis, dst_bb); + struct List* phis = *shd_dict_find_value(const Node*, struct List*, fn_ctx->phis, dst_bb); assert(phis); size_t params_count = shd_list_count(phis); LARRAY(const Node*, params, params_count); diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index 7dc7887b1..d258efcd3 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -29,7 +29,7 @@ static const Node* convert_named_tuple_metadata(Parser* p, LLVMValueRef v, Strin name = unique_name(a, node_name); Node* g = global_var(p->dst, singleton(annotation(a, (Annotation) { .name = "LLVMMetaData" })), unit_type(a), name, AsDebugInfo); const Node* r = ref_decl_helper(a, g); - insert_dict(LLVMValueRef, const Type*, p->map, v, r); + shd_dict_insert(LLVMValueRef, const Type*, p->map, v, r); Nodes args = convert_mdnode_operands(p, v); args = prepend_nodes(a, args, string_lit_helper(a, node_name)); @@ -128,7 +128,7 @@ const Node* convert_metadata(Parser* p, LLVMMetadataRef meta) { LLVMValueRef v = LLVMMetadataAsValue(p->ctx, meta); if (v) { - const Type** found = find_value_dict(LLVMTypeRef, const Type*, p->map, v); + const Type** found = shd_dict_find_value(LLVMTypeRef, const Type*, p->map, v); if (found) return *found; } diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index 1cd5906f0..fdb96c700 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -7,7 +7,7 @@ #include "util.h" const Type* convert_type(Parser* p, LLVMTypeRef t) { - const Type** found = find_value_dict(LLVMTypeRef, const Type*, p->map, t); + const Type** found = shd_dict_find_value(LLVMTypeRef, const Type*, p->map, t); if (found) return *found; IrArena* a = get_module_arena(p->dst); @@ -54,7 +54,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { if (name) { decl = nominal_type(p->dst, empty(a), name); result = type_decl_ref_helper(a, decl); - insert_dict(LLVMTypeRef, const Type*, p->map, t, result); + shd_dict_insert(LLVMTypeRef, const Type*, p->map, t, result); } unsigned size = LLVMCountStructElementTypes(t); diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index a1ca549ad..6c3650f66 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -44,7 +44,7 @@ static const Node* data_composite(const Type* t, size_t size, LLVMValueRef v) { } const Node* convert_value(Parser* p, LLVMValueRef v) { - const Type** found = find_value_dict(LLVMTypeRef, const Type*, p->map, v); + const Type** found = shd_dict_find_value(LLVMTypeRef, const Type*, p->map, v); if (found) return *found; IrArena* a = get_module_arena(p->dst); @@ -82,7 +82,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { assert(t); Node* decl = constant(p->dst, annotations, t, name); r = ref_decl_helper(a, decl); - insert_dict(LLVMTypeRef, const Type*, p->map, v, r); + shd_dict_insert(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = begin_block_pure(a); decl->payload.constant.value = yield_value_and_wrap_in_block(bb, convert_instruction(p, NULL, NULL, bb, v)); return r; @@ -190,7 +190,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { } if (r) { - insert_dict(LLVMTypeRef, const Type*, p->map, v, r); + shd_dict_insert(LLVMTypeRef, const Type*, p->map, v, r); return r; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 0674c9918..cf424353a 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -398,7 +398,7 @@ Nodes get_args_from_phi(SpvParser* parser, SpvId block, SpvId predecessor) { if (params_count == 0) return empty(parser->arena); - SpvPhiArgs** found = find_value_dict(SpvId, SpvPhiArgs*, parser->phi_arguments, block); + SpvPhiArgs** found = shd_dict_find_value(SpvId, SpvPhiArgs*, parser->phi_arguments, block); assert(found); SpvPhiArgs* arg = *found; while (true) { @@ -931,7 +931,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .next_ = NULL, }; - SpvPhiArgs** found = find_value_dict(SpvId, SpvPhiArgs*, parser->phi_arguments, parser->current_block.id); + SpvPhiArgs** found = shd_dict_find_value(SpvId, SpvPhiArgs*, parser->phi_arguments, parser->current_block.id); if (found) { SpvPhiArgs* arg = *found; while (arg->next_) { @@ -939,7 +939,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } arg->next_ = new; } else { - insert_dict(SpvId, SpvPhiArgs*, parser->phi_arguments, parser->current_block.id, new); + shd_dict_insert(SpvId, SpvPhiArgs*, parser->phi_arguments, parser->current_block.id, new); } debugv_print("s2s: recorded argument %d (value id=%d) for block %d with predecessor %d\n", parser->fun_arg_i, argument_value, parser->current_block.id, predecessor_block); @@ -1329,7 +1329,7 @@ SpvDef* get_definition_by_id(SpvParser* parser, size_t id) { } KeyHash hash_spvid(SpvId* p) { - return hash_murmur(p, sizeof(SpvId)); + return shd_hash_murmur(p, sizeof(SpvId)); } bool compare_spvid(SpvId* pa, SpvId* pb) { @@ -1351,7 +1351,7 @@ S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const .arena = get_module_arena(*dst), .decorations_arena = shd_new_arena(), - .phi_arguments = new_dict(SpvId, SpvPhiArgs*, (HashFn) hash_spvid, (CmpFn) compare_spvid), + .phi_arguments = shd_new_dict(SpvId, SpvPhiArgs*, (HashFn) hash_spvid, (CmpFn) compare_spvid), }; if (!parse_spv_header(&parser)) @@ -1365,7 +1365,7 @@ S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const parser.cursor += parse_spv_instruction_at(&parser, parser.cursor); } - destroy_dict(parser.phi_arguments); + shd_destroy_dict(parser.phi_arguments); shd_destroy_arena(parser.decorations_arena); free(parser.defs); diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index 91988e9de..448e6f1f3 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -212,7 +212,7 @@ KeyHash hash_string(const char** string); bool compare_string(const char** a, const char** b); static KeyHash hash_spec_program_key(SpecProgramKey* ptr) { - return hash_murmur(ptr->base, sizeof(Program*)) ^ hash_string(&ptr->entry_point); + return shd_hash_murmur(ptr->base, sizeof(Program*)) ^ hash_string(&ptr->entry_point); } static bool cmp_spec_program_keys(SpecProgramKey* a, SpecProgramKey* b) { @@ -271,7 +271,7 @@ static VkrDevice* create_vkr_device(SHADY_UNUSED VkrBackend* runtime, VkPhysical .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT }, NULL, &device->cmd_pool), goto delete_device); - device->specialized_programs = new_dict(SpecProgramKey, VkrSpecProgram*, (HashFn) hash_spec_program_key, (CmpFn) cmp_spec_program_keys); + device->specialized_programs = shd_new_dict(SpecProgramKey, VkrSpecProgram*, (HashFn) hash_spec_program_key, (CmpFn) cmp_spec_program_keys); vkGetDeviceQueue(device->device, device->caps.compute_queue_family, 0, &device->compute_queue); @@ -290,10 +290,10 @@ static void shutdown_vkr_device(VkrDevice* device) { size_t i = 0; SpecProgramKey k; VkrSpecProgram* sp; - while (dict_iter(device->specialized_programs, &i, &k, &sp)) { + while (shd_dict_iter(device->specialized_programs, &i, &k, &sp)) { destroy_specialized_program(sp); } - destroy_dict(device->specialized_programs); + shd_destroy_dict(device->specialized_programs); vkDestroyCommandPool(device->device, device->cmd_pool, NULL); vkDestroyDevice(device->device, NULL); free(device); diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index ea3121f92..4122c69a3 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -497,12 +497,12 @@ static VkrSpecProgram* create_specialized_program(SpecProgramKey key, VkrDevice* VkrSpecProgram* get_specialized_program(Program* program, String entry_point, VkrDevice* device) { SpecProgramKey key = { .base = program, .entry_point = entry_point }; - VkrSpecProgram** found = find_value_dict(SpecProgramKey, VkrSpecProgram*, device->specialized_programs, key); + VkrSpecProgram** found = shd_dict_find_value(SpecProgramKey, VkrSpecProgram*, device->specialized_programs, key); if (found) return *found; VkrSpecProgram* spec = create_specialized_program(key, device); assert(spec); - insert_dict(SpecProgramKey, VkrSpecProgram*, device->specialized_programs, key, spec); + shd_dict_insert(SpecProgramKey, VkrSpecProgram*, device->specialized_programs, key, spec); return spec; } diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index b514c7ca9..57124442a 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -16,7 +16,7 @@ KeyHash hash_node(const Node**); bool compare_node(const Node**, const Node**); KeyHash hash_cgedge(CGEdge* n) { - return hash_murmur(n, sizeof(CGEdge)); + return shd_hash_murmur(n, sizeof(CGEdge)); } bool compare_cgedge(CGEdge* a, CGEdge* b) { @@ -52,8 +52,8 @@ static void visit_callsite(CGVisitor* visitor, const Node* callee, const Node* i .dst_fn = target, .instr = instr, }; - insert_set_get_result(CGEdge, visitor->root->callees, edge); - insert_set_get_result(CGEdge, target->callers, edge); + shd_set_insert_get_result(CGEdge, visitor->root->callees, edge); + shd_set_insert_get_result(CGEdge, target->callers, edge); } static void search_for_callsites(CGVisitor* visitor, const Node* node) { @@ -87,15 +87,15 @@ static void search_for_callsites(CGVisitor* visitor, const Node* node) { static CGNode* analyze_fn(CallGraph* graph, const Node* fn) { assert(fn && fn->tag == Function_TAG); - CGNode** found = find_value_dict(const Node*, CGNode*, graph->fn2cgn, fn); + CGNode** found = shd_dict_find_value(const Node*, CGNode*, graph->fn2cgn, fn); if (found) return *found; CGNode* new = calloc(1, sizeof(CGNode)); new->fn = fn; - new->callees = new_set(CGEdge, (HashFn) hash_cgedge, (CmpFn) compare_cgedge); - new->callers = new_set(CGEdge, (HashFn) hash_cgedge, (CmpFn) compare_cgedge); + new->callees = shd_new_set(CGEdge, (HashFn) hash_cgedge, (CmpFn) compare_cgedge); + new->callers = shd_new_set(CGEdge, (HashFn) hash_cgedge, (CmpFn) compare_cgedge); new->tarjan.index = -1; - insert_dict_and_get_key(const Node*, CGNode*, graph->fn2cgn, fn, new); + shd_dict_insert_get_key(const Node*, CGNode*, graph->fn2cgn, fn, new); CGVisitor v = { .visitor = { @@ -139,8 +139,8 @@ static void strongconnect(CGNode* v, int* index, struct List* stack) { { size_t iter = 0; CGEdge e; - debugv_print(" has %d successors\n", entries_count_dict(v->callees)); - while (dict_iter(v->callees, &iter, &e, NULL)) { + debugv_print(" has %d successors\n", shd_dict_count(v->callees)); + while (shd_dict_iter(v->callees, &iter, &e, NULL)) { debugv_print(" %s\n", e.dst_fn->fn->payload.fun.name); if (e.dst_fn->tarjan.index == -1) { // Successor w has not yet been visited; recurse on it @@ -186,7 +186,7 @@ static void tarjan(struct Dict* verts) { size_t iter = 0; CGNode* n; - while (dict_iter(verts, &iter, NULL, &n)) { + while (shd_dict_iter(verts, &iter, NULL, &n)) { if (n->tarjan.index == -1) strongconnect(n, &index, stack); } @@ -197,7 +197,7 @@ static void tarjan(struct Dict* verts) { CallGraph* new_callgraph(Module* mod) { CallGraph* graph = calloc(sizeof(CallGraph), 1); *graph = (CallGraph) { - .fn2cgn = new_dict(const Node*, CGNode*, (HashFn) hash_node, (CmpFn) compare_node) + .fn2cgn = shd_new_dict(const Node*, CGNode*, (HashFn) hash_node, (CmpFn) compare_node) }; const UsesMap* uses = create_module_uses_map(mod, NcType); @@ -239,7 +239,7 @@ CallGraph* new_callgraph(Module* mod) { destroy_uses_map(uses); - debugv_print("CallGraph: done with CFG build, contains %d nodes\n", entries_count_dict(graph->fn2cgn)); + debugv_print("CallGraph: done with CFG build, contains %d nodes\n", shd_dict_count(graph->fn2cgn)); tarjan(graph->fn2cgn); @@ -249,12 +249,12 @@ CallGraph* new_callgraph(Module* mod) { void destroy_callgraph(CallGraph* graph) { size_t i = 0; CGNode* node; - while (dict_iter(graph->fn2cgn, &i, NULL, &node)) { + while (shd_dict_iter(graph->fn2cgn, &i, NULL, &node)) { debugv_print("Freeing CG node: %s\n", node->fn->payload.fun.name); - destroy_dict(node->callers); - destroy_dict(node->callees); + shd_destroy_dict(node->callers); + shd_destroy_dict(node->callees); free(node); } - destroy_dict(graph->fn2cgn); + shd_destroy_dict(graph->fn2cgn); free(graph); } diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 4b6c23dbb..95ad08453 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -50,7 +50,7 @@ typedef struct { static void process_cf_node(CfgBuildContext* ctx, CFNode* node); CFNode* cfg_lookup(CFG* cfg, const Node* abs) { - CFNode** found = find_value_dict(const Node*, CFNode*, cfg->map, abs); + CFNode** found = shd_dict_find_value(const Node*, CFNode*, cfg->map, abs); if (found) { CFNode* cfnode = *found; assert(cfnode->node); @@ -69,7 +69,7 @@ static CFNode* new_cfnode(Arena* a) { .rpo_index = SIZE_MAX, .idom = NULL, .dominates = NULL, - .structurally_dominates = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .structurally_dominates = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), }; return new; } @@ -77,13 +77,13 @@ static CFNode* new_cfnode(Arena* a) { static CFNode* get_or_enqueue(CfgBuildContext* ctx, const Node* abs) { assert(is_abstraction(abs)); assert(!is_function(abs) || abs == ctx->function); - CFNode** found = find_value_dict(const Node*, CFNode*, ctx->nodes, abs); + CFNode** found = shd_dict_find_value(const Node*, CFNode*, ctx->nodes, abs); if (found) return *found; CFNode* new = new_cfnode(ctx->arena); new->node = abs; assert(abs && new->node); - insert_dict(const Node*, CFNode*, ctx->nodes, abs, new); + shd_dict_insert(const Node*, CFNode*, ctx->nodes, abs, new); process_cf_node(ctx, new); shd_list_append(Node*, ctx->contents, new); return new; @@ -142,7 +142,7 @@ static void add_structural_edge(CfgBuildContext* ctx, CFNode* parent, const Node static void add_structural_dominance_edge(CfgBuildContext* ctx, CFNode* parent, const Node* dst, CFEdgeType type, const Node* term) { add_edge(ctx, parent->node, dst, type, term); - insert_set_get_result(const Node*, parent->structurally_dominates, dst); + shd_set_insert_get_result(const Node*, parent->structurally_dominates, dst); } static void add_jump_edge(CfgBuildContext* ctx, const Node* src, const Node* j) { @@ -211,14 +211,14 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); //CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); const Node* tail = get_structured_construct_tail(terminator); - insert_dict(const Node*, const Node*, ctx->join_point_values, param, tail); + shd_dict_insert(const Node*, const Node*, ctx->join_point_values, param, tail); add_structural_dominance_edge(ctx, node, terminator->payload.control.inside, StructuredEnterBodyEdge, terminator); if (ctx->config.include_structured_tails) add_structural_dominance_edge(ctx, node, get_structured_construct_tail(terminator), StructuredTailEdge, terminator); return; } case Join_TAG: { if (ctx->config.include_structured_exits) { - const Node** dst = find_value_dict(const Node*, const Node*, ctx->join_point_values, terminator->payload.join.join_point); + const Node** dst = shd_dict_find_value(const Node*, const Node*, ctx->join_point_values, terminator->payload.join.join_point); if (dst) add_edge(ctx, node->node, *dst, StructuredLeaveBodyEdge, terminator); } @@ -381,8 +381,8 @@ CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { .arena = arena, .function = function, .entry = entry, - .nodes = new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), - .join_point_values = new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .nodes = shd_new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), + .join_point_values = shd_new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), .contents = shd_new_list(CFNode*), .config = config, }; @@ -396,7 +396,7 @@ CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { // process_cf_node(&context, this); //} - destroy_dict(context.join_point_values); + shd_destroy_dict(context.join_point_values); CFG* cfg = calloc(sizeof(CFG), 1); *cfg = (CFG) { @@ -431,7 +431,7 @@ void destroy_cfg(CFG* cfg) { if (node->dominates) shd_destroy_list(node->dominates); if (node->structurally_dominates) - destroy_dict(node->structurally_dominates); + shd_destroy_dict(node->structurally_dominates); } if (!entry_destroyed) { shd_destroy_list(cfg->entry->pred_edges); @@ -439,7 +439,7 @@ void destroy_cfg(CFG* cfg) { if (cfg->entry->dominates) shd_destroy_list(cfg->entry->dominates); } - destroy_dict(cfg->map); + shd_destroy_dict(cfg->map); shd_destroy_arena(cfg->arena); free(cfg->rpo); shd_destroy_list(cfg->contents); diff --git a/src/shady/analysis/free_frontier.c b/src/shady/analysis/free_frontier.c index d332b397d..652068f61 100644 --- a/src/shady/analysis/free_frontier.c +++ b/src/shady/analysis/free_frontier.c @@ -13,9 +13,9 @@ typedef struct { } FreeFrontierVisitor; static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { - if (find_key_dict(const Node*, v->seen, node)) + if (shd_dict_find_key(const Node*, v->seen, node)) return; - insert_set_get_result(const Node*, v->seen, node); + shd_set_insert_get_result(const Node*, v->seen, node); CFNode* where = schedule_instruction(v->scheduler, node); if (where) { FreeFrontierVisitor vv = *v; @@ -26,13 +26,13 @@ static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { struct Dict* other_ff = free_frontier(v->scheduler, v->cfg, node); size_t i = 0; const Node* f; - while (dict_iter(other_ff, &i, &f, NULL)) { - insert_set_get_result(const Node*, v->frontier, f); + while (shd_dict_iter(other_ff, &i, &f, NULL)) { + shd_set_insert_get_result(const Node*, v->frontier, f); } - destroy_dict(other_ff); + shd_destroy_dict(other_ff); } if (is_value(node)) { - insert_set_get_result(const Node*, v->frontier, node); + shd_set_insert_get_result(const Node*, v->frontier, node); } } } @@ -49,11 +49,11 @@ struct Dict* free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs) { .scheduler = scheduler, .cfg = cfg, .start = cfg_lookup(cfg, abs), - .frontier = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .seen = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .frontier = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .seen = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), }; if (get_abstraction_body(abs)) visit_free_frontier(&ffv, get_abstraction_body(abs)); - destroy_dict(ffv.seen); + shd_destroy_dict(ffv.seen); return ffv.frontier; } \ No newline at end of file diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index a3a2d1c67..0f67a41be 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -178,7 +178,7 @@ static void build_map_recursive(struct Dict* map, LTNode* n) { if (n->type == LF_LEAF) { assert(shd_list_count(n->cf_nodes) == 1); const Node* node = shd_read_list(CFNode*, n->cf_nodes)[0]->node; - insert_dict(const Node*, LTNode*, map, node, n); + shd_dict_insert(const Node*, LTNode*, map, node, n); } else { for (size_t i = 0; i < shd_list_count(n->lf_children); i++) { LTNode* child = shd_read_list(LTNode*, n->lf_children)[i]; @@ -188,7 +188,7 @@ static void build_map_recursive(struct Dict* map, LTNode* n) { } LTNode* looptree_lookup(LoopTree* lt, const Node* block) { - LTNode** found = find_value_dict(const Node*, LTNode*, lt->map, block); + LTNode** found = shd_dict_find_value(const Node*, LTNode*, lt->map, block); if (found) return *found; assert(false); } @@ -221,7 +221,7 @@ LoopTree* build_loop_tree(CFG* s) { shd_destroy_list(global_heads); shd_destroy_list(ltb.stack); - lt->map = new_dict(const Node*, LTNode*, (HashFn) hash_node, (CmpFn) compare_node); + lt->map = shd_new_dict(const Node*, LTNode*, (HashFn) hash_node, (CmpFn) compare_node); build_map_recursive(lt->map, lt->root); return lt; @@ -238,7 +238,7 @@ static void destroy_lt_node(LTNode* n) { void destroy_loop_tree(LoopTree* lt) { destroy_lt_node(lt->root); - destroy_dict(lt->map); + shd_destroy_dict(lt->map); free(lt); } diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c index 8af8e878f..f639929e8 100644 --- a/src/shady/analysis/scheduler.c +++ b/src/shady/analysis/scheduler.c @@ -51,14 +51,14 @@ Scheduler* new_scheduler(CFG* cfg) { .visit_op_fn = (VisitOpFn) visit_operand, }, .cfg = cfg, - .scheduled = new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), + .scheduled = shd_new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), }; return s; } CFNode* schedule_instruction(Scheduler* s, const Node* n) { //assert(n && is_instruction(n)); - CFNode** found = find_value_dict(const Node*, CFNode*, s->scheduled, n); + CFNode** found = shd_dict_find_value(const Node*, CFNode*, s->scheduled, n); if (found) return *found; @@ -74,11 +74,11 @@ CFNode* schedule_instruction(Scheduler* s, const Node* n) { } visit_node_operands(&s2.v, 0, n); - insert_dict(const Node*, CFNode*, s->scheduled, n, s2.result); + shd_dict_insert(const Node*, CFNode*, s->scheduled, n, s2.result); return s2.result; } void destroy_scheduler(Scheduler* s) { - destroy_dict(s->scheduled); + shd_destroy_dict(s->scheduled); free(s); } diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index b4eed1139..8361c600a 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -35,8 +35,8 @@ static Use* get_last_use(UsesMap* map, const Node* n) { } static void uses_visit_node(UsesMapVisitor* v, const Node* n) { - if (!find_key_dict(const Node*, v->seen, n)) { - insert_set_get_result(const Node*, v->seen, n); + if (!shd_dict_find_key(const Node*, v->seen, n)) { + shd_set_insert_get_result(const Node*, v->seen, n); UsesMapVisitor nv = *v; nv.user = n; visit_node_operands(&nv.v, v->exclude, n); @@ -58,7 +58,7 @@ static void uses_visit_op(UsesMapVisitor* v, NodeClass class, String op_name, co if (last_use) last_use->next_use = use; else - insert_dict(const Node*, const Use*, v->map->map, op, use); + shd_dict_insert(const Node*, const Use*, v->map->map, op, use); uses_visit_node(v, op); } @@ -66,7 +66,7 @@ static void uses_visit_op(UsesMapVisitor* v, NodeClass class, String op_name, co static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeClass exclude) { UsesMap* uses = calloc(sizeof(UsesMap), 1); *uses = (UsesMap) { - .map = new_dict(const Node*, Use*, (HashFn) hash_node, (CmpFn) compare_node), + .map = shd_new_dict(const Node*, Use*, (HashFn) hash_node, (CmpFn) compare_node), .a = shd_new_arena(), }; @@ -74,7 +74,7 @@ static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeCl .v = { .visit_op_fn = (VisitOpFn) uses_visit_op }, .map = uses, .exclude = exclude, - .seen = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .seen = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), }; if (root) uses_visit_node(&v, root); @@ -83,7 +83,7 @@ static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeCl for (size_t i = 0; i < nodes.count; i++) uses_visit_node(&v, nodes.nodes[i]); } - destroy_dict(v.seen); + shd_destroy_dict(v.seen); return uses; } @@ -97,12 +97,12 @@ const UsesMap* create_module_uses_map(const Module* m, NodeClass exclude) { void destroy_uses_map(const UsesMap* map) { shd_destroy_arena(map->a); - destroy_dict(map->map); + shd_destroy_dict(map->map); free((void*) map); } const Use* get_first_use(const UsesMap* map, const Node* n) { - const Use** found = find_value_dict(const Node*, const Use*, map->map, n); + const Use** found = shd_dict_find_value(const Node*, const Use*, map->map, n); if (found) return *found; return NULL; diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index c61b1daf9..8041bf945 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -20,9 +20,9 @@ typedef struct { static void visit_verify_same_arena(ArenaVerifyVisitor* visitor, const Node* node) { assert(visitor->arena == node->arena); - if (find_key_dict(const Node*, visitor->once, node)) + if (shd_dict_find_key(const Node*, visitor->once, node)) return; - insert_set_get_result(const Node*, visitor->once, node); + shd_set_insert_get_result(const Node*, visitor->once, node); visit_node_operands(&visitor->visitor, 0, node); } @@ -36,10 +36,10 @@ static void verify_same_arena(Module* mod) { .visit_node_fn = (VisitNodeFn) visit_verify_same_arena, }, .arena = arena, - .once = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node) + .once = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node) }; visit_module(&visitor.visitor, mod); - destroy_dict(visitor.once); + shd_destroy_dict(visitor.once); } static void verify_scoping(const CompilerConfig* config, Module* mod) { @@ -48,14 +48,14 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; Scheduler* scheduler = new_scheduler(cfg); struct Dict* set = free_frontier(scheduler, cfg, cfg->entry->node); - if (entries_count_dict(set) > 0) { + if (shd_dict_count(set) > 0) { log_string(ERROR, "Leaking variables in "); log_node(ERROR, cfg->entry->node); log_string(ERROR, ":\n"); size_t j = 0; const Node* leaking; - while (dict_iter(set, &j, &leaking, NULL)) { + while (shd_dict_iter(set, &j, &leaking, NULL)) { log_node(ERROR, leaking); error_print("\n"); } @@ -64,7 +64,7 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { log_module(ERROR, config, mod); error_die(); } - destroy_dict(set); + shd_destroy_dict(set); destroy_scheduler(scheduler); destroy_cfg(cfg); } @@ -119,7 +119,7 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { if (is_instruction(node)) { ScheduleContext* search = ctx; while (search) { - if (find_key_dict(const Node*, search->bound, node)) + if (shd_dict_find_key(const Node*, search->bound, node)) break; search = search->parent; } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 6d7335fdf..e831fb3cd 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -28,7 +28,7 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { *pfresh = false; Node* ptr = &node; - Node** found = find_key_dict(Node*, arena->node_set, ptr); + Node** found = shd_dict_find_key(Node*, arena->node_set, ptr); // sanity check nominal nodes to be unique, check for duplicates in structural nodes if (is_nominal(&node)) assert(!found); @@ -42,7 +42,7 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { Node* folded = (Node*) fold_node(arena, ptr); if (folded != ptr) { // The folding process simplified the node, we store a mapping to that simplified node and bail out ! - insert_set_get_result(Node*, arena->node_set, folded); + shd_set_insert_get_result(Node*, arena->node_set, folded); return folded; } } @@ -54,7 +54,7 @@ static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { Node* alloc = (Node*) shd_arena_alloc(arena->arena, sizeof(Node)); *alloc = node; alloc->id = allocate_node_id(arena, alloc); - insert_set_get_result(const Node*, arena->node_set, alloc); + shd_set_insert_get_result(const Node*, arena->node_set, alloc); return alloc; } diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index e40537899..01b173de1 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -57,7 +57,7 @@ static void generate_node_payload_hash_fn(Growy* g, json_object* src, json_objec String op_name = json_object_get_string(json_object_object_get(op, "name")); bool ignore = json_object_get_boolean(json_object_object_get(op, "ignore")); if (!ignore) { - growy_append_formatted(g, "\t\thash = hash ^ hash_murmur(&payload.%s, sizeof(payload.%s));\n", op_name, op_name); + growy_append_formatted(g, "\t\thash = hash ^ shd_hash_murmur(&payload.%s, sizeof(payload.%s));\n", op_name, op_name); } } growy_append_formatted(g, "\t\tbreak;\n"); diff --git a/src/shady/ir.c b/src/shady/ir.c index f5d4373ee..56b2d3acf 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -30,11 +30,11 @@ IrArena* new_ir_arena(const ArenaConfig* config) { .modules = shd_new_list(Module*), - .node_set = new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .string_set = new_set(const char*, (HashFn) hash_string, (CmpFn) compare_string), + .node_set = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .string_set = shd_new_set(const char*, (HashFn) hash_string, (CmpFn) compare_string), - .nodes_set = new_set(Nodes, (HashFn) hash_nodes, (CmpFn) compare_nodes), - .strings_set = new_set(Strings, (HashFn) hash_strings, (CmpFn) compare_strings), + .nodes_set = shd_new_set(Nodes, (HashFn) hash_nodes, (CmpFn) compare_nodes), + .strings_set = shd_new_set(Strings, (HashFn) hash_strings, (CmpFn) compare_strings), .ids = new_growy(), }; @@ -51,10 +51,10 @@ void destroy_ir_arena(IrArena* arena) { } shd_destroy_list(arena->modules); - destroy_dict(arena->strings_set); - destroy_dict(arena->string_set); - destroy_dict(arena->nodes_set); - destroy_dict(arena->node_set); + shd_destroy_dict(arena->strings_set); + shd_destroy_dict(arena->string_set); + shd_destroy_dict(arena->nodes_set); + shd_destroy_dict(arena->node_set); shd_destroy_arena(arena->arena); destroy_growy(arena->ids); free(arena); @@ -74,7 +74,7 @@ Nodes nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { .count = count, .nodes = in_nodes }; - const Nodes* found = find_key_dict(Nodes, arena->nodes_set, tmp); + const Nodes* found = shd_dict_find_key(Nodes, arena->nodes_set, tmp); if (found) return *found; @@ -84,7 +84,7 @@ Nodes nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { for (size_t i = 0; i < count; i++) nodes.nodes[i] = in_nodes[i]; - insert_set_get_result(Nodes, arena->nodes_set, nodes); + shd_set_insert_get_result(Nodes, arena->nodes_set, nodes); return nodes; } @@ -93,7 +93,7 @@ Strings strings(IrArena* arena, size_t count, const char* in_strs[]) { .count = count, .strings = in_strs, }; - const Strings* found = find_key_dict(Strings, arena->strings_set, tmp); + const Strings* found = shd_dict_find_key(Strings, arena->strings_set, tmp); if (found) return *found; @@ -103,7 +103,7 @@ Strings strings(IrArena* arena, size_t count, const char* in_strs[]) { for (size_t i = 0; i < count; i++) strings.strings[i] = in_strs[i]; - insert_set_get_result(Strings, arena->strings_set, strings); + shd_set_insert_get_result(Strings, arena->strings_set, strings); return strings; } @@ -169,7 +169,7 @@ static const char* string_impl(IrArena* arena, size_t size, const char* zero_ter if (!zero_terminated) return NULL; const char* ptr = zero_terminated; - const char** found = find_key_dict(const char*, arena->string_set, ptr); + const char** found = shd_dict_find_key(const char*, arena->string_set, ptr); if (found) return *found; @@ -177,7 +177,7 @@ static const char* string_impl(IrArena* arena, size_t size, const char* zero_ter strncpy(new_str, zero_terminated, size); new_str[size] = '\0'; - insert_set_get_result(const char*, arena->string_set, new_str); + shd_set_insert_get_result(const char*, arena->string_set, new_str); return new_str; } @@ -232,7 +232,7 @@ const char* unique_name(IrArena* arena, const char* str) { } KeyHash hash_nodes(Nodes* nodes) { - return hash_murmur(nodes->nodes, sizeof(const Node*) * nodes->count); + return shd_hash_murmur(nodes->nodes, sizeof(const Node*) * nodes->count); } bool compare_nodes(Nodes* a, Nodes* b) { @@ -243,7 +243,7 @@ bool compare_nodes(Nodes* a, Nodes* b) { } KeyHash hash_strings(Strings* strings) { - return hash_murmur(strings->strings, sizeof(char*) * strings->count); + return shd_hash_murmur(strings->strings, sizeof(char*) * strings->count); } bool compare_strings(Strings* a, Strings* b) { @@ -256,7 +256,7 @@ bool compare_strings(Strings* a, Strings* b) { KeyHash hash_string(const char** string) { if (!*string) return 0; - return hash_murmur(*string, strlen(*string)); + return shd_hash_murmur(*string, strlen(*string)); } bool compare_string(const char** a, const char** b) { diff --git a/src/shady/node.c b/src/shady/node.c index 0b5c66af3..6fd6b438a 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -343,7 +343,7 @@ KeyHash hash_node(Node** pnode) { goto end; } - KeyHash tag_hash = hash_murmur(&node->tag, sizeof(NodeTag)); + KeyHash tag_hash = shd_hash_murmur(&node->tag, sizeof(NodeTag)); KeyHash payload_hash = 0; if (node_type_has_payload[node->tag]) { diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index de3d05288..185768a26 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -60,7 +60,7 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No struct Dict* fvs = free_frontier(ctx->scheduler, ctx->cfg, old); const Node* fv; - for (size_t i = 0; dict_iter(fvs, &i, &fv, NULL);) { + for (size_t i = 0; shd_dict_iter(fvs, &i, &fv, NULL);) { const CFNode* defining_cf_node = schedule_instruction(ctx->scheduler, fv); assert(defining_cf_node); const LTNode* defining_loop = get_loop(looptree_lookup(ctx->loop_tree, defining_cf_node->node)); @@ -76,10 +76,10 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No *nargs = append_nodes(a, *nargs, narg); } } - destroy_dict(fvs); + shd_destroy_dict(fvs); if (nparams->count > 0) - insert_dict(const Node*, Nodes, ctx->lifted_arguments, old, *nparams); + shd_dict_insert(const Node*, Nodes, ctx->lifted_arguments, old, *nparams); } const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* body) { @@ -113,22 +113,22 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* new_children[i] = basic_block(a, concat_nodes(a, nparams, new_params[i]), get_abstraction_name(old_children[i])); register_processed(&ctx->rewriter, old_children[i], new_children[i]); register_processed_list(&ctx->rewriter, get_abstraction_params(old_children[i]), nparams); - insert_dict(const Node*, Nodes, ctx->lifted_arguments, old_children[i], nargs); + shd_dict_insert(const Node*, Nodes, ctx->lifted_arguments, old_children[i], nargs); } const Node* new = rewrite_node(&ctx->rewriter, body); - ctx->rewriter.map = clone_dict(ctx->rewriter.map); + ctx->rewriter.map = shd_clone_dict(ctx->rewriter.map); for (size_t i = 0; i < children_count; i++) { for (size_t j = 0; j < lifted_params[i].count; j++) { - remove_dict(const Node*, ctx->rewriter.map, lifted_params[i].nodes[j]); + shd_dict_remove(const Node*, ctx->rewriter.map, lifted_params[i].nodes[j]); } register_processed_list(&ctx->rewriter, lifted_params[i], new_params[i]); new_children[i]->payload.basic_block.body = process_abstraction_body(ctx, old_children[i], get_abstraction_body(old_children[i])); } - destroy_dict(ctx->rewriter.map); + shd_destroy_dict(ctx->rewriter.map); return new; } @@ -166,7 +166,7 @@ const Node* process_node(Context* ctx, const Node* old) { case Jump_TAG: { Jump payload = old->payload.jump; Nodes nargs = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); - Nodes* lifted_args = find_value_dict(const Node*, Nodes, ctx->lifted_arguments, old->payload.jump.target); + Nodes* lifted_args = shd_dict_find_value(const Node*, Nodes, ctx->lifted_arguments, old->payload.jump.target); if (lifted_args) { nargs = concat_nodes(a, nargs, *lifted_args); } @@ -197,11 +197,11 @@ Module* lcssa(const CompilerConfig* config, Module* src) { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .current_fn = NULL, - .lifted_arguments = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node) + .lifted_arguments = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node) }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.lifted_arguments); + shd_destroy_dict(ctx.lifted_arguments); return dst; } diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index c43fbfbf9..d9b326d5d 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -53,7 +53,7 @@ static const Node* process(Context* ctx, const Node* node) { Context bb_ctx = *ctx; bb_ctx.rewriter = create_children_rewriter(&ctx->rewriter); - while (dict_iter(frontier, &i, &value, NULL)) { + while (shd_dict_iter(frontier, &i, &value, NULL)) { if (is_value(value)) { additional_args = append_nodes(a, additional_args, value); const Type* t = rewrite_node(r, value->type); @@ -63,8 +63,8 @@ static const Node* process(Context* ctx, const Node* node) { } } - destroy_dict(frontier); - insert_dict(const Node*, Nodes, ctx->lift, node, additional_args); + shd_destroy_dict(frontier); + shd_dict_insert(const Node*, Nodes, ctx->lift, node, additional_args); Node* new_bb = basic_block(a, new_params, get_abstraction_name_unsafe(node)); Context* fn_ctx = ctx; @@ -85,7 +85,7 @@ static const Node* process(Context* ctx, const Node* node) { Jump payload = node->payload.jump; rewrite_node(r, payload.target); - Nodes* additional_args = find_value_dict(const Node*, Nodes, ctx->lift, payload.target); + Nodes* additional_args = shd_dict_find_value(const Node*, Nodes, ctx->lift, payload.target); assert(additional_args); return jump(a, (Jump) { .mem = rewrite_node(r, payload.mem), @@ -109,10 +109,10 @@ Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .lift = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), + .lift = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), }; rewrite_module(&ctx.rewriter); - destroy_dict(ctx.lift); + shd_destroy_dict(ctx.lift); destroy_rewriter(&ctx.rewriter); src = dst; } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index be8edaefb..18e341972 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -60,11 +60,11 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, Nodes sp } static Nodes set2nodes(IrArena* a, struct Dict* set) { - size_t count = entries_count_dict(set); + size_t count = shd_dict_count(set); LARRAY(const Node*, tmp, count); size_t i = 0, j = 0; const Node* key; - while (dict_iter(set, &i, &key, NULL)) { + while (shd_dict_iter(set, &i, &key, NULL)) { tmp[j++] = key; } assert(j == count); @@ -73,7 +73,7 @@ static Nodes set2nodes(IrArena* a, struct Dict* set) { static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { assert(is_basic_block(liftee)); - LiftedCont** found = find_value_dict(const Node*, LiftedCont*, ctx->lifted, liftee); + LiftedCont** found = shd_dict_find_value(const Node*, LiftedCont*, ctx->lifted, liftee); if (found) return *found; @@ -84,7 +84,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { Scheduler* scheduler = new_scheduler(cfg); struct Dict* frontier_set = free_frontier(scheduler, cfg, liftee); Nodes frontier = set2nodes(a, frontier_set); - destroy_dict(frontier_set); + shd_destroy_dict(frontier_set); size_t recover_context_size = frontier.count; @@ -117,7 +117,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { LiftedCont* lifted_cont = calloc(sizeof(LiftedCont), 1); lifted_cont->old_cont = liftee; lifted_cont->save_values = frontier; - insert_dict(const Node*, LiftedCont*, ctx->lifted, liftee, lifted_cont); + shd_dict_insert(const Node*, LiftedCont*, ctx->lifted, liftee, lifted_cont); register_processed_list(r, ovariables, new_params); @@ -234,7 +234,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { bool todo = false; Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), - .lifted = new_dict(const Node*, LiftedCont*, (HashFn) hash_node, (CmpFn) compare_node), + .lifted = shd_new_dict(const Node*, LiftedCont*, (HashFn) hash_node, (CmpFn) compare_node), .config = config, .todo = &todo @@ -244,10 +244,10 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { size_t iter = 0; LiftedCont* lifted_cont; - while (dict_iter(ctx.lifted, &iter, NULL, &lifted_cont)) { + while (shd_dict_iter(ctx.lifted, &iter, NULL, &lifted_cont)) { free(lifted_cont); } - destroy_dict(ctx.lifted); + shd_destroy_dict(ctx.lifted); destroy_rewriter(&ctx.rewriter); verify_module(config, dst); src = dst; diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index cf30a8d62..fe2722456 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -48,7 +48,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { IrArena* a = vctx->context->rewriter.dst_arena; switch (node->tag) { case StackAlloc_TAG: { - StackSlot* found = find_value_dict(const Node*, StackSlot, vctx->prepared_offsets, node); + StackSlot* found = shd_dict_find_value(const Node*, StackSlot, vctx->prepared_offsets, node); if (found) break; @@ -58,7 +58,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { shd_list_append(const Type*, vctx->members, element_type); StackSlot slot = { vctx->num_slots, slot_offset, element_type, AsPrivate }; - insert_dict(const Node*, StackSlot, vctx->prepared_offsets, node, slot); + shd_dict_insert(const Node*, StackSlot, vctx->prepared_offsets, node, slot); vctx->num_slots++; break; @@ -90,7 +90,7 @@ static const Node* process(Context* ctx, const Node* node) { } BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); - ctx2.prepared_offsets = new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); + ctx2.prepared_offsets = shd_new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); ctx2.base_stack_addr_on_entry = gen_get_stack_base_addr(bb); ctx2.stack_size_on_entry = gen_get_stack_size(bb); set_value_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); @@ -123,12 +123,12 @@ static const Node* process(Context* ctx, const Node* node) { register_processed(r, get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); - destroy_dict(ctx2.prepared_offsets); + shd_destroy_dict(ctx2.prepared_offsets); return fun; } case StackAlloc_TAG: { if (!ctx->disable_lowering) { - StackSlot* found_slot = find_value_dict(const Node*, StackSlot, ctx->prepared_offsets, node); + StackSlot* found_slot = shd_dict_find_value(const Node*, StackSlot, ctx->prepared_offsets, node); if (!found_slot) { error_print("lower_alloca: failed to find a stack offset for "); log_node(ERROR, node); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 765d1dff8..ccd742d3f 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -53,7 +53,7 @@ static const Node* process_node(Context* ctx, const Node* node) { }); const Node* jp = param(a, jp_type, "if_join"); Nodes jps = singleton(jp); - insert_dict(const Node*, Nodes, ctx->structured_join_tokens, node, jps); + shd_dict_insert(const Node*, Nodes, ctx->structured_join_tokens, node, jps); const Node* true_block = rewrite_node(r, payload.if_true); @@ -99,7 +99,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* break_point = param(a, break_jp_type, "loop_break_point"); const Node* continue_point = param(a, continue_jp_type, "loop_continue_point"); Nodes jps = mk_nodes(a, break_point, continue_point); - insert_dict(const Node*, Nodes, ctx->structured_join_tokens, node, jps); + shd_dict_insert(const Node*, Nodes, ctx->structured_join_tokens, node, jps); Nodes new_params = recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_block)); Node* loop_header_block = basic_block(a, new_params, unique_name(a, "loop_header")); @@ -146,7 +146,7 @@ static const Node* process_node(Context* ctx, const Node* node) { error_die(); } - Nodes* jps = find_value_dict(const Node*, Nodes, ctx->structured_join_tokens, selection_instr); + Nodes* jps = shd_dict_find_value(const Node*, Nodes, ctx->structured_join_tokens, selection_instr); assert(jps && jps->count == 1); const Node* jp = first(*jps); assert(jp); @@ -180,7 +180,7 @@ static const Node* process_node(Context* ctx, const Node* node) { error_die(); } - Nodes* jps = find_value_dict(const Node*, Nodes, ctx->structured_join_tokens, loop_start); + Nodes* jps = shd_dict_find_value(const Node*, Nodes, ctx->structured_join_tokens, loop_start); assert(jps && jps->count == 2); const Node* jp = jps->nodes[1]; assert(jp); @@ -214,7 +214,7 @@ static const Node* process_node(Context* ctx, const Node* node) { error_die(); } - Nodes* jps = find_value_dict(const Node*, Nodes, ctx->structured_join_tokens, loop_start); + Nodes* jps = shd_dict_find_value(const Node*, Nodes, ctx->structured_join_tokens, loop_start); assert(jps && jps->count == 2); const Node* jp = first(*jps); assert(jp); @@ -239,11 +239,11 @@ Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), - .structured_join_tokens = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), + .structured_join_tokens = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.structured_join_tokens); + shd_destroy_dict(ctx.structured_join_tokens); return dst; } diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index fec30259e..e1b2c160d 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -85,7 +85,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo case StoreFn: name = format_string_interned(a, "generated_store_Generic_%s", name_type_safe(a, t)); break; } - const Node** found = find_value_dict(String, const Node*, ctx->fns, name); + const Node** found = shd_dict_find_value(String, const Node*, ctx->fns, name); if (found) return *found; @@ -103,7 +103,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo break; } Node* new_fn = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); - insert_dict(String, const Node*, ctx->fns, name, new_fn); + shd_dict_insert(String, const Node*, ctx->fns, name, new_fn); size_t max_tag = sizeof(generic_ptr_tags) / sizeof(generic_ptr_tags[0]); switch (which) { @@ -279,12 +279,12 @@ Module* lower_generic_ptrs(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .fns = new_dict(String, const Node*, (HashFn) hash_string, (CmpFn) compare_string), + .fns = shd_new_dict(String, const Node*, (HashFn) hash_string, (CmpFn) compare_string), .generic_ptr_type = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false}), .config = config, }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.fns); + shd_destroy_dict(ctx.fns); return dst; } diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 3774363ed..9e4814cf7 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -15,7 +15,7 @@ typedef struct { static const Node* make_nullptr(Context* ctx, const Type* t) { IrArena* a = ctx->rewriter.dst_arena; - const Node** found = find_value_dict(const Type*, const Node*, ctx->map, t); + const Node** found = shd_dict_find_value(const Type*, const Node*, ctx->map, t); if (found) return *found; @@ -26,7 +26,7 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { })), t, format_string_interned(a, "nullptr_%s", name_type_safe(a, t))); decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(nul)); const Node* ref = ref_decl_helper(a, decl); - insert_dict(const Type*, const Node*, ctx->map, t, ref); + shd_dict_insert(const Type*, const Node*, ctx->map, t, ref); return ref; } @@ -54,10 +54,10 @@ Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.map); + shd_destroy_dict(ctx.map); return dst; } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 56155145b..3dd5d6cc2 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -254,7 +254,7 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un else cache = ser ? ctx->serialisation_varying[as] : ctx->deserialisation_varying[as]; - const Node** found = find_value_dict(const Node*, const Node*, cache, element_type); + const Node** found = shd_dict_find_value(const Node*, const Node*, cache, element_type); if (found) return *found; @@ -272,7 +272,7 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un String name = format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", get_address_space_name(as), uniform_address ? "uniform" : "varying", name_type_safe(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); - insert_dict(const Node*, Node*, cache, element_type, fun); + shd_dict_insert(const Node*, Node*, cache, element_type, fun); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); const Node* base = *get_emulated_as_word_array(ctx, as); @@ -503,10 +503,10 @@ Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { for (size_t i = 0; i < NumAddressSpaces; i++) { if (is_as_emulated(&ctx, i)) { - ctx.serialisation_varying[i] = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); - ctx.deserialisation_varying[i] = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); - ctx.serialisation_uniform[i] = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); - ctx.deserialisation_uniform[i] = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + ctx.serialisation_varying[i] = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + ctx.deserialisation_varying[i] = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + ctx.serialisation_uniform[i] = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + ctx.deserialisation_uniform[i] = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); } } @@ -515,10 +515,10 @@ Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { for (size_t i = 0; i < NumAddressSpaces; i++) { if (is_as_emulated(&ctx, i)) { - destroy_dict(ctx.serialisation_varying[i]); - destroy_dict(ctx.deserialisation_varying[i]); - destroy_dict(ctx.serialisation_uniform[i]); - destroy_dict(ctx.deserialisation_uniform[i]); + shd_destroy_dict(ctx.serialisation_varying[i]); + shd_destroy_dict(ctx.deserialisation_varying[i]); + shd_destroy_dict(ctx.serialisation_uniform[i]); + shd_destroy_dict(ctx.deserialisation_uniform[i]); } } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 4834f115d..7dddc4112 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -30,7 +30,7 @@ typedef struct Context_ { static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { struct Dict* cache = push ? ctx->push : ctx->pop; - const Node** found = find_value_dict(const Node*, const Node*, cache, element_type); + const Node** found = shd_dict_find_value(const Node*, const Node*, cache, element_type); if (found) return *found; @@ -42,7 +42,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { Nodes return_ts = push ? empty(a) : singleton(qualified_t); String name = format_string_arena(a->arena, "generated_%s_%s", push ? "push" : "pop", name_type_safe(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); - insert_dict(const Node*, Node*, cache, element_type, fun); + shd_dict_insert(const Node*, Node*, cache, element_type, fun); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); @@ -184,8 +184,8 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { .config = config, - .push = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), - .pop = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .push = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .pop = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), }; if (config->per_thread_stack_size > 0) { @@ -212,7 +212,7 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.push); - destroy_dict(ctx.pop); + shd_destroy_dict(ctx.push); + shd_destroy_dict(ctx.pop); return dst; } diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 3ccf7c1e1..8646278b3 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -113,14 +113,14 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod error("TODO") Node* fn = NULL; - Node** found = find_value_dict(const Node*, Node*, ctx->fns, t); + Node** found = shd_dict_find_value(const Node*, Node*, ctx->fns, t); if (found) fn = *found; else { const Node* src_param = param(a, qualified_type_helper(t, false), "src"); fn = function(m, singleton(src_param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), mk_nodes(a, annotation(a, (Annotation) { .name = "Generated"}), annotation(a, (Annotation) { .name = "Leaf" })), singleton(qualified_type_helper(t, true))); - insert_dict(const Node*, Node*, ctx->fns, t, fn); + shd_dict_insert(const Node*, Node*, ctx->fns, t, fn); build_fn_body(ctx, fn, scope, src_param, t); } @@ -155,10 +155,10 @@ Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, - .fns = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node) + .fns = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node) }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.fns); + shd_destroy_dict(ctx.fns); return dst; } diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 3ebd8b8a7..3f6a52299 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -22,15 +22,15 @@ static const Node* process(Context* ctx, const Node* node) { Node* newfun = recreate_decl_header_identity(r, node); if (get_abstraction_body(node)) { Context functx = *ctx; - functx.rewriter.map = clone_dict(functx.rewriter.map); - clear_dict(functx.rewriter.map); + functx.rewriter.map = shd_clone_dict(functx.rewriter.map); + shd_dict_clear(functx.rewriter.map); register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, empty(a), "post-prelude"); register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); - destroy_dict(functx.rewriter.map); + shd_destroy_dict(functx.rewriter.map); } return newfun; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 0d36679eb..2069e9ad9 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -54,11 +54,11 @@ static FnPtr get_fn_ptr(Context* ctx, const Node* the_function) { assert(the_function->arena == ctx->rewriter.src_arena); assert(the_function->tag == Function_TAG); - FnPtr* found = find_value_dict(const Node*, FnPtr, ctx->assigned_fn_ptrs, the_function); + FnPtr* found = shd_dict_find_value(const Node*, FnPtr, ctx->assigned_fn_ptrs, the_function); if (found) return *found; FnPtr ptr = (*ctx->next_fn_ptr)++; - bool r = insert_dict_and_get_result(const Node*, FnPtr, ctx->assigned_fn_ptrs, the_function, ptr); + bool r = shd_dict_insert_get_result(const Node*, FnPtr, ctx->assigned_fn_ptrs, the_function, ptr); assert(r); return ptr; } @@ -442,7 +442,7 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) IrArena* a = new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); - struct Dict* ptrs = new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); + struct Dict* ptrs = shd_new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); Node* init_fn = function(dst, nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), nodes(a, 0, NULL)); set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = empty(a), .mem = get_abstraction_mem(init_fn) })); @@ -468,7 +468,7 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) if (*ctx.top_dispatcher_fn) generate_top_level_dispatch_fn(&ctx); - destroy_dict(ptrs); + shd_destroy_dict(ptrs); destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index eb917d6ed..10c89d999 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -27,7 +27,7 @@ typedef struct { } FnInfo; static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { - FnInfo* info = find_value_dict(const Node*, FnInfo, ctx->fns, fn_node->fn); + FnInfo* info = shd_dict_find_value(const Node*, FnInfo, ctx->fns, fn_node->fn); if (info) { // if we encounter a function before 'done' is set, it must be part of a recursive chain if (!info->done) { @@ -41,8 +41,8 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { .node = fn_node, .done = false, }; - insert_dict(const Node*, FnInfo, ctx->fns, fn_node->fn, initial_info); - info = find_value_dict(const Node*, FnInfo, ctx->fns, fn_node->fn); + shd_dict_insert(const Node*, FnInfo, ctx->fns, fn_node->fn, initial_info); + info = shd_dict_find_value(const Node*, FnInfo, ctx->fns, fn_node->fn); assert(info); if (fn_node->is_address_captured || fn_node->is_recursive || fn_node->calls_indirect) { @@ -72,7 +72,7 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { size_t iter = 0; CGEdge e; - while (dict_iter(fn_node->callees, &iter, &e, NULL)) { + while (shd_dict_iter(fn_node->callees, &iter, &e, NULL)) { if (!is_leaf_fn(ctx, e.dst_fn)) { debugv_print("Function %s can't be a leaf function because its callee %s is not a leaf function.\n", get_abstraction_name(fn_node->fn), get_abstraction_name(e.dst_fn->fn)); info->is_leaf = false; @@ -81,7 +81,7 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { } // by analysing the callees, the dict might have been regrown so we must refetch this to update the ptr if needed - info = find_value_dict(const Node*, FnInfo, ctx->fns, fn_node->fn); + info = shd_dict_find_value(const Node*, FnInfo, ctx->fns, fn_node->fn); if (!info->done) { info->is_leaf = true; @@ -96,7 +96,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Function_TAG: { Context fn_ctx = *ctx; - CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, node); + CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, node); fn_ctx.is_leaf = is_leaf_fn(ctx, fn_node); fn_ctx.cfg = build_fn_cfg(node); fn_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); @@ -157,11 +157,11 @@ Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* s Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .fns = new_dict(const Node*, FnInfo, (HashFn) hash_node, (CmpFn) compare_node), + .fns = shd_new_dict(const Node*, FnInfo, (HashFn) hash_node, (CmpFn) compare_node), .graph = new_callgraph(src) }; rewrite_module(&ctx.rewriter); - destroy_dict(ctx.fns); + shd_destroy_dict(ctx.fns); destroy_callgraph(ctx.graph); destroy_rewriter(&ctx.rewriter); return dst; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 9f4e61163..6988f7b11 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -110,7 +110,7 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { switch (instr->tag) { case StackAlloc_TAG: case LocalAlloc_TAG: { - k.src_alloca = *find_value_dict(const Node*, AllocaInfo*, ctx->alloca_info, instr); + k.src_alloca = *shd_dict_find_value(const Node*, AllocaInfo*, ctx->alloca_info, instr); return k; } case PrimOp_TAG: { @@ -144,7 +144,7 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t *k = (AllocaInfo) { .type = rewrite_node(r, old_type) }; assert(ctx->uses); visit_ptr_uses(old, old_type, k, ctx->uses); - insert_dict(const Node*, AllocaInfo*, ctx->alloca_info, old, k); + shd_dict_insert(const Node*, AllocaInfo*, ctx->alloca_info, old, k); // debugv_print("demote_alloca: uses analysis results for "); // log_node(DEBUGV, old); // debugv_print(": leaks=%d read_from=%d non_logical_use=%d\n", k->leaks, k->read_from, k->non_logical_use); @@ -243,12 +243,12 @@ bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .arena = shd_new_arena(), - .alloca_info = new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), + .alloca_info = shd_new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), .todo = &todo }; rewrite_module(&ctx.rewriter); destroy_rewriter(&ctx.rewriter); - destroy_dict(ctx.alloca_info); + shd_destroy_dict(ctx.alloca_info); shd_destroy_arena(ctx.arena); *m = dst; return todo; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 9bea6bf69..4305e6411 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -64,7 +64,7 @@ static FnInliningCriteria get_inlining_heuristic(const CompilerConfig* config, C CGEdge e; size_t i = 0; - while (dict_iter(fn_node->callers, &i, &e, NULL)) { + while (shd_dict_iter(fn_node->callers, &i, &e, NULL)) { crit.num_calls++; if (is_call_potentially_inlineable(e.src_fn->fn, e.dst_fn->fn)) crit.num_inlineable_calls++; @@ -108,7 +108,7 @@ static const Node* inline_call(Context* ctx, const Node* ocallee, const Node* nm log_string(DEBUG, "Inlining '%s' inside '%s'\n", get_abstraction_name(ocallee), get_abstraction_name(ctx->fun)); Context inline_context = *ctx; - inline_context.rewriter.map = clone_dict(inline_context.rewriter.map); + inline_context.rewriter.map = shd_clone_dict(inline_context.rewriter.map); ctx = &inline_context; InlinedCall inlined_call = { @@ -123,7 +123,7 @@ static const Node* inline_call(Context* ctx, const Node* ocallee, const Node* nm const Node* nbody = rewrite_node(&inline_context.rewriter, get_abstraction_body(ocallee)); - destroy_dict(inline_context.rewriter.map); + shd_destroy_dict(inline_context.rewriter.map); assert(is_terminator(nbody)); return nbody; @@ -138,7 +138,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Function_TAG: { if (ctx->graph) { - CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, node); + CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, node); if (get_inlining_heuristic(ctx->config, fn_node).can_be_eliminated) { debugv_print("Eliminating %s because it has exactly one caller\n", get_abstraction_name(fn_node->fn)); return NULL; @@ -150,14 +150,14 @@ static const Node* process(Context* ctx, const Node* node) { register_processed(r, node, new); Context fn_ctx = *ctx; - fn_ctx.rewriter.map = clone_dict(fn_ctx.rewriter.map); + fn_ctx.rewriter.map = shd_clone_dict(fn_ctx.rewriter.map); fn_ctx.old_fun = node; fn_ctx.fun = new; fn_ctx.inlined_call = NULL; for (size_t i = 0; i < new->payload.fun.params.count; i++) register_processed(&fn_ctx.rewriter, node->payload.fun.params.nodes[i], new->payload.fun.params.nodes[i]); recreate_decl_body_identity(&fn_ctx.rewriter, node, new); - destroy_dict(fn_ctx.rewriter.map); + shd_destroy_dict(fn_ctx.rewriter.map); return new; } case Call_TAG: { @@ -168,7 +168,7 @@ static const Node* process(Context* ctx, const Node* node) { ocallee = ignore_immediate_fn_addr(ocallee); if (ocallee->tag == Function_TAG) { - CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); + CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined && is_call_potentially_inlineable(ctx->old_fun, ocallee)) { debugv_print("Inlining call to %s\n", get_abstraction_name(ocallee)); Nodes nargs = rewrite_nodes(&ctx->rewriter, payload.args); @@ -208,7 +208,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* ocallee = node->payload.tail_call.callee; ocallee = ignore_immediate_fn_addr(ocallee); if (ocallee->tag == Function_TAG) { - CGNode* fn_node = *find_value_dict(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); + CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined) { debugv_print("Inlining tail call to %s\n", get_abstraction_name(ocallee)); Nodes nargs = rewrite_nodes(&ctx->rewriter, node->payload.tail_call.args); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 1665e0416..211b3b218 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -45,7 +45,7 @@ typedef struct { static TmpAllocCleanupClosure create_delete_dict_closure(struct Dict* d) { return (TmpAllocCleanupClosure) { - .fn = (TmpAllocCleanupFn) destroy_dict, + .fn = (TmpAllocCleanupFn) shd_destroy_dict, .payload = d, }; } @@ -137,7 +137,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, BodyBuilder* bb = begin_body_with_mem(a, mem); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); - struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); + struct Dict* tmp_processed = shd_clone_dict(ctx->rewriter.map); TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; @@ -157,7 +157,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, set_abstraction_body(structured_target, structured); // forget we rewrote all that - destroy_dict(tmp_processed); + shd_destroy_dict(tmp_processed); shd_list_pop_impl(ctx->cleanup_stack); shd_list_pop_impl(ctx->cleanup_stack); @@ -361,7 +361,7 @@ static const Node* process(Context* ctx, const Node* node) { gen_store(bb, ptr, int32_literal(a, 0)); ctx2.level_ptr = ptr; ctx2.fn = new; - struct Dict* tmp_processed = clone_dict(ctx->rewriter.map); + struct Dict* tmp_processed = shd_clone_dict(ctx->rewriter.map); TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; @@ -371,7 +371,7 @@ static const Node* process(Context* ctx, const Node* node) { // We made it! Pop off the pending cleanup stuff and do it ourselves. shd_list_pop_impl(ctx->cleanup_stack); shd_list_pop_impl(ctx->cleanup_stack); - destroy_dict(tmp_processed); + shd_destroy_dict(tmp_processed); } //if (is_leaf) diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 552ad1259..02f9be75b 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -61,8 +61,8 @@ static void gather_exiting_nodes(LoopTree* lt, const CFNode* entry, const CFNode static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, struct Dict* free_set, struct List* leaking) { const Node* v; size_t i = 0; - while (dict_iter(free_set, &i, &v, NULL)) { - if (find_key_dict(const Node*, bound_set, v)) + while (shd_dict_iter(free_set, &i, &v, NULL)) { + if (shd_dict_find_key(const Node*, bound_set, v)) continue; log_string(DEBUGVV, "Found variable used outside it's control scope: "); @@ -182,13 +182,13 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; cached_exits[i] = search_processed(rewriter, exiting_node->node); if (cached_exits[i]) - remove_dict(const Node*, rewriter->map, exiting_node->node); + shd_dict_remove(const Node*, rewriter->map, exiting_node->node); register_processed(rewriter, exiting_node->node, exits[i].wrapper); } // ditto for the loop entry and the continue wrapper const Node** cached_entry = search_processed(rewriter, node); if (cached_entry) - remove_dict(const Node*, rewriter->map, node); + shd_dict_remove(const Node*, rewriter->map, node); register_processed(rewriter, node, continue_wrapper); // make sure we haven't started rewriting this... @@ -197,7 +197,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { // } struct Dict* old_map = rewriter->map; - rewriter->map = clone_dict(rewriter->map); + rewriter->map = shd_clone_dict(rewriter->map); Nodes inner_loop_params = recreate_params(rewriter, get_abstraction_params(node)); register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); Node* inner_control_case = case_(arena, singleton(join_token_continue)); @@ -222,17 +222,17 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { set_abstraction_body(inner_control_case, loop_body); - destroy_dict(rewriter->map); + shd_destroy_dict(rewriter->map); rewriter->map = old_map; //register_processed_list(rewriter, get_abstraction_params(node), nparams); // restore the old context for (size_t i = 0; i < exiting_nodes_count; i++) { - remove_dict(const Node*, rewriter->map, shd_read_list(CFNode *, exiting_nodes)[i]->node); + shd_dict_remove(const Node*, rewriter->map, shd_read_list(CFNode *, exiting_nodes)[i]->node); if (cached_exits[i]) register_processed(rewriter, shd_read_list(CFNode*, exiting_nodes)[i]->node, *cached_exits[i]); } - remove_dict(const Node*, rewriter->map, node); + shd_dict_remove(const Node*, rewriter->map, node); if (cached_entry) register_processed(rewriter, node, *cached_entry); @@ -440,7 +440,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node** cached = search_processed(r, post_dominator); if (cached) - remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); + shd_dict_remove(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); for (size_t i = 0; i < old_params.count; i++) { assert(!search_processed(r, old_params.nodes[i])); } @@ -456,7 +456,7 @@ static const Node* process_node(Context* ctx, const Node* node) { }); set_abstraction_body(control_case, inner_terminator); - remove_dict(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); + shd_dict_remove(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); if (cached) register_processed(r, post_dominator, *cached); diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index f90013ee4..9eadc1cd7 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -62,15 +62,15 @@ static Nodes remake_params(Context* ctx, Nodes old) { } static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { - Controls** found = find_value_dict(const Node, Controls*, ctx->controls, fn_or_bb); + Controls** found = shd_dict_find_value(const Node, Controls*, ctx->controls, fn_or_bb); if (found) return *found; IrArena* a = ctx->rewriter.dst_arena; Controls* controls = shd_arena_alloc(ctx->arena, sizeof(Controls)); *controls = (Controls) { - .control_destinations = new_dict(const Node*, AddControl, (HashFn) hash_node, (CmpFn) compare_node), + .control_destinations = shd_new_dict(const Node*, AddControl, (HashFn) hash_node, (CmpFn) compare_node), }; - insert_dict(const Node*, Controls*, ctx->controls, fn_or_bb, controls); + shd_dict_insert(const Node*, Controls*, ctx->controls, fn_or_bb, controls); return controls; } @@ -111,7 +111,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab size_t i = 0; AddControl add_control; - while(dict_iter(controls->control_destinations, &i, NULL, &add_control)) { + while(shd_dict_iter(controls->control_destinations, &i, NULL, &add_control)) { const Node* dst = add_control.destination; Node* control_case = case_(a, singleton(add_control.token)); set_abstraction_body(control_case, jump_helper(a, c, empty(a), get_abstraction_mem(control_case))); @@ -213,7 +213,7 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); Controls* controls = get_or_create_controls(ctx, dom->node); - AddControl* found = find_value_dict(const Node, AddControl, controls->control_destinations, dst); + AddControl* found = shd_dict_find_value(const Node, AddControl, controls->control_destinations, dst); Wrapped wrapped; if (found) { wrapped.wrapper = found->wrapper; @@ -240,10 +240,10 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed .wrapper = wrapper, }; wrapped.wrapper = wrapper; - insert_dict(const Node*, AddControl, controls->control_destinations, dst, add_control); + shd_dict_insert(const Node*, AddControl, controls->control_destinations, dst, add_control); } - insert_dict(const Node*, Wrapped, ctx->jump2wrapper, edge.jump, wrapped); + shd_dict_insert(const Node*, Wrapped, ctx->jump2wrapper, edge.jump, wrapped); // return jump_helper(a, wrapper, rewrite_nodes(&ctx->rewriter, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); } else { dom = dom->idom; @@ -288,7 +288,7 @@ static const Node* process_node(Context* ctx, const Node* node) { break; } case Jump_TAG: { - Wrapped* found = find_value_dict(const Node*, Wrapped, ctx->jump2wrapper, node); + Wrapped* found = shd_dict_find_value(const Node*, Wrapped, ctx->jump2wrapper, node); if (found) return jump_helper(a, found->wrapper, rewrite_nodes(r, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); break; @@ -308,8 +308,8 @@ Module* scope2control(const CompilerConfig* config, Module* src) { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .arena = shd_new_arena(), - .controls = new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), - .jump2wrapper = new_dict(const Node*, Wrapped, (HashFn) hash_node, (CmpFn) compare_node), + .controls = shd_new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), + .jump2wrapper = shd_new_dict(const Node*, Wrapped, (HashFn) hash_node, (CmpFn) compare_node), }; ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; @@ -318,17 +318,17 @@ Module* scope2control(const CompilerConfig* config, Module* src) { size_t i = 0; Controls* controls; - while (dict_iter(ctx.controls, &i, NULL, &controls)) { + while (shd_dict_iter(ctx.controls, &i, NULL, &controls)) { //size_t j = 0; //AddControl add_control; // while (dict_iter(controls.control_destinations, &j, NULL, &add_control)) { // destroy_list(add_control.lift); // } - destroy_dict(controls->control_destinations); + shd_destroy_dict(controls->control_destinations); } - destroy_dict(ctx.controls); - destroy_dict(ctx.jump2wrapper); + shd_destroy_dict(ctx.controls); + shd_destroy_dict(ctx.jump2wrapper); shd_destroy_arena(ctx.arena); destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/print.c b/src/shady/print.c index 11002e0b0..3befa2e43 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -51,7 +51,7 @@ static PrinterCtx make_printer_ctx(Printer* printer, NodePrintConfig config) { PrinterCtx ctx = { .printer = printer, .config = config, - .emitted = new_dict(const Node*, String, (HashFn) hash_node, (CmpFn) compare_node), + .emitted = shd_new_dict(const Node*, String, (HashFn) hash_node, (CmpFn) compare_node), .root_growy = new_growy(), }; ctx.root_printer = open_growy_as_printer(ctx.root_growy); @@ -59,7 +59,7 @@ static PrinterCtx make_printer_ctx(Printer* printer, NodePrintConfig config) { } static void destroy_printer_ctx(PrinterCtx ctx) { - destroy_dict(ctx.emitted); + shd_destroy_dict(ctx.emitted); } void print_module(Printer* printer, NodePrintConfig config, Module* mod) { @@ -1017,7 +1017,7 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { return "?"; } - String* found = find_value_dict(const Node*, String, ctx->emitted, node); + String* found = shd_dict_find_value(const Node*, String, ctx->emitted, node); if (found) return *found; @@ -1032,7 +1032,7 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { } else { r = format_string_interned(node->arena, "%%%d", node->id); } - insert_dict(const Node*, String, ctx->emitted, node, r); + shd_dict_insert(const Node*, String, ctx->emitted, node, r); Growy* g = new_growy(); PrinterCtx ctx2 = *ctx; @@ -1052,7 +1052,7 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { if (print_inline) { String is = string(node->arena, s); - insert_dict(const Node*, String, ctx->emitted, node, is); + shd_dict_insert(const Node*, String, ctx->emitted, node, is); free((void*) s); return is; } else { diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index e1266ef82..11e129076 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -23,9 +23,9 @@ Rewriter create_rewriter_base(Module* src, Module* dst) { .search_map = true, .write_map = true, }, - .map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), .own_decls = true, - .decls_map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .decls_map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), .parent = NULL, }; } @@ -45,9 +45,9 @@ Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn) { void destroy_rewriter(Rewriter* r) { assert(r->map); - destroy_dict(r->map); + shd_destroy_dict(r->map); if (r->own_decls) - destroy_dict(r->decls_map); + shd_destroy_dict(r->decls_map); } Rewriter create_importer(Module* src, Module* dst) { @@ -56,7 +56,7 @@ Rewriter create_importer(Module* src, Module* dst) { Rewriter create_children_rewriter(Rewriter* parent) { Rewriter r = *parent; - r.map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + r.map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); r.parent = parent; r.own_decls = false; return r; @@ -64,7 +64,7 @@ Rewriter create_children_rewriter(Rewriter* parent) { Rewriter create_decl_rewriter(Rewriter* parent) { Rewriter r = *parent; - r.map = new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + r.map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); r.own_decls = false; return r; } @@ -168,13 +168,13 @@ static Nodes rewrite_ops_helper(Rewriter* rewriter, NodeClass class, String op_n static const Node** search_processed_(const Rewriter* ctx, const Node* old, bool deep) { if (is_declaration(old)) { - const Node** found = find_value_dict(const Node*, const Node*, ctx->decls_map, old); + const Node** found = shd_dict_find_value(const Node*, const Node*, ctx->decls_map, old); return found ? found : NULL; } while (ctx) { assert(ctx->map && "this rewriter has no processed cache"); - const Node** found = find_value_dict(const Node*, const Node*, ctx->map, old); + const Node** found = shd_dict_find_value(const Node*, const Node*, ctx->map, old); if (found) return found; if (deep) @@ -222,7 +222,7 @@ void register_processed(Rewriter* ctx, const Node* old, const Node* new) { #endif struct Dict* map = is_declaration(old) ? ctx->decls_map : ctx->map; assert(map && "this rewriter has no processed cache"); - bool r = insert_dict_and_get_result(const Node*, const Node*, map, old, new); + bool r = shd_dict_insert_get_result(const Node*, const Node*, map, old, new); assert(r); } @@ -370,7 +370,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { void dump_rewriter_map(Rewriter* r) { size_t i = 0; const Node* src, *dst; - while (dict_iter(r->map, &i, &src, &dst)) { + while (shd_dict_iter(r->map, &i, &src, &dst)) { log_node(ERROR, src); log_string(ERROR, " -> "); log_node(ERROR, dst); diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 5f915676e..2154f3cc0 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -13,7 +13,7 @@ #define STRINGIFY(x) STRINGIFY2(x) #define VCC_CLANG STRINGIFY(VCC_CLANG_EXECUTABLE_NAME) -uint32_t hash_murmur(const void* data, size_t size); +uint32_t shd_hash_murmur(const void* data, size_t size); void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { int argc = *pargc; @@ -98,7 +98,7 @@ void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* inpu uint32_t hash = 0; for (size_t i = 0; i < num_source_files; i++) { String filename = input_filenames[i]; - hash ^= hash_murmur(filename, strlen(filename)); + hash ^= shd_hash_murmur(filename, strlen(filename)); } srand(hash); for (size_t i = 0; i < 32; i++) { From 1119e51e15f073306e145b9c66178dae3169bff8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 15:21:24 +0200 Subject: [PATCH 595/693] add shd_ prefix to util.h and log.h --- samples/aobench/ao_main.c | 2 +- src/backend/c/emit_c.c | 60 ++++---- src/backend/c/emit_c_control_flow.c | 2 +- src/backend/c/emit_c_type.c | 48 +++---- src/backend/c/emit_c_value.c | 144 ++++++++++---------- src/backend/spirv/emit_spv.c | 8 +- src/backend/spirv/emit_spv_type.c | 2 +- src/backend/spirv/spirv_builder.c | 78 +++++------ src/common/growy.c | 22 +-- src/common/growy.h | 20 +-- src/common/log.h | 4 +- src/common/printer.c | 18 +-- src/common/printer.h | 2 +- src/common/util.c | 26 ++-- src/common/util.h | 18 +-- src/driver/cli.c | 8 +- src/driver/driver.c | 10 +- src/frontend/llvm/generator_l2s.c | 28 ++-- src/frontend/llvm/l2s.c | 2 +- src/frontend/llvm/l2s_annotations.c | 2 +- src/frontend/llvm/l2s_instr.c | 24 ++-- src/frontend/llvm/l2s_meta.c | 2 +- src/frontend/llvm/l2s_private.h | 4 +- src/frontend/llvm/l2s_type.c | 2 +- src/frontend/llvm/l2s_value.c | 2 +- src/frontend/slim/parser.c | 4 +- src/frontend/spirv/s2s.c | 6 +- src/runtime/vulkan/vk_runtime_buffer.c | 2 +- src/runtime/vulkan/vk_runtime_program.c | 22 +-- src/shady/analysis/cfg.c | 6 +- src/shady/analysis/cfg_dump.c | 6 +- src/shady/analysis/verify.c | 4 +- src/shady/api/generator_grammar.c | 60 ++++---- src/shady/api/generator_primops.c | 10 +- src/shady/api/generator_type.c | 6 +- src/shady/generator/generator.c | 8 +- src/shady/generator/generator_common.c | 69 +++++----- src/shady/generator/generator_main.c | 14 +- src/shady/generator/import_spv_defs.c | 24 ++-- src/shady/generator_constructors.c | 56 ++++---- src/shady/generator_node.c | 120 ++++++++-------- src/shady/generator_primops.c | 14 +- src/shady/generator_print.c | 42 +++--- src/shady/generator_rewrite.c | 46 +++---- src/shady/generator_type.c | 16 +-- src/shady/generator_visit.c | 24 ++-- src/shady/ir.c | 14 +- src/shady/node.c | 2 +- src/shady/passes/import.c | 4 +- src/shady/passes/lcssa.c | 2 +- src/shady/passes/lower_alloca.c | 4 +- src/shady/passes/lower_cf_instrs.c | 6 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 8 +- src/shady/passes/lower_stack.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/opt_inline.c | 2 +- src/shady/passes/reconvergence_heuristics.c | 6 +- src/shady/passes/scope2control.c | 2 +- src/shady/passes/setup_stack_frames.c | 2 +- src/shady/print.c | 20 +-- src/shady/rewrite.c | 2 +- src/shady/transform/ir_gen_helpers.c | 2 +- src/shady/type.c | 10 +- vcc/vcc.c | 2 +- vcc/vcc_lib.c | 40 +++--- 68 files changed, 617 insertions(+), 618 deletions(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 1c4279756..143a121a5 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -165,7 +165,7 @@ int main(int argc, char **argv) { do_all = false; } else { error_print("Unrecognised argument: %s\n", argv[i]); - error_die(); + shd_error_die(); } } diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 6ad49c4a6..01192fc7a 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -52,13 +52,13 @@ CValue to_cvalue(SHADY_UNUSED Emitter* e, CTerm term) { if (term.value) return term.value; if (term.var) - return format_string_arena(e->arena->arena, "(&%s)", term.var); + return shd_format_string_arena(e->arena->arena, "(&%s)", term.var); assert(false); } CAddr deref_term(Emitter* e, CTerm term) { if (term.value) - return format_string_arena(e->arena->arena, "(*%s)", term.value); + return shd_format_string_arena(e->arena->arena, "(*%s)", term.value); if (term.var) return term.var; assert(false); @@ -125,11 +125,11 @@ void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const // add extra qualifiers if immutable if (!mut) switch (emitter->config.dialect) { case CDialect_ISPC: - center = format_string_arena(emitter->arena->arena, "const %s", center); + center = shd_format_string_arena(emitter->arena->arena, "const %s", center); break; case CDialect_C11: case CDialect_CUDA: - center = format_string_arena(emitter->arena->arena, "const %s", center); + center = shd_format_string_arena(emitter->arena->arena, "const %s", center); break; case CDialect_GLSL: if (emitter->config.glsl_version >= 130) @@ -166,7 +166,7 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String if (as != AsGeneric) warn_print_once(c11_non_generic_as, "warning: standard C does not have address spaces\n"); prefix = ""; if (constant) - name = format_string_arena(emitter->arena->arena, "const %s", name); + name = shd_format_string_arena(emitter->arena->arena, "const %s", name); break; } case CDialect_ISPC: @@ -179,7 +179,7 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String assert(false); // Note: this requires many hacks. prefix = "__device__ "; - name = format_string_arena(emitter->arena->arena, "__shady_private_globals.%s", name); + name = shd_format_string_arena(emitter->arena->arena, "__shady_private_globals.%s", name); break; case AsShared: prefix = "__shared__ "; break; case AsGlobal: { @@ -190,7 +190,7 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String break; } default: { - prefix = format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); + prefix = shd_format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); warn_print("warning: address space %s not supported in CUDA for global variables\n", get_address_space_name(as)); break; } @@ -210,7 +210,7 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String break; } default: { - prefix = format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); + prefix = shd_format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); warn_print("warning: address space %s not supported in GLSL for global variables\n", get_address_space_name(as)); break; } @@ -224,9 +224,9 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String if (emitter->config.dialect == CDialect_ISPC) { bool uniform = is_addr_space_uniform(emitter->arena, as); if (uniform) - name = format_string_arena(emitter->arena->arena, "uniform %s", name); + name = shd_format_string_arena(emitter->arena->arena, "uniform %s", name); else - name = format_string_arena(emitter->arena->arena, "varying %s", name); + name = shd_format_string_arena(emitter->arena->arena, "varying %s", name); } if (init) @@ -284,7 +284,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { emit_as = term_from_cvar(name); if ((decl->payload.global_variable.address_space == AsPrivate) && emitter->config.dialect == CDialect_CUDA) { if (emitter->use_private_globals) { - register_emitted(emitter, NULL, decl, term_from_cvar(format_string_arena(emitter->arena->arena, "__shady_private_globals->%s", name))); + register_emitted(emitter, NULL, decl, term_from_cvar(shd_format_string_arena(emitter->arena->arena, "__shady_private_globals->%s", name))); // HACK return; } @@ -325,15 +325,15 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { if (emitter->config.dialect == CDialect_ISPC) { // ISPC hack: This compiler (like seemingly all LLVM-based compilers) has broken handling of the execution mask - it fails to generated masked stores for the entry BB of a function that may be called non-uniformingly // therefore we must tell ISPC to please, pretty please, mask everything by branching on what the mask should be - fn_body = format_string_arena(emitter->arena->arena, "if ((lanemask() >> programIndex) & 1u) { %s}", fn_body); + fn_body = shd_format_string_arena(emitter->arena->arena, "if ((lanemask() >> programIndex) & 1u) { %s}", fn_body); // I hate everything about this too. } else if (emitter->config.dialect == CDialect_CUDA) { if (lookup_annotation(decl, "EntryPoint")) { // fn_body = format_string_arena(emitter->arena->arena, "\n__shady_entry_point_init();%s", fn_body); if (emitter->use_private_globals) { - fn_body = format_string_arena(emitter->arena->arena, "\n__shady_PrivateGlobals __shady_private_globals_alloc;\n __shady_PrivateGlobals* __shady_private_globals = &__shady_private_globals_alloc;\n%s", fn_body); + fn_body = shd_format_string_arena(emitter->arena->arena, "\n__shady_PrivateGlobals __shady_private_globals_alloc;\n __shady_PrivateGlobals* __shady_private_globals = &__shady_private_globals_alloc;\n%s", fn_body); } - fn_body = format_string_arena(emitter->arena->arena, "\n__shady_prepare_builtins();%s", fn_body); + fn_body = shd_format_string_arena(emitter->arena->arena, "\n__shady_prepare_builtins();%s", fn_body); } } print(emitter->fn_defs, "\n%s { ", head); @@ -365,7 +365,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { switch (emitter->config.dialect) { case CDialect_ISPC: default: print(emitter->type_decls, "\ntypedef %s;", c_emit_type(emitter, decl->payload.nom_type.body, emitted)); break; - case CDialect_GLSL: c_emit_nominal_type_body(emitter, format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; + case CDialect_GLSL: c_emit_nominal_type_body(emitter, shd_format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; } return; } @@ -389,7 +389,7 @@ static Module* run_backend_specific_passes(const CompilerConfig* config, CEmitte } static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* p = open_growy_as_printer(g); print(p, "typedef struct __shady_PrivateGlobals {\n"); @@ -409,7 +409,7 @@ static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { if (count == 0) { destroy_printer(p); - destroy_growy(g); + shd_destroy_growy(g); return NULL; } return printer_growy_unwrap(p); @@ -426,9 +426,9 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module mod = run_backend_specific_passes(compiler_config, &config, mod); IrArena* arena = get_module_arena(mod); - Growy* type_decls_g = new_growy(); - Growy* fn_decls_g = new_growy(); - Growy* fn_defs_g = new_growy(); + Growy* type_decls_g = shd_new_growy(); + Growy* fn_decls_g = shd_new_growy(); + Growy* fn_defs_g = shd_new_growy(); Emitter emitter = { .compiler_config = compiler_config, @@ -468,7 +468,7 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module destroy_printer(emitter.fn_decls); destroy_printer(emitter.fn_defs); - Growy* final = new_growy(); + Growy* final = shd_new_growy(); Printer* finalp = open_growy_as_printer(final); if (emitter.config.dialect == CDialect_GLSL) { @@ -508,28 +508,28 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module } print(finalp, "\n/* types: */\n"); - growy_append_bytes(final, growy_size(type_decls_g), growy_data(type_decls_g)); + shd_growy_append_bytes(final, shd_growy_size(type_decls_g), shd_growy_data(type_decls_g)); print(finalp, "\n/* declarations: */\n"); - growy_append_bytes(final, growy_size(fn_decls_g), growy_data(fn_decls_g)); + shd_growy_append_bytes(final, shd_growy_size(fn_decls_g), shd_growy_data(fn_decls_g)); print(finalp, "\n/* definitions: */\n"); - growy_append_bytes(final, growy_size(fn_defs_g), growy_data(fn_defs_g)); + shd_growy_append_bytes(final, shd_growy_size(fn_defs_g), shd_growy_data(fn_defs_g)); print(finalp, "\n"); print(finalp, "\n"); print(finalp, "\n"); - growy_append_bytes(final, 1, "\0"); + shd_growy_append_bytes(final, 1, "\0"); - destroy_growy(type_decls_g); - destroy_growy(fn_decls_g); - destroy_growy(fn_defs_g); + shd_destroy_growy(type_decls_g); + shd_destroy_growy(fn_decls_g); + shd_destroy_growy(fn_defs_g); shd_destroy_dict(emitter.emitted_types); shd_destroy_dict(emitter.emitted_terms); - *output_size = growy_size(final) - 1; - *output = growy_deconstruct(final); + *output_size = shd_growy_size(final) - 1; + *output = shd_growy_deconstruct(final); destroy_printer(finalp); if (new_mod) diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index d0229ae23..71d442df9 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -15,7 +15,7 @@ String c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { const Node* body = get_abstraction_body(abs); assert(body && is_terminator(body)); CFNode* cf_node = cfg_lookup(fn->cfg, abs); - Printer* p = open_growy_as_printer(new_growy()); + Printer* p = open_growy_as_printer(shd_new_growy()); fn->instruction_printers[cf_node->rpo_index] = p; //indent(p); diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index 1cd54f864..dc347e411 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -25,7 +25,7 @@ String c_get_record_field_name(const Type* t, size_t i) { void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { assert(type->tag == RecordType_TAG); - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* p = open_growy_as_printer(g); print(p, "\n%s {", name); @@ -36,10 +36,10 @@ void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { } deindent(p); print(p, "\n};\n"); - growy_append_bytes(g, 1, (char[]) { '\0' }); + shd_growy_append_bytes(g, 1, (char[]) { '\0' }); - print(emitter->type_decls, growy_data(g)); - destroy_growy(g); + print(emitter->type_decls, shd_growy_data(g)); + shd_destroy_growy(g); destroy_printer(p); } @@ -50,7 +50,7 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons const Node* entry_point = fn ? lookup_annotation(fn, "EntryPoint") : NULL; - Growy* paramg = new_growy(); + Growy* paramg = shd_new_growy(); Printer* paramp = open_growy_as_printer(paramg); Nodes dom = fn_type->payload.fn_type.param_types; if (dom.count == 0 && emitter->config.dialect == CDialect_C11) @@ -85,16 +85,16 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons } } } - growy_append_bytes(paramg, 1, (char[]) { 0 }); + shd_growy_append_bytes(paramg, 1, (char[]) { 0 }); const char* parameters = printer_growy_unwrap(paramp); switch (emitter->config.dialect) { default: - center = format_string_arena(emitter->arena->arena, "(%s)(%s)", center, parameters); + center = shd_format_string_arena(emitter->arena->arena, "(%s)(%s)", center, parameters); break; case CDialect_GLSL: // GLSL does not accept functions declared like void (foo)(int); // it also does not support higher-order functions and/or function pointers, so we drop the parentheses - center = format_string_arena(emitter->arena->arena, "%s(%s)", center, parameters); + center = shd_format_string_arena(emitter->arena->arena, "%s(%s)", center, parameters); break; } free_tmp_str(parameters); @@ -107,14 +107,14 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons case CDialect_GLSL: break; case CDialect_ISPC: - c_decl = format_string_arena(emitter->arena->arena, "export %s", c_decl); + c_decl = shd_format_string_arena(emitter->arena->arena, "export %s", c_decl); break; case CDialect_CUDA: - c_decl = format_string_arena(emitter->arena->arena, "extern \"C\" __global__ %s", c_decl); + c_decl = shd_format_string_arena(emitter->arena->arena, "extern \"C\" __global__ %s", c_decl); break; } } else if (emitter->config.dialect == CDialect_CUDA) { - c_decl = format_string_arena(emitter->arena->arena, "__device__ %s", c_decl); + c_decl = shd_format_string_arena(emitter->arena->arena, "__device__ %s", c_decl); } return c_decl; @@ -215,7 +215,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { //} emitted = unique_name(emitter->arena, "Record"); - String prefixed = format_string_arena(emitter->arena->arena, "struct %s", emitted); + String prefixed = shd_format_string_arena(emitter->arena->arena, "struct %s", emitted); c_emit_nominal_type_body(emitter, prefixed, type); // C puts structs in their own namespace so we always need the prefix if (emitter->config.dialect == CDialect_C11) @@ -233,15 +233,15 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { return c_emit_type(emitter, type->payload.qualified_type.type, center); case CDialect_ISPC: if (type->payload.qualified_type.is_uniform) - return c_emit_type(emitter, type->payload.qualified_type.type, format_string_arena(emitter->arena->arena, "uniform %s", center)); + return c_emit_type(emitter, type->payload.qualified_type.type, shd_format_string_arena(emitter->arena->arena, "uniform %s", center)); else - return c_emit_type(emitter, type->payload.qualified_type.type, format_string_arena(emitter->arena->arena, "varying %s", center)); + return c_emit_type(emitter, type->payload.qualified_type.type, shd_format_string_arena(emitter->arena->arena, "varying %s", center)); } case Type_PtrType_TAG: { - CType t = c_emit_type(emitter, type->payload.ptr_type.pointed_type, format_string_arena(emitter->arena->arena, "* %s", center)); + CType t = c_emit_type(emitter, type->payload.ptr_type.pointed_type, shd_format_string_arena(emitter->arena->arena, "* %s", center)); // we always emit pointers to _uniform_ data, no exceptions if (emitter->config.dialect == CDialect_ISPC) - t = format_string_arena(emitter->arena->arena, "uniform %s", t); + t = shd_format_string_arena(emitter->arena->arena, "uniform %s", t); return t; } case Type_FnType_TAG: { @@ -249,8 +249,8 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { } case Type_ArrType_TAG: { emitted = unique_name(emitter->arena, "Array"); - String prefixed = format_string_arena(emitter->arena->arena, "struct %s", emitted); - Growy* g = new_growy(); + String prefixed = shd_format_string_arena(emitter->arena->arena, "struct %s", emitted); + Growy* g = shd_new_growy(); Printer* p = open_growy_as_printer(g); const Node* size = type->payload.arr_type.size; @@ -261,13 +261,13 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { indent(p); String inner_decl_rhs; if (size) - inner_decl_rhs = format_string_arena(emitter->arena->arena, "arr[%zu]", get_int_literal_value(*resolve_to_int_literal(size), false)); + inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[%zu]", get_int_literal_value(*resolve_to_int_literal(size), false)); else - inner_decl_rhs = format_string_arena(emitter->arena->arena, "arr[0]"); + inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[0]"); print(p, "\n%s;", c_emit_type(emitter, type->payload.arr_type.element_type, inner_decl_rhs)); deindent(p); print(p, "\n};\n"); - growy_append_bytes(g, 1, (char[]) { '\0' }); + shd_growy_append_bytes(g, 1, (char[]) { '\0' }); String subdecl = printer_growy_unwrap(p); print(emitter->type_decls, subdecl); @@ -298,13 +298,13 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { case Float_TAG: base = "vec"; break; default: error("not a valid GLSL vector type"); } - emitted = format_string_arena(emitter->arena->arena, "%s%d", base, width); + emitted = shd_format_string_arena(emitter->arena->arena, "%s%d", base, width); break; } case CDialect_ISPC: error("Please lower to something else") case CDialect_C11: { emitted = c_emit_type(emitter, element_type, NULL); - emitted = format_string_arena(emitter->arena->arena, "__attribute__ ((vector_size (%d * sizeof(%s) ))) %s", width, emitted, emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "__attribute__ ((vector_size (%d * sizeof(%s) ))) %s", width, emitted, emitted); break; } } @@ -323,7 +323,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { assert(emitted != NULL); if (strlen(center) > 0) - emitted = format_string_arena(emitter->arena->arena, "%s %s", emitted, center); + emitted = shd_format_string_arena(emitter->arena->arena, "%s %s", emitted, center); return emitted; } diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index e4bf99290..ead9a0935 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -51,7 +51,7 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e if (i + 1 < c.count) print(p, ", "); } - growy_append_bytes(g, 1, "\0"); + shd_growy_append_bytes(g, 1, "\0"); return ObjectsList; } } @@ -73,17 +73,17 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No } case Value_IntLiteral_TAG: { if (value->payload.int_literal.is_signed) - emitted = format_string_arena(emitter->arena->arena, "%" PRIi64, value->payload.int_literal.value); + emitted = shd_format_string_arena(emitter->arena->arena, "%" PRIi64, value->payload.int_literal.value); else - emitted = format_string_arena(emitter->arena->arena, "%" PRIu64, value->payload.int_literal.value); + emitted = shd_format_string_arena(emitter->arena->arena, "%" PRIu64, value->payload.int_literal.value); bool is_long = value->payload.int_literal.width == IntTy64; bool is_signed = value->payload.int_literal.is_signed; if (emitter->config.dialect == CDialect_GLSL && emitter->config.glsl_version >= 130) { if (!is_signed) - emitted = format_string_arena(emitter->arena->arena, "%sU", emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "%sU", emitted); if (is_long) - emitted = format_string_arena(emitter->arena->arena, "%sL", emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "%sL", emitted); } break; @@ -97,12 +97,12 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No float f; memcpy(&f, &v, sizeof(uint32_t)); double d = (double) f; - emitted = format_string_arena(emitter->arena->arena, "%#.9gf", d); break; + emitted = shd_format_string_arena(emitter->arena->arena, "%#.9gf", d); break; } case FloatTy64: { double d; memcpy(&d, &v, sizeof(uint64_t)); - emitted = format_string_arena(emitter->arena->arena, "%.17g", d); break; + emitted = shd_format_string_arena(emitter->arena->arena, "%.17g", d); break; } } break; @@ -123,20 +123,20 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No const Type* type = value->payload.composite.type; Nodes elements = value->payload.composite.contents; - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* p2 = p; Printer* p = open_growy_as_printer(g); if (type->tag == ArrType_TAG) { switch (array_insides_helper(emitter, fn, p, g, type, elements)) { case ObjectsList: - emitted = growy_data(g); + emitted = shd_growy_data(g); break; case StringLit: - emitted = format_string_arena(emitter->arena->arena, "\"%s\"", growy_data(g)); + emitted = shd_format_string_arena(emitter->arena->arena, "\"%s\"", shd_growy_data(g)); break; case CharsLit: - emitted = format_string_arena(emitter->arena->arena, "'%s'", growy_data(g)); + emitted = shd_format_string_arena(emitter->arena->arena, "'%s'", shd_growy_data(g)); break; } } else { @@ -145,16 +145,16 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No if (i + 1 < elements.count) print(p, ", "); } - emitted = growy_data(g); + emitted = shd_growy_data(g); } - growy_append_bytes(g, 1, "\0"); + shd_growy_append_bytes(g, 1, "\0"); switch (emitter->config.dialect) { no_compound_literals: case CDialect_ISPC: { // arrays need double the brackets if (type->tag == ArrType_TAG) - emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "{ %s }", emitted); if (p2) { String tmp = unique_name(emitter->arena, "composite"); @@ -162,7 +162,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No emitted = tmp; } else { // this requires us to end up in the initialisation side of a declaration - emitted = format_string_arena(emitter->arena->arena, "{ %s }", emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "{ %s }", emitted); } break; } @@ -171,23 +171,23 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No // If we're C89 (ew) if (!emitter->config.allow_compound_literals) goto no_compound_literals; - emitted = format_string_arena(emitter->arena->arena, "((%s) { %s })", c_emit_type(emitter, value->type, NULL), emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "((%s) { %s })", c_emit_type(emitter, value->type, NULL), emitted); break; case CDialect_GLSL: if (type->tag != PackType_TAG) goto no_compound_literals; // GLSL doesn't have compound literals, but it does have constructor syntax for vectors - emitted = format_string_arena(emitter->arena->arena, "%s(%s)", c_emit_type(emitter, value->type, NULL), emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "%s(%s)", c_emit_type(emitter, value->type, NULL), emitted); break; } - destroy_growy(g); + shd_destroy_growy(g); destroy_printer(p); break; } case Value_Fill_TAG: error("lower me") case Value_StringLiteral_TAG: { - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* p = open_growy_as_printer(g); String str = value->payload.string_lit.string; @@ -198,19 +198,19 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No case '\n': print(p, "\\n"); break; default: - growy_append_bytes(g, 1, &c); + shd_growy_append_bytes(g, 1, &c); } } - growy_append_bytes(g, 1, "\0"); + shd_growy_append_bytes(g, 1, "\0"); - emitted = format_string_arena(emitter->arena->arena, "\"%s\"", growy_data(g)); - destroy_growy(g); + emitted = shd_format_string_arena(emitter->arena->arena, "\"%s\"", shd_growy_data(g)); + shd_destroy_growy(g); destroy_printer(p); break; } case Value_FnAddr_TAG: { emitted = c_legalize_identifier(emitter, get_declaration_name(value->payload.fn_addr.fn)); - emitted = format_string_arena(emitter->arena->arena, "(&%s)", emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "(&%s)", emitted); break; } case Value_RefDecl_TAG: { @@ -369,12 +369,12 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, FnEmitter* fn, Printe case OsInfix: { CTerm a = c_emit_value(emitter, fn, operands.nodes[0]); CTerm b = c_emit_value(emitter, fn, operands.nodes[1]); - *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s %s %s", to_cvalue(emitter, a), operator_str, to_cvalue(emitter, b))); + *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s %s %s", to_cvalue(emitter, a), operator_str, to_cvalue(emitter, b))); break; } case OsPrefix: { CTerm operand = c_emit_value(emitter, fn, operands.nodes[0]); - *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s%s", operator_str, to_cvalue(emitter, operand))); + *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s%s", operator_str, to_cvalue(emitter, operand))); break; } case OsCall: { @@ -382,18 +382,18 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, FnEmitter* fn, Printe for (size_t i = 0; i < operands.count; i++) cops[i] = c_emit_value(emitter, fn, operands.nodes[i]); if (operands.count == 1) - *out = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", operator_str, to_cvalue(emitter, cops[0]))); + *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", operator_str, to_cvalue(emitter, cops[0]))); else { - Growy* g = new_growy(); - growy_append_string(g, operator_str); - growy_append_string_literal(g, "("); + Growy* g = shd_new_growy(); + shd_growy_append_string(g, operator_str); + shd_growy_append_string_literal(g, "("); for (size_t i = 0; i < operands.count; i++) { - growy_append_string(g, to_cvalue(emitter, cops[i])); + shd_growy_append_string(g, to_cvalue(emitter, cops[i])); if (i + 1 < operands.count) - growy_append_string_literal(g, ", "); + shd_growy_append_string_literal(g, ", "); } - growy_append_string_literal(g, ")"); - *out = term_from_cvalue(growy_deconstruct(g)); + shd_growy_append_string_literal(g, ")"); + *out = term_from_cvalue(shd_growy_deconstruct(g)); } break; } @@ -422,11 +422,11 @@ static const ISelTableEntry* lookup_entry(Emitter* emitter, Op op) { static String index_into_array(Emitter* emitter, const Type* arr_type, CTerm expr, CTerm index) { IrArena* arena = emitter->arena; - String index2 = emitter->config.dialect == CDialect_GLSL ? format_string_arena(arena->arena, "int(%s)", to_cvalue(emitter, index)) : to_cvalue(emitter, index); + String index2 = emitter->config.dialect == CDialect_GLSL ? shd_format_string_arena(arena->arena, "int(%s)", to_cvalue(emitter, index)) : to_cvalue(emitter, index); if (emitter->config.decay_unsized_arrays && !arr_type->payload.arr_type.size) - return format_string_arena(arena->arena, "((&%s)[%s])", deref_term(emitter, expr), index2); + return shd_format_string_arena(arena->arena, "((&%s)[%s])", deref_term(emitter, expr), index2); else - return format_string_arena(arena->arena, "(%s.arr[%s])", deref_term(emitter, expr), index2); + return shd_format_string_arena(arena->arena, "(%s.arr[%s])", deref_term(emitter, expr), index2); } static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* node) { @@ -445,30 +445,30 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case fract_op: { CTerm floored; emit_using_entry(&floored, emitter, fn, p, lookup_entry(emitter, floor_op), prim_op->operands); - term = term_from_cvalue(format_string_arena(arena->arena, "1 - %s", to_cvalue(emitter, floored))); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "1 - %s", to_cvalue(emitter, floored))); break; } case inv_sqrt_op: { CTerm floored; emit_using_entry(&floored, emitter, fn, p, lookup_entry(emitter, sqrt_op), prim_op->operands); - term = term_from_cvalue(format_string_arena(arena->arena, "1.0f / %s", to_cvalue(emitter, floored))); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "1.0f / %s", to_cvalue(emitter, floored))); break; } case min_op: { CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); - term = term_from_cvalue(format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, b, a)); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, b, a)); break; } case max_op: { CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); - term = term_from_cvalue(format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, a, b)); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, a, b)); break; } case sign_op: { CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); - term = term_from_cvalue(format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); break; } case fma_op: { @@ -478,11 +478,11 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node switch (emitter->config.dialect) { case CDialect_C11: case CDialect_CUDA: { - term = term_from_cvalue(format_string_arena(arena->arena, "fmaf(%s, %s, %s)", a, b, c)); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "fmaf(%s, %s, %s)", a, b, c)); break; } default: { - term = term_from_cvalue(format_string_arena(arena->arena, "(%s * %s) + %s", a, b, c)); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s * %s) + %s", a, b, c)); break; } } @@ -496,16 +496,16 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node CValue c_offset = to_cvalue(emitter, c_emit_value(emitter, fn, offset)); if (emitter->config.dialect == CDialect_GLSL) { if (get_unqualified_type(offset->type)->payload.int_type.width == IntTy64) - c_offset = format_string_arena(arena->arena, "int(%s)", c_offset); + c_offset = shd_format_string_arena(arena->arena, "int(%s)", c_offset); } - term = term_from_cvalue(format_string_arena(arena->arena, "(%s %s %s)", src, prim_op->op == lshift_op ? "<<" : ">>", c_offset)); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s %s %s)", src, prim_op->op == lshift_op ? "<<" : ">>", c_offset)); break; } case size_of_op: - term = term_from_cvalue(format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); break; case align_of_op: - term = term_from_cvalue(format_string_arena(emitter->arena->arena, "alignof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "alignof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); break; case offset_of_op: { const Type* t = first(prim_op->type_arguments); @@ -515,14 +515,14 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node const Node* index = first(prim_op->operands); uint64_t index_literal = get_int_literal_value(*resolve_to_int_literal(index), false); String member_name = c_get_record_field_name(t, index_literal); - term = term_from_cvalue(format_string_arena(emitter->arena->arena, "offsetof(%s, %s)", c_emit_type(emitter, t, NULL), member_name)); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "offsetof(%s, %s)", c_emit_type(emitter, t, NULL), member_name)); break; } case select_op: { assert(prim_op->operands.count == 3); CValue condition = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[0])); CValue l = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); CValue r = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[2])); - term = term_from_cvalue(format_string_arena(emitter->arena->arena, "(%s) ? (%s) : (%s)", condition, l, r)); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "(%s) ? (%s) : (%s)", condition, l, r)); break; } case convert_op: { @@ -532,12 +532,12 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node if (emitter->config.dialect == CDialect_GLSL) { if (is_glsl_scalar_type(src_type) && is_glsl_scalar_type(dst_type)) { CType t = c_emit_type(emitter, dst_type, NULL); - term = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", t, to_cvalue(emitter, src))); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", t, to_cvalue(emitter, src))); } else assert(false); } else { CType t = c_emit_type(emitter, dst_type, NULL); - term = term_from_cvalue(format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src))); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src))); } break; } @@ -579,14 +579,14 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } } if (conv_fn) { - return term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, to_cvalue(emitter, src_value))); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, to_cvalue(emitter, src_value))); } error_print("glsl: unsupported bit cast from "); log_node(ERROR, src_type); error_print(" to "); log_node(ERROR, dst_type); error_print(".\n"); - error_die(); + shd_error_die(); } case CDialect_ISPC: { if (dst_type->tag == Float_TAG) { @@ -600,14 +600,14 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case FloatTy64: n = "doublebits"; break; } - return term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); } else if (src_type->tag == Float_TAG) { assert(dst_type->tag == Int_TAG); - return term_from_cvalue(format_string_arena(emitter->arena->arena, "intbits(%s)", to_cvalue(emitter, src_value))); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "intbits(%s)", to_cvalue(emitter, src_value))); } CType t = c_emit_type(emitter, dst_type, NULL); - return term_from_cvalue(format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src_value))); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src_value))); } } SHADY_UNREACHABLE; @@ -641,16 +641,16 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node assert(static_index); Strings names = t->payload.record_type.names; if (names.count == 0) - acc = format_string_arena(emitter->arena->arena, "(%s._%d)", acc, static_index->value); + acc = shd_format_string_arena(emitter->arena->arena, "(%s._%d)", acc, static_index->value); else - acc = format_string_arena(emitter->arena->arena, "(%s.%s)", acc, names.strings[static_index->value]); + acc = shd_format_string_arena(emitter->arena->arena, "(%s.%s)", acc, names.strings[static_index->value]); break; } case Type_PackType_TAG: { assert(static_index); assert(static_index->value < 4 && static_index->value < t->payload.pack_type.width); String suffixes = "xyzw"; - acc = format_string_arena(emitter->arena->arena, "(%s.%c)", acc, suffixes[static_index->value]); + acc = shd_format_string_arena(emitter->arena->arena, "(%s.%c)", acc, suffixes[static_index->value]); break; } case Type_ArrType_TAG: { @@ -721,8 +721,8 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E case SpvOpGroupNonUniformBroadcastFirst: { CValue value = to_cvalue(emitter, c_emit_value(emitter, fn, first(instr.operands))); switch (emitter->config.dialect) { - case CDialect_CUDA: return term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; - case CDialect_ISPC: return term_from_cvalue(format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; + case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; + case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; case CDialect_C11: case CDialect_GLSL: error("TODO") } @@ -733,8 +733,8 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E const IntLiteral* scope = resolve_to_int_literal(first(instr.operands)); assert(scope && scope->value == SpvScopeSubgroup); switch (emitter->config.dialect) { - case CDialect_CUDA: return term_from_cvalue(format_string_arena(emitter->arena->arena, "__shady_elect_first()")); - case CDialect_ISPC: return term_from_cvalue(format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); + case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_elect_first()")); + case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); case CDialect_C11: case CDialect_GLSL: error("TODO") } @@ -759,7 +759,7 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* else assert(false); - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* paramsp = open_growy_as_printer(g); if (emitter->use_private_globals) { print(paramsp, "__shady_private_globals"); @@ -781,7 +781,7 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* String params = printer_growy_unwrap(paramsp); - CTerm called = term_from_cvalue(format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); + CTerm called = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); called = c_bind_intermediary_result(emitter, p, call->type, called); free_tmp_str(params); @@ -828,7 +828,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a record need to be constant"); size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); String field_name = c_get_record_field_name(pointee_type, static_index); - acc = term_from_cvar(format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); + acc = term_from_cvar(shd_format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.record_type.members.nodes[static_index], .address_space = curr_ptr_type->payload.ptr_type.address_space @@ -838,7 +838,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer case Type_PackType_TAG: { size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); String suffixes = "xyzw"; - acc = term_from_cvar(format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); + acc = term_from_cvar(shd_format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.pack_type.element_type, .address_space = curr_ptr_type->payload.ptr_type.address_space @@ -870,7 +870,7 @@ static CTerm emit_ptr_array_element_offset(Emitter* emitter, FnEmitter* fn, Prin // this means such code is never going to be legal in GLSL // also the cast is to account for our arrays-in-structs hack const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); - acc = term_from_cvalue(format_string_arena(arena->arena, "((%s) &(%s)[%s])", c_emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); + acc = term_from_cvalue(shd_format_string_arena(arena->arena, "((%s) &(%s)[%s])", c_emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); uniform &= is_qualified_type_uniform(lea.offset->type); } @@ -934,7 +934,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const CValue cvalue = to_cvalue(emitter, c_emit_value(emitter, fn, payload.value)); // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this if (emitter->config.dialect == CDialect_ISPC && addr_uniform && is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) - cvalue = format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); + cvalue = shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); print(p, "\n%s = %s;", dereferenced, cvalue); return empty_term(); @@ -959,9 +959,9 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const CValue str = to_cvalue(emitter, c_emit_value(emitter, fn, instruction->payload.debug_printf.args.nodes[i])); if (emitter->config.dialect == CDialect_ISPC && i > 0) - str = format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); + str = shd_format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); - args_list = format_string_arena(emitter->arena->arena, "%s, %s", args_list, str); + args_list = shd_format_string_arena(emitter->arena->arena, "%s, %s", args_list, str); } switch (emitter->config.dialect) { case CDialect_ISPC: diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 25f2609d6..577135269 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -132,11 +132,11 @@ static void emit_function(Emitter* emitter, const Node* node) { spvb_define_function(emitter->file_builder, fn_builder.base); } else { - Growy* g = new_growy(); + Growy* g = shd_new_growy(); spvb_literal_name(g, get_abstraction_name(node)); - growy_append_bytes(g, 4, (char*) &(uint32_t) { SpvLinkageTypeImport }); - spvb_decorate(emitter->file_builder, fn_id, SpvDecorationLinkageAttributes, growy_size(g) / 4, (uint32_t*) growy_data(g)); - destroy_growy(g); + shd_growy_append_bytes(g, 4, (char*) &(uint32_t) { SpvLinkageTypeImport }); + spvb_decorate(emitter->file_builder, fn_id, SpvDecorationLinkageAttributes, shd_growy_size(g) / 4, (uint32_t*) shd_growy_data(g)); + shd_destroy_growy(g); spvb_declare_function(emitter->file_builder, fn_builder.base); } diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index fdb63fe80..6460b6245 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -33,7 +33,7 @@ SpvStorageClass spv_emit_addr_space(Emitter* emitter, AddressSpace address_space default: { error_print("Cannot emit address space %s.\n", get_address_space_name(address_space)); - error_die(); + shd_error_die(); SHADY_UNREACHABLE; } } diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index 7b8a2a42d..ece6388d4 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -20,7 +20,7 @@ inline static int div_roundup(int a, int b) { } inline static void output_word(SpvbSectionBuilder data, uint32_t word) { - growy_append_bytes(data, sizeof(uint32_t), (char*) &word); + shd_growy_append_bytes(data, sizeof(uint32_t), (char*) &word); } #define op(opcode, size) op_(target_data, opcode, size) @@ -61,7 +61,7 @@ inline static void literal_int_(SpvbSectionBuilder data, uint32_t i) { #define copy_section(section) copy_section_(target_data, section) inline static void copy_section_(SpvbSectionBuilder target, SpvbSectionBuilder source) { - growy_append_bytes(target, growy_size(source), growy_data(source)); + shd_growy_append_bytes(target, shd_growy_size(source), shd_growy_data(source)); } struct SpvbFileBuilder_ { @@ -103,18 +103,18 @@ SpvbFileBuilder* spvb_begin() { SpvbFileBuilder* file_builder = (SpvbFileBuilder*) malloc(sizeof(SpvbFileBuilder)); *file_builder = (SpvbFileBuilder) { .bound = 1, - .capabilities = new_growy(), - .extensions = new_growy(), - .ext_inst_import = new_growy(), - .entry_points = new_growy(), - .execution_modes = new_growy(), - .debug_string_source = new_growy(), - .debug_names = new_growy(), - .debug_module_processed = new_growy(), - .annotations = new_growy(), - .types_constants = new_growy(), - .fn_decls = new_growy(), - .fn_defs = new_growy(), + .capabilities = shd_new_growy(), + .extensions = shd_new_growy(), + .ext_inst_import = shd_new_growy(), + .entry_points = shd_new_growy(), + .execution_modes = shd_new_growy(), + .debug_string_source = shd_new_growy(), + .debug_names = shd_new_growy(), + .debug_module_processed = shd_new_growy(), + .annotations = shd_new_growy(), + .types_constants = shd_new_growy(), + .fn_decls = shd_new_growy(), + .fn_defs = shd_new_growy(), .capabilities_set = shd_new_set(SpvCapability, (HashFn) hash_u32, (CmpFn) compare_u32s), .extensions_set = shd_new_set(const char*, (HashFn) hash_string, (CmpFn) compare_string), @@ -175,30 +175,30 @@ static uint32_t byteswap(uint32_t v) { } size_t spvb_finish(SpvbFileBuilder* file_builder, char** output) { - Growy* g = new_growy(); + Growy* g = shd_new_growy(); merge_sections(file_builder, g); - destroy_growy(file_builder->fn_defs); - destroy_growy(file_builder->fn_decls); - destroy_growy(file_builder->types_constants); - destroy_growy(file_builder->annotations); - destroy_growy(file_builder->debug_module_processed); - destroy_growy(file_builder->debug_names); - destroy_growy(file_builder->debug_string_source); - destroy_growy(file_builder->execution_modes); - destroy_growy(file_builder->entry_points); - destroy_growy(file_builder->ext_inst_import); - destroy_growy(file_builder->extensions); - destroy_growy(file_builder->capabilities); + shd_destroy_growy(file_builder->fn_defs); + shd_destroy_growy(file_builder->fn_decls); + shd_destroy_growy(file_builder->types_constants); + shd_destroy_growy(file_builder->annotations); + shd_destroy_growy(file_builder->debug_module_processed); + shd_destroy_growy(file_builder->debug_names); + shd_destroy_growy(file_builder->debug_string_source); + shd_destroy_growy(file_builder->execution_modes); + shd_destroy_growy(file_builder->entry_points); + shd_destroy_growy(file_builder->ext_inst_import); + shd_destroy_growy(file_builder->extensions); + shd_destroy_growy(file_builder->capabilities); shd_destroy_dict(file_builder->capabilities_set); shd_destroy_dict(file_builder->extensions_set); free(file_builder); - size_t s = growy_size(g); + size_t s = shd_growy_size(g); assert(s % 4 == 0); - *output = growy_deconstruct(g); + *output = shd_growy_deconstruct(g); if (is_big_endian()) for (size_t i = 0; i < s / 4; i++) { ((uint32_t*)*output)[i] = byteswap(((uint32_t*)(*output))[i]); @@ -509,8 +509,8 @@ SpvbFnBuilder* spvb_begin_fn(SpvbFileBuilder* file_builder, SpvId fn_id, SpvId f .fn_ret_type = fn_ret_type, .file_builder = file_builder, .bbs = shd_new_list(SpvbBasicBlockBuilder*), - .variables = new_growy(), - .header = new_growy(), + .variables = shd_new_growy(), + .header = shd_new_growy(), }; return fnb; } @@ -556,8 +556,8 @@ void spvb_declare_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_buil op(SpvOpFunctionEnd, 1); shd_destroy_list(fn_builder->bbs); - destroy_growy(fn_builder->header); - destroy_growy(fn_builder->variables); + shd_destroy_growy(fn_builder->header); + shd_destroy_growy(fn_builder->variables); free(fn_builder); } #undef target_data @@ -626,16 +626,16 @@ void spvb_define_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_build copy_section(bb->terminator_section); shd_destroy_list(bb->phis); - destroy_growy(bb->instructions_section); - destroy_growy(bb->terminator_section); + shd_destroy_growy(bb->instructions_section); + shd_destroy_growy(bb->terminator_section); free(bb); } op(SpvOpFunctionEnd, 1); shd_destroy_list(fn_builder->bbs); - destroy_growy(fn_builder->header); - destroy_growy(fn_builder->variables); + shd_destroy_growy(fn_builder->header); + shd_destroy_growy(fn_builder->variables); free(fn_builder); } #undef target_data @@ -646,8 +646,8 @@ SpvbBasicBlockBuilder* spvb_begin_bb(SpvbFnBuilder* fn_builder, SpvId label) { .fn_builder = fn_builder, .label = label, .phis = shd_new_list(SpvbPhi*), - .instructions_section = new_growy(), - .terminator_section = new_growy(), + .instructions_section = shd_new_growy(), + .terminator_section = shd_new_growy(), }; return bbb; } diff --git a/src/common/growy.c b/src/common/growy.c index 9cc43b39c..8efe2178b 100644 --- a/src/common/growy.c +++ b/src/common/growy.c @@ -11,7 +11,7 @@ struct Growy_ { size_t used, size; }; -Growy* new_growy() { +Growy* shd_new_growy() { Growy* g = calloc(1, sizeof(Growy)); *g = (Growy) { .buffer = calloc(1, init_size), @@ -21,7 +21,7 @@ Growy* new_growy() { return g; } -void growy_append_bytes(Growy* g, size_t s, const char* bytes) { +void shd_growy_append_bytes(Growy* g, size_t s, const char* bytes) { size_t old_used = g->used; g->used += s; while (g->used >= g->size) { @@ -31,30 +31,30 @@ void growy_append_bytes(Growy* g, size_t s, const char* bytes) { memcpy(g->buffer + old_used, bytes, s); } -void growy_append_string(Growy* g, const char* str) { +void shd_growy_append_string(Growy* g, const char* str) { size_t len = strlen(str); - growy_append_bytes(g, len, str); + shd_growy_append_bytes(g, len, str); } -void format_string_internal(const char* str, va_list args, void* uptr, void callback(void*, size_t, char*)); +void shd_format_string_internal(const char* str, va_list args, void* uptr, void callback(void*, size_t, char*)); -void growy_append_formatted(Growy* g, const char* str, ...) { +void shd_growy_append_formatted(Growy* g, const char* str, ...) { va_list args; va_start(args, str); - format_string_internal(str, args, g, (void(*)(void*, size_t, char*)) growy_append_bytes); + shd_format_string_internal(str, args, g, (void (*)(void*, size_t, char*)) shd_growy_append_bytes); va_end(args); } -void destroy_growy(Growy* g) { +void shd_destroy_growy(Growy* g) { free(g->buffer); free(g); } -char* growy_deconstruct(Growy* g) { +char* shd_growy_deconstruct(Growy* g) { char* buf = g->buffer; free(g); return buf; } -size_t growy_size(const Growy* g) { return g->used; } -char* growy_data(const Growy* g) { return g->buffer; } +size_t shd_growy_size(const Growy* g) { return g->used; } +char* shd_growy_data(const Growy* g) { return g->buffer; } diff --git a/src/common/growy.h b/src/common/growy.h index e35b6a199..43b7fc37e 100644 --- a/src/common/growy.h +++ b/src/common/growy.h @@ -7,16 +7,16 @@ /// Addresses not guaranteed to be stable. typedef struct Growy_ Growy; -Growy* new_growy(); -void growy_append_bytes(Growy*, size_t, const char*); -void growy_append_string(Growy*, const char*); -void growy_append_formatted(Growy* g, const char* str, ...); -#define growy_append_string_literal(a, v) growy_append_bytes(a, sizeof(v) - 1, (char*) &v) -#define growy_append_object(a, v) growy_append_bytes(a, sizeof(v), (char*) &v) -size_t growy_size(const Growy*); -char* growy_data(const Growy*); -void destroy_growy(Growy*g); +Growy* shd_new_growy(); +void shd_growy_append_bytes(Growy*, size_t, const char*); +void shd_growy_append_string(Growy* g, const char* str); +void shd_growy_append_formatted(Growy* g, const char* str, ...); +#define shd_growy_append_string_literal(a, v) shd_growy_append_bytes(a, sizeof(v) - 1, (char*) &v) +#define shd_growy_append_object(a, v) shd_growy_append_bytes(a, sizeof(v), (char*) &v) +size_t shd_growy_size(const Growy* g); +char* shd_growy_data(const Growy* g); +void shd_destroy_growy(Growy*g); // Like destroy, but we scavenge the internal allocation for later use. -char* growy_deconstruct(Growy*); +char* shd_growy_deconstruct(Growy* g); #endif diff --git a/src/common/log.h b/src/common/log.h index d596023eb..7930aece4 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -53,10 +53,10 @@ void log_module(LogLevel level, const CompilerConfig*, Module*); fprintf (stderr, "Error at %s:%d: ", __FILE__, __LINE__); \ fprintf (stderr, __VA_ARGS__); \ fprintf (stderr, "\n"); \ - error_die(); \ + shd_error_die(); \ } #include -noreturn void error_die(); +noreturn void shd_error_die(); #endif diff --git a/src/common/printer.c b/src/common/printer.c index ffafcfbd7..2fabd0ca3 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -45,7 +45,7 @@ static void print_bare(Printer* p, size_t len, const char* str) { assert(strlen(str) >= len); switch(p->output) { case PoFile: fwrite(str, sizeof(char), len, p->file); break; - case PoGrowy: growy_append_bytes(p->growy, len, str); + case PoGrowy: shd_growy_append_bytes(p->growy, len, str); } } @@ -132,26 +132,26 @@ Printer* print(Printer* p, const char* f, ...) { const char* printer_growy_unwrap(Printer* p) { assert(p->output == PoGrowy); - growy_append_bytes(p->growy, 1, "\0"); - const char* insides = growy_deconstruct(p->growy); + shd_growy_append_bytes(p->growy, 1, "\0"); + const char* insides = shd_growy_deconstruct(p->growy); free(p); return insides; } const char* replace_string(const char* source, const char* match, const char* replace_with) { - Growy* g = new_growy(); + Growy* g = shd_new_growy(); size_t match_len = strlen(match); size_t replace_len = strlen(replace_with); const char* next_match = strstr(source, match); while (next_match != NULL) { size_t diff = next_match - source; - growy_append_bytes(g, diff, (char*) source); - growy_append_bytes(g, replace_len, (char*) replace_with); + shd_growy_append_bytes(g, diff, (char*) source); + shd_growy_append_bytes(g, replace_len, (char*) replace_with); source = next_match + match_len; next_match = strstr(source, match); } - growy_append_bytes(g, strlen(source), (char*) source); + shd_growy_append_bytes(g, strlen(source), (char*) source); char zero = '\0'; - growy_append_bytes(g, 1, &zero); - return growy_deconstruct(g); + shd_growy_append_bytes(g, 1, &zero); + return shd_growy_deconstruct(g); } diff --git a/src/common/printer.h b/src/common/printer.h index 4a6a809d8..7aee8ac5f 100644 --- a/src/common/printer.h +++ b/src/common/printer.h @@ -17,7 +17,7 @@ void deindent(Printer* p); void flush(Printer*); const char* printer_growy_unwrap(Printer* p); -Growy* new_growy(); +Growy* shd_new_growy(); #define helper_format_string(f, ...) printer_growy_unwrap(cunk_print(cunk_open_growy_as_printer(cunk_new_growy()), (f), __VA_ARGS__)) const char* replace_string(const char* source, const char* match, const char* replace_with); diff --git a/src/common/util.c b/src/common/util.c index 21c85a06a..e734ba386 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -19,7 +19,7 @@ X( 'f', '\f') \ X( 'a', '\a') \ X( 'v', '\v') \ -size_t apply_escape_codes(const char* src, size_t size, char* dst) { +size_t shd_apply_escape_codes(const char* src, size_t size, char* dst) { char p, c = '\0'; size_t j = 0; for (size_t i = 0; i < size; i++) { @@ -39,7 +39,7 @@ size_t apply_escape_codes(const char* src, size_t size, char* dst) { return j; } -size_t unapply_escape_codes(const char* src, size_t size, char* dst) { +size_t shd_unapply_escape_codes(const char* src, size_t size, char* dst) { char c = '\0'; size_t j = 0; for (size_t i = 0; i < size; i++) { @@ -74,7 +74,7 @@ static long get_file_size(FILE* f) { return fsize; } -bool read_file(const char* filename, size_t* size, char** output) { +bool shd_read_file(const char* filename, size_t* size, char** output) { FILE *f = fopen(filename, "rb"); if (f == NULL) return false; @@ -107,7 +107,7 @@ bool read_file(const char* filename, size_t* size, char** output) { return false; } -bool write_file(const char* filename, size_t size, const char* data) { +bool shd_write_file(const char* filename, size_t size, const char* data) { FILE* f = fopen(filename, "wb"); if (f == NULL) return false; @@ -130,7 +130,7 @@ enum { static char static_buffer[ThreadLocalStaticBufferSize]; -void format_string_internal(const char* str, va_list args, void* uptr, void callback(void*, size_t, char*)) { +void shd_format_string_internal(const char* str, va_list args, void* uptr, void callback(void*, size_t, char*)) { size_t buffer_size = ThreadLocalStaticBufferSize; int len; char* tmp; @@ -166,12 +166,12 @@ static void intern_in_arena(InternInArenaPayload* uptr, size_t len, char* tmp) { *uptr->result = interned; } -char* format_string_arena(Arena* arena, const char* str, ...) { +char* shd_format_string_arena(Arena* arena, const char* str, ...) { char* result = NULL; InternInArenaPayload p = { .a = arena, .result = &result }; va_list args; va_start(args, str); - format_string_internal(str, args, &p, (void(*)(void*, size_t, char*)) intern_in_arena); + shd_format_string_internal(str, args, &p, (void (*)(void*, size_t, char*)) intern_in_arena); va_end(args); return result; } @@ -185,17 +185,17 @@ static void put_in_new(PutNewPayload* uptr, size_t len, char* tmp) { *uptr->result = allocated; } -char* format_string_new(const char* str, ...) { +char* shd_format_string_new(const char* str, ...) { char* result = NULL; PutNewPayload p = { .result = &result }; va_list args; va_start(args, str); - format_string_internal(str, args, &p, (void(*)(void*, size_t, char*)) put_in_new); + shd_format_string_internal(str, args, &p, (void (*)(void*, size_t, char*)) put_in_new); va_end(args); return result; } -bool string_starts_with(const char* string, const char* prefix) { +bool shd_string_starts_with(const char* string, const char* prefix) { size_t len = strlen(string); size_t slen = strlen(prefix); if (len < slen) @@ -203,7 +203,7 @@ bool string_starts_with(const char* string, const char* prefix) { return memcmp(string, prefix, slen) == 0; } -bool string_ends_with(const char* string, const char* suffix) { +bool shd_string_ends_with(const char* string, const char* suffix) { size_t len = strlen(string); size_t slen = strlen(suffix); if (len < slen) @@ -215,7 +215,7 @@ bool string_ends_with(const char* string, const char* suffix) { return true; } -char* strip_path(const char* path) { +char* shd_strip_path(const char* path) { char separator = strchr(path, '\\') == NULL ? '/' : '\\'; char* end = strrchr(path, separator); if (!end) { @@ -233,6 +233,6 @@ char* strip_path(const char* path) { return new; } -void error_die() { +void shd_error_die() { abort(); } diff --git a/src/common/util.h b/src/common/util.h index 4842710c0..f00e0634f 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -4,18 +4,18 @@ #include #include -size_t apply_escape_codes(const char* src, size_t og_len, char* dst); -size_t unapply_escape_codes(const char* src, size_t og_len, char* dst); +size_t shd_apply_escape_codes(const char* src, size_t size, char* dst); +size_t shd_unapply_escape_codes(const char* src, size_t size, char* dst); -bool read_file(const char* filename, size_t* size, char** output); -bool write_file(const char* filename, size_t size, const char* data); +bool shd_read_file(const char* filename, size_t* size, char** output); +bool shd_write_file(const char* filename, size_t size, const char* data); typedef struct Arena_ Arena; -char* format_string_arena(Arena*, const char* str, ...); -char* format_string_new(const char* str, ...); -bool string_starts_with(const char* string, const char* prefix); -bool string_ends_with(const char* string, const char* suffix); +char* shd_format_string_arena(Arena* arena, const char* str, ...); +char* shd_format_string_new(const char* str, ...); +bool shd_string_starts_with(const char* string, const char* prefix); +bool shd_string_ends_with(const char* string, const char* suffix); -char* strip_path(const char*); +char* shd_strip_path(const char*); #endif diff --git a/src/driver/cli.c b/src/driver/cli.c index 606d6f40f..21d9fa823 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -12,13 +12,13 @@ #include "util.h" CodegenTarget guess_target(const char* filename) { - if (string_ends_with(filename, ".c")) + if (shd_string_ends_with(filename, ".c")) return TgtC; - else if (string_ends_with(filename, "glsl")) + else if (shd_string_ends_with(filename, "glsl")) return TgtGLSL; - else if (string_ends_with(filename, "spirv") || string_ends_with(filename, "spv")) + else if (shd_string_ends_with(filename, "spirv") || shd_string_ends_with(filename, "spv")) return TgtSPV; - else if (string_ends_with(filename, "ispc")) + else if (shd_string_ends_with(filename, "ispc")) return TgtISPC; error_print("No target has been specified, and output filename '%s' did not allow guessing the right one\n"); exit(InvalidTarget); diff --git a/src/driver/driver.c b/src/driver/driver.c index 756b72fe4..a3572b276 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -26,13 +26,13 @@ #pragma GCC diagnostic error "-Wswitch" SourceLanguage guess_source_language(const char* filename) { - if (string_ends_with(filename, ".ll") || string_ends_with(filename, ".bc")) + if (shd_string_ends_with(filename, ".ll") || shd_string_ends_with(filename, ".bc")) return SrcLLVM; - else if (string_ends_with(filename, ".spv")) + else if (shd_string_ends_with(filename, ".spv")) return SrcSPIRV; - else if (string_ends_with(filename, ".slim")) + else if (shd_string_ends_with(filename, ".slim")) return SrcSlim; - else if (string_ends_with(filename, ".slim")) + else if (shd_string_ends_with(filename, ".slim")) return SrcShadyIR; warn_print("unknown filename extension '%s', interpreting as Slim sourcecode by default.", filename); @@ -76,7 +76,7 @@ ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* conf size_t len; char* contents; assert(filename); - bool ok = read_file(filename, &len, &contents); + bool ok = shd_read_file(filename, &len, &contents); if (!ok) { error_print("Failed to read file '%s'\n", filename); err = InputFileIOError; diff --git a/src/frontend/llvm/generator_l2s.c b/src/frontend/llvm/generator_l2s.c index c205e5cb5..f03ef5b43 100644 --- a/src/frontend/llvm/generator_l2s.c +++ b/src/frontend/llvm/generator_l2s.c @@ -1,31 +1,31 @@ #include "generator.h" void generate_llvm_shady_address_space_conversion(Growy* g, json_object* address_spaces) { - growy_append_formatted(g, "AddressSpace convert_llvm_address_space(unsigned as) {\n"); - growy_append_formatted(g, "\tstatic bool warned = false;\n"); - growy_append_formatted(g, "\tswitch (as) {\n"); + shd_growy_append_formatted(g, "AddressSpace convert_llvm_address_space(unsigned as) {\n"); + shd_growy_append_formatted(g, "\tstatic bool warned = false;\n"); + shd_growy_append_formatted(g, "\tswitch (as) {\n"); for (size_t i = 0; i < json_object_array_length(address_spaces); i++) { json_object* as = json_object_array_get_idx(address_spaces, i); String name = json_object_get_string(json_object_object_get(as, "name")); json_object* llvm_id = json_object_object_get(as, "llvm-id"); if (!llvm_id || json_object_get_type(llvm_id) != json_type_int) continue; - growy_append_formatted(g, "\t\t case %d: return As%s;\n", json_object_get_int(llvm_id), name); + shd_growy_append_formatted(g, "\t\t case %d: return As%s;\n", json_object_get_int(llvm_id), name); } - growy_append_formatted(g, "\t\tdefault:\n"); - growy_append_formatted(g, "\t\t\tif (!warned)\n"); - growy_append_string(g, "\t\t\t\twarn_print(\"Warning: unrecognised address space %d\", as);\n"); - growy_append_formatted(g, "\t\t\twarned = true;\n"); - growy_append_formatted(g, "\t\t\treturn AsGeneric;\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t\tdefault:\n"); + shd_growy_append_formatted(g, "\t\t\tif (!warned)\n"); + shd_growy_append_string(g, "\t\t\t\twarn_print(\"Warning: unrecognised address space %d\", as);\n"); + shd_growy_append_formatted(g, "\t\t\twarned = true;\n"); + shd_growy_append_formatted(g, "\t\t\treturn AsGeneric;\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n"); } void generate(Growy* g, json_object* src) { generate_header(g, src); - growy_append_formatted(g, "#include \"l2s_private.h\"\n"); - growy_append_formatted(g, "#include \"log.h\"\n"); - growy_append_formatted(g, "#include \n"); + shd_growy_append_formatted(g, "#include \"l2s_private.h\"\n"); + shd_growy_append_formatted(g, "#include \"log.h\"\n"); + shd_growy_append_formatted(g, "#include \n"); generate_llvm_shady_address_space_conversion(g, json_object_object_get(src, "address-spaces")); } diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index ae62aff0a..f60c42f37 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -293,7 +293,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* if (LLVMParseIRInContext(context, mem, &src, &parsing_diagnostic)) { error_print("Failed to parse LLVM IR\n"); error_print(parsing_diagnostic); - error_die(); + shd_error_die(); } info_print("LLVM IR parsed successfully\n"); diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index cf484ecab..13ebe999e 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -155,7 +155,7 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { }); } else { error_print("Unrecognised shady annotation '%s'\n", keyword); - error_die(); + shd_error_die(); } } else { warn_print("Ignoring annotation '%s'\n", ostr); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index e98ee0fa9..311490ef4 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -478,31 +478,31 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B // TODO return NULL; } - if (string_starts_with(intrinsic, "llvm.lifetime")) { + if (shd_string_starts_with(intrinsic, "llvm.lifetime")) { // don't care return NULL; } - if (string_starts_with(intrinsic, "llvm.experimental.noalias.scope.decl")) { + if (shd_string_starts_with(intrinsic, "llvm.experimental.noalias.scope.decl")) { // don't care return NULL; } - if (string_starts_with(intrinsic, "llvm.var.annotation")) { + if (shd_string_starts_with(intrinsic, "llvm.var.annotation")) { // don't care return NULL; } - if (string_starts_with(intrinsic, "llvm.memcpy")) { + if (shd_string_starts_with(intrinsic, "llvm.memcpy")) { Nodes ops = convert_operands(p, num_ops, instr); return bind_instruction_single(b, copy_bytes(a, (CopyBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = bb_mem(b) })); - } else if (string_starts_with(intrinsic, "llvm.memset")) { + } else if (shd_string_starts_with(intrinsic, "llvm.memset")) { Nodes ops = convert_operands(p, num_ops, instr); return bind_instruction_single(b, fill_bytes(a, (FillBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = bb_mem(b) })); - } else if (string_starts_with(intrinsic, "llvm.fmuladd")) { + } else if (shd_string_starts_with(intrinsic, "llvm.fmuladd")) { Nodes ops = convert_operands(p, num_ops, instr); return prim_op_helper(a, fma_op, empty(a), nodes(a, 3, ops.nodes)); - } else if (string_starts_with(intrinsic, "llvm.fabs")) { + } else if (shd_string_starts_with(intrinsic, "llvm.fabs")) { Nodes ops = convert_operands(p, num_ops, instr); return prim_op_helper(a, abs_op, empty(a), nodes(a, 1, ops.nodes)); - } else if (string_starts_with(intrinsic, "llvm.floor")) { + } else if (shd_string_starts_with(intrinsic, "llvm.floor")) { Nodes ops = convert_operands(p, num_ops, instr); return prim_op_helper(a, floor_op, empty(a), nodes(a, 1, ops.nodes)); } @@ -575,15 +575,15 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B } error_print("Unrecognised shady instruction '%s'\n", instructionname); - error_die(); + shd_error_die(); } else { error_print("Unrecognised shady intrinsic '%s'\n", keyword); - error_die(); + shd_error_die(); } } error_print("Unhandled intrinsic '%s'\n", intrinsic); - error_die(); + shd_error_die(); } finish: @@ -663,5 +663,5 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B error_print("Shady: unimplemented LLVM instruction "); LLVMDumpValue(instr); error_print(" (opcode=%d)\n", opcode); - error_die(); + shd_error_die(); } diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index d258efcd3..e5a2f1534 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -158,6 +158,6 @@ LLVM_DI_METADATA_NODES(N) error_print("Unknown metadata kind %d for ", kind); LLVMDumpValue(v); error_print(".\n"); - error_die(); + shd_error_die(); } } diff --git a/src/frontend/llvm/l2s_private.h b/src/frontend/llvm/l2s_private.h index 3ef8a4a2c..682ad167a 100644 --- a/src/frontend/llvm/l2s_private.h +++ b/src/frontend/llvm/l2s_private.h @@ -85,7 +85,7 @@ void postprocess(Parser*, Module* src, Module* dst); inline static String is_llvm_intrinsic(LLVMValueRef fn) { assert(LLVMIsAFunction(fn) || LLVMIsConstant(fn)); String name = LLVMGetValueName(fn); - if (string_starts_with(name, "llvm.")) + if (shd_string_starts_with(name, "llvm.")) return name; return NULL; } @@ -93,7 +93,7 @@ inline static String is_llvm_intrinsic(LLVMValueRef fn) { inline static String is_shady_intrinsic(LLVMValueRef fn) { assert(LLVMIsAFunction(fn) || LLVMIsConstant(fn)); String name = LLVMGetValueName(fn); - if (string_starts_with(name, "shady::")) + if (shd_string_starts_with(name, "shady::")) return name; return NULL; } diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index fdb96c700..c1653132e 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -140,5 +140,5 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { error_print("Unsupported type: "); LLVMDumpType(t); - error_die(); + shd_error_die(); } diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index 6c3650f66..e5f8d7c64 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -197,5 +197,5 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { error_print("Failed to find value "); LLVMDumpValue(v); error_print(" in the already emitted map (kind=%d)\n", LLVMGetValueKind(v)); - error_die(); + shd_error_die(); } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 4eace6bcd..92f8b5cd1 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -216,7 +216,7 @@ static const Node* accept_numerical_literal(ctxparams) { } if (negate) // add back the - in front - str = format_string_arena(arena->arena, "-%s", str); + str = shd_format_string_arena(arena->arena, "-%s", str); const Node* n = untyped_number(arena, (UntypedNumber) { .plaintext = str @@ -336,7 +336,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { case string_lit_tok: { next_token(tokenizer); char* unescaped = calloc(size + 1, 1); - size_t j = apply_escape_codes(&contents[tok.start], size, unescaped); + size_t j = shd_apply_escape_codes(&contents[tok.start], size, unescaped); const Node* lit = string_lit(arena, (StringLiteral) {.string = string_sized(arena, (int) j, unescaped) }); free(unescaped); return lit; diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index cf424353a..63c861d8a 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -639,7 +639,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < members_count; i++) { member_names[i] = get_member_name(parser, result, i); if (!member_names[i]) - member_names[i] = format_string_arena(parser->arena->arena, "member%d", i); + member_names[i] = shd_format_string_arena(parser->arena->arena, "member%d", i); member_tys[i] = get_def_type(parser, instruction[2 + i]); } nominal_type_decl->payload.nom_type.body = record_type(parser->arena, (RecordType) { @@ -856,7 +856,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpFunctionParameter: { parser->defs[result].type = Value; String param_name = get_name(parser, result); - param_name = param_name ? param_name : format_string_arena(parser->arena->arena, "param%d", parser->fun_arg_i); + param_name = param_name ? param_name : shd_format_string_arena(parser->arena->arena, "param%d", parser->fun_arg_i); parser->defs[result].node = param(parser->arena, qualified_type_helper(get_def_type(parser, result_t), parser->is_entry_pt), param_name); break; } @@ -1119,7 +1119,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { if (callee->tag == Function_TAG) { const Node* fn = callee; //callee->payload.fn_addr.fn; String fn_name = get_abstraction_name(fn); - if (string_starts_with(fn_name, "__shady")) { + if (shd_string_starts_with(fn_name, "__shady")) { char* copy = malloc(strlen(fn_name) + 1); memcpy(copy, fn_name, strlen(fn_name) + 1); strtok(copy, ":"); diff --git a/src/runtime/vulkan/vk_runtime_buffer.c b/src/runtime/vulkan/vk_runtime_buffer.c index dc5e5bf34..80a75a5a9 100644 --- a/src/runtime/vulkan/vk_runtime_buffer.c +++ b/src/runtime/vulkan/vk_runtime_buffer.c @@ -126,7 +126,7 @@ bool vkr_can_import_host_memory(VkrDevice* device) { VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { if (!vkr_can_import_host_memory_(device, true)) { - error_die(); + shd_error_die(); } VkrBuffer* buffer = calloc(sizeof(VkrBuffer), 1); diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 4122c69a3..83c3c742c 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -30,11 +30,11 @@ static void register_required_descriptors(VkrSpecProgram* program, VkDescriptorS static void add_binding(VkDescriptorSetLayoutCreateInfo* layout_create_info, Growy** bindings_lists, int set, VkDescriptorSetLayoutBinding binding) { if (bindings_lists[set] == NULL) { - bindings_lists[set] = new_growy(); - layout_create_info[set].pBindings = (const VkDescriptorSetLayoutBinding*) growy_data(bindings_lists[set]); + bindings_lists[set] = shd_new_growy(); + layout_create_info[set].pBindings = (const VkDescriptorSetLayoutBinding*) shd_growy_data(bindings_lists[set]); } layout_create_info[set].bindingCount += 1; - growy_append_object(bindings_lists[set], binding); + shd_growy_append_object(bindings_lists[set], binding); } VkDescriptorType as_to_descriptor_type(AddressSpace as) { @@ -88,7 +88,7 @@ static void write_value(unsigned char* tgt, const Node* value) { static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLayout layouts[]) { VkDescriptorSetLayoutCreateInfo layout_create_infos[MAX_DESCRIPTOR_SETS] = { 0 }; Growy* bindings_lists[MAX_DESCRIPTOR_SETS] = { 0 }; - Growy* resources = new_growy(); + Growy* resources = shd_new_growy(); Nodes decls = get_module_declarations(program->specialized_module); for (size_t i = 0; i < decls.count; i++) { @@ -113,7 +113,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay .set = set, .binding = binding, }; - growy_append_object(resources, res_info); + shd_growy_append_object(resources, res_info); program->resources.num_resources++; const Type* struct_t = decl->payload.global_variable.type; @@ -130,7 +130,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay .parent = res_info, .as = as, }; - growy_append_object(resources, constant_res_info); + shd_growy_append_object(resources, constant_res_info); program->resources.num_resources++; constant_res_info->size = layout.size_in_bytes; @@ -173,11 +173,11 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay layout_create_infos[set].pNext = NULL; vkCreateDescriptorSetLayout(program->device->device, &layout_create_infos[set], NULL, &layouts[set]); if (bindings_lists[set] != NULL) { - destroy_growy(bindings_lists[set]); + shd_destroy_growy(bindings_lists[set]); } } - program->resources.resources = (ProgramResourceInfo**) growy_deconstruct(resources); + program->resources.resources = (ProgramResourceInfo**) shd_growy_deconstruct(resources); return true; } @@ -393,14 +393,14 @@ static bool compile_specialized_program(VkrSpecProgram* spec) { if (spec->key.base->runtime->config.dump_spv) { String module_name = get_module_name(spec->specialized_module); - String file_name = format_string_new("%s.spv", module_name); - write_file(file_name, spec->spirv_size, (const char*) spec->spirv_bytes); + String file_name = shd_format_string_new("%s.spv", module_name); + shd_write_file(file_name, spec->spirv_size, (const char*) spec->spirv_bytes); free((void*) file_name); } String override_file = getenv("SHADY_OVERRIDE_SPV"); if (override_file) { - read_file(override_file, &spec->spirv_size, &spec->spirv_bytes); + shd_read_file(override_file, &spec->spirv_size, &spec->spirv_bytes); return true; } diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 95ad08453..f99e343c0 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -345,15 +345,15 @@ static void validate_cfg(CFG* cfg) { if (structured_body_uses > 0) { if (structured_body_uses > 1) { error_print("Basic block %s is used as a structural target more than once (structured_body_uses: %zu)", get_abstraction_name_safe(node->node), structured_body_uses); - error_die(); + shd_error_die(); } if (num_jumps > 0) { error_print("Basic block %s is used as structural target, but is also jumped into (num_jumps: %zu)", get_abstraction_name_safe(node->node), num_jumps); - error_die(); + shd_error_die(); } if (!is_tail && num_exits > 0) { error_print("Basic block %s is not a merge target yet is used as once (num_exits: %zu)", get_abstraction_name_safe(node->node), num_exits); - error_die(); + shd_error_die(); } } } diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 72b0bd713..c4030532c 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -14,7 +14,7 @@ static int extra_uniqueness = 0; static void print_node_helper(Printer* p, const Node* n) { - Growy* tmp_g = new_growy(); + Growy* tmp_g = shd_new_growy(); Printer* tmp_p = open_growy_as_printer(tmp_g); NodePrintConfig config = { @@ -26,7 +26,7 @@ static void print_node_helper(Printer* p, const Node* n) { String label = printer_growy_unwrap(tmp_p); char* escaped_label = calloc(strlen(label) * 2, 1); - unapply_escape_codes(label, strlen(label), escaped_label); + shd_unapply_escape_codes(label, strlen(label), escaped_label); print(p, "%s", escaped_label); free(escaped_label); @@ -64,7 +64,7 @@ static void dump_cf_node(FILE* output, const CFNode* n) { default: break; } - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* p = open_growy_as_printer(g); String abs_name = get_abstraction_name_safe(bb); diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 8041bf945..28d4122c7 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -62,7 +62,7 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { log_string(ERROR, "Problematic module:\n"); log_module(ERROR, config, mod); - error_die(); + shd_error_die(); } shd_destroy_dict(set); destroy_scheduler(scheduler); @@ -129,7 +129,7 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { log_string(ERROR, "was encountered before we saw it be bound by a let!\n"); log_string(ERROR, "Problematic module:\n"); log_module(ERROR, ctx->config, ctx->mod); - error_die(); + shd_error_die(); } } visit_node_operands(&ctx->visitor, NcTerminator | NcDeclaration, node); diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 0a7c4598b..472cccc6d 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -1,21 +1,21 @@ #include "generator.h" static void generate_address_spaces(Growy* g, json_object* address_spaces) { - growy_append_formatted(g, "typedef enum AddressSpace_ {\n"); + shd_growy_append_formatted(g, "typedef enum AddressSpace_ {\n"); for (size_t i = 0; i < json_object_array_length(address_spaces); i++) { json_object* as = json_object_array_get_idx(address_spaces, i); String name = json_object_get_string(json_object_object_get(as, "name")); add_comments(g, "\t", json_object_object_get(as, "description")); - growy_append_formatted(g, "\tAs%s,\n", name); + shd_growy_append_formatted(g, "\tAs%s,\n", name); } - growy_append_formatted(g, "\tNumAddressSpaces,\n"); - growy_append_formatted(g, "} AddressSpace;\n\n"); + shd_growy_append_formatted(g, "\tNumAddressSpaces,\n"); + shd_growy_append_formatted(g, "} AddressSpace;\n\n"); } static void generate_node_tags(Growy* g, json_object* nodes) { assert(json_object_get_type(nodes) == json_type_array); - growy_append_formatted(g, "typedef enum {\n"); - growy_append_formatted(g, "\tInvalidNode_TAG,\n"); + shd_growy_append_formatted(g, "typedef enum {\n"); + shd_growy_append_formatted(g, "\tInvalidNode_TAG,\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -25,9 +25,9 @@ static void generate_node_tags(Growy* g, json_object* nodes) { if (!ops) add_comments(g, "\t", json_object_object_get(node, "description")); - growy_append_formatted(g, "\t%s_TAG,\n", name); + shd_growy_append_formatted(g, "\t%s_TAG,\n", name); } - growy_append_formatted(g, "} NodeTag;\n\n"); + shd_growy_append_formatted(g, "} NodeTag;\n\n"); } static void generate_node_payloads(Growy* g, json_object* src, json_object* nodes) { @@ -41,24 +41,24 @@ static void generate_node_payloads(Growy* g, json_object* src, json_object* node if (ops) { assert(json_object_get_type(ops) == json_type_array); add_comments(g, "", json_object_object_get(node, "description")); - growy_append_formatted(g, "typedef struct SHADY_DESIGNATED_INIT {\n"); + shd_growy_append_formatted(g, "typedef struct SHADY_DESIGNATED_INIT {\n"); for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); - growy_append_formatted(g, "\t%s %s;\n", get_type_for_operand(src, op), op_name); + shd_growy_append_formatted(g, "\t%s %s;\n", get_type_for_operand(src, op), op_name); } - growy_append_formatted(g, "} %s;\n\n", name); + shd_growy_append_formatted(g, "} %s;\n\n", name); } } } static void generate_node_type(Growy* g, json_object* nodes) { - growy_append_formatted(g, "struct Node_ {\n"); - growy_append_formatted(g, "\tIrArena* arena;\n"); - growy_append_formatted(g, "\tNodeId id;\n"); - growy_append_formatted(g, "\tconst Type* type;\n"); - growy_append_formatted(g, "\tNodeTag tag;\n"); - growy_append_formatted(g, "\tunion NodesUnion {\n"); + shd_growy_append_formatted(g, "struct Node_ {\n"); + shd_growy_append_formatted(g, "\tIrArena* arena;\n"); + shd_growy_append_formatted(g, "\tNodeId id;\n"); + shd_growy_append_formatted(g, "\tconst Type* type;\n"); + shd_growy_append_formatted(g, "\tNodeTag tag;\n"); + shd_growy_append_formatted(g, "\tunion NodesUnion {\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -71,20 +71,20 @@ static void generate_node_type(Growy* g, json_object* nodes) { json_object* ops = json_object_object_get(node, "ops"); if (ops) - growy_append_formatted(g, "\t\t%s %s;\n", name, snake_name); + shd_growy_append_formatted(g, "\t\t%s %s;\n", name, snake_name); } - growy_append_formatted(g, "\t} payload;\n"); - growy_append_formatted(g, "};\n\n"); + shd_growy_append_formatted(g, "\t} payload;\n"); + shd_growy_append_formatted(g, "};\n\n"); } static void generate_node_tags_for_class(Growy* g, json_object* nodes, String class, String capitalized_class) { assert(json_object_get_type(nodes) == json_type_array); - growy_append_formatted(g, "typedef enum {\n"); + shd_growy_append_formatted(g, "typedef enum {\n"); if (starts_with_vowel(class)) - growy_append_formatted(g, "\tNotAn%s = 0,\n", capitalized_class); + shd_growy_append_formatted(g, "\tNotAn%s = 0,\n", capitalized_class); else - growy_append_formatted(g, "\tNotA%s = 0,\n", capitalized_class); + shd_growy_append_formatted(g, "\tNotA%s = 0,\n", capitalized_class); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -96,12 +96,12 @@ static void generate_node_tags_for_class(Growy* g, json_object* nodes, String cl break; case json_type_string: if (nclass && strcmp(json_object_get_string(nclass), class) == 0) - growy_append_formatted(g, "\t%s_%s_TAG = %s_TAG,\n", capitalized_class, name, name); + shd_growy_append_formatted(g, "\t%s_%s_TAG = %s_TAG,\n", capitalized_class, name, name); break; case json_type_array: { for (size_t j = 0; j < json_object_array_length(nclass); j++) { if (nclass && strcmp(json_object_get_string(json_object_array_get_idx(nclass, j)), class) == 0) { - growy_append_formatted(g, "\t%s_%s_TAG = %s_TAG,\n", capitalized_class, name, name); + shd_growy_append_formatted(g, "\t%s_%s_TAG = %s_TAG,\n", capitalized_class, name, name); break; } } @@ -115,7 +115,7 @@ static void generate_node_tags_for_class(Growy* g, json_object* nodes, String cl } } - growy_append_formatted(g, "} %sTag;\n\n", capitalized_class); + shd_growy_append_formatted(g, "} %sTag;\n\n", capitalized_class); } static void generate_header_getters_for_class(Growy* g, json_object* src, json_object* node_class) { @@ -128,7 +128,7 @@ static void generate_header_getters_for_class(Growy* g, json_object* src, json_o json_object* operand = json_object_array_get_idx(class_ops, i); String operand_name = json_object_get_string(json_object_object_get(operand, "name")); assert(operand_name); - growy_append_formatted(g, "%s get_%s_%s(const Node* node);\n", get_type_for_operand(src, operand), class_name, operand_name); + shd_growy_append_formatted(g, "%s get_%s_%s(const Node* node);\n", get_type_for_operand(src, operand), class_name, operand_name); } } @@ -142,7 +142,7 @@ void generate(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); generate_node_tags(g, nodes); - growy_append_formatted(g, "NodeClass get_node_class_from_tag(NodeTag tag);\n\n"); + shd_growy_append_formatted(g, "NodeClass get_node_class_from_tag(NodeTag tag);\n\n"); generate_node_payloads(g, src, nodes); generate_node_type(g, nodes); generate_node_ctor(g, nodes, false); @@ -155,10 +155,10 @@ void generate(Growy* g, json_object* src) { if (!generate_enum || json_object_get_boolean(generate_enum)) { String capitalized = capitalize(name); generate_node_tags_for_class(g, nodes, name, capitalized); - growy_append_formatted(g, "%sTag is_%s(const Node*);\n", capitalized, name); + shd_growy_append_formatted(g, "%sTag is_%s(const Node*);\n", capitalized, name); free((void*) capitalized); } else { - growy_append_formatted(g, "bool is_%s(const Node*);\n", name); + shd_growy_append_formatted(g, "bool is_%s(const Node*);\n", name); } generate_header_getters_for_class(g, src, node_class); diff --git a/src/shady/api/generator_primops.c b/src/shady/api/generator_primops.c index e4f6813a5..ddad3887f 100644 --- a/src/shady/api/generator_primops.c +++ b/src/shady/api/generator_primops.c @@ -4,7 +4,7 @@ void generate(Growy* g, json_object* src) { generate_header(g, src); json_object* nodes = json_object_object_get(src, "prim-ops"); - growy_append_formatted(g, "typedef enum Op_ {\n"); + shd_growy_append_formatted(g, "typedef enum Op_ {\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -12,13 +12,13 @@ void generate(Growy* g, json_object* src) { String name = json_object_get_string(json_object_object_get(node, "name")); assert(name); - growy_append_formatted(g, "\t%s_op,\n", name); + shd_growy_append_formatted(g, "\t%s_op,\n", name); } - growy_append_formatted(g, "\tPRIMOPS_COUNT,\n"); - growy_append_formatted(g, "} Op;\n"); + shd_growy_append_formatted(g, "\tPRIMOPS_COUNT,\n"); + shd_growy_append_formatted(g, "} Op;\n"); json_object* op_classes = json_object_object_get(src, "prim-ops-classes"); generate_bit_enum(g, "OpClass", "Oc", op_classes); - growy_append_formatted(g, "OpClass get_primop_class(Op);\n\n"); + shd_growy_append_formatted(g, "OpClass get_primop_class(Op);\n\n"); } diff --git a/src/shady/api/generator_type.c b/src/shady/api/generator_type.c index cb812e00b..46a596995 100644 --- a/src/shady/api/generator_type.c +++ b/src/shady/api/generator_type.c @@ -21,14 +21,14 @@ void generate(Growy* g, json_object* src) { if (!t || json_object_get_boolean(t)) { json_object* ops = json_object_object_get(node, "ops"); if (ops) - growy_append_formatted(g, "const Type* check_type_%s(IrArena*, %s);\n", snake_name, name); + shd_growy_append_formatted(g, "const Type* check_type_%s(IrArena*, %s);\n", snake_name, name); else - growy_append_formatted(g, "const Type* check_type_%s(IrArena*);\n", snake_name); + shd_growy_append_formatted(g, "const Type* check_type_%s(IrArena*);\n", snake_name); } if (alloc) free(alloc); } - growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node);\n"); + shd_growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node);\n"); } diff --git a/src/shady/generator/generator.c b/src/shady/generator/generator.c index ee0ec7d83..1f97d2722 100644 --- a/src/shady/generator/generator.c +++ b/src/shady/generator/generator.c @@ -11,7 +11,7 @@ void add_comments(Growy* g, String indent, json_object* comments) { if (!indent) indent = ""; if (json_object_get_type(comments) == json_type_string) { - growy_append_formatted(g, "%s/// %s\n", indent, json_object_get_string(comments)); + shd_growy_append_formatted(g, "%s/// %s\n", indent, json_object_get_string(comments)); } else if (json_object_get_type(comments) == json_type_array) { size_t size = json_object_array_length(comments); for (size_t i = 0; i < size; i++) @@ -67,9 +67,9 @@ void generate_header(Growy* g, json_object* root) { int32_t major = json_object_get_int(json_object_object_get(spv, "major_version")); int32_t minor = json_object_get_int(json_object_object_get(spv, "minor_version")); int32_t revision = json_object_get_int(json_object_object_get(spv, "revision")); - growy_append_formatted(g, "/* Generated from SPIR-V %d.%d revision %d */\n", major, minor, revision); - growy_append_formatted(g, "/* Do not edit this file manually ! */\n"); - growy_append_formatted(g, "/* It is generated by the 'generator' target using Json grammar files. */\n\n"); + shd_growy_append_formatted(g, "/* Generated from SPIR-V %d.%d revision %d */\n", major, minor, revision); + shd_growy_append_formatted(g, "/* Do not edit this file manually ! */\n"); + shd_growy_append_formatted(g, "/* It is generated by the 'generator' target using Json grammar files. */\n\n"); } bool starts_with_vowel(String str) { diff --git a/src/shady/generator/generator_common.c b/src/shady/generator/generator_common.c index a7b24d510..5bc948298 100644 --- a/src/shady/generator/generator_common.c +++ b/src/shady/generator/generator_common.c @@ -16,7 +16,7 @@ void generate_node_ctor(Growy* g, json_object* nodes, bool definition) { continue; if (definition && i > 0) - growy_append_formatted(g, "\n"); + shd_growy_append_formatted(g, "\n"); String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); const void* alloc = NULL; @@ -27,31 +27,31 @@ void generate_node_ctor(Growy* g, json_object* nodes, bool definition) { String ap = definition ? " arena" : ""; json_object* ops = json_object_object_get(node, "ops"); if (ops) - growy_append_formatted(g, "const Node* %s(IrArena*%s, %s%s)", snake_name, ap, name, definition ? " payload" : ""); + shd_growy_append_formatted(g, "const Node* %s(IrArena*%s, %s%s)", snake_name, ap, name, definition ? " payload" : ""); else - growy_append_formatted(g, "const Node* %s(IrArena*%s)", snake_name, ap); + shd_growy_append_formatted(g, "const Node* %s(IrArena*%s)", snake_name, ap); if (definition) { - growy_append_formatted(g, " {\n"); - growy_append_formatted(g, "\tNode node;\n"); - growy_append_formatted(g, "\tmemset((void*) &node, 0, sizeof(Node));\n"); - growy_append_formatted(g, "\tnode = (Node) {\n"); - growy_append_formatted(g, "\t\t.arena = arena,\n"); - growy_append_formatted(g, "\t\t.tag = %s_TAG,\n", name); + shd_growy_append_formatted(g, " {\n"); + shd_growy_append_formatted(g, "\tNode node;\n"); + shd_growy_append_formatted(g, "\tmemset((void*) &node, 0, sizeof(Node));\n"); + shd_growy_append_formatted(g, "\tnode = (Node) {\n"); + shd_growy_append_formatted(g, "\t\t.arena = arena,\n"); + shd_growy_append_formatted(g, "\t\t.tag = %s_TAG,\n", name); if (ops) - growy_append_formatted(g, "\t\t.payload.%s = payload,\n", snake_name); - growy_append_formatted(g, "\t\t.type = NULL,\n"); - growy_append_formatted(g, "\t};\n"); - growy_append_formatted(g, "\treturn create_node_helper(arena, node, NULL);\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t\t.payload.%s = payload,\n", snake_name); + shd_growy_append_formatted(g, "\t\t.type = NULL,\n"); + shd_growy_append_formatted(g, "\t};\n"); + shd_growy_append_formatted(g, "\treturn create_node_helper(arena, node, NULL);\n"); + shd_growy_append_formatted(g, "}\n"); } else { - growy_append_formatted(g, ";\n"); + shd_growy_append_formatted(g, ";\n"); } if (alloc) free((void*) alloc); } - growy_append_formatted(g, "\n"); + shd_growy_append_formatted(g, "\n"); } json_object* lookup_node_class(json_object* src, String name) { @@ -77,7 +77,7 @@ String class_to_type(json_object* src, String class, bool list) { // check the class is valid if (!lookup_node_class(src, class)) { error_print("invalid node class '%s'\n", class); - error_die(); + shd_error_die(); } return list ? "Nodes" : "const Node*"; } @@ -111,47 +111,46 @@ void preprocess(json_object* src) { void generate_bit_enum(Growy* g, String enum_type_name, String enum_case_prefix, json_object* cases) { assert(json_object_get_type(cases) == json_type_array); - growy_append_formatted(g, "typedef enum {\n"); + shd_growy_append_formatted(g, "typedef enum {\n"); for (size_t i = 0; i < json_object_array_length(cases); i++) { json_object* node_class = json_object_array_get_idx(cases, i); String name = json_object_get_string(json_object_object_get(node_class, "name")); String capitalized = capitalize(name); - growy_append_formatted(g, "\t%s%s = 0x%x", enum_case_prefix, capitalized, (1 << i)); - growy_append_formatted(g, ",\n"); + shd_growy_append_formatted(g, "\t%s%s = 0x%x", enum_case_prefix, capitalized, (1 << i)); + shd_growy_append_formatted(g, ",\n"); free((void*) capitalized); } - growy_append_formatted(g, "} %s;\n\n", enum_type_name); + shd_growy_append_formatted(g, "} %s;\n\n", enum_type_name); } void generate_bit_enum_classifier(Growy* g, String fn_name, String enum_type_name, String enum_case_prefix, String src_type_name, String src_case_prefix, String src_case_suffix, json_object* cases) { - growy_append_formatted(g, "%s %s(%s tag) {\n", enum_type_name, fn_name, src_type_name); - growy_append_formatted(g, "\tswitch (tag) { \n"); + shd_growy_append_formatted(g, "%s %s(%s tag) {\n", enum_type_name, fn_name, src_type_name); + shd_growy_append_formatted(g, "\tswitch (tag) { \n"); assert(json_object_get_type(cases) == json_type_array); for (size_t i = 0; i < json_object_array_length(cases); i++) { json_object* node = json_object_array_get_idx(cases, i); String name = json_object_get_string(json_object_object_get(node, "name")); - growy_append_formatted(g, "\t\tcase %s%s%s: \n", src_case_prefix, name, src_case_suffix); + shd_growy_append_formatted(g, "\t\tcase %s%s%s: \n", src_case_prefix, name, src_case_suffix); json_object* class = json_object_object_get(node, "class"); switch (json_object_get_type(class)) { - case json_type_null: - growy_append_formatted(g, "\t\t\treturn 0;\n"); + case json_type_null:shd_growy_append_formatted(g, "\t\t\treturn 0;\n"); break; case json_type_string: { String cap = capitalize(json_object_get_string(class)); - growy_append_formatted(g, "\t\t\treturn %s%s;\n", enum_case_prefix, cap); + shd_growy_append_formatted(g, "\t\t\treturn %s%s;\n", enum_case_prefix, cap); free((void*) cap); break; } case json_type_array: { - growy_append_formatted(g, "\t\t\treturn "); + shd_growy_append_formatted(g, "\t\t\treturn "); for (size_t j = 0; j < json_object_array_length(class); j++) { if (j > 0) - growy_append_formatted(g, " | "); + shd_growy_append_formatted(g, " | "); String cap = capitalize(json_object_get_string(json_object_array_get_idx(class, j))); - growy_append_formatted(g, "%s%s", enum_case_prefix, cap); + shd_growy_append_formatted(g, "%s%s", enum_case_prefix, cap); free((void*) cap); } - growy_append_formatted(g, ";\n"); + shd_growy_append_formatted(g, ";\n"); break; } case json_type_boolean: @@ -162,8 +161,8 @@ void generate_bit_enum_classifier(Growy* g, String fn_name, String enum_type_nam break; } } - growy_append_formatted(g, "\t\tdefault: assert(false);\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "\tSHADY_UNREACHABLE;\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t\tdefault: assert(false);\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "\tSHADY_UNREACHABLE;\n"); + shd_growy_append_formatted(g, "}\n"); } \ No newline at end of file diff --git a/src/shady/generator/generator_main.c b/src/shady/generator/generator_main.c index de9dba0d3..bd85d79da 100644 --- a/src/shady/generator/generator_main.c +++ b/src/shady/generator/generator_main.c @@ -29,7 +29,7 @@ int main(int argc, char** argv) { LARRAY(JsonFile, json_files, inputs_count); for (size_t i = 0; i < inputs_count; i++) { String path = argv[ArgFirstInput + i]; - read_file(path, &json_files[i].size, &json_files[i].contents); + shd_read_file(path, &json_files[i].size, &json_files[i].contents); json_files[i].root = json_tokener_parse_ex(tokener, json_files[i].contents, json_files[i].size); json_err = json_tokener_get_error(tokener); if (json_err != json_tokener_success) { @@ -38,7 +38,7 @@ int main(int argc, char** argv) { info_print("Correctly opened json file: %s\n", path); } - Growy* g = new_growy(); + Growy* g = shd_new_growy(); json_object* src = json_object_new_object(); @@ -49,13 +49,13 @@ int main(int argc, char** argv) { preprocess(src); generate(g, src); - size_t final_size = growy_size(g); - growy_append_bytes(g, 1, (char[]) { 0 }); - char* generated = growy_deconstruct(g); + size_t final_size = shd_growy_size(g); + shd_growy_append_bytes(g, 1, (char[]) { 0 }); + char* generated = shd_growy_deconstruct(g); debug_print("debug: %s\n", generated); - if (!write_file(dst_file, final_size, generated)) { + if (!shd_write_file(dst_file, final_size, generated)) { error_print("Failed to write file '%s'\n", dst_file); - error_die(); + shd_error_die(); } free(generated); for (size_t i = 0; i < inputs_count; i++) { diff --git a/src/shady/generator/import_spv_defs.c b/src/shady/generator/import_spv_defs.c index cb840e5e3..11d5dcfc0 100644 --- a/src/shady/generator/import_spv_defs.c +++ b/src/shady/generator/import_spv_defs.c @@ -14,10 +14,10 @@ static String sanitize_node_name(String name) { char* tmpname = NULL; tmpname = calloc(strlen(name) + 1, 1); bool is_type = false; - if (string_starts_with(name, "OpType")) { + if (shd_string_starts_with(name, "OpType")) { memcpy(tmpname, name + 6, strlen(name) - 6); is_type = true; - } else if (string_starts_with(name, "Op")) + } else if (shd_string_starts_with(name, "Op")) memcpy(tmpname, name + 2, strlen(name) - 2); else memcpy(tmpname, name, strlen(name)); @@ -273,7 +273,7 @@ int main(int argc, char** argv) { // search the include path for spirv.core.grammar.json char* spv_core_json_path = NULL; for (size_t i = ArgSpirvGrammarSearchPathBegins; i < argc; i++) { - char* path = format_string_new("%s/spirv/unified1/spirv.core.grammar.json", argv[i]); + char* path = shd_format_string_new("%s/spirv/unified1/spirv.core.grammar.json", argv[i]); info_print("trying path %s\n", path); FILE* f = fopen(path, "rb"); if (f) { @@ -297,7 +297,7 @@ int main(int argc, char** argv) { } JsonFile; JsonFile imports; - read_file(argv[ArgImportsFile], &imports.size, &imports.contents); + shd_read_file(argv[ArgImportsFile], &imports.size, &imports.contents); imports.root = json_tokener_parse_ex(tokener, imports.contents, imports.size); json_err = json_tokener_get_error(tokener); if (json_err != json_tokener_success) { @@ -305,7 +305,7 @@ int main(int argc, char** argv) { } JsonFile spirv; - read_file(spv_core_json_path, &spirv.size, &spirv.contents); + shd_read_file(spv_core_json_path, &spirv.size, &spirv.contents); spirv.root = json_tokener_parse_ex(tokener, spirv.contents, spirv.size); json_err = json_tokener_get_error(tokener); if (json_err != json_tokener_success) { @@ -318,17 +318,17 @@ int main(int argc, char** argv) { import_spirv_defs(imports.root, spirv.root, output); - Growy* g = new_growy(); - growy_append_string(g, json_object_to_json_string_ext(output, JSON_C_TO_STRING_PRETTY)); + Growy* g = shd_new_growy(); + shd_growy_append_string(g, json_object_to_json_string_ext(output, JSON_C_TO_STRING_PRETTY)); json_object_put(output); - size_t final_size = growy_size(g); - growy_append_bytes(g, 1, (char[]) { 0 }); - char* generated = growy_deconstruct(g); + size_t final_size = shd_growy_size(g); + shd_growy_append_bytes(g, 1, (char[]) { 0 }); + char* generated = shd_growy_deconstruct(g); debug_print("debug: %s\n", generated); - if (!write_file(dst_file, final_size, generated)) { + if (!shd_write_file(dst_file, final_size, generated)) { error_print("Failed to write file '%s'\n", dst_file); - error_die(); + shd_error_die(); } free(generated); free(spirv.contents); diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 9c49b98b6..a092bd8ef 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -2,8 +2,8 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); - growy_append_formatted(g, "void pre_construction_validation(IrArena* arena, Node* node) {\n"); - growy_append_formatted(g, "\tswitch (node->tag) { \n"); + shd_growy_append_formatted(g, "void pre_construction_validation(IrArena* arena, Node* node) {\n"); + shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -14,7 +14,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { snake_name = to_snake_case(name); alloc = (void*) snake_name; } - growy_append_formatted(g, "\tcase %s_TAG: {\n", name); + shd_growy_append_formatted(g, "\tcase %s_TAG: {\n", name); json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); @@ -27,53 +27,53 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { bool list = json_object_get_boolean(json_object_object_get(op, "list")); if (strcmp(class, "string") == 0) { if (!list) - growy_append_formatted(g, "\t\tnode->payload.%s.%s = string(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); + shd_growy_append_formatted(g, "\t\tnode->payload.%s.%s = string(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); else - growy_append_formatted(g, "\t\tnode->payload.%s.%s = import_strings(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); + shd_growy_append_formatted(g, "\t\tnode->payload.%s.%s = import_strings(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); } else { String cap = capitalize(class); - growy_append_formatted(g, "\t\t{\n"); + shd_growy_append_formatted(g, "\t\t{\n"); String extra = ""; if (list) { - growy_append_formatted(g, "\t\t\tsize_t ops_count = node->payload.%s.%s.count;\n", snake_name, op_name); - growy_append_formatted(g, "\t\t\tLARRAY(const Node*, ops, ops_count);\n"); - growy_append_formatted(g, "\t\t\tif (ops_count > 0) memcpy(ops, node->payload.%s.%s.nodes, sizeof(const Node*) * ops_count);\n", snake_name, op_name); - growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < ops_count; i++) {\n"); - growy_append_formatted(g, "\t\t\tconst Node** pop = &ops[i];\n"); + shd_growy_append_formatted(g, "\t\t\tsize_t ops_count = node->payload.%s.%s.count;\n", snake_name, op_name); + shd_growy_append_formatted(g, "\t\t\tLARRAY(const Node*, ops, ops_count);\n"); + shd_growy_append_formatted(g, "\t\t\tif (ops_count > 0) memcpy(ops, node->payload.%s.%s.nodes, sizeof(const Node*) * ops_count);\n", snake_name, op_name); + shd_growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < ops_count; i++) {\n"); + shd_growy_append_formatted(g, "\t\t\tconst Node** pop = &ops[i];\n"); extra = "\t"; } if (!list) - growy_append_formatted(g, "\t\t\tconst Node** pop = &node->payload.%s.%s;\n", snake_name, op_name); + shd_growy_append_formatted(g, "\t\t\tconst Node** pop = &node->payload.%s.%s;\n", snake_name, op_name); - growy_append_formatted(g, "\t\t\t*pop = fold_node_operand(%s_TAG, Nc%s, \"%s\", *pop);\n", name, cap, op_name); + shd_growy_append_formatted(g, "\t\t\t*pop = fold_node_operand(%s_TAG, Nc%s, \"%s\", *pop);\n", name, cap, op_name); if (!(json_object_get_boolean(json_object_object_get(op, "nullable")) || json_object_get_boolean(json_object_object_get(op, "ignore")))) { - growy_append_formatted(g, "%s\t\t\tif (!*pop) {\n", extra); - growy_append_formatted(g, "%s\t\t\t\terror(\"operand '%s' of node '%s' cannot be null\");\n", extra, op_name, name); - growy_append_formatted(g, "%s\t\t\t}\n", extra); + shd_growy_append_formatted(g, "%s\t\t\tif (!*pop) {\n", extra); + shd_growy_append_formatted(g, "%s\t\t\t\terror(\"operand '%s' of node '%s' cannot be null\");\n", extra, op_name, name); + shd_growy_append_formatted(g, "%s\t\t\t}\n", extra); } - growy_append_formatted(g, "%s\t\t\tif (arena->config.check_op_classes && *pop != NULL && !is_%s(*pop)) {\n", extra, class); - growy_append_formatted(g, "%s\t\t\t\terror_print(\"Invalid '%s' operand for node '%s', expected a %s\");\n", extra, op_name, name, class); - growy_append_formatted(g, "%s\t\t\t\terror_die();\n", extra); - growy_append_formatted(g, "%s\t\t\t}\n", extra); + shd_growy_append_formatted(g, "%s\t\t\tif (arena->config.check_op_classes && *pop != NULL && !is_%s(*pop)) {\n", extra, class); + shd_growy_append_formatted(g, "%s\t\t\t\terror_print(\"Invalid '%s' operand for node '%s', expected a %s\");\n", extra, op_name, name, class); + shd_growy_append_formatted(g, "%s\t\t\t\tshd_error_die();\n", extra); + shd_growy_append_formatted(g, "%s\t\t\t}\n", extra); if (list) { - growy_append_formatted(g, "\t\t\t}\n"); - growy_append_formatted(g, "\t\t\tnode->payload.%s.%s = nodes(arena, ops_count, ops);\n", snake_name, op_name); + shd_growy_append_formatted(g, "\t\t\t}\n"); + shd_growy_append_formatted(g, "\t\t\tnode->payload.%s.%s = nodes(arena, ops_count, ops);\n", snake_name, op_name); } free((void*) cap); - growy_append_formatted(g, "\t\t}\n"); + shd_growy_append_formatted(g, "\t\t}\n"); } } } - growy_append_formatted(g, "\t\tbreak;\n"); - growy_append_formatted(g, "\t}\n", name); + shd_growy_append_formatted(g, "\t\tbreak;\n"); + shd_growy_append_formatted(g, "\t}\n", name); if (alloc) free(alloc); } - growy_append_formatted(g, "\t\tdefault: break;\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n\n"); + shd_growy_append_formatted(g, "\t\tdefault: break;\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n\n"); } void generate(Growy* g, json_object* src) { diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 01b173de1..9d2d8a8de 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -3,8 +3,8 @@ #include "generator.h" static void generate_node_names_string_array(Growy* g, json_object* nodes) { - growy_append_formatted(g, "const char* node_tags[] = {\n"); - growy_append_formatted(g, "\t\"invalid\",\n"); + shd_growy_append_formatted(g, "const char* node_tags[] = {\n"); + shd_growy_append_formatted(g, "\t\"invalid\",\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); String name = json_object_get_string(json_object_object_get(node, "name")); @@ -15,28 +15,28 @@ static void generate_node_names_string_array(Growy* g, json_object* nodes) { alloc = (void*) snake_name; } assert(name); - growy_append_formatted(g, "\t\"%s\",\n", snake_name); + shd_growy_append_formatted(g, "\t\"%s\",\n", snake_name); if (alloc) free(alloc); } - growy_append_formatted(g, "};\n\n"); + shd_growy_append_formatted(g, "};\n\n"); } static void generate_node_has_payload_array(Growy* g, json_object* nodes) { - growy_append_formatted(g, "const bool node_type_has_payload[] = {\n"); - growy_append_formatted(g, "\tfalse,\n"); + shd_growy_append_formatted(g, "const bool node_type_has_payload[] = {\n"); + shd_growy_append_formatted(g, "\tfalse,\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); json_object* ops = json_object_object_get(node, "ops"); - growy_append_formatted(g, "\t%s,\n", ops ? "true" : "false"); + shd_growy_append_formatted(g, "\t%s,\n", ops ? "true" : "false"); } - growy_append_formatted(g, "};\n\n"); + shd_growy_append_formatted(g, "};\n\n"); } static void generate_node_payload_hash_fn(Growy* g, json_object* src, json_object* nodes) { - growy_append_formatted(g, "KeyHash hash_node_payload(const Node* node) {\n"); - growy_append_formatted(g, "\tKeyHash hash = 0;\n"); - growy_append_formatted(g, "\tswitch (node->tag) { \n"); + shd_growy_append_formatted(g, "KeyHash hash_node_payload(const Node* node) {\n"); + shd_growy_append_formatted(g, "\tKeyHash hash = 0;\n"); + shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -50,32 +50,32 @@ static void generate_node_payload_hash_fn(Growy* g, json_object* src, json_objec json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); - growy_append_formatted(g, "\tcase %s_TAG: {\n", name); - growy_append_formatted(g, "\t\t%s payload = node->payload.%s;\n", name, snake_name); + shd_growy_append_formatted(g, "\tcase %s_TAG: {\n", name); + shd_growy_append_formatted(g, "\t\t%s payload = node->payload.%s;\n", name, snake_name); for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); bool ignore = json_object_get_boolean(json_object_object_get(op, "ignore")); if (!ignore) { - growy_append_formatted(g, "\t\thash = hash ^ shd_hash_murmur(&payload.%s, sizeof(payload.%s));\n", op_name, op_name); + shd_growy_append_formatted(g, "\t\thash = hash ^ shd_hash_murmur(&payload.%s, sizeof(payload.%s));\n", op_name, op_name); } } - growy_append_formatted(g, "\t\tbreak;\n"); - growy_append_formatted(g, "\t}\n", name); + shd_growy_append_formatted(g, "\t\tbreak;\n"); + shd_growy_append_formatted(g, "\t}\n", name); } if (alloc) free(alloc); } - growy_append_formatted(g, "\t\tdefault: assert(false);\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "\treturn hash;\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t\tdefault: assert(false);\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "\treturn hash;\n"); + shd_growy_append_formatted(g, "}\n"); } static void generate_node_payload_cmp_fn(Growy* g, json_object* src, json_object* nodes) { - growy_append_formatted(g, "bool compare_node_payload(const Node* a, const Node* b) {\n"); - growy_append_formatted(g, "\tbool eq = true;\n"); - growy_append_formatted(g, "\tswitch (a->tag) { \n"); + shd_growy_append_formatted(g, "bool compare_node_payload(const Node* a, const Node* b) {\n"); + shd_growy_append_formatted(g, "\tbool eq = true;\n"); + shd_growy_append_formatted(g, "\tswitch (a->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -89,60 +89,60 @@ static void generate_node_payload_cmp_fn(Growy* g, json_object* src, json_object json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); - growy_append_formatted(g, "\tcase %s_TAG: {\n", name); - growy_append_formatted(g, "\t\t%s payload_a = a->payload.%s;\n", name, snake_name); - growy_append_formatted(g, "\t\t%s payload_b = b->payload.%s;\n", name, snake_name); + shd_growy_append_formatted(g, "\tcase %s_TAG: {\n", name); + shd_growy_append_formatted(g, "\t\t%s payload_a = a->payload.%s;\n", name, snake_name); + shd_growy_append_formatted(g, "\t\t%s payload_b = b->payload.%s;\n", name, snake_name); for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); bool ignore = json_object_get_boolean(json_object_object_get(op, "ignore")); if (!ignore) { - growy_append_formatted(g, "\t\teq &= memcmp(&payload_a.%s, &payload_b.%s, sizeof(payload_a.%s)) == 0;\n", op_name, op_name, op_name); + shd_growy_append_formatted(g, "\t\teq &= memcmp(&payload_a.%s, &payload_b.%s, sizeof(payload_a.%s)) == 0;\n", op_name, op_name, op_name); } } - growy_append_formatted(g, "\t\tbreak;\n"); - growy_append_formatted(g, "\t}\n", name); + shd_growy_append_formatted(g, "\t\tbreak;\n"); + shd_growy_append_formatted(g, "\t}\n", name); } if (alloc) free(alloc); } - growy_append_formatted(g, "\t\tdefault: assert(false);\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "\treturn eq;\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t\tdefault: assert(false);\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "\treturn eq;\n"); + shd_growy_append_formatted(g, "}\n"); } static void generate_node_is_nominal(Growy* g, json_object* nodes) { - growy_append_formatted(g, "bool is_nominal(const Node* node) {\n"); - growy_append_formatted(g, "\tswitch (node->tag) { \n"); + shd_growy_append_formatted(g, "bool is_nominal(const Node* node) {\n"); + shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); String name = json_object_get_string(json_object_object_get(node, "name")); if (json_object_get_boolean(json_object_object_get(node, "nominal"))) { - growy_append_formatted(g, "\t\tcase %s_TAG: return true;\n", name); + shd_growy_append_formatted(g, "\t\tcase %s_TAG: return true;\n", name); } } - growy_append_formatted(g, "\t\tdefault: return false;\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t\tdefault: return false;\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n"); } static void generate_isa_for_class(Growy* g, json_object* nodes, String class, String capitalized_class, bool use_enum) { assert(json_object_get_type(nodes) == json_type_array); if (use_enum) - growy_append_formatted(g, "%sTag is_%s(const Node* node) {\n", capitalized_class, class); + shd_growy_append_formatted(g, "%sTag is_%s(const Node* node) {\n", capitalized_class, class); else - growy_append_formatted(g, "bool is_%s(const Node* node) {\n", class); - growy_append_formatted(g, "\tif (get_node_class_from_tag(node->tag) & Nc%s)\n", capitalized_class); + shd_growy_append_formatted(g, "bool is_%s(const Node* node) {\n", class); + shd_growy_append_formatted(g, "\tif (get_node_class_from_tag(node->tag) & Nc%s)\n", capitalized_class); if (use_enum) { - growy_append_formatted(g, "\t\treturn (%sTag) node->tag;\n", capitalized_class); - growy_append_formatted(g, "\treturn (%sTag) 0;\n", capitalized_class); + shd_growy_append_formatted(g, "\t\treturn (%sTag) node->tag;\n", capitalized_class); + shd_growy_append_formatted(g, "\treturn (%sTag) 0;\n", capitalized_class); } else { - growy_append_formatted(g, "\t\treturn true;\n", capitalized_class); - growy_append_formatted(g, "\treturn false;\n", capitalized_class); + shd_growy_append_formatted(g, "\t\treturn true;\n", capitalized_class); + shd_growy_append_formatted(g, "\treturn false;\n", capitalized_class); } - growy_append_formatted(g, "}\n\n"); + shd_growy_append_formatted(g, "}\n\n"); } static bool is_of(json_object* node, String class_name) { @@ -169,35 +169,35 @@ static void generate_getters_for_class(Growy* g, json_object* src, json_object* json_object* operand = json_object_array_get_idx(class_ops, i); String operand_name = json_object_get_string(json_object_object_get(operand, "name")); assert(operand_name); - growy_append_formatted(g, "%s get_%s_%s(const Node* node) {\n", get_type_for_operand(src, operand), class_name, operand_name); - growy_append_formatted(g, "\tswitch(node->tag) {\n"); + shd_growy_append_formatted(g, "%s get_%s_%s(const Node* node) {\n", get_type_for_operand(src, operand), class_name, operand_name); + shd_growy_append_formatted(g, "\tswitch(node->tag) {\n"); for (size_t j = 0; j < json_object_array_length(nodes); j++) { json_object* node = json_object_array_get_idx(nodes, j); if (is_of(json_object_object_get(node, "class"), class_name)) { String node_name = json_object_get_string(json_object_object_get(node, "name")); - growy_append_formatted(g, "\t\tcase %s_TAG: ", node_name); + shd_growy_append_formatted(g, "\t\tcase %s_TAG: ", node_name); String node_snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); assert(node_snake_name); - growy_append_formatted(g, "return node->payload.%s.%s;\n", node_snake_name, operand_name); + shd_growy_append_formatted(g, "return node->payload.%s.%s;\n", node_snake_name, operand_name); } } - growy_append_formatted(g, "\t\tdefault: break;\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "\tassert(false);\n"); - growy_append_formatted(g, "}\n\n"); + shd_growy_append_formatted(g, "\t\tdefault: break;\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "\tassert(false);\n"); + shd_growy_append_formatted(g, "}\n\n"); } } void generate_address_space_name_fn(Growy* g, json_object* address_spaces) { - growy_append_formatted(g, "String get_address_space_name(AddressSpace as) {\n"); - growy_append_formatted(g, "\tswitch (as) {\n"); + shd_growy_append_formatted(g, "String get_address_space_name(AddressSpace as) {\n"); + shd_growy_append_formatted(g, "\tswitch (as) {\n"); for (size_t i = 0; i < json_object_array_length(address_spaces); i++) { json_object* as = json_object_array_get_idx(address_spaces, i); String name = json_object_get_string(json_object_object_get(as, "name")); - growy_append_formatted(g, "\t\t case As%s: return \"%s\";\n", name, name); + shd_growy_append_formatted(g, "\t\t case As%s: return \"%s\";\n", name, name); } - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n"); } void generate(Growy* g, json_object* src) { diff --git a/src/shady/generator_primops.c b/src/shady/generator_primops.c index bb57bf258..9d1f9890a 100644 --- a/src/shady/generator_primops.c +++ b/src/shady/generator_primops.c @@ -1,7 +1,7 @@ #include "generator.h" static void generate_primops_names_array(Growy* g, json_object* primops) { - growy_append_string(g, "const char* primop_names[] = {\n"); + shd_growy_append_string(g, "const char* primop_names[] = {\n"); for (size_t i = 0; i < json_object_array_length(primops); i++) { json_object* node = json_object_array_get_idx(primops, i); @@ -9,14 +9,14 @@ static void generate_primops_names_array(Growy* g, json_object* primops) { String name = json_object_get_string(json_object_object_get(node, "name")); assert(name); - growy_append_formatted(g, "\"%s\",", name); + shd_growy_append_formatted(g, "\"%s\",", name); } - growy_append_string(g, "\n};\n"); + shd_growy_append_string(g, "\n};\n"); } static void generate_primops_side_effects_array(Growy* g, json_object* primops) { - growy_append_string(g, "const bool primop_side_effects[] = {\n"); + shd_growy_append_string(g, "const bool primop_side_effects[] = {\n"); for (size_t i = 0; i < json_object_array_length(primops); i++) { json_object* node = json_object_array_get_idx(primops, i); @@ -26,12 +26,12 @@ static void generate_primops_side_effects_array(Growy* g, json_object* primops) bool side_effects = json_object_get_boolean(json_object_object_get(node, "side-effects")); if (side_effects) - growy_append_string(g, "true, "); + shd_growy_append_string(g, "true, "); else - growy_append_string(g, "false, "); + shd_growy_append_string(g, "false, "); } - growy_append_string(g, "\n};\n"); + shd_growy_append_string(g, "\n};\n"); } void generate(Growy* g, json_object* shd) { diff --git a/src/shady/generator_print.c b/src/shady/generator_print.c index 2bf9bd8a1..7c09442f9 100644 --- a/src/shady/generator_print.c +++ b/src/shady/generator_print.c @@ -2,8 +2,8 @@ void generate_node_print_fns(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); - growy_append_formatted(g, "void print_node_generated(PrinterCtx* ctx, const Node* node) {\n"); - growy_append_formatted(g, "\tswitch (node->tag) { \n"); + shd_growy_append_formatted(g, "void print_node_generated(PrinterCtx* ctx, const Node* node) {\n"); + shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -14,11 +14,11 @@ void generate_node_print_fns(Growy* g, json_object* src) { snake_name = to_snake_case(name); alloc = (void*) snake_name; } - growy_append_formatted(g, "\tcase %s_TAG: {\n", name); - growy_append_formatted(g, "\t\tprint(ctx->printer, GREEN);\n"); - growy_append_formatted(g, "\t\tprint(ctx->printer, \"%s\");\n", name); - growy_append_formatted(g, "\t\tprint(ctx->printer, RESET);\n"); - growy_append_formatted(g, "\t\tprint(ctx->printer, \"(\");\n"); + shd_growy_append_formatted(g, "\tcase %s_TAG: {\n", name); + shd_growy_append_formatted(g, "\t\tprint(ctx->printer, GREEN);\n"); + shd_growy_append_formatted(g, "\t\tprint(ctx->printer, \"%s\");\n", name); + shd_growy_append_formatted(g, "\t\tprint(ctx->printer, RESET);\n"); + shd_growy_append_formatted(g, "\t\tprint(ctx->printer, \"(\");\n"); json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); @@ -34,17 +34,17 @@ void generate_node_print_fns(Growy* g, json_object* src) { bool is_list = json_object_get_boolean(json_object_object_get(op, "list")); String cap_class = capitalize(op_class); if (is_list) { - growy_append_formatted(g, "\t\t{\n"); - growy_append_formatted(g, "\t\t\tprint_node_operand_list(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); + shd_growy_append_formatted(g, "\t\t{\n"); + shd_growy_append_formatted(g, "\t\t\tprint_node_operand_list(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); // growy_append_formatted(g, "\t\t\tsize_t count = node->payload.%s.%s.count;\n", snake_name, op_name); // growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < count; i++) {\n"); // growy_append_formatted(g, "\t\t\t\tprint_node_operand(printer, node, \"%s\", Nc%s, i, node->payload.%s.%s.nodes[i], config);\n", op_name, cap_class, snake_name, op_name); // growy_append_formatted(g, "\t\t\t}\n"); - growy_append_formatted(g, "\t\t}\n"); + shd_growy_append_formatted(g, "\t\t}\n"); } else { - growy_append_formatted(g, "\t\t{\n"); - growy_append_formatted(g, "\t\t\tprint_node_operand(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); - growy_append_formatted(g, "\t\t}\n"); + shd_growy_append_formatted(g, "\t\t{\n"); + shd_growy_append_formatted(g, "\t\t\tprint_node_operand(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); + shd_growy_append_formatted(g, "\t\t}\n"); } free((void*) cap_class); } else { @@ -61,23 +61,23 @@ void generate_node_print_fns(Growy* g, json_object* src) { if (!isalnum(s[k])) s[k] = '_'; } - growy_append_formatted(g, "\t\tprint_node_operand_%s(ctx, node, \"%s\", node->payload.%s.%s);\n", s, op_name, snake_name, op_name); + shd_growy_append_formatted(g, "\t\tprint_node_operand_%s(ctx, node, \"%s\", node->payload.%s.%s);\n", s, op_name, snake_name, op_name); free(s); } if (j + 1 < json_object_array_length(ops)) - growy_append_formatted(g, "\t\tprint(ctx->printer, \", \");\n"); + shd_growy_append_formatted(g, "\t\tprint(ctx->printer, \", \");\n"); } } - growy_append_formatted(g, "\t\tprint(ctx->printer, \")\");\n"); - growy_append_formatted(g, "\t\tbreak;\n"); - growy_append_formatted(g, "\t}\n", name); + shd_growy_append_formatted(g, "\t\tprint(ctx->printer, \")\");\n"); + shd_growy_append_formatted(g, "\t\tbreak;\n"); + shd_growy_append_formatted(g, "\t}\n", name); if (alloc) free(alloc); } - growy_append_formatted(g, "\t\tdefault: assert(false);\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t\tdefault: assert(false);\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n"); } void generate(Growy* g, json_object* src) { diff --git a/src/shady/generator_rewrite.c b/src/shady/generator_rewrite.c index c0ce02051..55e2fc777 100644 --- a/src/shady/generator_rewrite.c +++ b/src/shady/generator_rewrite.c @@ -1,24 +1,24 @@ #include "generator.h" static void generate_can_be_default_rewritten_fn(Growy* g, json_object* nodes) { - growy_append_formatted(g, "static bool can_be_default_rewritten(NodeTag tag) {\n"); - growy_append_formatted(g, "\tswitch (tag) { \n"); + shd_growy_append_formatted(g, "static bool can_be_default_rewritten(NodeTag tag) {\n"); + shd_growy_append_formatted(g, "\tswitch (tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); if (has_custom_ctor(node)) continue; String name = json_object_get_string(json_object_object_get(node, "name")); - growy_append_formatted(g, "\t\tcase %s_TAG: return true;\n", name); + shd_growy_append_formatted(g, "\t\tcase %s_TAG: return true;\n", name); } - growy_append_formatted(g, "\t\tdefault: return false;\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n\n"); + shd_growy_append_formatted(g, "\t\tdefault: return false;\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n\n"); } static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { - growy_append_formatted(g, "static const Node* recreate_node_identity_generated(Rewriter* rewriter, const Node* node) {\n"); - growy_append_formatted(g, "\tswitch (node->tag) { \n"); + shd_growy_append_formatted(g, "static const Node* recreate_node_identity_generated(Rewriter* rewriter, const Node* node) {\n"); + shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -33,13 +33,13 @@ static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { snake_name = to_snake_case(name); alloc = (void*) snake_name; } - growy_append_formatted(g, "\t\tcase %s_TAG: {\n", name); + shd_growy_append_formatted(g, "\t\tcase %s_TAG: {\n", name); json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); - growy_append_formatted(g, "\t\t\t%s old_payload = node->payload.%s;\n", name, snake_name); - growy_append_formatted(g, "\t\t\t%s payload;\n", name); - growy_append_formatted(g, "\t\t\tmemset(&payload, 0, sizeof(payload));\n"); + shd_growy_append_formatted(g, "\t\t\t%s old_payload = node->payload.%s;\n", name, snake_name); + shd_growy_append_formatted(g, "\t\t\t%s payload;\n", name); + shd_growy_append_formatted(g, "\t\t\tmemset(&payload, 0, sizeof(payload));\n"); for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); @@ -50,34 +50,34 @@ static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { String class = json_object_get_string(json_object_object_get(op, "class")); if (!class) { assert(!list); - growy_append_formatted(g, "\t\t\tpayload.%s = old_payload.%s;\n", op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tpayload.%s = old_payload.%s;\n", op_name, op_name); continue; } if (strcmp(class, "string") == 0) { if (list) - growy_append_formatted(g, "\t\t\tpayload.%s = strings(rewriter->dst_arena, old_payload.%s.count, old_payload.%s.strings);\n", op_name, op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tpayload.%s = strings(rewriter->dst_arena, old_payload.%s.count, old_payload.%s.strings);\n", op_name, op_name, op_name); else - growy_append_formatted(g, "\t\t\tpayload.%s = string(rewriter->dst_arena, old_payload.%s);\n", op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tpayload.%s = string(rewriter->dst_arena, old_payload.%s);\n", op_name, op_name); continue; } String class_cap = capitalize(class); if (list) - growy_append_formatted(g, "\t\t\tpayload.%s = rewrite_ops_helper(rewriter, Nc%s, \"%s\", old_payload.%s);\n", op_name, class_cap, op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tpayload.%s = rewrite_ops_helper(rewriter, Nc%s, \"%s\", old_payload.%s);\n", op_name, class_cap, op_name, op_name); else - growy_append_formatted(g, "\t\t\tpayload.%s = rewrite_op_helper(rewriter, Nc%s, \"%s\", old_payload.%s);\n", op_name, class_cap, op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tpayload.%s = rewrite_op_helper(rewriter, Nc%s, \"%s\", old_payload.%s);\n", op_name, class_cap, op_name, op_name); free((void*) class_cap); } - growy_append_formatted(g, "\t\t\treturn %s(rewriter->dst_arena, payload);\n", snake_name); + shd_growy_append_formatted(g, "\t\t\treturn %s(rewriter->dst_arena, payload);\n", snake_name); } else - growy_append_formatted(g, "\t\t\treturn %s(rewriter->dst_arena);\n", snake_name); - growy_append_formatted(g, "\t\t}\n", name); + shd_growy_append_formatted(g, "\t\t\treturn %s(rewriter->dst_arena);\n", snake_name); + shd_growy_append_formatted(g, "\t\t}\n", name); if (alloc) free(alloc); } - growy_append_formatted(g, "\t\tdefault: assert(false);\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n\n"); + shd_growy_append_formatted(g, "\t\tdefault: assert(false);\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n\n"); } void generate(Growy* g, json_object* src) { diff --git a/src/shady/generator_type.c b/src/shady/generator_type.c index 096fa6ae9..f25d87d5c 100644 --- a/src/shady/generator_type.c +++ b/src/shady/generator_type.c @@ -5,8 +5,8 @@ void generate(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); - growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node) {\n"); - growy_append_formatted(g, "\tswitch(node->tag) {\n"); + shd_growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node) {\n"); + shd_growy_append_formatted(g, "\tswitch(node->tag) {\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -22,18 +22,18 @@ void generate(Growy* g, json_object* src) { json_object* t = json_object_object_get(node, "type"); if (!t || json_object_get_boolean(t)) { - growy_append_formatted(g, "\t\tcase %s_TAG: ", name); + shd_growy_append_formatted(g, "\t\tcase %s_TAG: ", name); json_object* ops = json_object_object_get(node, "ops"); if (ops) - growy_append_formatted(g, "return check_type_%s(a, node->payload.%s);\n", snake_name, snake_name); + shd_growy_append_formatted(g, "return check_type_%s(a, node->payload.%s);\n", snake_name, snake_name); else - growy_append_formatted(g, "return check_type_%s(a);\n", snake_name); + shd_growy_append_formatted(g, "return check_type_%s(a);\n", snake_name); } if (alloc) free(alloc); } - growy_append_formatted(g, "\t\tdefault: return NULL;\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n"); + shd_growy_append_formatted(g, "\t\tdefault: return NULL;\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n"); } diff --git a/src/shady/generator_visit.c b/src/shady/generator_visit.c index 46111c630..b7bcde003 100644 --- a/src/shady/generator_visit.c +++ b/src/shady/generator_visit.c @@ -4,8 +4,8 @@ void generate(Growy* g, json_object* src) { generate_header(g, src); json_object* nodes = json_object_object_get(src, "nodes"); - growy_append_formatted(g, "void visit_node_operands(Visitor* visitor, NodeClass exclude, const Node* node) {\n"); - growy_append_formatted(g, "\tswitch (node->tag) { \n"); + shd_growy_append_formatted(g, "void visit_node_operands(Visitor* visitor, NodeClass exclude, const Node* node) {\n"); + shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -16,11 +16,11 @@ void generate(Growy* g, json_object* src) { snake_name = to_snake_case(name); alloc = (void*) snake_name; } - growy_append_formatted(g, "\tcase %s_TAG: {\n", name); + shd_growy_append_formatted(g, "\tcase %s_TAG: {\n", name); json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); - growy_append_formatted(g, "\t\t%s payload = node->payload.%s;\n", name, snake_name); + shd_growy_append_formatted(g, "\t\t%s payload = node->payload.%s;\n", name, snake_name); for (size_t j = 0; j < json_object_array_length(ops); j++) { json_object* op = json_object_array_get_idx(ops, j); String op_name = json_object_get_string(json_object_object_get(op, "name")); @@ -31,21 +31,21 @@ void generate(Growy* g, json_object* src) { bool list = json_object_get_boolean(json_object_object_get(op, "list")); bool ignore = json_object_get_boolean(json_object_object_get(op, "ignore")); if (!ignore) { - growy_append_formatted(g, "\t\tif ((exclude & Nc%s) == 0)\n", class_cap); + shd_growy_append_formatted(g, "\t\tif ((exclude & Nc%s) == 0)\n", class_cap); if (list) - growy_append_formatted(g, "\t\t\tvisit_ops(visitor, Nc%s, \"%s\", payload.%s);\n", class_cap, op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tvisit_ops(visitor, Nc%s, \"%s\", payload.%s);\n", class_cap, op_name, op_name); else - growy_append_formatted(g, "\t\t\tvisit_op(visitor, Nc%s, \"%s\", payload.%s, 0);\n", class_cap, op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tvisit_op(visitor, Nc%s, \"%s\", payload.%s, 0);\n", class_cap, op_name, op_name); } free((void*) class_cap); } } - growy_append_formatted(g, "\t\tbreak;\n"); - growy_append_formatted(g, "\t}\n", name); + shd_growy_append_formatted(g, "\t\tbreak;\n"); + shd_growy_append_formatted(g, "\t}\n", name); if (alloc) free(alloc); } - growy_append_formatted(g, "\t\tdefault: assert(false);\n"); - growy_append_formatted(g, "\t}\n"); - growy_append_formatted(g, "}\n\n"); + shd_growy_append_formatted(g, "\t\tdefault: assert(false);\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "}\n\n"); } diff --git a/src/shady/ir.c b/src/shady/ir.c index 56b2d3acf..789e40fcf 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -36,13 +36,13 @@ IrArena* new_ir_arena(const ArenaConfig* config) { .nodes_set = shd_new_set(Nodes, (HashFn) hash_nodes, (CmpFn) compare_nodes), .strings_set = shd_new_set(Strings, (HashFn) hash_strings, (CmpFn) compare_strings), - .ids = new_growy(), + .ids = shd_new_growy(), }; return arena; } const Node* get_node_by_id(const IrArena* a, NodeId id) { - return ((const Node**) growy_data(a->ids))[id]; + return ((const Node**) shd_growy_data(a->ids))[id]; } void destroy_ir_arena(IrArena* arena) { @@ -56,7 +56,7 @@ void destroy_ir_arena(IrArena* arena) { shd_destroy_dict(arena->nodes_set); shd_destroy_dict(arena->node_set); shd_destroy_arena(arena->arena); - destroy_growy(arena->ids); + shd_destroy_growy(arena->ids); free(arena); } @@ -65,8 +65,8 @@ const ArenaConfig* get_arena_config(const IrArena* a) { } NodeId allocate_node_id(IrArena* arena, const Node* n) { - growy_append_object(arena->ids, n); - return growy_size(arena->ids) / sizeof(const Node*); + shd_growy_append_object(arena->ids, n); + return shd_growy_size(arena->ids) / sizeof(const Node*); } Nodes nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { @@ -205,7 +205,7 @@ Strings import_strings(IrArena* dst_arena, Strings old_strings) { return strings(dst_arena, count, arr); } -void format_string_internal(const char* str, va_list args, void* uptr, void callback(void*, size_t, char*)); +void shd_format_string_internal(const char* str, va_list args, void* uptr, void callback(void*, size_t, char*)); typedef struct { IrArena* a; @@ -222,7 +222,7 @@ String format_string_interned(IrArena* arena, const char* str, ...) { InternInArenaPayload p = { .a = arena, .result = &result }; va_list args; va_start(args, str); - format_string_internal(str, args, &p, (void (*)(void*, size_t, char*)) intern_in_arena); + shd_format_string_internal(str, args, &p, (void (*)(void*, size_t, char*)) intern_in_arena); va_end(args); return result; } diff --git a/src/shady/node.c b/src/shady/node.c index 6fd6b438a..5ac7fb583 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -56,7 +56,7 @@ double get_float_literal_value(FloatLiteral literal) { switch (literal.width) { case FloatTy16: error_print("TODO: fp16 literals"); - error_die(); + shd_error_die(); SHADY_UNREACHABLE; break; case FloatTy32: { diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 102bd2046..4950e9e75 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -28,7 +28,7 @@ const Node* import_node(Rewriter* r, const Node* node) { error_print(" vs "); log_node(ERROR, imported_t); error_print(".\n"); - error_die(); + shd_error_die(); } if (node->tag != existing->tag) { error_print("Incompatible node types for to-be-merged declaration: %s ", get_declaration_name(node)); @@ -36,7 +36,7 @@ const Node* import_node(Rewriter* r, const Node* node) { error_print(" vs "); error_print("%s", node_tags[node->tag]); error_print(".\n"); - error_die(); + shd_error_die(); } switch (is_declaration(node)) { case NotADeclaration: assert(false); diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 185768a26..89a1e37be 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -90,7 +90,7 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* if (!ctx->cfg) { error_print("LCSSA: Trying to process an abstraction that's not part of a function ('%s')!", get_abstraction_name(old)); log_module(ERROR, ctx->config, ctx->rewriter.src_module); - error_die(); + shd_error_die(); } const CFNode* n = cfg_lookup(ctx->cfg, old); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index fe2722456..2de976d06 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -95,7 +95,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.stack_size_on_entry = gen_get_stack_size(bb); set_value_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); - Node* nom_t = nominal_type(m, empty(a), format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); + Node* nom_t = nominal_type(m, empty(a), shd_format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); VContext vctx = { .visitor = { .visit_node_fn = (VisitNodeFn) search_operand_for_alloca, @@ -134,7 +134,7 @@ static const Node* process(Context* ctx, const Node* node) { log_node(ERROR, node); error_print(", most likely this means this alloca was not found in the first block of a function.\n"); log_module(DEBUG, ctx->config, ctx->rewriter.src_module); - error_die(); + shd_error_die(); } BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, node->payload.stack_alloc.mem)); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index ccd742d3f..66bf647bb 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -143,7 +143,7 @@ static const Node* process_node(Context* ctx, const Node* node) { error_print("Scoping error: Failed to find a dominating selection construct for "); log_node(ERROR, node); error_print(".\n"); - error_die(); + shd_error_die(); } Nodes* jps = shd_dict_find_value(const Node*, Nodes, ctx->structured_join_tokens, selection_instr); @@ -177,7 +177,7 @@ static const Node* process_node(Context* ctx, const Node* node) { error_print("Scoping error: Failed to find a dominating loop construct for "); log_node(ERROR, node); error_print(".\n"); - error_die(); + shd_error_die(); } Nodes* jps = shd_dict_find_value(const Node*, Nodes, ctx->structured_join_tokens, loop_start); @@ -211,7 +211,7 @@ static const Node* process_node(Context* ctx, const Node* node) { error_print("Scoping error: Failed to find a dominating loop construct for "); log_node(ERROR, node); error_print(".\n"); - error_die(); + shd_error_die(); } Nodes* jps = shd_dict_find_value(const Node*, Nodes, ctx->structured_join_tokens, loop_start); diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 776cb91b7..c8318a54b 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -51,7 +51,7 @@ static const Node* generate_arg_struct(Rewriter* rewriter, const Node* old_entry Nodes annotations = mk_nodes(a, annotation_value(a, (AnnotationValue) { .name = "EntryPointArgs", .value = fn_addr_helper(a, new_entry_point) })); const Node* type = generate_arg_struct_type(rewriter, old_entry_point->payload.fun.params); - String name = format_string_arena(a->arena, "__%s_args", old_entry_point->payload.fun.name); + String name = shd_format_string_arena(a->arena, "__%s_args", old_entry_point->payload.fun.name); Node* var = global_var(rewriter->dst_module, annotations, type, name, AsExternal); return ref_decl_helper(a, var); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 3dd5d6cc2..2a28f9678 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -182,7 +182,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element if (needs_patch) { original_word = gen_load(bb, gen_lea(bb, arr, zero, singleton(base_offset))); error_print("TODO"); - error_die(); + shd_error_die(); // word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded }*/ const Node* word = value; @@ -270,7 +270,7 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Type* return_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && is_addr_space_uniform(a, as)), .type = element_type }); Nodes return_ts = ser ? empty(a) : singleton(return_value_t); - String name = format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", get_address_space_name(as), uniform_address ? "uniform" : "varying", name_type_safe(a, element_type)); + String name = shd_format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", get_address_space_name(as), uniform_address ? "uniform" : "varying", name_type_safe(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); @@ -389,7 +389,7 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect Module* m = ctx->rewriter.dst_module; String as_name = get_address_space_name(as); - Node* global_struct_t = nominal_type(m, singleton(annotation(a, (Annotation) { .name = "Generated" })), format_string_arena(a->arena, "globals_physical_%s_t", as_name)); + Node* global_struct_t = nominal_type(m, singleton(annotation(a, (Annotation) { .name = "Generated" })), shd_format_string_arena(a->arena, "globals_physical_%s_t", as_name)); LARRAY(String, member_names, collected.count); LARRAY(const Type*, member_tys, collected.count); @@ -476,7 +476,7 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { .size = ref_decl_helper(a, constant_decl) }); - Node* words_array = global_var(m, append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical"})), words_array_type, format_string_arena(a->arena, "memory_%s", as_name), as); + Node* words_array = global_var(m, append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical"})), words_array_type, shd_format_string_arena(a->arena, "memory_%s", as_name), as); *get_emulated_as_word_array(ctx, as) = ref_decl_helper(a, words_array); } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 7dddc4112..176b1e6ac 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -40,7 +40,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { const Node* value_param = push ? param(a, qualified_t, "value") : NULL; Nodes params = push ? singleton(value_param) : empty(a); Nodes return_ts = push ? empty(a) : singleton(qualified_t); - String name = format_string_arena(a->arena, "generated_%s_%s", push ? "push" : "pop", name_type_safe(a, element_type)); + String name = shd_format_string_arena(a->arena, "generated_%s_%s", push ? "push" : "pop", name_type_safe(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 8646278b3..0dccec30e 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -99,7 +99,7 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* scope, const Node* log_string(ERROR, "subgroup_first emulation is not supported for "); log_node(ERROR, t); log_string(ERROR, ".\n"); - error_die(); + shd_error_die(); } static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* scope, const Node* src) { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 2069e9ad9..b62cc6ed6 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -140,7 +140,7 @@ static const Node* process(Context* ctx, const Node* old) { new_annotations = append_nodes(a, new_annotations, annotation_value(a, (AnnotationValue) { .name = "FnId", .value = lower_fn_addr(ctx, old) })); new_annotations = append_nodes(a, new_annotations, annotation(a, (Annotation) { .name = "Leaf" })); - String new_name = format_string_arena(a->arena, "%s_indirect", old->payload.fun.name); + String new_name = shd_format_string_arena(a->arena, "%s_indirect", old->payload.fun.name); Node* fun = function(ctx->rewriter.dst_module, nodes(a, 0, NULL), new_name, filter_out_annotation(a, new_annotations, "EntryPoint"), nodes(a, 0, NULL)); register_processed(&ctx->rewriter, old, fun); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 9ceecdfcd..af5c12696 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -69,7 +69,7 @@ static const Node* process(Context* ctx, const Node* node) { // recreate the old entry point, but this time it's not the entry point anymore Nodes nannotations = filter_out_annotation(a, wannotations, "EntryPoint"); Nodes nparams = recreate_params(&ctx->rewriter, node->payload.fun.params); - Node* inner = function(m, nparams, format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, empty(a)); + Node* inner = function(m, nparams, shd_format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, empty(a)); register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); register_processed(&ctx->rewriter, get_abstraction_mem(node), get_abstraction_mem(inner)); set_abstraction_body(inner, recreate_node_identity(&ctx->rewriter, node->payload.fun.body)); diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 4305e6411..98ca7e6da 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -176,7 +176,7 @@ static const Node* process(Context* ctx, const Node* node) { // Prepare a join point to replace the old function return Nodes nyield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); - const Node* join_point = param(a, qualified_type_helper(jp_type, true), format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); + const Node* join_point = param(a, qualified_type_helper(jp_type, true), shd_format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); Node* control_case = case_(a, singleton(join_point)); const Node* nbody = inline_call(ctx, ocallee, get_abstraction_mem(control_case), nargs, join_point); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 02f9be75b..b30545d31 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -163,7 +163,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); - Node* wrapper = basic_block(arena, exit_wrapper_params, format_string_arena(arena->arena, "exit_wrapper_%d", i)); + Node* wrapper = basic_block(arena, exit_wrapper_params, shd_format_string_arena(arena->arena, "exit_wrapper_%d", i)); exits[i].wrapper = wrapper; } @@ -258,7 +258,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; - Node* exit_bb = basic_block(arena, empty(arena), format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); + Node* exit_bb = basic_block(arena, empty(arena), shd_format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); const Node* recreated_exit = rewrite_node(rewriter, exiting_node->node); @@ -431,7 +431,7 @@ static const Node* process_node(Context* ctx, const Node* node) { .yield_types = yield_types }), true), "jp_postdom"); - Node* pre_join = basic_block(a, exit_args, format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction) , get_abstraction_name_safe(post_dominator))); + Node* pre_join = basic_block(a, exit_args, shd_format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction), get_abstraction_name_safe(post_dominator))); set_abstraction_body(pre_join, join(a, (Join) { .join_point = join_token, .args = exit_args, diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 9eadc1cd7..0d4765973 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -227,7 +227,7 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed }); const Node* join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); - Node* wrapper = basic_block(a, wrapper_params, format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); + Node* wrapper = basic_block(a, wrapper_params, shd_format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); wrapper->payload.basic_block.body = join(a, (Join) { .args = join_args, .join_point = join_token, diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index d94c17af7..f59dd1b8a 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -32,7 +32,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); if (!ctx2.disable_lowering) { ctx2.stack_size_on_entry = gen_get_stack_size(bb); - set_value_name((Node*) ctx2.stack_size_on_entry, format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun))); + set_value_name((Node*) ctx2.stack_size_on_entry, shd_format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun))); } register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); if (node->payload.fun.body) diff --git a/src/shady/print.c b/src/shady/print.c index 3befa2e43..49997421e 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -52,7 +52,7 @@ static PrinterCtx make_printer_ctx(Printer* printer, NodePrintConfig config) { .printer = printer, .config = config, .emitted = shd_new_dict(const Node*, String, (HashFn) hash_node, (CmpFn) compare_node), - .root_growy = new_growy(), + .root_growy = shd_new_growy(), }; ctx.root_printer = open_growy_as_printer(ctx.root_growy); return ctx; @@ -83,23 +83,23 @@ void print_node(Printer* printer, NodePrintConfig config, const Node* node) { } void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* p = open_growy_as_printer(g); if (node) print(p, "%%%d ", node->id); print_node(p, (NodePrintConfig) {.reparseable = true}, node); destroy_printer(p); - *size = growy_size(g); - *str_ptr = growy_deconstruct(g); + *size = shd_growy_size(g); + *str_ptr = shd_growy_deconstruct(g); } void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* p = open_growy_as_printer(g); print_module(p, (NodePrintConfig) {.reparseable = true,}, mod); destroy_printer(p); - *size = growy_size(g); - *str_ptr = growy_deconstruct(g); + *size = shd_growy_size(g); + *str_ptr = shd_growy_deconstruct(g); } void dump_node(const Node* node) { @@ -264,7 +264,7 @@ static void print_basic_block(PrinterCtx* ctx, const CFNode* node) { } static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { - Growy* g = new_growy(); + Growy* g = shd_new_growy(); Printer* p = open_growy_as_printer(g); CFNode* cfnode = ctx->cfg ? cfg_lookup(ctx->cfg, abs) : NULL; if (cfnode) @@ -273,7 +273,7 @@ static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { emit_node(ctx, get_abstraction_body(abs)); if (cfnode) { - Growy* g2 = new_growy(); + Growy* g2 = shd_new_growy(); Printer* p2 = open_growy_as_printer(g2); size_t count = cfnode->dominates->elements_count; for (size_t i = 0; i < count; i++) { @@ -1034,7 +1034,7 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { } shd_dict_insert(const Node*, String, ctx->emitted, node, r); - Growy* g = new_growy(); + Growy* g = shd_new_growy(); PrinterCtx ctx2 = *ctx; ctx2.printer = open_growy_as_printer(g); bool print_inline = print_node_impl(&ctx2, node); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 11e129076..308d2c255 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -353,7 +353,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { log_string(ERROR, "Can't rewrite: "); log_node(ERROR, node); log_string(ERROR, ", params should be rewritten by the abstraction rewrite logic"); - error_die(); + shd_error_die(); case BasicBlock_TAG: { Nodes params = recreate_params(rewriter, node->payload.basic_block.params); register_processed_list(rewriter, node->payload.basic_block.params, params); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index e89576697..536816e45 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -169,7 +169,7 @@ const Node* get_or_create_builtin(Module* m, Builtin b, String n) { AddressSpace as = get_builtin_as(b); IrArena* a = get_module_arena(m); - decl = global_var(m, singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, get_builtin_name(b)))), get_builtin_type(a, b), n ? n : format_string_arena(a->arena, "builtin_%s", get_builtin_name(b)), as); + decl = global_var(m, singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, get_builtin_name(b)))), get_builtin_type(a, b), n ? n : shd_format_string_arena(a->arena, "builtin_%s", get_builtin_name(b)), as); return decl; } diff --git a/src/shady/type.c b/src/shady/type.c index cffafd1e9..c9ea8ec96 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -195,11 +195,11 @@ String name_type_safe(IrArena* arena, const Type* t) { case Type_NoRet_TAG: return "no_ret"; case Type_Int_TAG: { if (t->payload.int_type.is_signed) - return format_string_arena(arena->arena, "i%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); + return shd_format_string_arena(arena->arena, "i%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); else - return format_string_arena(arena->arena, "u%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); + return shd_format_string_arena(arena->arena, "u%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); } - case Type_Float_TAG: return format_string_arena(arena->arena, "f%s", ((String[]) { "16", "32", "64" })[t->payload.float_type.width]); + case Type_Float_TAG: return shd_format_string_arena(arena->arena, "f%s", ((String[]) { "16", "32", "64" })[t->payload.float_type.width]); case Type_Bool_TAG: return "bool"; case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; default: break; @@ -378,7 +378,7 @@ const Type* check_type_pack_type(IrArena* arena, PackType pack_type) { const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { if (!arena->config.address_spaces[ptr_type.address_space].allowed) { error_print("Address space %s is not allowed in this arena\n", get_address_space_name(ptr_type.address_space)); - error_die(); + shd_error_die(); } assert(ptr_type.pointed_type && "Shady does not support untyped pointers, but can infer them, see infer.c"); if (ptr_type.pointed_type) { @@ -1253,7 +1253,7 @@ const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_var error_print(" instead of the expected "); log_node(ERROR, t); error_print(".\n"); - error_die(); + shd_error_die(); } } diff --git a/vcc/vcc.c b/vcc/vcc.c index 77356a731..9985e90e3 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -31,7 +31,7 @@ int main(int argc, char** argv) { vcc_check_clang(); if (vcc_options.only_run_clang) - vcc_options.tmp_filename = format_string_new("%s", args.output_filename); + vcc_options.tmp_filename = shd_format_string_new("%s", args.output_filename); vcc_run_clang(&vcc_options, shd_list_count(args.input_filenames), shd_read_list(String, args.input_filenames)); if (!vcc_options.only_run_clang) { diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 2154f3cc0..3b5a179f3 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -24,7 +24,7 @@ void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { else if (strcmp(argv[i], "--vcc-keep-tmp-file") == 0) { argv[i] = NULL; options->delete_tmp_file = false; - options->tmp_filename = format_string_new("vcc_tmp.ll"); + options->tmp_filename = shd_format_string_new("vcc_tmp.ll"); continue; } else if (strcmp(argv[i], "--vcc-include-path") == 0) { argv[i] = NULL; @@ -33,7 +33,7 @@ void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { error("Missing subgroup size name"); if (options->include_path) free((void*) options->include_path); - options->include_path = format_string_new("%s", argv[i]); + options->include_path = shd_format_string_new("%s", argv[i]); continue; } else if (strcmp(argv[i], "--only-run-clang") == 0) { argv[i] = NULL; @@ -62,9 +62,9 @@ VccConfig vcc_init_config(CompilerConfig* compiler_config) { compiler_config->input_cf.has_scope_annotations = true; String self_path = get_executable_location(); - String working_dir = strip_path(self_path); + String working_dir = shd_strip_path(self_path); if (!vcc_config.include_path) { - vcc_config.include_path = format_string_new("%s/../share/vcc/include/", working_dir); + vcc_config.include_path = shd_format_string_new("%s/../share/vcc/include/", working_dir); } free((void*) working_dir); free((void*) self_path); @@ -79,18 +79,18 @@ void destroy_vcc_options(VccConfig vcc_options) { } void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* input_filenames) { - Growy* g = new_growy(); - growy_append_string(g, VCC_CLANG); + Growy* g = shd_new_growy(); + shd_growy_append_string(g, VCC_CLANG); String self_path = get_executable_location(); - String working_dir = strip_path(self_path); - growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options->include_path); + String working_dir = shd_strip_path(self_path); + shd_growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options->include_path); free((void*) working_dir); free((void*) self_path); if (!vcc_options->tmp_filename) { if (vcc_options->only_run_clang) { error_print("Please provide an output filename.\n"); - error_die(); + shd_error_die(); } char* tmp_alloc; vcc_options->tmp_filename = tmp_alloc = malloc(33); @@ -105,34 +105,34 @@ void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* inpu tmp_alloc[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % (10 + 26 * 2)]; } } - growy_append_formatted(g, " -o %s", vcc_options->tmp_filename); + shd_growy_append_formatted(g, " -o %s", vcc_options->tmp_filename); for (size_t i = 0; i < num_source_files; i++) { String filename = input_filenames[i]; - growy_append_string(g, " \""); - growy_append_bytes(g, strlen(filename), filename); - growy_append_string(g, "\""); + shd_growy_append_string(g, " \""); + shd_growy_append_bytes(g, strlen(filename), filename); + shd_growy_append_string(g, "\""); } - growy_append_bytes(g, 1, "\0"); - char* arg_string = growy_deconstruct(g); + shd_growy_append_bytes(g, 1, "\0"); + char* arg_string = shd_growy_deconstruct(g); info_print("built command: %s\n", arg_string); FILE* stream = popen(arg_string, "r"); free(arg_string); - Growy* json_bytes = new_growy(); + Growy* json_bytes = shd_new_growy(); while (true) { char buf[4096]; int read = fread(buf, 1, sizeof(buf), stream); if (read == 0) break; - growy_append_bytes(json_bytes, read, buf); + shd_growy_append_bytes(json_bytes, read, buf); } - growy_append_string(json_bytes, "\0"); - char* llvm_result = growy_deconstruct(json_bytes); + shd_growy_append_string(json_bytes, "\0"); + char* llvm_result = shd_growy_deconstruct(json_bytes); int clang_returned = pclose(stream); info_print("Clang returned %d and replied: \n%s", clang_returned, llvm_result); free(llvm_result); @@ -143,7 +143,7 @@ void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* inpu Module* vcc_parse_back_into_module(CompilerConfig* config, VccConfig* vcc_options, String module_name) { size_t len; char* llvm_ir; - if (!read_file(vcc_options->tmp_filename, &len, &llvm_ir)) + if (!shd_read_file(vcc_options->tmp_filename, &len, &llvm_ir)) exit(InputFileIOError); Module* mod; driver_load_source_file(config, SrcLLVM, len, llvm_ir, module_name, &mod); From 92fb63373ce8b2ff3582854fb743e9e94fc1e5d7 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 15:23:22 +0200 Subject: [PATCH 596/693] add shd_ prefix to portability.h --- samples/aobench/ao_main.c | 12 ++++++------ src/common/portability.c | 6 +++--- src/common/portability.h | 10 +++++----- src/common/test_dict.c | 2 +- src/driver/slim.c | 2 +- src/runtime/vulkan/vk_runtime_program.c | 4 ++-- test/opt/opt_oracle.c | 2 +- vcc/vcc.c | 2 +- vcc/vcc_lib.c | 4 ++-- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 143a121a5..f6e87b81b 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -43,7 +43,7 @@ void render_host(TEXEL_T* img, int w, int h, int nsubsamples) { Scalar* fimg = (Scalar *)malloc(sizeof(Scalar) * w * h * 3); memset((void *)fimg, 0, sizeof(Scalar) * w * h * 3); - uint64_t tsn = get_time_nano(); + uint64_t tsn = shd_get_time_nano(); Ctx ctx = get_init_context(); init_scene(&ctx); @@ -52,7 +52,7 @@ void render_host(TEXEL_T* img, int w, int h, int nsubsamples) { render_pixel(&ctx, x, y, w, h, nsubsamples, img); } } - uint64_t tpn = get_time_nano(); + uint64_t tpn = shd_get_time_nano(); info_print("reference rendering took %d us\n", (tpn - tsn) / 1000); } @@ -66,7 +66,7 @@ typedef struct { extern Vec3u builtin_NumWorkgroups; void render_ispc(TEXEL_T* img, int w, int h, int nsubsamples) { - uint64_t tsn = get_time_nano(); + uint64_t tsn = shd_get_time_nano(); Ctx ctx = get_init_context(); init_scene(&ctx); for (size_t i = 0; i < WIDTH; i++) { @@ -82,7 +82,7 @@ void render_ispc(TEXEL_T* img, int w, int h, int nsubsamples) { builtin_NumWorkgroups.z = 1; aobench_kernel(img); - uint64_t tpn = get_time_nano(); + uint64_t tpn = shd_get_time_nano(); info_print("ispc rendering took %d us\n", (tpn - tsn) / 1000); } #endif @@ -121,13 +121,13 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri // run it twice to compile everything and benefit from caches wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, NULL)); - uint64_t tsn = get_time_nano(); + uint64_t tsn = shd_get_time_nano(); uint64_t profiled_gpu_time = 0; ExtraKernelOptions extra_kernel_options = { .profiled_gpu_time = &profiled_gpu_time }; wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, &extra_kernel_options)); - uint64_t tpn = get_time_nano(); + uint64_t tpn = shd_get_time_nano(); info_print("device rendering took %dus (gpu time: %dus)\n", (tpn - tsn) / 1000, profiled_gpu_time / 1000); if (!import_memory) diff --git a/src/common/portability.c b/src/common/portability.c index 84200bed2..7b392be0c 100644 --- a/src/common/portability.c +++ b/src/common/portability.c @@ -15,7 +15,7 @@ #endif -void platform_specific_terminal_init_extras() { +void shd_platform_specific_terminal_init_extras(void) { #ifdef NEED_COLOR_FIX HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); if (handle != INVALID_HANDLE_VALUE) { @@ -38,7 +38,7 @@ uint64_t get_time_nano() { } #else #include -uint64_t get_time_nano() { +uint64_t shd_get_time_nano(void) { struct timespec t; timespec_get(&t, TIME_UTC); return t.tv_sec * 1000000000 + t.tv_nsec; @@ -54,7 +54,7 @@ uint64_t get_time_nano() { #include #include #endif -const char* get_executable_location(void) { +const char* shd_get_executable_location(void) { size_t len = 256; char* buf = calloc(len + 1, 1); #ifdef WIN32 diff --git a/src/common/portability.h b/src/common/portability.h index 097181906..c1e797fb4 100644 --- a/src/common/portability.h +++ b/src/common/portability.h @@ -31,7 +31,7 @@ static_assert(__STDC_VERSION__ >= 201112L, "C11 support is required to build sha #define SHADY_FALLTHROUGH __attribute__((fallthrough)); #endif -static inline void* alloc_aligned(size_t size, size_t alignment) { +static inline void* shd_alloc_aligned(size_t size, size_t alignment) { #ifdef _WIN32 return _aligned_malloc(size, alignment); #else @@ -39,7 +39,7 @@ static inline void* alloc_aligned(size_t size, size_t alignment) { #endif } -static inline void free_aligned(void* ptr) { +static inline void shd_free_aligned(void* ptr) { #ifdef _WIN32 _aligned_free(ptr); #else @@ -48,9 +48,9 @@ static inline void free_aligned(void* ptr) { } #include -uint64_t get_time_nano(); -const char* get_executable_location(void); +uint64_t shd_get_time_nano(void); +const char* shd_get_executable_location(void); -void platform_specific_terminal_init_extras(); +void shd_platform_specific_terminal_init_extras(void); #endif diff --git a/src/common/test_dict.c b/src/common/test_dict.c index d1b2095c7..0f4467d38 100644 --- a/src/common/test_dict.c +++ b/src/common/test_dict.c @@ -27,7 +27,7 @@ void shuffle(int arr[]) { } int main(int argc, char** argv) { - srand((int) get_time_nano()); + srand((int) shd_get_time_nano()); struct Dict* d = shd_new_set(int, (HashFn) bad_hash_i32, (CmpFn) compare_i32); int arr[TEST_ENTRIES]; diff --git a/src/driver/slim.c b/src/driver/slim.c index 38d4668fd..61d4c5fc5 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -7,7 +7,7 @@ #include "portability.h" int main(int argc, char** argv) { - platform_specific_terminal_init_extras(); + shd_platform_specific_terminal_init_extras(); DriverConfig args = default_driver_config(); cli_parse_driver_arguments(&args, &argc, argv); diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 83c3c742c..6c4662005 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -448,7 +448,7 @@ static bool prepare_resources(VkrSpecProgram* program) { if (resource->host_backed_allocation) { assert(vkr_can_import_host_memory(program->device)); - resource->host_ptr = alloc_aligned(resource->size, program->device->caps.properties.external_memory_host.minImportedHostPointerAlignment); + resource->host_ptr = shd_alloc_aligned(resource->size, program->device->caps.properties.external_memory_host.minImportedHostPointerAlignment); resource->buffer = vkr_import_buffer_host(program->device, resource->host_ptr, resource->size); } else { resource->buffer = vkr_allocate_buffer_device(program->device, resource->size); @@ -521,7 +521,7 @@ void destroy_specialized_program(VkrSpecProgram* spec) { if (resource->buffer) vkr_destroy_buffer(resource->buffer); if (resource->host_ptr && resource->host_backed_allocation) - free_aligned(resource->host_ptr); + shd_free_aligned(resource->host_ptr); } free(spec->resources.resources); vkDestroyDescriptorPool(spec->device->device, spec->descriptor_pool, NULL); diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 42772f76c..69656f4cd 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -74,7 +74,7 @@ static Module* oracle_passes(const CompilerConfig* config, Module* initial_mod) } int main(int argc, char** argv) { - platform_specific_terminal_init_extras(); + shd_platform_specific_terminal_init_extras(); DriverConfig args = default_driver_config(); cli_parse_driver_arguments(&args, &argc, argv); diff --git a/vcc/vcc.c b/vcc/vcc.c index 9985e90e3..c0a95eeeb 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -10,7 +10,7 @@ #include int main(int argc, char** argv) { - platform_specific_terminal_init_extras(); + shd_platform_specific_terminal_init_extras(); DriverConfig args = default_driver_config(); VccConfig vcc_options = vcc_init_config(&args.config); diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 3b5a179f3..4039f1212 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -61,7 +61,7 @@ VccConfig vcc_init_config(CompilerConfig* compiler_config) { compiler_config->input_cf.add_scope_annotations = true; compiler_config->input_cf.has_scope_annotations = true; - String self_path = get_executable_location(); + String self_path = shd_get_executable_location(); String working_dir = shd_strip_path(self_path); if (!vcc_config.include_path) { vcc_config.include_path = shd_format_string_new("%s/../share/vcc/include/", working_dir); @@ -81,7 +81,7 @@ void destroy_vcc_options(VccConfig vcc_options) { void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* input_filenames) { Growy* g = shd_new_growy(); shd_growy_append_string(g, VCC_CLANG); - String self_path = get_executable_location(); + String self_path = shd_get_executable_location(); String working_dir = shd_strip_path(self_path); shd_growy_append_formatted(g, " -c -emit-llvm -S -g -O0 -ffreestanding -Wno-main-return-type -Xclang -fpreserve-vec3-type --target=spir64-unknown-unknown -isystem\"%s\" -D__SHADY__=1", vcc_options->include_path); free((void*) working_dir); From 02566a2d5b59fc530357ea3e2266e4fcbccdcbda Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 15:36:29 +0200 Subject: [PATCH 597/693] added shd_ prefix to print.h --- src/backend/c/emit_c.c | 110 +++++++++++------------ src/backend/c/emit_c_control_flow.c | 88 +++++++++---------- src/backend/c/emit_c_type.c | 54 ++++++------ src/backend/c/emit_c_value.c | 74 ++++++++-------- src/common/printer.c | 48 ++++------ src/common/printer.h | 22 +++-- src/driver/cli.c | 4 +- src/runtime/runtime_app_common.h | 4 +- src/shady/analysis/cfg_dump.c | 38 ++++---- src/shady/generator_print.c | 12 +-- src/shady/print.c | 130 ++++++++++++++-------------- 11 files changed, 281 insertions(+), 303 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 01192fc7a..6ca8e01fb 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -112,7 +112,7 @@ CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Ty const Type* ut = qualified_type_helper(ptr_type, true); const Type* vt = qualified_type_helper(ptr_type, false); String lhs = c_emit_type(emitter, vt, interm); - print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, c_emit_type(emitter, ut, NULL), to_cvalue(emitter, term)); + shd_print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, c_emit_type(emitter, ut, NULL), to_cvalue(emitter, term)); return term_from_cvalue(interm); } @@ -139,20 +139,20 @@ void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const String decl = c_emit_type(emitter, t, center); if (initializer) - print(block_printer, "\n%s%s = %s;", prefix, decl, to_cvalue(emitter, *initializer)); + shd_print(block_printer, "\n%s%s = %s;", prefix, decl, to_cvalue(emitter, *initializer)); else - print(block_printer, "\n%s%s;", prefix, decl); + shd_print(block_printer, "\n%s%s;", prefix, decl); } void c_emit_pack_code(Printer* p, Strings src, String dst) { for (size_t i = 0; i < src.count; i++) { - print(p, "\n%s->_%d = %s", dst, src.strings[i], i); + shd_print(p, "\n%s->_%d = %s", dst, src.strings[i], i); } } void c_emit_unpack_code(Printer* p, String src, Strings dst) { for (size_t i = 0; i < dst.count; i++) { - print(p, "\n%s = %s->_%d", dst.strings[i], src, i); + shd_print(p, "\n%s = %s->_%d", dst.strings[i], src, i); } } @@ -230,15 +230,15 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String } if (init) - print(emitter->fn_decls, "\n%s%s = %s;", prefix, c_emit_type(emitter, type, name), init); + shd_print(emitter->fn_decls, "\n%s%s = %s;", prefix, c_emit_type(emitter, type, name), init); else - print(emitter->fn_decls, "\n%s%s;", prefix, c_emit_type(emitter, type, name)); + shd_print(emitter->fn_decls, "\n%s%s;", prefix, c_emit_type(emitter, type, name)); //if (!has_forward_declarations(emitter->config.dialect) || !init) // return; // //String declaration = c_emit_type(emitter, type, decl_center); - //print(emitter->fn_decls, "\n%s;", declaration); + //shd_print(emitter->fn_decls, "\n%s;", declaration); } void c_emit_decl(Emitter* emitter, const Node* decl) { @@ -336,11 +336,11 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { fn_body = shd_format_string_arena(emitter->arena->arena, "\n__shady_prepare_builtins();%s", fn_body); } } - print(emitter->fn_defs, "\n%s { ", head); - indent(emitter->fn_defs); - print(emitter->fn_defs, " %s", fn_body); - deindent(emitter->fn_defs); - print(emitter->fn_defs, "\n}"); + shd_print(emitter->fn_defs, "\n%s { ", head); + shd_printer_indent(emitter->fn_defs); + shd_print(emitter->fn_defs, " %s", fn_body); + shd_printer_deindent(emitter->fn_defs); + shd_print(emitter->fn_defs, "\n}"); destroy_scheduler(fn.scheduler); destroy_cfg(fn.cfg); @@ -348,7 +348,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { free(fn.instruction_printers); } - print(emitter->fn_decls, "\n%s;", head); + shd_print(emitter->fn_decls, "\n%s;", head); return; } case Constant_TAG: { @@ -364,7 +364,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { register_emitted_type(emitter, decl, emitted); switch (emitter->config.dialect) { case CDialect_ISPC: - default: print(emitter->type_decls, "\ntypedef %s;", c_emit_type(emitter, decl->payload.nom_type.body, emitted)); break; + default: shd_print(emitter->type_decls, "\ntypedef %s;", c_emit_type(emitter, decl->payload.nom_type.body, emitted)); break; case CDialect_GLSL: c_emit_nominal_type_body(emitter, shd_format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; } return; @@ -390,9 +390,9 @@ static Module* run_backend_specific_passes(const CompilerConfig* config, CEmitte static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { Growy* g = shd_new_growy(); - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); - print(p, "typedef struct __shady_PrivateGlobals {\n"); + shd_print(p, "typedef struct __shady_PrivateGlobals {\n"); Nodes decls = get_module_declarations(m); size_t count = 0; for (size_t i = 0; i < decls.count; i++) { @@ -402,17 +402,17 @@ static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { AddressSpace as = decl->payload.global_variable.address_space; if (as != AsPrivate) continue; - print(p, "%s;\n", c_emit_type(emitter, decl->payload.global_variable.type, decl->payload.global_variable.name)); + shd_print(p, "%s;\n", c_emit_type(emitter, decl->payload.global_variable.type, decl->payload.global_variable.name)); count++; } - print(p, "} __shady_PrivateGlobals;\n"); + shd_print(p, "} __shady_PrivateGlobals;\n"); if (count == 0) { - destroy_printer(p); + shd_destroy_printer(p); shd_destroy_growy(g); return NULL; } - return printer_growy_unwrap(p); + return shd_printer_growy_unwrap(p); } CEmitterConfig default_c_emitter_config(void) { @@ -434,9 +434,9 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module .compiler_config = compiler_config, .config = config, .arena = arena, - .type_decls = open_growy_as_printer(type_decls_g), - .fn_decls = open_growy_as_printer(fn_decls_g), - .fn_defs = open_growy_as_printer(fn_defs_g), + .type_decls = shd_new_printer_from_growy(type_decls_g), + .fn_decls = shd_new_printer_from_growy(fn_decls_g), + .fn_defs = shd_new_printer_from_growy(fn_defs_g), .emitted_terms = shd_new_dict(Node*, CTerm, (HashFn) hash_node, (CmpFn) compare_node), .emitted_types = shd_new_dict(Node*, String, (HashFn) hash_node, (CmpFn) compare_node), }; @@ -446,16 +446,16 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module emitter.total_workgroup_size = emitter.arena->config.specializations.workgroup_size[0]; emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[1]; emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[2]; - print(emitter.type_decls, "\ntypedef %s;\n", c_emit_type(&emitter, arr_type(arena, (ArrType) { + shd_print(emitter.type_decls, "\ntypedef %s;\n", c_emit_type(&emitter, arr_type(arena, (ArrType) { .size = int32_literal(arena, 3), .element_type = uint32_type(arena) }), "uvec3")); - print(emitter.fn_defs, shady_cuda_builtins_src); + shd_print(emitter.fn_defs, shady_cuda_builtins_src); String private_globals = collect_private_globals_in_struct(&emitter, mod); if (private_globals) { emitter.use_private_globals = true; - print(emitter.type_decls, private_globals); + shd_print(emitter.type_decls, private_globals); free((void*)private_globals); } } @@ -464,61 +464,61 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module for (size_t i = 0; i < decls.count; i++) c_emit_decl(&emitter, decls.nodes[i]); - destroy_printer(emitter.type_decls); - destroy_printer(emitter.fn_decls); - destroy_printer(emitter.fn_defs); + shd_destroy_printer(emitter.type_decls); + shd_destroy_printer(emitter.fn_decls); + shd_destroy_printer(emitter.fn_defs); Growy* final = shd_new_growy(); - Printer* finalp = open_growy_as_printer(final); + Printer* finalp = shd_new_printer_from_growy(final); if (emitter.config.dialect == CDialect_GLSL) { - print(finalp, "#version %d\n", emitter.config.glsl_version); + shd_print(finalp, "#version %d\n", emitter.config.glsl_version); } - print(finalp, "/* file generated by shady */\n"); + shd_print(finalp, "/* file generated by shady */\n"); switch (emitter.config.dialect) { case CDialect_ISPC: break; case CDialect_CUDA: { - print(finalp, "#define __shady_workgroup_size %d\n", emitter.total_workgroup_size); - print(finalp, "#define __shady_replicate_thread_local(v) { "); + shd_print(finalp, "#define __shady_workgroup_size %d\n", emitter.total_workgroup_size); + shd_print(finalp, "#define __shady_replicate_thread_local(v) { "); for (size_t i = 0; i < emitter.total_workgroup_size; i++) - print(finalp, "v, "); - print(finalp, "}\n"); - print(finalp, shady_cuda_prelude_src); + shd_print(finalp, "v, "); + shd_print(finalp, "}\n"); + shd_print(finalp, shady_cuda_prelude_src); break; } case CDialect_C11: - print(finalp, "\n#include "); - print(finalp, "\n#include "); - print(finalp, "\n#include "); - print(finalp, "\n#include "); - print(finalp, "\n#include "); + shd_print(finalp, "\n#include "); + shd_print(finalp, "\n#include "); + shd_print(finalp, "\n#include "); + shd_print(finalp, "\n#include "); + shd_print(finalp, "\n#include "); break; case CDialect_GLSL: if (emitter.need_64b_ext) - print(finalp, "#extension GL_ARB_gpu_shader_int64: require\n"); - print(finalp, "#define ubyte uint\n"); - print(finalp, "#define uchar uint\n"); - print(finalp, "#define ulong uint\n"); + shd_print(finalp, "#extension GL_ARB_gpu_shader_int64: require\n"); + shd_print(finalp, "#define ubyte uint\n"); + shd_print(finalp, "#define uchar uint\n"); + shd_print(finalp, "#define ulong uint\n"); if (emitter.config.glsl_version <= 120) - print(finalp, shady_glsl_120_polyfills_src); + shd_print(finalp, shady_glsl_120_polyfills_src); break; } - print(finalp, "\n/* types: */\n"); + shd_print(finalp, "\n/* types: */\n"); shd_growy_append_bytes(final, shd_growy_size(type_decls_g), shd_growy_data(type_decls_g)); - print(finalp, "\n/* declarations: */\n"); + shd_print(finalp, "\n/* declarations: */\n"); shd_growy_append_bytes(final, shd_growy_size(fn_decls_g), shd_growy_data(fn_decls_g)); - print(finalp, "\n/* definitions: */\n"); + shd_print(finalp, "\n/* definitions: */\n"); shd_growy_append_bytes(final, shd_growy_size(fn_defs_g), shd_growy_data(fn_defs_g)); - print(finalp, "\n"); - print(finalp, "\n"); - print(finalp, "\n"); + shd_print(finalp, "\n"); + shd_print(finalp, "\n"); + shd_print(finalp, "\n"); shd_growy_append_bytes(final, 1, "\0"); shd_destroy_growy(type_decls_g); @@ -530,7 +530,7 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module *output_size = shd_growy_size(final) - 1; *output = shd_growy_deconstruct(final); - destroy_printer(finalp); + shd_destroy_printer(finalp); if (new_mod) *new_mod = mod; diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index 71d442df9..8770c0dad 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -15,7 +15,7 @@ String c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { const Node* body = get_abstraction_body(abs); assert(body && is_terminator(body)); CFNode* cf_node = cfg_lookup(fn->cfg, abs); - Printer* p = open_growy_as_printer(shd_new_growy()); + Printer* p = shd_new_printer_from_growy(shd_new_growy()); fn->instruction_printers[cf_node->rpo_index] = p; //indent(p); @@ -27,10 +27,10 @@ String c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { }*/ //deindent(p); - // print(p, "\n"); + // shd_print(p, "\n"); fn->instruction_printers[cf_node->rpo_index] = NULL; - String s2 = printer_growy_unwrap(p); + String s2 = shd_printer_growy_unwrap(p); String s = string(emitter->arena, s2); free((void*)s2); return s; @@ -65,18 +65,18 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { String false_body = if_.if_false ? c_emit_body(&sub_emiter, fn, if_.if_false) : NULL; String tail = c_emit_body(emitter, fn, if_.tail); CValue condition = to_cvalue(emitter, c_emit_value(emitter, fn, if_.condition)); - print(p, "\nif (%s) { ", condition); - indent(p); - print(p, "%s", true_body); - deindent(p); - print(p, "\n}"); + shd_print(p, "\nif (%s) { ", condition); + shd_printer_indent(p); + shd_print(p, "%s", true_body); + shd_printer_deindent(p); + shd_print(p, "\n}"); if (if_.if_false) { assert(get_abstraction_params(if_.if_false).count == 0); - print(p, " else {"); - indent(p); - print(p, "%s", false_body); - deindent(p); - print(p, "\n}"); + shd_print(p, " else {"); + shd_printer_indent(p); + shd_print(p, "%s", false_body); + shd_printer_deindent(p); + shd_print(p, "\n}"); } Nodes results = get_abstraction_params(if_.tail); @@ -84,7 +84,7 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - print(p, "%s", tail); + shd_print(p, "%s", tail); } static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) { @@ -112,22 +112,22 @@ static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) bodies[i] = c_emit_body(&sub_emiter, fn, match.cases.nodes[i]); } for (size_t i = 0; i < match.cases.count; i++) { - print(p, "\n"); + shd_print(p, "\n"); if (!first) - print(p, "else "); - print(p, "if (%s == %s) { ", inspectee, literals[i]); - indent(p); - print(p, "%s", bodies[i]); - deindent(p); - print(p, "\n}"); + shd_print(p, "else "); + shd_print(p, "if (%s == %s) { ", inspectee, literals[i]); + shd_printer_indent(p); + shd_print(p, "%s", bodies[i]); + shd_printer_deindent(p); + shd_print(p, "\n}"); first = false; } if (match.default_case) { - print(p, "\nelse { "); - indent(p); - print(p, "%s", default_case_body); - deindent(p); - print(p, "\n}"); + shd_print(p, "\nelse { "); + shd_printer_indent(p); + shd_print(p, "%s", default_case_body); + shd_printer_deindent(p); + shd_print(p, "\n}"); } Nodes results = get_abstraction_params(match.tail); @@ -135,7 +135,7 @@ static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - print(p, "%s", tail); + shd_print(p, "%s", tail); } static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { @@ -159,18 +159,18 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { String body = c_emit_body(&sub_emiter, fn, loop.body); String tail = c_emit_body(emitter, fn, loop.tail); - print(p, "\nwhile(true) { "); - indent(p); - print(p, "%s", body); - deindent(p); - print(p, "\n}"); + shd_print(p, "\nwhile(true) { "); + shd_printer_indent(p); + shd_print(p, "%s", body); + shd_printer_deindent(p); + shd_print(p, "\n}"); Nodes results = get_abstraction_params(loop.tail); for (size_t i = 0; i < ephis.count; i++) { register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } - print(p, "%s", tail); + shd_print(p, "%s", tail); } static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_printer, const Node* terminator) { @@ -189,16 +189,16 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin case Terminator_Return_TAG: { Nodes args = terminator->payload.fn_ret.args; if (args.count == 0) { - print(block_printer, "\nreturn;"); + shd_print(block_printer, "\nreturn;"); } else if (args.count == 1) { - print(block_printer, "\nreturn %s;", to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[0]))); + shd_print(block_printer, "\nreturn %s;", to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[0]))); } else { String packed = unique_name(emitter->arena, "pack_return"); LARRAY(CValue, values, args.count); for (size_t i = 0; i < args.count; i++) values[i] = to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i])); c_emit_pack_code(block_printer, strings(emitter->arena, args.count, values), packed); - print(block_printer, "\nreturn %s;", packed); + shd_print(block_printer, "\nreturn %s;", packed); } break; } @@ -207,7 +207,7 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin Phis phis = emitter->phis.selection; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); + shd_print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); break; } @@ -216,8 +216,8 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin Phis phis = emitter->phis.loop_continue; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); - print(block_printer, "\ncontinue;"); + shd_print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); + shd_print(block_printer, "\ncontinue;"); break; } case MergeBreak_TAG: { @@ -225,21 +225,21 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin Phis phis = emitter->phis.loop_break; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); - print(block_printer, "\nbreak;"); + shd_print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); + shd_print(block_printer, "\nbreak;"); break; } case Terminator_Unreachable_TAG: { switch (emitter->config.dialect) { case CDialect_CUDA: case CDialect_C11: - print(block_printer, "\n__builtin_unreachable();"); + shd_print(block_printer, "\n__builtin_unreachable();"); break; case CDialect_ISPC: - print(block_printer, "\nassert(false);"); + shd_print(block_printer, "\nassert(false);"); break; case CDialect_GLSL: - print(block_printer, "\n//unreachable"); + shd_print(block_printer, "\n//unreachable"); break; } break; diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index dc347e411..c2b944ea0 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -26,21 +26,21 @@ String c_get_record_field_name(const Type* t, size_t i) { void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { assert(type->tag == RecordType_TAG); Growy* g = shd_new_growy(); - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); - print(p, "\n%s {", name); - indent(p); + shd_print(p, "\n%s {", name); + shd_printer_indent(p); for (size_t i = 0; i < type->payload.record_type.members.count; i++) { String member_identifier = c_get_record_field_name(type, i); - print(p, "\n%s;", c_emit_type(emitter, type->payload.record_type.members.nodes[i], member_identifier)); + shd_print(p, "\n%s;", c_emit_type(emitter, type->payload.record_type.members.nodes[i], member_identifier)); } - deindent(p); - print(p, "\n};\n"); + shd_printer_deindent(p); + shd_print(p, "\n};\n"); shd_growy_append_bytes(g, 1, (char[]) { '\0' }); - print(emitter->type_decls, shd_growy_data(g)); + shd_print(emitter->type_decls, shd_growy_data(g)); shd_destroy_growy(g); - destroy_printer(p); + shd_destroy_printer(p); } String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn) { @@ -51,42 +51,42 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons const Node* entry_point = fn ? lookup_annotation(fn, "EntryPoint") : NULL; Growy* paramg = shd_new_growy(); - Printer* paramp = open_growy_as_printer(paramg); + Printer* paramp = shd_new_printer_from_growy(paramg); Nodes dom = fn_type->payload.fn_type.param_types; if (dom.count == 0 && emitter->config.dialect == CDialect_C11) - print(paramp, "void"); + shd_print(paramp, "void"); else if (fn) { Nodes params = fn->payload.fun.params; assert(params.count == dom.count); if (emitter->use_private_globals && !entry_point) { - print(paramp, "__shady_PrivateGlobals* __shady_private_globals"); + shd_print(paramp, "__shady_PrivateGlobals* __shady_private_globals"); if (params.count > 0) - print(paramp, ", "); + shd_print(paramp, ", "); } for (size_t i = 0; i < dom.count; i++) { String param_name; String variable_name = get_value_name_unsafe(fn->payload.fun.params.nodes[i]); param_name = format_string_interned(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); - print(paramp, c_emit_type(emitter, params.nodes[i]->type, param_name)); + shd_print(paramp, c_emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { - print(paramp, ", "); + shd_print(paramp, ", "); } } } else { if (emitter->use_private_globals) { - print(paramp, "__shady_PrivateGlobals*"); + shd_print(paramp, "__shady_PrivateGlobals*"); if (dom.count > 0) - print(paramp, ", "); + shd_print(paramp, ", "); } for (size_t i = 0; i < dom.count; i++) { - print(paramp, c_emit_type(emitter, dom.nodes[i], "")); + shd_print(paramp, c_emit_type(emitter, dom.nodes[i], "")); if (i + 1 < dom.count) { - print(paramp, ", "); + shd_print(paramp, ", "); } } } shd_growy_append_bytes(paramg, 1, (char[]) { 0 }); - const char* parameters = printer_growy_unwrap(paramp); + const char* parameters = shd_printer_growy_unwrap(paramp); switch (emitter->config.dialect) { default: center = shd_format_string_arena(emitter->arena->arena, "(%s)(%s)", center, parameters); @@ -251,26 +251,26 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { emitted = unique_name(emitter->arena, "Array"); String prefixed = shd_format_string_arena(emitter->arena->arena, "struct %s", emitted); Growy* g = shd_new_growy(); - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); const Node* size = type->payload.arr_type.size; if (!size && emitter->config.decay_unsized_arrays) return c_emit_type(emitter, type->payload.arr_type.element_type, center); - print(p, "\n%s {", prefixed); - indent(p); + shd_print(p, "\n%s {", prefixed); + shd_printer_indent(p); String inner_decl_rhs; if (size) inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[%zu]", get_int_literal_value(*resolve_to_int_literal(size), false)); else inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[0]"); - print(p, "\n%s;", c_emit_type(emitter, type->payload.arr_type.element_type, inner_decl_rhs)); - deindent(p); - print(p, "\n};\n"); + shd_print(p, "\n%s;", c_emit_type(emitter, type->payload.arr_type.element_type, inner_decl_rhs)); + shd_printer_deindent(p); + shd_print(p, "\n};\n"); shd_growy_append_bytes(g, 1, (char[]) { '\0' }); - String subdecl = printer_growy_unwrap(p); - print(emitter->type_decls, subdecl); + String subdecl = shd_printer_growy_unwrap(p); + shd_print(emitter->type_decls, subdecl); free_tmp_str(subdecl); // ditto from RecordType diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index ead9a0935..4f1bdfb30 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -39,17 +39,17 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e if (is_stringy && i == c.count - 1) break; if (isprint(tmp[i])) - print(p, "%c", tmp[i]); + shd_print(p, "%c", tmp[i]); else - print(p, "\\x%02x", tmp[i]); + shd_print(p, "\\x%02x", tmp[i]); } free(tmp); return is_stringy ? StringLit : CharsLit; } else { for (size_t i = 0; i < c.count; i++) { - print(p, to_cvalue(e, c_emit_value(e, fn, c.nodes[i]))); + shd_print(p, to_cvalue(e, c_emit_value(e, fn, c.nodes[i]))); if (i + 1 < c.count) - print(p, ", "); + shd_print(p, ", "); } shd_growy_append_bytes(g, 1, "\0"); return ObjectsList; @@ -125,7 +125,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No Growy* g = shd_new_growy(); Printer* p2 = p; - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); if (type->tag == ArrType_TAG) { switch (array_insides_helper(emitter, fn, p, g, type, elements)) { @@ -141,9 +141,9 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No } } else { for (size_t i = 0; i < elements.count; i++) { - print(p, "%s", to_cvalue(emitter, c_emit_value(emitter, fn, elements.nodes[i]))); + shd_print(p, "%s", to_cvalue(emitter, c_emit_value(emitter, fn, elements.nodes[i]))); if (i + 1 < elements.count) - print(p, ", "); + shd_print(p, ", "); } emitted = shd_growy_data(g); } @@ -158,7 +158,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No if (p2) { String tmp = unique_name(emitter->arena, "composite"); - print(p2, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); + shd_print(p2, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); emitted = tmp; } else { // this requires us to end up in the initialisation side of a declaration @@ -182,20 +182,20 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No } shd_destroy_growy(g); - destroy_printer(p); + shd_destroy_printer(p); break; } case Value_Fill_TAG: error("lower me") case Value_StringLiteral_TAG: { Growy* g = shd_new_growy(); - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); String str = value->payload.string_lit.string; size_t len = strlen(str); for (size_t i = 0; i < len; i++) { char c = str[i]; switch (c) { - case '\n': print(p, "\\n"); + case '\n': shd_print(p, "\\n"); break; default: shd_growy_append_bytes(g, 1, &c); @@ -205,7 +205,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No emitted = shd_format_string_arena(emitter->arena->arena, "\"%s\"", shd_growy_data(g)); shd_destroy_growy(g); - destroy_printer(p); + shd_destroy_printer(p); break; } case Value_FnAddr_TAG: { @@ -236,7 +236,7 @@ CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CT if (is_term_empty(term)) return term; if (t == empty_multiple_return_type(emitter->arena)) { - print(p, "%s;", to_cvalue(emitter, term)); + shd_print(p, "%s;", to_cvalue(emitter, term)); return empty_term(); } String bind_to = unique_name(emitter->arena, ""); @@ -550,9 +550,9 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case CDialect_C11: { String src = unique_name(arena, "bitcast_src"); String dst = unique_name(arena, "bitcast_result"); - print(p, "\n%s = %s;", c_emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); - print(p, "\n%s;", c_emit_type(emitter, dst_type, dst)); - print(p, "\nmemcpy(&%s, &%s, sizeof(%s));", dst, src, src); + shd_print(p, "\n%s = %s;", c_emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); + shd_print(p, "\n%s;", c_emit_type(emitter, dst_type, dst)); + shd_print(p, "\nmemcpy(&%s, &%s, sizeof(%s));", dst, src, src); return term_from_cvalue(dst); } // GLSL does not feature arbitrary casts, instead we need to run specialized conversion functions... @@ -620,7 +620,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node if (insert) { String dst = unique_name(arena, "modified"); - print(p, "\n%s = %s;", c_emit_type(emitter, node->type, dst), acc); + shd_print(p, "\n%s = %s;", c_emit_type(emitter, node->type, dst), acc); acc = dst; term = term_from_cvalue(dst); } @@ -663,7 +663,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } if (insert) { - print(p, "\n%s = %s;", acc, to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1]))); + shd_print(p, "\n%s = %s;", acc, to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1]))); break; } @@ -683,17 +683,17 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node size_t left_size = lhs_t->payload.pack_type.width; // size_t total_size = lhs_t->payload.pack_type.width + rhs_t->payload.pack_type.width; String suffixes = "xyzw"; - print(p, "\n%s = vec%d(", c_emit_type(emitter, node->type, dst), prim_op->operands.count - 2); + shd_print(p, "\n%s = vec%d(", c_emit_type(emitter, node->type, dst), prim_op->operands.count - 2); for (size_t i = 2; i < prim_op->operands.count; i++) { const IntLiteral* selector = resolve_to_int_literal(prim_op->operands.nodes[i]); if (selector->value < left_size) - print(p, "%s.%c\n", lhs_e, suffixes[selector->value]); + shd_print(p, "%s.%c\n", lhs_e, suffixes[selector->value]); else - print(p, "%s.%c\n", rhs_e, suffixes[selector->value - left_size]); + shd_print(p, "%s.%c\n", rhs_e, suffixes[selector->value - left_size]); if (i + 1 < prim_op->operands.count) - print(p, ", "); + shd_print(p, ", "); } - print(p, ");\n"); + shd_print(p, ");\n"); term = term_from_cvalue(dst); break; } @@ -760,16 +760,16 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* assert(false); Growy* g = shd_new_growy(); - Printer* paramsp = open_growy_as_printer(g); + Printer* paramsp = shd_new_printer_from_growy(g); if (emitter->use_private_globals) { - print(paramsp, "__shady_private_globals"); + shd_print(paramsp, "__shady_private_globals"); if (args.count > 0) - print(paramsp, ", "); + shd_print(paramsp, ", "); } for (size_t i = 0; i < args.count; i++) { - print(paramsp, to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); + shd_print(paramsp, to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); if (i + 1 < args.count) - print(paramsp, ", "); + shd_print(paramsp, ", "); } CValue e_callee; @@ -779,7 +779,7 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* else e_callee = to_cvalue(emitter, c_emit_value(emitter, fn, callee)); - String params = printer_growy_unwrap(paramsp); + String params = shd_printer_growy_unwrap(paramsp); CTerm called = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); called = c_bind_intermediary_result(emitter, p, call->type, called); @@ -821,7 +821,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer // See https://github.com/ispc/ispc/issues/2496 if (emitter->config.dialect == CDialect_ISPC) { String interm = unique_name(arena, "lea_intermediary_ptr_value"); - print(p, "\n%s = %s;", c_emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); + shd_print(p, "\n%s = %s;", c_emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); acc = term_from_cvalue(interm); } @@ -912,7 +912,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case Instruction_ExtInstr_TAG: return emit_ext_instruction(emitter, fn, p, instruction->payload.ext_instr); case Instruction_PrimOp_TAG: return c_bind_intermediary_result(emitter, p, instruction->type, emit_primop(emitter, fn, p, instruction)); case Instruction_Call_TAG: return emit_call(emitter, fn, p, instruction); - case Instruction_Comment_TAG: print(p, "/* %s */", instruction->payload.comment.string); return empty_term(); + case Instruction_Comment_TAG: shd_print(p, "/* %s */", instruction->payload.comment.string); return empty_term(); case Instruction_StackAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); case Instruction_LocalAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); case Instruction_PtrArrayElementOffset_TAG: return emit_ptr_array_element_offset(emitter, fn, p, instruction->payload.ptr_array_element_offset); @@ -936,19 +936,19 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const if (emitter->config.dialect == CDialect_ISPC && addr_uniform && is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) cvalue = shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); - print(p, "\n%s = %s;", dereferenced, cvalue); + shd_print(p, "\n%s = %s;", dereferenced, cvalue); return empty_term(); } case Instruction_CopyBytes_TAG: { CopyBytes payload = instruction->payload.copy_bytes; c_emit_mem(emitter, fn, payload.mem); - print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, fn, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.src)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.count))); + shd_print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, fn, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.src)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.count))); return empty_term(); } case Instruction_FillBytes_TAG:{ FillBytes payload = instruction->payload.fill_bytes; c_emit_mem(emitter, fn, payload.mem); - print(p, "\nmemset(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, fn, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.src)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.count))); + shd_print(p, "\nmemset(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, fn, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.src)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.count))); return empty_term(); } case Instruction_DebugPrintf_TAG: { @@ -964,12 +964,10 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const args_list = shd_format_string_arena(emitter->arena->arena, "%s, %s", args_list, str); } switch (emitter->config.dialect) { - case CDialect_ISPC: - print(p, "\nforeach_active(printf_thread_index) { print(%s); }", args_list); + case CDialect_ISPC:shd_print(p, "\nforeach_active(printf_thread_index) { shd_print(%s); }", args_list); break; case CDialect_CUDA: - case CDialect_C11: - print(p, "\nprintf(%s);", args_list); + case CDialect_C11:shd_print(p, "\nprintf(%s);", args_list); break; case CDialect_GLSL: warn_print("printf is not supported in GLSL"); break; diff --git a/src/common/printer.c b/src/common/printer.c index 2fabd0ca3..2b9988191 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -23,25 +23,25 @@ struct Printer_ { int indent; }; -Printer* open_file_as_printer(void* f) { +Printer* shd_new_printer_from_file(void* f) { Printer* p = calloc(1, sizeof(Printer)); p->output = PoFile; p->file = (FILE*) f; return p; } -Printer* open_growy_as_printer(Growy* g) { +Printer* shd_new_printer_from_growy(Growy* g) { Printer* p = calloc(1, sizeof(Printer)); p->output = PoGrowy; p->growy = g; return p; } -void destroy_printer(Printer* p) { +void shd_destroy_printer(Printer* p) { free(p); } -static void print_bare(Printer* p, size_t len, const char* str) { +static void shd_printer_print_raw(Printer* p, size_t len, const char* str) { assert(strlen(str) >= len); switch(p->output) { case PoFile: fwrite(str, sizeof(char), len, p->file); break; @@ -49,30 +49,30 @@ static void print_bare(Printer* p, size_t len, const char* str) { } } -void flush(Printer* p) { +void shd_printer_flush(Printer* p) { switch(p->output) { case PoFile: fflush(p->file); break; case PoGrowy: break; } } -void indent(Printer* p) { +void shd_printer_indent(Printer* p) { p->indent++; } -void deindent(Printer* p) { +void shd_printer_deindent(Printer* p) { p->indent--; } -void newline(Printer* p) { - print_bare(p, 1, "\n"); +void shd_newline(Printer* p) { + shd_printer_print_raw(p, 1, "\n"); for (int i = 0; i < p->indent; i++) - print_bare(p, 4, " "); + shd_printer_print_raw(p, 4, " "); } #define LOCAL_BUFFER_SIZE 32 -Printer* print(Printer* p, const char* f, ...) { +Printer* shd_print(Printer* p, const char* f, ...) { size_t len = strlen(f) + 1; if (len == 1) return p; @@ -116,42 +116,24 @@ Printer* print(Printer* p, const char* f, ...) { size_t i = 0; while(i < written) { if (tmp[i] == '\n') { - print_bare(p, i - start, &tmp[start]); - newline(p); + shd_printer_print_raw(p, i - start, &tmp[start]); + shd_newline(p); start = i + 1; } i++; } if (start < i) - print_bare(p, i - start, &tmp[start]); + shd_printer_print_raw(p, i - start, &tmp[start]); free(alloc); return p; } -const char* printer_growy_unwrap(Printer* p) { +const char* shd_printer_growy_unwrap(Printer* p) { assert(p->output == PoGrowy); shd_growy_append_bytes(p->growy, 1, "\0"); const char* insides = shd_growy_deconstruct(p->growy); free(p); return insides; } - -const char* replace_string(const char* source, const char* match, const char* replace_with) { - Growy* g = shd_new_growy(); - size_t match_len = strlen(match); - size_t replace_len = strlen(replace_with); - const char* next_match = strstr(source, match); - while (next_match != NULL) { - size_t diff = next_match - source; - shd_growy_append_bytes(g, diff, (char*) source); - shd_growy_append_bytes(g, replace_len, (char*) replace_with); - source = next_match + match_len; - next_match = strstr(source, match); - } - shd_growy_append_bytes(g, strlen(source), (char*) source); - char zero = '\0'; - shd_growy_append_bytes(g, 1, &zero); - return shd_growy_deconstruct(g); -} diff --git a/src/common/printer.h b/src/common/printer.h index 7aee8ac5f..924fd9f93 100644 --- a/src/common/printer.h +++ b/src/common/printer.h @@ -6,20 +6,18 @@ typedef struct Printer_ Printer; typedef struct Growy_ Growy; -Printer* open_file_as_printer(void* FILE); -Printer* open_growy_as_printer(Growy*); -void destroy_printer(Printer*); +Printer* shd_new_printer_from_file(void* FILE); +Printer* shd_new_printer_from_growy(Growy* g); +void shd_destroy_printer(Printer* p); -Printer* print(Printer*, const char*, ...); -void newline(Printer* p); -void indent(Printer* p); -void deindent(Printer* p); -void flush(Printer*); +Printer* shd_print(Printer*, const char*, ...); +void shd_newline(Printer* p); +void shd_printer_indent(Printer* p); +void shd_printer_deindent(Printer* p); +void shd_printer_flush(Printer* p); -const char* printer_growy_unwrap(Printer* p); +const char* shd_printer_growy_unwrap(Printer* p); Growy* shd_new_growy(); -#define helper_format_string(f, ...) printer_growy_unwrap(cunk_print(cunk_open_growy_as_printer(cunk_new_growy()), (f), __VA_ARGS__)) - -const char* replace_string(const char* source, const char* match, const char* replace_with); +#define shd_helper_format_string(f, ...) printer_growy_unwrap(cunk_print(cunk_open_growy_as_printer(cunk_new_growy()), (f), __VA_ARGS__)) #endif diff --git a/src/driver/cli.c b/src/driver/cli.c index 21d9fa823..4f902927c 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -172,8 +172,8 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a } if (help) { - error_print(" --print-internal Includes internal functions in the debug output\n"); - error_print(" --print-generated Includes generated functions in the debug output\n"); + error_print(" --shd_print-internal Includes internal functions in the debug output\n"); + error_print(" --shd_print-generated Includes generated functions in the debug output\n"); error_print(" --no-dynamic-scheduling Disable the built-in dynamic scheduler, restricts code to only leaf functions\n"); error_print(" --simt2d Emits SIMD code instead of SIMT, only effective with the C backend.\n"); error_print(" --entry-point Selects an entry point for the program to be specialized on.\n"); diff --git a/src/runtime/runtime_app_common.h b/src/runtime/runtime_app_common.h index 526b82a08..c40ea92c2 100644 --- a/src/runtime/runtime_app_common.h +++ b/src/runtime/runtime_app_common.h @@ -41,8 +41,8 @@ static void cli_parse_common_app_arguments(CommonAppArgs* args, int* pargc, char error_print("Usage: runtime_test [source.slim]\n"); error_print("Available arguments: \n"); error_print(" --log-level debug[v[v]], info, warn, error]\n"); - error_print(" --print-builtin\n"); - error_print(" --print-generated\n"); + error_print(" --shd_print-builtin\n"); + error_print(" --shd_print-generated\n"); error_print(" --device n\n"); exit(0); } diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index c4030532c..d4fd2baeb 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -15,7 +15,7 @@ static int extra_uniqueness = 0; static void print_node_helper(Printer* p, const Node* n) { Growy* tmp_g = shd_new_growy(); - Printer* tmp_p = open_growy_as_printer(tmp_g); + Printer* tmp_p = shd_new_printer_from_growy(tmp_g); NodePrintConfig config = { .color = false, @@ -24,11 +24,11 @@ static void print_node_helper(Printer* p, const Node* n) { print_node(tmp_p, config, n); - String label = printer_growy_unwrap(tmp_p); + String label = shd_printer_growy_unwrap(tmp_p); char* escaped_label = calloc(strlen(label) * 2, 1); shd_unapply_escape_codes(label, strlen(label), escaped_label); - print(p, "%s", escaped_label); + shd_print(p, "%s", escaped_label); free(escaped_label); free((void*)label); } @@ -65,28 +65,28 @@ static void dump_cf_node(FILE* output, const CFNode* n) { } Growy* g = shd_new_growy(); - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); String abs_name = get_abstraction_name_safe(bb); - print(p, "%s: \n%d: ", abs_name, bb->id); + shd_print(p, "%s: \n%d: ", abs_name, bb->id); if (getenv("SHADY_CFG_SCOPE_ONLY")) { const Nodes* scope = find_scope_info(bb); if (scope) { for (size_t i = 0; i < scope->count; i++) { - print(p, "%d", scope->nodes[i]->id); + shd_print(p, "%d", scope->nodes[i]->id); if (i + 1 < scope->count) - print(p, ", "); + shd_print(p, ", "); } } } else { print_node_helper(p, body); - print(p, "\\l"); + shd_print(p, "\\l"); } - print(p, "rpo: %d, idom: %s, sdom: %s", n->rpo_index, n->idom ? get_abstraction_name_safe(n->idom->node) : "null", n->structured_idom ? get_abstraction_name_safe(n->structured_idom->node) : "null"); + shd_print(p, "rpo: %d, idom: %s, sdom: %s", n->rpo_index, n->idom ? get_abstraction_name_safe(n->idom->node) : "null", n->structured_idom ? get_abstraction_name_safe(n->structured_idom->node) : "null"); - String label = printer_growy_unwrap(p); + String label = shd_printer_growy_unwrap(p); fprintf(output, "bb_%zu [nojustify=true, label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); free((void*) label); @@ -172,25 +172,25 @@ void dump_cfgs_auto(Module* mod) { static void dump_domtree_cfnode(Printer* p, CFNode* idom) { String name = get_abstraction_name_safe(idom->node); if (name) - print(p, "bb_%zu [label=\"%s\", shape=box];\n", (size_t) idom, name); + shd_print(p, "bb_%zu [label=\"%s\", shape=box];\n", (size_t) idom, name); else - print(p, "bb_%zu [label=\"%%%d\", shape=box];\n", (size_t) idom, idom->node->id); + shd_print(p, "bb_%zu [label=\"%%%d\", shape=box];\n", (size_t) idom, idom->node->id); for (size_t i = 0; i < shd_list_count(idom->dominates); i++) { CFNode* child = shd_read_list(CFNode*, idom->dominates)[i]; dump_domtree_cfnode(p, child); - print(p, "bb_%zu -> bb_%zu;\n", (size_t) (idom), (size_t) (child)); + shd_print(p, "bb_%zu -> bb_%zu;\n", (size_t) (idom), (size_t) (child)); } } void dump_domtree_cfg(Printer* p, CFG* s) { - print(p, "subgraph cluster_%s {\n", get_abstraction_name_safe(s->entry->node)); + shd_print(p, "subgraph cluster_%s {\n", get_abstraction_name_safe(s->entry->node)); dump_domtree_cfnode(p, s->entry); - print(p, "}\n"); + shd_print(p, "}\n"); } void dump_domtree_module(Printer* p, Module* mod) { - print(p, "digraph G {\n"); + shd_print(p, "digraph G {\n"); struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; @@ -198,13 +198,13 @@ void dump_domtree_module(Printer* p, Module* mod) { destroy_cfg(cfg); } shd_destroy_list(cfgs); - print(p, "}\n"); + shd_print(p, "}\n"); } void dump_domtree_auto(Module* mod) { FILE* f = fopen("domtree.dot", "wb"); - Printer* p = open_file_as_printer(f); + Printer* p = shd_new_printer_from_file(f); dump_domtree_module(p, mod); - destroy_printer(p); + shd_destroy_printer(p); fclose(f); } diff --git a/src/shady/generator_print.c b/src/shady/generator_print.c index 7c09442f9..2151a1be2 100644 --- a/src/shady/generator_print.c +++ b/src/shady/generator_print.c @@ -15,10 +15,10 @@ void generate_node_print_fns(Growy* g, json_object* src) { alloc = (void*) snake_name; } shd_growy_append_formatted(g, "\tcase %s_TAG: {\n", name); - shd_growy_append_formatted(g, "\t\tprint(ctx->printer, GREEN);\n"); - shd_growy_append_formatted(g, "\t\tprint(ctx->printer, \"%s\");\n", name); - shd_growy_append_formatted(g, "\t\tprint(ctx->printer, RESET);\n"); - shd_growy_append_formatted(g, "\t\tprint(ctx->printer, \"(\");\n"); + shd_growy_append_formatted(g, "\t\tshd_print(ctx->printer, GREEN);\n"); + shd_growy_append_formatted(g, "\t\tshd_print(ctx->printer, \"%s\");\n", name); + shd_growy_append_formatted(g, "\t\tshd_print(ctx->printer, RESET);\n"); + shd_growy_append_formatted(g, "\t\tshd_print(ctx->printer, \"(\");\n"); json_object* ops = json_object_object_get(node, "ops"); if (ops) { assert(json_object_get_type(ops) == json_type_array); @@ -66,10 +66,10 @@ void generate_node_print_fns(Growy* g, json_object* src) { } if (j + 1 < json_object_array_length(ops)) - shd_growy_append_formatted(g, "\t\tprint(ctx->printer, \", \");\n"); + shd_growy_append_formatted(g, "\t\tshd_print(ctx->printer, \", \");\n"); } } - shd_growy_append_formatted(g, "\t\tprint(ctx->printer, \")\");\n"); + shd_growy_append_formatted(g, "\t\tshd_print(ctx->printer, \")\");\n"); shd_growy_append_formatted(g, "\t\tbreak;\n"); shd_growy_append_formatted(g, "\t}\n", name); if (alloc) diff --git a/src/shady/print.c b/src/shady/print.c index 49997421e..d5186dda5 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -54,7 +54,7 @@ static PrinterCtx make_printer_ctx(Printer* printer, NodePrintConfig config) { .emitted = shd_new_dict(const Node*, String, (HashFn) hash_node, (CmpFn) compare_node), .root_growy = shd_new_growy(), }; - ctx.root_printer = open_growy_as_printer(ctx.root_growy); + ctx.root_printer = shd_new_printer_from_growy(ctx.root_growy); return ctx; } @@ -65,63 +65,63 @@ static void destroy_printer_ctx(PrinterCtx ctx) { void print_module(Printer* printer, NodePrintConfig config, Module* mod) { PrinterCtx ctx = make_printer_ctx(printer, config); print_mod_impl(&ctx, mod); - String s = printer_growy_unwrap(ctx.root_printer); - print(ctx.printer, "%s", s); + String s = shd_printer_growy_unwrap(ctx.root_printer); + shd_print(ctx.printer, "%s", s); free((void*)s); - flush(ctx.printer); + shd_printer_flush(ctx.printer); destroy_printer_ctx(ctx); } void print_node(Printer* printer, NodePrintConfig config, const Node* node) { PrinterCtx ctx = make_printer_ctx(printer, config); String emitted = emit_node(&ctx, node); - String s = printer_growy_unwrap(ctx.root_printer); - print(ctx.printer, "%s%s", s, emitted); + String s = shd_printer_growy_unwrap(ctx.root_printer); + shd_print(ctx.printer, "%s%s", s, emitted); free((void*)s); - flush(ctx.printer); + shd_printer_flush(ctx.printer); destroy_printer_ctx(ctx); } void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { Growy* g = shd_new_growy(); - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); if (node) - print(p, "%%%d ", node->id); + shd_print(p, "%%%d ", node->id); print_node(p, (NodePrintConfig) {.reparseable = true}, node); - destroy_printer(p); + shd_destroy_printer(p); *size = shd_growy_size(g); *str_ptr = shd_growy_deconstruct(g); } void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { Growy* g = shd_new_growy(); - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); print_module(p, (NodePrintConfig) {.reparseable = true,}, mod); - destroy_printer(p); + shd_destroy_printer(p); *size = shd_growy_size(g); *str_ptr = shd_growy_deconstruct(g); } void dump_node(const Node* node) { - Printer* p = open_file_as_printer(stdout); + Printer* p = shd_new_printer_from_file(stdout); if (node) - print(p, "%%%d ", node->id); + shd_print(p, "%%%d ", node->id); print_node(p, (NodePrintConfig) {.color = true}, node); printf("\n"); } void dump_module(Module* mod) { - Printer* p = open_file_as_printer(stdout); + Printer* p = shd_new_printer_from_file(stdout); print_module(p, (NodePrintConfig) {.color = true}, mod); - destroy_printer(p); + shd_destroy_printer(p); printf("\n"); } void log_node(LogLevel level, const Node* node) { if (level <= get_log_level()) { - Printer* p = open_file_as_printer(stderr); + Printer* p = shd_new_printer_from_file(stderr); print_node(p, (NodePrintConfig) {.color = true}, node); - destroy_printer(p); + shd_destroy_printer(p); } } @@ -133,9 +133,9 @@ void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) config.print_internal = compiler_cfg->logging.print_internal; } if (level <= get_log_level()) { - Printer* p = open_file_as_printer(stderr); + Printer* p = shd_new_printer_from_file(stderr); print_module(p, config, mod); - destroy_printer(p); + shd_destroy_printer(p); } } @@ -159,7 +159,7 @@ void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) #define BCYAN COLOR("\033[0;96m") #define BWHITE COLOR("\033[0;97m") -#define printf(...) print(ctx->printer, __VA_ARGS__) +#define printf(...) shd_print(ctx->printer, __VA_ARGS__) #define print_node(n) print_operand_helper(ctx, 0, n) #define print_operand(nc, n) print_operand_helper(ctx, nc, n) @@ -256,16 +256,16 @@ static void print_basic_block(PrinterCtx* ctx, const CFNode* node) { print_param_list(ctx, bb->payload.basic_block.params, NULL); printf(" {"); - indent(ctx->printer); + shd_printer_indent(ctx->printer); printf("\n"); printf("%s", emit_abs_body(ctx, bb)); - deindent(ctx->printer); + shd_printer_deindent(ctx->printer); printf("\n}"); } static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { Growy* g = shd_new_growy(); - Printer* p = open_growy_as_printer(g); + Printer* p = shd_new_printer_from_growy(g); CFNode* cfnode = ctx->cfg ? cfg_lookup(ctx->cfg, abs) : NULL; if (cfnode) ctx->bb_printers[cfnode->rpo_index] = p; @@ -274,7 +274,7 @@ static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { if (cfnode) { Growy* g2 = shd_new_growy(); - Printer* p2 = open_growy_as_printer(g2); + Printer* p2 = shd_new_printer_from_growy(g2); size_t count = cfnode->dominates->elements_count; for (size_t i = 0; i < count; i++) { const CFNode* dominated = shd_read_list(const CFNode*, cfnode->dominates)[i]; @@ -283,15 +283,15 @@ static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { bb_ctx.printer = p2; print_basic_block(&bb_ctx, dominated); if (i + 1 < count) - newline(bb_ctx.printer); + shd_newline(bb_ctx.printer); } - String bbs = printer_growy_unwrap(p2); - print(p, "%s", bbs); + String bbs = shd_printer_growy_unwrap(p2); + shd_print(p, "%s", bbs); free((void*) bbs); } - String s = printer_growy_unwrap(p); + String s = shd_printer_growy_unwrap(p); String s2 = string(ctx->fn->arena, s); if (cfnode) ctx->bb_printers[cfnode->rpo_index] = NULL; @@ -323,12 +323,12 @@ static void print_function(PrinterCtx* ctx, const Node* node) { printf(";"); } else { printf(" {"); - indent(ctx->printer); + shd_printer_indent(ctx->printer); printf("\n"); printf("%s", emit_abs_body(ctx, node)); - deindent(ctx->printer); + shd_printer_deindent(ctx->printer); printf("\n}"); } @@ -1036,10 +1036,10 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { Growy* g = shd_new_growy(); PrinterCtx ctx2 = *ctx; - ctx2.printer = open_growy_as_printer(g); + ctx2.printer = shd_new_printer_from_growy(g); bool print_inline = print_node_impl(&ctx2, node); - String s = printer_growy_unwrap(ctx2.printer); + String s = shd_printer_growy_unwrap(ctx2.printer); Printer* p = ctx->root_printer; if (ctx->scheduler) { CFNode* dst = schedule_instruction(ctx->scheduler, node); @@ -1048,7 +1048,7 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { } if (print_def) - print(p, "%%%d = %s\n", node->id, s); + shd_print(p, "%%%d = %s\n", node->id, s); if (print_inline) { String is = string(node->arena, s); @@ -1135,108 +1135,108 @@ static void print_mem(PrinterCtx* ctx, const Node* mem) { } static void print_operand_name_helper(PrinterCtx* ctx, String name) { - print(ctx->printer, GREY); - print(ctx->printer, "%s", name); - print(ctx->printer, RESET); - print(ctx->printer, ": ", name); + shd_print(ctx->printer, GREY); + shd_print(ctx->printer, "%s", name); + shd_print(ctx->printer, RESET); + shd_print(ctx->printer, ": ", name); } static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op) { if (getenv("SHADY_SUPER_VERBOSE_NODE_DEBUG")) { if (op && (is_value(op) || is_instruction(op))) - print(ctx->printer, "%%%d ", op->id); - print(ctx->printer, "%s", emit_node(ctx, op)); + shd_print(ctx->printer, "%%%d ", op->id); + shd_print(ctx->printer, "%s", emit_node(ctx, op)); } else { - print(ctx->printer, "%s", emit_node(ctx, op)); + shd_print(ctx->printer, "%s", emit_node(ctx, op)); } } void print_node_operand(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, const Node* op) { print_operand_name_helper(ctx, name); if (op_class == NcBasic_block) - print(ctx->printer, BYELLOW); + shd_print(ctx->printer, BYELLOW); print_operand_helper(ctx, op_class, op); - print(ctx->printer, RESET); + shd_print(ctx->printer, RESET); } void print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, Nodes ops) { print_operand_name_helper(ctx, name); - print(ctx->printer, "["); + shd_print(ctx->printer, "["); for (size_t i = 0; i < ops.count; i++) { print_operand_helper(ctx, op_class, ops.nodes[i]); if (i + 1 < ops.count) - print(ctx->printer, ", "); + shd_print(ctx->printer, ", "); } - print(ctx->printer, "]"); + shd_print(ctx->printer, "]"); } void print_node_operand_AddressSpace(PrinterCtx* ctx, const Node* n, String name, AddressSpace as) { print_operand_name_helper(ctx, name); - print(ctx->printer, "%s", get_address_space_name(as)); + shd_print(ctx->printer, "%s", get_address_space_name(as)); } void print_node_operand_Op(PrinterCtx* ctx, const Node* n, String name, Op op) { print_operand_name_helper(ctx, name); - print(ctx->printer, "%s", get_primop_name(op)); + shd_print(ctx->printer, "%s", get_primop_name(op)); } void print_node_operand_RecordSpecialFlag(PrinterCtx* ctx, const Node* n, String name, RecordSpecialFlag flags) { print_operand_name_helper(ctx, name); if (flags & DecorateBlock) - print(ctx->printer, "DecorateBlock"); + shd_print(ctx->printer, "DecorateBlock"); } void print_node_operand_uint32_t(PrinterCtx* ctx, const Node* n, String name, uint32_t i) { print_operand_name_helper(ctx, name); - print(ctx->printer, "%u", i); + shd_print(ctx->printer, "%u", i); } void print_node_operand_uint64_t(PrinterCtx* ctx, const Node* n, String name, uint64_t i) { print_operand_name_helper(ctx, name); - print(ctx->printer, "%zu", i); + shd_print(ctx->printer, "%zu", i); } void print_node_operand_IntSizes(PrinterCtx* ctx, const Node* n, String name, IntSizes s) { print_operand_name_helper(ctx, name); switch (s) { - case IntTy8: print(ctx->printer, "8"); break; - case IntTy16: print(ctx->printer, "16"); break; - case IntTy32: print(ctx->printer, "32"); break; - case IntTy64: print(ctx->printer, "64"); break; + case IntTy8: shd_print(ctx->printer, "8"); break; + case IntTy16: shd_print(ctx->printer, "16"); break; + case IntTy32: shd_print(ctx->printer, "32"); break; + case IntTy64: shd_print(ctx->printer, "64"); break; } } void print_node_operand_FloatSizes(PrinterCtx* ctx, const Node* n, String name, FloatSizes s) { print_operand_name_helper(ctx, name); switch (s) { - case FloatTy16: print(ctx->printer, "16"); break; - case FloatTy32: print(ctx->printer, "32"); break; - case FloatTy64: print(ctx->printer, "64"); break; + case FloatTy16: shd_print(ctx->printer, "16"); break; + case FloatTy32: shd_print(ctx->printer, "32"); break; + case FloatTy64: shd_print(ctx->printer, "64"); break; } } void print_node_operand_String(PrinterCtx* ctx, const Node* n, String name, String s ){ print_operand_name_helper(ctx, name); - print(ctx->printer, "\"%s\"", s); + shd_print(ctx->printer, "\"%s\"", s); } void print_node_operand_Strings(PrinterCtx* ctx, const Node* n, String name, Strings ops) { print_operand_name_helper(ctx, name); - print(ctx->printer, "["); + shd_print(ctx->printer, "["); for (size_t i = 0; i < ops.count; i++) { - print(ctx->printer, "\"%s\"", (size_t) ops.strings[i]); + shd_print(ctx->printer, "\"%s\"", (size_t) ops.strings[i]); if (i + 1 < ops.count) - print(ctx->printer, ", "); + shd_print(ctx->printer, ", "); } - print(ctx->printer, "]"); + shd_print(ctx->printer, "]"); } void print_node_operand_bool(PrinterCtx* ctx, const Node* n, String name, bool b) { print_operand_name_helper(ctx, name); if (b) - print(ctx->printer, "true"); + shd_print(ctx->printer, "true"); else - print(ctx->printer, "false"); + shd_print(ctx->printer, "false"); } #include "print_generated.c" From 8c6a6978f06314fc63f2c1ae0427d68c8c1914c6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 15:50:14 +0200 Subject: [PATCH 598/693] add shd_ prefix to log.h --- samples/aobench/ao_main.c | 18 ++--- samples/checkerboard/checkerboard.c | 12 +-- src/backend/c/emit_c.c | 8 +- src/backend/c/emit_c_control_flow.c | 6 +- src/backend/c/emit_c_type.c | 18 ++--- src/backend/c/emit_c_value.c | 44 +++++------ src/backend/spirv/emit_spv.c | 6 +- src/backend/spirv/emit_spv_control_flow.c | 4 +- src/backend/spirv/emit_spv_type.c | 10 +-- src/backend/spirv/emit_spv_value.c | 30 +++---- src/backend/spirv/spirv_map_entrypoint_args.c | 4 +- src/common/log.c | 10 +-- src/common/log.h | 44 +++++------ src/common/test_dict.c | 4 +- src/common/util.c | 2 +- src/driver/cli.c | 78 +++++++++---------- src/driver/driver.c | 28 +++---- src/driver/slim.c | 2 +- src/frontend/llvm/generator_l2s.c | 2 +- src/frontend/llvm/l2s.c | 30 +++---- src/frontend/llvm/l2s_annotations.c | 4 +- src/frontend/llvm/l2s_instr.c | 24 +++--- src/frontend/llvm/l2s_meta.c | 4 +- src/frontend/llvm/l2s_type.c | 4 +- src/frontend/llvm/l2s_value.c | 6 +- src/frontend/slim/bind.c | 16 ++-- src/frontend/slim/infer.c | 20 ++--- src/frontend/slim/parser.c | 38 ++++----- src/frontend/slim/slim_driver.c | 4 +- src/frontend/slim/token.c | 4 +- src/frontend/spirv/s2s.c | 26 +++---- src/runtime/cuda/cuda_runtime.c | 2 +- src/runtime/cuda/cuda_runtime_private.h | 4 +- src/runtime/cuda/cuda_runtime_program.c | 6 +- src/runtime/runtime.c | 4 +- src/runtime/runtime_app_common.h | 14 ++-- src/runtime/runtime_cli.c | 14 ++-- src/runtime/runtime_private.h | 2 +- src/runtime/runtime_test.c | 4 +- src/runtime/vulkan/vk_runtime.c | 16 ++-- src/runtime/vulkan/vk_runtime_buffer.c | 16 ++-- src/runtime/vulkan/vk_runtime_device.c | 24 +++--- src/runtime/vulkan/vk_runtime_dispatch.c | 2 +- src/runtime/vulkan/vk_runtime_private.h | 2 +- src/runtime/vulkan/vk_runtime_program.c | 28 +++---- src/shady/analysis/callgraph.c | 12 +-- src/shady/analysis/cfg.c | 10 +-- src/shady/analysis/verify.c | 24 +++--- src/shady/annotation.c | 6 +- src/shady/api/generator_grammar.c | 2 +- src/shady/body_builder.c | 4 +- src/shady/builtins.c | 2 +- src/shady/compile.c | 14 ++-- src/shady/generator/generator_common.c | 4 +- src/shady/generator/generator_main.c | 8 +- src/shady/generator/import_spv_defs.c | 20 ++--- src/shady/generator/json_apply.c | 2 +- src/shady/generator_constructors.c | 2 +- src/shady/node.c | 2 +- src/shady/passes/cleanup.c | 6 +- src/shady/passes/import.c | 20 ++--- src/shady/passes/lcssa.c | 10 +-- src/shady/passes/lift_indirect_targets.c | 10 +-- src/shady/passes/lower_alloca.c | 8 +- src/shady/passes/lower_cf_instrs.c | 18 ++--- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 4 +- src/shady/passes/lower_lea.c | 2 +- src/shady/passes/lower_logical_pointers.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 26 +++---- src/shady/passes/lower_subgroup_ops.c | 8 +- src/shady/passes/lower_switch_btree.c | 2 +- src/shady/passes/mark_leaf_functions.c | 30 +++---- src/shady/passes/normalize_builtins.c | 10 +-- src/shady/passes/opt_inline.c | 26 +++---- src/shady/passes/opt_restructure.c | 6 +- src/shady/passes/reconvergence_heuristics.c | 12 +-- src/shady/passes/scope2control.c | 22 +++--- src/shady/passes/scope_heuristic.c | 2 +- src/shady/passes/specialize_entry_point.c | 8 +- src/shady/print.c | 20 ++--- src/shady/rewrite.c | 36 ++++----- src/shady/transform/ir_gen_helpers.c | 4 +- src/shady/transform/memory_layout.c | 6 +- src/shady/type.c | 32 ++++---- src/shady/type_helpers.c | 22 +++--- test/opt/opt_oracle.c | 8 +- test/test_builder.c | 2 +- test/test_math.c | 2 +- vcc/vcc.c | 4 +- vcc/vcc_lib.c | 10 +-- 91 files changed, 570 insertions(+), 570 deletions(-) diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index f6e87b81b..5e0e911ae 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -53,7 +53,7 @@ void render_host(TEXEL_T* img, int w, int h, int nsubsamples) { } } uint64_t tpn = shd_get_time_nano(); - info_print("reference rendering took %d us\n", (tpn - tsn) / 1000); + shd_info_print("reference rendering took %d us\n", (tpn - tsn) / 1000); } #ifdef ENABLE_ISPC @@ -83,7 +83,7 @@ void render_ispc(TEXEL_T* img, int w, int h, int nsubsamples) { aobench_kernel(img); uint64_t tpn = shd_get_time_nano(); - info_print("ispc rendering took %d us\n", (tpn - tsn) / 1000); + shd_info_print("ispc rendering took %d us\n", (tpn - tsn) / 1000); } #endif @@ -96,14 +96,14 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri } } - info_print("Shady checkerboard test starting...\n"); + shd_info_print("Shady checkerboard test starting...\n"); Runtime* runtime = initialize_runtime(args->runtime_config); Device* device = get_device(runtime, args->common_app_args.device); assert(device); img[0] = 69; - info_print("malloc'd address is: %zu\n", (size_t) img); + shd_info_print("malloc'd address is: %zu\n", (size_t) img); Buffer* buf; if (import_memory) @@ -113,7 +113,7 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri uint64_t buf_addr = get_buffer_device_pointer(buf); - info_print("Device-side address is: %zu\n", buf_addr); + shd_info_print("Device-side address is: %zu\n", buf_addr); Module* m; CHECK(driver_load_source_file_from_filename(&args->compiler_config, path, "aobench", &m) == NoError, return); @@ -128,18 +128,18 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri }; wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, &extra_kernel_options)); uint64_t tpn = shd_get_time_nano(); - info_print("device rendering took %dus (gpu time: %dus)\n", (tpn - tsn) / 1000, profiled_gpu_time / 1000); + shd_info_print("device rendering took %dus (gpu time: %dus)\n", (tpn - tsn) / 1000, profiled_gpu_time / 1000); if (!import_memory) copy_from_buffer(buf, 0, img, sizeof(*img) * WIDTH * HEIGHT * 3); - debug_print("data %d\n", (int) img[0]); + shd_debug_print("data %d\n", (int) img[0]); destroy_buffer(buf); shutdown_runtime(runtime); } int main(int argc, char **argv) { - set_log_level(INFO); + shd_log_set_level(INFO); Args args = { .compiler_config = default_compiler_config(), .runtime_config = default_runtime_config(), @@ -164,7 +164,7 @@ int main(int argc, char **argv) { do_ispc = true; do_all = false; } else { - error_print("Unrecognised argument: %s\n", argv[i]); + shd_error_print("Unrecognised argument: %s\n", argv[i]); shd_error_die(); } } diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index da49bd95d..9acb4ecdd 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -40,7 +40,7 @@ int main(int argc, char **argv) } } - set_log_level(INFO); + shd_log_set_level(INFO); CompilerConfig compiler_config = default_compiler_config(); RuntimeConfig runtime_config = default_runtime_config(); @@ -49,33 +49,33 @@ int main(int argc, char **argv) cli_parse_compiler_config_args(&compiler_config, &argc, argv); cli_parse_runtime_config(&runtime_config, &argc, argv); - info_print("Shady checkerboard test starting...\n"); + shd_info_print("Shady checkerboard test starting...\n"); Runtime* runtime = initialize_runtime(runtime_config); Device* device = get_device(runtime, 0); assert(device); img[0] = 69; - info_print("malloc'd address is: %zu\n", (size_t) img); + shd_info_print("malloc'd address is: %zu\n", (size_t) img); int buf_size = sizeof(uint8_t) * WIDTH * HEIGHT * 3; Buffer* buf = allocate_buffer_device(device, buf_size); copy_to_buffer(buf, 0, img, buf_size); uint64_t buf_addr = get_buffer_device_pointer(buf); - info_print("Device-side address is: %zu\n", buf_addr); + shd_info_print("Device-side address is: %zu\n", buf_addr); ArenaConfig aconfig = default_arena_config(&compiler_config.target); IrArena* a = new_ir_arena(&aconfig); Module* m; if (driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, "checkerboard", &m) != NoError) - error("Failed to load checkerboard module"); + shd_error("Failed to load checkerboard module"); Program* program = new_program_from_module(runtime, &compiler_config, m); wait_completion(launch_kernel(program, device, "checkerboard", 16, 16, 1, 1, (void*[]) { &buf_addr }, NULL)); copy_from_buffer(buf, 0, img, buf_size); - info_print("data %d\n", (int) img[0]); + shd_info_print("data %d\n", (int) img[0]); destroy_buffer(buf); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 6ca8e01fb..d91d944d2 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -163,7 +163,7 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String // GLSL wants 'const' to go on the left to start the declaration, but in C const should go on the right (east const convention) switch (emitter->config.dialect) { case CDialect_C11: { - if (as != AsGeneric) warn_print_once(c11_non_generic_as, "warning: standard C does not have address spaces\n"); + if (as != AsGeneric) shd_warn_print_once(c11_non_generic_as, "warning: standard C does not have address spaces\n"); prefix = ""; if (constant) name = shd_format_string_arena(emitter->arena->arena, "const %s", name); @@ -191,7 +191,7 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String } default: { prefix = shd_format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); - warn_print("warning: address space %s not supported in CUDA for global variables\n", get_address_space_name(as)); + shd_warn_print("warning: address space %s not supported in CUDA for global variables\n", get_address_space_name(as)); break; } } @@ -211,7 +211,7 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String } default: { prefix = shd_format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); - warn_print("warning: address space %s not supported in GLSL for global variables\n", get_address_space_name(as)); + shd_warn_print("warning: address space %s not supported in GLSL for global variables\n", get_address_space_name(as)); break; } } @@ -369,7 +369,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { } return; } - default: error("not a decl"); + default: shd_error("not a decl"); } } diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index 8770c0dad..2659a65f2 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -177,15 +177,15 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin c_emit_mem(emitter, fn, get_terminator_mem(terminator)); switch (is_terminator(terminator)) { case NotATerminator: assert(false); - case Join_TAG: error("this must be lowered away!"); + case Join_TAG: shd_error("this must be lowered away!"); case Jump_TAG: case Branch_TAG: case Switch_TAG: - case TailCall_TAG: error("TODO"); + case TailCall_TAG: shd_error("TODO"); case If_TAG: return emit_if(emitter, fn, block_printer, terminator->payload.if_instr); case Match_TAG: return emit_match(emitter, fn, block_printer, terminator->payload.match_instr); case Loop_TAG: return emit_loop(emitter, fn, block_printer, terminator->payload.loop_instr); - case Control_TAG: error("TODO") + case Control_TAG: shd_error("TODO") case Terminator_Return_TAG: { Nodes args = terminator->payload.fn_ret.args; if (args.count == 0) { diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index c2b944ea0..450acc61e 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -134,12 +134,12 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { switch (is_type(type)) { case NotAType: assert(false); break; case LamType_TAG: - case BBType_TAG: error("these types do not exist in C"); - case MaskType_TAG: error("should be lowered away"); + case BBType_TAG: shd_error("these types do not exist in C"); + case MaskType_TAG: shd_error("should be lowered away"); case Type_SampledImageType_TAG: case Type_SamplerType_TAG: case Type_ImageType_TAG: - case JoinPointType_TAG: error("TODO") + case JoinPointType_TAG: shd_error("TODO") case NoRet_TAG: case Bool_TAG: emitted = "bool"; break; case Int_TAG: { @@ -178,16 +178,16 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { break; } switch (type->payload.int_type.width) { - case IntTy8: warn_print("vanilla GLSL does not support 8-bit integers\n"); + case IntTy8: shd_warn_print("vanilla GLSL does not support 8-bit integers\n"); emitted = sign ? "byte" : "ubyte"; break; - case IntTy16: warn_print("vanilla GLSL does not support 16-bit integers\n"); + case IntTy16: shd_warn_print("vanilla GLSL does not support 16-bit integers\n"); emitted = sign ? "short" : "ushort"; break; case IntTy32: emitted = sign ? "int" : "uint"; break; case IntTy64: emitter->need_64b_ext = true; - warn_print("vanilla GLSL does not support 64-bit integers\n"); + shd_warn_print("vanilla GLSL does not support 64-bit integers\n"); emitted = sign ? "int64_t" : "uint64_t"; break; } @@ -287,7 +287,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { int width = type->payload.pack_type.width; const Type* element_type = type->payload.pack_type.element_type; switch (emitter->config.dialect) { - case CDialect_CUDA: error("TODO") + case CDialect_CUDA: shd_error("TODO") case CDialect_GLSL: { assert(is_glsl_scalar_type(element_type)); assert(width > 1); @@ -296,12 +296,12 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { case Bool_TAG: base = "bvec"; break; case Int_TAG: base = "uvec"; break; // TODO not every int is 32-bit case Float_TAG: base = "vec"; break; - default: error("not a valid GLSL vector type"); + default: shd_error("not a valid GLSL vector type"); } emitted = shd_format_string_arena(emitter->arena->arena, "%s%d", base, width); break; } - case CDialect_ISPC: error("Please lower to something else") + case CDialect_ISPC: shd_error("Please lower to something else") case CDialect_C11: { emitted = c_emit_type(emitter, element_type, NULL); emitted = shd_format_string_arena(emitter->arena->arena, "__attribute__ ((vector_size (%d * sizeof(%s) ))) %s", width, emitted, emitted); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 4f1bdfb30..3f1bce6fb 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -65,11 +65,11 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No switch (is_value(value)) { case NotAValue: assert(false); case Value_ConstrainedValue_TAG: - case Value_UntypedNumber_TAG: error("lower me"); - case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); + case Value_UntypedNumber_TAG: shd_error("lower me"); + case Param_TAG: shd_error("tried to emit a param: all params should be emitted by their binding abstraction !"); default: { assert(!is_instruction(value)); - error("Unhandled value for code generation: %s", node_tags[value->tag]); + shd_error("Unhandled value for code generation: %s", node_tags[value->tag]); } case Value_IntLiteral_TAG: { if (value->payload.int_literal.is_signed) @@ -185,7 +185,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No shd_destroy_printer(p); break; } - case Value_Fill_TAG: error("lower me") + case Value_Fill_TAG: shd_error("lower me") case Value_StringLiteral_TAG: { Growy* g = shd_new_growy(); Printer* p = shd_new_printer_from_growy(g); @@ -439,7 +439,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case add_carry_op: case sub_borrow_op: case mul_extended_op: - error("TODO: implement extended arithm ops in C"); + shd_error("TODO: implement extended arithm ops in C"); break; // MATH OPS case fract_op: { @@ -581,11 +581,11 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node if (conv_fn) { return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, to_cvalue(emitter, src_value))); } - error_print("glsl: unsupported bit cast from "); - log_node(ERROR, src_type); - error_print(" to "); - log_node(ERROR, dst_type); - error_print(".\n"); + shd_error_print("glsl: unsupported bit cast from "); + shd_log_node(ERROR, src_type); + shd_error_print(" to "); + shd_log_node(ERROR, dst_type); + shd_error_print(".\n"); shd_error_die(); } case CDialect_ISPC: { @@ -658,7 +658,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } default: - case NotAType: error("Must be a type"); + case NotAType: shd_error("Must be a type"); } } @@ -703,7 +703,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } } case empty_mask_op: - case mask_is_thread_active_op: error("lower_me"); + case mask_is_thread_active_op: shd_error("lower_me"); default: break; case PRIMOPS_COUNT: assert(false); break; } @@ -724,7 +724,7 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; case CDialect_C11: - case CDialect_GLSL: error("TODO") + case CDialect_GLSL: shd_error("TODO") } break; } @@ -736,17 +736,17 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_elect_first()")); case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); case CDialect_C11: - case CDialect_GLSL: error("TODO") + case CDialect_GLSL: shd_error("TODO") } break; } // [subgroup_active_mask_op] = { IsMono, OsCall, "lanemask" }, // [subgroup_ballot_op] = { IsMono, OsCall, "packmask" }, // [subgroup_reduce_sum_op] = { IsMono, OsCall, "reduce_add" }, - default: error("Unsupported core spir-v instruction: %d", instr.opcode); + default: shd_error("Unsupported core spir-v instruction: %d", instr.opcode); } } else { - error("Unsupported extended instruction set: %s", instr.set); + shd_error("Unsupported extended instruction set: %s", instr.set); } } @@ -845,7 +845,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer }); break; } - default: error("lea can't work on this"); + default: shd_error("lea can't work on this"); } // if (emitter->config.dialect == CDialect_ISPC) @@ -908,7 +908,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case Instruction_PopStack_TAG: case Instruction_GetStackSize_TAG: case Instruction_SetStackSize_TAG: - case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); + case Instruction_GetStackBaseAddr_TAG: shd_error("Stack operations need to be lowered."); case Instruction_ExtInstr_TAG: return emit_ext_instruction(emitter, fn, p, instruction->payload.ext_instr); case Instruction_PrimOp_TAG: return c_bind_intermediary_result(emitter, p, instruction->type, emit_primop(emitter, fn, p, instruction)); case Instruction_Call_TAG: return emit_call(emitter, fn, p, instruction); @@ -969,7 +969,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case CDialect_CUDA: case CDialect_C11:shd_print(p, "\nprintf(%s);", args_list); break; - case CDialect_GLSL: warn_print("printf is not supported in GLSL"); + case CDialect_GLSL: shd_warn_print("printf is not supported in GLSL"); break; } @@ -1006,8 +1006,8 @@ CTerm c_emit_value(Emitter* emitter, FnEmitter* fn_builder, const Node* node) { return emitted; } else if (!can_appear_at_top_level(emitter, node)) { if (!fn_builder) { - log_node(ERROR, node); - log_string(ERROR, "cannot appear at top-level"); + shd_log_node(ERROR, node); + shd_log_fmt(ERROR, "cannot appear at top-level"); exit(-1); } // Pick the entry block of the current fn @@ -1028,5 +1028,5 @@ CTerm c_emit_mem(Emitter* e, FnEmitter* b, const Node* mem) { return empty_term(); if (is_instruction(mem)) return c_emit_value(e, b, mem); - error("What sort of mem is this ?"); + shd_error("What sort of mem is this ?"); } diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 577135269..6c6338b98 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -228,9 +228,9 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { spv_emit_nominal_type_body(emitter, decl->payload.nom_type.body, given_id); return given_id; } - case NotADeclaration: error(""); + case NotADeclaration: shd_error(""); } - error("unreachable"); + shd_error("unreachable"); } static SpvExecutionModel emit_exec_model(ExecutionModel model) { @@ -238,7 +238,7 @@ static SpvExecutionModel emit_exec_model(ExecutionModel model) { case EmCompute: return SpvExecutionModelGLCompute; case EmVertex: return SpvExecutionModelVertex; case EmFragment: return SpvExecutionModelFragment; - case EmNone: error("No execution model but we were asked to emit it anyways"); + case EmNone: shd_error("No execution model but we were asked to emit it anyways"); } } diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index ce7c2208f..dabebefda 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -254,8 +254,8 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi } case Terminator_Control_TAG: case TailCall_TAG: - case Join_TAG: error("Lower me"); - case NotATerminator: error("TODO: emit terminator %s", node_tags[terminator->tag]); + case Join_TAG: shd_error("Lower me"); + case NotATerminator: shd_error("TODO: emit terminator %s", node_tags[terminator->tag]); } SHADY_UNREACHABLE; } diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 6460b6245..4349e28c9 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -32,7 +32,7 @@ SpvStorageClass spv_emit_addr_space(Emitter* emitter, AddressSpace address_space case AsUniformConstant: return SpvStorageClassUniformConstant; default: { - error_print("Cannot emit address space %s.\n", get_address_space_name(address_space)); + shd_error_print("Cannot emit address space %s.\n", get_address_space_name(address_space)); shd_error_die(); SHADY_UNREACHABLE; } @@ -87,7 +87,7 @@ void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id) { } break; } - default: error("not a suitable nominal type body (tag=%s)", node_tags[type->tag]); + default: shd_error("not a suitable nominal type body (tag=%s)", node_tags[type->tag]); } } @@ -102,7 +102,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { SpvId new; switch (is_type(type)) { - case NotAType: error("Not a type"); + case NotAType: shd_error("Not a type"); case Int_TAG: { int width; switch (type->payload.int_type.width) { @@ -158,7 +158,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { } case NoRet_TAG: case LamType_TAG: - case BBType_TAG: error("we can't emit arrow types that aren't those of first-class functions") + case BBType_TAG: shd_error("we can't emit arrow types that aren't those of first-class functions") case FnType_TAG: { const FnType* fnt = &type->payload.fn_type; LARRAY(SpvId, params, fnt->param_types.count); @@ -212,7 +212,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { break; } case Type_MaskType_TAG: - case Type_JoinPointType_TAG: error("These must be lowered beforehand") + case Type_JoinPointType_TAG: shd_error("These must be lowered beforehand") } if (is_data_type(type)) { diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 26d1a58c1..78400d658 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -44,7 +44,7 @@ static OperandClass classify_operand_type(const Type* type) { case Bool_TAG: return Logical; case PtrType_TAG: return Ptr; case Float_TAG: return FP; - default: error("we don't know what to do with this") + default: shd_error("we don't know what to do with this") } } @@ -270,9 +270,9 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b return spvb_select(bb_builder, spv_emit_type(emitter, args.nodes[1]->type), cond, truv, flsv); } - default: error("TODO: unhandled op"); + default: shd_error("TODO: unhandled op"); } - error("unreachable"); + shd_error("unreachable"); } static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, ExtInstr instr) { @@ -358,15 +358,15 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui assert(is_instruction(instruction)); switch (is_instruction(instruction)) { - case NotAnInstruction: error(""); + case NotAnInstruction: shd_error(""); case Instruction_PushStack_TAG: case Instruction_PopStack_TAG: case Instruction_GetStackSize_TAG: case Instruction_SetStackSize_TAG: - case Instruction_GetStackBaseAddr_TAG: error("Stack operations need to be lowered."); + case Instruction_GetStackBaseAddr_TAG: shd_error("Stack operations need to be lowered."); case Instruction_CopyBytes_TAG: case Instruction_FillBytes_TAG: - case Instruction_StackAlloc_TAG: error("Should be lowered elsewhere") + case Instruction_StackAlloc_TAG: shd_error("Should be lowered elsewhere") case Instruction_ExtInstr_TAG: return emit_ext_instr(emitter, fn_builder, bb_builder, instruction->payload.ext_instr); case Instruction_Call_TAG: return emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call); case PrimOp_TAG: return emit_primop(emitter, fn_builder, bb_builder, instruction); @@ -462,11 +462,11 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder SpvId new; switch (is_value(node)) { - case NotAValue: error(""); - case Param_TAG: error("tried to emit a param: all params should be emitted by their binding abstraction !"); + case NotAValue: shd_error(""); + case Param_TAG: shd_error("tried to emit a param: all params should be emitted by their binding abstraction !"); case Value_ConstrainedValue_TAG: case Value_UntypedNumber_TAG: - case Value_FnAddr_TAG: error("Should be lowered away earlier!"); + case Value_FnAddr_TAG: shd_error("Should be lowered away earlier!"); case IntLiteral_TAG: { new = spvb_fresh_id(emitter->file_builder); SpvId ty = spv_emit_type(emitter, node->type); @@ -538,7 +538,7 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder new = spvb_undef(emitter->file_builder, spv_emit_type(emitter, node->payload.undef.type)); break; } - case Value_Fill_TAG: error("lower me") + case Value_Fill_TAG: shd_error("lower me") case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; switch (decl->tag) { @@ -550,12 +550,12 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder new = spv_emit_value(emitter, fn_builder, decl->payload.constant.value); break; } - default: error("RefDecl must reference a constant or global"); + default: shd_error("RefDecl must reference a constant or global"); } break; } default: { - error("Unhandled value for code generation: %s", node_tags[node->tag]); + shd_error("Unhandled value for code generation: %s", node_tags[node->tag]); } } @@ -589,8 +589,8 @@ SpvId spv_emit_value(Emitter* emitter, FnBuilder* fn_builder, const Node* node) return emitted; } else if (!can_appear_at_top_level(node)) { if (!fn_builder) { - log_node(ERROR, node); - log_string(ERROR, "cannot appear at top-level"); + shd_log_node(ERROR, node); + shd_log_fmt(ERROR, "cannot appear at top-level"); exit(-1); } // Pick the entry block of the current fn @@ -612,5 +612,5 @@ SpvId spv_emit_mem(Emitter* e, FnBuilder* b, const Node* mem) { return 0; if (is_instruction(mem)) return spv_emit_value(e, b, mem); - error("What sort of mem is this ?"); + shd_error("What sort of mem is this ?"); } diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index 4ff784fab..55c5acaa3 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -16,7 +16,7 @@ static const Node* rewrite_args_type(Rewriter* rewriter, const Node* old_type) { IrArena* a = rewriter->dst_arena; if (old_type->tag != RecordType_TAG || old_type->payload.record_type.special != NotSpecial) - error("EntryPointArgs type must be a plain record type"); + shd_error("EntryPointArgs type must be a plain record type"); const Node* new_type = record_type(a, (RecordType) { .members = rewrite_nodes(rewriter, old_type->payload.record_type.members), @@ -34,7 +34,7 @@ static const Node* process(Context* ctx, const Node* node) { case GlobalVariable_TAG: if (lookup_annotation(node, "EntryPointArgs")) { if (node->payload.global_variable.address_space != AsExternal) - error("EntryPointArgs address space must be extern"); + shd_error("EntryPointArgs address space must be extern"); Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations); const Node* type = rewrite_args_type(&ctx->rewriter, node->payload.global_variable.type); diff --git a/src/common/log.c b/src/common/log.c index 2bb1b652b..58b4a7c7d 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -4,22 +4,22 @@ LogLevel shady_log_level = INFO; -LogLevel get_log_level() { +LogLevel shd_log_get_level(void) { return shady_log_level; } -void set_log_level(LogLevel l) { +void shd_log_set_level(LogLevel l) { shady_log_level = l; } -void log_fmtv(LogLevel level, const char* format, va_list args) { +void shd_log_fmt_va_list(LogLevel level, const char* format, va_list args) { if (level <= shady_log_level) vfprintf(stderr, format, args); } -void log_string(LogLevel level, const char* format, ...) { +void shd_log_fmt(LogLevel level, const char* format, ...) { va_list args; va_start(args, format); - log_fmtv(level, format, args); + shd_log_fmt_va_list(level, format, args); va_end(args); } diff --git a/src/common/log.h b/src/common/log.h index 7930aece4..637f24f73 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -16,27 +16,27 @@ typedef enum LogLevel_ { DEBUGVV, } LogLevel; -LogLevel get_log_level(); -void set_log_level(LogLevel); -void log_fmtv(LogLevel level, const char* format, va_list args); -void log_string(LogLevel level, const char* format, ...); -void log_node(LogLevel level, const Node* node); +LogLevel shd_log_get_level(void); +void shd_log_set_level(LogLevel l); +void shd_log_fmt_va_list(LogLevel level, const char* format, va_list args); +void shd_log_fmt(LogLevel level, const char* format, ...); +void shd_log_node(LogLevel level, const Node* node); typedef struct CompilerConfig_ CompilerConfig; -void log_module(LogLevel level, const CompilerConfig*, Module*); - -#define debugvv_print(...) log_string(DEBUGVV, __VA_ARGS__) -#define debugv_print(...) log_string(DEBUGV, __VA_ARGS__) -#define debug_print(...) log_string(DEBUG, __VA_ARGS__) -#define info_print(...) log_string(INFO, __VA_ARGS__) -#define warn_print(...) log_string(WARN, __VA_ARGS__) -#define error_print(...) log_string(ERROR, __VA_ARGS__) - -#define debugvv_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; debugvv_print(__VA_ARGS__ ); } } -#define debugv_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; debugv_print(__VA_ARGS__ ); } } -#define debug_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; debug_print(__VA_ARGS__ ); } } -#define info_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; info_print(__VA_ARGS__ ); } } -#define warn_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; warn_print(__VA_ARGS__ ); } } -#define error_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; error_print(__VA_ARGS__ ); } } +void shd_log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod); + +#define shd_debugvv_print(...) shd_log_fmt(DEBUGVV, __VA_ARGS__) +#define shd_debugv_print(...) shd_log_fmt(DEBUGV, __VA_ARGS__) +#define shd_debug_print(...) shd_log_fmt(DEBUG, __VA_ARGS__) +#define shd_info_print(...) shd_log_fmt(INFO, __VA_ARGS__) +#define shd_warn_print(...) shd_log_fmt(WARN, __VA_ARGS__) +#define shd_error_print(...) shd_log_fmt(ERROR, __VA_ARGS__) + +#define shd_debugvv_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; shd_debugvv_print(__VA_ARGS__ ); } } +#define shd_debugv_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; shd_debugv_print(__VA_ARGS__ ); } } +#define shd_debug_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; shd_debug_print(__VA_ARGS__ ); } } +#define shd_info_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; shd_info_print(__VA_ARGS__ ); } } +#define shd_warn_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; shd_warn_print(__VA_ARGS__ ); } } +#define shd_error_print_once(flag, ...) { static bool flag = false; if (!flag) { flag = true; shd_error_print(__VA_ARGS__ ); } } #ifdef _MSC_VER #define SHADY_UNREACHABLE __assume(0) @@ -49,7 +49,7 @@ void log_module(LogLevel level, const CompilerConfig*, Module*); SHADY_UNREACHABLE; \ } -#define error(...) { \ +#define shd_error(...) { \ fprintf (stderr, "Error at %s:%d: ", __FILE__, __LINE__); \ fprintf (stderr, __VA_ARGS__); \ fprintf (stderr, "\n"); \ @@ -57,6 +57,6 @@ void log_module(LogLevel level, const CompilerConfig*, Module*); } #include -noreturn void shd_error_die(); +noreturn void shd_error_die(void); #endif diff --git a/src/common/test_dict.c b/src/common/test_dict.c index 0f4467d38..35f287b1c 100644 --- a/src/common/test_dict.c +++ b/src/common/test_dict.c @@ -43,7 +43,7 @@ int main(int argc, char** argv) { for (int i = 0; i < TEST_ENTRIES; i++) { bool unique = shd_set_insert_get_result(int, d, arr[i]); if (!unique) { - error("Entry %d was thought to be already in the dict", arr[i]); + shd_error("Entry %d was thought to be already in the dict", arr[i]); } contained[arr[i]] = true; } @@ -73,7 +73,7 @@ int main(int argc, char** argv) { if (!contained[arr[i]]) { bool unique = shd_set_insert_get_result(int, d, arr[i]); if (!unique) { - error("Entry %d was thought to be already in the dict", arr[i]); + shd_error("Entry %d was thought to be already in the dict", arr[i]); } contained[arr[i]] = true; } diff --git a/src/common/util.c b/src/common/util.c index e734ba386..7cf30608e 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -233,6 +233,6 @@ char* shd_strip_path(const char* path) { return new; } -void shd_error_die() { +void shd_error_die(void) { abort(); } diff --git a/src/driver/cli.c b/src/driver/cli.c index 4f902927c..17cac3969 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -20,7 +20,7 @@ CodegenTarget guess_target(const char* filename) { return TgtSPV; else if (shd_string_ends_with(filename, "ispc")) return TgtISPC; - error_print("No target has been specified, and output filename '%s' did not allow guessing the right one\n"); + shd_error_print("No target has been specified, and output filename '%s' did not allow guessing the right one\n"); exit(InvalidTarget); } @@ -48,22 +48,22 @@ void cli_parse_common_args(int* pargc, char** argv) { if (i == argc) goto incorrect_log_level; if (strcmp(argv[i], "debugvv") == 0) - set_log_level(DEBUGVV); + shd_log_set_level(DEBUGVV); else if (strcmp(argv[i], "debugv") == 0) - set_log_level(DEBUGV); + shd_log_set_level(DEBUGV); else if (strcmp(argv[i], "debug") == 0) - set_log_level(DEBUG); + shd_log_set_level(DEBUG); else if (strcmp(argv[i], "info") == 0) - set_log_level(INFO); + shd_log_set_level(INFO); else if (strcmp(argv[i], "warn") == 0) - set_log_level(WARN); + shd_log_set_level(WARN); else if (strcmp(argv[i], "error") == 0) - set_log_level(ERROR); + shd_log_set_level(ERROR); else { incorrect_log_level: - error_print("--log-level argument takes one of: "); - error_print("debug, info, warn, error"); - error_print("\n"); + shd_error_print("--log-level argument takes one of: "); + shd_error_print("debug, info, warn, error"); + shd_error_print("\n"); exit(IncorrectLogLevel); } } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { @@ -76,7 +76,7 @@ void cli_parse_common_args(int* pargc, char** argv) { } if (help) { - error_print(" --log-level debug[v[v]], info, warn, error]\n"); + shd_error_print(" --log-level debug[v[v]], info, warn, error]\n"); } cli_pack_remaining_args(pargc, argv); @@ -104,7 +104,7 @@ static IntSizes parse_int_size(String argv) { return IntTy32; if (strcmp(argv, "64") == 0) return IntTy64; - error("Valid pointer sizes are 8, 16, 32 or 64."); + shd_error("Valid pointer sizes are 8, 16, 32 or 64."); } void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { @@ -121,31 +121,31 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a argv[i] = NULL; i++; if (i == argc) - error("Missing entry point name"); + shd_error("Missing entry point name"); config->specialization.entry_point = argv[i]; } else if (strcmp(argv[i], "--subgroup-size") == 0) { argv[i] = NULL; i++; if (i == argc) - error("Missing subgroup size"); + shd_error("Missing subgroup size"); config->specialization.subgroup_size = atoi(argv[i]); } else if (strcmp(argv[i], "--stack-size") == 0) { argv[i] = NULL; i++; if (i == argc) - error("Missing stack size"); + shd_error("Missing stack size"); config->per_thread_stack_size = atoi(argv[i]); } else if (strcmp(argv[i], "--execution-model") == 0) { argv[i] = NULL; i++; if (i == argc) - error("Missing execution model name"); + shd_error("Missing execution model name"); ExecutionModel em = EmNone; #define EM(n, _) if (strcmp(argv[i], #n) == 0) em = Em##n; EXECUTION_MODELS(EM) #undef EM if (em == EmNone) - error("Unknown execution model: %s", argv[i]); + shd_error("Unknown execution model: %s", argv[i]); switch (em) { case EmFragment: case EmVertex: @@ -172,18 +172,18 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a } if (help) { - error_print(" --shd_print-internal Includes internal functions in the debug output\n"); - error_print(" --shd_print-generated Includes generated functions in the debug output\n"); - error_print(" --no-dynamic-scheduling Disable the built-in dynamic scheduler, restricts code to only leaf functions\n"); - error_print(" --simt2d Emits SIMD code instead of SIMT, only effective with the C backend.\n"); - error_print(" --entry-point Selects an entry point for the program to be specialized on.\n"); - error_print(" --word-size <8|16|32|64> Sets the word size for physical memory emulation (default=32)\n"); - error_print(" --pointer-size <8|16|32|64> Sets the pointer size for physical pointers (default=64)\n"); + shd_error_print(" --shd_print-internal Includes internal functions in the debug output\n"); + shd_error_print(" --shd_print-generated Includes generated functions in the debug output\n"); + shd_error_print(" --no-dynamic-scheduling Disable the built-in dynamic scheduler, restricts code to only leaf functions\n"); + shd_error_print(" --simt2d Emits SIMD code instead of SIMT, only effective with the C backend.\n"); + shd_error_print(" --entry-point Selects an entry point for the program to be specialized on.\n"); + shd_error_print(" --word-size <8|16|32|64> Sets the word size for physical memory emulation (default=32)\n"); + shd_error_print(" --pointer-size <8|16|32|64> Sets the pointer size for physical pointers (default=64)\n"); #define EM(name, _) #name", " - error_print(" --execution-model Selects an entry point for the program to be specialized on.\nPossible values: " EXECUTION_MODELS(EM)); + shd_error_print(" --execution-model Selects an entry point for the program to be specialized on.\nPossible values: " EXECUTION_MODELS(EM)); #undef EM - error_print(" --subgroup-size N Sets the subgroup size the program will be specialized for.\n"); - error_print(" --lift-join-points Forcefully lambda-lifts all join points. Can help with reconvergence issues.\n"); + shd_error_print(" --subgroup-size N Sets the subgroup size the program will be specialized for.\n"); + shd_error_print(" --lift-join-points Forcefully lambda-lifts all join points. Can help with reconvergence issues.\n"); } cli_pack_remaining_args(pargc, argv); @@ -228,7 +228,7 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { argv[i] = NULL; i++; if (i == argc) { - error_print("--output must be followed with a filename"); + shd_error_print("--output must be followed with a filename"); exit(MissingOutputArg); } args->output_filename = argv[i]; @@ -236,7 +236,7 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { argv[i] = NULL; i++; if (i == argc) { - error_print("--dump-cfg must be followed with a filename"); + shd_error_print("--dump-cfg must be followed with a filename"); exit(MissingDumpCfgArg); } args->cfg_output_filename = argv[i]; @@ -244,7 +244,7 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { argv[i] = NULL; i++; if (i == argc) { - error_print("--dump-loop-tree must be followed with a filename"); + shd_error_print("--dump-loop-tree must be followed with a filename"); exit(MissingDumpCfgArg); } args->loop_tree_output_filename = argv[i]; @@ -252,7 +252,7 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { argv[i] = NULL; i++; if (i == argc) { - error_print("--dump-ir must be followed with a filename"); + shd_error_print("--dump-ir must be followed with a filename"); exit(MissingDumpIrArg); } args->shd_output_filename = argv[i]; @@ -278,7 +278,7 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { argv[i] = NULL; continue; invalid_target: - error_print("--target must be followed with a valid target (see help for list of targets)"); + shd_error_print("--target must be followed with a valid target (see help for list of targets)"); exit(InvalidTarget); } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { help = true; @@ -290,13 +290,13 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { } if (help) { - // error_print("Usage: slim source.slim\n"); - // error_print("Available arguments: \n"); - error_print(" --target \n"); - error_print(" --output , -o \n"); - error_print(" --dump-cfg Dumps the control flow graph of the final IR\n"); - error_print(" --dump-loop-tree \n"); - error_print(" --dump-ir Dumps the final IR\n"); + // shd_error_print("Usage: slim source.slim\n"); + // shd_error_print("Available arguments: \n"); + shd_error_print(" --target \n"); + shd_error_print(" --output , -o \n"); + shd_error_print(" --dump-cfg Dumps the control flow graph of the final IR\n"); + shd_error_print(" --dump-loop-tree \n"); + shd_error_print(" --dump-ir Dumps the final IR\n"); } cli_pack_remaining_args(pargc, argv); diff --git a/src/driver/driver.c b/src/driver/driver.c index a3572b276..6fbbcf1d2 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -35,7 +35,7 @@ SourceLanguage guess_source_language(const char* filename) { else if (shd_string_ends_with(filename, ".slim")) return SrcShadyIR; - warn_print("unknown filename extension '%s', interpreting as Slim sourcecode by default.", filename); + shd_warn_print("unknown filename extension '%s', interpreting as Slim sourcecode by default.", filename); return SrcSlim; } @@ -63,7 +63,7 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang ParserConfig pconfig = { .front_end = lang == SrcSlim, }; - debugvv_print("Parsing: \n%s\n", file_contents); + shd_debugvv_print("Parsing: \n%s\n", file_contents); *mod = parse_slim_module(config, pconfig, (const char*) file_contents, name); } } @@ -78,12 +78,12 @@ ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* conf assert(filename); bool ok = shd_read_file(filename, &len, &contents); if (!ok) { - error_print("Failed to read file '%s'\n", filename); + shd_error_print("Failed to read file '%s'\n", filename); err = InputFileIOError; goto exit; } if (contents == NULL) { - error_print("file does not exist\n"); + shd_error_print("file does not exist\n"); err = InputFileDoesNotExist; goto exit; } @@ -95,7 +95,7 @@ ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* conf ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { if (shd_list_count(args->input_filenames) == 0) { - error_print("Missing input file. See --help for proper usage"); + shd_error_print("Missing input file. See --help for proper usage"); return MissingInputArg; } @@ -113,23 +113,23 @@ ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { } ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { - debugv_print("Parsed program successfully: \n"); - log_module(DEBUGV, &args->config, mod); + shd_debugv_print("Parsed program successfully: \n"); + shd_log_module(DEBUGV, &args->config, mod); CompilationResult result = run_compiler_passes(&args->config, &mod); if (result != CompilationNoError) { - error_print("Compilation pipeline failed, errcode=%d\n", (int) result); + shd_error_print("Compilation pipeline failed, errcode=%d\n", (int) result); exit(result); } - debug_print("Ran all passes successfully\n"); - log_module(DEBUG, &args->config, mod); + shd_debug_print("Ran all passes successfully\n"); + shd_log_module(DEBUG, &args->config, mod); if (args->cfg_output_filename) { FILE* f = fopen(args->cfg_output_filename, "wb"); assert(f); dump_cfgs(f, mod); fclose(f); - debug_print("CFG dumped\n"); + shd_debug_print("CFG dumped\n"); } if (args->loop_tree_output_filename) { @@ -137,7 +137,7 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { assert(f); dump_loop_trees(f, mod); fclose(f); - debug_print("Loop tree dumped\n"); + shd_debug_print("Loop tree dumped\n"); } if (args->shd_output_filename) { @@ -149,7 +149,7 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { fwrite(output_buffer, output_size, 1, f); free((void*) output_buffer); fclose(f); - debug_print("IR dumped\n"); + shd_debug_print("IR dumped\n"); } if (args->output_filename) { @@ -174,7 +174,7 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; } - debug_print("Wrote result to %s\n", args->output_filename); + shd_debug_print("Wrote result to %s\n", args->output_filename); fwrite(output_buffer, output_size, 1, f); free((void*) output_buffer); fclose(f); diff --git a/src/driver/slim.c b/src/driver/slim.c index 61d4c5fc5..f7e9b81be 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -26,7 +26,7 @@ int main(int argc, char** argv) { err = driver_compile(&args, mod); if (err) exit(err); - info_print("Compilation successful\n"); + shd_info_print("Compilation successful\n"); destroy_ir_arena(arena); destroy_driver_config(&args); diff --git a/src/frontend/llvm/generator_l2s.c b/src/frontend/llvm/generator_l2s.c index f03ef5b43..9c3f8429e 100644 --- a/src/frontend/llvm/generator_l2s.c +++ b/src/frontend/llvm/generator_l2s.c @@ -14,7 +14,7 @@ void generate_llvm_shady_address_space_conversion(Growy* g, json_object* address } shd_growy_append_formatted(g, "\t\tdefault:\n"); shd_growy_append_formatted(g, "\t\t\tif (!warned)\n"); - shd_growy_append_string(g, "\t\t\t\twarn_print(\"Warning: unrecognised address space %d\", as);\n"); + shd_growy_append_string(g, "\t\t\t\tshd_warn_print(\"Warning: unrecognised address space %d\", as);\n"); shd_growy_append_formatted(g, "\t\t\twarned = true;\n"); shd_growy_append_formatted(g, "\t\t\treturn AsGeneric;\n"); shd_growy_append_formatted(g, "\t}\n"); diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index f60c42f37..5cc452e2e 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -61,7 +61,7 @@ static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { continue; shd_dict_insert(LLVMValueRef, const Node*, p->map, instr, emitted); } - log_string(ERROR, "Reached end of LLVM basic block without encountering a terminator!"); + shd_log_fmt(ERROR, "Reached end of LLVM basic block without encountering a terminator!"); SHADY_UNREACHABLE; } @@ -73,8 +73,8 @@ static void write_bb_tail(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); - debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); - if (get_log_level() >= DEBUG) + shd_debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); + if (shd_log_get_level() >= DEBUG) LLVMDumpValue((LLVMValueRef)bb); struct List* phis = shd_new_list(LLVMValueRef); @@ -141,18 +141,18 @@ const Node* convert_basic_block_body(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlo const Node* convert_function(Parser* p, LLVMValueRef fn) { if (is_llvm_intrinsic(fn)) { - warn_print("Skipping unknown LLVM intrinsic function: %s\n", LLVMGetValueName(fn)); + shd_warn_print("Skipping unknown LLVM intrinsic function: %s\n", LLVMGetValueName(fn)); return NULL; } if (is_shady_intrinsic(fn)) { - warn_print("Skipping shady intrinsic function: %s\n", LLVMGetValueName(fn)); + shd_warn_print("Skipping shady intrinsic function: %s\n", LLVMGetValueName(fn)); return NULL; } const Node** found = shd_dict_find_value(LLVMValueRef, const Node*, p->map, fn); if (found) return *found; IrArena* a = get_module_arena(p->dst); - debug_print("Converting function: %s\n", LLVMGetValueName(fn)); + shd_debug_print("Converting function: %s\n", LLVMGetValueName(fn)); Nodes params = empty(a); for (LLVMValueRef oparam = LLVMGetFirstParam(fn); oparam; oparam = LLVMGetNextParam(oparam)) { @@ -248,10 +248,10 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { if (strcmp(intrinsic, "llvm.global.annotations") == 0) { return NULL; } - warn_print("Skipping unknown LLVM intrinsic function: %s\n", name); + shd_warn_print("Skipping unknown LLVM intrinsic function: %s\n", name); return NULL; } - debug_print("Converting global: %s\n", name); + shd_debug_print("Converting global: %s\n", name); Node* decl = NULL; @@ -291,11 +291,11 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* LLVMMemoryBufferRef mem = LLVMCreateMemoryBufferWithMemoryRange(data, len, "my_great_buffer", false); char* parsing_diagnostic = ""; if (LLVMParseIRInContext(context, mem, &src, &parsing_diagnostic)) { - error_print("Failed to parse LLVM IR\n"); - error_print(parsing_diagnostic); + shd_error_print("Failed to parse LLVM IR\n"); + shd_error_print(parsing_diagnostic); shd_error_die(); } - info_print("LLVM IR parsed successfully\n"); + shd_info_print("LLVM IR parsed successfully\n"); ArenaConfig aconfig = default_arena_config(&config->target); aconfig.check_types = false; @@ -329,16 +329,16 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* break; global = LLVMGetNextGlobal(global); } - log_string(DEBUGVV, "Shady module parsed from LLVM:"); - log_module(DEBUGVV, config, dirty); + shd_log_fmt(DEBUGVV, "Shady module parsed from LLVM:"); + shd_log_module(DEBUGVV, config, dirty); aconfig.check_types = true; aconfig.allow_fold = true; IrArena* arena2 = new_ir_arena(&aconfig); *dst = new_module(arena2, name); postprocess(&p, dirty, *dst); - log_string(DEBUGVV, "Shady module parsed from LLVM, after cleanup:"); - log_module(DEBUGVV, config, *dst); + shd_log_fmt(DEBUGVV, "Shady module parsed from LLVM, after cleanup:"); + shd_log_module(DEBUGVV, config, *dst); verify_module(config, *dst); destroy_ir_arena(arena); diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 13ebe999e..da8c7e0d4 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -154,11 +154,11 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { }) }); } else { - error_print("Unrecognised shady annotation '%s'\n", keyword); + shd_error_print("Unrecognised shady annotation '%s'\n", keyword); shd_error_die(); } } else { - warn_print("Ignoring annotation '%s'\n", ostr); + shd_warn_print("Ignoring annotation '%s'\n", ostr); } free(str); //dump_node(annotation_payload); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 311490ef4..d0ba1ad38 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -118,14 +118,14 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B //if (!found) { Nodes str = scope_to_string(p, dbgloc); //insert_dict(const Node*, Nodes, p->scopes, fn_or_bb, str); - debugv_print("Found a debug location for "); - log_node(DEBUGV, fn_or_bb); - debugv_print(" "); + shd_debugv_print("Found a debug location for "); + shd_log_node(DEBUGV, fn_or_bb); + shd_debugv_print(" "); for (size_t i = 0; i < str.count; i++) { - log_node(DEBUGV, str.nodes[i]); - debugv_print(" -> "); + shd_log_node(DEBUGV, str.nodes[i]); + shd_debugv_print(" -> "); } - debugv_print(" (depth= %zu)\n", str.count); + shd_debugv_print(" (depth= %zu)\n", str.count); bind_instruction_single(b, ext_instr(a, (ExtInstr) { .set = "shady.scope", .opcode = 0, @@ -568,21 +568,21 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B Nodes ops = convert_operands(p, num_args, instr); if (strcmp(instructionname, "DebugPrintf") == 0) { if (ops.count == 0) - error("DebugPrintf called without arguments"); + shd_error("DebugPrintf called without arguments"); size_t whocares; gen_debug_printf(b, LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), nodes(a, ops.count - 1, &ops.nodes[1])); return tuple_helper(a, empty(a)); } - error_print("Unrecognised shady instruction '%s'\n", instructionname); + shd_error_print("Unrecognised shady instruction '%s'\n", instructionname); shd_error_die(); } else { - error_print("Unrecognised shady intrinsic '%s'\n", keyword); + shd_error_print("Unrecognised shady intrinsic '%s'\n", keyword); shd_error_die(); } } - error_print("Unhandled intrinsic '%s'\n", intrinsic); + shd_error_print("Unhandled intrinsic '%s'\n", intrinsic); shd_error_die(); } finish: @@ -660,8 +660,8 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B }*/ unimplemented: - error_print("Shady: unimplemented LLVM instruction "); + shd_error_print("Shady: unimplemented LLVM instruction "); LLVMDumpValue(instr); - error_print(" (opcode=%d)\n", opcode); + shd_error_print(" (opcode=%d)\n", opcode); shd_error_die(); } diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index e5a2f1534..afed33741 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -155,9 +155,9 @@ const Node* convert_metadata(Parser* p, LLVMMetadataRef meta) { LLVM_DI_METADATA_NODES(N) #undef N default: default_: - error_print("Unknown metadata kind %d for ", kind); + shd_error_print("Unknown metadata kind %d for ", kind); LLVMDumpValue(v); - error_print(".\n"); + shd_error_print(".\n"); shd_error_die(); } } diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index c1653132e..0b47cb6d8 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -28,7 +28,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { case 16: return uint16_type(a); case 32: return uint32_type(a); case 64: return uint64_type(a); - default: error("Unsupported integer width: %d\n", LLVMGetIntTypeWidth(t)); break; + default: shd_error("Unsupported integer width: %d\n", LLVMGetIntTypeWidth(t)); break; } case LLVMFunctionTypeKind: { unsigned num_params = LLVMCountParamTypes(t); @@ -138,7 +138,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { break; } - error_print("Unsupported type: "); + shd_error_print("Unsupported type: "); LLVMDumpType(t); shd_error_die(); } diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index e5f8d7c64..d7f8229bb 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -159,7 +159,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { uint64_t u = 0; static_assert(sizeof(u) == sizeof(d), ""); switch (t->payload.float_type.width) { - case FloatTy16: error("todo") + case FloatTy16: shd_error("todo") case FloatTy32: { float f = (float) d; static_assert(sizeof(f) == sizeof(uint32_t), ""); @@ -194,8 +194,8 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { return r; } - error_print("Failed to find value "); + shd_error_print("Failed to find value "); LLVMDumpValue(v); - error_print(" in the already emitted map (kind=%d)\n", LLVMGetValueKind(v)); + shd_error_print(" in the already emitted map (kind=%d)\n", LLVMGetValueKind(v)); shd_error_die(); } diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index ab6bd47df..598f06e39 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -68,7 +68,7 @@ static Resolved resolve_using_name(Context* ctx, const char* name) { } } - error("could not resolve node %s", name) + shd_error("could not resolve node %s", name) } static void add_binding(Context* ctx, bool is_var, String name, const Node* node) { @@ -128,7 +128,7 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { static const Node* get_node_address(Context* ctx, const Node* node) { const Node* got = get_node_address_maybe(ctx, node); - if (!got) error("This doesn't really look like a place expression...") + if (!got) shd_error("This doesn't really look like a place expression...") return got; } @@ -145,7 +145,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { Nodes results = deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = get_string_literal(a, names[i]); - log_string(DEBUGV, "Bound immutable variable '%s'\n", name); + shd_log_fmt(DEBUGV, "Bound immutable variable '%s'\n", name); add_binding(ctx, false, name, results.nodes[i]); } break; @@ -166,7 +166,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { bind_instruction_outputs_count(bb, store(a, (Store) { .ptr = ptr, .value = results.nodes[0], .mem = bb_mem(bb) }), 0); add_binding(ctx, true, name, ptr); - log_string(DEBUGV, "Bound mutable variable '%s'\n", name); + shd_log_fmt(DEBUGV, "Bound mutable variable '%s'\n", name); } break; } @@ -181,7 +181,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { bbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(conts[i])); register_processed(r, conts[i], bbs[i]); add_binding(ctx, false, name, bbs[i]); - log_string(DEBUGV, "Bound continuation '%s'\n", name); + shd_log_fmt(DEBUGV, "Bound continuation '%s'\n", name); } for (size_t i = 0; i < names_count; i++) { Context cont_ctx = *ctx; @@ -240,10 +240,10 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { bound->payload.nom_type.body = rewrite_node(&ctx->rewriter, decl->payload.nom_type.body); return bound; } - default: error("unknown declaration kind"); + default: shd_error("unknown declaration kind"); } - error("unreachable") + shd_error("unreachable") //register_processed(&ctx->rewriter, decl, bound); //return bound; } @@ -285,7 +285,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { assert(is_declaration(node)); return rewrite_decl(ctx, node); } - case Param_TAG: error("the binders should be handled such that this node is never reached"); + case Param_TAG: shd_error("the binders should be handled such that this node is never reached"); case BasicBlock_TAG: { assert(is_basic_block(node)); Nodes new_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 9b94801ee..f1df0e79b 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -47,7 +47,7 @@ static Nodes infer_nodes(Context* ctx, Nodes nodes) { return rewrite_nodes(&ctx->rewriter, nodes); } -#define rewrite_node error("don't use this directly, use the 'infer' and 'infer_node' helpers") +#define rewrite_node shd_error("don't use this directly, use the 'infer' and 'infer_node' helpers") #define rewrite_nodes rewrite_node static const Node* infer_annotation(Context* ctx, const Node* node) { @@ -58,7 +58,7 @@ static const Node* infer_annotation(Context* ctx, const Node* node) { case AnnotationValue_TAG: return annotation_value(a, (AnnotationValue) { .name = node->payload.annotation_value.name, .value = infer(ctx, node->payload.annotation_value.value, NULL) }); case AnnotationValues_TAG: return annotation_values(a, (AnnotationValues) { .name = node->payload.annotation_values.name, .values = infer_nodes(ctx, node->payload.annotation_values.values) }); case AnnotationCompound_TAG: return annotation_compound(a, (AnnotationCompound) { .name = node->payload.annotation_compound.name, .entries = infer_nodes(ctx, node->payload.annotation_compound.entries) }); - default: error("Not an annotation"); + default: shd_error("Not an annotation"); } } @@ -146,7 +146,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { nnominal_type->payload.nom_type.body = infer(ctx, onom_type->body, NULL); return nnominal_type; } - case NotADeclaration: error("not a decl"); + case NotADeclaration: shd_error("not a decl"); } } @@ -163,7 +163,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; switch (is_value(node)) { - case NotAValue: error(""); + case NotAValue: shd_error(""); case Param_TAG: case Value_ConstrainedValue_TAG: { const Type* type = infer(ctx, node->payload.constrained.type, NULL); @@ -204,7 +204,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec uint64_t v; switch (expected_type->payload.float_type.width) { case FloatTy16: - error("TODO: implement fp16 parsing"); + shd_error("TODO: implement fp16 parsing"); case FloatTy32: assert(sizeof(float) == sizeof(uint32_t)); float f = strtof(node->payload.untyped_number.plaintext, NULL); @@ -403,13 +403,13 @@ static const Node* infer_indirect_call(Context* ctx, const Node* node, const Nod const Type* callee_type = get_unqualified_type(new_callee->type); if (callee_type->tag != PtrType_TAG) - error("functions are called through function pointers"); + shd_error("functions are called through function pointers"); callee_type = callee_type->payload.ptr_type.pointed_type; if (callee_type->tag != FnType_TAG) - error("Callees must have a function type"); + shd_error("Callees must have a function type"); if (callee_type->payload.fn_type.param_types.count != node->payload.call.args.count) - error("Mismatched argument counts"); + shd_error("Mismatched argument counts"); for (size_t i = 0; i < node->payload.call.args.count; i++) { const Node* arg = node->payload.call.args.nodes[i]; assert(arg); @@ -537,7 +537,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* return stack_alloc(a, (StackAlloc) { .type = infer_type(ctx, element_type), .mem = infer(ctx, node->payload.stack_alloc.mem, NULL) }); } default: break; - case NotAnInstruction: error("not an instruction"); + case NotAnInstruction: shd_error("not an instruction"); } return recreate_node_identity(&ctx->rewriter, node); } @@ -547,7 +547,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { switch (is_terminator(node)) { case NotATerminator: assert(false); case If_TAG: return infer_if (ctx, node); - case Match_TAG: error("TODO") + case Match_TAG: shd_error("TODO") case Loop_TAG: return infer_loop (ctx, node); case Control_TAG: return infer_control(ctx, node); case Return_TAG: { diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 92f8b5cd1..5887f822c 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -30,7 +30,7 @@ static int get_precedence(InfixOperators op) { #define INFIX_OPERATOR(name, token, primop_op, precedence) case Infix##name: return precedence; INFIX_OPERATORS() #undef INFIX_OPERATOR - default: error("unknown operator"); + default: shd_error("unknown operator"); } } static bool is_primop_op(InfixOperators op, Op* out) { @@ -38,7 +38,7 @@ static bool is_primop_op(InfixOperators op, Op* out) { #define INFIX_OPERATOR(name, token, primop_op, precedence) case Infix##name: if (primop_op != -1) { *out = primop_op; return true; } else return false; INFIX_OPERATORS() #undef INFIX_OPERATOR - default: error("unknown operator"); + default: shd_error("unknown operator"); } } @@ -74,19 +74,19 @@ static void error_with_loc(ctxparams) { size_t len = strlen(contents); for (size_t i = 0; i < len; i++) { if (line >= startline && line <= endline) { - log_string(ERROR, "%c", contents[i]); + shd_log_fmt(ERROR, "%c", contents[i]); } if (contents[i] == '\n') { if (line == loc.line) { for (size_t digit = 0; digit < numdigits; digit++) { - log_string(ERROR, " "); + shd_log_fmt(ERROR, " "); } - log_string(ERROR, " "); + shd_log_fmt(ERROR, " "); for (size_t j = 1; j < loc.column; j++) { - log_string(ERROR, " "); + shd_log_fmt(ERROR, " "); } - log_string(ERROR, "^"); - log_string(ERROR, "\n"); + shd_log_fmt(ERROR, "^"); + shd_log_fmt(ERROR, "\n"); } line++; @@ -102,13 +102,13 @@ static void error_with_loc(ctxparams) { digits[numdigits - 1 - digit] = (char) ' '; } for (digit = 0; digit < numdigits; digit++) { - log_string(ERROR, "%c", digits[numdigits - 1 - digit]); + shd_log_fmt(ERROR, "%c", digits[numdigits - 1 - digit]); } - log_string(ERROR, ": "); + shd_log_fmt(ERROR, ": "); } } } - log_string(ERROR, "At %d:%d, ", loc.line, loc.column); + shd_log_fmt(ERROR, "At %d:%d, ", loc.line, loc.column); } #define syntax_error(condition) syntax_error_impl(ctx, condition) @@ -117,8 +117,8 @@ static void syntax_error_impl(ctxparams, const char* format, ...) { va_list args; va_start(args, format); error_with_loc(ctx); - log_fmtv(ERROR, format, args); - log_string(ERROR, "\n"); + shd_log_fmt_va_list(ERROR, format, args); + shd_log_fmt(ERROR, "\n"); exit(-4); va_end(args); } @@ -130,9 +130,9 @@ static void expect_impl(ctxparams, bool condition, const char* format, ...) { va_list args; va_start(args, format); error_with_loc(ctx); - log_string(ERROR, "expected "); - log_fmtv(ERROR, format, args); - log_string(ERROR, "\n"); + shd_log_fmt(ERROR, "expected "); + shd_log_fmt_va_list(ERROR, format, args); + shd_log_fmt(ERROR, "\n"); exit(-4); va_end(args); } @@ -1240,9 +1240,9 @@ void slim_parse_string(ParserConfig config, const char* contents, Module* mod) { if (!decl) decl = accept_nominal_type_decl(ctx, annotations); if (decl) { - log_string(DEBUGVV, "decl parsed : "); - log_node(DEBUGVV, decl); - log_string(DEBUGVV, "\n"); + shd_log_fmt(DEBUGVV, "decl parsed : "); + shd_log_node(DEBUGVV, decl); + shd_log_fmt(DEBUGVV, "\n"); continue; } diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index 276f6bfda..dc57ca5ea 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -29,8 +29,8 @@ Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, co Module** pmod = &m; Module* old_mod = NULL; - debugv_print("Parsed slim module:\n"); - log_module(DEBUGV, config, *pmod); + shd_debugv_print("Parsed slim module:\n"); + shd_log_module(DEBUGV, config, *pmod); generate_dummy_constants(config, *pmod); diff --git a/src/frontend/slim/token.c b/src/frontend/slim/token.c index 0b90c5ce2..907702c93 100644 --- a/src/frontend/slim/token.c +++ b/src/frontend/slim/token.c @@ -107,7 +107,7 @@ static void eat_whitespace_and_comments(Tokenizer* tokenizer) { Token next_token(Tokenizer* tokenizer) { eat_whitespace_and_comments(tokenizer); if (tokenizer->pos == tokenizer->source_size) { - debugvv_print("EOF\n"); + shd_debugvv_print("EOF\n"); Token token = { .tag = EOF_tok }; @@ -192,7 +192,7 @@ Token next_token(Tokenizer* tokenizer) { goto parsed_successfully; } - error_print("We don't know how to tokenize %.16s...\n", slice); + shd_error_print("We don't know how to tokenize %.16s...\n", slice); exit(-2); parsed_successfully: diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 63c861d8a..77b0972b5 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -232,7 +232,7 @@ AddressSpace convert_storage_class(SpvStorageClass class) { default: break; } - error("s2s: Unsupported storage class: %d\n", class); + shd_error("s2s: Unsupported storage class: %d\n", class); } typedef struct { @@ -355,7 +355,7 @@ SpvId get_result_defined_at(SpvParser* parser, size_t instruction_offset) { result = instruction[1]; return result; } - error("no result defined at offset %zu", instruction_offset); + shd_error("no result defined at offset %zu", instruction_offset); } void scan_definitions(SpvParser* parser) { @@ -518,7 +518,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { type = "Vertex"; break; default: - error("Unsupported execution model %d", instruction[1]) + shd_error("Unsupported execution model %d", instruction[1]) } add_decoration(parser, instruction[2], (SpvDeco) { .decoration = ShdDecorationEntryPointType, @@ -573,7 +573,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case 16: w = IntTy16; break; case 32: w = IntTy32; break; case 64: w = IntTy64; break; - default: error("unhandled int width"); + default: shd_error("unhandled int width"); } parser->defs[result].type = Typ; parser->defs[result].node = int_type(parser->arena, (Int) { @@ -589,7 +589,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case 16: w = FloatTy16; break; case 32: w = FloatTy32; break; case 64: w = FloatTy64; break; - default: error("unhandled float width"); + default: shd_error("unhandled float width"); } parser->defs[result].type = Typ; parser->defs[result].node = float_type(parser->arena, (Float) { @@ -700,7 +700,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { }); break; } - default: error("OpConstant must produce an int or a float"); + default: shd_error("OpConstant must produce an int or a float"); } break; } @@ -808,7 +808,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } else if (strcmp(entry_point_type->payload.str, "Vertex") == 0) { } else { - warn_print("Unknown entry point type '%s' for '%s'\n", entry_point_type->payload.str, name); + shd_warn_print("Unknown entry point type '%s' for '%s'\n", entry_point_type->payload.str, name); } } @@ -942,7 +942,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { shd_dict_insert(SpvId, SpvPhiArgs*, parser->phi_arguments, parser->current_block.id, new); } - debugv_print("s2s: recorded argument %d (value id=%d) for block %d with predecessor %d\n", parser->fun_arg_i, argument_value, parser->current_block.id, predecessor_block); + shd_debugv_print("s2s: recorded argument %d (value id=%d) for block %d with predecessor %d\n", parser->fun_arg_i, argument_value, parser->current_block.id, predecessor_block); } parser->fun_arg_i++; break; @@ -1210,7 +1210,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { .operands = singleton(args[0]) }); break; - default: error("unhandled extended instruction %d in set '%s'", ext_instr, set); + default: shd_error("unhandled extended instruction %d in set '%s'", ext_instr, set); } } else if (strcmp(set, "GLSL.std.450") == 0) { switch (ext_instr) { @@ -1263,10 +1263,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case GLSLstd450UMax: instr = prim_op(parser->arena, (PrimOp) { .op = max_op, .operands = mk_nodes(parser->arena, args[0], args[1]) }); break; case GLSLstd450Exp: instr = prim_op(parser->arena, (PrimOp) { .op = exp_op, .operands = singleton(args[0]) }); break; case GLSLstd450Pow: instr = prim_op(parser->arena, (PrimOp) { .op = pow_op, .operands = mk_nodes(parser->arena, args[0], args[1]) }); break; - default: error("unhandled extended instruction %d in set '%s'", ext_instr, set); + default: shd_error("unhandled extended instruction %d in set '%s'", ext_instr, set); } } else { - error("Unknown extended instruction set '%s'", set); + shd_error("Unknown extended instruction set '%s'", set); } parser->defs[result].type = Value; @@ -1308,7 +1308,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->current_block.builder = NULL; break; } - default: error("Unsupported op: %d, size: %d", op, size); + default: shd_error("Unsupported op: %d, size: %d", op, size); } if (has_result) { @@ -1321,7 +1321,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { SpvDef* get_definition_by_id(SpvParser* parser, size_t id) { assert(id > 0 && id < parser->header.bound); if (parser->defs[id].type == Nothing) - error("there is no Op that defines result %zu", id); + shd_error("there is no Op that defines result %zu", id); if (parser->defs[id].type == Forward) parse_spv_instruction_at(parser, parser->defs[id].instruction_offset); assert(parser->defs[id].type != Forward); diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 799ac063d..225943a1a 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -122,7 +122,7 @@ Backend* initialize_cuda_backend(Runtime* base) { return &backend->base; init_fail_free: - error_print("Failed to initialise the CUDA back-end.\n"); + shd_error_print("Failed to initialise the CUDA back-end.\n"); free(backend); return NULL; } \ No newline at end of file diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index fc82eb8c6..db8fc4687 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -7,8 +7,8 @@ #include #include -#define CHECK_NVRTC(x, failure_handler) { nvrtcResult the_result_ = x; if (the_result_ != NVRTC_SUCCESS) { const char* msg = nvrtcGetErrorString(the_result_); error_print(#x " failed (%s)\n", msg); failure_handler; } } -#define CHECK_CUDA(x, failure_handler) { CUresult the_result_ = x; if (the_result_ != CUDA_SUCCESS) { const char* msg; cuGetErrorName(the_result_, &msg); error_print(#x " failed (%s)\n", msg); failure_handler; } } +#define CHECK_NVRTC(x, failure_handler) { nvrtcResult the_result_ = x; if (the_result_ != NVRTC_SUCCESS) { const char* msg = nvrtcGetErrorString(the_result_); shd_error_print(#x " failed (%s)\n", msg); failure_handler; } } +#define CHECK_CUDA(x, failure_handler) { CUresult the_result_ = x; if (the_result_ != CUDA_SUCCESS) { const char* msg; cuGetErrorName(the_result_, &msg); shd_error_print(#x " failed (%s)\n", msg); failure_handler; } } typedef struct { Program* base; diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 68b075d12..2cf520191 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -60,7 +60,7 @@ static bool cuda_c_to_ptx(CudaKernel* kernel) { nvrtcResult compile_result = nvrtcCompileProgram(program, sizeof(options)/sizeof(*options), options); if (compile_result != NVRTC_SUCCESS) { - error_print("NVRTC compilation failed: %s\n", nvrtcGetErrorString(compile_result)); + shd_error_print("NVRTC compilation failed: %s\n", nvrtcGetErrorString(compile_result)); debug_print("Dumping source:\n%s", kernel->cuda_code); } @@ -68,7 +68,7 @@ static bool cuda_c_to_ptx(CudaKernel* kernel) { CHECK_NVRTC(nvrtcGetProgramLogSize(program, &log_size), return false); char* log_buffer = calloc(log_size, 1); CHECK_NVRTC(nvrtcGetProgramLog(program, log_buffer), return false); - log_string(compile_result == NVRTC_SUCCESS ? DEBUG : ERROR, "NVRTC compilation log: %s\n", log_buffer); + shd_log_fmt(compile_result == NVRTC_SUCCESS ? DEBUG : ERROR, "NVRTC compilation log: %s\n", log_buffer); free(log_buffer); CHECK_NVRTC(nvrtcGetPTXSize(program, &kernel->ptx_size), return false); @@ -125,7 +125,7 @@ static bool load_ptx_into_cuda_program(CudaKernel* kernel) { if (*info_log) info_print("CUDA JIT info: %s\n", info_log); if (*error_log) - error_print("CUDA JIT failed: %s\n", error_log); + shd_error_print("CUDA JIT failed: %s\n", error_log); err_linker_create: return false; } diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 72d48bcc5..6a1185bed 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -25,11 +25,11 @@ Runtime* initialize_runtime(RuntimeConfig config) { append_list(Backend*, runtime->backends, cuda_backend); #endif - info_print("Shady runtime successfully initialized !\n"); + shd_info_print("Shady runtime successfully initialized !\n"); return runtime; init_fail_free: - error_print("Failed to initialise the runtime.\n"); + shd_error_print("Failed to initialise the runtime.\n"); free(runtime); return NULL; } diff --git a/src/runtime/runtime_app_common.h b/src/runtime/runtime_app_common.h index c40ea92c2..f485c22bd 100644 --- a/src/runtime/runtime_app_common.h +++ b/src/runtime/runtime_app_common.h @@ -27,7 +27,7 @@ static void cli_parse_common_app_arguments(CommonAppArgs* args, int* pargc, char argv[i] = NULL; i++; if (i >= argc) { - error_print("Missing device number for --device\n"); + shd_error_print("Missing device number for --device\n"); exit(1); } args->device = strtol(argv[i], NULL, 10); @@ -38,12 +38,12 @@ static void cli_parse_common_app_arguments(CommonAppArgs* args, int* pargc, char } if (help) { - error_print("Usage: runtime_test [source.slim]\n"); - error_print("Available arguments: \n"); - error_print(" --log-level debug[v[v]], info, warn, error]\n"); - error_print(" --shd_print-builtin\n"); - error_print(" --shd_print-generated\n"); - error_print(" --device n\n"); + shd_error_print("Usage: runtime_test [source.slim]\n"); + shd_error_print("Available arguments: \n"); + shd_error_print(" --log-level debug[v[v]], info, warn, error]\n"); + shd_error_print(" --shd_print-builtin\n"); + shd_error_print(" --shd_print-generated\n"); + shd_error_print(" --device n\n"); exit(0); } diff --git a/src/runtime/runtime_cli.c b/src/runtime/runtime_cli.c index a705a38b4..74f2dcc66 100644 --- a/src/runtime/runtime_cli.c +++ b/src/runtime/runtime_cli.c @@ -36,13 +36,13 @@ void cli_parse_runtime_config(RuntimeConfig* config, int* pargc, char** argv) { } if (help) { - // error_print("Usage: slim source.slim\n"); - // error_print("Available arguments: \n"); - error_print(" --target \n"); - error_print(" --output , -o \n"); - error_print(" --dump-cfg Dumps the control flow graph of the final IR\n"); - error_print(" --dump-loop-tree \n"); - error_print(" --dump-ir Dumps the final IR\n"); + // shd_error_print("Usage: slim source.slim\n"); + // shd_error_print("Available arguments: \n"); + shd_error_print(" --target \n"); + shd_error_print(" --output , -o \n"); + shd_error_print(" --dump-cfg Dumps the control flow graph of the final IR\n"); + shd_error_print(" --dump-loop-tree \n"); + shd_error_print(" --dump-ir Dumps the final IR\n"); } cli_pack_remaining_args(pargc, argv); diff --git a/src/runtime/runtime_private.h b/src/runtime/runtime_private.h index a8d6e2d72..988bdfe7c 100644 --- a/src/runtime/runtime_private.h +++ b/src/runtime/runtime_private.h @@ -3,7 +3,7 @@ #include "shady/runtime.h" #include "shady/ir.h" -#define CHECK(x, failure_handler) { if (!(x)) { error_print(#x " failed\n"); failure_handler; } } +#define CHECK(x, failure_handler) { if (!(x)) { shd_error_print(#x " failed\n"); failure_handler; } } // typedef struct SpecProgram_ SpecProgram; diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 7f31a1edb..965937bd6 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -29,7 +29,7 @@ static const char* default_shader = "}"; int main(int argc, char* argv[]) { - set_log_level(INFO); + shd_log_set_level(INFO); Args args = { .driver_config = default_driver_config(), .runtime_config = default_runtime_config(), @@ -40,7 +40,7 @@ int main(int argc, char* argv[]) { cli_parse_compiler_config_args(&args.driver_config.config, &argc, argv); cli_parse_input_files(args.driver_config.input_filenames, &argc, argv); - info_print("Shady runtime test starting...\n"); + shd_info_print("Shady runtime test starting...\n"); Runtime* runtime = initialize_runtime(args.runtime_config); Device* device = get_device(runtime, args.common_app_args.device); diff --git a/src/runtime/vulkan/vk_runtime.c b/src/runtime/vulkan/vk_runtime.c index e5d58a600..ac694126f 100644 --- a/src/runtime/vulkan/vk_runtime.c +++ b/src/runtime/vulkan/vk_runtime.c @@ -9,7 +9,7 @@ #include static VKAPI_ATTR VkBool32 VKAPI_CALL the_callback(SHADY_UNUSED VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, SHADY_UNUSED VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, SHADY_UNUSED void* pUserData) { - warn_print("Validation says: %s\n", pCallbackData->pMessage); + shd_warn_print("Validation says: %s\n", pCallbackData->pMessage); return VK_FALSE; } @@ -52,7 +52,7 @@ static bool initialize_vk_instance(VkrBackend* runtime) { // Enable validation if the config says so if (runtime->base.runtime->config.use_validation && strcmp(layer->layerName, "VK_LAYER_KHRONOS_validation") == 0) { - info_print("Enabling validation... \n"); + shd_info_print("Enabling validation... \n"); runtime->enabled_layers.validation.enabled = true; enabled_layers[enabled_layers_count++] = layer->layerName; } @@ -71,7 +71,7 @@ static bool initialize_vk_instance(VkrBackend* runtime) { #define X(is_required, name, _) \ if (strcmp(extension->extensionName, "VK_"#name) == 0) { \ - info_print("Enabling instance extension VK_"#name"\n"); \ + shd_info_print("Enabling instance extension VK_"#name"\n"); \ runtime->instance_exts.name.enabled = true; \ enabled_extensions[enabled_extensions_count++] = extension->extensionName; \ } @@ -106,12 +106,12 @@ static bool initialize_vk_instance(VkrBackend* runtime) { case VK_ERROR_INCOMPATIBLE_DRIVER: { // Vulkan 1.0 is not worth supporting. It has many API warts and 1.1 fixes many of them. // the hardware support is basically identical, so you're not cutting off any devices, just stinky old drivers. - error_print("vkCreateInstance reported VK_ERROR_INCOMPATIBLE_DRIVER. This most certainly means you're trying to run on a Vulkan 1.0 implementation.\n"); - error_print("This application is written with Vulkan 1.1 as the baseline, you will need to update your Vulkan loader and/or driver."); + shd_error_print("vkCreateInstance reported VK_ERROR_INCOMPATIBLE_DRIVER. This most certainly means you're trying to run on a Vulkan 1.0 implementation.\n"); + shd_error_print("This application is written with Vulkan 1.1 as the baseline, you will need to update your Vulkan loader and/or driver."); return false; } default: { - error_print("vkCreateInstanced failed (%u)\n", err_create_instance); + shd_error_print("vkCreateInstanced failed (%u)\n", err_create_instance); return false; } } @@ -144,11 +144,11 @@ Backend* initialize_vk_backend(Runtime* base) { CHECK(initialize_vk_instance(backend), goto init_fail_free) probe_vkr_devices(backend); - info_print("Shady Vulkan backend successfully initialized !\n"); + shd_info_print("Shady Vulkan backend successfully initialized !\n"); return &backend->base; init_fail_free: - error_print("Failed to initialise the Vulkan back-end.\n"); + shd_error_print("Failed to initialise the Vulkan back-end.\n"); free(backend); return NULL; } diff --git a/src/runtime/vulkan/vk_runtime_buffer.c b/src/runtime/vulkan/vk_runtime_buffer.c index 80a75a5a9..211dc88c5 100644 --- a/src/runtime/vulkan/vk_runtime_buffer.c +++ b/src/runtime/vulkan/vk_runtime_buffer.c @@ -32,14 +32,14 @@ static uint32_t find_suitable_memory_type(VkrDevice* device, uint32_t memory_typ } } } - error("Unable to find a suitable memory type") + shd_error("Unable to find a suitable memory type") } static Buffer make_base_buffer(VkrDevice*); VkrBuffer* vkr_allocate_buffer_device_(VkrDevice* device, size_t size, AllocHeap heap) { if (!device->caps.features.buffer_device_address.bufferDeviceAddress) { - error_print("device buffers require VK_KHR_buffer_device_address\n"); + shd_error_print("device buffers require VK_KHR_buffer_device_address\n"); return NULL; } @@ -109,12 +109,12 @@ VkrBuffer* vkr_allocate_buffer_device(VkrDevice* device, size_t size) { static bool vkr_can_import_host_memory_(VkrDevice* device, bool log) { if (!device->caps.supported_extensions[ShadySupportsEXT_external_memory_host]) { if (log) - error_print("host imported buffers require VK_EXT_external_memory_host\n"); + shd_error_print("host imported buffers require VK_EXT_external_memory_host\n"); return false; } if (!device->caps.features.buffer_device_address.bufferDeviceAddress) { if (log) - error_print("host imported buffers require VK_KHR_buffer_device_address\n"); + shd_error_print("host imported buffers require VK_KHR_buffer_device_address\n"); return false; } return true; @@ -140,7 +140,7 @@ VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { size_t aligned_addr = (unaligned_addr / desired_alignment) * desired_alignment; assert(unaligned_addr >= aligned_addr); buffer->offset = unaligned_addr - aligned_addr; - debug_print("desired alignment = %zu, offset = %zu\n", desired_alignment, buffer->offset); + shd_debug_print("desired alignment = %zu, offset = %zu\n", desired_alignment, buffer->offset); size_t unaligned_end = unaligned_addr + size; assert(unaligned_end >= aligned_addr); @@ -149,8 +149,8 @@ VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { size_t aligned_size = aligned_end - aligned_addr; assert(aligned_size >= size); assert(aligned_size % desired_alignment == 0); - debug_print("unaligned start %zu end %zu\n", unaligned_addr, unaligned_end); - debug_print("aligned start %zu end %zu\n", aligned_addr, aligned_end); + shd_debug_print("unaligned start %zu end %zu\n", unaligned_addr, unaligned_end); + shd_debug_print("aligned start %zu end %zu\n", aligned_addr, aligned_end); buffer->host_ptr = (void*) aligned_addr; buffer->size = aligned_size; @@ -180,7 +180,7 @@ VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { uint32_t memory_type_index = find_suitable_memory_type(device, host_ptr_properties.memoryTypeBits, AllocHostVisible); VkPhysicalDeviceMemoryProperties device_memory_properties; vkGetPhysicalDeviceMemoryProperties(device->caps.physical_device, &device_memory_properties); - debug_print("memory type index: %d heap: %d\n", memory_type_index, device_memory_properties.memoryTypes[memory_type_index].heapIndex); + shd_debug_print("memory type index: %d heap: %d\n", memory_type_index, device_memory_properties.memoryTypes[memory_type_index].heapIndex); VkMemoryAllocateInfo allocation_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index 448e6f1f3..64f2e6d09 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -62,7 +62,7 @@ static void figure_out_spirv_version(VkrDeviceCaps* caps) { caps->spirv_version.minor = 6; } - debug_print("Using SPIR-V version %d.%d, on Vulkan %d.%d\n", caps->spirv_version.major, caps->spirv_version.minor, major, minor); + shd_debug_print("Using SPIR-V version %d.%d, on Vulkan %d.%d\n", caps->spirv_version.major, caps->spirv_version.minor, major, minor); } static bool fill_device_properties(VkrDeviceCaps* caps) { @@ -70,13 +70,13 @@ static bool fill_device_properties(VkrDeviceCaps* caps) { vkGetPhysicalDeviceProperties2(caps->physical_device, &caps->properties.base); if (caps->properties.base.properties.apiVersion < VK_MAKE_API_VERSION(0, 1, 1, 0)) { - info_print("Rejecting device '%s' because it does not support Vulkan 1.1 or later\n", caps->properties.base.properties.deviceName); + shd_info_print("Rejecting device '%s' because it does not support Vulkan 1.1 or later\n", caps->properties.base.properties.deviceName); return false; } String missing_ext; if (!fill_available_extensions(caps->physical_device, NULL, &missing_ext, caps->supported_extensions)) { - info_print("Rejecting device %s because it lacks support for '%s'\n", caps->properties.base.properties.deviceName, missing_ext); + shd_info_print("Rejecting device %s because it lacks support for '%s'\n", caps->properties.base.properties.deviceName, missing_ext); return false; } @@ -114,7 +114,7 @@ static bool fill_device_properties(VkrDeviceCaps* caps) { caps->subgroup_size.max = caps->properties.subgroup.subgroupSize; caps->subgroup_size.min = caps->properties.subgroup.subgroupSize; } - debug_print("Subgroup size range for device '%s' is [%d; %d]\n", caps->properties.base.properties.deviceName, caps->subgroup_size.min, caps->subgroup_size.max); + shd_debug_print("Subgroup size range for device '%s' is [%d; %d]\n", caps->properties.base.properties.deviceName, caps->subgroup_size.min, caps->subgroup_size.max); return true; } @@ -157,7 +157,7 @@ static bool fill_device_features(VkrDeviceCaps* caps) { vkGetPhysicalDeviceFeatures2(caps->physical_device, &caps->features.base); if (!caps->features.subgroup_size_control.computeFullSubgroups) { - warn_print("Potentially broken behaviour on device %s because it does not support computeFullSubgroups", caps->properties.base.properties.deviceName); + shd_warn_print("Potentially broken behaviour on device %s because it does not support computeFullSubgroups", caps->properties.base.properties.deviceName); // TODO just outright reject such devices ? } @@ -183,7 +183,7 @@ static bool fill_queue_properties(VkrDeviceCaps* caps) { } } if (compute_queue_family >= queue_families_count) { - info_print("Rejecting device %s because it lacks a compute queue family\n", caps->properties.base.properties.deviceName); + shd_info_print("Rejecting device %s because it lacks a compute queue family\n", caps->properties.base.properties.deviceName); return false; } caps->compute_queue_family = compute_queue_family; @@ -237,7 +237,7 @@ static VkrDevice* create_vkr_device(SHADY_UNUSED VkrBackend* runtime, VkPhysical VkrDevice* device = calloc(1, sizeof(VkrDevice)); device->runtime = runtime; CHECK(get_physical_device_caps(runtime, physical_device, &device->caps), assert(false)); - info_print("Initialising device %s\n", device->caps.properties.base.properties.deviceName); + shd_info_print("Initialising device %s\n", device->caps.properties.base.properties.deviceName); LARRAY(const char*, enabled_device_exts, ShadySupportedDeviceExtensionsCount); size_t enabled_device_exts_count; @@ -308,8 +308,8 @@ bool probe_vkr_devices(VkrBackend* runtime) { CHECK_VK(vkEnumeratePhysicalDevices(runtime->instance, &devices_count, available_devices), return false) if (devices_count == 0 && !runtime->base.runtime->config.allow_no_devices) { - error_print("No vulkan devices found!\n"); - error_print("You may be able to diagnose this further using `VK_LOADER_DEBUG=all vulkaninfo`.\n"); + shd_error_print("No vulkan devices found!\n"); + shd_error_print("You may be able to diagnose this further using `VK_LOADER_DEBUG=all vulkaninfo`.\n"); return false; } @@ -331,12 +331,12 @@ bool probe_vkr_devices(VkrBackend* runtime) { } if (shd_list_count(runtime->base.runtime->devices) == 0 && !runtime->base.runtime->config.allow_no_devices) { - error_print("No __suitable__ vulkan devices found!\n"); - error_print("This is caused by running on weird hardware configurations. Hardware support might get better in the future.\n"); + shd_error_print("No __suitable__ vulkan devices found!\n"); + shd_error_print("This is caused by running on weird hardware configurations. Hardware support might get better in the future.\n"); return false; } - info_print("Found %d usable devices\n", shd_list_count(runtime->base.runtime->devices)); + shd_info_print("Found %d usable devices\n", shd_list_count(runtime->base.runtime->devices)); return true; } diff --git a/src/runtime/vulkan/vk_runtime_dispatch.c b/src/runtime/vulkan/vk_runtime_dispatch.c index 379ef7fd9..bcf69f244 100644 --- a/src/runtime/vulkan/vk_runtime_dispatch.c +++ b/src/runtime/vulkan/vk_runtime_dispatch.c @@ -62,7 +62,7 @@ VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_ VkrSpecProgram* prog = get_specialized_program(program, entry_point, device); - debug_print("Dispatching kernel on %s\n", device->caps.properties.base.properties.deviceName); + shd_debug_print("Dispatching kernel on %s\n", device->caps.properties.base.properties.deviceName); VkrCommand* cmd = vkr_begin_command(device); if (!cmd) diff --git a/src/runtime/vulkan/vk_runtime_private.h b/src/runtime/vulkan/vk_runtime_private.h index 1361b5caf..62fa6dd7a 100644 --- a/src/runtime/vulkan/vk_runtime_private.h +++ b/src/runtime/vulkan/vk_runtime_private.h @@ -62,7 +62,7 @@ SHADY_UNUSED static const bool is_instance_ext_required[] = { INSTANCE_EXTENSION SHADY_UNUSED static const bool is_device_ext_required[] = { DEVICE_EXTENSIONS(R) }; #undef R -#define CHECK_VK(x, failure_handler) { VkResult the_result_ = x; if (the_result_ != VK_SUCCESS) { error_print(#x " failed (code %d)\n", the_result_); failure_handler; } } +#define CHECK_VK(x, failure_handler) { VkResult the_result_ = x; if (the_result_ != VK_SUCCESS) { shd_error_print(#x " failed (code %d)\n", the_result_); failure_handler; } } typedef struct VkrSpecProgram_ VkrSpecProgram; diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 6c4662005..7a9bbdcf0 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -41,7 +41,7 @@ VkDescriptorType as_to_descriptor_type(AddressSpace as) { switch (as) { case AsUniform: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; case AsShaderStorageBufferObject: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - default: error("No mapping to a descriptor type"); + default: shd_error("No mapping to a descriptor type"); } } @@ -184,7 +184,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay static bool extract_layout(VkrSpecProgram* program) { if (program->parameters.args_size > program->device->caps.properties.base.properties.limits.maxPushConstantsSize) { - error_print("EntryPointArgs exceed available push constant space\n"); + shd_error_print("EntryPointArgs exceed available push constant space\n"); return false; } VkPushConstantRange push_constant_ranges[1] = { @@ -262,13 +262,13 @@ static CompilerConfig get_compiler_config_for_device(VkrDevice* device, const Co config.lower.int64 = !device->caps.features.base.features.shaderInt64; if (device->caps.implementation.is_moltenvk) { - warn_print("Hack: MoltenVK says they supported subgroup extended types, but it's a lie. 64-bit types are unaccounted for !\n"); + shd_warn_print("Hack: MoltenVK says they supported subgroup extended types, but it's a lie. 64-bit types are unaccounted for !\n"); config.lower.emulate_subgroup_ops_extended_types = true; - warn_print("Hack: MoltenVK does not support pointers to unsized arrays properly.\n"); + shd_warn_print("Hack: MoltenVK does not support pointers to unsized arrays properly.\n"); config.lower.decay_ptrs = true; } if (device->caps.properties.driver_properties.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) { - warn_print("Hack: NVidia somehow has unreliable broadcast_first. Emulating it with shuffles seemingly fixes the issue.\n"); + shd_warn_print("Hack: NVidia somehow has unreliable broadcast_first. Emulating it with shuffles seemingly fixes the issue.\n"); config.hacks.spv_shuffle_instead_of_broadcast_first = true; } @@ -290,12 +290,12 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) const Node* entry_point_args_annotation = lookup_annotation(node, "EntryPointArgs"); if (entry_point_args_annotation) { if (node->payload.global_variable.type->tag != RecordType_TAG) { - error_print("EntryPointArgs must be a struct\n"); + shd_error_print("EntryPointArgs must be a struct\n"); return false; } if (args_struct_type) { - error_print("there cannot be more than one EntryPointArgs\n"); + shd_error_print("there cannot be more than one EntryPointArgs\n"); return false; } @@ -307,12 +307,12 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) case Function_TAG: { if (lookup_annotation(node, "EntryPoint")) { if (node->payload.fun.params.count != 0) { - error_print("EntryPoint cannot have parameters\n"); + shd_error_print("EntryPoint cannot have parameters\n"); return false; } if (entry_point_function) { - error_print("there cannot be more than one EntryPoint\n"); + shd_error_print("there cannot be more than one EntryPoint\n"); return false; } @@ -325,7 +325,7 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) } if (!entry_point_function) { - error_print("could not find EntryPoint\n"); + shd_error_print("could not find EntryPoint\n"); return false; } @@ -335,21 +335,21 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) } if (args_struct_annotation->tag != AnnotationValue_TAG) { - error_print("EntryPointArgs annotation must contain exactly one value\n"); + shd_error_print("EntryPointArgs annotation must contain exactly one value\n"); return false; } const Node* annotation_fn = args_struct_annotation->payload.annotation_value.value; assert(annotation_fn->tag == FnAddr_TAG); if (annotation_fn->payload.fn_addr.fn != entry_point_function) { - error_print("EntryPointArgs annotation refers to different EntryPoint\n"); + shd_error_print("EntryPointArgs annotation refers to different EntryPoint\n"); return false; } size_t num_args = args_struct_type->payload.record_type.members.count; if (num_args == 0) { - error_print("EntryPointArgs cannot be empty\n"); + shd_error_print("EntryPointArgs cannot be empty\n"); return false; } @@ -360,7 +360,7 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) size_t* offset_size_buffer = calloc(1, 2 * num_args * sizeof(size_t)); if (!offset_size_buffer) { - error_print("failed to allocate EntryPointArgs offsets and sizes array\n"); + shd_error_print("failed to allocate EntryPointArgs offsets and sizes array\n"); return false; } size_t* offsets = offset_size_buffer; diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index 57124442a..7c0c9b3e3 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -127,7 +127,7 @@ static int min(int a, int b) { return a < b ? a : b; } // https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm static void strongconnect(CGNode* v, int* index, struct List* stack) { - debugv_print("strongconnect(%s) \n", v->fn->payload.fun.name); + shd_debugv_print("strongconnect(%s) \n", v->fn->payload.fun.name); v->tarjan.index = *index; v->tarjan.lowlink = *index; @@ -139,9 +139,9 @@ static void strongconnect(CGNode* v, int* index, struct List* stack) { { size_t iter = 0; CGEdge e; - debugv_print(" has %d successors\n", shd_dict_count(v->callees)); + shd_debugv_print(" has %d successors\n", shd_dict_count(v->callees)); while (shd_dict_iter(v->callees, &iter, &e, NULL)) { - debugv_print(" %s\n", e.dst_fn->fn->payload.fun.name); + shd_debugv_print(" %s\n", e.dst_fn->fn->payload.fun.name); if (e.dst_fn->tarjan.index == -1) { // Successor w has not yet been visited; recurse on it strongconnect(e.dst_fn, index, stack); @@ -173,7 +173,7 @@ static void strongconnect(CGNode* v, int* index, struct List* stack) { if (scc_size > 1) { for (size_t i = 0; i < scc_size; i++) { CGNode* w = scc[i]; - debugv_print("Function %s is part of a recursive call chain \n", w->fn->payload.fun.name); + shd_debugv_print("Function %s is part of a recursive call chain \n", w->fn->payload.fun.name); w->is_recursive = true; } } @@ -239,7 +239,7 @@ CallGraph* new_callgraph(Module* mod) { destroy_uses_map(uses); - debugv_print("CallGraph: done with CFG build, contains %d nodes\n", shd_dict_count(graph->fn2cgn)); + shd_debugv_print("CallGraph: done with CFG build, contains %d nodes\n", shd_dict_count(graph->fn2cgn)); tarjan(graph->fn2cgn); @@ -250,7 +250,7 @@ void destroy_callgraph(CallGraph* graph) { size_t i = 0; CGNode* node; while (shd_dict_iter(graph->fn2cgn, &i, NULL, &node)) { - debugv_print("Freeing CG node: %s\n", node->fn->payload.fun.name); + shd_debugv_print("Freeing CG node: %s\n", node->fn->payload.fun.name); shd_destroy_dict(node->callers); shd_destroy_dict(node->callees); free(node); diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index f99e343c0..5f12ada76 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -244,7 +244,7 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { case Unreachable_TAG: return; case NotATerminator: - error("Grammar problem"); + shd_error("Grammar problem"); return; } SHADY_UNREACHABLE; @@ -344,15 +344,15 @@ static void validate_cfg(CFG* cfg) { if (node != cfg->entry /* this exception exists since we might build CFGs rooted in cases */) { if (structured_body_uses > 0) { if (structured_body_uses > 1) { - error_print("Basic block %s is used as a structural target more than once (structured_body_uses: %zu)", get_abstraction_name_safe(node->node), structured_body_uses); + shd_error_print("Basic block %s is used as a structural target more than once (structured_body_uses: %zu)", get_abstraction_name_safe(node->node), structured_body_uses); shd_error_die(); } if (num_jumps > 0) { - error_print("Basic block %s is used as structural target, but is also jumped into (num_jumps: %zu)", get_abstraction_name_safe(node->node), num_jumps); + shd_error_print("Basic block %s is used as structural target, but is also jumped into (num_jumps: %zu)", get_abstraction_name_safe(node->node), num_jumps); shd_error_die(); } if (!is_tail && num_exits > 0) { - error_print("Basic block %s is not a merge target yet is used as once (num_exits: %zu)", get_abstraction_name_safe(node->node), num_exits); + shd_error_print("Basic block %s is not a merge target yet is used as once (num_exits: %zu)", get_abstraction_name_safe(node->node), num_exits); shd_error_die(); } } @@ -540,7 +540,7 @@ void compute_domtree(CFG* cfg) { if (structured_idom) { continue; } - error("no idom found"); + shd_error("no idom found"); outer_loop:; } diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 28d4122c7..914f6fb6c 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -49,19 +49,19 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { Scheduler* scheduler = new_scheduler(cfg); struct Dict* set = free_frontier(scheduler, cfg, cfg->entry->node); if (shd_dict_count(set) > 0) { - log_string(ERROR, "Leaking variables in "); - log_node(ERROR, cfg->entry->node); - log_string(ERROR, ":\n"); + shd_log_fmt(ERROR, "Leaking variables in "); + shd_log_node(ERROR, cfg->entry->node); + shd_log_fmt(ERROR, ":\n"); size_t j = 0; const Node* leaking; while (shd_dict_iter(set, &j, &leaking, NULL)) { - log_node(ERROR, leaking); - error_print("\n"); + shd_log_node(ERROR, leaking); + shd_error_print("\n"); } - log_string(ERROR, "Problematic module:\n"); - log_module(ERROR, config, mod); + shd_log_fmt(ERROR, "Problematic module:\n"); + shd_log_module(ERROR, config, mod); shd_error_die(); } shd_destroy_dict(set); @@ -124,11 +124,11 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { search = search->parent; } if (!search) { - log_string(ERROR, "Scheduling problem: "); - log_node(ERROR, node); - log_string(ERROR, "was encountered before we saw it be bound by a let!\n"); - log_string(ERROR, "Problematic module:\n"); - log_module(ERROR, ctx->config, ctx->mod); + shd_log_fmt(ERROR, "Scheduling problem: "); + shd_log_node(ERROR, node); + shd_log_fmt(ERROR, "was encountered before we saw it be bound by a let!\n"); + shd_log_fmt(ERROR, "Problematic module:\n"); + shd_log_module(ERROR, ctx->config, ctx->mod); shd_error_die(); } } diff --git a/src/shady/annotation.c b/src/shady/annotation.c index ae2710b2f..6979ffc99 100644 --- a/src/shady/annotation.c +++ b/src/shady/annotation.c @@ -36,14 +36,14 @@ const Node* lookup_annotation_list(Nodes annotations, const char* name) { const Node* get_annotation_value(const Node* annotation) { assert(annotation); if (annotation->tag != AnnotationValue_TAG) - error("This annotation does not have a single payload"); + shd_error("This annotation does not have a single payload"); return annotation->payload.annotation_value.value; } Nodes get_annotation_values(const Node* annotation) { assert(annotation); if (annotation->tag != AnnotationValues_TAG) - error("This annotation does not have multiple payloads"); + shd_error("This annotation does not have multiple payloads"); return annotation->payload.annotation_values.values; } @@ -52,7 +52,7 @@ const char* get_annotation_string_payload(const Node* annotation) { const Node* payload = get_annotation_value(annotation); if (!payload) return NULL; if (payload->tag != StringLiteral_TAG) - error("Wrong annotation payload tag, expected a string literal") + shd_error("Wrong annotation payload tag, expected a string literal") return payload->payload.string_lit.string; } diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 472cccc6d..6b7c5a907 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -111,7 +111,7 @@ static void generate_node_tags_for_class(Growy* g, json_object* nodes, String cl case json_type_double: case json_type_int: case json_type_object: - error_print("Invalid datatype for a node's 'class' attribute"); + shd_error_print("Invalid datatype for a node's 'class' attribute"); } } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index dc4a142c7..1abde9ca2 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -97,7 +97,7 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { StackEntry entry = shd_read_list(StackEntry, bb->stack)[i]; const Node* t2 = terminator; switch (entry.structured.tag) { - case NotAStructured_construct: error("") + case NotAStructured_construct: shd_error("") case Structured_construct_If_TAG: { terminator = if_instr(a, entry.structured.payload.if_instr); break; @@ -248,7 +248,7 @@ Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constru .vars = params, }; switch (entry.structured.tag) { - case NotAStructured_construct: error("") + case NotAStructured_construct: shd_error("") case Structured_construct_If_TAG: { entry.structured.payload.if_instr.tail = tail; entry.structured.payload.if_instr.mem = bb_mem(bb); diff --git a/src/shady/builtins.c b/src/shady/builtins.c index 750ba12dd..936c32d12 100644 --- a/src/shady/builtins.c +++ b/src/shady/builtins.c @@ -26,7 +26,7 @@ const Type* get_builtin_type(IrArena* arena, Builtin builtin) { #define BUILTIN(name, _, datatype) case Builtin##name: return datatype; SHADY_BUILTINS() #undef BUILTIN - default: error("Unhandled builtin") + default: shd_error("Unhandled builtin") } } diff --git a/src/shady/compile.c b/src/shady/compile.c index ae642bd0f..82562f0a9 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -19,7 +19,7 @@ void add_scheduler_source(const CompilerConfig* config, Module* dst) { .front_end = true, }; Module* builtin_scheduler_mod = parse_slim_module(config, pconfig, shady_scheduler_src, "builtin_scheduler"); - debug_print("Adding builtin scheduler code"); + shd_debug_print("Adding builtin scheduler code"); link_module(dst, builtin_scheduler_mod); destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); } @@ -35,7 +35,7 @@ void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial old_mod = *pmod; *pmod = pass(config, *pmod); (*pmod)->sealed = true; - debugvv_print("After pass %s: \n", pass_name); + shd_debugvv_print("After pass %s: \n", pass_name); if (SHADY_RUN_VERIFY) verify_module(config, *pmod); if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) @@ -43,7 +43,7 @@ void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial old_mod = *pmod; if (config->optimisations.cleanup.after_every_pass) *pmod = cleanup(config, *pmod); - log_module(DEBUGVV, config, *pmod); + shd_log_module(DEBUGVV, config, *pmod); if (SHADY_RUN_VERIFY) verify_module(config, *pmod); if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) @@ -57,8 +57,8 @@ void apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPas *todo |= changed; if (getenv("SHADY_DUMP_CLEAN_ROUNDS") && changed) { - log_string(DEBUGVV, "%s changed something:\n", pass_name); - log_module(DEBUGVV, config, *m); + shd_log_fmt(DEBUGVV, "%s changed something:\n", pass_name); + shd_log_module(DEBUGVV, config, *m); } } @@ -67,8 +67,8 @@ CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { // we don't want to mess with the original module *pmod = import(config, *pmod); - log_string(DEBUG, "After import:\n"); - log_module(DEBUG, config, *pmod); + shd_log_fmt(DEBUG, "After import:\n"); + shd_log_module(DEBUG, config, *pmod); if (config->input_cf.has_scope_annotations) { // RUN_PASS(scope_heuristic) diff --git a/src/shady/generator/generator_common.c b/src/shady/generator/generator_common.c index 5bc948298..1e43a2c4d 100644 --- a/src/shady/generator/generator_common.c +++ b/src/shady/generator/generator_common.c @@ -76,7 +76,7 @@ String class_to_type(json_object* src, String class, bool list) { } // check the class is valid if (!lookup_node_class(src, class)) { - error_print("invalid node class '%s'\n", class); + shd_error_print("invalid node class '%s'\n", class); shd_error_die(); } return list ? "Nodes" : "const Node*"; @@ -157,7 +157,7 @@ void generate_bit_enum_classifier(Growy* g, String fn_name, String enum_type_nam case json_type_double: case json_type_int: case json_type_object: - error_print("Invalid datatype for a node's 'class' attribute"); + shd_error_print("Invalid datatype for a node's 'class' attribute"); break; } } diff --git a/src/shady/generator/generator_main.c b/src/shady/generator/generator_main.c index bd85d79da..a24fe3448 100644 --- a/src/shady/generator/generator_main.c +++ b/src/shady/generator/generator_main.c @@ -33,10 +33,10 @@ int main(int argc, char** argv) { json_files[i].root = json_tokener_parse_ex(tokener, json_files[i].contents, json_files[i].size); json_err = json_tokener_get_error(tokener); if (json_err != json_tokener_success) { - error("Json tokener error while parsing %s:\n %s\n", path, json_tokener_error_desc(json_err)); + shd_error("Json tokener error while parsing %s:\n %s\n", path, json_tokener_error_desc(json_err)); } - info_print("Correctly opened json file: %s\n", path); + shd_info_print("Correctly opened json file: %s\n", path); } Growy* g = shd_new_growy(); @@ -52,9 +52,9 @@ int main(int argc, char** argv) { size_t final_size = shd_growy_size(g); shd_growy_append_bytes(g, 1, (char[]) { 0 }); char* generated = shd_growy_deconstruct(g); - debug_print("debug: %s\n", generated); + shd_debug_print("debug: %s\n", generated); if (!shd_write_file(dst_file, final_size, generated)) { - error_print("Failed to write file '%s'\n", dst_file); + shd_error_print("Failed to write file '%s'\n", dst_file); shd_error_die(); } free(generated); diff --git a/src/shady/generator/import_spv_defs.c b/src/shady/generator/import_spv_defs.c index 11d5dcfc0..57409307a 100644 --- a/src/shady/generator/import_spv_defs.c +++ b/src/shady/generator/import_spv_defs.c @@ -83,7 +83,7 @@ void apply_instruction_filter(json_object* filter, json_object* instruction, jso }*/ break; } - default: error("Filters need to be arrays or objects"); + default: shd_error("Filters need to be arrays or objects"); } } @@ -147,7 +147,7 @@ void apply_operand_filter(json_object* filter, json_object* operand, json_object json_apply_object(instantiated_filter, filter); break; } - default: error("Filters need to be arrays or objects"); + default: shd_error("Filters need to be arrays or objects"); } } @@ -183,7 +183,7 @@ json_object* import_operand(json_object* operand, json_object* instruction_filte json_object_put(filter); return NULL; } else if (strcmp(import_property, "yes") != 0) { - error("a filter's 'import' property needs to be 'yes' or 'no'") + shd_error("a filter's 'import' property needs to be 'yes' or 'no'") } json_object* field = json_object_new_object(); @@ -209,7 +209,7 @@ json_object* import_filtered_instruction(json_object* instruction, json_object* if (!import_property || (strcmp(import_property, "no") == 0)) { return NULL; } else if (strcmp(import_property, "yes") != 0) { - error("a filter's 'import' property needs to be 'yes' or 'no'") + shd_error("a filter's 'import' property needs to be 'yes' or 'no'") } String node_name = sanitize_node_name(name); @@ -274,7 +274,7 @@ int main(int argc, char** argv) { char* spv_core_json_path = NULL; for (size_t i = ArgSpirvGrammarSearchPathBegins; i < argc; i++) { char* path = shd_format_string_new("%s/spirv/unified1/spirv.core.grammar.json", argv[i]); - info_print("trying path %s\n", path); + shd_info_print("trying path %s\n", path); FILE* f = fopen(path, "rb"); if (f) { spv_core_json_path = path; @@ -301,7 +301,7 @@ int main(int argc, char** argv) { imports.root = json_tokener_parse_ex(tokener, imports.contents, imports.size); json_err = json_tokener_get_error(tokener); if (json_err != json_tokener_success) { - error("Json tokener error while parsing %s:\n %s\n", argv[ArgImportsFile], json_tokener_error_desc(json_err)); + shd_error("Json tokener error while parsing %s:\n %s\n", argv[ArgImportsFile], json_tokener_error_desc(json_err)); } JsonFile spirv; @@ -309,10 +309,10 @@ int main(int argc, char** argv) { spirv.root = json_tokener_parse_ex(tokener, spirv.contents, spirv.size); json_err = json_tokener_get_error(tokener); if (json_err != json_tokener_success) { - error("Json tokener error while parsing %s:\n %s\n", spv_core_json_path, json_tokener_error_desc(json_err)); + shd_error("Json tokener error while parsing %s:\n %s\n", spv_core_json_path, json_tokener_error_desc(json_err)); } - info_print("Correctly opened json file: %s\n", spv_core_json_path); + shd_info_print("Correctly opened json file: %s\n", spv_core_json_path); json_object* output = json_object_new_object(); @@ -325,9 +325,9 @@ int main(int argc, char** argv) { size_t final_size = shd_growy_size(g); shd_growy_append_bytes(g, 1, (char[]) { 0 }); char* generated = shd_growy_deconstruct(g); - debug_print("debug: %s\n", generated); + shd_debug_print("debug: %s\n", generated); if (!shd_write_file(dst_file, final_size, generated)) { - error_print("Failed to write file '%s'\n", dst_file); + shd_error_print("Failed to write file '%s'\n", dst_file); shd_error_die(); } free(generated); diff --git a/src/shady/generator/json_apply.c b/src/shady/generator/json_apply.c index 6fc6d010a..5eac0168f 100644 --- a/src/shady/generator/json_apply.c +++ b/src/shady/generator/json_apply.c @@ -29,7 +29,7 @@ void json_apply_object(json_object* target, json_object* src) { } } else { if (existing) - warn_print("json-apply: overwriting key '%s'\n", name); + shd_warn_print("json-apply: overwriting key '%s'\n", name); // json_object* copy = NULL; // json_object_deep_copy(value, ©, NULL); // json_object_object_add(target, name, copy); diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index a092bd8ef..704b55abd 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -54,7 +54,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { } shd_growy_append_formatted(g, "%s\t\t\tif (arena->config.check_op_classes && *pop != NULL && !is_%s(*pop)) {\n", extra, class); - shd_growy_append_formatted(g, "%s\t\t\t\terror_print(\"Invalid '%s' operand for node '%s', expected a %s\");\n", extra, op_name, name, class); + shd_growy_append_formatted(g, "%s\t\t\t\tshd_error_print(\"Invalid '%s' operand for node '%s', expected a %s\");\n", extra, op_name, name, class); shd_growy_append_formatted(g, "%s\t\t\t\tshd_error_die();\n", extra); shd_growy_append_formatted(g, "%s\t\t\t}\n", extra); if (list) { diff --git a/src/shady/node.c b/src/shady/node.c index 5ac7fb583..54c287a36 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -55,7 +55,7 @@ double get_float_literal_value(FloatLiteral literal) { double r; switch (literal.width) { case FloatTy16: - error_print("TODO: fp16 literals"); + shd_error_print("TODO: fp16 literals"); shd_error_die(); SHADY_UNREACHABLE; break; diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 24c081ced..df185a153 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -57,7 +57,7 @@ const Node* process(Context* ctx, const Node* old) { case BasicBlock_TAG: { size_t uses = count_calls(ctx->map, old); if (uses <= 1 && a->config.optimisations.inline_single_use_bbs) { - log_string(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name_safe(old), uses); + shd_log_fmt(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name_safe(old), uses); *ctx->todo = true; return NULL; } @@ -145,7 +145,7 @@ Module* cleanup(const CompilerConfig* config, Module* const src) { bool changed_at_all = false; do { todo = false; - debugv_print("Cleanup round %d\n", r); + shd_debugv_print("Cleanup round %d\n", r); APPLY_OPT(opt_demote_alloca); APPLY_OPT(opt_mem2reg); @@ -156,6 +156,6 @@ Module* cleanup(const CompilerConfig* config, Module* const src) { r++; } while (todo); if (changed_at_all) - debugv_print("After %d rounds of cleanup:\n", r); + shd_debugv_print("After %d rounds of cleanup:\n", r); return import(config, m); } diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 4950e9e75..36386510e 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -23,19 +23,19 @@ const Node* import_node(Rewriter* r, const Node* node) { if (existing) { const Node* imported_t = rewrite_node(r, node->type); if (imported_t != existing->type) { - error_print("Incompatible types for to-be-merged declaration: %s ", get_declaration_name(node)); - log_node(ERROR, existing->type); - error_print(" vs "); - log_node(ERROR, imported_t); - error_print(".\n"); + shd_error_print("Incompatible types for to-be-merged declaration: %s ", get_declaration_name(node)); + shd_log_node(ERROR, existing->type); + shd_error_print(" vs "); + shd_log_node(ERROR, imported_t); + shd_error_print(".\n"); shd_error_die(); } if (node->tag != existing->tag) { - error_print("Incompatible node types for to-be-merged declaration: %s ", get_declaration_name(node)); - error_print("%s", node_tags[existing->tag]); - error_print(" vs "); - error_print("%s", node_tags[node->tag]); - error_print(".\n"); + shd_error_print("Incompatible node types for to-be-merged declaration: %s ", get_declaration_name(node)); + shd_error_print("%s", node_tags[existing->tag]); + shd_error_print(" vs "); + shd_error_print("%s", node_tags[node->tag]); + shd_error_print(".\n"); shd_error_die(); } switch (is_declaration(node)) { diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 89a1e37be..1e2d75dee 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -66,9 +66,9 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No const LTNode* defining_loop = get_loop(looptree_lookup(ctx->loop_tree, defining_cf_node->node)); if (!is_child(defining_loop, bb_loop)) { // that's it, that variable is leaking ! - log_string(DEBUGV, "lcssa: "); - log_node(DEBUGV, fv); - log_string(DEBUGV, " (%%%d) is used outside of the loop that defines it %s %s\n", fv->id, loop_name(defining_loop), loop_name(bb_loop)); + shd_log_fmt(DEBUGV, "lcssa: "); + shd_log_node(DEBUGV, fv); + shd_log_fmt(DEBUGV, " (%%%d) is used outside of the loop that defines it %s %s\n", fv->id, loop_name(defining_loop), loop_name(bb_loop)); const Node* narg = rewrite_node(&ctx->rewriter, fv); const Node* nparam = param(a, narg->type, "lcssa_phi"); *nparams = append_nodes(a, *nparams, nparam); @@ -88,8 +88,8 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* ctx = &ctx2; if (!ctx->cfg) { - error_print("LCSSA: Trying to process an abstraction that's not part of a function ('%s')!", get_abstraction_name(old)); - log_module(ERROR, ctx->config, ctx->rewriter.src_module); + shd_error_print("LCSSA: Trying to process an abstraction that's not part of a function ('%s')!", get_abstraction_name(old)); + shd_log_module(ERROR, ctx->config, ctx->rewriter.src_module); shd_error_die(); } const CFNode* n = cfg_lookup(ctx->cfg, old); diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 18e341972..4535a3f67 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -95,18 +95,18 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { Rewriter* r = &lifting_ctx.rewriter; Nodes ovariables = get_abstraction_params(liftee); - debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); + shd_debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { const Node* item = frontier.nodes[i]; if (!is_value(item)) { //lambda_lift() continue; } - debugv_print("%%%d", item->id); + shd_debugv_print("%%%d", item->id); if (i + 1 < recover_context_size) - debugv_print(", "); + shd_debugv_print(", "); } - debugv_print("\n"); + shd_debugv_print("\n"); // Create and register new parameters for the lifted continuation LARRAY(const Node*, new_params_arr, ovariables.count); @@ -227,7 +227,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { int round = 0; while (true) { - debugv_print("lift_indirect_target: round %d\n", round++); + shd_debugv_print("lift_indirect_target: round %d\n", round++); IrArena* oa = a; a = new_ir_arena(&aconfig); dst = new_module(a, get_module_name(src)); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 2de976d06..f05349eea 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -130,10 +130,10 @@ static const Node* process(Context* ctx, const Node* node) { if (!ctx->disable_lowering) { StackSlot* found_slot = shd_dict_find_value(const Node*, StackSlot, ctx->prepared_offsets, node); if (!found_slot) { - error_print("lower_alloca: failed to find a stack offset for "); - log_node(ERROR, node); - error_print(", most likely this means this alloca was not found in the first block of a function.\n"); - log_module(DEBUG, ctx->config, ctx->rewriter.src_module); + shd_error_print("lower_alloca: failed to find a stack offset for "); + shd_log_node(ERROR, node); + shd_error_print(", most likely this means this alloca was not found in the first block of a function.\n"); + shd_log_module(DEBUG, ctx->config, ctx->rewriter.src_module); shd_error_die(); } diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 66bf647bb..75eb802d6 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -140,9 +140,9 @@ static const Node* process_node(Context* ctx, const Node* node) { } if (!selection_instr) { - error_print("Scoping error: Failed to find a dominating selection construct for "); - log_node(ERROR, node); - error_print(".\n"); + shd_error_print("Scoping error: Failed to find a dominating selection construct for "); + shd_log_node(ERROR, node); + shd_error_print(".\n"); shd_error_die(); } @@ -174,9 +174,9 @@ static const Node* process_node(Context* ctx, const Node* node) { } if (!loop_start) { - error_print("Scoping error: Failed to find a dominating loop construct for "); - log_node(ERROR, node); - error_print(".\n"); + shd_error_print("Scoping error: Failed to find a dominating loop construct for "); + shd_log_node(ERROR, node); + shd_error_print(".\n"); shd_error_die(); } @@ -208,9 +208,9 @@ static const Node* process_node(Context* ctx, const Node* node) { } if (!loop_start) { - error_print("Scoping error: Failed to find a dominating loop construct for "); - log_node(ERROR, node); - error_print(".\n"); + shd_error_print("Scoping error: Failed to find a dominating loop construct for "); + shd_log_node(ERROR, node); + shd_error_print(".\n"); shd_error_die(); } diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index c8318a54b..21367bc4c 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -34,7 +34,7 @@ static const Node* generate_arg_struct_type(Rewriter* rewriter, Nodes params) { const Type* type = rewrite_node(rewriter, params.nodes[i]->type); if (!deconstruct_qualified_type(&type)) - error("EntryPoint parameters must be uniform"); + shd_error("EntryPoint parameters must be uniform"); types[i] = type; names[i] = get_value_name_safe(params.nodes[i]); diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index e1b2c160d..9a46f75c3 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -41,7 +41,7 @@ static uint64_t get_tag_for_addr_space(AddressSpace as) { if (generic_ptr_tags[i] == as) return (uint64_t) i; } - error("address space '%s' can't be converted to generic", get_address_space_name(as)); + shd_error("address space '%s' can't be converted to generic", get_address_space_name(as)); } static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t tag, const Node* nptr, const Type* element_type) { @@ -257,7 +257,7 @@ static const Node* process(Context* ctx, const Node* old) { return yield_values_and_wrap_in_block(bb, singleton(generic_ptr)); } else if (old_src_t->tag == PtrType_TAG && old_src_t->payload.ptr_type.address_space == AsGeneric) { // cast _from_ generic - error("TODO"); + shd_error("TODO"); } break; } diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 9a26b6d93..035604fc5 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -75,7 +75,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po }); break; } - default: error("cannot index into this") + default: shd_error("cannot index into this") } return ptr; diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index e8871f0eb..e48fc87d0 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -36,7 +36,7 @@ static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node } default: break; } - error("Cannot fix pointer") + shd_error("Cannot fix pointer") } return ptr; } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 2a28f9678..8e67a0902 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -50,7 +50,7 @@ static const Node** get_emulated_as_word_array(Context* ctx, AddressSpace as) { case AsPrivate: return &ctx->fake_private_memory; case AsSubgroup: return &ctx->fake_subgroup_memory; case AsShared: return &ctx->fake_shared_memory; - default: error("Emulation of this AS is not supported"); + default: shd_error("Emulation of this AS is not supported"); } } @@ -71,7 +71,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* unsigned_int = gen_deserialisation(ctx, bb, ptr_int_t, arr, address); return gen_reinterpret_cast(bb, element_type, unsigned_int); } - default: error("TODO") + default: shd_error("TODO") } case Int_TAG: ser_int: { assert(element_type->tag == Int_TAG); @@ -124,9 +124,9 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type case PackType_TAG: { const Node* size = get_fill_type_size(element_type); if (size->tag != IntLiteral_TAG) { - error_print("Size of type "); - log_node(ERROR, element_type); - error_print(" is not known a compile-time!\n"); + shd_error_print("Size of type "); + shd_log_node(ERROR, element_type); + shd_error_print(" is not known a compile-time!\n"); } size_t components_count = get_int_literal_value(*resolve_to_int_literal(size), 0); const Type* component_type = get_fill_type_element_type(element_type); @@ -138,7 +138,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type } return composite_helper(a, element_type, nodes(a, components_count, components)); } - default: error("TODO"); + default: shd_error("TODO"); } } @@ -161,7 +161,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, singleton(ptr_int_t), singleton(value)); return gen_serialisation(ctx, bb, ptr_int_t, arr, address, unsigned_value); } - default: error("TODO") + default: shd_error("TODO") } case Int_TAG: des_int: { assert(element_type->tag == Int_TAG); @@ -181,7 +181,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* original_word = NULL; if (needs_patch) { original_word = gen_load(bb, gen_lea(bb, arr, zero, singleton(base_offset))); - error_print("TODO"); + shd_error_print("TODO"); shd_error_die(); // word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded }*/ @@ -228,9 +228,9 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element case PackType_TAG: { const Node* size = get_fill_type_size(element_type); if (size->tag != IntLiteral_TAG) { - error_print("Size of type "); - log_node(ERROR, element_type); - error_print(" is not known a compile-time!\n"); + shd_error_print("Size of type "); + shd_log_node(ERROR, element_type); + shd_error_print(" is not known a compile-time!\n"); } size_t components_count = get_int_literal_value(*resolve_to_int_literal(size), 0); const Type* component_type = get_fill_type_element_type(element_type); @@ -241,7 +241,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element } return; } - default: error("TODO"); + default: shd_error("TODO"); } } @@ -323,7 +323,7 @@ static const Node* process_node(Context* ctx, const Node* old) { gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, pointer_as_offset, value)); return yield_values_and_wrap_in_block(bb, empty(a)); } - case StackAlloc_TAG: error("This needs to be lowered (see setup_stack_frames.c)") + case StackAlloc_TAG: shd_error("This needs to be lowered (see setup_stack_frames.c)") case PtrType_TAG: { if (!old->payload.ptr_type.is_reference && is_as_emulated(ctx, old->payload.ptr_type.address_space)) return int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 0dccec30e..d7b184710 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -96,9 +96,9 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* scope, const Node* return; } - log_string(ERROR, "subgroup_first emulation is not supported for "); - log_node(ERROR, t); - log_string(ERROR, ".\n"); + shd_log_fmt(ERROR, "subgroup_first emulation is not supported for "); + shd_log_node(ERROR, t); + shd_log_fmt(ERROR, ".\n"); shd_error_die(); } @@ -110,7 +110,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, qualified_type_helper(t, true), mk_nodes(a, scope, src)); if (resolve_to_int_literal(scope)->value != SpvScopeSubgroup) - error("TODO") + shd_error("TODO") Node* fn = NULL; Node** found = shd_dict_find_value(const Node*, Node*, ctx->fns, t); diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 23e78503f..8fbbc39b7 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -171,7 +171,7 @@ static const Node* process(Context* ctx, const Node* node) { destroy_arena(arena); return finish_body(bb, rewrite_node(r, get_abstraction_body(get_structured_construct_tail(node))));*/ - error("TODO") + shd_error("TODO") // return yield_values_and_wrap_in_block(bb, final_results); } default: break; diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index 10c89d999..02f172835 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -48,25 +48,25 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { if (fn_node->is_address_captured || fn_node->is_recursive || fn_node->calls_indirect) { info->is_leaf = false; info->done = true; - debugv_print("Function %s can't be a leaf function because", get_abstraction_name(fn_node->fn)); + shd_debugv_print("Function %s can't be a leaf function because", get_abstraction_name(fn_node->fn)); bool and = false; if (fn_node->is_address_captured) { - debugv_print("its address is captured"); + shd_debugv_print("its address is captured"); and = true; } if (fn_node->is_recursive) { if (and) - debugv_print(" and "); - debugv_print("it is recursive"); + shd_debugv_print(" and "); + shd_debugv_print("it is recursive"); and = true; } if (fn_node->calls_indirect) { if (and) - debugv_print(" and "); - debugv_print("it makes indirect calls"); + shd_debugv_print(" and "); + shd_debugv_print("it makes indirect calls"); and = true; } - debugv_print(".\n"); + shd_debugv_print(".\n"); return false; } @@ -74,7 +74,7 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { CGEdge e; while (shd_dict_iter(fn_node->callees, &iter, &e, NULL)) { if (!is_leaf_fn(ctx, e.dst_fn)) { - debugv_print("Function %s can't be a leaf function because its callee %s is not a leaf function.\n", get_abstraction_name(fn_node->fn), get_abstraction_name(e.dst_fn->fn)); + shd_debugv_print("Function %s can't be a leaf function because its callee %s is not a leaf function.\n", get_abstraction_name(fn_node->fn), get_abstraction_name(e.dst_fn->fn)); info->is_leaf = false; info->done = true; } @@ -110,7 +110,7 @@ static const Node* process(Context* ctx, const Node* node) { recreate_decl_body_identity(&ctx->rewriter, node, new); if (fn_ctx.is_leaf) { - debugv_print("Function %s is a leaf function!\n", get_abstraction_name(node)); + shd_debugv_print("Function %s is a leaf function!\n", get_abstraction_name(node)); new->payload.fun.annotations = append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Leaf", })); @@ -122,9 +122,9 @@ static const Node* process(Context* ctx, const Node* node) { } case Control_TAG: { if (!is_control_static(ctx->uses, node)) { - debugv_print("Function %s can't be a leaf function because the join point ", get_abstraction_name(ctx->cfg->entry->node)); - log_node(DEBUGV, first(get_abstraction_params(node->payload.control.inside))); - debugv_print("escapes its control block, preventing restructuring.\n"); + shd_debugv_print("Function %s can't be a leaf function because the join point ", get_abstraction_name(ctx->cfg->entry->node)); + shd_log_node(DEBUGV, first(get_abstraction_params(node->payload.control.inside))); + shd_debugv_print("escapes its control block, preventing restructuring.\n"); ctx->is_leaf = false; } break; @@ -136,9 +136,9 @@ static const Node* process(Context* ctx, const Node* node) { if (control && is_control_static(ctx->uses, control)) break; } - debugv_print("Function %s can't be a leaf function because it joins with ", get_abstraction_name(ctx->cfg->entry->node)); - log_node(DEBUGV, old_jp); - debugv_print("which is not bound by a control node within that function.\n"); + shd_debugv_print("Function %s can't be a leaf function because it joins with ", get_abstraction_name(ctx->cfg->entry->node)); + shd_log_node(DEBUGV, old_jp); + shd_debugv_print("which is not bound by a control node within that function.\n"); ctx->is_leaf = false; break; } diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 41adef082..43c9be198 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -25,11 +25,11 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { const Type* expected_t = get_builtin_type(a, b); const Type* actual_t = rewrite_node(&ctx->rewriter, src)->payload.global_variable.type; if (expected_t != actual_t) { - log_string(INFO, "normalize_builtins: found builtin decl '%s' not matching expected type: '", global_variable.name); - log_node(INFO, expected_t); - log_string(INFO, "', got '"); - log_node(INFO, actual_t); - log_string(INFO, "'."); + shd_log_fmt(INFO, "normalize_builtins: found builtin decl '%s' not matching expected type: '", global_variable.name); + shd_log_node(INFO, expected_t); + shd_log_fmt(INFO, "', got '"); + shd_log_node(INFO, actual_t); + shd_log_fmt(INFO, "'."); return actual_t; } } diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 98ca7e6da..ad0ee59f5 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -89,15 +89,15 @@ static FnInliningCriteria get_inlining_heuristic(const CompilerConfig* config, C if (!is_call_safely_removable(fn_node->fn)) crit.can_be_eliminated = false; - debugv_print("inlining heuristic for '%s': num_calls=%d num_inlineable_calls=%d safely_removable=%d address_leaks=%d recursive=%d inlineable=%d can_be_eliminated=%d\n", - get_abstraction_name(fn_node->fn), - crit.num_calls, - crit.num_inlineable_calls, - is_call_safely_removable(fn_node->fn), - fn_node->is_address_captured, - fn_node->is_recursive, - crit.can_be_inlined, - crit.can_be_eliminated); + shd_debugv_print("inlining heuristic for '%s': num_calls=%d num_inlineable_calls=%d safely_removable=%d address_leaks=%d recursive=%d inlineable=%d can_be_eliminated=%d\n", + get_abstraction_name(fn_node->fn), + crit.num_calls, + crit.num_inlineable_calls, + is_call_safely_removable(fn_node->fn), + fn_node->is_address_captured, + fn_node->is_recursive, + crit.can_be_inlined, + crit.can_be_eliminated); return crit; } @@ -106,7 +106,7 @@ static FnInliningCriteria get_inlining_heuristic(const CompilerConfig* config, C static const Node* inline_call(Context* ctx, const Node* ocallee, const Node* nmem, Nodes nargs, const Node* return_to) { assert(is_abstraction(ocallee)); - log_string(DEBUG, "Inlining '%s' inside '%s'\n", get_abstraction_name(ocallee), get_abstraction_name(ctx->fun)); + shd_log_fmt(DEBUG, "Inlining '%s' inside '%s'\n", get_abstraction_name(ocallee), get_abstraction_name(ctx->fun)); Context inline_context = *ctx; inline_context.rewriter.map = shd_clone_dict(inline_context.rewriter.map); @@ -140,7 +140,7 @@ static const Node* process(Context* ctx, const Node* node) { if (ctx->graph) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, node); if (get_inlining_heuristic(ctx->config, fn_node).can_be_eliminated) { - debugv_print("Eliminating %s because it has exactly one caller\n", get_abstraction_name(fn_node->fn)); + shd_debugv_print("Eliminating %s because it has exactly one caller\n", get_abstraction_name(fn_node->fn)); return NULL; } } @@ -170,7 +170,7 @@ static const Node* process(Context* ctx, const Node* node) { if (ocallee->tag == Function_TAG) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined && is_call_potentially_inlineable(ctx->old_fun, ocallee)) { - debugv_print("Inlining call to %s\n", get_abstraction_name(ocallee)); + shd_debugv_print("Inlining call to %s\n", get_abstraction_name(ocallee)); Nodes nargs = rewrite_nodes(&ctx->rewriter, payload.args); // Prepare a join point to replace the old function return @@ -210,7 +210,7 @@ static const Node* process(Context* ctx, const Node* node) { if (ocallee->tag == Function_TAG) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined) { - debugv_print("Inlining tail call to %s\n", get_abstraction_name(ocallee)); + shd_debugv_print("Inlining tail call to %s\n", get_abstraction_name(ocallee)); Nodes nargs = rewrite_nodes(&ctx->rewriter, node->payload.tail_call.args); return inline_call(ctx, ocallee, rewrite_node(r, node->payload.tail_call.mem), nargs, NULL); } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 211b3b218..8af305277 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -312,10 +312,10 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { case If_TAG: case Match_TAG: - case Loop_TAG: error("not supposed to exist in IR at this stage"); + case Loop_TAG: shd_error("not supposed to exist in IR at this stage"); case Terminator_MergeBreak_TAG: case Terminator_MergeContinue_TAG: - case Terminator_MergeSelection_TAG: error("Only control nodes are tolerated here.") + case Terminator_MergeSelection_TAG: shd_error("Only control nodes are tolerated here.") } } @@ -408,7 +408,7 @@ static const Node* process(Context* ctx, const Node* node) { assert(false); // actually that should not come up. longjmp(ctx->bail, 1); } - case BasicBlock_TAG: error("All basic blocks should be processed explicitly") + case BasicBlock_TAG: shd_error("All basic blocks should be processed explicitly") default: break; } return recreate_node_identity(&ctx->rewriter, node); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index b30545d31..d69b983f1 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -65,11 +65,11 @@ static void find_unbound_vars(const Node* exiting_node, struct Dict* bound_set, if (shd_dict_find_key(const Node*, bound_set, v)) continue; - log_string(DEBUGVV, "Found variable used outside it's control scope: "); - log_node(DEBUGVV, v); - log_string(DEBUGVV, " (exiting_node:"); - log_node(DEBUGVV, exiting_node); - log_string(DEBUGVV, " )\n"); + shd_log_fmt(DEBUGVV, "Found variable used outside it's control scope: "); + shd_log_node(DEBUGVV, v); + shd_log_fmt(DEBUGVV, " (exiting_node:"); + shd_log_node(DEBUGVV, exiting_node); + shd_log_fmt(DEBUGVV, " )\n"); shd_list_append(const Node*, leaking, v); } @@ -120,7 +120,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { gather_exiting_nodes(ctx->current_looptree, current_node, current_node, exiting_nodes); for (size_t i = 0; i < shd_list_count(exiting_nodes); i++) { - debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(shd_read_list(CFNode *, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); + shd_debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(shd_read_list(CFNode *, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); } size_t exiting_nodes_count = shd_list_count(exiting_nodes); diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 0d4765973..380bcee31 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -176,15 +176,15 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed const Nodes* src_lexical_scope = find_scope_info(src); const Nodes* dst_lexical_scope = find_scope_info(dst); if (!src_lexical_scope) { - warn_print("Failed to find jump source node "); - log_node(WARN, src); - warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); + shd_warn_print("Failed to find jump source node "); + shd_log_node(WARN, src); + shd_warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); } else if (!dst_lexical_scope) { - warn_print("Failed to find jump target node "); - log_node(WARN, dst); - warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); + shd_warn_print("Failed to find jump target node "); + shd_log_node(WARN, dst); + shd_warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { - debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name_safe(src), get_abstraction_name_safe(dst)); + shd_debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name_safe(src), get_abstraction_name_safe(dst)); CFNode* src_cfnode = cfg_lookup(cfg, src); assert(src_cfnode->node); @@ -196,21 +196,21 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed CFNode* dom = src_cfnode->idom; while (dom) { - debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); + shd_debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); Nodes* dom_lexical_scope = find_scope_info(dom->node); if (!dom_lexical_scope) { - warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); + shd_warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); dom = dom->idom; continue; } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { - error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); + shd_error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { // if (cfg_is_dominated(target_cfnode, dom)) { if (!cfg_is_dominated(dom, dst_cfnode) && dst_cfnode != dom) { // assert(false); } - debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); + shd_debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); Controls* controls = get_or_create_controls(ctx, dom->node); AddControl* found = shd_dict_find_value(const Node, AddControl, controls->control_destinations, dst); diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index 55f42d2c5..f7379bce6 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -87,7 +87,7 @@ static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* fl LTNode* pst_lt = looptree_lookup(lt, f_src_ipostdom->node); assert(src_lt->type == LF_LEAF && pst_lt->type == LF_LEAF); if (src_lt->parent == pst_lt->parent) { - log_string(DEBUGVV, "We have a candidate for reconvergence: a branch starts at %d and ends at %d\n", src->node->id, f_src_ipostdom->node->id); + shd_log_fmt(DEBUGVV, "We have a candidate for reconvergence: a branch starts at %d and ends at %d\n", src->node->id, f_src_ipostdom->node->id); paint_dominated_up_to_postdom(n, a, arr, f_src_ipostdom->node, n->node); } } diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 3fdf0106e..5213f0280 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -82,14 +82,14 @@ static const Node* find_entry_point(Module* m, const CompilerConfig* config) { static void specialize_arena_config(const CompilerConfig* config, Module* src, ArenaConfig* target) { const Node* old_entry_point_decl = find_entry_point(src, config); if (!old_entry_point_decl) - error("Entry point not found") + shd_error("Entry point not found") if (old_entry_point_decl->tag != Function_TAG) - error("%s is not a function", config->specialization.entry_point); + shd_error("%s is not a function", config->specialization.entry_point); const Node* ep = lookup_annotation(old_entry_point_decl, "EntryPoint"); if (!ep) - error("%s is not annotated with @EntryPoint", config->specialization.entry_point); + shd_error("%s is not annotated with @EntryPoint", config->specialization.entry_point); switch (execution_model_from_string(get_annotation_string_payload(ep))) { - case EmNone: error("Unknown entry point type: %s", get_annotation_string_payload(ep)) + case EmNone: shd_error("Unknown entry point type: %s", get_annotation_string_payload(ep)) case EmCompute: { const Node* old_wg_size_annotation = lookup_annotation(old_entry_point_decl, "WorkgroupSize"); assert(old_wg_size_annotation && old_wg_size_annotation->tag == AnnotationValues_TAG && get_annotation_values(old_wg_size_annotation).count == 3); diff --git a/src/shady/print.c b/src/shady/print.c index d5186dda5..d856207fc 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -117,22 +117,22 @@ void dump_module(Module* mod) { printf("\n"); } -void log_node(LogLevel level, const Node* node) { - if (level <= get_log_level()) { +void shd_log_node(LogLevel level, const Node* node) { + if (level <= shd_log_get_level()) { Printer* p = shd_new_printer_from_file(stderr); print_node(p, (NodePrintConfig) {.color = true}, node); shd_destroy_printer(p); } } -void log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) { +void shd_log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* mod) { NodePrintConfig config = { .color = true }; if (compiler_cfg) { config.print_generated = compiler_cfg->logging.print_generated; config.print_builtin = compiler_cfg->logging.print_builtin; config.print_internal = compiler_cfg->logging.print_internal; } - if (level <= get_log_level()) { + if (level <= shd_log_get_level()) { Printer* p = shd_new_printer_from_file(stderr); print_module(p, config, mod); shd_destroy_printer(p); @@ -363,7 +363,7 @@ static bool print_type(PrinterCtx* ctx, const Node* node) { case FloatTy16: printf("16"); break; case FloatTy32: printf("32"); break; case FloatTy64: printf("64"); break; - default: error("Not a known valid float width") + default: shd_error("Not a known valid float width") } break; case MaskType_TAG: printf("mask"); break; @@ -380,7 +380,7 @@ static bool print_type(PrinterCtx* ctx, const Node* node) { case IntTy16: printf("16"); break; case IntTy32: printf("32"); break; case IntTy64: printf("64"); break; - default: error("Not a known valid int width") + default: shd_error("Not a known valid int width") } break; case RecordType_TAG: @@ -546,7 +546,7 @@ static bool print_value(PrinterCtx* ctx, const Node* node) { case IntTy16: printf("%" PRIu16, (uint16_t) v); break; case IntTy32: printf("%" PRIu32, (uint32_t) v); break; case IntTy64: printf("%" PRIu64, v); break; - default: error("Not a known valid int width") + default: shd_error("Not a known valid int width") } printf(RESET); return true; @@ -565,7 +565,7 @@ static bool print_value(PrinterCtx* ctx, const Node* node) { memcpy(&d, &node->payload.float_literal.value, sizeof(uint64_t)); printf("%.17g", d); break; } - default: error("Not a known valid float width") + default: shd_error("Not a known valid float width") } printf(RESET); return true; @@ -969,7 +969,7 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { printf(";\n\n"); break; } - default: error("Not a decl"); + default: shd_error("Not a decl"); } } @@ -1008,7 +1008,7 @@ static void print_annotation(PrinterCtx* ctx, const Node* node) { print_args_list(ctx, annotation->values); break; } - case NotAnAnnotation: error(""); + case NotAnAnnotation: shd_error(""); } } diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 308d2c255..74365ba5b 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -207,17 +207,17 @@ void register_processed(Rewriter* ctx, const Node* old, const Node* new) { // as long as there is no conflict, this is correct, but this might hide perf hazards if we fail to cache things if (*found == new) return; - error_print("Trying to replace "); - log_node(ERROR, old); - error_print(" with "); - log_node(ERROR, new); - error_print(" but there was already "); + shd_error_print("Trying to replace "); + shd_log_node(ERROR, old); + shd_error_print(" with "); + shd_log_node(ERROR, new); + shd_error_print(" but there was already "); if (*found) - log_node(ERROR, *found); + shd_log_node(ERROR, *found); else - log_string(ERROR, "NULL"); - error_print("\n"); - error("The same node got processed twice !"); + shd_log_fmt(ERROR, "NULL"); + shd_error_print("\n"); + shd_error("The same node got processed twice !"); } #endif struct Dict* map = is_declaration(old) ? ctx->decls_map : ctx->map; @@ -298,7 +298,7 @@ Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { new = nominal_type(rewriter->dst_module, new_annotations, old->payload.nom_type.name); break; } - case NotADeclaration: error("not a decl"); + case NotADeclaration: shd_error("not a decl"); } assert(new); register_processed(rewriter, old, new); @@ -326,7 +326,7 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) new->payload.nom_type.body = rewrite_op_helper(rewriter, NcType, "body", old->payload.nom_type.body); break; } - case NotADeclaration: error("not a decl"); + case NotADeclaration: shd_error("not a decl"); } } @@ -350,9 +350,9 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { return new; } case Param_TAG: - log_string(ERROR, "Can't rewrite: "); - log_node(ERROR, node); - log_string(ERROR, ", params should be rewritten by the abstraction rewrite logic"); + shd_log_fmt(ERROR, "Can't rewrite: "); + shd_log_node(ERROR, node); + shd_log_fmt(ERROR, ", params should be rewritten by the abstraction rewrite logic"); shd_error_die(); case BasicBlock_TAG: { Nodes params = recreate_params(rewriter, node->payload.basic_block.params); @@ -371,9 +371,9 @@ void dump_rewriter_map(Rewriter* r) { size_t i = 0; const Node* src, *dst; while (shd_dict_iter(r->map, &i, &src, &dst)) { - log_node(ERROR, src); - log_string(ERROR, " -> "); - log_node(ERROR, dst); - log_string(ERROR, "\n"); + shd_log_node(ERROR, src); + shd_log_fmt(ERROR, " -> "); + shd_log_node(ERROR, dst); + shd_log_fmt(ERROR, "\n"); } } \ No newline at end of file diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 536816e45..025b9bdd2 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -274,7 +274,7 @@ const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, cons const Node* get_default_zero_value(IrArena* a, const Type* t) { switch (is_type(t)) { - case NotAType: error("") + case NotAType: shd_error("") case Type_Int_TAG: return int_literal(a, (IntLiteral) { .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed, .value = 0 }); case Type_Float_TAG: return float_literal(a, (FloatLiteral) { .width = t->payload.float_type.width, .value = 0 }); case Type_Bool_TAG: return false_lit(a); @@ -286,7 +286,7 @@ const Node* get_default_zero_value(IrArena* a, const Type* t) { case Type_TypeDeclRef_TAG: { Nodes elem_tys = get_composite_type_element_types(t); if (elem_tys.count >= 1024) { - warn_print("Potential performance issue: creating a really composite full of zero/default values (size=%d)!\n", elem_tys.count); + shd_warn_print("Potential performance issue: creating a really composite full of zero/default values (size=%d)!\n", elem_tys.count); } LARRAY(const Node*, elems, elem_tys.count); for (size_t i = 0; i < elem_tys.count; i++) diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 32fd5eba0..410100f71 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -60,14 +60,14 @@ TypeMemLayout get_mem_layout(IrArena* a, const Type* type) { size_t base_word_size = int_size_in_bytes(a->config.memory.word_size); assert(is_type(type)); switch (type->tag) { - case FnType_TAG: error("Functions have an opaque memory representation"); + case FnType_TAG: shd_error("Functions have an opaque memory representation"); case PtrType_TAG: switch (type->payload.ptr_type.address_space) { case AsPrivate: case AsSubgroup: case AsShared: case AsGlobal: case AsGeneric: return get_mem_layout(a, int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false })); // TODO: use per-as layout - default: error("Pointers in address space '%s' does not have a defined memory layout", get_address_space_name(type->payload.ptr_type.address_space)); + default: shd_error("Pointers in address space '%s' does not have a defined memory layout", get_address_space_name(type->payload.ptr_type.address_space)); } case Int_TAG: return (TypeMemLayout) { .type = type, @@ -107,7 +107,7 @@ TypeMemLayout get_mem_layout(IrArena* a, const Type* type) { case QualifiedType_TAG: return get_mem_layout(a, type->payload.qualified_type.type); case TypeDeclRef_TAG: return get_mem_layout(a, type->payload.type_decl_ref.decl->payload.nom_type.body); case RecordType_TAG: return get_record_layout(a, type, NULL); - default: error("not a known type"); + default: shd_error("not a known type"); } } diff --git a/src/shady/type.c b/src/shady/type.c index c9ea8ec96..e1b8b50e8 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -29,7 +29,7 @@ bool is_subtype(const Type* supertype, const Type* type) { if (type == supertype) return true; switch (is_type(supertype)) { - case NotAType: error("supplied not a type to is_subtype"); + case NotAType: shd_error("supplied not a type to is_subtype"); case QualifiedType_TAG: { // uniform T <: varying T if (supertype->payload.qualified_type.is_uniform && !type->payload.qualified_type.is_uniform) @@ -146,11 +146,11 @@ bool is_subtype(const Type* supertype, const Type* type) { void check_subtype(const Type* supertype, const Type* type) { if (!is_subtype(supertype, type)) { - log_node(ERROR, type); - error_print(" isn't a subtype of "); - log_node(ERROR, supertype); - error_print("\n"); - error("failed check_subtype") + shd_log_node(ERROR, type); + shd_error_print(" isn't a subtype of "); + shd_log_node(ERROR, supertype); + shd_error_print("\n"); + shd_error("failed check_subtype") } } @@ -377,7 +377,7 @@ const Type* check_type_pack_type(IrArena* arena, PackType pack_type) { const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { if (!arena->config.address_spaces[ptr_type.address_space].allowed) { - error_print("Address space %s is not allowed in this arena\n", get_address_space_name(ptr_type.address_space)); + shd_error_print("Address space %s is not allowed in this arena\n", get_address_space_name(ptr_type.address_space)); shd_error_die(); } assert(ptr_type.pointed_type && "Shady does not support untyped pointers, but can infer them, see infer.c"); @@ -407,7 +407,7 @@ const Type* check_type_param(IrArena* arena, Param variable) { } const Type* check_type_untyped_number(IrArena* arena, UntypedNumber untyped) { - error("should never happen"); + shd_error("should never happen"); } const Type* check_type_int_literal(IrArena* arena, IntLiteral lit) { @@ -516,7 +516,7 @@ const Type* check_type_ref_decl(IrArena* arena, RefDecl ref_decl) { switch (ref_decl.decl->tag) { case GlobalVariable_TAG: case Constant_TAG: break; - default: error("You can only use RefDecl on a global or a constant. See FnAddr for taking addresses of functions.") + default: shd_error("You can only use RefDecl on a global or a constant. See FnAddr for taking addresses of functions.") } assert(t->tag != QualifiedType_TAG && "decl types may not be qualified"); return qualified_type(arena, (QualifiedType) { @@ -895,7 +895,7 @@ const Type* check_type_ext_instr(IrArena* arena, ExtInstr payload) { static void check_arguments_types_against_parameters_helper(Nodes param_types, Nodes arg_types) { if (param_types.count != arg_types.count) - error("Mismatched number of arguments/parameters"); + shd_error("Mismatched number of arguments/parameters"); for (size_t i = 0; i < param_types.count; i++) check_subtype(param_types.nodes[i], arg_types.nodes[i]); } @@ -943,7 +943,7 @@ const Type* check_type_if_instr(IrArena* arena, If if_instr) { assert(if_instr.tail && is_abstraction(if_instr.tail)); ensure_types_are_data_types(&if_instr.yield_types); if (get_unqualified_type(if_instr.condition->type) != bool_type(arena)) - error("condition of an if should be bool"); + shd_error("condition of an if should be bool"); // TODO check the contained Merge instrs if (if_instr.yield_types.count > 0) assert(if_instr.if_false); @@ -1248,11 +1248,11 @@ const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_var assert(b != BuiltinsCount); const Type* t = get_builtin_type(arena, b); if (t != global_variable.type) { - error_print("Creating a @Builtin global variable '%s' with the incorrect type: ", global_variable.name); - log_node(ERROR, global_variable.type); - error_print(" instead of the expected "); - log_node(ERROR, t); - error_print(".\n"); + shd_error_print("Creating a @Builtin global variable '%s' with the incorrect type: ", global_variable.name); + shd_log_node(ERROR, global_variable.type); + shd_error_print(" instead of the expected "); + shd_log_node(ERROR, t); + shd_error_print(".\n"); shd_error_die(); } } diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 2f24f35ee..5b34212cb 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -87,12 +87,12 @@ void enter_composite(const Type** datatype, bool* uniform, const Node* selector, } // also remember to assert literals for the selectors ! default: { - log_string(ERROR, "Trying to enter non-composite type '"); - log_node(ERROR, current_type); - log_string(ERROR, "' with selector '"); - log_node(ERROR, selector); - log_string(ERROR, "'."); - error(""); + shd_log_fmt(ERROR, "Trying to enter non-composite type '"); + shd_log_node(ERROR, current_type); + shd_log_fmt(ERROR, "' with selector '"); + shd_log_node(ERROR, selector); + shd_log_fmt(ERROR, "'."); + shd_error(""); } } *datatype = current_type; @@ -140,7 +140,7 @@ bool deconstruct_qualified_type(const Type** type_out) { if (type->tag == QualifiedType_TAG) { *type_out = type->payload.qualified_type.type; return type->payload.qualified_type.is_uniform; - } else error("Expected a value type (annotated with qual_type)") + } else shd_error("Expected a value type (annotated with qual_type)") } const Type* qualified_type_helper(const Type* type, bool uniform) { @@ -261,7 +261,7 @@ Nodes get_composite_type_element_types(const Type* type) { case Type_PackType_TAG: { size_t size = get_int_literal_value(*resolve_to_int_literal(get_fill_type_size(type)), false); if (size >= 1024) { - warn_print("Potential performance issue: creating a really big array of composites of types (size=%d)!\n", size); + shd_warn_print("Potential performance issue: creating a really big array of composites of types (size=%d)!\n", size); } const Type* element_type = get_fill_type_element_type(type); LARRAY(const Type*, types, size); @@ -270,7 +270,7 @@ Nodes get_composite_type_element_types(const Type* type) { } return nodes(type->arena, size, types); } - default: error("Not a composite type !") + default: shd_error("Not a composite type !") } } @@ -278,7 +278,7 @@ const Node* get_fill_type_element_type(const Type* composite_t) { switch (composite_t->tag) { case ArrType_TAG: return composite_t->payload.arr_type.element_type; case PackType_TAG: return composite_t->payload.pack_type.element_type; - default: error("fill values need to be either array or pack types") + default: shd_error("fill values need to be either array or pack types") } } @@ -286,6 +286,6 @@ const Node* get_fill_type_size(const Type* composite_t) { switch (composite_t->tag) { case ArrType_TAG: return composite_t->payload.arr_type.size; case PackType_TAG: return int32_literal(composite_t->arena, composite_t->payload.pack_type.width); - default: error("fill values need to be either array or pack types") + default: shd_error("fill values need to be either array or pack types") } } diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 69656f4cd..25147fa03 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -36,10 +36,10 @@ static void check_module(Module* mod) { Visitor v = { .visit_node_fn = search_for_memstuff }; visit_module(&v, mod); if (expect_memstuff != found_memstuff) { - error_print("Expected "); + shd_error_print("Expected "); if (!expect_memstuff) - error_print("no more "); - error_print("memory primops in the output.\n"); + shd_error_print("no more "); + shd_error_print("memory primops in the output.\n"); dump_module(mod); exit(-1); } @@ -97,7 +97,7 @@ int main(int argc, char** argv) { if (err) exit(err); - info_print("Compilation successful\n"); + shd_info_print("Compilation successful\n"); destroy_ir_arena(arena); destroy_driver_config(&args); diff --git a/test/test_builder.c b/test/test_builder.c index a11fb531a..4316763a4 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -12,7 +12,7 @@ #include #include -#define CHECK(x, failure_handler) { if (!(x)) { error_print(#x " failed\n"); failure_handler; } } +#define CHECK(x, failure_handler) { if (!(x)) { shd_error_print(#x " failed\n"); failure_handler; } } static void test_body_builder_constants(IrArena* a) { BodyBuilder* bb = begin_block_pure(a); diff --git a/test/test_math.c b/test/test_math.c index da13a97af..5d1b05bb1 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -7,7 +7,7 @@ #include #include -#define CHECK(x, failure_handler) { if (!(x)) { error_print(#x " failed\n"); failure_handler; } } +#define CHECK(x, failure_handler) { if (!(x)) { shd_error_print(#x " failed\n"); failure_handler; } } static bool check_same_bytes(char* a, char* b, size_t size) { if (memcmp(a, b, size) == 0) diff --git a/vcc/vcc.c b/vcc/vcc.c index c0a95eeeb..0a88c5615 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -21,7 +21,7 @@ int main(int argc, char** argv) { cli_parse_input_files(args.input_filenames, &argc, argv); if (shd_list_count(args.input_filenames) == 0) { - error_print("Missing input file. See --help for proper usage"); + shd_error_print("Missing input file. See --help for proper usage"); exit(MissingInputArg); } @@ -40,7 +40,7 @@ int main(int argc, char** argv) { destroy_ir_arena(get_module_arena(mod)); } - info_print("Done\n"); + shd_info_print("Done\n"); destroy_vcc_options(vcc_options); destroy_ir_arena(arena); diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 4039f1212..5db84d161 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -30,7 +30,7 @@ void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { argv[i] = NULL; i++; if (i == argc) - error("Missing subgroup size name"); + shd_error("Missing subgroup size name"); if (options->include_path) free((void*) options->include_path); options->include_path = shd_format_string_new("%s", argv[i]); @@ -48,7 +48,7 @@ void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { void vcc_check_clang(void) { int clang_retval = system(VCC_CLANG" --version"); if (clang_retval != 0) - error("clang not present in path or otherwise broken (retval=%d)", clang_retval); + shd_error("clang not present in path or otherwise broken (retval=%d)", clang_retval); } VccConfig vcc_init_config(CompilerConfig* compiler_config) { @@ -89,7 +89,7 @@ void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* inpu if (!vcc_options->tmp_filename) { if (vcc_options->only_run_clang) { - error_print("Please provide an output filename.\n"); + shd_error_print("Please provide an output filename.\n"); shd_error_die(); } char* tmp_alloc; @@ -118,7 +118,7 @@ void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* inpu shd_growy_append_bytes(g, 1, "\0"); char* arg_string = shd_growy_deconstruct(g); - info_print("built command: %s\n", arg_string); + shd_info_print("built command: %s\n", arg_string); FILE* stream = popen(arg_string, "r"); free(arg_string); @@ -134,7 +134,7 @@ void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* inpu shd_growy_append_string(json_bytes, "\0"); char* llvm_result = shd_growy_deconstruct(json_bytes); int clang_returned = pclose(stream); - info_print("Clang returned %d and replied: \n%s", clang_returned, llvm_result); + shd_info_print("Clang returned %d and replied: \n%s", clang_returned, llvm_result); free(llvm_result); if (clang_returned) exit(ClangInvocationFailed); From 64f36b96982e22bea2f3b8f2a6e503d8832bac92 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 15:54:15 +0200 Subject: [PATCH 599/693] common: normalized all remaining (void) fns --- src/common/arena.c | 2 +- src/common/arena.h | 2 +- src/common/growy.c | 2 +- src/common/growy.h | 2 +- src/common/printer.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/arena.c b/src/common/arena.c index 3b9133401..3b4525c64 100644 --- a/src/common/arena.c +++ b/src/common/arena.c @@ -19,7 +19,7 @@ inline static size_t round_up(size_t a, size_t b) { return divided * b; } -Arena* shd_new_arena() { +Arena* shd_new_arena(void) { Arena* arena = malloc(sizeof(Arena)); *arena = (Arena) { .nblocks = 0, diff --git a/src/common/arena.h b/src/common/arena.h index ddcee2e42..45c3426cf 100644 --- a/src/common/arena.h +++ b/src/common/arena.h @@ -5,7 +5,7 @@ typedef struct Arena_ Arena; -Arena* shd_new_arena(); +Arena* shd_new_arena(void); void shd_destroy_arena(Arena* arena); void* shd_arena_alloc(Arena* arena, size_t size); diff --git a/src/common/growy.c b/src/common/growy.c index 8efe2178b..95ae760e2 100644 --- a/src/common/growy.c +++ b/src/common/growy.c @@ -11,7 +11,7 @@ struct Growy_ { size_t used, size; }; -Growy* shd_new_growy() { +Growy* shd_new_growy(void) { Growy* g = calloc(1, sizeof(Growy)); *g = (Growy) { .buffer = calloc(1, init_size), diff --git a/src/common/growy.h b/src/common/growy.h index 43b7fc37e..de0af8f55 100644 --- a/src/common/growy.h +++ b/src/common/growy.h @@ -7,7 +7,7 @@ /// Addresses not guaranteed to be stable. typedef struct Growy_ Growy; -Growy* shd_new_growy(); +Growy* shd_new_growy(void); void shd_growy_append_bytes(Growy*, size_t, const char*); void shd_growy_append_string(Growy* g, const char* str); void shd_growy_append_formatted(Growy* g, const char* str, ...); diff --git a/src/common/printer.h b/src/common/printer.h index 924fd9f93..d1c087caf 100644 --- a/src/common/printer.h +++ b/src/common/printer.h @@ -17,7 +17,7 @@ void shd_printer_deindent(Printer* p); void shd_printer_flush(Printer* p); const char* shd_printer_growy_unwrap(Printer* p); -Growy* shd_new_growy(); +Growy* shd_new_growy(void); #define shd_helper_format_string(f, ...) printer_growy_unwrap(cunk_print(cunk_open_growy_as_printer(cunk_new_growy()), (f), __VA_ARGS__)) #endif From d0a3e4699700dbdd455f4e1d5f4262ceb2bdf397 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 16:01:18 +0200 Subject: [PATCH 600/693] add shd_ prefix to nodes functions --- include/shady/ir.h | 22 ++-- readme.md | 2 +- src/backend/c/emit_c_control_flow.c | 6 +- src/backend/c/emit_c_value.c | 38 +++--- src/backend/spirv/emit_spv_type.c | 2 +- src/backend/spirv/emit_spv_value.c | 28 ++-- src/backend/spirv/spirv_builder.c | 2 +- src/backend/spirv/spirv_lift_globals_ssbo.c | 24 ++-- src/frontend/llvm/l2s.c | 22 ++-- src/frontend/llvm/l2s_annotations.c | 2 +- src/frontend/llvm/l2s_instr.c | 124 +++++++++--------- src/frontend/llvm/l2s_meta.c | 12 +- src/frontend/llvm/l2s_postprocess.c | 20 +-- src/frontend/llvm/l2s_type.c | 8 +- src/frontend/llvm/l2s_value.c | 10 +- src/frontend/slim/bind.c | 16 +-- src/frontend/slim/infer.c | 32 ++--- src/frontend/slim/parser.c | 108 +++++++-------- src/frontend/spirv/s2s.c | 138 ++++++++++---------- src/runtime/vulkan/vk_runtime_program.c | 4 +- src/shady/analysis/cfg.c | 2 +- src/shady/analysis/leak.c | 2 +- src/shady/annotation.c | 2 +- src/shady/body_builder.c | 22 ++-- src/shady/constructors.c | 6 +- src/shady/fold.c | 26 ++-- src/shady/generator_constructors.c | 2 +- src/shady/generator_rewrite.c | 2 +- src/shady/ir.c | 40 +++--- src/shady/module.c | 2 +- src/shady/node.c | 14 +- src/shady/passes/cleanup.c | 2 +- src/shady/passes/lcssa.c | 16 +-- src/shady/passes/lift_everything.c | 8 +- src/shady/passes/lift_indirect_targets.c | 16 +-- src/shady/passes/lower_alloca.c | 18 +-- src/shady/passes/lower_callf.c | 18 +-- src/shady/passes/lower_cf_instrs.c | 20 +-- src/shady/passes/lower_entrypoint_args.c | 8 +- src/shady/passes/lower_fill.c | 2 +- src/shady/passes/lower_generic_globals.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 82 ++++++------ src/shady/passes/lower_int64.c | 20 +-- src/shady/passes/lower_lea.c | 10 +- src/shady/passes/lower_logical_pointers.c | 6 +- src/shady/passes/lower_memcpy.c | 50 +++---- src/shady/passes/lower_memory_layout.c | 8 +- src/shady/passes/lower_nullptr.c | 4 +- src/shady/passes/lower_physical_ptrs.c | 78 +++++------ src/shady/passes/lower_stack.c | 34 ++--- src/shady/passes/lower_subgroup_ops.c | 22 ++-- src/shady/passes/lower_subgroup_vars.c | 4 +- src/shady/passes/lower_switch_btree.c | 2 +- src/shady/passes/lower_tailcalls.c | 120 ++++++++--------- src/shady/passes/lower_vec_arr.c | 6 +- src/shady/passes/lower_workgroups.c | 30 ++--- src/shady/passes/mark_leaf_functions.c | 6 +- src/shady/passes/normalize_builtins.c | 6 +- src/shady/passes/opt_demote_alloca.c | 6 +- src/shady/passes/opt_inline.c | 2 +- src/shady/passes/opt_mem2reg.c | 4 +- src/shady/passes/opt_restructure.c | 46 +++---- src/shady/passes/passes.h | 2 +- src/shady/passes/reconvergence_heuristics.c | 36 ++--- src/shady/passes/remove_critical_edges.c | 4 +- src/shady/passes/scope2control.c | 14 +- src/shady/passes/scope_heuristic.c | 18 +-- src/shady/rewrite.c | 6 +- src/shady/transform/ir_gen_helpers.c | 52 ++++---- src/shady/transform/memory_layout.c | 2 +- src/shady/type.c | 40 +++--- src/shady/type_helpers.c | 14 +- test/test_builder.c | 36 ++--- 73 files changed, 810 insertions(+), 810 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 9f3239d81..bed15097b 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -24,20 +24,20 @@ typedef struct Strings_ { String* strings; } Strings; -Nodes nodes(IrArena*, size_t count, const Node*[]); -Strings strings(IrArena*, size_t count, const char*[]); +Nodes shd_nodes(IrArena*, size_t count, const Node*[]); +Strings shd_strings(IrArena* arena, size_t count, const char** in_strs); -Nodes empty(IrArena*); -Nodes singleton(const Node*); -#define mk_nodes(arena, ...) nodes(arena, sizeof((const Node*[]) { __VA_ARGS__ }) / sizeof(const Node*), (const Node*[]) { __VA_ARGS__ }) +Nodes shd_empty(IrArena* a); +Nodes shd_singleton(const Node* n); +#define mk_nodes(arena, ...) shd_nodes(arena, sizeof((const Node*[]) { __VA_ARGS__ }) / sizeof(const Node*), (const Node*[]) { __VA_ARGS__ }) -const Node* first(Nodes nodes); +const Node* shd_first(Nodes nodes); -Nodes append_nodes(IrArena*, Nodes, const Node*); -Nodes prepend_nodes(IrArena*, Nodes, const Node*); -Nodes concat_nodes(IrArena*, Nodes, Nodes); -Nodes change_node_at_index(IrArena*, Nodes, size_t, const Node*); -bool find_in_nodes(Nodes nodes, const Node* n); +Nodes shd_nodes_append(IrArena*, Nodes, const Node*); +Nodes shd_nodes_prepend(IrArena*, Nodes, const Node*); +Nodes shd_concat_nodes(IrArena* arena, Nodes a, Nodes b); +Nodes shd_change_node_at_index(IrArena* arena, Nodes old, size_t i, const Node* n); +bool shd_find_in_nodes(Nodes nodes, const Node* n); String string_sized(IrArena*, size_t size, const char* start); String string(IrArena*, const char*); diff --git a/readme.md b/readme.md index f05c8a763..0a3f17eee 100644 --- a/readme.md +++ b/readme.md @@ -75,7 +75,7 @@ The grammar is defined in [grammar.json](include/shady/grammar.json), this file ## Language syntax -The textual syntax of the language is C-like in that return types come first. Variance annotations are supported. +The textual syntax of the language is C-like in that return types come shd_first. Variance annotations are supported. Overall the language is structurally close to SPIR-V and LLVM, very much on purpose. There is a 'front-end' (slim) variant of the IR that allows for mutable variables and using instructions as values. diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index 2659a65f2..b5b73d2be 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -52,7 +52,7 @@ static Strings emit_variable_declarations(Emitter* emitter, FnEmitter* fn, Print } else c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); } - return strings(emitter->arena, types.count, names); + return shd_strings(emitter->arena, types.count, names); } static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { @@ -148,7 +148,7 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { if (!arr[i]) arr[i] = unique_name(emitter->arena, "phi"); } - Strings param_names = strings(emitter->arena, variables.count, arr); + Strings param_names = shd_strings(emitter->arena, variables.count, arr); Strings eparams = emit_variable_declarations(emitter, fn, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop.initial_args); for (size_t i = 0; i < params.count; i++) register_emitted(&sub_emiter, fn, params.nodes[i], term_from_cvalue(eparams.strings[i])); @@ -197,7 +197,7 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin LARRAY(CValue, values, args.count); for (size_t i = 0; i < args.count; i++) values[i] = to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i])); - c_emit_pack_code(block_printer, strings(emitter->arena, args.count, values), packed); + c_emit_pack_code(block_printer, shd_strings(emitter->arena, args.count, values), packed); shd_print(block_printer, "\nreturn %s;", packed); } break; diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 3f1bce6fb..08b0379c6 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -245,7 +245,7 @@ CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CT } static const Type* get_first_op_scalar_type(Nodes ops) { - const Type* t = first(ops)->type; + const Type* t = shd_first(ops)->type; deconstruct_qualified_type(&t); deconstruct_maybe_packed_type(&t); return t; @@ -455,19 +455,19 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } case min_op: { - CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); + CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, b, a)); break; } case max_op: { - CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); + CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, a, b)); break; } case sign_op: { - CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); + CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); break; } @@ -491,7 +491,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case lshift_op: case rshift_arithm_op: case rshift_logical_op: { - CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); + CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); const Node* offset = prim_op->operands.nodes[1]; CValue c_offset = to_cvalue(emitter, c_emit_value(emitter, fn, offset)); if (emitter->config.dialect == CDialect_GLSL) { @@ -502,17 +502,17 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } case size_of_op: - term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, shd_first(prim_op->type_arguments), NULL))); break; case align_of_op: - term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "alignof(%s)", c_emit_type(emitter, first(prim_op->type_arguments), NULL))); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "alignof(%s)", c_emit_type(emitter, shd_first(prim_op->type_arguments), NULL))); break; case offset_of_op: { - const Type* t = first(prim_op->type_arguments); + const Type* t = shd_first(prim_op->type_arguments); while (t->tag == TypeDeclRef_TAG) { t = get_nominal_type_body(t); } - const Node* index = first(prim_op->operands); + const Node* index = shd_first(prim_op->operands); uint64_t index_literal = get_int_literal_value(*resolve_to_int_literal(index), false); String member_name = c_get_record_field_name(t, index_literal); term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "offsetof(%s, %s)", c_emit_type(emitter, t, NULL), member_name)); @@ -526,9 +526,9 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } case convert_op: { - CTerm src = c_emit_value(emitter, fn, first(prim_op->operands)); - const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); - const Type* dst_type = first(prim_op->type_arguments); + CTerm src = c_emit_value(emitter, fn, shd_first(prim_op->operands)); + const Type* src_type = get_unqualified_type(shd_first(prim_op->operands)->type); + const Type* dst_type = shd_first(prim_op->type_arguments); if (emitter->config.dialect == CDialect_GLSL) { if (is_glsl_scalar_type(src_type) && is_glsl_scalar_type(dst_type)) { CType t = c_emit_type(emitter, dst_type, NULL); @@ -542,9 +542,9 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } case reinterpret_op: { - CTerm src_value = c_emit_value(emitter, fn, first(prim_op->operands)); - const Type* src_type = get_unqualified_type(first(prim_op->operands)->type); - const Type* dst_type = first(prim_op->type_arguments); + CTerm src_value = c_emit_value(emitter, fn, shd_first(prim_op->operands)); + const Type* src_type = get_unqualified_type(shd_first(prim_op->operands)->type); + const Type* dst_type = shd_first(prim_op->type_arguments); switch (emitter->config.dialect) { case CDialect_CUDA: case CDialect_C11: { @@ -615,7 +615,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case insert_op: case extract_dynamic_op: case extract_op: { - CValue acc = to_cvalue(emitter, c_emit_value(emitter, fn, first(prim_op->operands))); + CValue acc = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); bool insert = prim_op->op == insert_op; if (insert) { @@ -625,7 +625,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node term = term_from_cvalue(dst); } - const Type* t = get_unqualified_type(first(prim_op->operands)->type); + const Type* t = get_unqualified_type(shd_first(prim_op->operands)->type); for (size_t i = (insert ? 2 : 1); i < prim_op->operands.count; i++) { const Node* index = prim_op->operands.nodes[i]; const IntLiteral* static_index = resolve_to_int_literal(index); @@ -719,7 +719,7 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E if (strcmp(instr.set, "spirv.core") == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { - CValue value = to_cvalue(emitter, c_emit_value(emitter, fn, first(instr.operands))); + CValue value = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(instr.operands))); switch (emitter->config.dialect) { case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; @@ -730,7 +730,7 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E } case SpvOpGroupNonUniformElect: { assert(instr.operands.count == 1); - const IntLiteral* scope = resolve_to_int_literal(first(instr.operands)); + const IntLiteral* scope = resolve_to_int_literal(shd_first(instr.operands)); assert(scope && scope->value == SpvScopeSubgroup); switch (emitter->config.dialect) { case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_elect_first()")); diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 4349e28c9..30149bd5b 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -158,7 +158,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { } case NoRet_TAG: case LamType_TAG: - case BBType_TAG: shd_error("we can't emit arrow types that aren't those of first-class functions") + case BBType_TAG: shd_error("we can't emit arrow types that aren't those of shd_first-class functions") case FnType_TAG: { const FnType* fnt = &type->payload.fn_type; LARRAY(SpvId, params, fnt->param_types.count); diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 78400d658..c66f85692 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -146,10 +146,10 @@ static const IselTableEntry isel_table[] = { static const Type* get_result_t(Emitter* emitter, IselTableEntry entry, Nodes args, Nodes type_arguments) { switch (entry.result_kind) { - case Same: return get_unqualified_type(first(args)->type); - case SameTuple: return record_type(emitter->arena, (RecordType) { .members = mk_nodes(emitter->arena, get_unqualified_type(first(args)->type), get_unqualified_type(first(args)->type)) }); + case Same: return get_unqualified_type(shd_first(args)->type); + case SameTuple: return record_type(emitter->arena, (RecordType) { .members = mk_nodes(emitter->arena, get_unqualified_type(shd_first(args)->type), get_unqualified_type(shd_first(args)->type)) }); case Bool: return bool_type(emitter->arena); - case TyOperand: return first(type_arguments); + case TyOperand: return shd_first(type_arguments); case Void: return unit_type(emitter->arena); } } @@ -160,14 +160,14 @@ static SpvOp get_opcode(SHADY_UNUSED Emitter* emitter, IselTableEntry entry, Nod case Monomorphic: return entry.op; case FirstOp: { assert(args.count >= 1); - OperandClass op_class = classify_operand_type(get_unqualified_type(first(args)->type)); + OperandClass op_class = classify_operand_type(get_unqualified_type(shd_first(args)->type)); return entry.fo[op_class]; } case FirstAndResult: { assert(args.count >= 1); assert(type_arguments.count == 1); - OperandClass op_class = classify_operand_type(get_unqualified_type(first(args)->type)); - OperandClass return_t_class = classify_operand_type(first(type_arguments)); + OperandClass op_class = classify_operand_type(get_unqualified_type(shd_first(args)->type)); + OperandClass return_t_class = classify_operand_type(shd_first(type_arguments)); return entry.foar[op_class][return_t_class]; } } @@ -211,18 +211,18 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b custom: switch (the_op.op) { case reinterpret_op: { - const Type* dst = first(the_op.type_arguments); - const Type* src = get_unqualified_type(first(the_op.operands)->type); + const Type* dst = shd_first(the_op.type_arguments); + const Type* src = get_unqualified_type(shd_first(the_op.operands)->type); assert(dst->tag == PtrType_TAG && src->tag == PtrType_TAG); assert(src != dst); - return spvb_op(bb_builder, SpvOpBitcast, spv_emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, fn_builder, first(the_op.operands)) }); + return spvb_op(bb_builder, SpvOpBitcast, spv_emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, fn_builder, shd_first(the_op.operands)) }); } case insert_op: case extract_dynamic_op: case extract_op: { bool insert = the_op.op == insert_op; - const Node* src_value = first(args); + const Node* src_value = shd_first(args); const Type* result_t = instr->type; size_t indices_start = insert ? 2 : 1; size_t indices_count = args.count - indices_start; @@ -264,7 +264,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b return spvb_vecshuffle(bb_builder, spv_emit_type(emitter, result_t), a, b, args.count - 2, indices); } case select_op: { - SpvId cond = spv_emit_value(emitter, fn_builder, first(args)); + SpvId cond = spv_emit_value(emitter, fn_builder, shd_first(args)); SpvId truv = spv_emit_value(emitter, fn_builder, args.nodes[1]); SpvId flsv = spv_emit_value(emitter, fn_builder, args.nodes[2]); @@ -286,7 +286,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); SpvId local_id = spvb_op(bb_builder, SpvOpLoad, spv_emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, fn_builder, b) }); - return spvb_group_shuffle(bb_builder, spv_emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, fn_builder, first(instr.operands)), local_id); + return spvb_group_shuffle(bb_builder, spv_emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, fn_builder, shd_first(instr.operands)), local_id); } break; } @@ -297,7 +297,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b // ad-hoc extension for my sanity if (get_unqualified_type(instr.result_t) == get_actual_mask_type(emitter->arena)) { const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = uint32_type(emitter->arena) }); - SpvId raw_result = spvb_group_ballot(bb_builder, spv_emit_type(emitter, i32x4), spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), spv_emit_value(emitter, fn_builder, first(instr.operands))); + SpvId raw_result = spvb_group_ballot(bb_builder, spv_emit_type(emitter, i32x4), spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), spv_emit_value(emitter, fn_builder, shd_first(instr.operands))); // TODO: why are we doing this in SPIR-V and not the IR ? SpvId low32 = spvb_extract(bb_builder, spv_emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 0 }); SpvId hi32 = spvb_extract(bb_builder, spv_emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 1 }); @@ -311,7 +311,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b } case SpvOpGroupNonUniformIAdd: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformArithmetic); - SpvId scope = spv_emit_value(emitter, fn_builder, first(instr.operands)); + SpvId scope = spv_emit_value(emitter, fn_builder, shd_first(instr.operands)); SpvGroupOperation group_op = get_int_literal_value(*resolve_to_int_literal(instr.operands.nodes[2]), false); return spvb_group_non_uniform_group_op(bb_builder, spv_emit_type(emitter, instr.result_t), instr.opcode, scope, group_op, spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), NULL); } diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index ece6388d4..ad76d85e2 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -551,7 +551,7 @@ void spvb_declare_function(SpvbFileBuilder* file_builder, SpvbFnBuilder* fn_buil // Includes stuff like OpFunctionParameters copy_section(fn_builder->header); - assert(shd_list_count(fn_builder->bbs) == 0 && "declared functions must be empty"); + assert(shd_list_count(fn_builder->bbs) == 0 && "declared functions must be shd_empty"); op(SpvOpFunctionEnd, 1); diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 93646a2cc..6c961111f 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -28,10 +28,10 @@ static const Node* process(Context* ctx, const Node* node) { shd_dict_clear(functx.rewriter.map); register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); - Node* post_prelude = basic_block(a, empty(a), "post-prelude"); + Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); - set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); + set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, shd_empty(a), bb_mem(functx.bb)))); shd_destroy_dict(functx.rewriter.map); } return newfun; @@ -41,7 +41,7 @@ static const Node* process(Context* ctx, const Node* node) { if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) break; assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); - const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), int32_literal(a, 0), singleton(rewrite_node(&ctx->rewriter, odecl))); + const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), int32_literal(a, 0), shd_singleton(rewrite_node(&ctx->rewriter, odecl))); const Node* ptr = gen_load(ctx->bb, ptr_addr); return ptr; } @@ -76,11 +76,11 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul LARRAY(String, member_names, old_decls.count); Nodes annotations = mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" })); - annotations = empty(a); + annotations = shd_empty(a); - annotations = append_nodes(a, annotations, annotation_value(a, (AnnotationValue) { .name = "DescriptorSet", .value = int32_literal(a, 0) })); - annotations = append_nodes(a, annotations, annotation_value(a, (AnnotationValue) { .name = "DescriptorBinding", .value = int32_literal(a, 0) })); - annotations = append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Constants" })); + annotations = shd_nodes_append(a, annotations, annotation_value(a, (AnnotationValue) { .name = "DescriptorSet", .value = int32_literal(a, 0) })); + annotations = shd_nodes_append(a, annotations, annotation_value(a, (AnnotationValue) { .name = "DescriptorBinding", .value = int32_literal(a, 0) })); + annotations = shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Constants" })); size_t lifted_globals_count = 0; for (size_t i = 0; i < old_decls.count; i++) { @@ -97,8 +97,8 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul if (lifted_globals_count > 0) { const Type* lifted_globals_struct_t = record_type(a, (RecordType) { - .members = nodes(a, lifted_globals_count, member_tys), - .names = strings(a, lifted_globals_count, member_names), + .members = shd_nodes(a, lifted_globals_count, member_tys), + .names = shd_strings(a, lifted_globals_count, member_names), .special = DecorateBlock }); ctx.lifted_globals_decl = global_var(dst, annotations, lifted_globals_struct_t, "lifted_globals", AsShaderStorageBufferObject); @@ -112,9 +112,9 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) continue; if (odecl->payload.global_variable.init) - ctx.lifted_globals_decl->payload.global_variable.annotations = append_nodes(a, ctx.lifted_globals_decl->payload.global_variable.annotations, annotation_values(a, (AnnotationValues) { - .name = "InitialValue", - .values = mk_nodes(a, int32_literal(a, lifted_globals_count), rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) + ctx.lifted_globals_decl->payload.global_variable.annotations = shd_nodes_append(a, ctx.lifted_globals_decl->payload.global_variable.annotations, annotation_values(a, (AnnotationValues) { + .name = "InitialValue", + .values = mk_nodes(a, int32_literal(a, lifted_globals_count), rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) })); lifted_globals_count++; diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 5cc452e2e..ccfd32e08 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -78,7 +78,7 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic LLVMDumpValue((LLVMValueRef)bb); struct List* phis = shd_new_list(LLVMValueRef); - Nodes params = empty(a); + Nodes params = shd_empty(a); LLVMValueRef instr = LLVMGetFirstInstruction(bb); while (instr) { switch (LLVMGetInstructionOpcode(instr)) { @@ -86,7 +86,7 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic const Node* nparam = param(a, qualified_type_helper(convert_type(p, LLVMTypeOf(instr)), false), "phi"); shd_dict_insert(LLVMValueRef, const Node*, p->map, instr, nparam); shd_list_append(LLVMValueRef, phis, instr); - params = append_nodes(a, params, nparam); + params = shd_nodes_append(a, params, nparam); break; } default: goto after_phis; @@ -154,24 +154,24 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { IrArena* a = get_module_arena(p->dst); shd_debug_print("Converting function: %s\n", LLVMGetValueName(fn)); - Nodes params = empty(a); + Nodes params = shd_empty(a); for (LLVMValueRef oparam = LLVMGetFirstParam(fn); oparam; oparam = LLVMGetNextParam(oparam)) { LLVMTypeRef ot = LLVMTypeOf(oparam); const Type* t = convert_type(p, ot); const Node* nparam = param(a, qualified_type_helper(t, false), LLVMGetValueName(oparam)); shd_dict_insert(LLVMValueRef, const Node*, p->map, oparam, nparam); - params = append_nodes(a, params, nparam); + params = shd_nodes_append(a, params, nparam); if (oparam == LLVMGetLastParam(fn)) break; } const Type* fn_type = convert_type(p, LLVMGlobalGetValueType(fn)); assert(fn_type->tag == FnType_TAG); assert(fn_type->payload.fn_type.param_types.count == params.count); - Nodes annotations = empty(a); + Nodes annotations = shd_empty(a); switch (LLVMGetLinkage(fn)) { case LLVMExternalLinkage: case LLVMExternalWeakLinkage: { - annotations = append_nodes(a, annotations, annotation(a, (Annotation) {.name = "Exported"})); + annotations = shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Exported" })); break; } default: @@ -185,7 +185,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { .jumps_todo = shd_new_list(JumpTodo), }; const Node* r = fn_addr_helper(a, f); - r = prim_op_helper(a, reinterpret_op, singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = unit_type(a) })), singleton(r)); + r = prim_op_helper(a, reinterpret_op, shd_singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = unit_type(a) })), shd_singleton(r)); //r = prim_op_helper(a, convert_op, singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = unit_type(a) })), singleton(r)); shd_dict_insert(LLVMValueRef, const Node*, p->map, fn, r); @@ -262,19 +262,19 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { const Type* ptr_t = convert_type(p, LLVMTypeOf(global)); assert(ptr_t->tag == PtrType_TAG); AddressSpace as = ptr_t->payload.ptr_type.address_space; - decl = global_var(p->dst, empty(a), type, name, as); + decl = global_var(p->dst, shd_empty(a), type, name, as); if (value && as != AsUniformConstant) decl->payload.global_variable.init = convert_value(p, value); if (UNTYPED_POINTERS) { - Node* untyped_wrapper = constant(p->dst, singleton(annotation(a, (Annotation) { .name = "Inline" })), ptr_t, format_string_interned(a, "%s_untyped", name)); + Node* untyped_wrapper = constant(p->dst, shd_singleton(annotation(a, (Annotation) { .name = "Inline" })), ptr_t, format_string_interned(a, "%s_untyped", name)); untyped_wrapper->payload.constant.value = ref_decl_helper(a, decl); - untyped_wrapper->payload.constant.value = prim_op_helper(a, reinterpret_op, singleton(ptr_t), singleton(ref_decl_helper(a, decl))); + untyped_wrapper->payload.constant.value = prim_op_helper(a, reinterpret_op, shd_singleton(ptr_t), shd_singleton(ref_decl_helper(a, decl))); decl = untyped_wrapper; } } else { const Type* type = convert_type(p, LLVMTypeOf(global)); - decl = constant(p->dst, empty(a), type, name); + decl = constant(p->dst, shd_empty(a), type, name); decl->payload.constant.value = convert_value(p, global); } diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index da8c7e0d4..8a6327b0f 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -38,7 +38,7 @@ static const Node* look_past_stuff(const Node* thing) { if (thing->tag == PrimOp_TAG) { switch (thing->payload.prim_op.op) { case reinterpret_op: - case convert_op: thing = first(thing->payload.prim_op.operands); break; + case convert_op: thing = shd_first(thing->payload.prim_op.operands); break; default: assert(false); } } diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index d0ba1ad38..06c287d76 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -20,7 +20,7 @@ static Nodes convert_operands(Parser* p, size_t num_ops, LLVMValueRef v) { else ops[i] = convert_value(p, op); } - Nodes operands = nodes(a, num_ops, ops); + Nodes operands = shd_nodes(a, num_ops, ops); return operands; } @@ -38,8 +38,8 @@ static Nodes reinterpret_operands(BodyBuilder* b, Nodes ops, const Type* dst_t) IrArena* a = dst_t->arena; LARRAY(const Node*, nops, ops.count); for (size_t i = 0; i < ops.count; i++) - nops[i] = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(dst_t), singleton(ops.nodes[i])), 1)); - return nodes(a, ops.count, nops); + nops[i] = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(dst_t), shd_singleton(ops.nodes[i])), 1)); + return shd_nodes(a, ops.count, nops); } LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { @@ -74,7 +74,7 @@ static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, assert(false && "failed to find the appropriate source"); next: continue; } - return jump_helper(a, dst_bb, nodes(a, params_count, params), mem); + return jump_helper(a, dst_bb, shd_nodes(a, params_count, params), mem); } static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* element_type) { @@ -93,7 +93,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B IrArena* a = get_module_arena(p->dst); int num_ops = LLVMGetNumOperands(instr); size_t num_results = 1; - Nodes result_types = empty(a); + Nodes result_types = shd_empty(a); // const Node* r = NULL; LLVMOpcode opcode; @@ -139,7 +139,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B switch (opcode) { case LLVMRet: return fn_ret(a, (Return) { - .args = num_ops == 0 ? empty(a) : convert_operands(p, num_ops, instr), + .args = num_ops == 0 ? shd_empty(a) : convert_operands(p, num_ops, instr), .mem = bb_mem(b), }); case LLVMBr: { @@ -174,8 +174,8 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B return br_switch(a, (Switch) { .switch_value = inspectee, .default_jump = default_jump, - .case_values = nodes(a, n_targets, literals), - .case_jumps = nodes(a, n_targets, targets), + .case_values = shd_nodes(a, n_targets, literals), + .case_jumps = shd_nodes(a, n_targets, targets), .mem = bb_mem(b), }); } @@ -187,62 +187,62 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B case LLVMCallBr: goto unimplemented; case LLVMFNeg: - return prim_op_helper(a, neg_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, neg_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMFAdd: case LLVMAdd: - return prim_op_helper(a, add_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, add_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMSub: case LLVMFSub: - return prim_op_helper(a, sub_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, sub_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMMul: case LLVMFMul: - return prim_op_helper(a, mul_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, mul_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMUDiv: case LLVMFDiv: - return prim_op_helper(a, div_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, div_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMSDiv: { const Type* int_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* signed_t = change_int_t_sign(int_t, true); - return prim_op_helper(a, reinterpret_op, singleton(int_t), singleton(prim_op_helper(a, div_op, empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)))); + return prim_op_helper(a, reinterpret_op, shd_singleton(int_t), shd_singleton(prim_op_helper(a, div_op, shd_empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)))); } case LLVMURem: case LLVMFRem: - return prim_op_helper(a, mod_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, mod_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMSRem: { const Type* int_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* signed_t = change_int_t_sign(int_t, true); - return prim_op_helper(a, reinterpret_op, singleton(int_t), singleton(prim_op_helper(a, mod_op, empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)))); + return prim_op_helper(a, reinterpret_op, shd_singleton(int_t), shd_singleton(prim_op_helper(a, mod_op, shd_empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)))); } case LLVMShl: - return prim_op_helper(a, lshift_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, lshift_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMLShr: - return prim_op_helper(a, rshift_logical_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, rshift_logical_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMAShr: - return prim_op_helper(a, rshift_arithm_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, rshift_arithm_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMAnd: - return prim_op_helper(a, and_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, and_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMOr: - return prim_op_helper(a, or_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, or_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMXor: - return prim_op_helper(a, xor_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, xor_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMAlloca: { assert(t->tag == PtrType_TAG); const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivate }); - const Node* r = first(bind_instruction_outputs_count(b, stack_alloc(a, (StackAlloc) { .type = allocated_t, .mem = bb_mem(b) }), 1)); + const Node* r = shd_first(bind_instruction_outputs_count(b, stack_alloc(a, (StackAlloc) { .type = allocated_t, .mem = bb_mem(b) }), 1)); if (UNTYPED_POINTERS) { const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivate }); - r = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), singleton(r)), 1)); + r = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(untyped_ptr_t), shd_singleton(r)), 1)); } - return prim_op_helper(a, convert_op, singleton(t), singleton(r)); + return prim_op_helper(a, convert_op, shd_singleton(t), shd_singleton(r)); } case LLVMLoad: { Nodes ops = convert_operands(p, num_ops, instr); assert(ops.count == 1); - const Node* ptr = first(ops); + const Node* ptr = shd_first(ops); if (UNTYPED_POINTERS) { const Type* element_t = t; const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); + ptr = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } return bind_instruction_single(b, load(a, (Load) { .ptr = ptr, .mem = bb_mem(b) })); } @@ -255,29 +255,29 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Type* element_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 1))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); + ptr = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } return bind_instruction_single(b, store(a, (Store) { .ptr = ptr, .value = ops.nodes[0], .mem = bb_mem(b) })); } case LLVMGetElementPtr: { Nodes ops = convert_operands(p, num_ops, instr); - const Node* ptr = first(ops); + const Node* ptr = shd_first(ops); if (UNTYPED_POINTERS) { const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, singleton(typed_ptr), singleton(ptr)), 1)); + ptr = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } - ops = change_node_at_index(a, ops, 0, ptr); - const Node* r = lea_helper(a, ops.nodes[0], ops.nodes[1], nodes(a, ops.count - 2, &ops.nodes[2])); + ops = shd_change_node_at_index(a, ops, 0, ptr); + const Node* r = lea_helper(a, ops.nodes[0], ops.nodes[1], shd_nodes(a, ops.count - 2, &ops.nodes[2])); if (UNTYPED_POINTERS) { const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); bool idk; //element_t = qualified_type_helper(element_t, false); - enter_composite_indices(&element_t, &idk, nodes(a, ops.count - 2, &ops.nodes[2]), true); + enter_composite_indices(&element_t, &idk, shd_nodes(a, ops.count - 2, &ops.nodes[2]), true); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - r = prim_op_helper(a, reinterpret_op, singleton(untyped_ptr_t), BIND_PREV_R(typed_ptr)); + r = prim_op_helper(a, reinterpret_op, shd_singleton(untyped_ptr_t), BIND_PREV_R(typed_ptr)); } return r; } @@ -290,18 +290,18 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B assert(t->tag == Int_TAG); const Node* zero = int_literal(a, (IntLiteral) { .value = 0, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); const Node* one = int_literal(a, (IntLiteral) { .value = 1, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); - r = prim_op_helper(a, select_op, empty(a), mk_nodes(a, first(ops), one, zero)); + r = prim_op_helper(a, select_op, shd_empty(a), mk_nodes(a, shd_first(ops), one, zero)); } else if (t->tag == Bool_TAG) { assert(src_t->tag == Int_TAG); const Node* one = int_literal(a, (IntLiteral) { .value = 1, .width = src_t->payload.int_type.width, .is_signed = false }); - r = prim_op_helper(a, and_op, empty(a), mk_nodes(a, first(ops), one)); - r = prim_op_helper(a, eq_op, empty(a), mk_nodes(a, first(BIND_PREV_R(int_type(a, (Int) { .width = src_t->payload.int_type.width, .is_signed = false }))), one)); + r = prim_op_helper(a, and_op, shd_empty(a), mk_nodes(a, shd_first(ops), one)); + r = prim_op_helper(a, eq_op, shd_empty(a), mk_nodes(a, shd_first(BIND_PREV_R(int_type(a, (Int) { .width = src_t->payload.int_type.width, .is_signed = false }))), one)); } else { // reinterpret as unsigned, convert to change size, reinterpret back to target T const Type* unsigned_src_t = change_int_t_sign(src_t, false); const Type* unsigned_dst_t = change_int_t_sign(t, false); - r = prim_op_helper(a, convert_op, singleton(unsigned_dst_t), reinterpret_operands(b, ops, unsigned_src_t)); - r = prim_op_helper(a, reinterpret_op, singleton(t), BIND_PREV_R(unsigned_dst_t)); + r = prim_op_helper(a, convert_op, shd_singleton(unsigned_dst_t), reinterpret_operands(b, ops, unsigned_src_t)); + r = prim_op_helper(a, reinterpret_op, shd_singleton(t), BIND_PREV_R(unsigned_dst_t)); } return r; } case LLVMSExt: { @@ -314,19 +314,19 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Node* zero = int_literal(a, (IntLiteral) { .value = 0, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); uint64_t i = UINT64_MAX >> (64 - int_size_in_bytes(t->payload.int_type.width) * 8); const Node* ones = int_literal(a, (IntLiteral) { .value = i, .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed }); - r = prim_op_helper(a, select_op, empty(a), mk_nodes(a, first(ops), ones, zero)); + r = prim_op_helper(a, select_op, shd_empty(a), mk_nodes(a, shd_first(ops), ones, zero)); } else { const Type* signed_src_t = change_int_t_sign(src_t, true); const Type* signed_dst_t = change_int_t_sign(t, true); - r = prim_op_helper(a, convert_op, singleton(signed_dst_t), reinterpret_operands(b, ops, signed_src_t)); - r = prim_op_helper(a, reinterpret_op, singleton(t), singleton(r)); + r = prim_op_helper(a, convert_op, shd_singleton(signed_dst_t), reinterpret_operands(b, ops, signed_src_t)); + r = prim_op_helper(a, reinterpret_op, shd_singleton(t), shd_singleton(r)); } return r; } case LLVMFPToUI: case LLVMFPToSI: case LLVMUIToFP: case LLVMSIToFP: - return prim_op_helper(a, convert_op, singleton(t), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, convert_op, shd_singleton(t), convert_operands(p, num_ops, instr)); case LLVMFPTrunc: goto unimplemented; case LLVMFPExt: @@ -337,7 +337,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B case LLVMAddrSpaceCast: { // when constructing or deconstructing generic pointers, we need to emit a convert_op instead assert(num_ops == 1); - const Node* src = first(convert_operands(p, num_ops, instr)); + const Node* src = shd_first(convert_operands(p, num_ops, instr)); Op op = reinterpret_op; const Type* src_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); if (src_t->tag == PtrType_TAG && t->tag == PtrType_TAG) { @@ -354,7 +354,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B } else { assert(opcode != LLVMAddrSpaceCast); } - return prim_op_helper(a, op, singleton(t), singleton(src)); + return prim_op_helper(a, op, shd_singleton(t), shd_singleton(src)); } case LLVMICmp: { Op op; @@ -402,7 +402,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Type* signed_t = change_int_t_sign(unsigned_t, true); ops = reinterpret_operands(b, ops, signed_t); } - return prim_op_helper(a, op, empty(a), ops); + return prim_op_helper(a, op, shd_empty(a), ops); } case LLVMFCmp: { Op op; @@ -435,7 +435,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B default: goto unimplemented; } Nodes ops = convert_operands(p, num_ops, instr); - return prim_op_helper(a, op, empty(a), ops); + return prim_op_helper(a, op, shd_empty(a), ops); break; } case LLVMPHI: @@ -498,13 +498,13 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B return bind_instruction_single(b, fill_bytes(a, (FillBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = bb_mem(b) })); } else if (shd_string_starts_with(intrinsic, "llvm.fmuladd")) { Nodes ops = convert_operands(p, num_ops, instr); - return prim_op_helper(a, fma_op, empty(a), nodes(a, 3, ops.nodes)); + return prim_op_helper(a, fma_op, shd_empty(a), shd_nodes(a, 3, ops.nodes)); } else if (shd_string_starts_with(intrinsic, "llvm.fabs")) { Nodes ops = convert_operands(p, num_ops, instr); - return prim_op_helper(a, abs_op, empty(a), nodes(a, 1, ops.nodes)); + return prim_op_helper(a, abs_op, shd_empty(a), shd_nodes(a, 1, ops.nodes)); } else if (shd_string_starts_with(intrinsic, "llvm.floor")) { Nodes ops = convert_operands(p, num_ops, instr); - return prim_op_helper(a, floor_op, empty(a), nodes(a, 1, ops.nodes)); + return prim_op_helper(a, floor_op, shd_empty(a), shd_nodes(a, 1, ops.nodes)); } typedef struct { @@ -556,11 +556,11 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B LARRAY(const Node*, processed_ops, ops.count); for (i = 0; i < num_args; i++) { if (decoded[i].is_byval) - processed_ops[i] = first(bind_instruction_outputs_count(b, load(a, (Load) { .ptr = ops.nodes[i], .mem = bb_mem(b) }), 1)); + processed_ops[i] = shd_first(bind_instruction_outputs_count(b, load(a, (Load) { .ptr = ops.nodes[i], .mem = bb_mem(b) }), 1)); else processed_ops[i] = ops.nodes[i]; } - r = prim_op_helper(a, op, empty(a), nodes(a, num_args, processed_ops)); + r = prim_op_helper(a, op, shd_empty(a), shd_nodes(a, num_args, processed_ops)); free(str); goto finish; } else if (strcmp(keyword, "instruction") == 0) { @@ -570,8 +570,8 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B if (ops.count == 0) shd_error("DebugPrintf called without arguments"); size_t whocares; - gen_debug_printf(b, LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), nodes(a, ops.count - 1, &ops.nodes[1])); - return tuple_helper(a, empty(a)); + gen_debug_printf(b, LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), shd_nodes(a, ops.count - 1, &ops.nodes[1])); + return tuple_helper(a, shd_empty(a)); } shd_error_print("Unrecognised shady instruction '%s'\n", instructionname); @@ -591,17 +591,17 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B Nodes ops = convert_operands(p, num_ops, instr); r = bind_instruction_single(b, call(a, (Call) { .mem = bb_mem(b), - .callee = prim_op_helper(a, reinterpret_op, singleton(ptr_type(a, (PtrType) { + .callee = prim_op_helper(a, reinterpret_op, shd_singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = convert_type(p, callee_type) - })), singleton(ops.nodes[num_args])), - .args = nodes(a, num_args, ops.nodes), + })), shd_singleton(ops.nodes[num_args])), + .args = shd_nodes(a, num_args, ops.nodes), })); } return r; } case LLVMSelect: - return prim_op_helper(a, select_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, select_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMUserOp1: goto unimplemented; case LLVMUserOp2: @@ -609,17 +609,17 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B case LLVMVAArg: goto unimplemented; case LLVMExtractElement: - return prim_op_helper(a, extract_dynamic_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, extract_dynamic_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMInsertElement: - return prim_op_helper(a, insert_op, empty(a), convert_operands(p, num_ops, instr)); + return prim_op_helper(a, insert_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMShuffleVector: { Nodes ops = convert_operands(p, num_ops, instr); unsigned num_indices = LLVMGetNumMaskElements(instr); LARRAY(const Node*, cindices, num_indices); for (size_t i = 0; i < num_indices; i++) cindices[i] = uint32_literal(a, LLVMGetMaskValue(instr, i)); - ops = concat_nodes(a, ops, nodes(a, num_indices, cindices)); - return prim_op_helper(a, shuffle_op, empty(a), ops); + ops = shd_concat_nodes(a, ops, shd_nodes(a, num_indices, cindices)); + return prim_op_helper(a, shuffle_op, shd_empty(a), ops); } case LLVMExtractValue: goto unimplemented; diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index afed33741..0f7dde146 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -17,7 +17,7 @@ static Nodes convert_mdnode_operands(Parser* p, LLVMValueRef mdnode) { LARRAY(const Node*, cops, count); for (size_t i = 0; i < count; i++) cops[i] = ops[i] ? convert_value(p, ops[i]) : string_lit_helper(a, "null"); - Nodes args = nodes(a, count, cops); + Nodes args = shd_nodes(a, count, cops); return args; } @@ -27,12 +27,12 @@ static const Node* convert_named_tuple_metadata(Parser* p, LLVMValueRef v, Strin String name = LLVMGetValueName(v); if (!name || strlen(name) == 0) name = unique_name(a, node_name); - Node* g = global_var(p->dst, singleton(annotation(a, (Annotation) { .name = "LLVMMetaData" })), unit_type(a), name, AsDebugInfo); + Node* g = global_var(p->dst, shd_singleton(annotation(a, (Annotation) { .name = "LLVMMetaData" })), unit_type(a), name, AsDebugInfo); const Node* r = ref_decl_helper(a, g); shd_dict_insert(LLVMValueRef, const Type*, p->map, v, r); Nodes args = convert_mdnode_operands(p, v); - args = prepend_nodes(a, args, string_lit_helper(a, node_name)); + args = shd_nodes_prepend(a, args, string_lit_helper(a, node_name)); g->payload.global_variable.init = tuple_helper(a, args); return r; } @@ -103,13 +103,13 @@ LLVM_DI_WITH_PARENT_SCOPES(N) Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { IrArena* a = get_module_arena(p->dst); - Nodes str = empty(a); + Nodes str = shd_empty(a); LLVMMetadataRef scope = LLVMDILocationGetScope(dbgloc); while (true) { if (!scope) break; - str = prepend_nodes(a, str, uint32_literal(a, convert_metadata(p, scope)->id)); + str = shd_nodes_prepend(a, str, uint32_literal(a, convert_metadata(p, scope)->id)); // LLVMDumpValue(LLVMMetadataAsValue(p->ctx, scope)); // printf("\n"); @@ -147,7 +147,7 @@ const Node* convert_metadata(Parser* p, LLVMMetadataRef meta) { case LLVMLocalAsMetadataMetadataKind: { Nodes ops = convert_mdnode_operands(p, v); assert(ops.count == 1); - return first(ops); + return shd_first(ops); } case LLVMDistinctMDOperandPlaceholderMetadataKind: goto default_; diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index f9a03d317..95ed2a8c5 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -35,7 +35,7 @@ static Nodes remake_params(Context* ctx, Nodes old) { nvars[i] = param(a, t, node->payload.param.name); assert(nvars[i]->tag == Param_TAG); } - return nodes(a, old.count, nvars); + return shd_nodes(a, old.count, nvars); } static const Node* process_node(Context* ctx, const Node* node) { @@ -49,8 +49,8 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* new = (Node*) recreate_node_identity(r, node); BodyBuilder* bb = begin_block_pure(a); const Node* value = new->payload.constant.value; - value = prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)); - new->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(value)); + value = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(value)); + new->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(value)); return new; } case Function_TAG: { @@ -73,9 +73,9 @@ static const Node* process_node(Context* ctx, const Node* node) { primop_intrinsic = op; } else if (strcmp(get_annotation_name(an->payload), "EntryPoint") == 0) { for (size_t i = 0; i < new_params.count; i++) - new_params = change_node_at_index(a, new_params, i, param(a, qualified_type_helper(get_unqualified_type(new_params.nodes[i]->payload.param.type), true), new_params.nodes[i]->payload.param.name)); + new_params = shd_change_node_at_index(a, new_params, i, param(a, qualified_type_helper(get_unqualified_type(new_params.nodes[i]->payload.param.type), true), new_params.nodes[i]->payload.param.name)); } - old_annotations = append_nodes(a, old_annotations, an->payload); + old_annotations = shd_nodes_append(a, old_annotations, an->payload); an = an->next; } register_processed_list(r, node->payload.fun.params, new_params); @@ -84,7 +84,7 @@ static const Node* process_node(Context* ctx, const Node* node) { register_processed(&ctx->rewriter, node, decl); if (primop_intrinsic != PRIMOPS_COUNT) { set_abstraction_body(decl, fn_ret(a, (Return) { - .args = singleton(prim_op_helper(a, primop_intrinsic, empty(a), get_abstraction_params(decl))), + .args = shd_singleton(prim_op_helper(a, primop_intrinsic, shd_empty(a), get_abstraction_params(decl))), .mem = get_abstraction_mem(decl), })); } else if (get_abstraction_body(node)) @@ -101,7 +101,7 @@ static const Node* process_node(Context* ctx, const Node* node) { ParsedAnnotation* an = find_annotation(ctx->p, node); AddressSpace old_as = as; while (an) { - annotations = append_nodes(a, annotations, rewrite_node(r, an->payload)); + annotations = shd_nodes_append(a, annotations, rewrite_node(r, an->payload)); if (strcmp(get_annotation_name(an->payload), "Builtin") == 0) old_init = NULL; if (strcmp(get_annotation_name(an->payload), "AddressSpace") == 0) @@ -112,11 +112,11 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* result = decl; if (old_as != as) { const Type* pt = ptr_type(a, (PtrType) { .address_space = old_as, .pointed_type = type }); - Node* c = constant(ctx->rewriter.dst_module, singleton(annotation(a, (Annotation) { + Node* c = constant(ctx->rewriter.dst_module, shd_singleton(annotation(a, (Annotation) { .name = "Inline" })), pt, format_string_interned(a, "%s_proxy", get_declaration_name(decl))); - c->payload.constant.value = prim_op_helper(a, convert_op, singleton(pt), singleton( - ref_decl_helper(a, decl))); + c->payload.constant.value = prim_op_helper(a, convert_op, shd_singleton(pt), shd_singleton( + ref_decl_helper(a, decl))); result = c; } diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index 0b47cb6d8..2476e9782 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -43,8 +43,8 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { else ret_type = qualified_type_helper(ret_type, false); return fn_type(a, (FnType) { - .param_types = nodes(a, num_params, cparam_types), - .return_types = ret_type == empty_multiple_return_type(a) ? empty(a) : singleton(ret_type) + .param_types = shd_nodes(a, num_params, cparam_types), + .return_types = ret_type == empty_multiple_return_type(a) ? shd_empty(a) : shd_singleton(ret_type) }); } case LLVMStructTypeKind: { @@ -52,7 +52,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { Node* decl = NULL; const Node* result = NULL; if (name) { - decl = nominal_type(p->dst, empty(a), name); + decl = nominal_type(p->dst, shd_empty(a), name); result = type_decl_ref_helper(a, decl); shd_dict_insert(LLVMTypeRef, const Type*, p->map, t, result); } @@ -66,7 +66,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { } const Node* product = record_type(a, (RecordType) { - .members = nodes(a, size, celements) + .members = shd_nodes(a, size, celements) }); if (decl) decl->payload.nom_type.body = product; diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index d7f8229bb..d2fa1e149 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -40,7 +40,7 @@ static const Node* data_composite(const Type* t, size_t size, LLVMValueRef v) { default: assert(false); } } - return composite_helper(a, t, nodes(a, size, elements)); + return composite_helper(a, t, shd_nodes(a, size, elements)); } const Node* convert_value(Parser* p, LLVMValueRef v) { @@ -78,7 +78,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { String name = LLVMGetValueName(v); if (!name || strlen(name) == 0) name = unique_name(a, "constant_expr"); - Nodes annotations = singleton(annotation(a, (Annotation) { .name = "Inline" })); + Nodes annotations = shd_singleton(annotation(a, (Annotation) { .name = "Inline" })); assert(t); Node* decl = constant(p->dst, annotations, t, name); r = ref_decl_helper(a, decl); @@ -109,7 +109,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { assert(value); elements[i] = convert_value(p, value); } - return composite_helper(a, t, nodes(a, size, elements)); + return composite_helper(a, t, shd_nodes(a, size, elements)); } case LLVMConstantVectorValueKind: { assert(t->tag == PackType_TAG); @@ -120,7 +120,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { assert(value); elements[i] = convert_value(p, value); } - return composite_helper(a, t, nodes(a, size, elements)); + return composite_helper(a, t, shd_nodes(a, size, elements)); } case LLVMUndefValueValueKind: return undef(a, (Undef) { .type = convert_type(p, LLVMTypeOf(v)) }); @@ -136,7 +136,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { assert(value); elements[i] = convert_value(p, value); } - return composite_helper(a, t, nodes(a, arr_size, elements)); + return composite_helper(a, t, shd_nodes(a, arr_size, elements)); } case LLVMConstantIntValueKind: { if (t->tag == Bool_TAG) { diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 598f06e39..26f4ac10a 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -95,7 +95,7 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { if (strcmp(payload.set, "shady.frontend") == 0) { if (payload.opcode == SlimOpSubscript) { assert(payload.operands.count == 2); - const Node* src_ptr = get_node_address_maybe(ctx, first(payload.operands)); + const Node* src_ptr = get_node_address_maybe(ctx, shd_first(payload.operands)); if (src_ptr == NULL) return NULL; const Node* index = rewrite_node(&ctx->rewriter, payload.operands.nodes[1]); @@ -107,12 +107,12 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { assert(payload.operands.count == 1); return mem_and_value(a, (MemAndValue) { .mem = rewrite_node(r, payload.mem), - .value = rewrite_node(&ctx->rewriter, first(payload.operands)), + .value = rewrite_node(&ctx->rewriter, shd_first(payload.operands)), }); } else if (payload.opcode == SlimOpUnbound) { if (payload.mem) rewrite_node(&ctx->rewriter, payload.mem); - Resolved entry = resolve_using_name(ctx, get_string_literal(a, first(payload.operands))); + Resolved entry = resolve_using_name(ctx, get_string_literal(a, shd_first(payload.operands))); // can't take the address if it's not a var! if (!entry.is_var) return NULL; @@ -141,7 +141,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { case SlimOpBindVal: { size_t names_count = instr.operands.count - 1; const Node** names = &instr.operands.nodes[1]; - const Node* value = rewrite_node(r, first(instr.operands)); + const Node* value = rewrite_node(r, shd_first(instr.operands)); Nodes results = deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = get_string_literal(a, names[i]); @@ -154,7 +154,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { size_t names_count = (instr.operands.count - 1) / 2; const Node** names = &instr.operands.nodes[1]; const Node** types = &instr.operands.nodes[1 + names_count]; - const Node* value = rewrite_node(r, first(instr.operands)); + const Node* value = rewrite_node(r, shd_first(instr.operands)); Nodes results = deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = get_string_literal(a, names[i]); @@ -198,7 +198,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { } } - return yield_values_and_wrap_in_block(bb, empty(a)); + return yield_values_and_wrap_in_block(bb, shd_empty(a)); } static const Node* rewrite_decl(Context* ctx, const Node* decl) { @@ -313,7 +313,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { if (!is_used_as_value(ctx, node)) return rewrite_node(r, payload.mem); return load(a, (Load) { - .ptr = rewrite_node(r, first(payload.operands)), + .ptr = rewrite_node(r, shd_first(payload.operands)), .mem = rewrite_node(r, payload.mem), }); case SlimOpAssign: { @@ -348,7 +348,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { return rewrite_node(r, payload.mem); mem = rewrite_node(r, payload.mem); } - Resolved entry = resolve_using_name(ctx, get_string_literal(a, first(payload.operands))); + Resolved entry = resolve_using_name(ctx, get_string_literal(a, shd_first(payload.operands))); if (entry.is_var) { return load(a, (Load) { .ptr = entry.node, .mem = mem }); } else if (mem) { diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index f1df0e79b..1febd6f82 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -22,7 +22,7 @@ static Nodes annotate_all_types(IrArena* a, Nodes types, bool uniform_by_default else ntypes[i] = types.nodes[i]; } - return nodes(a, types.count, ntypes); + return shd_nodes(a, types.count, ntypes); } typedef struct { @@ -102,7 +102,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { } Nodes nret_types = annotate_all_types(a, infer_nodes(ctx, node->payload.fun.return_types), false); - Node* fun = function(ctx->rewriter.dst_module, nodes(a, node->payload.fun.params.count, nparams), string(a, node->payload.fun.name), infer_nodes(ctx, node->payload.fun.annotations), nret_types); + Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, node->payload.fun.params.count, nparams), string(a, node->payload.fun.name), infer_nodes(ctx, node->payload.fun.annotations), nret_types); register_processed(&ctx->rewriter, node, fun); body_context.current_fn = fun; set_abstraction_body(fun, infer(&body_context, node->payload.fun.body, NULL)); @@ -253,7 +253,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec for (size_t i = 0; i < omembers.count; i++) inferred[i] = infer(ctx, omembers.nodes[i], NULL); } - Nodes nmembers = nodes(a, omembers.count, inferred); + Nodes nmembers = shd_nodes(a, omembers.count, inferred); // Composites are tuples by default if (!elem_type) @@ -306,7 +306,7 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg } } - Node* new_case = basic_block(a, nodes(a, inferred_arg_type.count, nparams), get_abstraction_name_unsafe(node)); + Node* new_case = basic_block(a, shd_nodes(a, inferred_arg_type.count, nparams), get_abstraction_name_unsafe(node)); register_processed(r, node, new_case); set_abstraction_body(new_case, infer(&body_context, node->payload.basic_block.body, NULL)); return new_case; @@ -328,7 +328,7 @@ static const Node* _infer_basic_block(Context* ctx, const Node* node) { register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); } - Node* bb = basic_block(a, nodes(a, node->payload.basic_block.params.count, nparams), node->payload.basic_block.name); + Node* bb = basic_block(a, shd_nodes(a, node->payload.basic_block.params.count, nparams), node->payload.basic_block.name); assert(bb); register_processed(&ctx->rewriter, node, bb); @@ -352,14 +352,14 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe BodyBuilder* bb = begin_block_pure(a); Op op = node->payload.prim_op.op; LARRAY(const Node*, new_operands, old_operands.count); - Nodes input_types = empty(a); + Nodes input_types = shd_empty(a); switch (node->payload.prim_op.op) { case reinterpret_op: case convert_op: { new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); const Type* src_pointer_type = get_unqualified_type(new_operands[0]->type); - const Type* old_dst_pointer_type = first(old_type_args); - const Type* dst_pointer_type = first(type_args); + const Type* old_dst_pointer_type = shd_first(old_type_args); + const Type* dst_pointer_type = shd_first(type_args); if (is_generic_ptr_type(src_pointer_type) != is_generic_ptr_type(dst_pointer_type)) op = convert_op; @@ -387,7 +387,7 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe const Node* new_instruction = prim_op(a, (PrimOp) { .op = op, .type_arguments = type_args, - .operands = nodes(a, old_operands.count, new_operands) + .operands = shd_nodes(a, old_operands.count, new_operands) }); return bind_last_instruction_and_wrap_in_block(bb, new_instruction); } @@ -419,7 +419,7 @@ static const Node* infer_indirect_call(Context* ctx, const Node* node, const Nod return call(a, (Call) { .callee = new_callee, - .args = nodes(a, node->payload.call.args.count, new_args), + .args = shd_nodes(a, node->payload.call.args.count, new_args), .mem = infer(ctx, node->payload.if_instr.mem, NULL), }); } @@ -434,10 +434,10 @@ static const Node* infer_if(Context* ctx, const Node* node) { // When we infer the types of the arguments to a call to merge(), they are expected to be varying Nodes expected_join_types = add_qualifiers(a, join_types, false); - const Node* true_body = infer_case(&infer_if_body_ctx, node->payload.if_instr.if_true, nodes(a, 0, NULL)); + const Node* true_body = infer_case(&infer_if_body_ctx, node->payload.if_instr.if_true, shd_nodes(a, 0, NULL)); // don't allow seeing the variables made available in the true branch infer_if_body_ctx.rewriter = ctx->rewriter; - const Node* false_body = node->payload.if_instr.if_false ? infer_case(&infer_if_body_ctx, node->payload.if_instr.if_false, nodes(a, 0, NULL)) : NULL; + const Node* false_body = node->payload.if_instr.if_false ? infer_case(&infer_if_body_ctx, node->payload.if_instr.if_false, shd_nodes(a, 0, NULL)) : NULL; return if_instr(a, (If) { .yield_types = join_types, @@ -474,7 +474,7 @@ static const Node* infer_loop(Context* ctx, const Node* node) { return loop_instr(a, (Loop) { .yield_types = loop_yield_types, - .initial_args = nodes(a, old_params.count, new_initial_args), + .initial_args = shd_nodes(a, old_params.count, new_initial_args), .body = nbody, //.tail = infer_case(ctx, node->payload.loop_instr.tail, qual_yield_types) .tail = infer(ctx, node->payload.loop_instr.tail, NULL), @@ -489,7 +489,7 @@ static const Node* infer_control(Context* ctx, const Node* node) { Nodes yield_types = infer_nodes(ctx, node->payload.control.yield_types); const Node* olam = node->payload.control.inside; - const Node* ojp = first(get_abstraction_params(olam)); + const Node* ojp = shd_first(get_abstraction_params(olam)); Context joinable_ctx = *ctx; const Type* jpt = join_point_type(a, (JoinPointType) { @@ -499,7 +499,7 @@ static const Node* infer_control(Context* ctx, const Node* node) { const Node* jp = param(a, jpt, ojp->payload.param.name); register_processed(&joinable_ctx.rewriter, ojp, jp); - Node* new_case = basic_block(a, singleton(jp), NULL); + Node* new_case = basic_block(a, shd_singleton(jp), NULL); register_processed(&joinable_ctx.rewriter, olam, new_case); set_abstraction_body(new_case, infer(&joinable_ctx, get_abstraction_body(olam), NULL)); @@ -559,7 +559,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { for (size_t i = 0; i < payload.args.count; i++) nvalues[i] = infer(ctx, payload.args.nodes[i], return_types.nodes[i]); return fn_ret(a, (Return) { - .args = nodes(a, payload.args.count, nvalues), + .args = shd_nodes(a, payload.args.count, nvalues), .mem = infer(ctx, payload.mem, NULL), }); } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 5887f822c..56a890686 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -232,12 +232,12 @@ static const Node* accept_numerical_literal(ctxparams) { } static Nodes accept_type_arguments(ctxparams) { - Nodes ty_args = empty(arena); + Nodes ty_args = shd_empty(arena); if (accept_token(ctx, lsbracket_tok)) { while (true) { const Type* t = accept_unqualified_type(ctx); expect(t, "unqualified type"); - ty_args = append_nodes(arena, ty_args, t); + ty_args = shd_nodes_append(arena, ty_args, t); if (accept_token(ctx, comma_tok)) continue; if (accept_token(ctx, rsbracket_tok)) @@ -253,7 +253,7 @@ static const Node* make_unbound(IrArena* a, const Node* mem, String identifier) .set = "shady.frontend", .opcode = SlimOpUnbound, .result_t = unit_type(a), - .operands = singleton(string_lit_helper(a, identifier)), + .operands = shd_singleton(string_lit_helper(a, identifier)), }); } @@ -306,7 +306,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { .operands = ops, })); } else if (strcmp(id, "alloca") == 0) { - const Node* type = first(accept_type_arguments(ctx)); + const Node* type = shd_first(accept_type_arguments(ctx)); Nodes ops = expect_operands(ctx, bb); expect(ops.count == 0, "no operands"); return bind_instruction_single(bb, stack_alloc(arena, (StackAlloc) { @@ -316,8 +316,8 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { } else if (strcmp(id, "debug_printf") == 0) { Nodes ops = expect_operands(ctx, bb); return bind_instruction_single(bb, debug_printf(arena, (DebugPrintf) { - .string = get_string_literal(arena, first(ops)), - .args = nodes(arena, ops.count - 1, &ops.nodes[1]), + .string = get_string_literal(arena, shd_first(ops)), + .args = shd_nodes(arena, ops.count - 1, &ops.nodes[1]), .mem = bb_mem(bb), })); } @@ -346,7 +346,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { case lpar_tok: { next_token(tokenizer); if (accept_token(ctx, rpar_tok)) { - return tuple_helper(arena, empty(arena)); + return tuple_helper(arena, shd_empty(arena)); } const Node* atom = expect_operand(ctx, bb); if (curr_token(tokenizer).tag == rpar_tok) { @@ -361,7 +361,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { shd_list_append(const Node*, elements, element); } - Nodes tcontents = nodes(arena, shd_list_count(elements), shd_read_list(const Node*, elements)); + Nodes tcontents = shd_nodes(arena, shd_list_count(elements), shd_read_list(const Node*, elements)); shd_destroy_list(elements); atom = tuple_helper(arena, tcontents); } @@ -461,8 +461,8 @@ static const Type* accept_unqualified_type(ctxparams) { shd_list_append(const Type*, types, elem); expect(accept_token(ctx, semi_tok), "';'"); } - Nodes elem_types = nodes(arena, shd_list_count(types), shd_read_list(const Type*, types)); - Strings names2 = strings(arena, shd_list_count(names), shd_read_list(String, names)); + Nodes elem_types = shd_nodes(arena, shd_list_count(types), shd_read_list(const Type*, types)); + Strings names2 = shd_strings(arena, shd_list_count(names), shd_read_list(String, names)); shd_destroy_list(names); shd_destroy_list(types); return record_type(arena, (RecordType) { @@ -548,10 +548,10 @@ static void expect_parameters(ctxparams, Nodes* parameters, Nodes* default_value } size_t count = shd_list_count(params); - *parameters = nodes(arena, count, shd_read_list(const Node*, params)); + *parameters = shd_nodes(arena, count, shd_read_list(const Node*, params)); shd_destroy_list(params); if (default_values) { - *default_values = nodes(arena, count, shd_read_list(const Node*, default_vals)); + *default_values = shd_nodes(arena, count, shd_read_list(const Node*, default_vals)); shd_destroy_list(default_vals); } } @@ -576,7 +576,7 @@ static Nodes accept_types(ctxparams, TokenTag separator, Qualified qualified) { accept_token(ctx, separator); } - Nodes types2 = nodes(arena, tmp->elements_count, (const Type**) tmp->alloc); + Nodes types2 = shd_nodes(arena, tmp->elements_count, (const Type**) tmp->alloc); shd_destroy_list(tmp); return types2; } @@ -594,7 +594,7 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { } else { return bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = neg_op, - .operands = nodes(arena, 1, (const Node* []) {expr}) + .operands = shd_nodes(arena, 1, (const Node* []) {expr}) })); } } else if (accept_token(ctx, unary_excl_tok)) { @@ -602,12 +602,12 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { expect(expr, "expression"); return bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = not_op, - .operands = singleton(expr), + .operands = shd_singleton(expr), })); } else if (accept_token(ctx, star_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr, "expression"); - return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpDereference, .operands = singleton(expr), .mem = bb_mem(bb) })); + return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpDereference, .operands = shd_singleton(expr), .mem = bb_mem(bb) })); } else if (accept_token(ctx, infix_and_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr, "expression"); @@ -615,7 +615,7 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpAddrOf, - .operands = singleton(expr), + .operands = shd_singleton(expr), .mem = bb_mem(bb), })); } @@ -639,7 +639,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) if (is_primop_op(infix, &primop_op)) { expr = bind_instruction_single(bb, prim_op(arena, (PrimOp) { .op = primop_op, - .operands = nodes(arena, 2, (const Node* []) {expr, rhs}) + .operands = shd_nodes(arena, 2, (const Node* []) {expr, rhs}) })); } else switch (infix) { case InfixAss: { @@ -647,7 +647,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) .set = "shady.frontend", .opcode = SlimOpAssign, .result_t = unit_type(arena), - .operands = nodes(arena, 2, (const Node* []) {expr, rhs}), + .operands = shd_nodes(arena, 2, (const Node* []) {expr, rhs}), .mem = bb_mem(bb), })); break; @@ -657,7 +657,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) .set = "shady.frontend", .opcode = SlimOpSubscript, .result_t = unit_type(arena), - .operands = nodes(arena, 2, (const Node* []) {expr, rhs}), + .operands = shd_nodes(arena, 2, (const Node* []) {expr, rhs}), .mem = bb_mem(bb), })); break; @@ -713,19 +713,19 @@ static Nodes expect_operands(ctxparams, BodyBuilder* bb) { syntax_error("Expected ',' or ')'"); } - Nodes final = nodes(arena, list->elements_count, (const Node**) list->alloc); + Nodes final = shd_nodes(arena, list->elements_count, (const Node**) list->alloc); shd_destroy_list(list); return final; } static const Node* make_selection_merge(const Node* mem) { IrArena* a = mem->arena; - return merge_selection(a, (MergeSelection) { .args = nodes(a, 0, NULL), .mem = mem }); + return merge_selection(a, (MergeSelection) { .args = shd_nodes(a, 0, NULL), .mem = mem }); } static const Node* make_loop_continue(const Node* mem) { IrArena* a = mem->arena; - return merge_continue(a, (MergeContinue) { .args = nodes(a, 0, NULL), .mem = mem }); + return merge_continue(a, (MergeContinue) { .args = shd_nodes(a, 0, NULL), .mem = mem }); } static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { @@ -740,14 +740,14 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { expect(accept_token(ctx, rpar_tok), "')'"); const Node* (*merge)(const Node*) = config.front_end ? make_selection_merge : NULL; - Node* true_case = case_(arena, nodes(arena, 0, NULL)); + Node* true_case = case_(arena, shd_nodes(arena, 0, NULL)); set_abstraction_body(true_case, expect_body(ctx, get_abstraction_mem(true_case), merge)); // else defaults to an empty body bool has_else = accept_token(ctx, else_tok); Node* false_case = NULL; if (has_else) { - false_case = case_(arena, nodes(arena, 0, NULL)); + false_case = case_(arena, shd_nodes(arena, 0, NULL)); set_abstraction_body(false_case, expect_body(ctx, get_abstraction_mem(false_case), merge)); } return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, true_case, false_case)); @@ -774,7 +774,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { .yield_types = yield_types, }), str); expect(accept_token(ctx, rpar_tok), "')'"); - Node* control_case = case_(arena, singleton(jp)); + Node* control_case = case_(arena, shd_singleton(jp)); set_abstraction_body(control_case, expect_body(ctx, get_abstraction_mem(control_case), NULL)); return maybe_tuple_helper(arena, gen_control(bb, yield_types, control_case)); } @@ -807,7 +807,7 @@ static void expect_identifiers(ctxparams, Strings* out_strings) { break; } - *out_strings = strings(arena, list->elements_count, (const char**) list->alloc); + *out_strings = shd_strings(arena, list->elements_count, (const char**) list->alloc); shd_destroy_list(list); } @@ -830,8 +830,8 @@ static void expect_types_and_identifiers(ctxparams, Strings* out_strings, Nodes* break; } - *out_strings = strings(arena, slist->elements_count, (const char**) slist->alloc); - *out_types = nodes(arena, tlist->elements_count, (const Node**) tlist->alloc); + *out_strings = shd_strings(arena, slist->elements_count, (const char**) slist->alloc); + *out_types = shd_nodes(arena, tlist->elements_count, (const Node**) tlist->alloc); shd_destroy_list(slist); shd_destroy_list(tlist); } @@ -840,7 +840,7 @@ static Nodes strings2nodes(IrArena* a, Strings strings) { LARRAY(const Node*, arr, strings.count); for (size_t i = 0; i < strings.count; i++) arr[i] = string_lit_helper(a, strings.strings[i]); - return nodes(a, strings.count, arr); + return shd_nodes(a, strings.count, arr); } static bool accept_statement(ctxparams, BodyBuilder* bb) { @@ -849,13 +849,13 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); - gen_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(bb->arena), prepend_nodes(bb->arena, strings2nodes(bb->arena, ids), instruction)); + gen_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(bb->arena), shd_nodes_prepend(bb->arena, strings2nodes(bb->arena, ids), instruction)); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); - gen_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(bb->arena), prepend_nodes(bb->arena, concat_nodes(bb->arena, strings2nodes(bb->arena, ids), types), instruction)); + gen_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(bb->arena), shd_nodes_prepend(bb->arena, shd_concat_nodes(bb->arena, strings2nodes(bb->arena, ids), types), instruction)); } else { const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; @@ -910,8 +910,8 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { const Node* inspectee = accept_value(ctx, bb); expect(inspectee, "value"); expect(accept_token(ctx, comma_tok), "','"); - Nodes values = empty(arena); - Nodes cases = empty(arena); + Nodes values = shd_empty(arena); + Nodes cases = shd_empty(arena); const Node* default_jump; while (true) { if (accept_token(ctx, default_tok)) { @@ -924,13 +924,13 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { expect(accept_token(ctx, comma_tok), "','"); const Node* j = expect_jump(ctx, bb); expect(accept_token(ctx, comma_tok), "','"); - values = append_nodes(arena, values, value); - cases = append_nodes(arena, cases, j); + values = shd_nodes_append(arena, values, value); + cases = shd_nodes_append(arena, cases, j); } expect(accept_token(ctx, rpar_tok), "')'"); return br_switch(arena, (Switch) { - .switch_value = first(values), + .switch_value = shd_first(values), .case_values = values, .case_jumps = cases, .default_jump = default_jump, @@ -947,7 +947,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { } case merge_selection_tok: { next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); + Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_selection(arena, (MergeSelection) { .args = args, .mem = bb_mem(bb) @@ -955,7 +955,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { } case continue_tok: { next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); + Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_continue(arena, (MergeContinue) { .args = args, .mem = bb_mem(bb) @@ -963,7 +963,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { } case break_tok: { next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : nodes(arena, 0, NULL); + Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_break(arena, (MergeBreak) { .args = args, .mem = bb_mem(bb) @@ -1001,7 +1001,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t break; } - Node* terminator_case = case_(arena, empty(arena)); + Node* terminator_case = case_(arena, shd_empty(arena)); BodyBuilder* terminator_bb = begin_body_with_mem(arena, get_abstraction_mem(terminator_case)); const Node* terminator = accept_terminator(ctx, terminator_bb); @@ -1017,11 +1017,11 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t set_abstraction_body(terminator_case, finish_body(terminator_bb, terminator)); - Node* cont_wrapper_case = case_(arena, empty(arena)); + Node* cont_wrapper_case = case_(arena, shd_empty(arena)); BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(cont_wrapper_case)); - Nodes ids = empty(arena); - Nodes conts = empty(arena); + Nodes ids = shd_empty(arena); + Nodes conts = shd_empty(arena); if (curr_token(tokenizer).tag == cont_tok) { while (true) { if (!accept_token(ctx, cont_tok)) @@ -1032,16 +1032,16 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t expect_parameters(ctx, ¶meters, NULL, bb); Node* continuation = basic_block(arena, parameters, name); set_abstraction_body(continuation, expect_body(ctx, get_abstraction_mem(continuation), NULL)); - ids = append_nodes(arena, ids, string_lit_helper(arena, name)); - conts = append_nodes(arena, conts, continuation); + ids = shd_nodes_append(arena, ids, string_lit_helper(arena, name)); + conts = shd_nodes_append(arena, conts, continuation); } } - gen_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), concat_nodes(arena, ids, conts)); + gen_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), shd_concat_nodes(arena, ids, conts)); expect(accept_token(ctx, rbracket_tok), "']'"); - set_abstraction_body(cont_wrapper_case, finish_body_with_jump(cont_wrapper_bb, terminator_case, empty(arena))); - return finish_body_with_jump(bb, cont_wrapper_case, empty(arena)); + set_abstraction_body(cont_wrapper_case, finish_body_with_jump(cont_wrapper_bb, terminator_case, shd_empty(arena))); + return finish_body_with_jump(bb, cont_wrapper_case, shd_empty(arena)); } static Nodes accept_annotations(ctxparams) { @@ -1073,7 +1073,7 @@ static Nodes accept_annotations(ctxparams) { } annot = annotation_values(arena, (AnnotationValues) { .name = id, - .values = nodes(arena, shd_list_count(values), shd_read_list(const Node*, values)) + .values = shd_nodes(arena, shd_list_count(values), shd_read_list(const Node*, values)) }); shd_destroy_list(values); } else { @@ -1097,7 +1097,7 @@ static Nodes accept_annotations(ctxparams) { break; } - Nodes annotations = nodes(arena, shd_list_count(list), shd_read_list(const Node*, list)); + Nodes annotations = shd_nodes(arena, shd_list_count(list), shd_read_list(const Node*, list)); shd_destroy_list(list); return annotations; } @@ -1117,13 +1117,13 @@ static const Node* accept_const(ctxparams, Nodes annotations) { expect(accept_token(ctx, semi_tok), "';'"); Node* cnst = constant(mod, annotations, type, id); - cnst->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(definition)); + cnst->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(definition)); return cnst; } static const Node* make_return_void(const Node* mem) { IrArena* a = mem->arena; - return fn_ret(a, (Return) { .args = empty(a), .mem = mem }); + return fn_ret(a, (Return) { .args = shd_empty(a), .mem = mem }); } static const Node* accept_fn_decl(ctxparams, Nodes annotations) { @@ -1183,7 +1183,7 @@ static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { } if (logical) { - annotations = append_nodes(arena, annotations, annotation(arena, (Annotation) { + annotations = shd_nodes_append(arena, annotations, annotation(arena, (Annotation) { .name = "Logical" })); } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 77b0972b5..93d2c5598 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -396,7 +396,7 @@ Nodes get_args_from_phi(SpvParser* parser, SpvId block, SpvId predecessor) { params[i] = NULL; if (params_count == 0) - return empty(parser->arena); + return shd_empty(parser->arena); SpvPhiArgs** found = shd_dict_find_value(SpvId, SpvPhiArgs*, parser->phi_arguments, block); assert(found); @@ -415,7 +415,7 @@ Nodes get_args_from_phi(SpvParser* parser, SpvId block, SpvId predecessor) { for (size_t i = 0; i < params_count; i++) assert(params[i]); - return nodes(parser->arena, params_count, params); + return shd_nodes(parser->arena, params_count, params); } size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { @@ -460,12 +460,12 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { int results_count = has_result ? 1 : 0; Nodes results = bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = shd_op.op, - .type_arguments = empty(parser->arena), - .operands = nodes(parser->arena, num_ops, ops) + .type_arguments = shd_empty(parser->arena), + .operands = shd_nodes(parser->arena, num_ops, ops) }), results_count); if (has_result) { parser->defs[result].type = Value; - parser->defs[result].node = first(results); + parser->defs[result].node = shd_first(results); } return size; } @@ -619,8 +619,8 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < size - 3; i++) param_ts[i] = get_def_type(parser, instruction[3 + i]); parser->defs[result].node = fn_type(parser->arena, (FnType) { - .return_types = (return_t == unit_type(parser->arena)) ? empty(parser->arena) : singleton(return_t), - .param_types = nodes(parser->arena, size - 3, param_ts) + .return_types = (return_t == unit_type(parser->arena)) ? shd_empty(parser->arena) : shd_singleton(return_t), + .param_types = shd_nodes(parser->arena, size - 3, param_ts) }); break; } @@ -628,7 +628,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].type = Typ; String name = get_name(parser, result); name = name ? name : unique_name(parser->arena, "struct_type"); - Node* nominal_type_decl = nominal_type(parser->mod, empty(parser->arena), name); + Node* nominal_type_decl = nominal_type(parser->mod, shd_empty(parser->arena), name); const Node* nom_t_ref = type_decl_ref(parser->arena, (TypeDeclRef) { .decl = nominal_type_decl }); @@ -643,8 +643,8 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { member_tys[i] = get_def_type(parser, instruction[2 + i]); } nominal_type_decl->payload.nom_type.body = record_type(parser->arena, (RecordType) { - .members = nodes(parser->arena, members_count, member_tys), - .names = strings(parser->arena, members_count, member_names), + .members = shd_nodes(parser->arena, members_count, member_tys), + .names = shd_strings(parser->arena, members_count, member_names), }); break; } @@ -728,7 +728,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { LARRAY(const Node*, contents, size - 3); for (size_t i = 0; i < size - 3; i++) contents[i] = get_def_ssa_value(parser, instruction[3 + i]); - parser->defs[result].node = composite_helper(parser->arena, t, nodes(parser->arena, size - 3, contents)); + parser->defs[result].node = composite_helper(parser->arena, t, shd_nodes(parser->arena, size - 3, contents)); break; } case SpvOpVariable: { @@ -742,7 +742,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { assert(is_data_type(contents_t)); if (parser->fun) { - const Node* ptr = first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { .type = contents_t, .mem = bb_mem(parser->current_block.builder) }), 1)); + const Node* ptr = shd_first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { .type = contents_t, .mem = bb_mem(parser->current_block.builder) }), 1)); parser->defs[result].type = Value; parser->defs[result].node = ptr; @@ -750,12 +750,12 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { if (size == 5) bind_instruction_outputs_count(parser->current_block.builder, store(parser->arena, (Store) { .ptr = ptr, .value = get_def_ssa_value(parser, instruction[4]), .mem = bb_mem(parser->current_block.builder) }), 1); } else { - Nodes annotations = empty(parser->arena); + Nodes annotations = shd_empty(parser->arena); SpvDeco* builtin = find_decoration(parser, result, -1, SpvDecorationBuiltIn); if (builtin) { Builtin b = get_builtin_by_spv_id(*builtin->payload.literals.data); assert(b != BuiltinsCount && "Unsupported builtin"); - annotations = append_nodes(parser->arena, annotations, annotation_value_helper(parser->arena, "Builtin", string_lit_helper(parser->arena, get_builtin_name(b)))); + annotations = shd_nodes_append(parser->arena, annotations, annotation_value_helper(parser->arena, "Builtin", string_lit_helper(parser->arena, get_builtin_name(b)))); } parser->defs[result].type = Decl; @@ -779,12 +779,12 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { else name = unique_name(parser->arena, name); - Nodes annotations = empty(parser->arena); - annotations = append_nodes(parser->arena, annotations, annotation(parser->arena, (Annotation) { .name = "Restructure" })); + Nodes annotations = shd_empty(parser->arena); + annotations = shd_nodes_append(parser->arena, annotations, annotation(parser->arena, (Annotation) { .name = "Restructure" })); SpvDeco* entry_point_type = find_decoration(parser, result, -1, ShdDecorationEntryPointType); parser->is_entry_pt = entry_point_type; if (entry_point_type) { - annotations = append_nodes(parser->arena, annotations, annotation_value(parser->arena, (AnnotationValue) { + annotations = shd_nodes_append(parser->arena, annotations, annotation_value(parser->arena, (AnnotationValue) { .name = "EntryPoint", .value = string_lit(parser->arena, (StringLiteral) { .string = entry_point_type->payload.str }) })); @@ -796,12 +796,12 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { if (strcmp(entry_point_type->payload.str, "Compute") == 0) { SpvDeco* wg_size_dec = find_decoration(parser, result, -2, SpvExecutionModeLocalSize); assert(wg_size_dec && wg_size_dec->payload.literals.count == 3 && "we require kernels decorated with a workgroup size"); - annotations = append_nodes(parser->arena, annotations, annotation_values(parser->arena, (AnnotationValues) { - .name = "WorkgroupSize", - .values = mk_nodes(parser->arena, - int32_literal(parser->arena, wg_size_dec->payload.literals.data[0]), - int32_literal(parser->arena, wg_size_dec->payload.literals.data[1]), - int32_literal(parser->arena, wg_size_dec->payload.literals.data[2])) + annotations = shd_nodes_append(parser->arena, annotations, annotation_values(parser->arena, (AnnotationValues) { + .name = "WorkgroupSize", + .values = mk_nodes(parser->arena, + int32_literal(parser->arena, wg_size_dec->payload.literals.data[0]), + int32_literal(parser->arena, wg_size_dec->payload.literals.data[1]), + int32_literal(parser->arena, wg_size_dec->payload.literals.data[2])) })); } else if (strcmp(entry_point_type->payload.str, "Fragment") == 0) { @@ -823,7 +823,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { instruction_offset += s; } - Node* fun = function(parser->mod, nodes(parser->arena, params_count, params), name, annotations, t->payload.fn_type.return_types); + Node* fun = function(parser->mod, shd_nodes(parser->arena, params_count, params), name, annotations, t->payload.fn_type.return_types); parser->defs[result].node = fun; Node* old_fun = parser->fun; parser->fun = fun; @@ -864,7 +864,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { struct CurrBlock old = parser->current_block; parser->current_block.id = result; - Nodes params = empty(parser->arena); + Nodes params = shd_empty(parser->arena); parser->fun_arg_i = 0; while (true) { SpvOp param_op = (parser->words + instruction_offset)[0] & 0xFFFF; @@ -884,7 +884,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { if (is_param) { const Node* param = get_definition_by_id(parser, get_result_defined_at(parser, instruction_offset))->node; assert(param && param->tag == Param_TAG); - params = concat_nodes(parser->arena, params, singleton(param)); + params = shd_concat_nodes(parser->arena, params, shd_singleton(param)); } size += s; instruction_offset += s; @@ -963,10 +963,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { const Type* src = get_def_ssa_value(parser, instruction[3]); const Type* dst_t = get_def_type(parser, result_t); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = convert_op, - .type_arguments = singleton(dst_t), - .operands = singleton(src) + parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + .op = convert_op, + .type_arguments = shd_singleton(dst_t), + .operands = shd_singleton(src) }), 1)); break; } @@ -976,10 +976,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { const Type* src = get_def_ssa_value(parser, instruction[3]); const Type* dst_t = get_def_type(parser, result_t); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = reinterpret_op, - .type_arguments = singleton(dst_t), - .operands = singleton(src) + parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + .op = reinterpret_op, + .type_arguments = shd_singleton(dst_t), + .operands = shd_singleton(src) }), 1)); break; } @@ -1000,7 +1000,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < num_indices; i++) indices[i] = get_def_ssa_value(parser, instruction[indices_start + i]); parser->defs[result].type = Value; - parser->defs[result].node = lea_helper(a, ptr, offset, nodes(a, num_indices, indices)); + parser->defs[result].node = lea_helper(a, ptr, offset, shd_nodes(a, num_indices, indices)); break; } case SpvOpCompositeExtract: { @@ -1010,10 +1010,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < num_indices; i++) ops[1 + i] = int32_literal(parser->arena, instruction[4 + i]); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = extract_op, - .type_arguments = empty(parser->arena), - .operands = nodes(parser->arena, 1 + num_indices, ops) + parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + .op = extract_op, + .type_arguments = shd_empty(parser->arena), + .operands = shd_nodes(parser->arena, 1 + num_indices, ops) }), 1)); break; } @@ -1025,10 +1025,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < num_indices; i++) ops[2 + i] = int32_literal(parser->arena, instruction[5 + i]); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { - .op = insert_op, - .type_arguments = empty(parser->arena), - .operands = nodes(parser->arena, 2 + num_indices, ops) + parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + .op = insert_op, + .type_arguments = shd_empty(parser->arena), + .operands = shd_nodes(parser->arena, 2 + num_indices, ops) }), 1)); break; } @@ -1050,9 +1050,9 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { index -= num_components_a; src = src_b; } - components[i] = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + components[i] = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = extract_op, - .type_arguments = empty(parser->arena), + .type_arguments = shd_empty(parser->arena), .operands = mk_nodes(parser->arena, src, int32_literal(parser->arena, index)) }), 1)); } @@ -1061,13 +1061,13 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].node = composite_helper(parser->arena, pack_type(parser->arena, (PackType) { .element_type = src_a_t->payload.pack_type.element_type, .width = num_components, - }), nodes(parser->arena, num_components, components)); + }), shd_nodes(parser->arena, num_components, components)); break; } case SpvOpLoad: { const Type* src = get_def_ssa_value(parser, instruction[3]); parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, load(a, (Load) { .ptr = src, .mem = bb_mem(parser->current_block.builder) }), 1)); + parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, load(a, (Load) { .ptr = src, .mem = bb_mem(parser->current_block.builder) }), 1)); break; } case SpvOpStore: { @@ -1085,10 +1085,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { const Type* elem_t = src->type; deconstruct_qualified_type(&elem_t); deconstruct_pointer_type(&elem_t); - cnt = first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + cnt = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = size_of_op, - .type_arguments = singleton(elem_t), - .operands = empty(parser->arena) + .type_arguments = shd_singleton(elem_t), + .operands = shd_empty(parser->arena) }), 1)); } else { cnt = get_def_ssa_value(parser, instruction[3]); @@ -1137,23 +1137,23 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { //assert(false && intrinsic); Nodes rslts = bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = op, - .type_arguments = empty(parser->arena), - .operands = nodes(parser->arena, num_args, args) + .type_arguments = shd_empty(parser->arena), + .operands = shd_nodes(parser->arena, num_args, args) }), rslts_count); if (rslts_count == 1) - parser->defs[result].node = first(rslts); + parser->defs[result].node = shd_first(rslts); break; } } Nodes rslts = bind_instruction_outputs_count(parser->current_block.builder, call(parser->arena, (Call) { .callee = fn_addr_helper(parser->arena, callee), - .args = nodes(parser->arena, num_args, args) + .args = shd_nodes(parser->arena, num_args, args) }), rslts_count); if (rslts_count == 1) - parser->defs[result].node = first(rslts); + parser->defs[result].node = shd_first(rslts); break; } @@ -1183,31 +1183,31 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case OpenCLstd_Floor: instr = prim_op(parser->arena, (PrimOp) { .op = floor_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case OpenCLstd_Sqrt: instr = prim_op(parser->arena, (PrimOp) { .op = sqrt_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case OpenCLstd_Fabs: instr = prim_op(parser->arena, (PrimOp) { .op = abs_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case OpenCLstd_Sin: instr = prim_op(parser->arena, (PrimOp) { .op = sin_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case OpenCLstd_Cos: instr = prim_op(parser->arena, (PrimOp) { .op = cos_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; default: shd_error("unhandled extended instruction %d in set '%s'", ext_instr, set); @@ -1228,31 +1228,31 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case GLSLstd450Floor: instr = prim_op(parser->arena, (PrimOp) { .op = floor_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case GLSLstd450Sqrt: instr = prim_op(parser->arena, (PrimOp) { .op = sqrt_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case GLSLstd450FAbs: instr = prim_op(parser->arena, (PrimOp) { .op = abs_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case GLSLstd450Sin: instr = prim_op(parser->arena, (PrimOp) { .op = sin_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case GLSLstd450Cos: instr = prim_op(parser->arena, (PrimOp) { .op = cos_op, - .operands = singleton(args[0]) + .operands = shd_singleton(args[0]) }); break; case GLSLstd450FMin: instr = prim_op(parser->arena, (PrimOp) { .op = min_op, .operands = mk_nodes(parser->arena, args[0], args[1]) }); break; @@ -1261,7 +1261,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case GLSLstd450FMax: instr = prim_op(parser->arena, (PrimOp) { .op = max_op, .operands = mk_nodes(parser->arena, args[0], args[1]) }); break; case GLSLstd450SMax: instr = prim_op(parser->arena, (PrimOp) { .op = max_op, .operands = mk_nodes(parser->arena, args[0], args[1]) }); break; case GLSLstd450UMax: instr = prim_op(parser->arena, (PrimOp) { .op = max_op, .operands = mk_nodes(parser->arena, args[0], args[1]) }); break; - case GLSLstd450Exp: instr = prim_op(parser->arena, (PrimOp) { .op = exp_op, .operands = singleton(args[0]) }); break; + case GLSLstd450Exp: instr = prim_op(parser->arena, (PrimOp) { .op = exp_op, .operands = shd_singleton(args[0]) }); break; case GLSLstd450Pow: instr = prim_op(parser->arena, (PrimOp) { .op = pow_op, .operands = mk_nodes(parser->arena, args[0], args[1]) }); break; default: shd_error("unhandled extended instruction %d in set '%s'", ext_instr, set); } @@ -1270,7 +1270,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } parser->defs[result].type = Value; - parser->defs[result].node = first(bind_instruction_outputs_count(parser->current_block.builder, instr, 1)); + parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, instr, 1)); break; } case SpvOpBranch: { @@ -1298,9 +1298,9 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpReturnValue: { Nodes args; if (op == SpvOpReturn) - args = empty(parser->arena); + args = shd_empty(parser->arena); else - args = singleton(get_def_ssa_value(parser, instruction[1])); + args = shd_singleton(get_def_ssa_value(parser, instruction[1])); BodyBuilder* bb = parser->current_block.builder; parser->current_block.finished = finish_body(bb, fn_ret(parser->arena, (Return) { .args = args, diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 7a9bbdcf0..88b43c664 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -141,7 +141,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay Nodes annotations = get_declaration_annotations(decl); for (size_t k = 0; k < annotations.count; k++) { const Node* a = annotations.nodes[k]; - if ((strcmp(get_annotation_name(a), "InitialValue") == 0) && resolve_to_int_literal(first(get_annotation_values(a)))->value == j) { + if ((strcmp(get_annotation_name(a), "InitialValue") == 0) && resolve_to_int_literal(shd_first(get_annotation_values(a)))->value == j) { constant_res_info->default_data = calloc(1, layout.size_in_bytes); write_value(constant_res_info->default_data, get_annotation_values(a).nodes[1]); //printf("wowie"); @@ -349,7 +349,7 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) size_t num_args = args_struct_type->payload.record_type.members.count; if (num_args == 0) { - shd_error_print("EntryPointArgs cannot be empty\n"); + shd_error_print("EntryPointArgs cannot be shd_empty\n"); return false; } diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 5f12ada76..c8ecc5d19 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -208,7 +208,7 @@ static void process_cf_node(CfgBuildContext* ctx, CFNode* node) { add_structural_edge(&loop_ctx, node, terminator->payload.loop_instr.body, StructuredEnterBodyEdge, terminator); return; } case Control_TAG: { - const Node* param = first(get_abstraction_params(terminator->payload.control.inside)); + const Node* param = shd_first(get_abstraction_params(terminator->payload.control.inside)); //CFNode* let_tail_cfnode = get_or_enqueue(ctx, get_structured_construct_tail(terminator)); const Node* tail = get_structured_construct_tail(terminator); shd_dict_insert(const Node*, const Node*, ctx->join_point_values, param, tail); diff --git a/src/shady/analysis/leak.c b/src/shady/analysis/leak.c index 762e2873b..ee253c46c 100644 --- a/src/shady/analysis/leak.c +++ b/src/shady/analysis/leak.c @@ -23,7 +23,7 @@ void visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, Visit bool is_control_static(const UsesMap* map, const Node* control) { assert(control->tag == Control_TAG); const Node* inside = control->payload.control.inside; - const Node* jp = first(get_abstraction_params(inside)); + const Node* jp = shd_first(get_abstraction_params(inside)); bool found_binding_abs = false; const Use* use = get_first_use(map, jp); diff --git a/src/shady/annotation.c b/src/shady/annotation.c index 6979ffc99..cc349bfa7 100644 --- a/src/shady/annotation.c +++ b/src/shady/annotation.c @@ -74,7 +74,7 @@ Nodes filter_out_annotation(IrArena* arena, Nodes annotations, const char* name) new_annotations[new_count++] = annotations.nodes[i]; } } - return nodes(arena, new_count, new_annotations); + return shd_nodes(arena, new_count, new_annotations); } ExecutionModel execution_model_from_string(const char* string) { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 1abde9ca2..01ef096d9 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -33,7 +33,7 @@ BodyBuilder* begin_body_with_mem(IrArena* a, const Node* mem) { } BodyBuilder* begin_block_with_side_effects(IrArena* a, const Node* mem) { - Node* block = basic_block(a, empty(a), NULL); + Node* block = basic_block(a, shd_empty(a), NULL); BodyBuilder* builder = begin_body_with_mem(a, get_abstraction_mem(block)); builder->tail_block = block; builder->block_entry_block = block; @@ -55,11 +55,11 @@ Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size LARRAY(const Node*, extracted, outputs_count); for (size_t i = 0; i < outputs_count; i++) extracted[i] = gen_extract_single(bb, value, int32_literal(bb->arena, i)); - return nodes(bb->arena, outputs_count, extracted); + return shd_nodes(bb->arena, outputs_count, extracted); } else if (outputs_count == 1) - return singleton(value); + return shd_singleton(value); else - return empty(bb->arena); + return shd_empty(bb->arena); } static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { @@ -73,17 +73,17 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { assert(bb->arena->config.check_types); - return bind_internal(bb, instruction, singleton(instruction->type).count); + return bind_internal(bb, instruction, shd_singleton(instruction->type).count); } const Node* bind_instruction_single(BodyBuilder* bb, const Node* instr) { - return first(bind_instruction_outputs_count(bb, instr, 1)); + return shd_first(bind_instruction_outputs_count(bb, instr, 1)); } Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String const output_names[]) { assert(bb->arena->config.check_types); assert(output_names); - return bind_internal(bb, instruction, singleton(instruction->type).count); + return bind_internal(bb, instruction, shd_singleton(instruction->type).count); } Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { @@ -235,7 +235,7 @@ static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { LARRAY(const Node*, tail_params, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) tail_params[i] = param(a, qyield_types.nodes[i], NULL); - return nodes(a, yield_types.count, tail_params); + return shd_nodes(a, yield_types.count, tail_params); } Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constructTag tag, union NodesUnion payload) { @@ -329,7 +329,7 @@ begin_control_t begin_control(BodyBuilder* bb, Nodes yield_types) { .is_uniform = true }); const Node* jp = param(a, jp_type, NULL); - Node* c = case_(a, singleton(jp)); + Node* c = case_(a, shd_singleton(jp)); return (begin_control_t) { .results = gen_control(bb, yield_types, c), .case_ = c, @@ -346,7 +346,7 @@ begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes for (size_t i = 0; i < arg_types.count; i++) { params[i] = param(a, qualified_type_helper(arg_types.nodes[i], false), NULL); } - Node* loop_header = case_(a, nodes(a, arg_types.count, params)); + Node* loop_header = case_(a, shd_nodes(a, arg_types.count, params)); set_abstraction_body(outer_control.case_, finish_body_with_jump(outer_control_case_builder, loop_header, initial_values)); BodyBuilder* loop_header_builder = begin_body_with_mem(a, get_abstraction_mem(loop_header)); begin_control_t inner_control = begin_control(loop_header_builder, arg_types); @@ -354,7 +354,7 @@ begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes return (begin_loop_helper_t) { .results = outer_control.results, - .params = nodes(a, arg_types.count, params), + .params = shd_nodes(a, arg_types.count, params), .loop_body = inner_control.case_, .break_jp = outer_control.jp, .continue_jp = inner_control.jp, diff --git a/src/shady/constructors.c b/src/shady/constructors.c index e831fb3cd..d25c70165 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -270,7 +270,7 @@ const Node* jump_helper(IrArena* a, const Node* dst, Nodes args, const Node* mem const Node* unit_type(IrArena* arena) { return record_type(arena, (RecordType) { - .members = empty(arena), + .members = shd_empty(arena), }); } @@ -331,11 +331,11 @@ const Node* fp_literal_helper(IrArena* a, FloatSizes size, double value) { const Node* extract_helper(const Node* composite, const Node* index) { IrArena* a = composite->arena; - return prim_op_helper(a, extract_op, empty(a), mk_nodes(a, composite, index)); + return prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, composite, index)); } const Node* maybe_tuple_helper(IrArena* a, Nodes values) { if (values.count == 1) - return first(values); + return shd_first(values); return tuple_helper(a, values); } diff --git a/src/shady/fold.c b/src/shady/fold.c index f06bfc55a..9374f0d90 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -80,7 +80,7 @@ break; else return quote_single(arena, fp_literal_helper(arena, float_width, fmod(get_float_literal_value(*float_literals[0]), get_float_literal_value(*float_literals[1])))); case reinterpret_op: { - const Type* dst_t = first(payload.type_arguments); + const Type* dst_t = shd_first(payload.type_arguments); uint64_t raw_value = int_literals[0] ? int_literals[0]->value : float_literals[0]->value; if (dst_t->tag == Int_TAG) { return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = dst_t->payload.int_type.is_signed, .width = dst_t->payload.int_type.width, .value = raw_value })); @@ -90,7 +90,7 @@ break; break; } case convert_op: { - const Type* dst_t = first(payload.type_arguments); + const Type* dst_t = shd_first(payload.type_arguments); uint64_t bitmask = 0; if (get_type_bitwidth(dst_t) == 64) bitmask = UINT64_MAX; @@ -142,7 +142,7 @@ static inline const Node* fold_simplify_math(const Node* node) { return quote_single(arena, payload.operands.nodes[0]); // if first operand is zero, invert the second one if (is_zero(payload.operands.nodes[0])) - return prim_op(arena, (PrimOp) { .op = neg_op, .operands = singleton(payload.operands.nodes[1]), .type_arguments = empty(arena) }); + return prim_op(arena, (PrimOp) { .op = neg_op, .operands = shd_singleton(payload.operands.nodes[1]), .type_arguments = shd_empty(arena) }); break; } case mul_op: { @@ -198,16 +198,16 @@ static inline const Node* resolve_ptr_source(const Node* ptr) { switch (instruction.op) { case reinterpret_op: { distance++; - ptr = first(instruction.operands); + ptr = shd_first(instruction.operands); continue; } case convert_op: { // only conversions to generic pointers are acceptable - if (first(instruction.type_arguments)->tag != PtrType_TAG) + if (shd_first(instruction.type_arguments)->tag != PtrType_TAG) break; assert(!specialize_generic && "something should not be converted to generic twice!"); specialize_generic = true; - ptr = first(instruction.operands); + ptr = shd_first(instruction.operands); src_as = get_unqualified_type(ptr->type)->payload.ptr_type.address_space; continue; } @@ -236,7 +236,7 @@ static inline const Node* resolve_ptr_source(const Node* ptr) { if (new_src_ptr_type->tag != PtrType_TAG || new_src_ptr_type->payload.ptr_type.pointed_type != desired_pointee_type) { PtrType payload = t->payload.ptr_type; payload.address_space = src_as; - ptr = prim_op_helper(a, reinterpret_op, singleton(ptr_type(a, payload)), singleton(ptr)); + ptr = prim_op_helper(a, reinterpret_op, shd_singleton(ptr_type(a, payload)), shd_singleton(ptr)); } return ptr; } @@ -310,7 +310,7 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { return node; if (!is_subtype(node->type, r->type)) - r = prim_op_helper(arena, convert_op, singleton(get_unqualified_type(node->type)), singleton(r)); + r = prim_op_helper(arena, convert_op, shd_singleton(get_unqualified_type(node->type)), shd_singleton(r)); return r; } @@ -322,7 +322,7 @@ static const Node* fold_prim_op(IrArena* arena, const Node* node) { switch (payload.op) { // TODO: case subgroup_broadcast_first_op: case subgroup_assume_uniform_op: { - const Node* value = first(payload.operands); + const Node* value = shd_first(payload.operands); if (is_qualified_type_uniform(value->type)) return quote_single(arena, value); break; @@ -348,7 +348,7 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { } case Store_TAG: { if (node->payload.store.ptr->tag == Undef_TAG) - return mem_and_value(arena, (MemAndValue) { .value = tuple_helper(arena, empty(arena)), .mem = node->payload.store.mem }); + return mem_and_value(arena, (MemAndValue) { .value = tuple_helper(arena, shd_empty(arena)), .mem = node->payload.store.mem }); break; } case PtrArrayElementOffset_TAG: { @@ -368,7 +368,7 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { switch (payload.op) { case reinterpret_op: case convert_op: { - if (first(payload.operands)->tag == Undef_TAG) + if (shd_first(payload.operands)->tag == Undef_TAG) return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); break; } @@ -450,8 +450,8 @@ const Node* fold_node(IrArena* arena, const Node* node) { .inspect = payload.inspect, .yield_types = payload.yield_types, .default_case = payload.default_case, - .literals = nodes(arena, new_cases_count, literals), - .cases = nodes(arena, new_cases_count, cases), + .literals = shd_nodes(arena, new_cases_count, literals), + .cases = shd_nodes(arena, new_cases_count, cases), .tail = payload.tail, .mem = payload.mem, }); diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 704b55abd..506b874a4 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -59,7 +59,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { shd_growy_append_formatted(g, "%s\t\t\t}\n", extra); if (list) { shd_growy_append_formatted(g, "\t\t\t}\n"); - shd_growy_append_formatted(g, "\t\t\tnode->payload.%s.%s = nodes(arena, ops_count, ops);\n", snake_name, op_name); + shd_growy_append_formatted(g, "\t\t\tnode->payload.%s.%s = shd_nodes(arena, ops_count, ops);\n", snake_name, op_name); } free((void*) cap); shd_growy_append_formatted(g, "\t\t}\n"); diff --git a/src/shady/generator_rewrite.c b/src/shady/generator_rewrite.c index 55e2fc777..73b42cda3 100644 --- a/src/shady/generator_rewrite.c +++ b/src/shady/generator_rewrite.c @@ -55,7 +55,7 @@ static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { } if (strcmp(class, "string") == 0) { if (list) - shd_growy_append_formatted(g, "\t\t\tpayload.%s = strings(rewriter->dst_arena, old_payload.%s.count, old_payload.%s.strings);\n", op_name, op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tpayload.%s = shd_strings(rewriter->dst_arena, old_payload.%s.count, old_payload.%s.strings);\n", op_name, op_name, op_name); else shd_growy_append_formatted(g, "\t\t\tpayload.%s = string(rewriter->dst_arena, old_payload.%s);\n", op_name, op_name); continue; diff --git a/src/shady/ir.c b/src/shady/ir.c index 789e40fcf..224db104b 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -69,7 +69,7 @@ NodeId allocate_node_id(IrArena* arena, const Node* n) { return shd_growy_size(arena->ids) / sizeof(const Node*); } -Nodes nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { +Nodes shd_nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { Nodes tmp = { .count = count, .nodes = in_nodes @@ -88,7 +88,7 @@ Nodes nodes(IrArena* arena, size_t count, const Node* in_nodes[]) { return nodes; } -Strings strings(IrArena* arena, size_t count, const char* in_strs[]) { +Strings shd_strings(IrArena* arena, size_t count, const char* in_strs[]) { Strings tmp = { .count = count, .strings = in_strs, @@ -107,38 +107,38 @@ Strings strings(IrArena* arena, size_t count, const char* in_strs[]) { return strings; } -Nodes empty(IrArena* a) { - return nodes(a, 0, NULL); +Nodes shd_empty(IrArena* a) { + return shd_nodes(a, 0, NULL); } -Nodes singleton(const Type* type) { - IrArena* arena = type->arena; - const Type* arr[] = { type }; - return nodes(arena, 1, arr); +Nodes shd_singleton(const Node* n) { + IrArena* arena = n->arena; + const Type* arr[] = { n }; + return shd_nodes(arena, 1, arr); } -const Node* first(Nodes nodes) { +const Node* shd_first(Nodes nodes) { assert(nodes.count > 0); return nodes.nodes[0]; } -Nodes append_nodes(IrArena* arena, Nodes old, const Node* new) { +Nodes shd_nodes_append(IrArena* arena, Nodes old, const Node* new) { LARRAY(const Node*, tmp, old.count + 1); for (size_t i = 0; i < old.count; i++) tmp[i] = old.nodes[i]; tmp[old.count] = new; - return nodes(arena, old.count + 1, tmp); + return shd_nodes(arena, old.count + 1, tmp); } -Nodes prepend_nodes(IrArena* arena, Nodes old, const Node* new) { +Nodes shd_nodes_prepend(IrArena* arena, Nodes old, const Node* new) { LARRAY(const Node*, tmp, old.count + 1); for (size_t i = 0; i < old.count; i++) tmp[i + 1] = old.nodes[i]; tmp[0] = new; - return nodes(arena, old.count + 1, tmp); + return shd_nodes(arena, old.count + 1, tmp); } -Nodes concat_nodes(IrArena* arena, Nodes a, Nodes b) { +Nodes shd_concat_nodes(IrArena* arena, Nodes a, Nodes b) { LARRAY(const Node*, tmp, a.count + b.count); size_t j = 0; for (size_t i = 0; i < a.count; i++) @@ -146,18 +146,18 @@ Nodes concat_nodes(IrArena* arena, Nodes a, Nodes b) { for (size_t i = 0; i < b.count; i++) tmp[j++] = b.nodes[i]; assert(j == a.count + b.count); - return nodes(arena, j, tmp); + return shd_nodes(arena, j, tmp); } -Nodes change_node_at_index(IrArena* arena, Nodes old, size_t i, const Node* n) { +Nodes shd_change_node_at_index(IrArena* arena, Nodes old, size_t i, const Node* n) { LARRAY(const Node*, tmp, old.count); for (size_t j = 0; j < old.count; j++) tmp[j] = old.nodes[j]; tmp[i] = n; - return nodes(arena, old.count, tmp); + return shd_nodes(arena, old.count, tmp); } -bool find_in_nodes(Nodes nodes, const Node* n) { +bool shd_find_in_nodes(Nodes nodes, const Node* n) { for (size_t i = 0; i < nodes.count; i++) if (nodes.nodes[i] == n) return true; @@ -202,7 +202,7 @@ Strings import_strings(IrArena* dst_arena, Strings old_strings) { LARRAY(String, arr, count); for (size_t i = 0; i < count; i++) arr[i] = string(dst_arena, old_strings.strings[i]); - return strings(dst_arena, count, arr); + return shd_strings(dst_arena, count, arr); } void shd_format_string_internal(const char* str, va_list args, void* uptr, void callback(void*, size_t, char*)); @@ -266,5 +266,5 @@ bool compare_string(const char** a, const char** b) { } Nodes list_to_nodes(IrArena* arena, struct List* list) { - return nodes(arena, shd_list_count(list), shd_read_list(const Node*, list)); + return shd_nodes(arena, shd_list_count(list), shd_read_list(const Node*, list)); } diff --git a/src/shady/module.c b/src/shady/module.c index e222783ae..680d85d0e 100644 --- a/src/shady/module.c +++ b/src/shady/module.c @@ -27,7 +27,7 @@ String get_module_name(const Module* m) { Nodes get_module_declarations(const Module* m) { size_t count = shd_list_count(m->decls); const Node** start = shd_read_list(const Node*, m->decls); - return nodes(get_module_arena(m), count, start); + return shd_nodes(get_module_arena(m), count, start); } void register_decl_module(Module* m, Node* node) { diff --git a/src/shady/node.c b/src/shady/node.c index 54c287a36..548214d41 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -95,8 +95,8 @@ const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { switch (ptr->payload.prim_op.op) { case convert_op: { // chase generic pointers to their source - if (first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { - ptr = first(ptr->payload.prim_op.operands); + if (shd_first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { + ptr = shd_first(ptr->payload.prim_op.operands); continue; } break; @@ -104,8 +104,8 @@ const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { case reinterpret_op: { // chase ptr casts to their source // TODO: figure out round-trips through integer casts? - if (first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { - ptr = first(ptr->payload.prim_op.operands); + if (shd_first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { + ptr = shd_first(ptr->payload.prim_op.operands); continue; } break; @@ -128,7 +128,7 @@ const Node* resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config) { case PrimOp_TAG: { switch (ptr->payload.prim_op.op) { case convert_op: { // allow address space conversions - ptr = first(ptr->payload.prim_op.operands); + ptr = shd_first(ptr->payload.prim_op.operands); continue; } default: break; @@ -177,7 +177,7 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi case convert_op: case reinterpret_op: { if (config.allow_incompatible_types) { - node = first(node->payload.prim_op.operands); + node = shd_first(node->payload.prim_op.operands); continue; } } @@ -312,7 +312,7 @@ void set_abstraction_body(Node* abs, const Node* body) { const Node* mem = insert->block_entry_mem; const Node* block = insert->block_entry_block; set_abstraction_body((Node*) block, finish_block_body(insert, body)); - body = jump_helper(a, block, empty(a), mem); + body = jump_helper(a, block, shd_empty(a), mem); // mem_abs->payload.basic_block.insert = NULL; continue; } diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index df185a153..3ca1da893 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -82,7 +82,7 @@ const Node* process(Context* ctx, const Node* old) { const Node* term = get_abstraction_body(control_inside); if (term->tag == Join_TAG) { Join payload_join = term->payload.join; - if (payload_join.join_point == first(get_abstraction_params(control_inside))) { + if (payload_join.join_point == shd_first(get_abstraction_params(control_inside))) { // if we immediately consume the join point and it's never leaked, this control block does nothing and can be eliminated register_processed(r, get_abstraction_mem(control_inside), rewrite_node(r, payload.mem)); register_processed(r, control_inside, NULL); diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 1e2d75dee..a4518038a 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -54,9 +54,9 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No const LTNode* bb_loop = get_loop(looptree_lookup(ctx->loop_tree, old)); - *nparams = empty(a); - *lparams = empty(a); - *nargs = empty(a); + *nparams = shd_empty(a); + *lparams = shd_empty(a); + *nargs = shd_empty(a); struct Dict* fvs = free_frontier(ctx->scheduler, ctx->cfg, old); const Node* fv; @@ -71,9 +71,9 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No shd_log_fmt(DEBUGV, " (%%%d) is used outside of the loop that defines it %s %s\n", fv->id, loop_name(defining_loop), loop_name(bb_loop)); const Node* narg = rewrite_node(&ctx->rewriter, fv); const Node* nparam = param(a, narg->type, "lcssa_phi"); - *nparams = append_nodes(a, *nparams, nparam); - *lparams = append_nodes(a, *lparams, fv); - *nargs = append_nodes(a, *nargs, narg); + *nparams = shd_nodes_append(a, *nparams, nparam); + *lparams = shd_nodes_append(a, *lparams, fv); + *nargs = shd_nodes_append(a, *nargs, narg); } } shd_destroy_dict(fvs); @@ -110,7 +110,7 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* Nodes nargs; find_liftable_loop_values(ctx, old_children[i], &new_params[i], &lifted_params[i], &nargs); Nodes nparams = recreate_params(&ctx->rewriter, get_abstraction_params(old_children[i])); - new_children[i] = basic_block(a, concat_nodes(a, nparams, new_params[i]), get_abstraction_name(old_children[i])); + new_children[i] = basic_block(a, shd_concat_nodes(a, nparams, new_params[i]), get_abstraction_name(old_children[i])); register_processed(&ctx->rewriter, old_children[i], new_children[i]); register_processed_list(&ctx->rewriter, get_abstraction_params(old_children[i]), nparams); shd_dict_insert(const Node*, Nodes, ctx->lifted_arguments, old_children[i], nargs); @@ -168,7 +168,7 @@ const Node* process_node(Context* ctx, const Node* old) { Nodes nargs = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); Nodes* lifted_args = shd_dict_find_value(const Node*, Nodes, ctx->lifted_arguments, old->payload.jump.target); if (lifted_args) { - nargs = concat_nodes(a, nargs, *lifted_args); + nargs = shd_concat_nodes(a, nargs, *lifted_args); } return jump(a, (Jump) { .target = rewrite_node(&ctx->rewriter, old->payload.jump.target), diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index d9b326d5d..a00c99904 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -44,7 +44,7 @@ static const Node* process(Context* ctx, const Node* node) { struct Dict* frontier = free_frontier(ctx->scheduler, ctx->cfg, node); // insert_dict(const Node*, Dict*, ctx->lift, node, frontier); - Nodes additional_args = empty(a); + Nodes additional_args = shd_empty(a); Nodes new_params = recreate_params(r, get_abstraction_params(node)); register_processed_list(r, get_abstraction_params(node), new_params); size_t i = 0; @@ -55,10 +55,10 @@ static const Node* process(Context* ctx, const Node* node) { while (shd_dict_iter(frontier, &i, &value, NULL)) { if (is_value(value)) { - additional_args = append_nodes(a, additional_args, value); + additional_args = shd_nodes_append(a, additional_args, value); const Type* t = rewrite_node(r, value->type); const Node* p = param(a, t, NULL); - new_params = append_nodes(a, new_params, p); + new_params = shd_nodes_append(a, new_params, p); register_processed(&bb_ctx.rewriter, value, p); } } @@ -90,7 +90,7 @@ static const Node* process(Context* ctx, const Node* node) { return jump(a, (Jump) { .mem = rewrite_node(r, payload.mem), .target = rewrite_node(r, payload.target), - .args = concat_nodes(a, rewrite_nodes(r, payload.args), rewrite_nodes(r, *additional_args)) + .args = shd_concat_nodes(a, rewrite_nodes(r, payload.args), rewrite_nodes(r, *additional_args)) }); } default: break; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 4535a3f67..283ceceef 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -68,7 +68,7 @@ static Nodes set2nodes(IrArena* a, struct Dict* set) { tmp[j++] = key; } assert(j == count); - return nodes(a, count, tmp); + return shd_nodes(a, count, tmp); } static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { @@ -112,7 +112,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { LARRAY(const Node*, new_params_arr, ovariables.count); for (size_t i = 0; i < ovariables.count; i++) new_params_arr[i] = param(a, rewrite_node(&ctx->rewriter, ovariables.nodes[i]->type), get_value_name_unsafe(ovariables.nodes[i])); - Nodes new_params = nodes(a, ovariables.count, new_params_arr); + Nodes new_params = shd_nodes(a, ovariables.count, new_params_arr); LiftedCont* lifted_cont = calloc(sizeof(LiftedCont), 1); lifted_cont->old_cont = liftee; @@ -124,9 +124,9 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { const Node* payload = param(a, qualified_type_helper(uint32_type(a), false), "sp"); // Keep annotations the same - Nodes annotations = singleton(annotation(a, (Annotation) { .name = "Exported" })); - new_params = prepend_nodes(a, new_params, payload); - Node* new_fn = function(ctx->rewriter.dst_module, new_params, name, annotations, nodes(a, 0, NULL)); + Nodes annotations = shd_singleton(annotation(a, (Annotation) { .name = "Exported" })); + new_params = shd_nodes_prepend(a, new_params, payload); + Node* new_fn = function(ctx->rewriter.dst_module, new_params, name, annotations, shd_nodes(a, 0, NULL)); lifted_cont->lifted_fn = new_fn; // Recover that stuff inside the new body @@ -144,7 +144,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { // set_value_name(recovered_value, param_name); if (is_qualified_type_uniform(ovar->type)) - recovered_value = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = singleton(recovered_value) }); + recovered_value = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = shd_singleton(recovered_value) }); register_processed(r, ovar, recovered_value); } @@ -206,9 +206,9 @@ static const Node* process_node(Context* ctx, const Node* node) { }); const Node* jp = gen_ext_instruction(bb, "shady.internal", ShadyOpCreateJoinPoint, qualified_type_helper(jp_type, true), mk_nodes(a, tail_ptr, sp)); // dumbass hack - jp = gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(jp)); + jp = gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(jp)); - register_processed(r, first(get_abstraction_params(oinside)), jp); + register_processed(r, shd_first(get_abstraction_params(oinside)), jp); register_processed(r, get_abstraction_mem(oinside), bb_mem(bb)); register_processed(r, oinside, NULL); return finish_body(bb, rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index f05349eea..6138d6521 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -54,7 +54,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); assert(is_data_type(element_type)); - const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, singleton(type_decl_ref_helper(a, vctx->nom_t)), singleton(int32_literal(a, shd_list_count(vctx->members)))); + const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, shd_singleton(type_decl_ref_helper(a, vctx->nom_t)), shd_singleton(int32_literal(a, shd_list_count(vctx->members)))); shd_list_append(const Type*, vctx->members, element_type); StackSlot slot = { vctx->num_slots, slot_offset, element_type, AsPrivate }; @@ -95,7 +95,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.stack_size_on_entry = gen_get_stack_size(bb); set_value_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); - Node* nom_t = nominal_type(m, empty(a), shd_format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); + Node* nom_t = nominal_type(m, shd_empty(a), shd_format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); VContext vctx = { .visitor = { .visit_node_fn = (VisitNodeFn) search_operand_for_alloca, @@ -110,13 +110,13 @@ static const Node* process(Context* ctx, const Node* node) { visit_function_bodies_rpo(&vctx.visitor, node); vctx.nom_t->payload.nom_type.body = record_type(a, (RecordType) { - .members = nodes(a, vctx.num_slots, shd_read_list(const Node*, vctx.members)), - .names = strings(a, 0, NULL), + .members = shd_nodes(a, vctx.num_slots, shd_read_list(const Node*, vctx.members)), + .names = shd_strings(a, 0, NULL), .special = 0 }); shd_destroy_list(vctx.members); ctx2.num_slots = vctx.num_slots; - ctx2.frame_size = gen_primop_e(bb, size_of_op, singleton(type_decl_ref_helper(a, vctx.nom_t)), empty(a)); + ctx2.frame_size = gen_primop_e(bb, size_of_op, shd_singleton(type_decl_ref_helper(a, vctx.nom_t)), shd_empty(a)); ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); // make sure to use the new mem from then on @@ -132,7 +132,7 @@ static const Node* process(Context* ctx, const Node* node) { if (!found_slot) { shd_error_print("lower_alloca: failed to find a stack offset for "); shd_log_node(ERROR, node); - shd_error_print(", most likely this means this alloca was not found in the first block of a function.\n"); + shd_error_print(", most likely this means this alloca was not found in the shd_first block of a function.\n"); shd_log_module(DEBUG, ctx->config, ctx->rewriter.src_module); shd_error_die(); } @@ -145,16 +145,16 @@ static const Node* process(Context* ctx, const Node* node) { //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); - const Node* slot = ptr_array_element_offset(a, (PtrArrayElementOffset) { .ptr = ctx->base_stack_addr_on_entry, .offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)) }); + const Node* slot = ptr_array_element_offset(a, (PtrArrayElementOffset) { .ptr = ctx->base_stack_addr_on_entry, .offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)) }); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = gen_reinterpret_cast(bb, ptr_t, slot); //bool last = found_slot->i == ctx->num_slots - 1; //if (last) { - const Node* updated_stack_ptr = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, ctx->stack_size_on_entry, ctx->frame_size)); + const Node* updated_stack_ptr = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, ctx->frame_size)); gen_set_stack_size(bb, updated_stack_ptr); //} - return yield_values_and_wrap_in_block(bb, singleton(slot)); + return yield_values_and_wrap_in_block(bb, shd_singleton(slot)); } break; } diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index ce224f6b7..903cf76f3 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -35,7 +35,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { Nodes nannots = rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); - Node* prelude = case_(a, empty(a)); + Node* prelude = case_(a, shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(prelude)); // Supplement an additional parameter for the join point @@ -44,19 +44,19 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { }); if (lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { - ctx2.return_jp = gen_ext_instruction(bb, "shady.internal", ShadyOpDefaultJoinPoint, qualified_type_helper(jp_type, true), empty(a)); + ctx2.return_jp = gen_ext_instruction(bb, "shady.internal", ShadyOpDefaultJoinPoint, qualified_type_helper(jp_type, true), shd_empty(a)); } else { const Node* jp_variable = param(a, qualified_type_helper(jp_type, false), "return_jp"); - nparams = append_nodes(a, nparams, jp_variable); + nparams = shd_nodes_append(a, nparams, jp_variable); ctx2.return_jp = jp_variable; } - Node* fun = function(ctx->rewriter.dst_module, nparams, get_abstraction_name(old), nannots, empty(a)); + Node* fun = function(ctx->rewriter.dst_module, nparams, get_abstraction_name(old), nannots, shd_empty(a)); register_processed(&ctx->rewriter, old, fun); register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(prelude, finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body))); - set_abstraction_body(fun, jump_helper(a, prelude, empty(a), get_abstraction_mem(fun))); + set_abstraction_body(fun, jump_helper(a, prelude, shd_empty(a), get_abstraction_mem(fun))); return fun; } @@ -77,10 +77,10 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .type = join_point_type(a, (JoinPointType) { .yield_types = strip_qualifiers(a, returned_types) }), .is_uniform = false }); - param_types = append_nodes(a, param_types, jp_type); + param_types = shd_nodes_append(a, param_types, jp_type); return fn_type(a, (FnType) { .param_types = param_types, - .return_types = empty(a), + .return_types = shd_empty(a), }); } case Return_TAG: { @@ -127,10 +127,10 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { const Node* jp = param(a, jp_type, "fn_return_point"); // Add that join point as the last argument to the newly made function - nargs = append_nodes(a, nargs, jp); + nargs = shd_nodes_append(a, nargs, jp); // the body of the control is just an immediate tail-call - Node* control_case = case_(a, singleton(jp)); + Node* control_case = case_(a, shd_singleton(jp)); const Node* control_body = tail_call(a, (TailCall) { .callee = ncallee, .args = nargs, diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 75eb802d6..3ef955f4d 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -52,7 +52,7 @@ static const Node* process_node(Context* ctx, const Node* node) { .is_uniform = false, }); const Node* jp = param(a, jp_type, "if_join"); - Nodes jps = singleton(jp); + Nodes jps = shd_singleton(jp); shd_dict_insert(const Node*, Nodes, ctx->structured_join_tokens, node, jps); const Node* true_block = rewrite_node(r, payload.if_true); @@ -62,15 +62,15 @@ static const Node* process_node(Context* ctx, const Node* node) { false_block = rewrite_node(r, payload.if_false); } else { assert(yield_types.count == 0); - false_block = basic_block(a, nodes(a, 0, NULL), unique_name(a, "if_false")); - set_abstraction_body((Node*) false_block, join(a, (Join) { .join_point = jp, .args = nodes(a, 0, NULL), .mem = get_abstraction_mem(false_block) })); + false_block = basic_block(a, shd_nodes(a, 0, NULL), unique_name(a, "if_false")); + set_abstraction_body((Node*) false_block, join(a, (Join) { .join_point = jp, .args = shd_nodes(a, 0, NULL), .mem = get_abstraction_mem(false_block) })); } - Node* control_case = basic_block(a, singleton(jp), NULL); + Node* control_case = basic_block(a, shd_singleton(jp), NULL); const Node* control_body = branch(a, (Branch) { .condition = rewrite_node(r, node->payload.if_instr.condition), - .true_jump = jump_helper(a, true_block, empty(a), get_abstraction_mem(control_case)), - .false_jump = jump_helper(a, false_block, empty(a), get_abstraction_mem(control_case)), + .true_jump = jump_helper(a, true_block, shd_empty(a), get_abstraction_mem(control_case)), + .false_jump = jump_helper(a, false_block, shd_empty(a), get_abstraction_mem(control_case)), .mem = get_abstraction_mem(control_case), }); set_abstraction_body(control_case, control_body); @@ -105,13 +105,13 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* loop_header_block = basic_block(a, new_params, unique_name(a, "loop_header")); BodyBuilder* inner_bb = begin_body_with_mem(a, get_abstraction_mem(loop_header_block)); - Node* inner_control_case = case_(a, singleton(continue_point)); + Node* inner_control_case = case_(a, shd_singleton(continue_point)); set_abstraction_body(inner_control_case, jump_helper(a, rewrite_node(r, old_loop_block), new_params, get_abstraction_mem(inner_control_case))); Nodes args = gen_control(inner_bb, param_types, inner_control_case); set_abstraction_body(loop_header_block, finish_body(inner_bb, jump(a, (Jump) { .target = loop_header_block, .args = args, .mem = bb_mem(inner_bb) }))); - Node* outer_control_case = case_(a, singleton(break_point)); + Node* outer_control_case = case_(a, shd_singleton(break_point)); const Node* first_iteration_jump = jump(a, (Jump) { .target = loop_header_block, .args = rewrite_nodes(r, payload.initial_args), @@ -148,7 +148,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes* jps = shd_dict_find_value(const Node*, Nodes, ctx->structured_join_tokens, selection_instr); assert(jps && jps->count == 1); - const Node* jp = first(*jps); + const Node* jp = shd_first(*jps); assert(jp); const Node* nmem = rewrite_node(r, payload.mem); return join(a, (Join) { @@ -216,7 +216,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes* jps = shd_dict_find_value(const Node*, Nodes, ctx->structured_join_tokens, loop_start); assert(jps && jps->count == 2); - const Node* jp = first(*jps); + const Node* jp = shd_first(*jps); assert(jp); const Node* nmem = rewrite_node(r, payload.mem); return join(a, (Join) { diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 21367bc4c..a7331b01b 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -17,7 +17,7 @@ static Node* rewrite_entry_point_fun(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); - Node* fun = function(ctx->rewriter.dst_module, empty(a), node->payload.fun.name, annotations, empty(a)); + Node* fun = function(ctx->rewriter.dst_module, shd_empty(a), node->payload.fun.name, annotations, shd_empty(a)); register_processed(&ctx->rewriter, node, fun); @@ -41,8 +41,8 @@ static const Node* generate_arg_struct_type(Rewriter* rewriter, Nodes params) { } return record_type(a, (RecordType) { - .members = nodes(a, params.count, types), - .names = strings(a, params.count, names) + .members = shd_nodes(a, params.count, types), + .names = shd_strings(a, params.count, names) }); } @@ -65,7 +65,7 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const Nodes params = old_entry_point->payload.fun.params; for (int i = 0; i < params.count; ++i) { - const Node* addr = gen_lea(bb, arg_struct, int32_literal(a, 0), singleton(int32_literal(a, i))); + const Node* addr = gen_lea(bb, arg_struct, int32_literal(a, 0), shd_singleton(int32_literal(a, i))); const Node* val = gen_load(bb, addr); register_processed(&ctx->rewriter, params.nodes[i], val); } diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index 408a599e2..85c8884c8 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -23,7 +23,7 @@ static const Node* process(Context* ctx, const Node* node) { for (size_t i = 0; i < actual_size; i++) { copies[i] = value; } - return composite_helper(a, composite_t, nodes(a, actual_size, copies)); + return composite_helper(a, composite_t, shd_nodes(a, actual_size, copies)); } default: break; } diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 7f5b0af5d..1c6d6acd9 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -30,7 +30,7 @@ static const Node* process(Context* ctx, const Node* node) { register_processed(&ctx->rewriter, node, new_global); const Type* dst_t = ptr_type(a, (PtrType) { .pointed_type = t, .address_space = AsGeneric }); - const Node* converted = prim_op_helper(a, convert_op, singleton(dst_t), singleton(ref_decl_helper(a, new_global))); + const Node* converted = prim_op_helper(a, convert_op, shd_singleton(dst_t), shd_singleton(ref_decl_helper(a, new_global))); register_processed(&ctx->rewriter, ref_decl_helper(node->arena, node), converted); return new_global; } diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 9a46f75c3..13e1caeb5 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -50,17 +50,17 @@ static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t const Node* generic_ptr_type = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false}); // first_non_tag_bit = nptr >> (64 - 2 - 1) - const Node* first_non_tag_bit = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, nptr, size_t_literal(a, get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth - 1))); + const Node* first_non_tag_bit = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth - 1))); // first_non_tag_bit &= 1 - first_non_tag_bit = gen_primop_e(bb, and_op, empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); + first_non_tag_bit = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); // needs_sign_extension = first_non_tag_bit == 1 - const Node* needs_sign_extension = gen_primop_e(bb, eq_op, empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); + const Node* needs_sign_extension = gen_primop_e(bb, eq_op, shd_empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); // sign_extension_patch = needs_sign_extension ? ((1 << 2) - 1) << (64 - 2) : 0 - const Node* sign_extension_patch = gen_primop_e(bb, select_op, empty(a), mk_nodes(a, needs_sign_extension, size_t_literal(a, ((size_t) ((1 << max_tag) - 1)) << (get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth)), size_t_literal(a, 0))); + const Node* sign_extension_patch = gen_primop_e(bb, select_op, shd_empty(a), mk_nodes(a, needs_sign_extension, size_t_literal(a, ((size_t) ((1 << max_tag) - 1)) << (get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth)), size_t_literal(a, 0))); // patched_ptr = nptr & 0b00111 ... 111 - const Node* patched_ptr = gen_primop_e(bb, and_op, empty(a), mk_nodes(a, nptr, size_t_literal(a, SIZE_MAX >> generic_ptr_tag_bitwidth))); + const Node* patched_ptr = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, SIZE_MAX >> generic_ptr_tag_bitwidth))); // patched_ptr = patched_ptr | sign_extension_patch - patched_ptr = gen_primop_e(bb, or_op, empty(a), mk_nodes(a, patched_ptr, sign_extension_patch)); + patched_ptr = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, patched_ptr, sign_extension_patch)); const Type* dst_ptr_t = ptr_type(a, (PtrType) { .pointed_type = element_type, .address_space = get_addr_space_from_tag(tag) }); const Node* reinterpreted_ptr = gen_reinterpret_cast(bb, dst_ptr_t, patched_ptr); return reinterpreted_ptr; @@ -91,15 +91,15 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo const Node* ptr_param = param(a, qualified_type_helper(ctx->generic_ptr_type, uniform_ptr), "ptr"); const Node* value_param; - Nodes params = singleton(ptr_param); - Nodes return_ts = empty(a); + Nodes params = shd_singleton(ptr_param); + Nodes return_ts = shd_empty(a); switch (which) { case LoadFn: - return_ts = singleton(qualified_type_helper(t, uniform_ptr)); + return_ts = shd_singleton(qualified_type_helper(t, uniform_ptr)); break; case StoreFn: value_param = param(a, qualified_type_helper(t, false), "value"); - params = append_nodes(a, params, value_param); + params = shd_nodes_append(a, params, value_param); break; } Node* new_fn = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); @@ -110,76 +110,76 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo case LoadFn: { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); - begin_control_t r = begin_control(bb, singleton(t)); - const Node* final_loaded_value = first(r.results); + begin_control_t r = begin_control(bb, shd_singleton(t)); + const Node* final_loaded_value = shd_first(r.results); LARRAY(const Node*, literals, max_tag); LARRAY(const Node*, jumps, max_tag); for (size_t tag = 0; tag < max_tag; tag++) { literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { - Node* tag_case = case_(a, empty(a)); + Node* tag_case = case_(a, shd_empty(a)); set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(tag_case) })); - jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); + jumps[tag] = jump_helper(a, tag_case, shd_empty(a), get_abstraction_mem(r.case_)); continue; } - Node* tag_case = case_(a, empty(a)); + Node* tag_case = case_(a, shd_empty(a)); BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); - set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, singleton(loaded_value))); - jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); + set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_singleton(loaded_value))); + jumps[tag] = jump_helper(a, tag_case, shd_empty(a), get_abstraction_mem(r.case_)); } // extracted_tag = nptr >> (64 - 2), for example - const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); + const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); - Node* default_case = case_(a, empty(a)); + Node* default_case = case_(a, shd_empty(a)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); set_abstraction_body(r.case_, br_switch(a, (Switch) { .mem = get_abstraction_mem(r.case_), .switch_value = extracted_tag, - .case_values = nodes(a, max_tag, literals), - .case_jumps = nodes(a, max_tag, jumps), - .default_jump = jump_helper(a, default_case, empty(a), get_abstraction_mem(r.case_)) + .case_values = shd_nodes(a, max_tag, literals), + .case_jumps = shd_nodes(a, max_tag, jumps), + .default_jump = jump_helper(a, default_case, shd_empty(a), get_abstraction_mem(r.case_)) })); - set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = singleton(final_loaded_value), .mem = bb_mem(bb) }))); + set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_singleton(final_loaded_value), .mem = bb_mem(bb) }))); break; } case StoreFn: { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); - begin_control_t r = begin_control(bb, empty(a)); + begin_control_t r = begin_control(bb, shd_empty(a)); LARRAY(const Node*, literals, max_tag); LARRAY(const Node*, jumps, max_tag); for (size_t tag = 0; tag < max_tag; tag++) { literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { - Node* tag_case = case_(a, empty(a)); + Node* tag_case = case_(a, shd_empty(a)); set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(tag_case) })); - jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); + jumps[tag] = jump_helper(a, tag_case, shd_empty(a), get_abstraction_mem(r.case_)); continue; } - Node* tag_case = case_(a, empty(a)); + Node* tag_case = case_(a, shd_empty(a)); BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); - set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, empty(a))); - jumps[tag] = jump_helper(a, tag_case, empty(a), get_abstraction_mem(r.case_)); + set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_empty(a))); + jumps[tag] = jump_helper(a, tag_case, shd_empty(a), get_abstraction_mem(r.case_)); } // extracted_tag = nptr >> (64 - 2), for example - const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); + const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); - Node* default_case = case_(a, empty(a)); + Node* default_case = case_(a, shd_empty(a)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); set_abstraction_body(r.case_, br_switch(a, (Switch) { .mem = get_abstraction_mem(r.case_), .switch_value = extracted_tag, - .case_values = nodes(a, max_tag, literals), - .case_jumps = nodes(a, max_tag, jumps), - .default_jump = jump_helper(a, default_case, empty(a), get_abstraction_mem(r.case_)) + .case_values = shd_nodes(a, max_tag, literals), + .case_jumps = shd_nodes(a, max_tag, jumps), + .default_jump = jump_helper(a, default_case, shd_empty(a), get_abstraction_mem(r.case_)) })); - set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) }))); + set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); break; } } @@ -212,7 +212,7 @@ static const Node* process(Context* ctx, const Node* old) { if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { return call(a, (Call) { .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, u, rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), - .args = singleton(rewrite_node(&ctx->rewriter, payload.ptr)), + .args = shd_singleton(rewrite_node(&ctx->rewriter, payload.ptr)), .mem = rewrite_node(r, payload.mem) }); } @@ -234,10 +234,10 @@ static const Node* process(Context* ctx, const Node* old) { case PrimOp_TAG: { switch (old->payload.prim_op.op) { case convert_op: { - const Node* old_src = first(old->payload.prim_op.operands); + const Node* old_src = shd_first(old->payload.prim_op.operands); const Type* old_src_t = old_src->type; deconstruct_qualified_type(&old_src_t); - const Type* old_dst_t = first(old->payload.prim_op.type_arguments); + const Type* old_dst_t = shd_first(old->payload.prim_op.type_arguments); if (old_dst_t->tag == PtrType_TAG && old_dst_t->payload.ptr_type.address_space == AsGeneric) { // cast _into_ generic AddressSpace src_as = old_src_t->payload.ptr_type.address_space; @@ -250,11 +250,11 @@ static const Node* process(Context* ctx, const Node* old) { const Node* generic_ptr = gen_reinterpret_cast(bb, ctx->generic_ptr_type, src_ptr); const Node* ptr_mask = size_t_literal(a, (UINT64_MAX >> (uint64_t) (generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr & 0x001111 ... 111 - generic_ptr = gen_primop_e(bb, and_op, empty(a), mk_nodes(a, generic_ptr, ptr_mask)); + generic_ptr = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, generic_ptr, ptr_mask)); const Node* shifted_tag = size_t_literal(a, (tag << (uint64_t) (get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr | 01000000 ... 000 - generic_ptr = gen_primop_e(bb, or_op, empty(a), mk_nodes(a, generic_ptr, shifted_tag)); - return yield_values_and_wrap_in_block(bb, singleton(generic_ptr)); + generic_ptr = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, generic_ptr, shifted_tag)); + return yield_values_and_wrap_in_block(bb, shd_singleton(generic_ptr)); } else if (old_src_t->tag == PtrType_TAG && old_src_t->payload.ptr_type.address_space == AsGeneric) { // cast _from_ generic shd_error("TODO"); diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 17dbeee9e..641dcb1d7 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -18,10 +18,10 @@ static bool should_convert(Context* ctx, const Type* t) { } static void extract_low_hi_halves(BodyBuilder* bb, const Node* src, const Node** lo, const Node** hi) { - *lo = first(bind_instruction(bb, prim_op(bb->arena, - (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, int32_literal(bb->arena, 0))}))); - *hi = first(bind_instruction(bb, prim_op(bb->arena, - (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, int32_literal(bb->arena, 1))}))); + *lo = shd_first(bind_instruction(bb, prim_op(bb->arena, + (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, int32_literal(bb->arena, 0)) }))); + *hi = shd_first(bind_instruction(bb, prim_op(bb->arena, + (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, int32_literal(bb->arena, 1)) }))); } static void extract_low_hi_halves_list(BodyBuilder* bb, Nodes src, const Node** lows, const Node** his) { @@ -56,17 +56,17 @@ static const Node* process(Context* ctx, const Node* node) { LARRAY(const Node*, lows, old_nodes.count); LARRAY(const Node*, his, old_nodes.count); switch(op) { - case add_op: if (should_convert(ctx, first(old_nodes)->type)) { + case add_op: if (should_convert(ctx, shd_first(old_nodes)->type)) { Nodes new_nodes = rewrite_nodes(&ctx->rewriter, old_nodes); // TODO: convert into and then out of unsigned BodyBuilder* bb = begin_block_pure(a); extract_low_hi_halves_list(bb, new_nodes, lows, his); - Nodes low_and_carry = bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_carry_op, .operands = nodes(a, 2, lows)})); - const Node* lo = first(low_and_carry); + Nodes low_and_carry = bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_carry_op, .operands = shd_nodes(a, 2, lows)})); + const Node* lo = shd_first(low_and_carry); // compute the high side, without forgetting the carry bit - const Node* hi = first(bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = nodes(a, 2, his)}))); - hi = first(bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = mk_nodes(a, hi, low_and_carry.nodes[1])}))); - return yield_values_and_wrap_in_block(bb, singleton(tuple_helper(a, mk_nodes(a, lo, hi)))); + const Node* hi = shd_first(bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = shd_nodes(a, 2, his) }))); + hi = shd_first(bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = mk_nodes(a, hi, low_and_carry.nodes[1]) }))); + return yield_values_and_wrap_in_block(bb, shd_singleton(tuple_helper(a, mk_nodes(a, lo, hi)))); } break; default: break; } diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 035604fc5..71dc3d580 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -39,7 +39,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po case ArrType_TAG: { const Type* element_type = pointed_type->payload.arr_type.element_type; - const Node* element_t_size = gen_primop_e(bb, size_of_op, singleton(element_type), empty(a)); + const Node* element_t_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); const Node* new_index = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, index); const Node* physical_offset = gen_primop_ce(bb, mul_op, 2, (const Node* []) {new_index, element_t_size}); @@ -66,7 +66,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po size_t n = selector_value->value; assert(n < member_types.count); - const Node* offset_of = gen_primop_e(bb, offset_of_op, singleton(pointed_type), singleton(uint64_literal(a, n))); + const Node* offset_of = gen_primop_e(bb, offset_of_op, shd_singleton(pointed_type), shd_singleton(uint64_literal(a, n))); ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, offset_of }); pointer_type = ptr_type(a, (PtrType) { @@ -95,7 +95,7 @@ static const Node* lower_ptr_offset(Context* ctx, BodyBuilder* bb, const Type* p // assert(arr_type->tag == ArrType_TAG); // const Type* element_type = arr_type->payload.arr_type.element_type; - const Node* element_t_size = gen_primop_e(bb, size_of_op, singleton(element_type), empty(a)); + const Node* element_t_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); const Node* new_offset = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, offset); const Node* physical_offset = gen_primop_ce(bb, mul_op, 2, (const Node* []) { new_offset, element_t_size}); @@ -134,7 +134,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* result = lower_ptr_offset(ctx, bb, new_base_t, cast_base, rewrite_node(r, lea.offset)); const Type* new_ptr_t = rewrite_node(&ctx->rewriter, old_result_t); const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); - return yield_values_and_wrap_in_block(bb, singleton(cast_result)); + return yield_values_and_wrap_in_block(bb, shd_singleton(cast_result)); } case PtrCompositeElement_TAG: { PtrCompositeElement lea = old->payload.ptr_composite_element; @@ -157,7 +157,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* result = lower_ptr_index(ctx, bb, new_base_t, cast_base, rewrite_node(r, lea.index)); const Type* new_ptr_t = rewrite_node(&ctx->rewriter, old_result_t); const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); - return yield_values_and_wrap_in_block(bb, singleton(cast_result)); + return yield_values_and_wrap_in_block(bb, shd_singleton(cast_result)); } default: break; } diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index e48fc87d0..4b8248944 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -31,7 +31,7 @@ static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node case RecordType_TAG: case ArrType_TAG: case PackType_TAG: { - ptr = gen_lea(bb, ptr, int32_literal(a, 0), singleton(int32_literal(a, 0))); + ptr = gen_lea(bb, ptr, int32_literal(a, 0), shd_singleton(int32_literal(a, 0))); continue; } default: break; @@ -84,7 +84,7 @@ static const Node* process(Context* ctx, const Node* old) { PrimOp payload = old->payload.prim_op; switch (payload.op) { case reinterpret_op: { - const Node* osrc = first(payload.operands); + const Node* osrc = shd_first(payload.operands); const Type* osrc_t = osrc->type; deconstruct_qualified_type(&osrc_t); if (osrc_t->tag == PtrType_TAG && !get_arena_config(a)->address_spaces[osrc_t->payload.ptr_type.address_space].physical) @@ -126,7 +126,7 @@ static const Node* process(Context* ctx, const Node* old) { if (get_arena_config(a)->address_spaces[as].physical) break; Nodes annotations = rewrite_nodes(r, old->payload.global_variable.annotations); - annotations = append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical" })); + annotations = shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Logical" })); Node* new = global_var(ctx->rewriter.dst_module, annotations, rewrite_node(r, old->payload.global_variable.type), old->payload.global_variable.name, as); recreate_decl_body_identity(r, old, new); return new; diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 66b8eb3db..23bee4eac 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -50,29 +50,29 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, payload.count)); const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num_in_bytes)); - begin_loop_helper_t l = begin_loop_helper(bb, empty(a), singleton(uint32_type(a)), singleton( uint32_literal(a, 0))); + begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(uint32_type(a)), shd_singleton(uint32_literal(a, 0))); - const Node* index = first(l.params); + const Node* index = shd_first(l.params); set_value_name(index, "memcpy_i"); Node* loop_case = l.loop_body; BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); - const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, empty(a))); - gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), loaded_word); - const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); + const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, shd_empty(a))); + gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), loaded_word); + const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, uint32_literal(a, 1))); - Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = singleton(next_index) })); - Node* false_case = case_(a, empty(a)); - set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = get_abstraction_mem(false_case), .args = empty(a) })); + Node* true_case = case_(a, shd_empty(a)); + set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); + Node* false_case = case_(a, shd_empty(a)); + set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = get_abstraction_mem(false_case), .args = shd_empty(a) })); set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { .mem = bb_mem(loop_bb), - .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), - .true_jump = jump_helper(a, true_case, empty(a), bb_mem(loop_bb)), - .false_jump = jump_helper(a, false_case, empty(a), bb_mem(loop_bb)), + .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), + .true_jump = jump_helper(a, true_case, shd_empty(a), bb_mem(loop_bb)), + .false_jump = jump_helper(a, false_case, shd_empty(a), bb_mem(loop_bb)), }))); - return yield_values_and_wrap_in_block(bb, empty(a)); + return yield_values_and_wrap_in_block(bb, shd_empty(a)); } case FillBytes_TAG: { FillBytes payload = old->payload.fill_bytes; @@ -97,27 +97,27 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num = rewrite_node(&ctx->rewriter, payload.count); const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); - begin_loop_helper_t l = begin_loop_helper(bb, empty(a), singleton(uint32_type(a)), singleton( uint32_literal(a, 0))); + begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(uint32_type(a)), shd_singleton(uint32_literal(a, 0))); - const Node* index = first(l.params); + const Node* index = shd_first(l.params); set_value_name(index, "memset_i"); Node* loop_case = l.loop_body; BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); - gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, empty(a)), src_value); - const Node* next_index = gen_primop_e(loop_bb, add_op, empty(a), mk_nodes(a, index, uint32_literal(a, 1))); + gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), src_value); + const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, uint32_literal(a, 1))); - Node* true_case = case_(a, empty(a)); - set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = singleton(next_index) })); - Node* false_case = case_(a, empty(a)); - set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = get_abstraction_mem(false_case), .args = empty(a) })); + Node* true_case = case_(a, shd_empty(a)); + set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); + Node* false_case = case_(a, shd_empty(a)); + set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = get_abstraction_mem(false_case), .args = shd_empty(a) })); set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { .mem = bb_mem(loop_bb), - .condition = gen_primop_e(loop_bb, lt_op, empty(a), mk_nodes(a, next_index, num_in_words)), - .true_jump = jump_helper(a, true_case, empty(a), bb_mem(loop_bb)), - .false_jump = jump_helper(a, false_case, empty(a), bb_mem(loop_bb)), + .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), + .true_jump = jump_helper(a, true_case, shd_empty(a), bb_mem(loop_bb)), + .false_jump = jump_helper(a, false_case, shd_empty(a), bb_mem(loop_bb)), }))); - return yield_values_and_wrap_in_block(bb, empty(a)); + return yield_values_and_wrap_in_block(bb, shd_empty(a)); } default: break; } diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 2eced9181..e78edfa54 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -19,18 +19,18 @@ static const Node* process(Context* ctx, const Node* old) { case PrimOp_TAG: { switch (old->payload.prim_op.op) { case size_of_op: { - const Type* t = rewrite_node(&ctx->rewriter, first(old->payload.prim_op.type_arguments)); + const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); TypeMemLayout layout = get_mem_layout(a, t); return int_literal(a, (IntLiteral) {.width = a->config.memory.ptr_size, .is_signed = false, .value = layout.size_in_bytes}); } case align_of_op: { - const Type* t = rewrite_node(&ctx->rewriter, first(old->payload.prim_op.type_arguments)); + const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); TypeMemLayout layout = get_mem_layout(a, t); return int_literal(a, (IntLiteral) {.width = a->config.memory.ptr_size, .is_signed = false, .value = layout.alignment_in_bytes}); } case offset_of_op: { - const Type* t = rewrite_node(&ctx->rewriter, first(old->payload.prim_op.type_arguments)); - const Node* n = rewrite_node(&ctx->rewriter, first(old->payload.prim_op.operands)); + const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); + const Node* n = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.operands)); const IntLiteral* literal = resolve_to_int_literal(n); assert(literal); t = get_maybe_nominal_type_body(t); diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 9e4814cf7..237280d43 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -21,10 +21,10 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { BodyBuilder* bb = begin_block_pure(a); const Node* nul = gen_reinterpret_cast(bb, t, uint64_literal(a, 0)); - Node* decl = constant(ctx->rewriter.dst_module, singleton(annotation(a, (Annotation) { + Node* decl = constant(ctx->rewriter.dst_module, shd_singleton(annotation(a, (Annotation) { .name = "Generated", })), t, format_string_interned(a, "nullptr_%s", name_type_safe(a, t))); - decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(nul)); + decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(nul)); const Node* ref = ref_decl_helper(a, decl); shd_dict_insert(const Type*, const Node*, ctx->map, t, ref); return ref; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 8e67a0902..bf5eeddf7 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -60,7 +60,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* zero = size_t_literal(a, 0); switch (element_type->tag) { case Bool_TAG: { - const Node* logical_ptr = gen_lea(bb, arr, zero, singleton(address)); + const Node* logical_ptr = gen_lea(bb, arr, zero, shd_singleton(address)); const Node* value = gen_load(bb, logical_ptr); return gen_primop_ce(bb, neq_op, 2, (const Node*[]) {value, int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size })}); } @@ -82,13 +82,13 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { - const Node* word = gen_load(bb, gen_lea(bb, arr, zero, singleton(offset))); + const Node* word = gen_load(bb, gen_lea(bb, arr, zero, shd_singleton(offset))); word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded - word = first(gen_primop(bb, lshift_op, empty(a), mk_nodes(a, word, shift))); // shift it - acc = gen_primop_e(bb, or_op, empty(a), mk_nodes(a, acc, word)); + word = shd_first(gen_primop(bb, lshift_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it + acc = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, acc, word)); - offset = first(gen_primop(bb, add_op, empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); - shift = first(gen_primop(bb, add_op, empty(a), mk_nodes(a, shift, word_bitwidth))); + offset = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); + shift = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); } if (config->printf_trace.memory_accesses) { AddressSpace as = get_unqualified_type(arr->type)->payload.ptr_type.address_space; @@ -114,11 +114,11 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type Nodes member_types = compound_type->payload.record_type.members; LARRAY(const Node*, loaded, member_types.count); for (size_t i = 0; i < member_types.count; i++) { - const Node* field_offset = gen_primop_e(bb, offset_of_op, singleton(element_type), singleton(size_t_literal(a, i))); - const Node* adjusted_offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, address, field_offset)); + const Node* field_offset = gen_primop_e(bb, offset_of_op, shd_singleton(element_type), shd_singleton(size_t_literal(a, i))); + const Node* adjusted_offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, address, field_offset)); loaded[i] = gen_deserialisation(ctx, bb, member_types.nodes[i], arr, adjusted_offset); } - return composite_helper(a, element_type, nodes(a, member_types.count, loaded)); + return composite_helper(a, element_type, shd_nodes(a, member_types.count, loaded)); } case ArrType_TAG: case PackType_TAG: { @@ -134,9 +134,9 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* offset = address; for (size_t i = 0; i < components_count; i++) { components[i] = gen_deserialisation(ctx, bb, component_type, arr, offset); - offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, singleton(component_type), empty(a)))); + offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, shd_singleton(component_type), shd_empty(a)))); } - return composite_helper(a, element_type, nodes(a, components_count, components)); + return composite_helper(a, element_type, shd_nodes(a, components_count, components)); } default: shd_error("TODO"); } @@ -148,7 +148,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* zero = size_t_literal(a, 0); switch (element_type->tag) { case Bool_TAG: { - const Node* logical_ptr = gen_lea(bb, arr, zero, singleton(address)); + const Node* logical_ptr = gen_lea(bb, arr, zero, shd_singleton(address)); const Node* zero_b = int_literal(a, (IntLiteral) { .value = 1, .width = a->config.memory.word_size }); const Node* one_b = int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size }); const Node* int_value = gen_primop_ce(bb, select_op, 3, (const Node*[]) { value, one_b, zero_b }); @@ -158,7 +158,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element case PtrType_TAG: switch (element_type->payload.ptr_type.address_space) { case AsGlobal: { const Type* ptr_int_t = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false }); - const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, singleton(ptr_int_t), singleton(value)); + const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, shd_singleton(ptr_int_t), shd_singleton(value)); return gen_serialisation(ctx, bb, ptr_int_t, arr, address, unsigned_value); } default: shd_error("TODO") @@ -186,12 +186,12 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element // word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded }*/ const Node* word = value; - word = first(gen_primop(bb, rshift_logical_op, empty(a), mk_nodes(a, word, shift))); // shift it + word = shd_first(gen_primop(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it word = gen_conversion(bb, int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }), word); // widen/truncate the word we want to store - gen_store(bb, gen_lea(bb, arr, zero, singleton(offset)), word); + gen_store(bb, gen_lea(bb, arr, zero, shd_singleton(offset)), word); - offset = first(gen_primop(bb, add_op, empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); - shift = first(gen_primop(bb, add_op, empty(a), mk_nodes(a, shift, word_bitwidth))); + offset = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); + shift = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); } if (config->printf_trace.memory_accesses) { AddressSpace as = get_unqualified_type(arr->type)->payload.ptr_type.address_space; @@ -205,15 +205,15 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element } case Float_TAG: { const Type* unsigned_int_t = int_type(a, (Int) {.width = float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); - const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, singleton(unsigned_int_t), singleton(value)); + const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, shd_singleton(unsigned_int_t), shd_singleton(value)); return gen_serialisation(ctx, bb, unsigned_int_t, arr, address, unsigned_value); } case RecordType_TAG: { Nodes member_types = element_type->payload.record_type.members; for (size_t i = 0; i < member_types.count; i++) { - const Node* extracted_value = prim_op(a, (PrimOp) { .op = extract_op, .operands = mk_nodes(a, value, int32_literal(a, i)), .type_arguments = empty(a) }); - const Node* field_offset = gen_primop_e(bb, offset_of_op, singleton(element_type), singleton(size_t_literal(a, i))); - const Node* adjusted_offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, address, field_offset)); + const Node* extracted_value = prim_op(a, (PrimOp) { .op = extract_op, .operands = mk_nodes(a, value, int32_literal(a, i)), .type_arguments = shd_empty(a) }); + const Node* field_offset = gen_primop_e(bb, offset_of_op, shd_singleton(element_type), shd_singleton(size_t_literal(a, i))); + const Node* adjusted_offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, address, field_offset)); gen_serialisation(ctx, bb, member_types.nodes[i], arr, adjusted_offset, extracted_value); } return; @@ -236,8 +236,8 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Type* component_type = get_fill_type_element_type(element_type); const Node* offset = address; for (size_t i = 0; i < components_count; i++) { - gen_serialisation(ctx, bb, component_type, arr, offset, gen_extract(bb, value, singleton(int32_literal(a, i)))); - offset = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, singleton(component_type), empty(a)))); + gen_serialisation(ctx, bb, component_type, arr, offset, gen_extract(bb, value, shd_singleton(int32_literal(a, i)))); + offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, shd_singleton(component_type), shd_empty(a)))); } return; } @@ -265,10 +265,10 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Type* input_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && is_addr_space_uniform(a, as) && false), .type = element_type }); const Node* value_param = ser ? param(a, input_value_t, "value") : NULL; - Nodes params = ser ? mk_nodes(a, address_param, value_param) : singleton(address_param); + Nodes params = ser ? mk_nodes(a, address_param, value_param) : shd_singleton(address_param); const Type* return_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && is_addr_space_uniform(a, as)), .type = element_type }); - Nodes return_ts = ser ? empty(a) : singleton(return_value_t); + Nodes return_ts = ser ? shd_empty(a) : shd_singleton(return_value_t); String name = shd_format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", get_address_space_name(as), uniform_address ? "uniform" : "varying", name_type_safe(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); @@ -278,11 +278,11 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { gen_serialisation(ctx, bb, element_type, base, address_param, value_param); - set_abstraction_body(fun, finish_body_with_return(bb, empty(a))); + set_abstraction_body(fun, finish_body_with_return(bb, shd_empty(a))); } else { const Node* loaded_value = gen_deserialisation(ctx, bb, element_type, base, address_param); assert(loaded_value); - set_abstraction_body(fun, finish_body_with_return(bb, singleton(loaded_value))); + set_abstraction_body(fun, finish_body_with_return(bb, shd_singleton(loaded_value))); } return fun; } @@ -303,7 +303,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, false, ptr_type->payload.ptr_type.address_space); - Nodes results = gen_call(bb, fn_addr_helper(a, fn), singleton(pointer_as_offset)); + Nodes results = gen_call(bb, fn_addr_helper(a, fn), shd_singleton(pointer_as_offset)); return yield_values_and_wrap_in_block(bb, results); } case Store_TAG: { @@ -321,7 +321,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* value = rewrite_node(&ctx->rewriter, payload.value); gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, pointer_as_offset, value)); - return yield_values_and_wrap_in_block(bb, empty(a)); + return yield_values_and_wrap_in_block(bb, shd_empty(a)); } case StackAlloc_TAG: shd_error("This needs to be lowered (see setup_stack_frames.c)") case PtrType_TAG: { @@ -380,7 +380,7 @@ static Nodes collect_globals(Context* ctx, AddressSpace as) { members_count++; } - return nodes(a, members_count, collected); + return shd_nodes(a, members_count, collected); } /// Collects all global variables in a specific AS, and creates a record type for them. @@ -389,7 +389,7 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect Module* m = ctx->rewriter.dst_module; String as_name = get_address_space_name(as); - Node* global_struct_t = nominal_type(m, singleton(annotation(a, (Annotation) { .name = "Generated" })), shd_format_string_arena(a->arena, "globals_physical_%s_t", as_name)); + Node* global_struct_t = nominal_type(m, shd_singleton(annotation(a, (Annotation) { .name = "Generated" })), shd_format_string_arena(a->arena, "globals_physical_%s_t", as_name)); LARRAY(String, member_names, collected.count); LARRAY(const Type*, member_tys, collected.count); @@ -409,15 +409,15 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect // we need to compute the actual pointer by getting the offset and dividing it // after lower_memory_layout, optimisations will eliminate this and resolve to a value BodyBuilder* bb = begin_block_pure(a); - const Node* offset = gen_primop_e(bb, offset_of_op, singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), singleton(size_t_literal(a, i))); - new_address->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(offset)); + const Node* offset = gen_primop_e(bb, offset_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_singleton(size_t_literal(a, i))); + new_address->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(offset)); register_processed(&ctx->rewriter, decl, new_address); } const Type* record_t = record_type(a, (RecordType) { - .members = nodes(a, collected.count, member_tys), - .names = strings(a, collected.count, member_names) + .members = shd_nodes(a, collected.count, member_tys), + .names = shd_strings(a, collected.count, member_names) }); //return record_t; @@ -461,22 +461,22 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { const Node* global_struct_t = make_record_type(ctx, as, ctx->collected[as]); - Nodes annotations = singleton(annotation(a, (Annotation) { .name = "Generated" })); + Nodes annotations = shd_singleton(annotation(a, (Annotation) { .name = "Generated" })); // compute the size BodyBuilder* bb = begin_block_pure(a); - const Node* size_of = gen_primop_e(bb, size_of_op, singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), empty(a)); + const Node* size_of = gen_primop_e(bb, size_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_empty(a)); const Node* size_in_words = bytes_to_words(bb, size_of); Node* constant_decl = constant(m, annotations, ptr_size_type, format_string_interned(a, "memory_%s_size", as_name)); - constant_decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, singleton(size_in_words)); + constant_decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(size_in_words)); const Type* words_array_type = arr_type(a, (ArrType) { .element_type = word_type, .size = ref_decl_helper(a, constant_decl) }); - Node* words_array = global_var(m, append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical"})), words_array_type, shd_format_string_arena(a->arena, "memory_%s", as_name), as); + Node* words_array = global_var(m, shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Logical" })), words_array_type, shd_format_string_arena(a->arena, "memory_%s", as_name), as); *get_emulated_as_word_array(ctx, as) = ref_decl_helper(a, words_array); } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 176b1e6ac..057ff4afe 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -38,15 +38,15 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { const Type* qualified_t = qualified_type(a, (QualifiedType) { .is_uniform = false, .type = element_type }); const Node* value_param = push ? param(a, qualified_t, "value") : NULL; - Nodes params = push ? singleton(value_param) : empty(a); - Nodes return_ts = push ? empty(a) : singleton(qualified_t); + Nodes params = push ? shd_singleton(value_param) : shd_empty(a); + Nodes return_ts = push ? shd_empty(a) : shd_singleton(qualified_t); String name = shd_format_string_arena(a->arena, "generated_%s_%s", push ? "push" : "pop", name_type_safe(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); - const Node* element_size = gen_primop_e(bb, size_of_op, singleton(element_type), empty(a)); + const Node* element_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); element_size = gen_conversion(bb, uint32_type(a), element_size); // TODO somehow annotate the uniform guys as uniform @@ -58,7 +58,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { if (!push) // for pop, we decrease the stack size first stack_size = gen_primop_ce(bb, sub_op, 2, (const Node* []) { stack_size, element_size}); - const Node* addr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); + const Node* addr = gen_lea(bb, ctx->stack, int32_literal(a, 0), shd_singleton(stack_size)); assert(get_unqualified_type(addr->type)->tag == PtrType_TAG); AddressSpace addr_space = get_unqualified_type(addr->type)->payload.ptr_type.address_space; @@ -76,15 +76,15 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { // store updated stack size gen_store(bb, stack_pointer, stack_size); if (ctx->config->printf_trace.stack_size) { - gen_debug_printf(bb, name, empty(a)); - gen_debug_printf(bb, "stack size after: %d\n", singleton(stack_size)); + gen_debug_printf(bb, name, shd_empty(a)); + gen_debug_printf(bb, "stack size after: %d\n", shd_singleton(stack_size)); } if (push) { - set_abstraction_body(fun, finish_body_with_return(bb, empty(a))); + set_abstraction_body(fun, finish_body_with_return(bb, shd_empty(a))); } else { assert(popped_value); - set_abstraction_body(fun, finish_body_with_return(bb, singleton(popped_value))); + set_abstraction_body(fun, finish_body_with_return(bb, shd_singleton(popped_value))); } return fun; } @@ -115,7 +115,7 @@ static const Node* process_node(Context* ctx, const Node* old) { GetStackSize payload = old->payload.get_stack_size; BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* sp = gen_load(bb, ctx->stack_pointer); - return yield_values_and_wrap_in_block(bb, singleton(sp)); + return yield_values_and_wrap_in_block(bb, shd_singleton(sp)); } case SetStackSize_TAG: { assert(ctx->stack); @@ -123,7 +123,7 @@ static const Node* process_node(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* val = rewrite_node(r, old->payload.set_stack_size.value); gen_store(bb, ctx->stack_pointer, val); - return yield_values_and_wrap_in_block(bb, empty(a)); + return yield_values_and_wrap_in_block(bb, shd_empty(a)); } case GetStackBaseAddr_TAG: { assert(ctx->stack); @@ -131,11 +131,11 @@ static const Node* process_node(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* stack_pointer = ctx->stack_pointer; const Node* stack_size = gen_load(bb, stack_pointer); - const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), singleton(stack_size)); + const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), shd_singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { - gen_debug_printf(bb, "trace: stack_size=%d\n", singleton(stack_size)); + gen_debug_printf(bb, "trace: stack_size=%d\n", shd_singleton(stack_size)); } - return yield_values_and_wrap_in_block(bb, singleton(stack_base_ptr)); + return yield_values_and_wrap_in_block(bb, shd_singleton(stack_base_ptr)); } case PushStack_TAG:{ assert(ctx->stack); @@ -146,10 +146,10 @@ static const Node* process_node(Context* ctx, const Node* old) { bool push = true; const Node* fn = gen_fn(ctx, element_type, push); - Nodes args = singleton(rewrite_node(&ctx->rewriter, old->payload.push_stack.value)); + Nodes args = shd_singleton(rewrite_node(&ctx->rewriter, old->payload.push_stack.value)); gen_call(bb, fn_addr_helper(a, fn), args); - return yield_values_and_wrap_in_block(bb, empty(a)); + return yield_values_and_wrap_in_block(bb, shd_empty(a)); } case PopStack_TAG: { assert(ctx->stack); @@ -160,7 +160,7 @@ static const Node* process_node(Context* ctx, const Node* old) { bool push = false; const Node* fn = gen_fn(ctx, element_type, push); - Nodes results = gen_call(bb, fn_addr_helper(a, fn), empty(a)); + Nodes results = gen_call(bb, fn_addr_helper(a, fn), shd_empty(a)); assert(results.count == 1); return yield_values_and_wrap_in_block(bb, results); @@ -202,7 +202,7 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { Node* stack_decl = global_var(dst, annotations, stack_arr_type, "stack", AsPrivate); // Pointers into those arrays - Node* stack_ptr_decl = global_var(dst, append_nodes(a, annotations, annotation(a, (Annotation) { .name = "Logical" })), stack_counter_t, "stack_ptr", AsPrivate); + Node* stack_ptr_decl = global_var(dst, shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Logical" })), stack_counter_t, "stack_ptr", AsPrivate); stack_ptr_decl->payload.global_variable.init = uint32_literal(a, 0); ctx.stack = ref_decl_helper(a, stack_decl); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index d7b184710..8c955b247 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -55,14 +55,14 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co Nodes element_types = get_composite_type_element_types(t); LARRAY(const Node*, elements, element_types.count); for (size_t i = 0; i < element_types.count; i++) { - const Node* e = gen_extract(bb, param, singleton(uint32_literal(a, i))); + const Node* e = gen_extract(bb, param, shd_singleton(uint32_literal(a, i))); elements[i] = build_subgroup_first(ctx, bb, scope, e); } - return composite_helper(a, original_t, nodes(a, element_types.count, elements)); + return composite_helper(a, original_t, shd_nodes(a, element_types.count, elements)); } case Type_Int_TAG: { if (t->payload.int_type.width == IntTy64) { - const Node* hi = gen_primop_e(bb, rshift_logical_op, empty(a), mk_nodes(a, param, int32_literal(a, 32))); + const Node* hi = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, param, int32_literal(a, 32))); hi = convert_int_zero_extend(bb, int32_type(a), hi); const Node* lo = convert_int_zero_extend(bb, int32_type(a), param); hi = build_subgroup_first(ctx, bb, scope, hi); @@ -70,8 +70,8 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co const Node* it = int_type(a, (Int) { .width = IntTy64, .is_signed = t->payload.int_type.is_signed }); hi = convert_int_zero_extend(bb, it, hi); lo = convert_int_zero_extend(bb, it, lo); - hi = gen_primop_e(bb, lshift_op, empty(a), mk_nodes(a, hi, int32_literal(a, 32))); - return gen_primop_e(bb, or_op, empty(a), mk_nodes(a, lo, hi)); + hi = gen_primop_e(bb, lshift_op, shd_empty(a), mk_nodes(a, hi, int32_literal(a, 32))); + return gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, lo, hi)); } break; } @@ -90,7 +90,7 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* scope, const Node* const Node* result = generate(ctx, bb, scope, t, param); if (result) { set_abstraction_body(fn, finish_body(bb, fn_ret(a, (Return) { - .args = singleton(result), + .args = shd_singleton(result), .mem = bb_mem(bb), }))); return; @@ -118,13 +118,13 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod fn = *found; else { const Node* src_param = param(a, qualified_type_helper(t, false), "src"); - fn = function(m, singleton(src_param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), - mk_nodes(a, annotation(a, (Annotation) { .name = "Generated"}), annotation(a, (Annotation) { .name = "Leaf" })), singleton(qualified_type_helper(t, true))); + fn = function(m, shd_singleton(src_param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), + mk_nodes(a, annotation(a, (Annotation) { .name = "Generated"}), annotation(a, (Annotation) { .name = "Leaf" })), shd_singleton(qualified_type_helper(t, true))); shd_dict_insert(const Node*, Node*, ctx->fns, t, fn); build_fn_body(ctx, fn, scope, src_param, t); } - return first(gen_call(bb, fn_addr_helper(a, fn), singleton(src))); + return shd_first(gen_call(bb, fn_addr_helper(a, fn), shd_singleton(src))); } static const Node* process(Context* ctx, const Node* node) { @@ -135,8 +135,8 @@ static const Node* process(Context* ctx, const Node* node) { ExtInstr payload = node->payload.ext_instr; if (strcmp(payload.set, "spirv.core") == 0 && payload.opcode == SpvOpGroupNonUniformBroadcastFirst) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - return yield_values_and_wrap_in_block(bb, singleton( - build_subgroup_first(ctx, bb, rewrite_node(r, payload.operands.nodes[0]), rewrite_node(r, payload.operands.nodes[1])))); + return yield_values_and_wrap_in_block(bb, shd_singleton( + build_subgroup_first(ctx, bb, rewrite_node(r, payload.operands.nodes[0]), rewrite_node(r, payload.operands.nodes[1])))); } } default: break; diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 3f6a52299..011b9951c 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -26,10 +26,10 @@ static const Node* process(Context* ctx, const Node* node) { shd_dict_clear(functx.rewriter.map); register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); - Node* post_prelude = basic_block(a, empty(a), "post-prelude"); + Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); - set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, empty(a), bb_mem(functx.bb)))); + set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, shd_empty(a), bb_mem(functx.bb)))); shd_destroy_dict(functx.rewriter.map); } return newfun; diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 8fbbc39b7..357d2144a 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -90,7 +90,7 @@ static const Node* generate_default_fallback_case(Context* ctx, bool in_if, cons for (size_t i = 0; i < ctx->yield_types.count; i++) undefs[i] = undef(a, (Undef) { .type = ctx->yield_types.nodes[i] }); Node* c = case_(a, empty(a)); - set_abstraction_body(c, finish_body(bb, gen_yield(ctx, in_if, nodes(a, ctx->yield_types.count, undefs)))); + set_abstraction_body(c, finish_body(bb, gen_yield(ctx, in_if, shd_nodes(a, ctx->yield_types.count, undefs)))); return c; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index b62cc6ed6..80b7a95a4 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -74,12 +74,12 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { IrArena* a = ctx->rewriter.dst_arena; // For the lifted entry point, we keep _all_ annotations Nodes rewritten_params = recreate_params(&ctx2.rewriter, old->payload.fun.params); - Node* new_entry_pt = function(ctx2.rewriter.dst_module, rewritten_params, old->payload.fun.name, rewrite_nodes(&ctx2.rewriter, old->payload.fun.annotations), nodes(a, 0, NULL)); + Node* new_entry_pt = function(ctx2.rewriter.dst_module, rewritten_params, old->payload.fun.name, rewrite_nodes(&ctx2.rewriter, old->payload.fun.annotations), shd_nodes(a, 0, NULL)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_entry_pt)); - gen_call(bb, fn_addr_helper(a, ctx->init_fn), empty(a)); - gen_call(bb, access_decl(&ctx->rewriter, "builtin_init_scheduler"), empty(a)); + gen_call(bb, fn_addr_helper(a, ctx->init_fn), shd_empty(a)); + gen_call(bb, access_decl(&ctx->rewriter, "builtin_init_scheduler"), shd_empty(a)); // shove the arguments on the stack for (size_t i = rewritten_params.count - 1; i < rewritten_params.count; i--) { @@ -90,16 +90,16 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { const Node* jump_fn = access_decl(&ctx->rewriter, "builtin_fork"); const Node* fn_addr = uint32_literal(a, get_fn_ptr(ctx, old)); // fn_addr = gen_conversion(bb, lowered_fn_type(ctx), fn_addr); - gen_call(bb, jump_fn, singleton(fn_addr)); + gen_call(bb, jump_fn, shd_singleton(fn_addr)); if (!*ctx->top_dispatcher_fn) { - *ctx->top_dispatcher_fn = function(ctx->rewriter.dst_module, nodes(a, 0, NULL), "top_dispatcher", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), nodes(a, 0, NULL)); + *ctx->top_dispatcher_fn = function(ctx->rewriter.dst_module, shd_nodes(a, 0, NULL), "top_dispatcher", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), shd_nodes(a, 0, NULL)); } - gen_call(bb, fn_addr_helper(a, *ctx->top_dispatcher_fn), empty(a)); + gen_call(bb, fn_addr_helper(a, *ctx->top_dispatcher_fn), shd_empty(a)); set_abstraction_body(new_entry_pt, finish_body(bb, fn_ret(a, (Return) { - .args = nodes(a, 0, NULL), + .args = shd_nodes(a, 0, NULL), .mem = bb_mem(bb), }))); } @@ -123,7 +123,7 @@ static const Node* process(Context* ctx, const Node* old) { if (old->payload.fun.body) { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); if (entry_point_annotation) { - gen_call(bb, fn_addr_helper(a, ctx2.init_fn), empty(a)); + gen_call(bb, fn_addr_helper(a, ctx2.init_fn), shd_empty(a)); } register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); @@ -137,12 +137,12 @@ static const Node* process(Context* ctx, const Node* old) { assert(ctx->config->dynamic_scheduling && "Dynamic scheduling is disabled, but we encountered a non-leaf function"); Nodes new_annotations = rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); - new_annotations = append_nodes(a, new_annotations, annotation_value(a, (AnnotationValue) { .name = "FnId", .value = lower_fn_addr(ctx, old) })); - new_annotations = append_nodes(a, new_annotations, annotation(a, (Annotation) { .name = "Leaf" })); + new_annotations = shd_nodes_append(a, new_annotations, annotation_value(a, (AnnotationValue) { .name = "FnId", .value = lower_fn_addr(ctx, old) })); + new_annotations = shd_nodes_append(a, new_annotations, annotation(a, (Annotation) { .name = "Leaf" })); String new_name = shd_format_string_arena(a->arena, "%s_indirect", old->payload.fun.name); - Node* fun = function(ctx->rewriter.dst_module, nodes(a, 0, NULL), new_name, filter_out_annotation(a, new_annotations, "EntryPoint"), nodes(a, 0, NULL)); + Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, 0, NULL), new_name, filter_out_annotation(a, new_annotations, "EntryPoint"), shd_nodes(a, 0, NULL)); register_processed(&ctx->rewriter, old, fun); if (entry_point_annotation) @@ -156,7 +156,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* popped = gen_pop_value_stack(bb, new_param_type); // TODO use the uniform stack instead ? or no ? if (is_qualified_type_uniform(old_param->type)) - popped = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = empty(a), .operands = singleton(popped) }); + popped = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = shd_empty(a), .operands = shd_singleton(popped) }); if (old_param->payload.param.name) set_value_name((Node*) popped, old_param->payload.param.name); register_processed(&ctx->rewriter, old_param, popped); @@ -191,7 +191,7 @@ static const Node* process(Context* ctx, const Node* old) { break; case ShadyOpCreateJoinPoint: callee_name = "builtin_create_control_point"; - args = change_node_at_index(a, args, 0, prim_op_helper(a, convert_op, singleton(uint32_type(a)), singleton(args.nodes[0]))); + args = shd_change_node_at_index(a, args, 0, prim_op_helper(a, convert_op, shd_singleton(uint32_type(a)), shd_singleton(args.nodes[0]))); break; } return call(a, (Call) { @@ -211,8 +211,8 @@ static const Node* process(Context* ctx, const Node* old) { const Node* target = rewrite_node(&ctx->rewriter, payload.callee); target = gen_conversion(bb, uint32_type(a), target); - gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), singleton(target)); - return finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) })); + gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); + return finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) })); } case Join_TAG: { Join payload = old->payload.join; @@ -227,13 +227,13 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, old->payload.join.args)); - const Node* jp_payload = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 2))); + const Node* jp_payload = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, int32_literal(a, 2))); gen_push_value_stack(bb, jp_payload); - const Node* dst = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 1))); - const Node* tree_node = gen_primop_e(bb, extract_op, empty(a), mk_nodes(a, jp, int32_literal(a, 0))); + const Node* dst = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, int32_literal(a, 1))); + const Node* tree_node = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, int32_literal(a, 0))); gen_call(bb, access_decl(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); - return finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) })); + return finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) })); } case PtrType_TAG: { const Node* pointee = old->payload.ptr_type.pointed_type; @@ -247,7 +247,7 @@ static const Node* process(Context* ctx, const Node* old) { Control payload = old->payload.control; if (is_control_static(ctx->uses, old)) { // const Node* old_inside = old->payload.control.inside; - const Node* old_jp = first(get_abstraction_params(payload.inside)); + const Node* old_jp = shd_first(get_abstraction_params(payload.inside)); assert(old_jp->tag == Param_TAG); const Node* old_jp_type = old_jp->type; deconstruct_qualified_type(&old_jp_type); @@ -257,7 +257,7 @@ static const Node* process(Context* ctx, const Node* old) { }); const Node* new_jp = param(a, qualified_type_helper(new_jp_type, true), old_jp->payload.param.name); register_processed(&ctx->rewriter, old_jp, new_jp); - Node* new_control_case = case_(a, singleton(new_jp)); + Node* new_control_case = case_(a, shd_singleton(new_jp)); register_processed(r, payload.inside, new_control_case); set_abstraction_body(new_control_case, rewrite_node(&ctx->rewriter, get_abstraction_body(payload.inside))); // BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); @@ -292,19 +292,19 @@ void generate_top_level_dispatch_fn(Context* ctx) { // if (count_iterations) // iterations_count_param = param(a, qualified_type(a, (QualifiedType) { .type = int32_type(a), .is_uniform = true }), "iterations"); - // Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : nodes(a, 0, NULL)); + // Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : shd_nodes(a, 0, NULL)); // gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a), loop_inside_case); - begin_loop_helper_t l = begin_loop_helper(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_type(a)) : empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a)); + begin_loop_helper_t l = begin_loop_helper(dispatcher_body_builder, shd_empty(a), count_iterations ? shd_singleton(int32_type(a)) : shd_empty(a), count_iterations ? shd_singleton(int32_literal(a, 0)) : shd_empty(a)); Node* loop_inside_case = l.loop_body; if (count_iterations) - iterations_count_param = first(l.params); + iterations_count_param = shd_first(l.params); BodyBuilder* loop_body_builder = begin_body_with_mem(a, get_abstraction_mem(loop_inside_case)); const Node* next_function = gen_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); const Node* get_active_branch_fn = access_decl(&ctx->rewriter, "builtin_get_active_branch"); - const Node* next_mask = first(gen_call(loop_body_builder, get_active_branch_fn, empty(a))); + const Node* next_mask = shd_first(gen_call(loop_body_builder, get_active_branch_fn, shd_empty(a))); const Node* local_id = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); - const Node* should_run = gen_primop_e(loop_body_builder, mask_is_thread_active_op, empty(a), mk_nodes(a, next_mask, local_id)); + const Node* should_run = gen_primop_e(loop_body_builder, mask_is_thread_active_op, shd_empty(a), mk_nodes(a, next_mask, local_id)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); @@ -316,25 +316,25 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* iteration_count_plus_one = NULL; if (count_iterations) - iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, 1))); + iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, shd_empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, 1))); if (ctx->config->shader_diagnostics.max_top_iterations > 0) { - begin_control_t c = begin_control(loop_body_builder, empty(a)); - const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); - Node* bail_case = case_(a, empty(a)); - const Node* break_terminator = join(a, (Join) { .args = empty(a), .join_point = l.break_jp, .mem = get_abstraction_mem(bail_case) }); + begin_control_t c = begin_control(loop_body_builder, shd_empty(a)); + const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, shd_empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); + Node* bail_case = case_(a, shd_empty(a)); + const Node* break_terminator = join(a, (Join) { .args = shd_empty(a), .join_point = l.break_jp, .mem = get_abstraction_mem(bail_case) }); set_abstraction_body(bail_case, break_terminator); - Node* proceed_case = case_(a, empty(a)); + Node* proceed_case = case_(a, shd_empty(a)); set_abstraction_body(proceed_case, join(a, (Join) { .join_point = c.jp, .mem = get_abstraction_mem(proceed_case), - .args = empty(a), + .args = shd_empty(a), })); set_abstraction_body(c.case_, branch(a, (Branch) { .mem = get_abstraction_mem(c.case_), .condition = bail_condition, - .true_jump = jump_helper(a, bail_case, empty(a), get_abstraction_mem(c.case_)), - .false_jump = jump_helper(a, proceed_case, empty(a), get_abstraction_mem(c.case_)), + .true_jump = jump_helper(a, bail_case, shd_empty(a), get_abstraction_mem(c.case_)), + .false_jump = jump_helper(a, proceed_case, shd_empty(a), get_abstraction_mem(c.case_)), })); // gen_if(loop_body_builder, empty(a), bail_condition, bail_case, NULL); } @@ -343,33 +343,33 @@ void generate_top_level_dispatch_fn(Context* ctx) { struct List* jumps = shd_new_list(const Node*); // Build 'zero' case (exits the program) - Node* zero_case_lam = case_(a, nodes(a, 0, NULL)); - Node* zero_if_true_lam = case_(a, empty(a)); + Node* zero_case_lam = case_(a, shd_nodes(a, 0, NULL)); + Node* zero_if_true_lam = case_(a, shd_empty(a)); BodyBuilder* zero_if_case_builder = begin_body_with_mem(a, get_abstraction_mem(zero_if_true_lam)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } - set_abstraction_body(zero_if_true_lam, finish_body_with_join(zero_if_case_builder, l.break_jp, empty(a))); + set_abstraction_body(zero_if_true_lam, finish_body_with_join(zero_if_case_builder, l.break_jp, shd_empty(a))); - Node* zero_if_false = case_(a, empty(a)); + Node* zero_if_false = case_(a, shd_empty(a)); BodyBuilder* zero_false_builder = begin_body_with_mem(a, get_abstraction_mem(zero_if_false)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, zero_false_builder, BuiltinSubgroupId); gen_debug_printf(zero_false_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } - set_abstraction_body(zero_if_false, finish_body_with_join(zero_false_builder, l.continue_jp, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); + set_abstraction_body(zero_if_false, finish_body_with_join(zero_false_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); set_abstraction_body(zero_case_lam, branch(a, (Branch) { .mem = get_abstraction_mem(zero_case_lam), .condition = should_run, - .true_jump = jump_helper(a, zero_if_true_lam, empty(a), get_abstraction_mem(zero_case_lam)), - .false_jump = jump_helper(a, zero_if_false, empty(a), get_abstraction_mem(zero_case_lam)), + .true_jump = jump_helper(a, zero_if_true_lam, shd_empty(a), get_abstraction_mem(zero_case_lam)), + .false_jump = jump_helper(a, zero_if_false, shd_empty(a), get_abstraction_mem(zero_case_lam)), })); const Node* zero_lit = uint64_literal(a, 0); shd_list_append(const Node*, literals, zero_lit); - const Node* zero_jump = jump_helper(a, zero_case_lam, empty(a), bb_mem(loop_body_builder)); + const Node* zero_jump = jump_helper(a, zero_case_lam, shd_empty(a), bb_mem(loop_body_builder)); shd_list_append(const Node*, jumps, zero_jump); Nodes old_decls = get_module_declarations(ctx->rewriter.src_module); @@ -381,55 +381,55 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* fn_lit = uint32_literal(a, get_fn_ptr(ctx, decl)); - Node* if_true_case = case_(a, empty(a)); + Node* if_true_case = case_(a, shd_empty(a)); BodyBuilder* if_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } - gen_call(if_builder, fn_addr_helper(a, rewrite_node(&ctx->rewriter, decl)), empty(a)); - set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, count_iterations ? singleton(iteration_count_plus_one) : empty(a))); + gen_call(if_builder, fn_addr_helper(a, rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); + set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); - Node* if_false = case_(a, empty(a)); + Node* if_false = case_(a, shd_empty(a)); set_abstraction_body(if_false, join(a, (Join) { .mem = get_abstraction_mem(if_false), .join_point = l.continue_jp, - .args = count_iterations ? singleton(iteration_count_plus_one) : empty(a) + .args = count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a) })); - Node* fn_case = case_(a, nodes(a, 0, NULL)); + Node* fn_case = case_(a, shd_nodes(a, 0, NULL)); set_abstraction_body(fn_case, branch(a, (Branch) { .mem = get_abstraction_mem(fn_case), .condition = should_run, - .true_jump = jump_helper(a, if_true_case, empty(a), get_abstraction_mem(fn_case)), - .false_jump = jump_helper(a, if_false, empty(a), get_abstraction_mem(fn_case)), + .true_jump = jump_helper(a, if_true_case, shd_empty(a), get_abstraction_mem(fn_case)), + .false_jump = jump_helper(a, if_false, shd_empty(a), get_abstraction_mem(fn_case)), })); shd_list_append(const Node*, literals, fn_lit); - const Node* j = jump_helper(a, fn_case, empty(a), bb_mem(loop_body_builder)); + const Node* j = jump_helper(a, fn_case, shd_empty(a), bb_mem(loop_body_builder)); shd_list_append(const Node*, jumps, j); } } - Node* default_case = case_(a, nodes(a, 0, NULL)); + Node* default_case = case_(a, shd_nodes(a, 0, NULL)); set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, br_switch(a, (Switch) { .mem = bb_mem(loop_body_builder), .switch_value = next_function, - .case_values = nodes(a, shd_list_count(literals), shd_read_list(const Node*, literals)), - .case_jumps = nodes(a, shd_list_count(jumps), shd_read_list(const Node*, jumps)), - .default_jump = jump_helper(a, default_case, empty(a), bb_mem(loop_body_builder)) + .case_values = shd_nodes(a, shd_list_count(literals), shd_read_list(const Node*, literals)), + .case_jumps = shd_nodes(a, shd_list_count(jumps), shd_read_list(const Node*, jumps)), + .default_jump = jump_helper(a, default_case, shd_empty(a), bb_mem(loop_body_builder)) }))); shd_destroy_list(literals); shd_destroy_list(jumps); if (ctx->config->printf_trace.god_function) - gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", empty(a)); + gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", shd_empty(a)); set_abstraction_body(*ctx->top_dispatcher_fn, finish_body(dispatcher_body_builder, fn_ret(a, (Return) { - .args = nodes(a, 0, NULL), + .args = shd_nodes(a, 0, NULL), .mem = bb_mem(dispatcher_body_builder), }))); } @@ -444,8 +444,8 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) struct Dict* ptrs = shd_new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); - Node* init_fn = function(dst, nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), nodes(a, 0, NULL)); - set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = empty(a), .mem = get_abstraction_mem(init_fn) })); + Node* init_fn = function(dst, shd_nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), shd_nodes(a, 0, NULL)); + set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = shd_empty(a), .mem = get_abstraction_mem(init_fn) })); FnPtr next_fn_ptr = 1; diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 35f4e323a..f5ec24c6f 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -23,14 +23,14 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { for (size_t i = 0; i < width; i++) { LARRAY(const Node*, nops, noperands.count); for (size_t j = 0; j < noperands.count; j++) - nops[j] = gen_extract(bb, noperands.nodes[j], singleton(int32_literal(a, i))); - elements[i] = gen_primop_e(bb, old->payload.prim_op.op, empty(a), nodes(a, noperands.count, nops)); + nops[j] = gen_extract(bb, noperands.nodes[j], shd_singleton(int32_literal(a, i))); + elements[i] = gen_primop_e(bb, old->payload.prim_op.op, shd_empty(a), shd_nodes(a, noperands.count, nops)); } const Type* t = arr_type(a, (ArrType) { .element_type = rewrite_node(&ctx->rewriter, dst_type), .size = int32_literal(a, width) }); - return yield_values_and_wrap_in_block(bb, singleton(composite_helper(a, t, nodes(a, width, elements)))); + return yield_values_and_wrap_in_block(bb, shd_singleton(composite_helper(a, t, shd_nodes(a, width, elements)))); } static const Node* process(Context* ctx, const Node* node) { diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index af5c12696..06d076957 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -19,12 +19,12 @@ typedef struct { static void add_bounds_check(BodyBuilder* bb, const Node* i, const Node* max) { IrArena* a = bb->arena; - Node* out_of_bounds_case = case_(a, empty(a)); + Node* out_of_bounds_case = case_(a, shd_empty(a)); set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) { - .args = empty(a), + .args = shd_empty(a), .mem = get_abstraction_mem(out_of_bounds_case) })); - gen_if(bb, empty(a), gen_primop_e(bb, gte_op, empty(a), mk_nodes(a, i, max)), out_of_bounds_case, NULL); + gen_if(bb, shd_empty(a), gen_primop_e(bb, gte_op, shd_empty(a), mk_nodes(a, i, max)), out_of_bounds_case, NULL); } static const Node* process(Context* ctx, const Node* node) { @@ -63,13 +63,13 @@ static const Node* process(Context* ctx, const Node* node) { Nodes wannotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); Nodes wparams = recreate_params(&ctx->rewriter, node->payload.fun.params); - Node* wrapper = function(m, wparams, get_abstraction_name(node), wannotations, empty(a)); + Node* wrapper = function(m, wparams, get_abstraction_name(node), wannotations, shd_empty(a)); register_processed(&ctx->rewriter, node, wrapper); // recreate the old entry point, but this time it's not the entry point anymore Nodes nannotations = filter_out_annotation(a, wannotations, "EntryPoint"); Nodes nparams = recreate_params(&ctx->rewriter, node->payload.fun.params); - Node* inner = function(m, nparams, shd_format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, empty(a)); + Node* inner = function(m, nparams, shd_format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, shd_empty(a)); register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); register_processed(&ctx->rewriter, get_abstraction_mem(node), get_abstraction_mem(inner)); set_abstraction_body(inner, recreate_node_identity(&ctx->rewriter, node->payload.fun.body)); @@ -84,7 +84,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* num_workgroups[3]; for (int dim = 0; dim < 3; dim++) { workgroup_id[dim] = param(a, qualified_type_helper(uint32_type(a), false), names[dim]); - num_workgroups[dim] = gen_extract(bb, workgroup_num_vec3, singleton(uint32_literal(a, dim))); + num_workgroups[dim] = gen_extract(bb, workgroup_num_vec3, shd_singleton(uint32_literal(a, dim))); } // Prepare variables for iterating inside workgroups @@ -116,7 +116,7 @@ static const Node* process(Context* ctx, const Node* node) { } else assert(false); for (int dim = 0; dim < 3; dim++) { - Node* loop_body = case_(a, singleton(params[dim])); + Node* loop_body = case_(a, shd_singleton(params[dim])); cases[scope * 3 + dim] = loop_body; BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_body)); builders[scope * 3 + dim] = loop_bb; @@ -131,14 +131,14 @@ static const Node* process(Context* ctx, const Node* node) { // write the local ID const Node* local_id[3]; // local_id[0] = SUBGROUP_SIZE * subgroup_id[0] + subgroup_local_id - local_id[0] = gen_primop_e(bb2, add_op, empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, empty(a), mk_nodes(a, uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); + local_id[0] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); local_id[1] = subgroup_id[1]; local_id[2] = subgroup_id[2]; gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); // write the global ID const Node* global_id[3]; for (int dim = 0; dim < 3; dim++) - global_id[dim] = gen_primop_e(bb2, add_op, empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, empty(a), mk_nodes(a, uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); + global_id[dim] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID gen_call(bb2, fn_addr_helper(a, inner), wparams); @@ -158,14 +158,14 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* body_bb = builders[depth]; set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) { - .args = singleton(gen_primop_e(body_bb, add_op, empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1)))), + .args = shd_singleton(gen_primop_e(body_bb, add_op, shd_empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1)))), .mem = bb_mem(body_bb) }))); - gen_loop(depth > 0 ? builders[depth - 1] : bb, empty(a), singleton(uint32_literal(a, 0)), loop_body); + gen_loop(depth > 0 ? builders[depth - 1] : bb, shd_empty(a), shd_singleton(uint32_literal(a, 0)), loop_body); } } - set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = empty(a), .mem = bb_mem(bb) }))); + set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); return wrapper; } return recreate_node_identity(&ctx2.rewriter, node); @@ -177,9 +177,9 @@ static const Node* process(Context* ctx, const Node* node) { ptr = ptr->payload.ref_decl.decl; if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - const Node* loaded = first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); - const Node* uniformized = first(gen_primop(bb, subgroup_assume_uniform_op, empty(a), singleton(loaded))); - return yield_values_and_wrap_in_block(bb, singleton(uniformized)); + const Node* loaded = shd_first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); + const Node* uniformized = shd_first(gen_primop(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(loaded))); + return yield_values_and_wrap_in_block(bb, shd_singleton(uniformized)); } } default: break; diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index 02f172835..abc6e98f3 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -111,8 +111,8 @@ static const Node* process(Context* ctx, const Node* node) { if (fn_ctx.is_leaf) { shd_debugv_print("Function %s is a leaf function!\n", get_abstraction_name(node)); - new->payload.fun.annotations = append_nodes(a, annotations, annotation(a, (Annotation) { - .name = "Leaf", + new->payload.fun.annotations = shd_nodes_append(a, annotations, annotation(a, (Annotation) { + .name = "Leaf", })); } @@ -123,7 +123,7 @@ static const Node* process(Context* ctx, const Node* node) { case Control_TAG: { if (!is_control_static(ctx->uses, node)) { shd_debugv_print("Function %s can't be a leaf function because the join point ", get_abstraction_name(ctx->cfg->entry->node)); - shd_log_node(DEBUGV, first(get_abstraction_params(node->payload.control.inside))); + shd_log_node(DEBUGV, shd_first(get_abstraction_params(node->payload.control.inside))); shd_debugv_print("escapes its control block, preventing restructuring.\n"); ctx->is_leaf = false; } diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 43c9be198..de5d2e48f 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -79,9 +79,9 @@ static const Node* process(Context* ctx, const Node* node) { if (req_cast) { assert(is_data_type(req_cast)); BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.load.mem)); - const Node* r1 = first(bind_instruction(bb, recreate_node_identity(r, node))); - const Node* r2 = first(gen_primop(bb, reinterpret_op, singleton(req_cast), singleton(r1))); - return yield_values_and_wrap_in_block(bb, singleton(r2)); + const Node* r1 = shd_first(bind_instruction(bb, recreate_node_identity(r, node))); + const Node* r2 = shd_first(gen_primop(bb, reinterpret_op, shd_singleton(req_cast), shd_singleton(r1))); + return yield_values_and_wrap_in_block(bb, shd_singleton(r2)); } break; } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 6988f7b11..de40268bd 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -74,7 +74,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca continue; } case convert_op: { - if (first(payload.type_arguments)->tag == PtrType_TAG) { + if (shd_first(payload.type_arguments)->tag == PtrType_TAG) { k->non_logical_use = true; visit_ptr_uses(use->user, slice_type, k, map); } else { @@ -118,7 +118,7 @@ PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { switch (payload.op) { case convert_op: case reinterpret_op: { - ptr = first(payload.operands); + ptr = shd_first(payload.operands); continue; } // TODO: lea and co @@ -219,7 +219,7 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.value)); gen_store(bb, k.src_alloca->new, data); - return yield_values_and_wrap_in_block(bb, empty(a)); + return yield_values_and_wrap_in_block(bb, shd_empty(a)); } } break; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index ad0ee59f5..37ed0cae7 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -178,7 +178,7 @@ static const Node* process(Context* ctx, const Node* node) { const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); const Node* join_point = param(a, qualified_type_helper(jp_type, true), shd_format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); - Node* control_case = case_(a, singleton(join_point)); + Node* control_case = case_(a, shd_singleton(join_point)); const Node* nbody = inline_call(ctx, ocallee, get_abstraction_mem(control_case), nargs, join_point); set_abstraction_body(control_case, nbody); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index a54475dfe..85553f374 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -40,7 +40,7 @@ static const Node* get_ptr_source(const Node* ptr) { switch (payload.op) { case reinterpret_op: case convert_op: { - const Node* src = first(payload.operands); + const Node* src = shd_first(payload.operands); if (get_unqualified_type(src->type)->tag == PtrType_TAG) { ptr = src; continue; @@ -109,7 +109,7 @@ static const Node* process(Context* ctx, const Node* node) { *ctx->todo = true; const Node* value = rewrite_node(r, ovalue); if (is_qualified_type_uniform(node->type)) - value = prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(value)); + value = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(value)); return mem_and_value(a, (MemAndValue) { .mem = rewrite_node(r, payload.mem), .value = value }); } } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 8af305277..849a96708 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -83,14 +83,14 @@ static DFSStackEntry* encountered_before(Context* ctx, const Node* bb, size_t* p } static const Node* make_unreachable_case(IrArena* a) { - Node* c = case_(a, empty(a)); + Node* c = case_(a, shd_empty(a)); set_abstraction_body(c, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(c) })); return c; } static const Node* make_selection_merge_case(IrArena* a) { - Node* c = case_(a, empty(a)); - set_abstraction_body(c, merge_selection(a, (MergeSelection) { .args = empty(a), .mem = get_abstraction_mem(c) })); + Node* c = case_(a, shd_empty(a)); + set_abstraction_body(c, merge_selection(a, (MergeSelection) { .args = shd_empty(a), .mem = get_abstraction_mem(c) })); return c; } @@ -147,10 +147,10 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, } // We use a basic block for the exit ladder because we don't know what the ladder needs to do ahead of time - Node* inner_exit_ladder_bb = basic_block(a, empty(a), unique_name(a, "exit_ladder_inline_me")); + Node* inner_exit_ladder_bb = basic_block(a, shd_empty(a), unique_name(a, "exit_ladder_inline_me")); // Just jumps to the actual ladder - Node* structured_target = case_(a, nodes(a, oargs.count, nparams)); + Node* structured_target = case_(a, shd_nodes(a, oargs.count, nparams)); register_processed(&ctx2.rewriter, get_abstraction_mem(old_target), get_abstraction_mem(structured_target)); const Node* structured = structure(&ctx2, get_abstraction_body(old_target), inner_exit_ladder_bb); assert(is_terminator(structured)); @@ -163,14 +163,14 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, if (dfs_entry.loop_header) { // Use the structured target as the body of a loop - gen_loop(bb, empty(a), rewrite_nodes(&ctx->rewriter, oargs), structured_target); + gen_loop(bb, shd_empty(a), rewrite_nodes(&ctx->rewriter, oargs), structured_target); // The exit ladder must exit that new loop - set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) })); + set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) })); // After that we jump to the parent exit - return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); + return finish_body(bb, jump_helper(a, exit, shd_empty(a), bb_mem(bb))); } else { // Simply jmp to the exit once done - set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, exit, empty(a), get_abstraction_mem(inner_exit_ladder_bb))); + set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, exit, shd_empty(a), get_abstraction_mem(inner_exit_ladder_bb))); // Jump into the new structured target return finish_body(bb, jump_helper(a, structured_target, rewrite_nodes(&ctx->rewriter, oargs), bb_mem(bb))); } @@ -207,33 +207,33 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { const Node* condition = rewrite_node(&ctx->rewriter, payload.condition); rewrite_node(r, payload.mem); - Node* true_case = case_(a, empty(a)); + Node* true_case = case_(a, shd_empty(a)); set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, get_abstraction_mem(true_case), make_selection_merge_case(a))); - Node* false_case = case_(a, empty(a)); + Node* false_case = case_(a, shd_empty(a)); set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, get_abstraction_mem(false_case), make_selection_merge_case(a))); BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - gen_if(bb, empty(a), condition, true_case, false_case); - return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); + gen_if(bb, shd_empty(a), condition, true_case, false_case); + return finish_body(bb, jump_helper(a, exit, shd_empty(a), bb_mem(bb))); } case Switch_TAG: { Switch payload = body->payload.br_switch; const Node* switch_value = rewrite_node(r, payload.switch_value); rewrite_node(r, payload.mem); - Node* default_case = case_(a, empty(a)); + Node* default_case = case_(a, shd_empty(a)); set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, get_abstraction_mem(default_case), make_selection_merge_case(a))); LARRAY(Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { - cases[i] = case_(a, empty(a)); + cases[i] = case_(a, shd_empty(a)); set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, get_abstraction_mem(cases[i]), make_selection_merge_case(a))); } BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - gen_match(bb, empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), nodes(a, body->payload.br_switch.case_jumps.count, (const Node**) cases), default_case); - return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); + gen_match(bb, shd_empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), shd_nodes(a, body->payload.br_switch.case_jumps.count, (const Node**) cases), default_case); + return finish_body(bb, jump_helper(a, exit, shd_empty(a), bb_mem(bb))); } // let(control(body), tail) // var phi = undef; level = N+1; structurize[body, if (level == N+1, _ => tail(load(phi))); structured_exit_terminator] @@ -258,7 +258,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { Context control_ctx = *ctx; ControlEntry control_entry = { .parent = ctx->control_stack, - .old_token = first(old_control_params), + .old_token = shd_first(old_control_params), .phis = phis, .depth = ctx->control_stack ? ctx->control_stack->depth + 1 : 1, }; @@ -268,7 +268,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { gen_store(bb_prelude, ctx->level_ptr, int32_literal(a, control_entry.depth)); // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() - Node* tail = case_(a, empty(a)); + Node* tail = case_(a, shd_empty(a)); BodyBuilder* bb_tail = begin_body_with_mem(a, get_abstraction_mem(tail)); LARRAY(const Node*, phi_values, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { @@ -279,11 +279,11 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { // Wrap the tail in a guarded if, to handle 'far' joins const Node* level_value = gen_load(bb_tail, ctx->level_ptr); const Node* guard = prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }); - Node* true_case = case_(a, empty(a)); + Node* true_case = case_(a, shd_empty(a)); register_processed(r, get_abstraction_mem(get_structured_construct_tail(body)), get_abstraction_mem(true_case)); set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); - gen_if(bb_tail, empty(a), guard, true_case, NULL); - set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, exit, empty(a), bb_mem(bb_tail)))); + gen_if(bb_tail, shd_empty(a), guard, true_case, NULL); + set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, exit, shd_empty(a), bb_mem(bb_tail)))); register_processed(r, get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); return finish_body(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); @@ -302,7 +302,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { gen_store(bb, control->phis[i], args.nodes[i]); } - return finish_body(bb, jump_helper(a, exit, empty(a), bb_mem(bb))); + return finish_body(bb, jump_helper(a, exit, shd_empty(a), bb_mem(bb))); } case Return_TAG: diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 4bf46eda9..064249337 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -64,7 +64,7 @@ RewritePass lower_physical_ptrs; /// Replaces size_of, offset_of etc with their exact values RewritePass lower_memory_layout; RewritePass lower_memcpy; -/// Eliminates pointers to unsized arrays from the IR. Needs lower_lea to have ran first! +/// Eliminates pointers to unsized arrays from the IR. Needs lower_lea to have ran shd_first! RewritePass lower_decay_ptrs; RewritePass lower_generic_globals; RewritePass lower_logical_pointers; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index d69b983f1..a8129d117 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -151,7 +151,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { exit_destination_alloca = gen_stack_alloc(outer_bb, int32_type(arena)); const Node* join_token_exit = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { - .yield_types = empty(arena) + .yield_types = shd_empty(arena) }), true), "jp_exit"); const Node* join_token_continue = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { @@ -200,7 +200,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { rewriter->map = shd_clone_dict(rewriter->map); Nodes inner_loop_params = recreate_params(rewriter, get_abstraction_params(node)); register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); - Node* inner_control_case = case_(arena, singleton(join_token_continue)); + Node* inner_control_case = case_(arena, shd_singleton(join_token_continue)); register_processed(rewriter, get_abstraction_mem(node), get_abstraction_mem(inner_control_case)); const Node* loop_body = rewrite_node(rewriter, get_abstraction_body(node)); @@ -217,7 +217,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (exiting_nodes_count > 1) gen_store(exit_wrapper_bb, exit_destination_alloca, int32_literal(arena, i)); - set_abstraction_body(exits[i].wrapper, finish_body_with_join(exit_wrapper_bb, join_token_exit, empty(arena))); + set_abstraction_body(exits[i].wrapper, finish_body_with_join(exit_wrapper_bb, join_token_exit, shd_empty(arena))); } set_abstraction_body(inner_control_case, loop_body); @@ -242,23 +242,23 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { // make sure what was uniform still is for (size_t j = 0; j < inner_control_results.count; j++) { if (is_qualified_type_uniform(nparams.nodes[j]->type)) - inner_control_results = change_node_at_index(arena, inner_control_results, j, prim_op_helper(arena, subgroup_assume_uniform_op, empty(arena), singleton(inner_control_results.nodes[j]))); + inner_control_results = shd_change_node_at_index(arena, inner_control_results, j, prim_op_helper(arena, subgroup_assume_uniform_op, shd_empty(arena), shd_singleton(inner_control_results.nodes[j]))); } set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); - Node* outer_control_case = case_(arena, singleton(join_token_exit)); + Node* outer_control_case = case_(arena, shd_singleton(join_token_exit)); set_abstraction_body(outer_control_case, jump(arena, (Jump) { .target = loop_outer, .args = nparams, .mem = get_abstraction_mem(outer_control_case), })); - gen_control(outer_bb, empty(arena), outer_control_case); + gen_control(outer_bb, shd_empty(arena), outer_control_case); LARRAY(const Node*, exit_numbers, exiting_nodes_count); LARRAY(const Node*, exit_jumps, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; - Node* exit_bb = basic_block(arena, empty(arena), shd_format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); + Node* exit_bb = basic_block(arena, shd_empty(arena), shd_format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); const Node* recreated_exit = rewrite_node(rewriter, exiting_node->node); @@ -267,12 +267,12 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t j = 0; j < exits[i].params_count; j++) { recovered_args[j] = gen_load(exit_recover_bb, exits[i].params[j].alloca); if (exits[i].params[j].uniform) - recovered_args[j] = prim_op_helper(arena, subgroup_assume_uniform_op, empty(arena), singleton(recovered_args[j])); + recovered_args[j] = prim_op_helper(arena, subgroup_assume_uniform_op, shd_empty(arena), shd_singleton(recovered_args[j])); } exit_numbers[i] = int32_literal(arena, i); - set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, nodes(arena, exits[i].params_count, recovered_args))); - exit_jumps[i] = jump_helper(arena, exit_bb, empty(arena), bb_mem(outer_bb)); + set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, shd_nodes(arena, exits[i].params_count, recovered_args))); + exit_jumps[i] = jump_helper(arena, exit_bb, shd_empty(arena), bb_mem(outer_bb)); } const Node* outer_body; @@ -283,8 +283,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { outer_body = finish_body(outer_bb, br_switch(arena, (Switch) { .switch_value = loaded_destination, .default_jump = exit_jumps[0], - .case_values = nodes(arena, exiting_nodes_count, exit_numbers), - .case_jumps = nodes(arena, exiting_nodes_count, exit_jumps), + .case_values = shd_nodes(arena, exiting_nodes_count, exit_numbers), + .case_jumps = shd_nodes(arena, exiting_nodes_count, exit_jumps), .mem = bb_mem(outer_bb) })); } @@ -404,8 +404,8 @@ static const Node* process_node(Context* ctx, const Node* node) { LARRAY(bool, uniform_param, old_params.count); if (old_params.count == 0) { - yield_types = empty(a); - exit_args = empty(a); + yield_types = shd_empty(a); + exit_args = shd_empty(a); } else { LARRAY(const Node*, types, old_params.count); LARRAY(const Node*, inner_args,old_params.count); @@ -423,8 +423,8 @@ static const Node* process_node(Context* ctx, const Node* node) { inner_args[j] = param(a, qualified_type, old_params.nodes[j]->payload.param.name); } - yield_types = nodes(a, old_params.count, types); - exit_args = nodes(a, old_params.count, inner_args); + yield_types = shd_nodes(a, old_params.count, types); + exit_args = shd_nodes(a, old_params.count, inner_args); } const Node* join_token = param(a, qualified_type_helper(join_point_type(a, (JoinPointType) { @@ -447,7 +447,7 @@ static const Node* process_node(Context* ctx, const Node* node) { register_processed(r, post_dominator, pre_join); - Node* control_case = case_(a, singleton(join_token)); + Node* control_case = case_(a, shd_singleton(join_token)); const Node* inner_terminator = branch(a, (Branch) { .mem = get_abstraction_mem(control_case), .condition = rewrite_node(r, payload.condition), @@ -467,7 +467,7 @@ static const Node* process_node(Context* ctx, const Node* node) { // make sure what was uniform still is for (size_t j = 0; j < old_params.count; j++) { if (uniform_param[j]) - results = change_node_at_index(a, results, j, prim_op_helper(a, subgroup_assume_uniform_op, empty(a), singleton(results.nodes[j]))); + results = shd_change_node_at_index(a, results, j, prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(results.nodes[j]))); } return finish_body_with_jump(bb, join_target, results); } diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index 025d1cf2c..5e080a7dc 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -17,9 +17,9 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Jump_TAG: { Jump payload = node->payload.jump; - Node* new_block = basic_block(a, empty(a), NULL); + Node* new_block = basic_block(a, shd_empty(a), NULL); set_abstraction_body(new_block, jump_helper(a, rewrite_node(r, payload.target), rewrite_nodes(r, payload.args), get_abstraction_mem(new_block))); - return jump_helper(a, new_block, empty(a), rewrite_node(r, payload.mem)); + return jump_helper(a, new_block, shd_empty(a), rewrite_node(r, payload.mem)); } default: break; } diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 380bcee31..4a2f33b84 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -58,7 +58,7 @@ static Nodes remake_params(Context* ctx, Nodes old) { nvars[i] = param(a, t, node->payload.param.name); assert(nvars[i]->tag == Param_TAG); } - return nodes(a, old.count, nvars); + return shd_nodes(a, old.count, nvars); } static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { @@ -95,7 +95,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab } // We introduce a dummy case now because we don't know yet whether the body of the abstraction will be wrapped - Node* c = case_(a, empty(a)); + Node* c = case_(a, shd_empty(a)); Node* oc = c; register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); @@ -113,10 +113,10 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab AddControl add_control; while(shd_dict_iter(controls->control_destinations, &i, NULL, &add_control)) { const Node* dst = add_control.destination; - Node* control_case = case_(a, singleton(add_control.token)); - set_abstraction_body(control_case, jump_helper(a, c, empty(a), get_abstraction_mem(control_case))); + Node* control_case = case_(a, shd_singleton(add_control.token)); + set_abstraction_body(control_case, jump_helper(a, c, shd_empty(a), get_abstraction_mem(control_case))); - Node* c2 = case_(a, empty(a)); + Node* c2 = case_(a, shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); const Type* jp_type = add_control.token->type; deconstruct_qualified_type(&jp_type); @@ -126,14 +126,14 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab Nodes original_params = get_abstraction_params(dst); for (size_t j = 0; j < results.count; j++) { if (is_qualified_type_uniform(original_params.nodes[j]->type)) - results = change_node_at_index(a, results, j, gen_primop_e(bb, subgroup_assume_uniform_op, empty(a), singleton(results.nodes[j]))); + results = shd_change_node_at_index(a, results, j, gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(results.nodes[j]))); } c = c2; set_abstraction_body(c2, finish_body(bb, jump_helper(a, find_processed(r, dst), results, bb_mem(bb)))); } - const Node* body = jump_helper(a, c, empty(a), get_abstraction_mem(nabs)); + const Node* body = jump_helper(a, c, shd_empty(a), get_abstraction_mem(nabs)); set_abstraction_body(nabs, body); } diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index f7379bce6..034634210 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -20,7 +20,7 @@ static Nodes to_ids(IrArena* a, Nodes in) { LARRAY(const Node*, arr, in.count); for (size_t i = 0; i < in.count; i++) arr[i] = uint32_literal(a, in.nodes[i]->id); - return nodes(a, in.count, arr); + return shd_nodes(a, in.count, arr); } static void visit_looptree_prepend(IrArena* a, Nodes* arr, LTNode* node, Nodes prefix) { @@ -32,7 +32,7 @@ static void visit_looptree_prepend(IrArena* a, Nodes* arr, LTNode* node, Nodes p } else { for (size_t i = 0; i < shd_list_count(node->cf_nodes); i++) { CFNode* n = shd_read_list(CFNode*, node->cf_nodes)[i]; - arr[n->rpo_index] = concat_nodes(a, prefix, arr[n->rpo_index]); + arr[n->rpo_index] = shd_concat_nodes(a, prefix, arr[n->rpo_index]); } assert(node->lf_children); } @@ -57,7 +57,7 @@ static void paint_dominated_up_to_postdom(CFNode* n, IrArena* a, Nodes* arr, con paint_dominated_up_to_postdom(dominated, a, arr, postdom, prefix); } - arr[n->rpo_index] = prepend_nodes(a, arr[n->rpo_index], prefix); + arr[n->rpo_index] = shd_nodes_prepend(a, arr[n->rpo_index], prefix); } static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* flipped, LTNode* loop, LoopTree* lt) { @@ -94,11 +94,11 @@ static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* fl static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, LoopTree* lt, LTNode* node) { if (node->type == LF_HEAD) { - Nodes surrounding = empty(a); + Nodes surrounding = shd_empty(a); bool is_loop = false; for (size_t i = 0; i < shd_list_count(node->cf_nodes); i++) { CFNode* n = shd_read_list(CFNode*, node->cf_nodes)[i]; - surrounding = append_nodes(a, surrounding, n->node); + surrounding = shd_nodes_append(a, surrounding, n->node); is_loop = true; } @@ -116,7 +116,7 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, node, lt); if (is_loop > 0) - surrounding = prepend_nodes(a, surrounding, string_lit_helper(a, unique_name(a, "loop_body"))); + surrounding = shd_nodes_prepend(a, surrounding, string_lit_helper(a, unique_name(a, "loop_body"))); visit_looptree_prepend(a, arr, node, surrounding); // Remove one level of scoping for the loop headers (forcing reconvergence) @@ -124,7 +124,7 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, CFNode* n = shd_read_list(CFNode*, node->cf_nodes)[i]; Nodes old = arr[n->rpo_index]; assert(old.count > 1); - arr[n->rpo_index] = nodes(a, old.count - 1, &old.nodes[0]); + arr[n->rpo_index] = shd_nodes(a, old.count - 1, &old.nodes[0]); } destroy_cfg(sub_cfg); @@ -150,7 +150,7 @@ static Nodes* compute_scope_depth(IrArena* a, CFG* cfg) { Nodes* arr = calloc(sizeof(Nodes), cfg->size); for (size_t i = 0; i < cfg->size; i++) - arr[i] = empty(a); + arr[i] = shd_empty(a); visit_looptree(a, arr, cfg->entry->node, flipped, lt, lt->root); @@ -174,7 +174,7 @@ static const Node* process(Context* ctx, const Node* node) { fn_ctx.depth_per_rpo = compute_scope_depth(a, fn_ctx.cfg); Node* new_fn = recreate_decl_header_identity(r, node); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); - gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), empty(a)); + gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), shd_empty(a)); register_processed(r, get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new_fn, finish_body(bb, rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); destroy_cfg(fn_ctx.cfg); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 74365ba5b..751501a3c 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -102,7 +102,7 @@ Nodes rewrite_nodes_with_fn(Rewriter* rewriter, Nodes values, RewriteNodeFn fn) LARRAY(const Node*, arr, values.count); for (size_t i = 0; i < values.count; i++) arr[i] = rewrite_node_with_fn(rewriter, values.nodes[i], fn); - return nodes(rewriter->dst_arena, values.count, arr); + return shd_nodes(rewriter->dst_arena, values.count, arr); } const Node* rewrite_node(Rewriter* rewriter, const Node* node) { @@ -139,7 +139,7 @@ Nodes rewrite_ops_with_fn(Rewriter* rewriter, NodeClass class, String op_name, N LARRAY(const Node*, arr, values.count); for (size_t i = 0; i < values.count; i++) arr[i] = rewrite_op_with_fn(rewriter, class, op_name, values.nodes[i], fn); - return nodes(rewriter->dst_arena, values.count, arr); + return shd_nodes(rewriter->dst_arena, values.count, arr); } const Node* rewrite_op(Rewriter* rewriter, NodeClass class, String op_name, const Node* node) { @@ -259,7 +259,7 @@ Nodes recreate_params(Rewriter* rewriter, Nodes oparams) { nparams[i] = recreate_param(rewriter, oparams.nodes[i]); assert(nparams[i]->tag == Param_TAG); } - return nodes(rewriter->dst_arena, oparams.count, nparams); + return shd_nodes(rewriter->dst_arena, oparams.count, nparams); } Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 025b9bdd2..e88557ef7 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -21,11 +21,11 @@ Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { Nodes gen_primop(BodyBuilder* bb, Op op, Nodes type_args, Nodes operands) { assert(bb->arena->config.check_types); const Node* instruction = prim_op(bb->arena, (PrimOp) { .op = op, .type_arguments = type_args, .operands = operands }); - return singleton(instruction); + return shd_singleton(instruction); } Nodes gen_primop_c(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { - return gen_primop(bb, op, empty(bb->arena), nodes(bb->arena, operands_count, operands)); + return gen_primop(bb, op, shd_empty(bb->arena), shd_nodes(bb->arena, operands_count, operands)); } const Node* gen_primop_ce(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { @@ -36,7 +36,7 @@ const Node* gen_primop_ce(BodyBuilder* bb, Op op, size_t operands_count, const N const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { Nodes result = gen_primop(bb, op, ty, nodes); - return first(result); + return shd_first(result); } const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { @@ -62,7 +62,7 @@ void gen_push_values_stack(BodyBuilder* bb, Nodes values) { const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { const Node* instruction = pop_stack(bb->arena, (PopStack) { .type = type, .mem = bb_mem(bb) }); - return first(bind_instruction(bb, instruction)); + return shd_first(bind_instruction(bb, instruction)); } const Node* gen_get_stack_base_addr(BodyBuilder* bb) { @@ -70,7 +70,7 @@ const Node* gen_get_stack_base_addr(BodyBuilder* bb) { } const Node* gen_get_stack_size(BodyBuilder* bb) { - return first(bind_instruction(bb, get_stack_size(bb->arena, (GetStackSize) { .mem = bb_mem(bb) }))); + return shd_first(bind_instruction(bb, get_stack_size(bb->arena, (GetStackSize) { .mem = bb_mem(bb) }))); } void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { @@ -79,12 +79,12 @@ void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); - return prim_op(bb->arena, (PrimOp) { .op = reinterpret_op, .operands = singleton(src), .type_arguments = singleton(dst)}); + return prim_op(bb->arena, (PrimOp) { .op = reinterpret_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); } const Node* gen_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); - return prim_op(bb->arena, (PrimOp) { .op = convert_op, .operands = singleton(src), .type_arguments = singleton(dst)}); + return prim_op(bb->arena, (PrimOp) { .op = convert_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); } const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { @@ -105,11 +105,11 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { } const Node* gen_stack_alloc(BodyBuilder* bb, const Type* type) { - return first(bind_instruction(bb, stack_alloc(bb->arena, (StackAlloc) { .type = type, .mem = bb_mem(bb) }))); + return shd_first(bind_instruction(bb, stack_alloc(bb->arena, (StackAlloc) { .type = type, .mem = bb_mem(bb) }))); } const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { - return first(bind_instruction(bb, local_alloc(bb->arena, (LocalAlloc) { .type = type, .mem = bb_mem(bb) }))); + return shd_first(bind_instruction(bb, local_alloc(bb->arena, (LocalAlloc) { .type = type, .mem = bb_mem(bb) }))); } const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Node* index) { @@ -117,7 +117,7 @@ const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Nod } const Node* gen_load(BodyBuilder* bb, const Node* ptr) { - return first(bind_instruction(bb, load(bb->arena, (Load) { .ptr = ptr, .mem = bb_mem(bb) }))); + return shd_first(bind_instruction(bb, load(bb->arena, (Load) { .ptr = ptr, .mem = bb_mem(bb) }))); } void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { @@ -169,7 +169,7 @@ const Node* get_or_create_builtin(Module* m, Builtin b, String n) { AddressSpace as = get_builtin_as(b); IrArena* a = get_module_arena(m); - decl = global_var(m, singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, get_builtin_name(b)))), get_builtin_type(a, b), n ? n : shd_format_string_arena(a->arena, "builtin_%s", get_builtin_name(b)), as); + decl = global_var(m, shd_singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, get_builtin_name(b)))), get_builtin_type(a, b), n ? n : shd_format_string_arena(a->arena, "builtin_%s", get_builtin_name(b)), as); return decl; } @@ -226,8 +226,8 @@ const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* d // first convert to final bitsize then bitcast const Type* extended_src_t = int_type(bb->arena, (Int) { .width = dst_type->payload.int_type.width, .is_signed = src_type->payload.int_type.is_signed }); const Node* val = src; - val = gen_primop_e(bb, convert_op, singleton(extended_src_t), singleton(val)); - val = gen_primop_e(bb, reinterpret_op, singleton(dst_type), singleton(val)); + val = gen_primop_e(bb, convert_op, shd_singleton(extended_src_t), shd_singleton(val)); + val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } @@ -239,8 +239,8 @@ const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* d // first bitcast then convert to final bitsize const Type* reinterpreted_src_t = int_type(bb->arena, (Int) { .width = src_type->payload.int_type.width, .is_signed = dst_type->payload.int_type.is_signed }); const Node* val = src; - val = gen_primop_e(bb, reinterpret_op, singleton(reinterpreted_src_t), singleton(val)); - val = gen_primop_e(bb, convert_op, singleton(dst_type), singleton(val)); + val = gen_primop_e(bb, reinterpret_op, shd_singleton(reinterpreted_src_t), shd_singleton(val)); + val = gen_primop_e(bb, convert_op, shd_singleton(dst_type), shd_singleton(val)); return val; } @@ -250,11 +250,11 @@ const Node* convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const assert(dst_type->tag == Int_TAG); const Node* val = src; - val = gen_primop_e(bb, reinterpret_op, singleton( - int_type(bb->arena, (Int) {.width = src_type->payload.int_type.width, .is_signed = false })), singleton(val)); - val = gen_primop_e(bb, convert_op, singleton( - int_type(bb->arena, (Int) {.width = dst_type->payload.int_type.width, .is_signed = false })), singleton(val)); - val = gen_primop_e(bb, reinterpret_op, singleton(dst_type), singleton(val)); + val = gen_primop_e(bb, reinterpret_op, shd_singleton( + int_type(bb->arena, (Int) { .width = src_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); + val = gen_primop_e(bb, convert_op, shd_singleton( + int_type(bb->arena, (Int) { .width = dst_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); + val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } @@ -264,11 +264,11 @@ const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, cons assert(dst_type->tag == Int_TAG); const Node* val = src; - val = gen_primop_e(bb, reinterpret_op, singleton( - int_type(bb->arena, (Int) {.width = src_type->payload.int_type.width, .is_signed = true })), singleton(val)); - val = gen_primop_e(bb, convert_op, singleton( - int_type(bb->arena, (Int) {.width = dst_type->payload.int_type.width, .is_signed = true })), singleton(val)); - val = gen_primop_e(bb, reinterpret_op, singleton(dst_type), singleton(val)); + val = gen_primop_e(bb, reinterpret_op, shd_singleton( + int_type(bb->arena, (Int) { .width = src_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); + val = gen_primop_e(bb, convert_op, shd_singleton( + int_type(bb->arena, (Int) { .width = dst_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); + val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } @@ -291,7 +291,7 @@ const Node* get_default_zero_value(IrArena* a, const Type* t) { LARRAY(const Node*, elems, elem_tys.count); for (size_t i = 0; i < elem_tys.count; i++) elems[i] = get_default_zero_value(a, elem_tys.nodes[i]); - return composite_helper(a, t, nodes(a, elem_tys.count, elems)); + return composite_helper(a, t, shd_nodes(a, elem_tys.count, elems)); } default: break; } diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 410100f71..31c04563b 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -124,7 +124,7 @@ const Node* bytes_to_words(BodyBuilder* bb, const Node* bytes) { const Type* word_type = int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }); size_t word_width = get_type_bitwidth(word_type); const Node* bytes_per_word = size_t_literal(a, word_width / 8); - return gen_primop_e(bb, div_op, empty(a), mk_nodes(a, bytes, bytes_per_word)); + return gen_primop_e(bb, div_op, shd_empty(a), mk_nodes(a, bytes, bytes_per_word)); } uint64_t bytes_to_words_static(const IrArena* a, uint64_t bytes) { diff --git a/src/shady/type.c b/src/shady/type.c index e1b8b50e8..9ebca342c 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -469,7 +469,7 @@ const Type* check_type_composite(IrArena* arena, Composite composite) { return qualified_type(arena, (QualifiedType) { .is_uniform = is_uniform, .type = record_type(arena, (RecordType) { - .members = nodes(arena, composite.contents.count, member_ts) + .members = shd_nodes(arena, composite.contents.count, member_ts) }) }); } @@ -543,7 +543,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); - const Type* type = first(prim_op.operands)->type; + const Type* type = shd_first(prim_op.operands)->type; assert(is_arithm_type(get_maybe_packed_type_element(get_unqualified_type(type)))); return type; } @@ -552,7 +552,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case lshift_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = first(prim_op.operands)->type; + const Type* first_operand_type = shd_first(prim_op.operands)->type; const Type* second_operand_type = prim_op.operands.nodes[1]->type; bool uniform_result = deconstruct_qualified_type(&first_operand_type); @@ -579,7 +579,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case mod_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(first(prim_op.operands)->type); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { @@ -605,7 +605,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); - const Type* type = first(prim_op.operands)->type; + const Type* type = shd_first(prim_op.operands)->type; assert(has_boolean_ops(get_maybe_packed_type_element(get_unqualified_type(type)))); return type; } @@ -614,7 +614,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case and_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(first(prim_op.operands)->type); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { @@ -638,7 +638,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case neq_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(first(prim_op.operands)->type); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); size_t first_operand_width = get_maybe_packed_type_width(first_operand_type); bool result_uniform = true; @@ -667,7 +667,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); - const Node* src_type = first(prim_op.operands)->type; + const Node* src_type = shd_first(prim_op.operands)->type; bool uniform = deconstruct_qualified_type(&src_type); size_t width = deconstruct_maybe_packed_type(&src_type); assert(src_type->tag == Float_TAG); @@ -676,7 +676,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case pow_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(first(prim_op.operands)->type); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { @@ -695,7 +695,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case fma_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 3); - const Type* first_operand_type = get_unqualified_type(first(prim_op.operands)->type); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { @@ -716,7 +716,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); - const Node* src_type = first(prim_op.operands)->type; + const Node* src_type = shd_first(prim_op.operands)->type; bool uniform = deconstruct_qualified_type(&src_type); size_t width = deconstruct_maybe_packed_type(&src_type); assert(src_type->tag == Float_TAG || src_type->tag == Int_TAG && src_type->payload.int_type.is_signed); @@ -734,7 +734,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case offset_of_op: { assert(prim_op.type_arguments.count == 1); assert(prim_op.operands.count == 1); - const Type* optype = first(prim_op.operands)->type; + const Type* optype = shd_first(prim_op.operands)->type; bool uniform = deconstruct_qualified_type(&optype); assert(uniform && optype->tag == Int_TAG); return qualified_type(arena, (QualifiedType) { @@ -769,10 +769,10 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case extract_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count >= 2); - const Node* source = first(prim_op.operands); + const Node* source = shd_first(prim_op.operands); size_t indices_start = prim_op.op == insert_op ? 2 : 1; - Nodes indices = nodes(arena, prim_op.operands.count - indices_start, &prim_op.operands.nodes[indices_start]); + Nodes indices = shd_nodes(arena, prim_op.operands.count - indices_start, &prim_op.operands.nodes[indices_start]); const Type* t = source->type; bool uniform = deconstruct_qualified_type(&t); @@ -818,11 +818,11 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case reinterpret_op: { assert(prim_op.type_arguments.count == 1); assert(prim_op.operands.count == 1); - const Node* source = first(prim_op.operands); + const Node* source = shd_first(prim_op.operands); const Type* src_type = source->type; bool src_uniform = deconstruct_qualified_type(&src_type); - const Type* dst_type = first(prim_op.type_arguments); + const Type* dst_type = shd_first(prim_op.type_arguments); assert(is_data_type(dst_type)); assert(is_reinterpret_cast_legal(src_type, dst_type)); @@ -834,11 +834,11 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case convert_op: { assert(prim_op.type_arguments.count == 1); assert(prim_op.operands.count == 1); - const Node* source = first(prim_op.operands); + const Node* source = shd_first(prim_op.operands); const Type* src_type = source->type; bool src_uniform = deconstruct_qualified_type(&src_type); - const Type* dst_type = first(prim_op.type_arguments); + const Type* dst_type = shd_first(prim_op.type_arguments); assert(is_data_type(dst_type)); assert(is_conversion_legal(src_type, dst_type)); @@ -875,7 +875,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case sample_texture_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* sampled_image_t = first(prim_op.operands)->type; + const Type* sampled_image_t = shd_first(prim_op.operands)->type; bool uniform_src = deconstruct_qualified_type(&sampled_image_t); const Type* coords_t = prim_op.operands.nodes[1]->type; deconstruct_qualified_type(&coords_t); @@ -969,7 +969,7 @@ const Type* check_type_loop_instr(IrArena* arena, Loop loop_instr) { const Type* check_type_control(IrArena* arena, Control control) { ensure_types_are_data_types(&control.yield_types); // TODO check it then ! - const Node* join_point = first(get_abstraction_params(control.inside)); + const Node* join_point = shd_first(get_abstraction_params(control.inside)); const Type* join_point_type = join_point->type; deconstruct_qualified_type(&join_point_type); diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 5b34212cb..c8f537189 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -11,7 +11,7 @@ const Type* maybe_multiple_return(IrArena* arena, Nodes types) { case 1: return types.nodes[0]; default: return record_type(arena, (RecordType) { .members = types, - .names = strings(arena, 0, NULL), + .names = shd_strings(arena, 0, NULL), .special = MultipleReturn, }); } @@ -26,7 +26,7 @@ Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type) { // fallthrough default: assert(is_value_type(type)); - return singleton(type); + return shd_singleton(type); } } @@ -111,7 +111,7 @@ Nodes get_param_types(IrArena* arena, Nodes variables) { assert(variables.nodes[i]->tag == Param_TAG); arr[i] = variables.nodes[i]->payload.param.type; } - return nodes(arena, variables.count, arr); + return shd_nodes(arena, variables.count, arr); } Nodes get_values_types(IrArena* arena, Nodes values) { @@ -119,7 +119,7 @@ Nodes get_values_types(IrArena* arena, Nodes values) { LARRAY(const Type*, arr, values.count); for (size_t i = 0; i < values.count; i++) arr[i] = values.nodes[i]->type; - return nodes(arena, values.count, arr); + return shd_nodes(arena, values.count, arr); } bool is_qualified_type_uniform(const Type* type) { @@ -151,14 +151,14 @@ Nodes strip_qualifiers(IrArena* arena, Nodes tys) { LARRAY(const Type*, arr, tys.count); for (size_t i = 0; i < tys.count; i++) arr[i] = get_unqualified_type(tys.nodes[i]); - return nodes(arena, tys.count, arr); + return shd_nodes(arena, tys.count, arr); } Nodes add_qualifiers(IrArena* arena, Nodes tys, bool uniform) { LARRAY(const Type*, arr, tys.count); for (size_t i = 0; i < tys.count; i++) arr[i] = qualified_type_helper(tys.nodes[i], uniform || !arena->config.is_simt /* SIMD arenas ban varying value types */); - return nodes(arena, tys.count, arr); + return shd_nodes(arena, tys.count, arr); } const Type* get_packed_type_element(const Type* type) { @@ -268,7 +268,7 @@ Nodes get_composite_type_element_types(const Type* type) { for (size_t i = 0; i < size; i++) { types[i] = element_type; } - return nodes(type->arena, size, types); + return shd_nodes(type->arena, size, types); } default: shd_error("Not a composite type !") } diff --git a/test/test_builder.c b/test/test_builder.c index 4316763a4..2237d6ebb 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -16,7 +16,7 @@ static void test_body_builder_constants(IrArena* a) { BodyBuilder* bb = begin_block_pure(a); - const Node* sum = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, int32_literal(a, 4), int32_literal(a, 38))); + const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, int32_literal(a, 4), int32_literal(a, 38))); const Node* result = yield_value_and_wrap_in_block(bb, sum); CHECK(sum == result, exit(-1)); CHECK(result->tag == IntLiteral_TAG, exit(-1)); @@ -35,23 +35,23 @@ static void test_body_builder_fun_body(IrArena* a) { }), false), NULL); // const Node* p3 = param(a, qualified_type_helper(bool_type(a), false), NULL); // const Node* p4 = param(a, qualified_type_helper(uint32_type(a), false), NULL); - Node* fun = function(m, mk_nodes(a, p1, p2), "fun", empty(a), empty(a)); + Node* fun = function(m, mk_nodes(a, p1, p2), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); const Node* p1_value = gen_load(bb, p1); CHECK(p1_value->tag == Load_TAG, exit(-1)); - Node* true_case = case_(a, empty(a)); + Node* true_case = case_(a, shd_empty(a)); BodyBuilder* tc_builder = begin_body_with_mem(a, get_abstraction_mem(true_case)); gen_store(tc_builder, p1, uint32_literal(a, 0)); - set_abstraction_body(true_case, finish_body_with_selection_merge(tc_builder, empty(a))); - gen_if(bb, empty(a), gen_primop_e(bb, gt_op, empty(a), mk_nodes(a, p1_value, uint32_literal(a, 0))), true_case, NULL); + set_abstraction_body(true_case, finish_body_with_selection_merge(tc_builder, shd_empty(a))); + gen_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, uint32_literal(a, 0))), true_case, NULL); const Node* p2_value = gen_load(bb, p2); - const Node* sum = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, p1_value, p2_value)); + const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, p1_value, p2_value)); const Node* return_terminator = fn_ret(a, (Return) { .mem = bb_mem(bb), - .args = singleton(sum) + .args = shd_singleton(sum) }); set_abstraction_body(fun, finish_body(bb, return_terminator)); // set_abstraction_body(fun, finish_body_with_return(bb, singleton(sum))); @@ -91,21 +91,21 @@ static void test_body_builder_impure_block(IrArena* a) { .address_space = AsGeneric, .pointed_type = uint32_type(a), }), false), NULL); - Node* fun = function(m, mk_nodes(a, p1), "fun", empty(a), empty(a)); + Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); const Node* first_load = gen_load(bb, p1); BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); gen_store(block_builder, p1, uint32_literal(a, 0)); - bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, empty(a))); + bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, shd_empty(a))); const Node* second_load = gen_load(bb, p1); - const Node* sum = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, first_load, second_load)); + const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); const Node* return_terminator = fn_ret(a, (Return) { .mem = bb_mem(bb), - .args = singleton(sum) + .args = shd_singleton(sum) }); set_abstraction_body(fun, finish_body(bb, return_terminator)); @@ -130,25 +130,25 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { .address_space = AsGeneric, .pointed_type = uint32_type(a), }), false), NULL); - Node* fun = function(m, mk_nodes(a, p1), "fun", empty(a), empty(a)); + Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); const Node* first_load = gen_load(bb, p1); BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); - Node* if_true_case = case_(a, empty(a)); + Node* if_true_case = case_(a, shd_empty(a)); BodyBuilder* if_true_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); gen_store(if_true_builder, p1, uint32_literal(a, 0)); - set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_true_builder, empty(a))); - gen_if(block_builder, empty(a), gen_primop_e(block_builder, neq_op, empty(a), mk_nodes(a, first_load, uint32_literal(a, 0))), if_true_case, NULL); - bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, empty(a))); + set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_true_builder, shd_empty(a))); + gen_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, uint32_literal(a, 0))), if_true_case, NULL); + bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, shd_empty(a))); const Node* second_load = gen_load(bb, p1); - const Node* sum = gen_primop_e(bb, add_op, empty(a), mk_nodes(a, first_load, second_load)); + const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); const Node* return_terminator = fn_ret(a, (Return) { .mem = bb_mem(bb), - .args = singleton(sum) + .args = shd_singleton(sum) }); set_abstraction_body(fun, finish_body(bb, return_terminator)); From dccaa47429425aa72552b1d1a90d3f506045b78f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 25 Sep 2024 16:10:21 +0200 Subject: [PATCH 601/693] add shd_ prefix to scalar type helpers --- include/shady/builtins.h | 52 +++++++++---------- include/shady/ir.h | 42 +++++++-------- src/backend/c/emit_c.c | 4 +- src/backend/spirv/emit_spv_value.c | 18 +++---- src/backend/spirv/spirv_lift_globals_ssbo.c | 10 ++-- src/frontend/llvm/l2s_annotations.c | 10 ++-- src/frontend/llvm/l2s_instr.c | 2 +- src/frontend/llvm/l2s_meta.c | 2 +- src/frontend/llvm/l2s_type.c | 20 +++---- src/frontend/llvm/l2s_value.c | 16 +++--- src/frontend/slim/infer.c | 4 +- src/frontend/slim/parser.c | 22 ++++---- src/frontend/spirv/s2s.c | 14 ++--- src/shady/body_builder.c | 2 +- src/shady/constructors.c | 42 +++++++-------- src/shady/fold.c | 8 +-- src/shady/generator_constructors.c | 2 +- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_int64.c | 10 ++-- src/shady/passes/lower_lea.c | 2 +- src/shady/passes/lower_logical_pointers.c | 2 +- src/shady/passes/lower_memcpy.c | 12 ++--- src/shady/passes/lower_nullptr.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 8 +-- src/shady/passes/lower_stack.c | 16 +++--- src/shady/passes/lower_subgroup_ops.c | 14 ++--- src/shady/passes/lower_subgroup_vars.c | 2 +- src/shady/passes/lower_tailcalls.c | 26 +++++----- src/shady/passes/lower_vec_arr.c | 6 +-- src/shady/passes/lower_workgroups.c | 22 ++++---- src/shady/passes/opt_restructure.c | 10 ++-- src/shady/passes/reconvergence_heuristics.c | 6 +-- src/shady/passes/scope_heuristic.c | 2 +- src/shady/passes/specialize_entry_point.c | 6 +-- src/shady/passes/specialize_execution_model.c | 2 +- src/shady/transform/internal_constants.h | 4 +- src/shady/type.c | 12 ++--- src/shady/type_helpers.c | 2 +- test/test_builder.c | 20 +++---- test/test_math.c | 8 +-- 42 files changed, 235 insertions(+), 235 deletions(-) diff --git a/include/shady/builtins.h b/include/shady/builtins.h index 7cffc8bd1..46631e0e4 100644 --- a/include/shady/builtins.h +++ b/include/shady/builtins.h @@ -3,35 +3,35 @@ #include "shady/ir.h" -#define u32vec3_type(arena) pack_type(arena, (PackType) { .width = 3, .element_type = uint32_type(arena) }) -#define i32vec3_type(arena) pack_type(arena, (PackType) { .width = 3, .element_type = int32_type(arena) }) -#define i32vec4_type(arena) pack_type(arena, (PackType) { .width = 4, .element_type = int32_type(arena) }) +#define shd_u32vec3_type(arena) pack_type(arena, (PackType) { .width = 3, .element_type = shd_uint32_type(arena) }) +#define shd_i32vec3_type(arena) pack_type(arena, (PackType) { .width = 3, .element_type = shd_int32_type(arena) }) +#define shd_i32vec4_type(arena) pack_type(arena, (PackType) { .width = 4, .element_type = shd_int32_type(arena) }) -#define f32vec4_type(arena) pack_type(arena, (PackType) { .width = 4, .element_type = fp32_type(arena) }) +#define shd_f32vec4_type(arena) pack_type(arena, (PackType) { .width = 4, .element_type = shd_fp32_type(arena) }) #define SHADY_BUILTINS() \ -BUILTIN(BaseInstance, AsInput, uint32_type(arena) )\ -BUILTIN(BaseVertex, AsInput, uint32_type(arena) )\ -BUILTIN(DeviceIndex, AsInput, uint32_type(arena) )\ -BUILTIN(DrawIndex, AsInput, uint32_type(arena) )\ -BUILTIN(VertexIndex, AsInput, uint32_type(arena) )\ -BUILTIN(FragCoord, AsInput, f32vec4_type(arena) )\ -BUILTIN(FragDepth, AsOutput, fp32_type(arena) )\ -BUILTIN(InstanceId, AsInput, uint32_type(arena) )\ -BUILTIN(InvocationId, AsInput, uint32_type(arena) )\ -BUILTIN(InstanceIndex, AsInput, uint32_type(arena) )\ -BUILTIN(LocalInvocationId, AsInput, u32vec3_type(arena) )\ -BUILTIN(LocalInvocationIndex, AsInput, uint32_type(arena) )\ -BUILTIN(GlobalInvocationId, AsInput, u32vec3_type(arena) )\ -BUILTIN(WorkgroupId, AsUInput, u32vec3_type(arena) )\ -BUILTIN(WorkgroupSize, AsUInput, u32vec3_type(arena) )\ -BUILTIN(NumSubgroups, AsUInput, uint32_type(arena) )\ -BUILTIN(NumWorkgroups, AsUInput, u32vec3_type(arena) )\ -BUILTIN(Position, AsOutput, f32vec4_type(arena) )\ -BUILTIN(PrimitiveId, AsInput, uint32_type(arena) )\ -BUILTIN(SubgroupLocalInvocationId, AsInput, uint32_type(arena) )\ -BUILTIN(SubgroupId, AsUInput, uint32_type(arena) )\ -BUILTIN(SubgroupSize, AsInput, uint32_type(arena) )\ +BUILTIN(BaseInstance, AsInput, shd_uint32_type(arena) )\ +BUILTIN(BaseVertex, AsInput, shd_uint32_type(arena) )\ +BUILTIN(DeviceIndex, AsInput, shd_uint32_type(arena) )\ +BUILTIN(DrawIndex, AsInput, shd_uint32_type(arena) )\ +BUILTIN(VertexIndex, AsInput, shd_uint32_type(arena) )\ +BUILTIN(FragCoord, AsInput, shd_f32vec4_type(arena) )\ +BUILTIN(FragDepth, AsOutput, shd_fp32_type(arena) )\ +BUILTIN(InstanceId, AsInput, shd_uint32_type(arena) )\ +BUILTIN(InvocationId, AsInput, shd_uint32_type(arena) )\ +BUILTIN(InstanceIndex, AsInput, shd_uint32_type(arena) )\ +BUILTIN(LocalInvocationId, AsInput, shd_u32vec3_type(arena) )\ +BUILTIN(LocalInvocationIndex, AsInput, shd_uint32_type(arena) )\ +BUILTIN(GlobalInvocationId, AsInput, shd_u32vec3_type(arena) )\ +BUILTIN(WorkgroupId, AsUInput, shd_u32vec3_type(arena) )\ +BUILTIN(WorkgroupSize, AsUInput, shd_u32vec3_type(arena) )\ +BUILTIN(NumSubgroups, AsUInput, shd_uint32_type(arena) )\ +BUILTIN(NumWorkgroups, AsUInput, shd_u32vec3_type(arena) )\ +BUILTIN(Position, AsOutput, shd_f32vec4_type(arena) )\ +BUILTIN(PrimitiveId, AsInput, shd_uint32_type(arena) )\ +BUILTIN(SubgroupLocalInvocationId, AsInput, shd_uint32_type(arena) )\ +BUILTIN(SubgroupId, AsUInput, shd_uint32_type(arena) )\ +BUILTIN(SubgroupSize, AsInput, shd_uint32_type(arena) )\ typedef enum { #define BUILTIN(name, as, datatype) Builtin##name, diff --git a/include/shady/ir.h b/include/shady/ir.h index bed15097b..749109a0f 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -221,33 +221,33 @@ const Node* unit_type(IrArena*); /// For typing instructions that return nothing (equivalent to C's void f()) const Node* empty_multiple_return_type(IrArena*); -const Type* int_type_helper(IrArena*, bool, IntSizes); +const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w); -const Type* int8_type(IrArena*); -const Type* int16_type(IrArena*); -const Type* int32_type(IrArena*); -const Type* int64_type(IrArena*); +const Type* shd_int8_type(IrArena* arena); +const Type* shd_int16_type(IrArena* arena); +const Type* shd_int32_type(IrArena* arena); +const Type* shd_int64_type(IrArena* arena); -const Type* uint8_type(IrArena*); -const Type* uint16_type(IrArena*); -const Type* uint32_type(IrArena*); -const Type* uint64_type(IrArena*); +const Type* shd_uint8_type(IrArena* arena); +const Type* shd_uint16_type(IrArena* arena); +const Type* shd_uint32_type(IrArena* arena); +const Type* shd_uint64_type(IrArena* arena); -const Type* int8_literal(IrArena*, int8_t i); -const Type* int16_literal(IrArena*, int16_t i); -const Type* int32_literal(IrArena*, int32_t i); -const Type* int64_literal(IrArena*, int64_t i); +const Type* shd_int8_literal(IrArena* arena, int8_t i); +const Type* shd_int16_literal(IrArena* arena, int16_t i); +const Type* shd_int32_literal(IrArena* arena, int32_t i); +const Type* shd_int64_literal(IrArena* arena, int64_t i); -const Type* uint8_literal(IrArena*, uint8_t i); -const Type* uint16_literal(IrArena*, uint16_t i); -const Type* uint32_literal(IrArena*, uint32_t i); -const Type* uint64_literal(IrArena*, uint64_t i); +const Type* shd_uint8_literal(IrArena* arena, uint8_t i); +const Type* shd_uint16_literal(IrArena* arena, uint16_t i); +const Type* shd_uint32_literal(IrArena* arena, uint32_t i); +const Type* shd_uint64_literal(IrArena* arena, uint64_t i); -const Type* fp16_type(IrArena*); -const Type* fp32_type(IrArena*); -const Type* fp64_type(IrArena*); +const Type* shd_fp16_type(IrArena* arena); +const Type* shd_fp32_type(IrArena* arena); +const Type* shd_fp64_type(IrArena* arena); -const Node* fp_literal_helper(IrArena*, FloatSizes, double); +const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value); const Node* type_decl_ref_helper(IrArena*, const Node* decl); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index d91d944d2..4e191c36c 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -447,8 +447,8 @@ void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[1]; emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[2]; shd_print(emitter.type_decls, "\ntypedef %s;\n", c_emit_type(&emitter, arr_type(arena, (ArrType) { - .size = int32_literal(arena, 3), - .element_type = uint32_type(arena) + .size = shd_int32_literal(arena, 3), + .element_type = shd_uint32_type(arena) }), "uvec3")); shd_print(emitter.fn_defs, shady_cuda_builtins_src); diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index c66f85692..7a5ce1c7c 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -281,11 +281,11 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformBallot); - SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); + SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, shd_int32_literal(emitter->arena, SpvScopeSubgroup)); if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); - SpvId local_id = spvb_op(bb_builder, SpvOpLoad, spv_emit_type(emitter, uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, fn_builder, b) }); + SpvId local_id = spvb_op(bb_builder, SpvOpLoad, spv_emit_type(emitter, shd_uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, fn_builder, b) }); return spvb_group_shuffle(bb_builder, spv_emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, fn_builder, shd_first(instr.operands)), local_id); } break; @@ -296,15 +296,15 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); // ad-hoc extension for my sanity if (get_unqualified_type(instr.result_t) == get_actual_mask_type(emitter->arena)) { - const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = uint32_type(emitter->arena) }); + const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = shd_uint32_type(emitter->arena) }); SpvId raw_result = spvb_group_ballot(bb_builder, spv_emit_type(emitter, i32x4), spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), spv_emit_value(emitter, fn_builder, shd_first(instr.operands))); // TODO: why are we doing this in SPIR-V and not the IR ? - SpvId low32 = spvb_extract(bb_builder, spv_emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 0 }); - SpvId hi32 = spvb_extract(bb_builder, spv_emit_type(emitter, uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 1 }); - SpvId low64 = spvb_op(bb_builder, SpvOpUConvert, spv_emit_type(emitter, uint64_type(emitter->arena)), 1, &low32); - SpvId hi64 = spvb_op(bb_builder, SpvOpUConvert, spv_emit_type(emitter, uint64_type(emitter->arena)), 1, &hi32); - hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, spv_emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { hi64, spv_emit_value(emitter, fn_builder, int64_literal(emitter->arena, 32)) }); - SpvId final_result = spvb_op(bb_builder, SpvOpBitwiseOr, spv_emit_type(emitter, uint64_type(emitter->arena)), 2, (SpvId []) { low64, hi64 }); + SpvId low32 = spvb_extract(bb_builder, spv_emit_type(emitter, shd_uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 0 }); + SpvId hi32 = spvb_extract(bb_builder, spv_emit_type(emitter, shd_uint32_type(emitter->arena)), raw_result, 1, (uint32_t[]) { 1 }); + SpvId low64 = spvb_op(bb_builder, SpvOpUConvert, spv_emit_type(emitter, shd_uint64_type(emitter->arena)), 1, &low32); + SpvId hi64 = spvb_op(bb_builder, SpvOpUConvert, spv_emit_type(emitter, shd_uint64_type(emitter->arena)), 1, &hi32); + hi64 = spvb_op(bb_builder, SpvOpShiftLeftLogical, spv_emit_type(emitter, shd_uint64_type(emitter->arena)), 2, (SpvId []) { hi64, spv_emit_value(emitter, fn_builder, shd_int64_literal(emitter->arena, 32)) }); + SpvId final_result = spvb_op(bb_builder, SpvOpBitwiseOr, spv_emit_type(emitter, shd_uint64_type(emitter->arena)), 2, (SpvId []) { low64, hi64 }); return final_result; } break; diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 6c961111f..525d39fa0 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -41,7 +41,7 @@ static const Node* process(Context* ctx, const Node* node) { if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) break; assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); - const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), int32_literal(a, 0), shd_singleton(rewrite_node(&ctx->rewriter, odecl))); + const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), shd_int32_literal(a, 0), shd_singleton(rewrite_node(&ctx->rewriter, odecl))); const Node* ptr = gen_load(ctx->bb, ptr_addr); return ptr; } @@ -78,8 +78,8 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul Nodes annotations = mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" })); annotations = shd_empty(a); - annotations = shd_nodes_append(a, annotations, annotation_value(a, (AnnotationValue) { .name = "DescriptorSet", .value = int32_literal(a, 0) })); - annotations = shd_nodes_append(a, annotations, annotation_value(a, (AnnotationValue) { .name = "DescriptorBinding", .value = int32_literal(a, 0) })); + annotations = shd_nodes_append(a, annotations, annotation_value(a, (AnnotationValue) { .name = "DescriptorSet", .value = shd_int32_literal(a, 0) })); + annotations = shd_nodes_append(a, annotations, annotation_value(a, (AnnotationValue) { .name = "DescriptorBinding", .value = shd_int32_literal(a, 0) })); annotations = shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Constants" })); size_t lifted_globals_count = 0; @@ -91,7 +91,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul member_tys[lifted_globals_count] = rewrite_node(&ctx.rewriter, odecl->type); member_names[lifted_globals_count] = get_declaration_name(odecl); - register_processed(&ctx.rewriter, odecl, int32_literal(a, lifted_globals_count)); + register_processed(&ctx.rewriter, odecl, shd_int32_literal(a, lifted_globals_count)); lifted_globals_count++; } @@ -114,7 +114,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul if (odecl->payload.global_variable.init) ctx.lifted_globals_decl->payload.global_variable.annotations = shd_nodes_append(a, ctx.lifted_globals_decl->payload.global_variable.annotations, annotation_values(a, (AnnotationValues) { .name = "InitialValue", - .values = mk_nodes(a, int32_literal(a, lifted_globals_count), rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) + .values = mk_nodes(a, shd_int32_literal(a, lifted_globals_count), rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) })); lifted_globals_count++; diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 8a6327b0f..deb421a44 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -107,7 +107,7 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { add_annotation(p, target, (ParsedAnnotation) { .payload = annotation_values(a, (AnnotationValues) { .name = "WorkgroupSize", - .values = mk_nodes(a, int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)), int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)), int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10))) + .values = mk_nodes(a, shd_int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)), shd_int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)), shd_int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10))) }) }); } else if (strcmp(keyword, "builtin") == 0) { @@ -123,7 +123,7 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { add_annotation(p, target, (ParsedAnnotation) { .payload = annotation_value(a, (AnnotationValue) { .name = "Location", - .value = int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)) + .value = shd_int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)) }) }); } else if (strcmp(keyword, "descriptor_set") == 0) { @@ -131,7 +131,7 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { add_annotation(p, target, (ParsedAnnotation) { .payload = annotation_value(a, (AnnotationValue) { .name = "DescriptorSet", - .value = int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)) + .value = shd_int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)) }) }); } else if (strcmp(keyword, "descriptor_binding") == 0) { @@ -139,7 +139,7 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { add_annotation(p, target, (ParsedAnnotation) { .payload = annotation_value(a, (AnnotationValue) { .name = "DescriptorBinding", - .value = int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)) + .value = shd_int32_literal(a, strtol(strtok(NULL, "::"), NULL, 10)) }) }); } else if (strcmp(keyword, "extern") == 0) { @@ -150,7 +150,7 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { add_annotation(p, target, (ParsedAnnotation) { .payload = annotation_value(a, (AnnotationValue) { .name = "AddressSpace", - .value = int32_literal(a, as) + .value = shd_int32_literal(a, as) }) }); } else { diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 06c287d76..105f52185 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -617,7 +617,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B unsigned num_indices = LLVMGetNumMaskElements(instr); LARRAY(const Node*, cindices, num_indices); for (size_t i = 0; i < num_indices; i++) - cindices[i] = uint32_literal(a, LLVMGetMaskValue(instr, i)); + cindices[i] = shd_uint32_literal(a, LLVMGetMaskValue(instr, i)); ops = shd_concat_nodes(a, ops, shd_nodes(a, num_indices, cindices)); return prim_op_helper(a, shuffle_op, shd_empty(a), ops); } diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index 0f7dde146..af71ad0fd 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -109,7 +109,7 @@ Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { while (true) { if (!scope) break; - str = shd_nodes_prepend(a, str, uint32_literal(a, convert_metadata(p, scope)->id)); + str = shd_nodes_prepend(a, str, shd_uint32_literal(a, convert_metadata(p, scope)->id)); // LLVMDumpValue(LLVMMetadataAsValue(p->ctx, scope)); // printf("\n"); diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index 2476e9782..b00756bbf 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -13,9 +13,9 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { switch (LLVMGetTypeKind(t)) { case LLVMVoidTypeKind: return unit_type(a); - case LLVMHalfTypeKind: return fp16_type(a); - case LLVMFloatTypeKind: return fp32_type(a); - case LLVMDoubleTypeKind: return fp64_type(a); + case LLVMHalfTypeKind: return shd_fp16_type(a); + case LLVMFloatTypeKind: return shd_fp32_type(a); + case LLVMDoubleTypeKind: return shd_fp64_type(a); case LLVMX86_FP80TypeKind: case LLVMFP128TypeKind: break; @@ -24,10 +24,10 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { case LLVMIntegerTypeKind: switch(LLVMGetIntTypeWidth(t)) { case 1: return bool_type(a); - case 8: return uint8_type(a); - case 16: return uint16_type(a); - case 32: return uint32_type(a); - case 64: return uint64_type(a); + case 8: return shd_uint8_type(a); + case 16: return shd_uint16_type(a); + case 32: return shd_uint32_type(a); + case 64: return shd_uint64_type(a); default: shd_error("Unsupported integer width: %d\n", LLVMGetIntTypeWidth(t)); break; } case LLVMFunctionTypeKind: { @@ -77,7 +77,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { case LLVMArrayTypeKind: { unsigned length = LLVMGetArrayLength(t); const Type* elem_t = convert_type(p, LLVMGetElementType(t)); - return arr_type(a, (ArrType) { .element_type = elem_t, .size = uint32_literal(a, length)}); + return arr_type(a, (ArrType) { .element_type = elem_t, .size = shd_uint32_literal(a, length)}); } case LLVMPointerTypeKind: { unsigned int llvm_as = LLVMGetPointerAddressSpace(t); @@ -88,8 +88,8 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { const Type* sampled_type = NULL; switch (type_id) { case 0x0: sampled_type = float_type(a, (Float) {.width = FloatTy32}); break; - case 0x1: sampled_type = int32_type(a); break; - case 0x2: sampled_type = uint32_type(a); break; + case 0x1: sampled_type = shd_int32_type(a); break; + case 0x2: sampled_type = shd_uint32_type(a); break; default: assert(false); } bool arrayed = (offset >> 6) & 1; diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index d2fa1e149..9cc68ba88 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -16,10 +16,10 @@ static const Node* data_composite(const Type* t, size_t size, LLVMValueRef v) { switch (et->tag) { case Int_TAG: { switch (et->payload.int_type.width) { - case IntTy8: elements[i] = uint8_literal(a, ((uint8_t*) raw_bytes)[i]); break; - case IntTy16: elements[i] = uint16_literal(a, ((uint16_t*) raw_bytes)[i]); break; - case IntTy32: elements[i] = uint32_literal(a, ((uint32_t*) raw_bytes)[i]); break; - case IntTy64: elements[i] = uint64_literal(a, ((uint64_t*) raw_bytes)[i]); break; + case IntTy8: elements[i] = shd_uint8_literal(a, ((uint8_t*) raw_bytes)[i]); break; + case IntTy16: elements[i] = shd_uint16_literal(a, ((uint16_t*) raw_bytes)[i]); break; + case IntTy32: elements[i] = shd_uint32_literal(a, ((uint32_t*) raw_bytes)[i]); break; + case IntTy64: elements[i] = shd_uint64_literal(a, ((uint64_t*) raw_bytes)[i]); break; } break; } @@ -146,10 +146,10 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { assert(t->tag == Int_TAG); unsigned long long value = LLVMConstIntGetZExtValue(v); switch (t->payload.int_type.width) { - case IntTy8: return uint8_literal(a, value); - case IntTy16: return uint16_literal(a, value); - case IntTy32: return uint32_literal(a, value); - case IntTy64: return uint64_literal(a, value); + case IntTy8: return shd_uint8_literal(a, value); + case IntTy16: return shd_uint16_literal(a, value); + case IntTy32: return shd_uint32_literal(a, value); + case IntTy64: return shd_uint64_literal(a, value); } } case LLVMConstantFPValueKind: { diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 1febd6f82..34d9c8dfc 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -190,7 +190,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec int64_t i = strtoll(node->payload.untyped_number.plaintext, &endptr, 10); if (!expected_type) { bool valid_int = *endptr == '\0'; - expected_type = valid_int ? int32_type(a) : fp32_type(a); + expected_type = valid_int ? shd_int32_type(a) : shd_fp32_type(a); } expected_type = remove_uniformity_qualifier(expected_type); if (expected_type->tag == Int_TAG) { @@ -368,7 +368,7 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe } case empty_mask_op: case mask_is_thread_active_op: { - input_types = mk_nodes(a, qualified_type_helper(mask_type(a), false), qualified_type_helper(uint32_type(a), false)); + input_types = mk_nodes(a, qualified_type_helper(mask_type(a), false), qualified_type_helper(shd_uint32_type(a), false)); break; } default: { diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 56a890686..af710702f 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -166,27 +166,27 @@ static const Type* accept_qualified_type(ctxparams); static const Type* accept_numerical_type(ctxparams) { if (accept_token(ctx, i8_tok)) { - return int8_type(arena); + return shd_int8_type(arena); } else if (accept_token(ctx, i16_tok)) { - return int16_type(arena); + return shd_int16_type(arena); } else if (accept_token(ctx, i32_tok)) { - return int32_type(arena); + return shd_int32_type(arena); } else if (accept_token(ctx, i64_tok)) { - return int64_type(arena); + return shd_int64_type(arena); } else if (accept_token(ctx, u8_tok)) { - return uint8_type(arena); + return shd_uint8_type(arena); } else if (accept_token(ctx, u16_tok)) { - return uint16_type(arena); + return shd_uint16_type(arena); } else if (accept_token(ctx, u32_tok)) { - return uint32_type(arena); + return shd_uint32_type(arena); } else if (accept_token(ctx, u64_tok)) { - return uint64_type(arena); + return shd_uint64_type(arena); } else if (accept_token(ctx, f16_tok)) { - return fp16_type(arena); + return shd_fp16_type(arena); } else if (accept_token(ctx, f32_tok)) { - return fp32_type(arena); + return shd_fp32_type(arena); } else if (accept_token(ctx, f64_tok)) { - return fp64_type(arena); + return shd_fp64_type(arena); } return NULL; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 93d2c5598..17b414335 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -799,9 +799,9 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { annotations = shd_nodes_append(parser->arena, annotations, annotation_values(parser->arena, (AnnotationValues) { .name = "WorkgroupSize", .values = mk_nodes(parser->arena, - int32_literal(parser->arena, wg_size_dec->payload.literals.data[0]), - int32_literal(parser->arena, wg_size_dec->payload.literals.data[1]), - int32_literal(parser->arena, wg_size_dec->payload.literals.data[2])) + shd_int32_literal(parser->arena, wg_size_dec->payload.literals.data[0]), + shd_int32_literal(parser->arena, wg_size_dec->payload.literals.data[1]), + shd_int32_literal(parser->arena, wg_size_dec->payload.literals.data[2])) })); } else if (strcmp(entry_point_type->payload.str, "Fragment") == 0) { @@ -996,7 +996,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { if (has_element) offset = get_def_ssa_value(parser, instruction[4]); else - offset = int32_literal(parser->arena, 0); + offset = shd_int32_literal(parser->arena, 0); for (size_t i = 0; i < num_indices; i++) indices[i] = get_def_ssa_value(parser, instruction[indices_start + i]); parser->defs[result].type = Value; @@ -1008,7 +1008,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { LARRAY(const Node*, ops, 1 + num_indices); ops[0] = get_def_ssa_value(parser, instruction[3]); for (size_t i = 0; i < num_indices; i++) - ops[1 + i] = int32_literal(parser->arena, instruction[4 + i]); + ops[1 + i] = shd_int32_literal(parser->arena, instruction[4 + i]); parser->defs[result].type = Value; parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = extract_op, @@ -1023,7 +1023,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { ops[0] = get_def_ssa_value(parser, instruction[4]); ops[1] = get_def_ssa_value(parser, instruction[3]); for (size_t i = 0; i < num_indices; i++) - ops[2 + i] = int32_literal(parser->arena, instruction[5 + i]); + ops[2 + i] = shd_int32_literal(parser->arena, instruction[5 + i]); parser->defs[result].type = Value; parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = insert_op, @@ -1053,7 +1053,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { components[i] = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = extract_op, .type_arguments = shd_empty(parser->arena), - .operands = mk_nodes(parser->arena, src, int32_literal(parser->arena, index)) + .operands = mk_nodes(parser->arena, src, shd_int32_literal(parser->arena, index)) }), 1)); } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 01ef096d9..734d4af5c 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -54,7 +54,7 @@ Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size if (outputs_count > 1) { LARRAY(const Node*, extracted, outputs_count); for (size_t i = 0; i < outputs_count; i++) - extracted[i] = gen_extract_single(bb, value, int32_literal(bb->arena, i)); + extracted[i] = gen_extract_single(bb, value, shd_int32_literal(bb->arena, i)); return shd_nodes(bb->arena, outputs_count, extracted); } else if (outputs_count == 1) return shd_singleton(value); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index d25c70165..51e88d5da 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -286,33 +286,33 @@ const Node* string_lit_helper(IrArena* a, String s) { return string_lit(a, (StringLiteral) { .string = s }); } -const Type* int_type_helper(IrArena* a, bool s, IntSizes w) { return int_type(a, (Int) { .width = w, .is_signed = s }); } +const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w) { return int_type(a, (Int) { .width = w, .is_signed = s }); } -const Type* int8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = true }); } -const Type* int16_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy16, .is_signed = true }); } -const Type* int32_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy32, .is_signed = true }); } -const Type* int64_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy64, .is_signed = true }); } +const Type* shd_int8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = true }); } +const Type* shd_int16_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy16, .is_signed = true }); } +const Type* shd_int32_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy32, .is_signed = true }); } +const Type* shd_int64_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy64, .is_signed = true }); } -const Type* uint8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = false }); } -const Type* uint16_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy16, .is_signed = false }); } -const Type* uint32_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy32, .is_signed = false }); } -const Type* uint64_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy64, .is_signed = false }); } +const Type* shd_uint8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = false }); } +const Type* shd_uint16_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy16, .is_signed = false }); } +const Type* shd_uint32_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy32, .is_signed = false }); } +const Type* shd_uint64_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy64, .is_signed = false }); } -const Type* int8_literal (IrArena* arena, int8_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy8, .value = (uint64_t) (uint8_t) i, .is_signed = true }); } -const Type* int16_literal(IrArena* arena, int16_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy16, .value = (uint64_t) (uint16_t) i, .is_signed = true }); } -const Type* int32_literal(IrArena* arena, int32_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy32, .value = (uint64_t) (uint32_t) i, .is_signed = true }); } -const Type* int64_literal(IrArena* arena, int64_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy64, .value = (uint64_t) i, .is_signed = true }); } +const Node* shd_int8_literal (IrArena* arena, int8_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy8, .value = (uint64_t) (uint8_t) i, .is_signed = true }); } +const Node* shd_int16_literal(IrArena* arena, int16_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy16, .value = (uint64_t) (uint16_t) i, .is_signed = true }); } +const Node* shd_int32_literal(IrArena* arena, int32_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy32, .value = (uint64_t) (uint32_t) i, .is_signed = true }); } +const Node* shd_int64_literal(IrArena* arena, int64_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy64, .value = (uint64_t) i, .is_signed = true }); } -const Type* uint8_literal (IrArena* arena, uint8_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy8, .value = (int64_t) i }); } -const Type* uint16_literal(IrArena* arena, uint16_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy16, .value = (int64_t) i }); } -const Type* uint32_literal(IrArena* arena, uint32_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy32, .value = (int64_t) i }); } -const Type* uint64_literal(IrArena* arena, uint64_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy64, .value = i }); } +const Node* shd_uint8_literal (IrArena* arena, uint8_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy8, .value = (int64_t) i }); } +const Node* shd_uint16_literal(IrArena* arena, uint16_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy16, .value = (int64_t) i }); } +const Node* shd_uint32_literal(IrArena* arena, uint32_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy32, .value = (int64_t) i }); } +const Node* shd_uint64_literal(IrArena* arena, uint64_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy64, .value = i }); } -const Type* fp16_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy16 }); } -const Type* fp32_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy32 }); } -const Type* fp64_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy64 }); } +const Type* shd_fp16_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy16 }); } +const Type* shd_fp32_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy32 }); } +const Type* shd_fp64_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy64 }); } -const Node* fp_literal_helper(IrArena* a, FloatSizes size, double value) { +const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value) { switch (size) { case FloatTy16: assert(false); break; case FloatTy32: { diff --git a/src/shady/fold.c b/src/shady/fold.c index 9374f0d90..350401c80 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -59,12 +59,12 @@ static inline const Node* fold_constant_math(const Node* node) { #define UN_OP(primop, op) case primop##_op: \ if (all_int_literals) return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = is_signed, .width = int_width, .value = op int_literals[0]->value})); \ -else if (all_float_literals) return quote_single(arena, fp_literal_helper(arena, float_width, op get_float_literal_value(*float_literals[0]))); \ +else if (all_float_literals) return quote_single(arena, shd_fp_literal_helper(arena, float_width, op get_float_literal_value(*float_literals[0]))); \ else break; #define BIN_OP(primop, op) case primop##_op: \ if (all_int_literals) return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = is_signed, .width = int_width, .value = int_literals[0]->value op int_literals[1]->value })); \ -else if (all_float_literals) return quote_single(arena, fp_literal_helper(arena, float_width, get_float_literal_value(*float_literals[0]) op get_float_literal_value(*float_literals[1]))); \ +else if (all_float_literals) return quote_single(arena, shd_fp_literal_helper(arena, float_width, get_float_literal_value(*float_literals[0]) op get_float_literal_value(*float_literals[1]))); \ break; if (all_int_literals || all_float_literals) { @@ -78,7 +78,7 @@ break; if (all_int_literals) return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = is_signed, .width = int_width, .value = int_literals[0]->value % int_literals[1]->value })); else - return quote_single(arena, fp_literal_helper(arena, float_width, fmod(get_float_literal_value(*float_literals[0]), get_float_literal_value(*float_literals[1])))); + return quote_single(arena, shd_fp_literal_helper(arena, float_width, fmod(get_float_literal_value(*float_literals[0]), get_float_literal_value(*float_literals[1])))); case reinterpret_op: { const Type* dst_t = shd_first(payload.type_arguments); uint64_t raw_value = int_literals[0] ? int_literals[0]->value : float_literals[0]->value; @@ -110,7 +110,7 @@ break; if (all_int_literals) { uint64_t old_value = get_int_literal_value(*int_literals[0], int_literals[0]->is_signed); double value = old_value; - return quote_single(arena, fp_literal_helper(arena, dst_t->payload.float_type.width, value)); + return quote_single(arena, shd_fp_literal_helper(arena, dst_t->payload.float_type.width, value)); } else if (all_float_literals) { double old_value = get_float_literal_value(*float_literals[0]); return quote_single(arena, float_literal(arena, (FloatLiteral) { .width = dst_t->payload.float_type.width, .value = old_value })); diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 506b874a4..da07e0ad3 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -49,7 +49,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { if (!(json_object_get_boolean(json_object_object_get(op, "nullable")) || json_object_get_boolean(json_object_object_get(op, "ignore")))) { shd_growy_append_formatted(g, "%s\t\t\tif (!*pop) {\n", extra); - shd_growy_append_formatted(g, "%s\t\t\t\terror(\"operand '%s' of node '%s' cannot be null\");\n", extra, op_name, name); + shd_growy_append_formatted(g, "%s\t\t\t\tshd_error(\"operand '%s' of node '%s' cannot be null\");\n", extra, op_name, name); shd_growy_append_formatted(g, "%s\t\t\t}\n", extra); } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 283ceceef..8ffd407b1 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -121,7 +121,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { register_processed_list(r, ovariables, new_params); - const Node* payload = param(a, qualified_type_helper(uint32_type(a), false), "sp"); + const Node* payload = param(a, qualified_type_helper(shd_uint32_type(a), false), "sp"); // Keep annotations the same Nodes annotations = shd_singleton(annotation(a, (Annotation) { .name = "Exported" })); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 6138d6521..5b60dc2cf 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -54,7 +54,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); assert(is_data_type(element_type)); - const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, shd_singleton(type_decl_ref_helper(a, vctx->nom_t)), shd_singleton(int32_literal(a, shd_list_count(vctx->members)))); + const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, shd_singleton(type_decl_ref_helper(a, vctx->nom_t)), shd_singleton(shd_int32_literal(a, shd_list_count(vctx->members)))); shd_list_append(const Type*, vctx->members, element_type); StackSlot slot = { vctx->num_slots, slot_offset, element_type, AsPrivate }; diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index a7331b01b..0db6f56e6 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -65,7 +65,7 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const Nodes params = old_entry_point->payload.fun.params; for (int i = 0; i < params.count; ++i) { - const Node* addr = gen_lea(bb, arg_struct, int32_literal(a, 0), shd_singleton(int32_literal(a, i))); + const Node* addr = gen_lea(bb, arg_struct, shd_int32_literal(a, 0), shd_singleton(shd_int32_literal(a, i))); const Node* val = gen_load(bb, addr); register_processed(&ctx->rewriter, params.nodes[i], val); } diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 641dcb1d7..b3a7c6b16 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -19,9 +19,9 @@ static bool should_convert(Context* ctx, const Type* t) { static void extract_low_hi_halves(BodyBuilder* bb, const Node* src, const Node** lo, const Node** hi) { *lo = shd_first(bind_instruction(bb, prim_op(bb->arena, - (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, int32_literal(bb->arena, 0)) }))); + (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, shd_int32_literal(bb->arena, 0)) }))); *hi = shd_first(bind_instruction(bb, prim_op(bb->arena, - (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, int32_literal(bb->arena, 1)) }))); + (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, shd_int32_literal(bb->arena, 1)) }))); } static void extract_low_hi_halves_list(BodyBuilder* bb, Nodes src, const Node** lows, const Node** his) { @@ -39,14 +39,14 @@ static const Node* process(Context* ctx, const Node* node) { case Int_TAG: if (node->payload.int_type.width == IntTy64 && ctx->config->lower.int64) return record_type(a, (RecordType) { - .members = mk_nodes(a, int32_type(a), int32_type(a)) + .members = mk_nodes(a, shd_int32_type(a), shd_int32_type(a)) }); break; case IntLiteral_TAG: if (node->payload.int_literal.width == IntTy64 && ctx->config->lower.int64) { uint64_t raw = node->payload.int_literal.value; - const Node* lower = uint32_literal(a, (uint32_t) raw); - const Node* upper = uint32_literal(a, (uint32_t) (raw >> 32)); + const Node* lower = shd_uint32_literal(a, (uint32_t) raw); + const Node* upper = shd_uint32_literal(a, (uint32_t) (raw >> 32)); return tuple_helper(a, mk_nodes(a, lower, upper)); } break; diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 71dc3d580..cc84294f2 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -66,7 +66,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po size_t n = selector_value->value; assert(n < member_types.count); - const Node* offset_of = gen_primop_e(bb, offset_of_op, shd_singleton(pointed_type), shd_singleton(uint64_literal(a, n))); + const Node* offset_of = gen_primop_e(bb, offset_of_op, shd_singleton(pointed_type), shd_singleton(shd_uint64_literal(a, n))); ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, offset_of }); pointer_type = ptr_type(a, (PtrType) { diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 4b8248944..e735cd3fa 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -31,7 +31,7 @@ static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node case RecordType_TAG: case ArrType_TAG: case PackType_TAG: { - ptr = gen_lea(bb, ptr, int32_literal(a, 0), shd_singleton(int32_literal(a, 0))); + ptr = gen_lea(bb, ptr, shd_int32_literal(a, 0), shd_singleton(shd_int32_literal(a, 0))); continue; } default: break; diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 23bee4eac..af31c9bc2 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -48,9 +48,9 @@ static const Node* process(Context* ctx, const Node* old) { src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, payload.count)); - const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num_in_bytes)); + const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), bytes_to_words(bb, num_in_bytes)); - begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(uint32_type(a)), shd_singleton(uint32_literal(a, 0))); + begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); const Node* index = shd_first(l.params); set_value_name(index, "memcpy_i"); @@ -58,7 +58,7 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, shd_empty(a))); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), loaded_word); - const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, uint32_literal(a, 1))); + const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); @@ -95,16 +95,16 @@ static const Node* process(Context* ctx, const Node* old) { dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); const Node* num = rewrite_node(&ctx->rewriter, payload.count); - const Node* num_in_words = gen_conversion(bb, uint32_type(a), bytes_to_words(bb, num)); + const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), bytes_to_words(bb, num)); - begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(uint32_type(a)), shd_singleton(uint32_literal(a, 0))); + begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); const Node* index = shd_first(l.params); set_value_name(index, "memset_i"); Node* loop_case = l.loop_body; BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), src_value); - const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, uint32_literal(a, 1))); + const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 237280d43..c744ceb3c 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -20,7 +20,7 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { return *found; BodyBuilder* bb = begin_block_pure(a); - const Node* nul = gen_reinterpret_cast(bb, t, uint64_literal(a, 0)); + const Node* nul = gen_reinterpret_cast(bb, t, shd_uint64_literal(a, 0)); Node* decl = constant(ctx->rewriter.dst_module, shd_singleton(annotation(a, (Annotation) { .name = "Generated", })), t, format_string_interned(a, "nullptr_%s", name_type_safe(a, t))); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index bf5eeddf7..16165db7f 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -95,7 +95,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type String template = format_string_interned(a, "loaded %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); const Node* widened = acc; if (element_type->payload.int_type.width < IntTy32) - widened = gen_conversion(bb, uint32_type(a), acc); + widened = gen_conversion(bb, shd_uint32_type(a), acc); gen_debug_printf(bb, template, mk_nodes(a, widened, address)); } acc = gen_reinterpret_cast(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = element_type->payload.int_type.is_signed }), acc);\ @@ -198,7 +198,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element String template = format_string_interned(a, "stored %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); const Node* widened = value; if (element_type->payload.int_type.width < IntTy32) - widened = gen_conversion(bb, uint32_type(a), value); + widened = gen_conversion(bb, shd_uint32_type(a), value); gen_debug_printf(bb, template, mk_nodes(a, widened, address)); } return; @@ -211,7 +211,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element case RecordType_TAG: { Nodes member_types = element_type->payload.record_type.members; for (size_t i = 0; i < member_types.count; i++) { - const Node* extracted_value = prim_op(a, (PrimOp) { .op = extract_op, .operands = mk_nodes(a, value, int32_literal(a, i)), .type_arguments = shd_empty(a) }); + const Node* extracted_value = prim_op(a, (PrimOp) { .op = extract_op, .operands = mk_nodes(a, value, shd_int32_literal(a, i)), .type_arguments = shd_empty(a) }); const Node* field_offset = gen_primop_e(bb, offset_of_op, shd_singleton(element_type), shd_singleton(size_t_literal(a, i))); const Node* adjusted_offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, address, field_offset)); gen_serialisation(ctx, bb, member_types.nodes[i], arr, adjusted_offset, extracted_value); @@ -236,7 +236,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Type* component_type = get_fill_type_element_type(element_type); const Node* offset = address; for (size_t i = 0; i < components_count; i++) { - gen_serialisation(ctx, bb, component_type, arr, offset, gen_extract(bb, value, shd_singleton(int32_literal(a, i)))); + gen_serialisation(ctx, bb, component_type, arr, offset, gen_extract(bb, value, shd_singleton(shd_int32_literal(a, i)))); offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, shd_singleton(component_type), shd_empty(a)))); } return; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 057ff4afe..ed697d6fb 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -47,7 +47,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); const Node* element_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); - element_size = gen_conversion(bb, uint32_type(a), element_size); + element_size = gen_conversion(bb, shd_uint32_type(a), element_size); // TODO somehow annotate the uniform guys as uniform const Node* stack_pointer = ctx->stack_pointer; @@ -58,7 +58,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { if (!push) // for pop, we decrease the stack size first stack_size = gen_primop_ce(bb, sub_op, 2, (const Node* []) { stack_size, element_size}); - const Node* addr = gen_lea(bb, ctx->stack, int32_literal(a, 0), shd_singleton(stack_size)); + const Node* addr = gen_lea(bb, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); assert(get_unqualified_type(addr->type)->tag == PtrType_TAG); AddressSpace addr_space = get_unqualified_type(addr->type)->payload.ptr_type.address_space; @@ -102,7 +102,7 @@ static const Node* process_node(Context* ctx, const Node* old) { // is this an old forgotten workaround ? if (ctx->stack) { const Node* stack_pointer = ctx->stack_pointer; - gen_store(bb, stack_pointer, uint32_literal(a, 0)); + gen_store(bb, stack_pointer, shd_uint32_literal(a, 0)); } register_processed(r, get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(new, finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body))); @@ -131,7 +131,7 @@ static const Node* process_node(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); const Node* stack_pointer = ctx->stack_pointer; const Node* stack_size = gen_load(bb, stack_pointer); - const Node* stack_base_ptr = gen_lea(bb, ctx->stack, int32_literal(a, 0), shd_singleton(stack_size)); + const Node* stack_base_ptr = gen_lea(bb, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { gen_debug_printf(bb, "trace: stack_size=%d\n", shd_singleton(stack_size)); } @@ -189,12 +189,12 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { }; if (config->per_thread_stack_size > 0) { - const Type* stack_base_element = uint8_type(a); + const Type* stack_base_element = shd_uint8_type(a); const Type* stack_arr_type = arr_type(a, (ArrType) { .element_type = stack_base_element, - .size = uint32_literal(a, config->per_thread_stack_size), + .size = shd_uint32_literal(a, config->per_thread_stack_size), }); - const Type* stack_counter_t = uint32_type(a); + const Type* stack_counter_t = shd_uint32_type(a); Nodes annotations = mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" })); @@ -203,7 +203,7 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { // Pointers into those arrays Node* stack_ptr_decl = global_var(dst, shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Logical" })), stack_counter_t, "stack_ptr", AsPrivate); - stack_ptr_decl->payload.global_variable.init = uint32_literal(a, 0); + stack_ptr_decl->payload.global_variable.init = shd_uint32_literal(a, 0); ctx.stack = ref_decl_helper(a, stack_decl); ctx.stack_pointer = ref_decl_helper(a, stack_ptr_decl); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 8c955b247..58165eb72 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -55,29 +55,29 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co Nodes element_types = get_composite_type_element_types(t); LARRAY(const Node*, elements, element_types.count); for (size_t i = 0; i < element_types.count; i++) { - const Node* e = gen_extract(bb, param, shd_singleton(uint32_literal(a, i))); + const Node* e = gen_extract(bb, param, shd_singleton(shd_uint32_literal(a, i))); elements[i] = build_subgroup_first(ctx, bb, scope, e); } return composite_helper(a, original_t, shd_nodes(a, element_types.count, elements)); } case Type_Int_TAG: { if (t->payload.int_type.width == IntTy64) { - const Node* hi = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, param, int32_literal(a, 32))); - hi = convert_int_zero_extend(bb, int32_type(a), hi); - const Node* lo = convert_int_zero_extend(bb, int32_type(a), param); + const Node* hi = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, param, shd_int32_literal(a, 32))); + hi = convert_int_zero_extend(bb, shd_int32_type(a), hi); + const Node* lo = convert_int_zero_extend(bb, shd_int32_type(a), param); hi = build_subgroup_first(ctx, bb, scope, hi); lo = build_subgroup_first(ctx, bb, scope, lo); const Node* it = int_type(a, (Int) { .width = IntTy64, .is_signed = t->payload.int_type.is_signed }); hi = convert_int_zero_extend(bb, it, hi); lo = convert_int_zero_extend(bb, it, lo); - hi = gen_primop_e(bb, lshift_op, shd_empty(a), mk_nodes(a, hi, int32_literal(a, 32))); + hi = gen_primop_e(bb, lshift_op, shd_empty(a), mk_nodes(a, hi, shd_int32_literal(a, 32))); return gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, lo, hi)); } break; } case Type_PtrType_TAG: { - param = gen_reinterpret_cast(bb, uint64_type(a), param); - return gen_reinterpret_cast(bb, t, generate(ctx, bb, scope, uint64_type(a), param)); + param = gen_reinterpret_cast(bb, shd_uint64_type(a), param); + return gen_reinterpret_cast(bb, t, generate(ctx, bb, scope, shd_uint64_type(a), param)); } default: break; } diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 011b9951c..d4847adf0 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -48,7 +48,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* ndecl = rewrite_node(&ctx->rewriter, odecl); assert(ctx->bb); const Node* index = gen_builtin_load(ctx->rewriter.dst_module, ctx->bb, BuiltinSubgroupId); - const Node* slice = gen_lea(ctx->bb, ref_decl_helper(a, ndecl), int32_literal(a, 0), mk_nodes(a, index)); + const Node* slice = gen_lea(ctx->bb, ref_decl_helper(a, ndecl), shd_int32_literal(a, 0), mk_nodes(a, index)); return slice; } case GlobalVariable_TAG: { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 80b7a95a4..f91f02d79 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -38,7 +38,7 @@ static const Node* process(Context* ctx, const Node* old); static const Type* lowered_fn_type(Context* ctx) { IrArena* a = ctx->rewriter.dst_arena; - return int_type_helper(a, false, ctx->config->target.memory.ptr_size); + return shd_int_type_helper(a, false, ctx->config->target.memory.ptr_size); } static const Node* fn_ptr_as_value(Context* ctx, FnPtr ptr) { @@ -88,7 +88,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { // Initialise next_fn/next_mask to the entry function const Node* jump_fn = access_decl(&ctx->rewriter, "builtin_fork"); - const Node* fn_addr = uint32_literal(a, get_fn_ptr(ctx, old)); + const Node* fn_addr = shd_uint32_literal(a, get_fn_ptr(ctx, old)); // fn_addr = gen_conversion(bb, lowered_fn_type(ctx), fn_addr); gen_call(bb, jump_fn, shd_singleton(fn_addr)); @@ -191,7 +191,7 @@ static const Node* process(Context* ctx, const Node* old) { break; case ShadyOpCreateJoinPoint: callee_name = "builtin_create_control_point"; - args = shd_change_node_at_index(a, args, 0, prim_op_helper(a, convert_op, shd_singleton(uint32_type(a)), shd_singleton(args.nodes[0]))); + args = shd_change_node_at_index(a, args, 0, prim_op_helper(a, convert_op, shd_singleton(shd_uint32_type(a)), shd_singleton(args.nodes[0]))); break; } return call(a, (Call) { @@ -209,7 +209,7 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, payload.args)); const Node* target = rewrite_node(&ctx->rewriter, payload.callee); - target = gen_conversion(bb, uint32_type(a), target); + target = gen_conversion(bb, shd_uint32_type(a), target); gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); return finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) })); @@ -227,10 +227,10 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, old->payload.join.args)); - const Node* jp_payload = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, int32_literal(a, 2))); + const Node* jp_payload = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 2))); gen_push_value_stack(bb, jp_payload); - const Node* dst = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, int32_literal(a, 1))); - const Node* tree_node = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, int32_literal(a, 0))); + const Node* dst = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 1))); + const Node* tree_node = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 0))); gen_call(bb, access_decl(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); return finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) })); @@ -238,7 +238,7 @@ static const Node* process(Context* ctx, const Node* old) { case PtrType_TAG: { const Node* pointee = old->payload.ptr_type.pointed_type; if (pointee->tag == FnType_TAG) { - const Type* emulated_fn_ptr_type = uint64_type(a); + const Type* emulated_fn_ptr_type = shd_uint64_type(a); return emulated_fn_ptr_type; } break; @@ -294,7 +294,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { // Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : shd_nodes(a, 0, NULL)); // gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a), loop_inside_case); - begin_loop_helper_t l = begin_loop_helper(dispatcher_body_builder, shd_empty(a), count_iterations ? shd_singleton(int32_type(a)) : shd_empty(a), count_iterations ? shd_singleton(int32_literal(a, 0)) : shd_empty(a)); + begin_loop_helper_t l = begin_loop_helper(dispatcher_body_builder, shd_empty(a), count_iterations ? shd_singleton(shd_int32_type(a)) : shd_empty(a), count_iterations ? shd_singleton(shd_int32_literal(a, 0)) : shd_empty(a)); Node* loop_inside_case = l.loop_body; if (count_iterations) iterations_count_param = shd_first(l.params); @@ -316,11 +316,11 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* iteration_count_plus_one = NULL; if (count_iterations) - iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, shd_empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, 1))); + iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, 1))); if (ctx->config->shader_diagnostics.max_top_iterations > 0) { begin_control_t c = begin_control(loop_body_builder, shd_empty(a)); - const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, shd_empty(a), mk_nodes(a, iterations_count_param, int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); + const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); Node* bail_case = case_(a, shd_empty(a)); const Node* break_terminator = join(a, (Join) { .args = shd_empty(a), .join_point = l.break_jp, .mem = get_abstraction_mem(bail_case) }); set_abstraction_body(bail_case, break_terminator); @@ -367,7 +367,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { .false_jump = jump_helper(a, zero_if_false, shd_empty(a), get_abstraction_mem(zero_case_lam)), })); - const Node* zero_lit = uint64_literal(a, 0); + const Node* zero_lit = shd_uint64_literal(a, 0); shd_list_append(const Node*, literals, zero_lit); const Node* zero_jump = jump_helper(a, zero_case_lam, shd_empty(a), bb_mem(loop_body_builder)); shd_list_append(const Node*, jumps, zero_jump); @@ -379,7 +379,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { if (lookup_annotation(decl, "Leaf")) continue; - const Node* fn_lit = uint32_literal(a, get_fn_ptr(ctx, decl)); + const Node* fn_lit = shd_uint32_literal(a, get_fn_ptr(ctx, decl)); Node* if_true_case = case_(a, shd_empty(a)); BodyBuilder* if_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index f5ec24c6f..182b60470 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -23,12 +23,12 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { for (size_t i = 0; i < width; i++) { LARRAY(const Node*, nops, noperands.count); for (size_t j = 0; j < noperands.count; j++) - nops[j] = gen_extract(bb, noperands.nodes[j], shd_singleton(int32_literal(a, i))); + nops[j] = gen_extract(bb, noperands.nodes[j], shd_singleton(shd_int32_literal(a, i))); elements[i] = gen_primop_e(bb, old->payload.prim_op.op, shd_empty(a), shd_nodes(a, noperands.count, nops)); } const Type* t = arr_type(a, (ArrType) { .element_type = rewrite_node(&ctx->rewriter, dst_type), - .size = int32_literal(a, width) + .size = shd_int32_literal(a, width) }); return yield_values_and_wrap_in_block(bb, shd_singleton(composite_helper(a, t, shd_nodes(a, width, elements)))); } @@ -40,7 +40,7 @@ static const Node* process(Context* ctx, const Node* node) { case PackType_TAG: { return arr_type(a, (ArrType) { .element_type = rewrite_node(&ctx->rewriter, node->payload.pack_type.element_type), - .size = int32_literal(a, node->payload.pack_type.width) + .size = shd_int32_literal(a, node->payload.pack_type.width) }); } case PrimOp_TAG: { diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 06d076957..f96d801c9 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -83,8 +83,8 @@ static const Node* process(Context* ctx, const Node* node) { const Node* workgroup_id[3]; const Node* num_workgroups[3]; for (int dim = 0; dim < 3; dim++) { - workgroup_id[dim] = param(a, qualified_type_helper(uint32_type(a), false), names[dim]); - num_workgroups[dim] = gen_extract(bb, workgroup_num_vec3, shd_singleton(uint32_literal(a, dim))); + workgroup_id[dim] = param(a, qualified_type_helper(shd_uint32_type(a), false), names[dim]); + num_workgroups[dim] = gen_extract(bb, workgroup_num_vec3, shd_singleton(shd_uint32_literal(a, dim))); } // Prepare variables for iterating inside workgroups @@ -98,8 +98,8 @@ static const Node* process(Context* ctx, const Node* node) { num_subgroups[2] = a->config.specializations.workgroup_size[2]; String names2[] = { "sgx", "sgy", "sgz" }; for (int dim = 0; dim < 3; dim++) { - subgroup_id[dim] = param(a, qualified_type_helper(uint32_type(a), false), names2[dim]); - num_subgroups_literals[dim] = uint32_literal(a, num_subgroups[dim]); + subgroup_id[dim] = param(a, qualified_type_helper(shd_uint32_type(a), false), names2[dim]); + num_subgroups_literals[dim] = shd_uint32_literal(a, num_subgroups[dim]); } Node* cases[6]; @@ -127,19 +127,19 @@ static const Node* process(Context* ctx, const Node* node) { // BodyBuilder* bb2 = begin_block_with_side_effects(a, bb_mem(builders[5])); BodyBuilder* bb2 = builders[5]; // write the workgroup ID - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); + gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); // write the local ID const Node* local_id[3]; // local_id[0] = SUBGROUP_SIZE * subgroup_id[0] + subgroup_local_id - local_id[0] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); + local_id[0] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); local_id[1] = subgroup_id[1]; local_id[2] = subgroup_id[2]; - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); + gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); // write the global ID const Node* global_id[3]; for (int dim = 0; dim < 3; dim++) - global_id[dim] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); + global_id[dim] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); + gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID gen_call(bb2, fn_addr_helper(a, inner), wparams); @@ -158,10 +158,10 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* body_bb = builders[depth]; set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) { - .args = shd_singleton(gen_primop_e(body_bb, add_op, shd_empty(a), mk_nodes(a, params[dim], uint32_literal(a, 1)))), + .args = shd_singleton(gen_primop_e(body_bb, add_op, shd_empty(a), mk_nodes(a, params[dim], shd_uint32_literal(a, 1)))), .mem = bb_mem(body_bb) }))); - gen_loop(depth > 0 ? builders[depth - 1] : bb, shd_empty(a), shd_singleton(uint32_literal(a, 0)), loop_body); + gen_loop(depth > 0 ? builders[depth - 1] : bb, shd_empty(a), shd_singleton(shd_uint32_literal(a, 0)), loop_body); } } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 849a96708..3ad91dd23 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -265,7 +265,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { control_ctx.control_stack = &control_entry; // Set the depth for threads entering the control body - gen_store(bb_prelude, ctx->level_ptr, int32_literal(a, control_entry.depth)); + gen_store(bb_prelude, ctx->level_ptr, shd_int32_literal(a, control_entry.depth)); // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() Node* tail = case_(a, shd_empty(a)); @@ -278,7 +278,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { // Wrap the tail in a guarded if, to handle 'far' joins const Node* level_value = gen_load(bb_tail, ctx->level_ptr); - const Node* guard = prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }); + const Node* guard = prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, shd_int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }); Node* true_case = case_(a, shd_empty(a)); register_processed(r, get_abstraction_mem(get_structured_construct_tail(body)), get_abstraction_mem(true_case)); set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); @@ -295,7 +295,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { longjmp(ctx->bail, 1); BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - gen_store(bb, ctx->level_ptr, int32_literal(a, control->depth - 1)); + gen_store(bb, ctx->level_ptr, shd_int32_literal(a, control->depth - 1)); Nodes args = rewrite_nodes(&ctx->rewriter, body->payload.join.args); for (size_t i = 0; i < args.count; i++) { @@ -356,9 +356,9 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); - const Node* ptr = gen_local_alloc(bb, int32_type(a)); + const Node* ptr = gen_local_alloc(bb, shd_int32_type(a)); set_value_name(ptr, "cf_depth"); - gen_store(bb, ptr, int32_literal(a, 0)); + gen_store(bb, ptr, shd_int32_literal(a, 0)); ctx2.level_ptr = ptr; ctx2.fn = new; struct Dict* tmp_processed = shd_clone_dict(ctx->rewriter.map); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index a8129d117..ec73bf00e 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -148,7 +148,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { const Node* exit_destination_alloca = NULL; if (exiting_nodes_count > 1) - exit_destination_alloca = gen_stack_alloc(outer_bb, int32_type(arena)); + exit_destination_alloca = gen_stack_alloc(outer_bb, shd_int32_type(arena)); const Node* join_token_exit = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { .yield_types = shd_empty(arena) @@ -215,7 +215,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { gen_store(exit_wrapper_bb, exits[i].params[j].alloca, exit_wrapper_params.nodes[j]); // Set the destination if there's more than one option if (exiting_nodes_count > 1) - gen_store(exit_wrapper_bb, exit_destination_alloca, int32_literal(arena, i)); + gen_store(exit_wrapper_bb, exit_destination_alloca, shd_int32_literal(arena, i)); set_abstraction_body(exits[i].wrapper, finish_body_with_join(exit_wrapper_bb, join_token_exit, shd_empty(arena))); } @@ -270,7 +270,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { recovered_args[j] = prim_op_helper(arena, subgroup_assume_uniform_op, shd_empty(arena), shd_singleton(recovered_args[j])); } - exit_numbers[i] = int32_literal(arena, i); + exit_numbers[i] = shd_int32_literal(arena, i); set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, shd_nodes(arena, exits[i].params_count, recovered_args))); exit_jumps[i] = jump_helper(arena, exit_bb, shd_empty(arena), bb_mem(outer_bb)); } diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index 034634210..6921719ca 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -19,7 +19,7 @@ typedef struct { static Nodes to_ids(IrArena* a, Nodes in) { LARRAY(const Node*, arr, in.count); for (size_t i = 0; i < in.count; i++) - arr[i] = uint32_literal(a, in.nodes[i]->id); + arr[i] = shd_uint32_literal(a, in.nodes[i]->id); return shd_nodes(a, in.count, arr); } diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 5213f0280..0b34f1cb1 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -21,12 +21,12 @@ static const Node* process(Context* ctx, const Node* node) { case PrimOp_TAG: { Builtin b; if (is_builtin_load_op(node, &b) && b == BuiltinWorkgroupSize) { - const Type* t = pack_type(a, (PackType) { .element_type = uint32_type(a), .width = 3 }); + const Type* t = pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }); uint32_t wg_size[3]; wg_size[0] = a->config.specializations.workgroup_size[0]; wg_size[1] = a->config.specializations.workgroup_size[1]; wg_size[2] = a->config.specializations.workgroup_size[2]; - return composite_helper(a, t, mk_nodes(a, uint32_literal(a, wg_size[0]), uint32_literal(a, wg_size[1]), uint32_literal(a, wg_size[2]) )); + return composite_helper(a, t, mk_nodes(a, shd_uint32_literal(a, wg_size[0]), shd_uint32_literal(a, wg_size[1]), shd_uint32_literal(a, wg_size[2]) )); } break; } @@ -55,7 +55,7 @@ static const Node* process(Context* ctx, const Node* node) { uint32_t subgroups_per_wg = (wg_size[0] * wg_size[1] * wg_size[2]) / ctx->config->specialization.subgroup_size; if (subgroups_per_wg == 0) subgroups_per_wg = 1; // uh-oh - ncnst->payload.constant.value = uint32_literal(a, subgroups_per_wg); + ncnst->payload.constant.value = shd_uint32_literal(a, subgroups_per_wg); } return ncnst; } diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index f72dee56e..580d520bd 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -20,7 +20,7 @@ static const Node* process(Context* ctx, const Node* node) { case Constant_TAG: { Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { - ncnst->payload.constant.value = uint32_literal(a, ctx->config->specialization.subgroup_size); + ncnst->payload.constant.value = shd_uint32_literal(a, ctx->config->specialization.subgroup_size); } return ncnst; } diff --git a/src/shady/transform/internal_constants.h b/src/shady/transform/internal_constants.h index 607eabcbc..3e7a7dce1 100644 --- a/src/shady/transform/internal_constants.h +++ b/src/shady/transform/internal_constants.h @@ -4,8 +4,8 @@ #include "shady/ir.h" #define INTERNAL_CONSTANTS(X) \ -X(SUBGROUP_SIZE, uint32_type(arena), uint32_literal(arena, 64)) \ -X(SUBGROUPS_PER_WG, uint32_type(arena), uint32_literal(arena, 1)) \ +X(SUBGROUP_SIZE, shd_uint32_type(arena), shd_uint32_literal(arena, 64)) \ +X(SUBGROUPS_PER_WG, shd_uint32_type(arena), shd_uint32_literal(arena, 1)) \ typedef struct CompilerConfig_ CompilerConfig; void generate_dummy_constants(const CompilerConfig* config, Module*); diff --git a/src/shady/type.c b/src/shady/type.c index 9ebca342c..06e13c0aa 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -182,7 +182,7 @@ bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { const Type* get_actual_mask_type(IrArena* arena) { switch (arena->config.specializations.subgroup_mask_representation) { case SubgroupMaskAbstract: return mask_type(arena); - case SubgroupMaskInt64: return uint64_type(arena); + case SubgroupMaskInt64: return shd_uint64_type(arena); default: assert(false); } } @@ -429,8 +429,8 @@ const Type* check_type_false_lit(IrArena* arena) { return qualified_type(arena, const Type* check_type_string_lit(IrArena* arena, StringLiteral str_lit) { const Type* t = arr_type(arena, (ArrType) { - .element_type = int8_type(arena), - .size = int32_literal(arena, strlen(str_lit.string)) + .element_type = shd_int8_type(arena), + .size = shd_int32_literal(arena, strlen(str_lit.string)) }); return qualified_type(arena, (QualifiedType) { .type = t, @@ -1126,16 +1126,16 @@ const Type* check_type_pop_stack(IrArena* a, PopStack payload) { } const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { - assert(get_unqualified_type(payload.value->type) == uint32_type(a)); + assert(get_unqualified_type(payload.value->type) == shd_uint32_type(a)); return qualified_type_helper(unit_type(a), true); } const Type* check_type_get_stack_size(IrArena* a, SHADY_UNUSED GetStackSize ss) { - return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = uint32_type(a) }); + return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = shd_uint32_type(a) }); } const Type* check_type_get_stack_base_addr(IrArena* a, SHADY_UNUSED GetStackBaseAddr gsba) { - const Node* ptr = ptr_type(a, (PtrType) { .pointed_type = uint8_type(a), .address_space = AsPrivate}); + const Node* ptr = ptr_type(a, (PtrType) { .pointed_type = shd_uint8_type(a), .address_space = AsPrivate}); return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = ptr }); } diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index c8f537189..0cefbaa4b 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -285,7 +285,7 @@ const Node* get_fill_type_element_type(const Type* composite_t) { const Node* get_fill_type_size(const Type* composite_t) { switch (composite_t->tag) { case ArrType_TAG: return composite_t->payload.arr_type.size; - case PackType_TAG: return int32_literal(composite_t->arena, composite_t->payload.pack_type.width); + case PackType_TAG: return shd_int32_literal(composite_t->arena, composite_t->payload.pack_type.width); default: shd_error("fill values need to be either array or pack types") } } diff --git a/test/test_builder.c b/test/test_builder.c index 2237d6ebb..d69f72669 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -16,7 +16,7 @@ static void test_body_builder_constants(IrArena* a) { BodyBuilder* bb = begin_block_pure(a); - const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, int32_literal(a, 4), int32_literal(a, 38))); + const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, shd_int32_literal(a, 4), shd_int32_literal(a, 38))); const Node* result = yield_value_and_wrap_in_block(bb, sum); CHECK(sum == result, exit(-1)); CHECK(result->tag == IntLiteral_TAG, exit(-1)); @@ -27,11 +27,11 @@ static void test_body_builder_fun_body(IrArena* a) { Module* m = new_module(a, "test_module"); const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { .address_space = AsGeneric, - .pointed_type = uint32_type(a), + .pointed_type = shd_uint32_type(a), }), false), NULL); const Node* p2 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { .address_space = AsGeneric, - .pointed_type = uint32_type(a), + .pointed_type = shd_uint32_type(a), }), false), NULL); // const Node* p3 = param(a, qualified_type_helper(bool_type(a), false), NULL); // const Node* p4 = param(a, qualified_type_helper(uint32_type(a), false), NULL); @@ -42,9 +42,9 @@ static void test_body_builder_fun_body(IrArena* a) { CHECK(p1_value->tag == Load_TAG, exit(-1)); Node* true_case = case_(a, shd_empty(a)); BodyBuilder* tc_builder = begin_body_with_mem(a, get_abstraction_mem(true_case)); - gen_store(tc_builder, p1, uint32_literal(a, 0)); + gen_store(tc_builder, p1, shd_uint32_literal(a, 0)); set_abstraction_body(true_case, finish_body_with_selection_merge(tc_builder, shd_empty(a))); - gen_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, uint32_literal(a, 0))), true_case, NULL); + gen_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, shd_uint32_literal(a, 0))), true_case, NULL); const Node* p2_value = gen_load(bb, p2); @@ -89,7 +89,7 @@ static void test_body_builder_impure_block(IrArena* a) { Module* m = new_module(a, "test_module"); const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { .address_space = AsGeneric, - .pointed_type = uint32_type(a), + .pointed_type = shd_uint32_type(a), }), false), NULL); Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); @@ -97,7 +97,7 @@ static void test_body_builder_impure_block(IrArena* a) { const Node* first_load = gen_load(bb, p1); BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); - gen_store(block_builder, p1, uint32_literal(a, 0)); + gen_store(block_builder, p1, shd_uint32_literal(a, 0)); bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, shd_empty(a))); const Node* second_load = gen_load(bb, p1); @@ -128,7 +128,7 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { Module* m = new_module(a, "test_module"); const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { .address_space = AsGeneric, - .pointed_type = uint32_type(a), + .pointed_type = shd_uint32_type(a), }), false), NULL); Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); @@ -138,9 +138,9 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); Node* if_true_case = case_(a, shd_empty(a)); BodyBuilder* if_true_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); - gen_store(if_true_builder, p1, uint32_literal(a, 0)); + gen_store(if_true_builder, p1, shd_uint32_literal(a, 0)); set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_true_builder, shd_empty(a))); - gen_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, uint32_literal(a, 0))), if_true_case, NULL); + gen_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, shd_uint32_literal(a, 0))), if_true_case, NULL); bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, shd_empty(a))); const Node* second_load = gen_load(bb, p1); diff --git a/test/test_math.c b/test/test_math.c index 5d1b05bb1..a26ee9d8b 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -48,25 +48,25 @@ static void test_int_literals(IrArena* a) { .is_signed = false, .value = 0 }; - check_int_literal_against_reference(a, uint8_literal(a, 0), ref_zero_u8); + check_int_literal_against_reference(a, shd_uint8_literal(a, 0), ref_zero_u8); IntLiteral ref_one_u8 = { .width = IntTy8, .is_signed = false, .value = 1 }; - check_int_literal_against_reference(a, uint8_literal(a, 1), ref_one_u8); + check_int_literal_against_reference(a, shd_uint8_literal(a, 1), ref_one_u8); IntLiteral ref_one_i8 = { .width = IntTy8, .is_signed = true, .value = 1 }; - check_int_literal_against_reference(a, int8_literal(a, 1), ref_one_i8); + check_int_literal_against_reference(a, shd_int8_literal(a, 1), ref_one_i8); IntLiteral ref_minus_one_i8 = { .width = IntTy8, .is_signed = true, .value = 255 }; - check_int_literal_against_reference(a, int8_literal(a, -1), ref_minus_one_i8); + check_int_literal_against_reference(a, shd_int8_literal(a, -1), ref_minus_one_i8); // Check sign extension works right int64_t i64_test_values[] = { 0, 1, 255, 256, -1, 65536, 65535, INT64_MAX, INT64_MIN }; for (size_t i = 0; i < sizeof(i64_test_values) / sizeof(i64_test_values[0]); i++) { From f268eeaec21f0d04cc05f753679e99ff15070d30 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 15:41:25 +0200 Subject: [PATCH 602/693] slim: added shd_ prefix --- src/driver/driver.c | 2 +- src/frontend/slim/bind.c | 2 +- src/frontend/slim/infer.c | 2 +- src/frontend/slim/normalize.c | 2 +- src/frontend/slim/parser.c | 116 +++++++++++++++++--------------- src/frontend/slim/parser.h | 2 +- src/frontend/slim/slim_driver.c | 14 ++-- src/frontend/slim/token.c | 16 ++--- src/frontend/slim/token.h | 12 ++-- src/shady/compile.c | 2 +- 10 files changed, 89 insertions(+), 81 deletions(-) diff --git a/src/driver/driver.c b/src/driver/driver.c index 6fbbcf1d2..bd75b160a 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -64,7 +64,7 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang .front_end = lang == SrcSlim, }; shd_debugvv_print("Parsing: \n%s\n", file_contents); - *mod = parse_slim_module(config, pconfig, (const char*) file_contents, name); + *mod = shd_parse_slim_module(config, pconfig, (const char*) file_contents, name); } } return NoError; diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 26f4ac10a..7fb15e047 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -366,7 +366,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { return recreate_node_identity(&ctx->rewriter, node); } -Module* bind_program(SHADY_UNUSED const CompilerConfig* compiler_config, Module* src) { +Module* slim_pass_bind(SHADY_UNUSED const CompilerConfig* compiler_config, Module* src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); assert(!src->arena->config.name_bound); aconfig.name_bound = true; diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 34d9c8dfc..4b550a5c4 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -603,7 +603,7 @@ static const Node* process(Context* src_ctx, const Node* node) { assert(false); } -Module* infer_program(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* slim_pass_infer(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); assert(!aconfig.check_types); aconfig.check_types = true; diff --git a/src/frontend/slim/normalize.c b/src/frontend/slim/normalize.c index 708164273..24276ec12 100644 --- a/src/frontend/slim/normalize.c +++ b/src/frontend/slim/normalize.c @@ -110,7 +110,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return new; } -Module* normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* slim_pass_normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); aconfig.check_op_classes = true; IrArena* a = new_ir_arena(&aconfig); diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index af710702f..442fda294 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -56,7 +56,7 @@ INFIX_OPERATORS() #define ctx config, contents, mod, arena, tokenizer static void error_with_loc(ctxparams) { - Loc loc = current_loc(tokenizer); + Loc loc = shd_current_loc(tokenizer); size_t startline = loc.line - 2; if (startline < 1) startline = 1; size_t endline = startline + 5; @@ -139,17 +139,17 @@ static void expect_impl(ctxparams, bool condition, const char* format, ...) { } static bool accept_token(ctxparams, TokenTag tag) { - if (curr_token(tokenizer).tag == tag) { - next_token(tokenizer); + if (shd_curr_token(tokenizer).tag == tag) { + shd_next_token(tokenizer); return true; } return false; } static const char* accept_identifier(ctxparams) { - Token tok = curr_token(tokenizer); + Token tok = shd_curr_token(tokenizer); if (tok.tag == identifier_tok) { - next_token(tokenizer); + shd_next_token(tokenizer); size_t size = tok.end - tok.start; return string_sized(arena, (int) size, &contents[tok.start]); } @@ -196,7 +196,7 @@ static const Node* accept_numerical_literal(ctxparams) { bool negate = accept_token(ctx, minus_tok); - Token tok = curr_token(tokenizer); + Token tok = shd_curr_token(tokenizer); size_t size = tok.end - tok.start; String str = string_sized(arena, (int) size, &contents[tok.start]); @@ -205,7 +205,7 @@ static const Node* accept_numerical_literal(ctxparams) { if (negate) syntax_error("hexadecimal literals can't start with '-'"); case dec_lit_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); break; } default: { @@ -258,7 +258,7 @@ static const Node* make_unbound(IrArena* a, const Node* mem, String identifier) } static const Node* accept_value(ctxparams, BodyBuilder* bb) { - Token tok = curr_token(tokenizer); + Token tok = shd_curr_token(tokenizer); size_t size = tok.end - tok.start; const Node* number = accept_numerical_literal(ctx); @@ -268,7 +268,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { switch (tok.tag) { case identifier_tok: { const char* id = string_sized(arena, (int) size, &contents[tok.start]); - next_token(tokenizer); + shd_next_token(tokenizer); Op op = PRIMOPS_COUNT; for (size_t i = 0; i < PRIMOPS_COUNT; i++) { @@ -328,29 +328,31 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { } case hex_lit_tok: case dec_lit_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); return untyped_number(arena, (UntypedNumber) { .plaintext = string_sized(arena, (int) size, &contents[tok.start]) }); } case string_lit_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); char* unescaped = calloc(size + 1, 1); size_t j = shd_apply_escape_codes(&contents[tok.start], size, unescaped); const Node* lit = string_lit(arena, (StringLiteral) {.string = string_sized(arena, (int) j, unescaped) }); free(unescaped); return lit; } - case true_tok: next_token(tokenizer); return true_lit(arena); - case false_tok: next_token(tokenizer); return false_lit(arena); + case true_tok: + shd_next_token(tokenizer); return true_lit(arena); + case false_tok: + shd_next_token(tokenizer); return false_lit(arena); case lpar_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); if (accept_token(ctx, rpar_tok)) { return tuple_helper(arena, shd_empty(arena)); } const Node* atom = expect_operand(ctx, bb); - if (curr_token(tokenizer).tag == rpar_tok) { - next_token(tokenizer); + if (shd_curr_token(tokenizer).tag == rpar_tok) { + shd_next_token(tokenizer); } else { struct List* elements = shd_new_list(const Node*); shd_list_append(const Node*, elements, atom); @@ -368,7 +370,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { return atom; } case composite_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); const Type* elem_type = accept_unqualified_type(ctx); expect(elem_type, "composite data type"); Nodes elems = expect_operands(ctx, bb); @@ -379,15 +381,23 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { } static AddressSpace accept_address_space(ctxparams) { - switch (curr_token(tokenizer).tag) { - case global_tok: next_token(tokenizer); return AsGlobal; - case private_tok: next_token(tokenizer); return AsPrivate; - case shared_tok: next_token(tokenizer); return AsShared; - case subgroup_tok: next_token(tokenizer); return AsSubgroup; - case generic_tok: next_token(tokenizer); return AsGeneric; - case input_tok: next_token(tokenizer); return AsInput; - case output_tok: next_token(tokenizer); return AsOutput; - case extern_tok: next_token(tokenizer); return AsExternal; + switch (shd_curr_token(tokenizer).tag) { + case global_tok: + shd_next_token(tokenizer); return AsGlobal; + case private_tok: + shd_next_token(tokenizer); return AsPrivate; + case shared_tok: + shd_next_token(tokenizer); return AsShared; + case subgroup_tok: + shd_next_token(tokenizer); return AsSubgroup; + case generic_tok: + shd_next_token(tokenizer); return AsGeneric; + case input_tok: + shd_next_token(tokenizer); return AsInput; + case output_tok: + shd_next_token(tokenizer); return AsOutput; + case extern_tok: + shd_next_token(tokenizer); return AsExternal; default: break; } @@ -628,10 +638,10 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) const Node* expr = accept_primary_expr(ctx, bb); while (expr) { InfixOperators infix; - if (is_infix_operator(curr_token(tokenizer).tag, &infix)) { + if (is_infix_operator(shd_curr_token(tokenizer).tag, &infix)) { int precedence = get_precedence(infix); if (precedence > outer_precedence) break; - next_token(tokenizer); + shd_next_token(tokenizer); const Node* rhs = accept_expr(ctx, bb, precedence - 1); expect(rhs, "expression"); @@ -667,7 +677,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) continue; } - switch (curr_token(tokenizer).tag) { + switch (shd_curr_token(tokenizer).tag) { case lpar_tok: { Nodes ops = expect_operands(ctx, bb); expr = bind_instruction_single(bb, call(arena, (Call) { @@ -729,10 +739,10 @@ static const Node* make_loop_continue(const Node* mem) { } static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { - Token current_token = curr_token(tokenizer); + Token current_token = shd_curr_token(tokenizer); switch (current_token.tag) { case if_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); Nodes yield_types = accept_types(ctx, 0, NeverQualified); expect(accept_token(ctx, lpar_tok), "'('"); const Node* condition = accept_operand(ctx, bb); @@ -753,7 +763,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, true_case, false_case)); } case loop_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); Nodes yield_types = accept_types(ctx, 0, NeverQualified); Nodes parameters; Nodes initial_arguments; @@ -765,7 +775,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, loop_case)); } case control_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); Nodes yield_types = accept_types(ctx, 0, NeverQualified); expect(accept_token(ctx, lpar_tok), "'('"); String str = accept_identifier(ctx); @@ -878,14 +888,14 @@ static const Node* expect_jump(ctxparams, BodyBuilder* bb) { } static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { - TokenTag tag = curr_token(tokenizer).tag; + TokenTag tag = shd_curr_token(tokenizer).tag; switch (tag) { case jump_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); return expect_jump(ctx, bb); } case branch_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); expect(accept_token(ctx, lpar_tok), "'('"); const Node* condition = accept_value(ctx, bb); @@ -904,7 +914,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { }); } case switch_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); expect(accept_token(ctx, lpar_tok), "'('"); const Node* inspectee = accept_value(ctx, bb); @@ -938,7 +948,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { }); } case return_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); Nodes args = expect_operands(ctx, bb); return fn_ret(arena, (Return) { .args = args, @@ -946,31 +956,31 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { }); } case merge_selection_tok: { - next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); + shd_next_token(tokenizer); + Nodes args = shd_curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_selection(arena, (MergeSelection) { .args = args, .mem = bb_mem(bb) }); } case continue_tok: { - next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); + shd_next_token(tokenizer); + Nodes args = shd_curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_continue(arena, (MergeContinue) { .args = args, .mem = bb_mem(bb) }); } case break_tok: { - next_token(tokenizer); - Nodes args = curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); + shd_next_token(tokenizer); + Nodes args = shd_curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_break(arena, (MergeBreak) { .args = args, .mem = bb_mem(bb) }); } case join_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); expect(accept_token(ctx, lpar_tok), "'('"); const Node* jp = accept_operand(ctx, bb); expect(accept_token(ctx, rpar_tok), "')'"); @@ -982,7 +992,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { }); } case unreachable_tok: { - next_token(tokenizer); + shd_next_token(tokenizer); expect(accept_token(ctx, lpar_tok), "'('"); expect(accept_token(ctx, rpar_tok), "')'"); return unreachable(arena, (Unreachable) { .mem = bb_mem(bb) }); @@ -1022,7 +1032,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t Nodes ids = shd_empty(arena); Nodes conts = shd_empty(arena); - if (curr_token(tokenizer).tag == cont_tok) { + if (shd_curr_token(tokenizer).tag == cont_tok) { while (true) { if (!accept_token(ctx, cont_tok)) break; @@ -1059,8 +1069,8 @@ static Nodes accept_annotations(ctxparams) { } // TODO: AnnotationCompound ? - if (curr_token(tokenizer).tag == comma_tok) { - next_token(tokenizer); + if (shd_curr_token(tokenizer).tag == comma_tok) { + shd_next_token(tokenizer); struct List* values = shd_new_list(const Node*); shd_list_append(const Node*, values, first_value); while (true) { @@ -1133,7 +1143,7 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { const char* name = accept_identifier(ctx); expect(name, "function name"); Nodes types = accept_types(ctx, comma_tok, MaybeQualified); - expect(curr_token(tokenizer).tag == lpar_tok, "')'"); + expect(shd_curr_token(tokenizer).tag == lpar_tok, "')'"); Nodes parameters; expect_parameters(ctx, ¶meters, NULL, NULL); @@ -1225,10 +1235,10 @@ static const Node* accept_nominal_type_decl(ctxparams, Nodes annotations) { void slim_parse_string(ParserConfig config, const char* contents, Module* mod) { IrArena* arena = get_module_arena(mod); - Tokenizer* tokenizer = new_tokenizer(contents); + Tokenizer* tokenizer = shd_new_tokenizer(contents); while (true) { - Token token = curr_token(tokenizer); + Token token = shd_curr_token(tokenizer); if (token.tag == EOF_tok) break; @@ -1249,6 +1259,6 @@ void slim_parse_string(ParserConfig config, const char* contents, Module* mod) { syntax_error("expected a declaration"); } - destroy_tokenizer(tokenizer); + shd_destroy_tokenizer(tokenizer); } diff --git a/src/frontend/slim/parser.h b/src/frontend/slim/parser.h index 61b514b36..b48acbb9e 100644 --- a/src/frontend/slim/parser.h +++ b/src/frontend/slim/parser.h @@ -39,6 +39,6 @@ INFIX_OPERATORS() } InfixOperators; typedef struct CompilerConfig_ CompilerConfig; -Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name); +Module* shd_parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name); #endif diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index dc57ca5ea..8e07c642f 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -8,15 +8,15 @@ #include "log.h" /// Removes all Unresolved nodes and replaces them with the appropriate decl/value -RewritePass bind_program; +RewritePass slim_pass_bind; /// Enforces the grammar, notably by let-binding any intermediary result -RewritePass normalize; +RewritePass slim_pass_normalize; /// Makes sure every node is well-typed -RewritePass infer_program; +RewritePass slim_pass_infer; void slim_parse_string(ParserConfig config, const char* contents, Module* mod); -Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name) { +Module* shd_parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name) { ArenaConfig aconfig = default_arena_config(&config->target); aconfig.name_bound = false; aconfig.check_op_classes = false; @@ -34,11 +34,11 @@ Module* parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, co generate_dummy_constants(config, *pmod); - RUN_PASS(bind_program) - RUN_PASS(normalize) + RUN_PASS(slim_pass_bind) + RUN_PASS(slim_pass_normalize) RUN_PASS(normalize_builtins) - RUN_PASS(infer_program) + RUN_PASS(slim_pass_infer) RUN_PASS(lower_cf_instrs) destroy_ir_arena(initial_arena); diff --git a/src/frontend/slim/token.c b/src/frontend/slim/token.c index 907702c93..aa57e58dc 100644 --- a/src/frontend/slim/token.c +++ b/src/frontend/slim/token.c @@ -15,7 +15,7 @@ static const char* token_strings[] = { #undef TOKEN }; -const char* token_tags[] = { +static const char* token_tags[] = { #define TOKEN(name, str) #name, TOKENS() #undef TOKEN @@ -42,7 +42,7 @@ typedef struct Tokenizer_ { Token current; } Tokenizer; -Tokenizer* new_tokenizer(const char* source) { +Tokenizer* shd_new_tokenizer(const char* source) { if (!constants_initialized) { init_tokenizer_constants(); constants_initialized = true; @@ -56,11 +56,11 @@ Tokenizer* new_tokenizer(const char* source) { .line = 1, }; memcpy(alloc, &tokenizer, sizeof(Tokenizer)); - next_token(alloc); + shd_next_token(alloc); return alloc; } -void destroy_tokenizer(Tokenizer* tokenizer) { +void shd_destroy_tokenizer(Tokenizer* tokenizer) { free(tokenizer); } @@ -68,7 +68,7 @@ static bool in_bounds(Tokenizer* tokenizer, size_t offset_to_slice) { return (tokenizer->pos + offset_to_slice) <= tokenizer->source_size; } -const char whitespace[] = { ' ', '\t', '\r' }; +static const char whitespace[] = { ' ', '\t', '\r' }; static inline bool is_alpha(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } static inline bool is_digit(char c) { return c >= '0' && c <= '9'; } @@ -104,7 +104,7 @@ static void eat_whitespace_and_comments(Tokenizer* tokenizer) { } } -Token next_token(Tokenizer* tokenizer) { +Token shd_next_token(Tokenizer* tokenizer) { eat_whitespace_and_comments(tokenizer); if (tokenizer->pos == tokenizer->source_size) { shd_debugvv_print("EOF\n"); @@ -212,13 +212,13 @@ Token next_token(Tokenizer* tokenizer) { return token; } -Loc current_loc(Tokenizer* tokenizer) { +Loc shd_current_loc(Tokenizer* tokenizer) { return (Loc) { .line = tokenizer->line, .column = tokenizer->pos - tokenizer->last_line_pos }; } -Token curr_token(Tokenizer* tokenizer) { +Token shd_curr_token(Tokenizer* tokenizer) { return tokenizer->current; } diff --git a/src/frontend/slim/token.h b/src/frontend/slim/token.h index 454b51bb5..12e161642 100644 --- a/src/frontend/slim/token.h +++ b/src/frontend/slim/token.h @@ -103,8 +103,8 @@ TOKEN(equal, "=") \ TOKEN(LIST_END, NULL) typedef struct Tokenizer_ Tokenizer; -Tokenizer* new_tokenizer(const char* source); -void destroy_tokenizer(Tokenizer*); +Tokenizer* shd_new_tokenizer(const char* source); +void shd_destroy_tokenizer(Tokenizer* tokenizer); typedef enum { #define TOKEN(name, str) name##_tok, @@ -112,8 +112,6 @@ typedef enum { #undef TOKEN } TokenTag; -extern const char* token_tags[]; - typedef struct { TokenTag tag; size_t start; @@ -124,10 +122,10 @@ typedef struct { size_t line, column; } Loc; -Loc current_loc(Tokenizer* tokenizer); +Loc shd_current_loc(Tokenizer* tokenizer); -Token curr_token(Tokenizer* tokenizer); -Token next_token(Tokenizer* tokenizer); +Token shd_curr_token(Tokenizer* tokenizer); +Token shd_next_token(Tokenizer* tokenizer); #define SHADY_TOKEN_H diff --git a/src/shady/compile.c b/src/shady/compile.c index 82562f0a9..26d8412ca 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -18,7 +18,7 @@ void add_scheduler_source(const CompilerConfig* config, Module* dst) { ParserConfig pconfig = { .front_end = true, }; - Module* builtin_scheduler_mod = parse_slim_module(config, pconfig, shady_scheduler_src, "builtin_scheduler"); + Module* builtin_scheduler_mod = shd_parse_slim_module(config, pconfig, shady_scheduler_src, "builtin_scheduler"); shd_debug_print("Adding builtin scheduler code"); link_module(dst, builtin_scheduler_mod); destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); From 7fc4a6238f6ff709d065bd329e916c78c4c1dfc0 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 15:47:33 +0200 Subject: [PATCH 603/693] fe/spv: add shd_ prefix --- src/driver/driver.c | 2 +- src/frontend/spirv/s2s.c | 2 +- src/frontend/spirv/s2s.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/driver/driver.c b/src/driver/driver.c index bd75b160a..4ecb4c698 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -52,7 +52,7 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang } case SrcSPIRV: { #ifdef SPV_PARSER_PRESENT - parse_spirv_into_shady(config, len, file_contents, name, mod); + shd_parse_spirv(config, len, file_contents, name, mod); #else assert(false && "SPIR-V front-end missing in this version"); #endif diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 17b414335..d09164dd9 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1338,7 +1338,7 @@ bool compare_spvid(SpvId* pa, SpvId* pb) { return *pa == *pb; } -S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { +S2SError shd_parse_spirv(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { ArenaConfig aconfig = default_arena_config(&config->target); IrArena* a = new_ir_arena(&aconfig); *dst = new_module(a, name); diff --git a/src/frontend/spirv/s2s.h b/src/frontend/spirv/s2s.h index 1f76f9376..2f095b48a 100644 --- a/src/frontend/spirv/s2s.h +++ b/src/frontend/spirv/s2s.h @@ -9,6 +9,6 @@ typedef enum { } S2SError; typedef struct CompilerConfig_ CompilerConfig; -S2SError parse_spirv_into_shady(const CompilerConfig* config, size_t len, const char* data, String name, Module**); +S2SError shd_parse_spirv(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst); #endif From 4a36c0dcc65b6b03aa65bf2afe9a415bf3947c10 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 15:47:55 +0200 Subject: [PATCH 604/693] fe/slim: move stuff onto the public headers more --- include/shady/fe/slim.h | 8 ++++++++ src/driver/driver.c | 4 ++-- src/frontend/slim/parser.c | 14 +++++++------- src/frontend/slim/parser.h | 11 +---------- src/frontend/slim/slim_driver.c | 4 ++-- src/shady/compile.c | 4 ++-- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/include/shady/fe/slim.h b/include/shady/fe/slim.h index 01cae7e5e..7beec0b4c 100644 --- a/include/shady/fe/slim.h +++ b/include/shady/fe/slim.h @@ -1,6 +1,8 @@ #ifndef SHADY_SLIM_H #define SHADY_SLIM_H +#include "shady/config.h" + typedef enum { SlimOpDereference, SlimOpAssign, @@ -12,4 +14,10 @@ typedef enum { SlimOpUnbound, } SlimFrontEndOpCodes; +typedef struct { + bool front_end; +} SlimParserConfig; + +Module* shd_parse_slim_module(const CompilerConfig* config, const SlimParserConfig* pconfig, const char* contents, String name); + #endif diff --git a/src/driver/driver.c b/src/driver/driver.c index 4ecb4c698..48695890c 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -60,11 +60,11 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang } case SrcShadyIR: case SrcSlim: { - ParserConfig pconfig = { + SlimParserConfig pconfig = { .front_end = lang == SrcSlim, }; shd_debugvv_print("Parsing: \n%s\n", file_contents); - *mod = shd_parse_slim_module(config, pconfig, (const char*) file_contents, name); + *mod = shd_parse_slim_module(config, &pconfig, (const char*) file_contents, name); } } return NoError; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 442fda294..f38d16f29 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -1,5 +1,5 @@ -#include "token.h" #include "parser.h" +#include "token.h" #include "list.h" #include "portability.h" @@ -52,7 +52,7 @@ INFIX_OPERATORS() } // to avoid some repetition -#define ctxparams SHADY_UNUSED ParserConfig config, SHADY_UNUSED const char* contents, SHADY_UNUSED Module* mod, SHADY_UNUSED IrArena* arena, SHADY_UNUSED Tokenizer* tokenizer +#define ctxparams SHADY_UNUSED const SlimParserConfig* config, SHADY_UNUSED const char* contents, SHADY_UNUSED Module* mod, SHADY_UNUSED IrArena* arena, SHADY_UNUSED Tokenizer* tokenizer #define ctx config, contents, mod, arena, tokenizer static void error_with_loc(ctxparams) { @@ -430,7 +430,7 @@ static const Type* accept_unqualified_type(ctxparams) { .pointed_type = elem_type, .is_reference = true, }); - } else if (config.front_end && accept_token(ctx, lsbracket_tok)) { + } else if (config->front_end && accept_token(ctx, lsbracket_tok)) { const Type* elem_type = accept_unqualified_type(ctx); expect(elem_type, "type"); const Node* size = NULL; @@ -519,7 +519,7 @@ static const Type* accept_qualified_type(ctxparams) { } static const Node* accept_operand(ctxparams, BodyBuilder* bb) { - return config.front_end ? accept_expr(ctx, bb, max_precedence()) : accept_value(ctx, bb); + return config->front_end ? accept_expr(ctx, bb, max_precedence()) : accept_value(ctx, bb); } static const Node* expect_operand(ctxparams, BodyBuilder* bb) { @@ -748,7 +748,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { const Node* condition = accept_operand(ctx, bb); expect(condition, "condition value"); expect(accept_token(ctx, rpar_tok), "')'"); - const Node* (*merge)(const Node*) = config.front_end ? make_selection_merge : NULL; + const Node* (*merge)(const Node*) = config->front_end ? make_selection_merge : NULL; Node* true_case = case_(arena, shd_nodes(arena, 0, NULL)); set_abstraction_body(true_case, expect_body(ctx, get_abstraction_mem(true_case), merge)); @@ -769,7 +769,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { Nodes initial_arguments; expect_parameters(ctx, ¶meters, &initial_arguments, bb); // by default loops continue forever - const Node* (*default_loop_end_behaviour)(const Node*) = config.front_end ? make_loop_continue : NULL; + const Node* (*default_loop_end_behaviour)(const Node*) = config->front_end ? make_loop_continue : NULL; Node* loop_case = case_(arena, parameters); set_abstraction_body(loop_case, expect_body(ctx, get_abstraction_mem(loop_case), default_loop_end_behaviour)); return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, loop_case)); @@ -1233,7 +1233,7 @@ static const Node* accept_nominal_type_decl(ctxparams, Nodes annotations) { return nom; } -void slim_parse_string(ParserConfig config, const char* contents, Module* mod) { +void slim_parse_string(const SlimParserConfig* config, const char* contents, Module* mod) { IrArena* arena = get_module_arena(mod); Tokenizer* tokenizer = shd_new_tokenizer(contents); diff --git a/src/frontend/slim/parser.h b/src/frontend/slim/parser.h index b48acbb9e..7e2e37884 100644 --- a/src/frontend/slim/parser.h +++ b/src/frontend/slim/parser.h @@ -1,14 +1,8 @@ #ifndef SHADY_PARSER_H - #define SHADY_PARSER_H -#include "shady/ir.h" - #include "shady/fe/slim.h" - -typedef struct { - bool front_end; -} ParserConfig; +#include "shady/ir.h" #define INFIX_OPERATORS() \ INFIX_OPERATOR(Mul, star_tok, mul_op, 1) \ @@ -38,7 +32,4 @@ INFIX_OPERATORS() InfixOperatorsCount } InfixOperators; -typedef struct CompilerConfig_ CompilerConfig; -Module* shd_parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name); - #endif diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index 8e07c642f..2df212603 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -14,9 +14,9 @@ RewritePass slim_pass_normalize; /// Makes sure every node is well-typed RewritePass slim_pass_infer; -void slim_parse_string(ParserConfig config, const char* contents, Module* mod); +void slim_parse_string(const SlimParserConfig* config, const char* contents, Module* mod); -Module* shd_parse_slim_module(const CompilerConfig* config, ParserConfig pconfig, const char* contents, String name) { +Module* shd_parse_slim_module(const CompilerConfig* config, const SlimParserConfig* pconfig, const char* contents, String name) { ArenaConfig aconfig = default_arena_config(&config->target); aconfig.name_bound = false; aconfig.check_op_classes = false; diff --git a/src/shady/compile.c b/src/shady/compile.c index 26d8412ca..268d884fe 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -15,10 +15,10 @@ #include void add_scheduler_source(const CompilerConfig* config, Module* dst) { - ParserConfig pconfig = { + SlimParserConfig pconfig = { .front_end = true, }; - Module* builtin_scheduler_mod = shd_parse_slim_module(config, pconfig, shady_scheduler_src, "builtin_scheduler"); + Module* builtin_scheduler_mod = shd_parse_slim_module(config, &pconfig, shady_scheduler_src, "builtin_scheduler"); shd_debug_print("Adding builtin scheduler code"); link_module(dst, builtin_scheduler_mod); destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); From 1967fe05f587284ee9784055e553b31b9088d16c Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 16:57:26 +0200 Subject: [PATCH 605/693] be/c: prefix with shd_ --- include/shady/be/c.h | 2 +- src/backend/c/emit_c.c | 2 +- src/driver/driver.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/shady/be/c.h b/include/shady/be/c.h index e36e05fb7..2281675a2 100644 --- a/include/shady/be/c.h +++ b/include/shady/be/c.h @@ -21,7 +21,7 @@ typedef struct { CEmitterConfig default_c_emitter_config(void); typedef struct CompilerConfig_ CompilerConfig; -void emit_c(const CompilerConfig* compiler_config, CEmitterConfig emitter_config, Module*, size_t* output_size, char** output, Module** new_mod); +void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod); #endif diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 4e191c36c..96b529782 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -421,7 +421,7 @@ CEmitterConfig default_c_emitter_config(void) { }; } -void emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod) { +void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod) { IrArena* initial_arena = get_module_arena(mod); mod = run_backend_specific_passes(compiler_config, &config, mod); IrArena* arena = get_module_arena(mod); diff --git a/src/driver/driver.c b/src/driver/driver.c index 48695890c..fe7bbd65a 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -163,15 +163,15 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { case TgtSPV: emit_spirv(&args->config, mod, &output_size, &output_buffer, NULL); break; case TgtC: args->c_emitter_config.dialect = CDialect_C11; - emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); + shd_emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; case TgtGLSL: args->c_emitter_config.dialect = CDialect_GLSL; - emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); + shd_emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; case TgtISPC: args->c_emitter_config.dialect = CDialect_ISPC; - emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); + shd_emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); break; } shd_debug_print("Wrote result to %s\n", args->output_filename); From 0b958b40f11edf981373c83dc6525bd35e60771c Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:00:05 +0200 Subject: [PATCH 606/693] config.h: added shd_ prefix --- include/shady/config.h | 7 +++---- samples/aobench/ao_main.c | 2 +- samples/checkerboard/checkerboard.c | 4 ++-- src/driver/cli.c | 2 +- src/driver/slim.c | 2 +- src/frontend/llvm/l2s.c | 2 +- src/frontend/slim/slim_driver.c | 2 +- src/frontend/spirv/s2s.c | 2 +- src/runtime/runtime_test.c | 2 +- src/shady/config.c | 8 ++++---- test/opt/opt_oracle.c | 2 +- test/test_builder.c | 4 ++-- test/test_math.c | 4 ++-- vcc/vcc.c | 2 +- 14 files changed, 22 insertions(+), 23 deletions(-) diff --git a/include/shady/config.h b/include/shady/config.h index fc58f6681..15c73f5ed 100644 --- a/include/shady/config.h +++ b/include/shady/config.h @@ -13,7 +13,7 @@ typedef struct { PointerModel memory; } TargetConfig; -TargetConfig default_target_config(); +TargetConfig shd_default_target_config(void); typedef enum { /// Uses the MaskType @@ -54,7 +54,7 @@ struct ArenaConfig_ { } optimisations; }; -ArenaConfig default_arena_config(const TargetConfig* target); +ArenaConfig shd_default_arena_config(const TargetConfig* target); typedef struct CompilerConfig_ CompilerConfig; struct CompilerConfig_ { @@ -124,7 +124,6 @@ struct CompilerConfig_ { } hooks; }; -CompilerConfig default_compiler_config(); +CompilerConfig shd_default_compiler_config(void); #endif - diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index 5e0e911ae..b33ff568b 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -141,7 +141,7 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri int main(int argc, char **argv) { shd_log_set_level(INFO); Args args = { - .compiler_config = default_compiler_config(), + .compiler_config = shd_default_compiler_config(), .runtime_config = default_runtime_config(), }; diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 9acb4ecdd..d95848926 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -41,7 +41,7 @@ int main(int argc, char **argv) } shd_log_set_level(INFO); - CompilerConfig compiler_config = default_compiler_config(); + CompilerConfig compiler_config = shd_default_compiler_config(); RuntimeConfig runtime_config = default_runtime_config(); @@ -65,7 +65,7 @@ int main(int argc, char **argv) shd_info_print("Device-side address is: %zu\n", buf_addr); - ArenaConfig aconfig = default_arena_config(&compiler_config.target); + ArenaConfig aconfig = shd_default_arena_config(&compiler_config.target); IrArena* a = new_ir_arena(&aconfig); Module* m; if (driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, "checkerboard", &m) != NoError) diff --git a/src/driver/cli.c b/src/driver/cli.c index 17cac3969..52f76cbad 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -205,7 +205,7 @@ void cli_parse_input_files(struct List* list, int* pargc, char** argv) { DriverConfig default_driver_config() { return (DriverConfig) { - .config = default_compiler_config(), + .config = shd_default_compiler_config(), .target = TgtAuto, .input_filenames = shd_new_list(const char*), .output_filename = NULL, diff --git a/src/driver/slim.c b/src/driver/slim.c index f7e9b81be..8c97b8d01 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -15,7 +15,7 @@ int main(int argc, char** argv) { cli_parse_compiler_config_args(&args.config, &argc, argv); cli_parse_input_files(args.input_filenames, &argc, argv); - ArenaConfig aconfig = default_arena_config(&args.config.target); + ArenaConfig aconfig = shd_default_arena_config(&args.config.target); IrArena* arena = new_ir_arena(&aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index ccfd32e08..aefd05bfc 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -297,7 +297,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* } shd_info_print("LLVM IR parsed successfully\n"); - ArenaConfig aconfig = default_arena_config(&config->target); + ArenaConfig aconfig = shd_default_arena_config(&config->target); aconfig.check_types = false; aconfig.allow_fold = false; aconfig.optimisations.inline_single_use_bbs = false; diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index 2df212603..d2da97fb7 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -17,7 +17,7 @@ RewritePass slim_pass_infer; void slim_parse_string(const SlimParserConfig* config, const char* contents, Module* mod); Module* shd_parse_slim_module(const CompilerConfig* config, const SlimParserConfig* pconfig, const char* contents, String name) { - ArenaConfig aconfig = default_arena_config(&config->target); + ArenaConfig aconfig = shd_default_arena_config(&config->target); aconfig.name_bound = false; aconfig.check_op_classes = false; aconfig.check_types = false; diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index d09164dd9..6f0e04197 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1339,7 +1339,7 @@ bool compare_spvid(SpvId* pa, SpvId* pb) { } S2SError shd_parse_spirv(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { - ArenaConfig aconfig = default_arena_config(&config->target); + ArenaConfig aconfig = shd_default_arena_config(&config->target); IrArena* a = new_ir_arena(&aconfig); *dst = new_module(a, name); diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 965937bd6..fb00240cd 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -48,7 +48,7 @@ int main(int argc, char* argv[]) { Program* program; IrArena* arena = NULL; - ArenaConfig aconfig = default_arena_config(&args.driver_config.config.target); + ArenaConfig aconfig = shd_default_arena_config(&args.driver_config.config.target); arena = new_ir_arena(&aconfig); if (shd_list_count(args.driver_config.input_filenames) == 0) { Module* module; diff --git a/src/shady/config.c b/src/shady/config.c index 12503ec08..e67850152 100644 --- a/src/shady/config.c +++ b/src/shady/config.c @@ -4,7 +4,7 @@ #define KiB * 1024 #define MiB * 1024 KiB -CompilerConfig default_compiler_config() { +CompilerConfig shd_default_compiler_config(void) { return (CompilerConfig) { .dynamic_scheduling = true, .per_thread_stack_size = 4 KiB, @@ -41,7 +41,7 @@ CompilerConfig default_compiler_config() { .god_function = true, },*/ - .target = default_target_config(), + .target = shd_default_target_config(), .specialization = { .subgroup_size = 8, @@ -50,7 +50,7 @@ CompilerConfig default_compiler_config() { }; } -TargetConfig default_target_config() { +TargetConfig shd_default_target_config(void) { return (TargetConfig) { .memory = { .word_size = IntTy32, @@ -59,7 +59,7 @@ TargetConfig default_target_config() { }; } -ArenaConfig default_arena_config(const TargetConfig* target) { +ArenaConfig shd_default_arena_config(const TargetConfig* target) { ArenaConfig config = { .is_simt = true, .name_bound = true, diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 25147fa03..9d89f61bc 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -83,7 +83,7 @@ int main(int argc, char** argv) { cli_parse_oracle_args(&argc, argv); cli_parse_input_files(args.input_filenames, &argc, argv); - ArenaConfig aconfig = default_arena_config(&args.config.target); + ArenaConfig aconfig = shd_default_arena_config(&args.config.target); aconfig.optimisations.weaken_non_leaking_allocas = true; IrArena* arena = new_ir_arena(&aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one diff --git a/test/test_builder.c b/test/test_builder.c index d69f72669..bb0672b3a 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -158,8 +158,8 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { int main(int argc, char** argv) { cli_parse_common_args(&argc, argv); - TargetConfig target_config = default_target_config(); - ArenaConfig aconfig = default_arena_config(&target_config); + TargetConfig target_config = shd_default_target_config(); + ArenaConfig aconfig = shd_default_arena_config(&target_config); IrArena* a = new_ir_arena(&aconfig); test_body_builder_constants(a); test_body_builder_fun_body(a); diff --git a/test/test_math.c b/test/test_math.c index a26ee9d8b..78d562af8 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -91,8 +91,8 @@ static void test_int_literals(IrArena* a) { int main(int argc, char** argv) { cli_parse_common_args(&argc, argv); - TargetConfig target_config = default_target_config(); - ArenaConfig aconfig = default_arena_config(&target_config); + TargetConfig target_config = shd_default_target_config(); + ArenaConfig aconfig = shd_default_arena_config(&target_config); aconfig.check_types = true; aconfig.allow_fold = true; IrArena* a = new_ir_arena(&aconfig); diff --git a/vcc/vcc.c b/vcc/vcc.c index 0a88c5615..4baddd5f3 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -25,7 +25,7 @@ int main(int argc, char** argv) { exit(MissingInputArg); } - ArenaConfig aconfig = default_arena_config(&args.config.target); + ArenaConfig aconfig = shd_default_arena_config(&args.config.target); IrArena* arena = new_ir_arena(&aconfig); vcc_check_clang(); From ec2e25bf31d4189d3447cbc4ad29122147fd0720 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:05:47 +0200 Subject: [PATCH 607/693] added shd_ prefix to builtins.h --- include/shady/builtins.h | 16 +++++----- src/backend/c/emit_c.c | 4 +-- src/backend/c/emit_c_builtin.c | 2 +- src/backend/c/emit_c_value.c | 6 ++-- src/backend/spirv/emit_spv.c | 6 ++-- src/frontend/spirv/s2s.c | 8 ++--- src/shady/builtins.c | 38 ++++++++++++++++------- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/normalize_builtins.c | 11 ++++--- src/shady/passes/specialize_entry_point.c | 2 +- src/shady/transform/ir_gen_helpers.c | 12 ++++--- src/shady/type.c | 4 +-- 12 files changed, 66 insertions(+), 45 deletions(-) diff --git a/include/shady/builtins.h b/include/shady/builtins.h index 46631e0e4..78e64d09e 100644 --- a/include/shady/builtins.h +++ b/include/shady/builtins.h @@ -40,16 +40,18 @@ SHADY_BUILTINS() BuiltinsCount } Builtin; -AddressSpace get_builtin_as(Builtin); -String get_builtin_name(Builtin); +AddressSpace shd_get_builtin_address_space(Builtin builtin); +String shd_get_builtin_name(Builtin builtin); -const Type* get_builtin_type(IrArena* arena, Builtin); -Builtin get_builtin_by_name(String); +const Type* shd_get_builtin_type(IrArena* arena, Builtin builtin); +Builtin shd_get_builtin_by_name(String s); typedef enum SpvBuiltIn_ SpvBuiltIn; -Builtin get_builtin_by_spv_id(SpvBuiltIn id); +Builtin shd_get_builtin_by_spv_id(SpvBuiltIn id); -bool is_decl_builtin(const Node*); -Builtin get_decl_builtin(const Node*); +bool shd_is_decl_builtin(const Node* decl); +Builtin shd_get_decl_builtin(const Node* decl); + +int32_t shd_get_builtin_spv_id(Builtin builtin); #endif diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 96b529782..c489e22d1 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -265,8 +265,8 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { init = NULL; const GlobalVariable* gvar = &decl->payload.global_variable; - if (is_decl_builtin(decl)) { - Builtin b = get_decl_builtin(decl); + if (shd_is_decl_builtin(decl)) { + Builtin b = shd_get_decl_builtin(decl); CTerm t = c_emit_builtin(emitter, b); register_emitted(emitter, NULL, decl, t); return; diff --git a/src/backend/c/emit_c_builtin.c b/src/backend/c/emit_c_builtin.c index d6b5b6a41..78307363e 100644 --- a/src/backend/c/emit_c_builtin.c +++ b/src/backend/c/emit_c_builtin.c @@ -27,5 +27,5 @@ CTerm c_emit_builtin(Emitter* emitter, Builtin b) { } if (name) return term_from_cvar(name); - return term_from_cvar(get_builtin_name(b)); + return term_from_cvar(shd_get_builtin_name(b)); } diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 08b0379c6..5fb2917d3 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -218,7 +218,8 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No c_emit_decl(emitter, decl); if (emitter->config.dialect == CDialect_ISPC && decl->tag == GlobalVariable_TAG) { - if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !is_decl_builtin(decl)) { + if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !shd_is_decl_builtin( + decl)) { assert(fn && "ISPC backend cannot statically refer to a varying variable"); return ispc_varying_ptr_helper(emitter, fn->instruction_printers[0], decl->type, *lookup_existing_term(emitter, NULL, decl)); } @@ -987,7 +988,8 @@ static bool can_appear_at_top_level(Emitter* emitter, const Node* node) { if (node->tag == RefDecl_TAG) { const Node* decl = node->payload.ref_decl.decl; if (decl->tag == GlobalVariable_TAG) - if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !is_decl_builtin(decl)) + if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !shd_is_decl_builtin( + decl)) //if (is_value(node) && !is_qualified_type_uniform(node->type)) return false; } diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 6c6338b98..013f2e736 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -19,8 +19,6 @@ #include #include -extern SpvBuiltIn spv_builtins[]; - KeyHash hash_node(Node**); bool compare_node(Node**, Node**); @@ -172,9 +170,9 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { String builtin_name = get_annotation_string_payload(a); assert(builtin_name); assert(b == BuiltinsCount && "Only one @Builtin annotation permitted."); - b = get_builtin_by_name(builtin_name); + b = shd_get_builtin_by_name(builtin_name); assert(b != BuiltinsCount); - SpvBuiltIn d = spv_builtins[b]; + SpvBuiltIn d = shd_get_builtin_spv_id(b); uint32_t decoration_payload[] = { d }; spvb_decorate(emitter->file_builder, given_id, SpvDecorationBuiltIn, 1, decoration_payload); } else if (strcmp(name, "Location") == 0) { diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 6f0e04197..24bb114c3 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -13,8 +13,6 @@ static void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy #include "spirv/unified1/OpenCL.std.h" #include "spirv/unified1/GLSL.std.450.h" -extern SpvBuiltIn spv_builtins[]; - // TODO: reserve real decoration IDs typedef enum { ShdDecorationName = 999999, @@ -753,9 +751,11 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { Nodes annotations = shd_empty(parser->arena); SpvDeco* builtin = find_decoration(parser, result, -1, SpvDecorationBuiltIn); if (builtin) { - Builtin b = get_builtin_by_spv_id(*builtin->payload.literals.data); + Builtin b = shd_get_builtin_by_spv_id(*builtin->payload.literals.data); assert(b != BuiltinsCount && "Unsupported builtin"); - annotations = shd_nodes_append(parser->arena, annotations, annotation_value_helper(parser->arena, "Builtin", string_lit_helper(parser->arena, get_builtin_name(b)))); + annotations = shd_nodes_append(parser->arena, annotations, annotation_value_helper(parser->arena, "Builtin", string_lit_helper(parser->arena, + shd_get_builtin_name( + b)))); } parser->defs[result].type = Decl; diff --git a/src/shady/builtins.c b/src/shady/builtins.c index 936c32d12..a73f6dc5a 100644 --- a/src/shady/builtins.c +++ b/src/shady/builtins.c @@ -5,23 +5,31 @@ #include "portability.h" #include -AddressSpace builtin_as[] = { +static AddressSpace builtin_as[] = { #define BUILTIN(_, as, _2) as, SHADY_BUILTINS() #undef BUILTIN }; -AddressSpace get_builtin_as(Builtin builtin) { return builtin_as[builtin]; } +AddressSpace shd_get_builtin_address_space(Builtin builtin) { + if (builtin >= BuiltinsCount) + return AsGeneric; + return builtin_as[builtin]; +} -String builtin_names[] = { +static String builtin_names[] = { #define BUILTIN(name, _, _2) #name, SHADY_BUILTINS() #undef BUILTIN }; -String get_builtin_name(Builtin builtin) { return builtin_names[builtin]; } +String shd_get_builtin_name(Builtin builtin) { + if (builtin >= BuiltinsCount) + return ""; + return builtin_names[builtin]; +} -const Type* get_builtin_type(IrArena* arena, Builtin builtin) { +const Type* shd_get_builtin_type(IrArena* arena, Builtin builtin) { switch (builtin) { #define BUILTIN(name, _, datatype) case Builtin##name: return datatype; SHADY_BUILTINS() @@ -31,13 +39,13 @@ SHADY_BUILTINS() } // What's the decoration for the builtin -SpvBuiltIn spv_builtins[] = { +static SpvBuiltIn spv_builtins[] = { #define BUILTIN(name, _, _2) SpvBuiltIn##name, SHADY_BUILTINS() #undef BUILTIN }; -Builtin get_builtin_by_name(String s) { +Builtin shd_get_builtin_by_name(String s) { for (size_t i = 0; i < BuiltinsCount; i++) { if (strcmp(s, builtin_names[i]) == 0) { return i; @@ -46,7 +54,7 @@ Builtin get_builtin_by_name(String s) { return BuiltinsCount; } -Builtin get_builtin_by_spv_id(SpvBuiltIn id) { +Builtin shd_get_builtin_by_spv_id(SpvBuiltIn id) { Builtin b = BuiltinsCount; for (size_t i = 0; i < BuiltinsCount; i++) { if (id == spv_builtins[i]) { @@ -57,15 +65,21 @@ Builtin get_builtin_by_spv_id(SpvBuiltIn id) { return b; } -Builtin get_decl_builtin(const Node* decl) { +Builtin shd_get_decl_builtin(const Node* decl) { const Node* a = lookup_annotation(decl, "Builtin"); if (!a) return BuiltinsCount; String payload = get_annotation_string_payload(a); - return get_builtin_by_name(payload); + return shd_get_builtin_by_name(payload); } -bool is_decl_builtin(const Node* decl) { - return get_decl_builtin(decl) != BuiltinsCount; +bool shd_is_decl_builtin(const Node* decl) { + return shd_get_decl_builtin(decl) != BuiltinsCount; +} + +int32_t shd_get_builtin_spv_id(Builtin builtin) { + if (builtin >= BuiltinsCount) + return 0; + return spv_builtins[builtin]; } diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index f96d801c9..2c1fd49cc 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -37,7 +37,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* ba = lookup_annotation(node, "Builtin"); if (ba) { Nodes filtered_as = rewrite_nodes(&ctx->rewriter, filter_out_annotation(a, node->payload.global_variable.annotations, "Builtin")); - Builtin b = get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); switch (b) { case BuiltinSubgroupId: case BuiltinWorkgroupId: diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index de5d2e48f..5d6045c12 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -20,9 +20,9 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { GlobalVariable global_variable = src->payload.global_variable; const Node* ba = lookup_annotation_list(global_variable.annotations, "Builtin"); if (ba) { - Builtin b = get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); assert(b != BuiltinsCount); - const Type* expected_t = get_builtin_type(a, b); + const Type* expected_t = shd_get_builtin_type(a, b); const Type* actual_t = rewrite_node(&ctx->rewriter, src)->payload.global_variable.type; if (expected_t != actual_t) { shd_log_fmt(INFO, "normalize_builtins: found builtin decl '%s' not matching expected type: '", global_variable.name); @@ -60,12 +60,13 @@ static const Node* process(Context* ctx, const Node* node) { GlobalVariable global_variable = node->payload.global_variable; const Node* ba = lookup_annotation_list(global_variable.annotations, "Builtin"); if (ba) { - Builtin b = get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); assert(b != BuiltinsCount); if (ctx->builtins[b]) return ctx->builtins[b]; - const Type* t = get_builtin_type(a, b); - Node* ndecl = global_var(r->dst_module, rewrite_nodes(r, global_variable.annotations), t, global_variable.name, get_builtin_as(b)); + const Type* t = shd_get_builtin_type(a, b); + Node* ndecl = global_var(r->dst_module, rewrite_nodes(r, global_variable.annotations), t, global_variable.name, + shd_get_builtin_address_space(b)); register_processed(r, node, ndecl); // no 'init' for builtins, right ? assert(!global_variable.init); diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 0b34f1cb1..628c4a97f 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -33,7 +33,7 @@ static const Node* process(Context* ctx, const Node* node) { case GlobalVariable_TAG: { const Node* ba = lookup_annotation(node, "Builtin"); if (ba) { - Builtin b = get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); switch (b) { case BuiltinWorkgroupSize: return NULL; diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index e88557ef7..5ecf0f2de 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -155,7 +155,7 @@ const Node* get_builtin(Module* m, Builtin b) { continue; String builtin_name = get_annotation_string_payload(a); assert(builtin_name); - if (strcmp(builtin_name, get_builtin_name(b)) == 0) + if (strcmp(builtin_name, shd_get_builtin_name(b)) == 0) return decl; } @@ -167,9 +167,13 @@ const Node* get_or_create_builtin(Module* m, Builtin b, String n) { if (decl) return decl; - AddressSpace as = get_builtin_as(b); + AddressSpace as = shd_get_builtin_address_space(b); IrArena* a = get_module_arena(m); - decl = global_var(m, shd_singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, get_builtin_name(b)))), get_builtin_type(a, b), n ? n : shd_format_string_arena(a->arena, "builtin_%s", get_builtin_name(b)), as); + decl = global_var(m, shd_singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, + shd_get_builtin_name(b)))), + shd_get_builtin_type(a, b), n ? n : shd_format_string_arena(a->arena, "builtin_%s", + shd_get_builtin_name( + b)), as); return decl; } @@ -188,7 +192,7 @@ bool is_builtin_load_op(const Node* n, Builtin* out) { if (a) { String bn = get_annotation_string_payload(a); assert(bn); - Builtin b = get_builtin_by_name(bn); + Builtin b = shd_get_builtin_by_name(bn); if (b != BuiltinsCount) { *out = b; return true; diff --git a/src/shady/type.c b/src/shady/type.c index 06e13c0aa..a09577b36 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1244,9 +1244,9 @@ const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_var const Node* ba = lookup_annotation_list(global_variable.annotations, "Builtin"); if (ba && arena->config.validate_builtin_types) { - Builtin b = get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); assert(b != BuiltinsCount); - const Type* t = get_builtin_type(arena, b); + const Type* t = shd_get_builtin_type(arena, b); if (t != global_variable.type) { shd_error_print("Creating a @Builtin global variable '%s' with the incorrect type: ", global_variable.name); shd_log_node(ERROR, global_variable.type); From 7b40d6ba794f4791723fae496847b01614bf0aca Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:08:48 +0200 Subject: [PATCH 608/693] pass.h: added shd_ prefix --- include/shady/pass.h | 8 ++++---- src/shady/compile.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/shady/pass.h b/include/shady/pass.h index 8556600f6..ebea68ca1 100644 --- a/include/shady/pass.h +++ b/include/shady/pass.h @@ -7,11 +7,11 @@ typedef Module* (RewritePass)(const CompilerConfig* config, Module* src); typedef bool (OptPass)(const CompilerConfig* config, Module** m); -void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name); -#define RUN_PASS(pass_name) run_pass_impl(config, pmod, initial_arena, pass_name, #pass_name); +void shd_run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name); +#define RUN_PASS(pass_name) shd_run_pass_impl(config, pmod, initial_arena, pass_name, #pass_name); -void apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPass pass, String pass_name); -#define APPLY_OPT(pass_name) apply_opt_impl(config, &todo, &m, pass_name, #pass_name); +void shd_apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPass pass, String pass_name); +#define APPLY_OPT(pass_name) shd_apply_opt_impl(config, &todo, &m, pass_name, #pass_name); #endif diff --git a/src/shady/compile.c b/src/shady/compile.c index 268d884fe..674f835bb 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -30,7 +30,7 @@ void add_scheduler_source(const CompilerConfig* config, Module* dst) { #define SHADY_RUN_VERIFY 1 #endif -void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name) { +void shd_run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial_arena, RewritePass pass, String pass_name) { Module* old_mod = NULL; old_mod = *pmod; *pmod = pass(config, *pmod); @@ -52,7 +52,7 @@ void run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* initial config->hooks.after_pass.fn(config->hooks.after_pass.uptr, pass_name, *pmod); } -void apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPass pass, String pass_name) { +void shd_apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, OptPass pass, String pass_name) { bool changed = pass(config, m); *todo |= changed; From 1799d9c6a9347d0d2398bf241fb168eb4db87274 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:09:01 +0200 Subject: [PATCH 609/693] print.h: added shd_ prefix --- include/shady/print.h | 8 ++++---- src/driver/driver.c | 2 +- src/shady/analysis/cfg_dump.c | 2 +- src/shady/print.c | 24 ++++++++++++------------ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/shady/print.h b/include/shady/print.h index 72262b19f..646c102fa 100644 --- a/include/shady/print.h +++ b/include/shady/print.h @@ -16,10 +16,10 @@ typedef struct { bool in_cfg; } NodePrintConfig; -void print_module_into_str(Module* mod, char** str_ptr, size_t* size); -void print_node_into_str(const Node* node, char** str_ptr, size_t* size); +void shd_print_module_into_str(Module* mod, char** str_ptr, size_t* size); +void shd_print_node_into_str(const Node* node, char** str_ptr, size_t* size); -void print_module(Printer* printer, NodePrintConfig config, Module* mod); -void print_node(Printer* printer, NodePrintConfig config, const Node* node); +void shd_print_module(Printer* printer, NodePrintConfig config, Module* mod); +void shd_print_node(Printer* printer, NodePrintConfig config, const Node* node); #endif \ No newline at end of file diff --git a/src/driver/driver.c b/src/driver/driver.c index fe7bbd65a..f4565c390 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -145,7 +145,7 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { assert(f); size_t output_size; char* output_buffer; - print_module_into_str(mod, &output_buffer, &output_size); + shd_print_module_into_str(mod, &output_buffer, &output_size); fwrite(output_buffer, output_size, 1, f); free((void*) output_buffer); fclose(f); diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index d4fd2baeb..ba5c590d6 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -22,7 +22,7 @@ static void print_node_helper(Printer* p, const Node* n) { .in_cfg = true, }; - print_node(tmp_p, config, n); + shd_print_node(tmp_p, config, n); String label = shd_printer_growy_unwrap(tmp_p); char* escaped_label = calloc(strlen(label) * 2, 1); diff --git a/src/shady/print.c b/src/shady/print.c index d856207fc..a409c7f02 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -62,7 +62,7 @@ static void destroy_printer_ctx(PrinterCtx ctx) { shd_destroy_dict(ctx.emitted); } -void print_module(Printer* printer, NodePrintConfig config, Module* mod) { +void shd_print_module(Printer* printer, NodePrintConfig config, Module* mod) { PrinterCtx ctx = make_printer_ctx(printer, config); print_mod_impl(&ctx, mod); String s = shd_printer_growy_unwrap(ctx.root_printer); @@ -72,7 +72,7 @@ void print_module(Printer* printer, NodePrintConfig config, Module* mod) { destroy_printer_ctx(ctx); } -void print_node(Printer* printer, NodePrintConfig config, const Node* node) { +void shd_print_node(Printer* printer, NodePrintConfig config, const Node* node) { PrinterCtx ctx = make_printer_ctx(printer, config); String emitted = emit_node(&ctx, node); String s = shd_printer_growy_unwrap(ctx.root_printer); @@ -82,21 +82,21 @@ void print_node(Printer* printer, NodePrintConfig config, const Node* node) { destroy_printer_ctx(ctx); } -void print_node_into_str(const Node* node, char** str_ptr, size_t* size) { +void shd_print_node_into_str(const Node* node, char** str_ptr, size_t* size) { Growy* g = shd_new_growy(); Printer* p = shd_new_printer_from_growy(g); if (node) shd_print(p, "%%%d ", node->id); - print_node(p, (NodePrintConfig) {.reparseable = true}, node); + shd_print_node(p, (NodePrintConfig) {.reparseable = true}, node); shd_destroy_printer(p); *size = shd_growy_size(g); *str_ptr = shd_growy_deconstruct(g); } -void print_module_into_str(Module* mod, char** str_ptr, size_t* size) { +void shd_print_module_into_str(Module* mod, char** str_ptr, size_t* size) { Growy* g = shd_new_growy(); Printer* p = shd_new_printer_from_growy(g); - print_module(p, (NodePrintConfig) {.reparseable = true,}, mod); + shd_print_module(p, (NodePrintConfig) {.reparseable = true,}, mod); shd_destroy_printer(p); *size = shd_growy_size(g); *str_ptr = shd_growy_deconstruct(g); @@ -106,13 +106,13 @@ void dump_node(const Node* node) { Printer* p = shd_new_printer_from_file(stdout); if (node) shd_print(p, "%%%d ", node->id); - print_node(p, (NodePrintConfig) {.color = true}, node); + shd_print_node(p, (NodePrintConfig) {.color = true}, node); printf("\n"); } void dump_module(Module* mod) { Printer* p = shd_new_printer_from_file(stdout); - print_module(p, (NodePrintConfig) {.color = true}, mod); + shd_print_module(p, (NodePrintConfig) {.color = true}, mod); shd_destroy_printer(p); printf("\n"); } @@ -120,7 +120,7 @@ void dump_module(Module* mod) { void shd_log_node(LogLevel level, const Node* node) { if (level <= shd_log_get_level()) { Printer* p = shd_new_printer_from_file(stderr); - print_node(p, (NodePrintConfig) {.color = true}, node); + shd_print_node(p, (NodePrintConfig) {.color = true}, node); shd_destroy_printer(p); } } @@ -134,7 +134,7 @@ void shd_log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* } if (level <= shd_log_get_level()) { Printer* p = shd_new_printer_from_file(stderr); - print_module(p, config, mod); + shd_print_module(p, config, mod); shd_destroy_printer(p); } } @@ -672,7 +672,7 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { // printf("call"); // printf(RESET); // printf(" ("); - // print_node(node->payload.call.callee); + // shd_print_node(node->payload.call.callee); // printf(")"); // print_args_list(ctx, node->payload.call.args); // break; @@ -861,7 +861,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { printf("join"); printf(RESET); printf("("); - print_node(node->payload.join.join_point); + shd_print_node(node->payload.join.join_point); printf(")"); print_args_list(ctx, node->payload.join.args); printf(";"); From e05c9758073992ba7a8560ec26753420ab074b46 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:09:11 +0200 Subject: [PATCH 610/693] made add_scheduler_source static --- src/shady/compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/compile.c b/src/shady/compile.c index 674f835bb..4dc2c4721 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -14,7 +14,7 @@ #include -void add_scheduler_source(const CompilerConfig* config, Module* dst) { +static void add_scheduler_source(const CompilerConfig* config, Module* dst) { SlimParserConfig pconfig = { .front_end = true, }; From 8953b6cd339a5b59b0ee732e404e8c18b196d73a Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:16:43 +0200 Subject: [PATCH 611/693] driver.h: add shd_ prefix --- include/shady/driver.h | 28 ++++++++++++------------- samples/aobench/ao_main.c | 6 +++--- samples/checkerboard/checkerboard.c | 7 ++++--- src/driver/cli.c | 24 ++++++++++----------- src/driver/cli.h | 2 +- src/driver/driver.c | 22 ++++++++++--------- src/driver/slim.c | 16 +++++++------- src/runtime/runtime_app_common.h | 2 +- src/runtime/runtime_cli.c | 2 +- src/runtime/runtime_program.c | 5 +++-- src/runtime/runtime_test.c | 15 ++++++------- src/runtime/vulkan/vk_runtime_program.c | 2 +- src/shady/compile.c | 2 +- test/opt/opt_oracle.c | 16 +++++++------- test/test_builder.c | 2 +- test/test_math.c | 2 +- vcc/vcc.c | 14 ++++++------- vcc/vcc_lib.c | 4 ++-- 18 files changed, 88 insertions(+), 83 deletions(-) diff --git a/include/shady/driver.h b/include/shady/driver.h index 81b067a29..bf0ce3a77 100644 --- a/include/shady/driver.h +++ b/include/shady/driver.h @@ -29,9 +29,9 @@ typedef enum { SrcLLVM, } SourceLanguage; -SourceLanguage guess_source_language(const char* filename); -ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t, const char* file_contents, String, Module** mod); -ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, String, Module** mod); +SourceLanguage shd_driver_guess_source_language(const char* filename); +ShadyErrorCodes shd_driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t len, const char* file_contents, String name, Module** mod); +ShadyErrorCodes shd_driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, String name, Module** mod); typedef enum { TgtAuto, @@ -41,16 +41,16 @@ typedef enum { TgtISPC, } CodegenTarget; -CodegenTarget guess_target(const char* filename); +CodegenTarget shd_guess_target(const char* filename); -void cli_pack_remaining_args(int* pargc, char** argv); +void shd_pack_remaining_args(int* pargc, char** argv); // parses 'common' arguments such as log level etc -void cli_parse_common_args(int* pargc, char** argv); +void shd_parse_common_args(int* pargc, char** argv); // parses compiler pipeline options -void cli_parse_compiler_config_args(CompilerConfig*, int* pargc, char** argv); +void shd_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv); // parses the remaining arguments into a list of files -void cli_parse_input_files(struct List*, int* pargc, char** argv); +void shd_driver_parse_input_files(struct List* list, int* pargc, char** argv); typedef struct { CompilerConfig config; @@ -63,18 +63,18 @@ typedef struct { const char* loop_tree_output_filename; } DriverConfig; -DriverConfig default_driver_config(); -void destroy_driver_config(DriverConfig*); +DriverConfig shd_default_driver_config(void); +void shd_destroy_driver_config(DriverConfig* config); -void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv); +void shd_parse_driver_args(DriverConfig* args, int* pargc, char** argv); -ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod); -ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod); +ShadyErrorCodes shd_driver_load_source_files(DriverConfig* args, Module* mod); +ShadyErrorCodes shd_driver_compile(DriverConfig* args, Module* mod); typedef enum CompilationResult_ { CompilationNoError } CompilationResult; -CompilationResult run_compiler_passes(CompilerConfig* config, Module** mod); +CompilationResult shd_run_compiler_passes(CompilerConfig* config, Module** pmod); #endif diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index b33ff568b..b5ba969a7 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -116,7 +116,7 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri shd_info_print("Device-side address is: %zu\n", buf_addr); Module* m; - CHECK(driver_load_source_file_from_filename(&args->compiler_config, path, "aobench", &m) == NoError, return); + CHECK(shd_driver_load_source_file_from_filename(&args->compiler_config, path, "aobench", &m) == NoError, return); Program* program = new_program_from_module(runtime, &args->compiler_config, m); // run it twice to compile everything and benefit from caches @@ -147,8 +147,8 @@ int main(int argc, char **argv) { args.compiler_config.input_cf.restructure_with_heuristics = true; - cli_parse_common_args(&argc, argv); - cli_parse_compiler_config_args(&args.compiler_config, &argc, argv); + shd_parse_common_args(&argc, argv); + shd_parse_compiler_config_args(&args.compiler_config, &argc, argv); cli_parse_runtime_config(&args.runtime_config, &argc, argv); cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index d95848926..47f753851 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -45,8 +45,8 @@ int main(int argc, char **argv) RuntimeConfig runtime_config = default_runtime_config(); - cli_parse_common_args(&argc, argv); - cli_parse_compiler_config_args(&compiler_config, &argc, argv); + shd_parse_common_args(&argc, argv); + shd_parse_compiler_config_args(&compiler_config, &argc, argv); cli_parse_runtime_config(&runtime_config, &argc, argv); shd_info_print("Shady checkerboard test starting...\n"); @@ -68,7 +68,8 @@ int main(int argc, char **argv) ArenaConfig aconfig = shd_default_arena_config(&compiler_config.target); IrArena* a = new_ir_arena(&aconfig); Module* m; - if (driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, "checkerboard", &m) != NoError) + if (shd_driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, + "checkerboard", &m) != NoError) shd_error("Failed to load checkerboard module"); Program* program = new_program_from_module(runtime, &compiler_config, m); diff --git a/src/driver/cli.c b/src/driver/cli.c index 52f76cbad..c706fb3e9 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -11,7 +11,7 @@ #include "list.h" #include "util.h" -CodegenTarget guess_target(const char* filename) { +CodegenTarget shd_guess_target(const char* filename) { if (shd_string_ends_with(filename, ".c")) return TgtC; else if (shd_string_ends_with(filename, "glsl")) @@ -24,7 +24,7 @@ CodegenTarget guess_target(const char* filename) { exit(InvalidTarget); } -void cli_pack_remaining_args(int* pargc, char** argv) { +void shd_pack_remaining_args(int* pargc, char** argv) { LARRAY(char*, nargv, *pargc); int nargc = 0; for (size_t i = 0; i < *pargc; i++) { @@ -35,7 +35,7 @@ void cli_pack_remaining_args(int* pargc, char** argv) { *pargc = nargc; } -void cli_parse_common_args(int* pargc, char** argv) { +void shd_parse_common_args(int* pargc, char** argv) { int argc = *pargc; bool help = false; @@ -79,7 +79,7 @@ void cli_parse_common_args(int* pargc, char** argv) { shd_error_print(" --log-level debug[v[v]], info, warn, error]\n"); } - cli_pack_remaining_args(pargc, argv); + shd_pack_remaining_args(pargc, argv); } #define COMPILER_CONFIG_TOGGLE_OPTIONS(F) \ @@ -107,7 +107,7 @@ static IntSizes parse_int_size(String argv) { shd_error("Valid pointer sizes are 8, 16, 32 or 64."); } -void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { +void shd_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** argv) { int argc = *pargc; bool help = false; @@ -186,10 +186,10 @@ void cli_parse_compiler_config_args(CompilerConfig* config, int* pargc, char** a shd_error_print(" --lift-join-points Forcefully lambda-lifts all join points. Can help with reconvergence issues.\n"); } - cli_pack_remaining_args(pargc, argv); + shd_pack_remaining_args(pargc, argv); } -void cli_parse_input_files(struct List* list, int* pargc, char** argv) { +void shd_driver_parse_input_files(struct List* list, int* pargc, char** argv) { int argc = *pargc; for (int i = 1; i < argc; i++) { @@ -199,11 +199,11 @@ void cli_parse_input_files(struct List* list, int* pargc, char** argv) { argv[i] = NULL; } - cli_pack_remaining_args(pargc, argv); + shd_pack_remaining_args(pargc, argv); assert(*pargc == 1); } -DriverConfig default_driver_config() { +DriverConfig shd_default_driver_config(void) { return (DriverConfig) { .config = shd_default_compiler_config(), .target = TgtAuto, @@ -215,11 +215,11 @@ DriverConfig default_driver_config() { }; } -void destroy_driver_config(DriverConfig* config) { +void shd_destroy_driver_config(DriverConfig* config) { shd_destroy_list(config->input_filenames); } -void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { +void shd_parse_driver_args(DriverConfig* args, int* pargc, char** argv) { int argc = *pargc; bool help = false; @@ -299,5 +299,5 @@ void cli_parse_driver_arguments(DriverConfig* args, int* pargc, char** argv) { shd_error_print(" --dump-ir Dumps the final IR\n"); } - cli_pack_remaining_args(pargc, argv); + shd_pack_remaining_args(pargc, argv); } diff --git a/src/driver/cli.h b/src/driver/cli.h index 207c96a57..f7e1995f1 100644 --- a/src/driver/cli.h +++ b/src/driver/cli.h @@ -10,6 +10,6 @@ if (strcmp(argv[i], "--no-"#name) == 0) { \ f = true; argv[i] = NULL; continue; \ } -void cli_pack_remaining_args(int* pargc, char** argv); +void shd_pack_remaining_args(int* pargc, char** argv); #endif diff --git a/src/driver/driver.c b/src/driver/driver.c index f4565c390..1b4dae8a4 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -25,7 +25,7 @@ #pragma GCC diagnostic error "-Wswitch" -SourceLanguage guess_source_language(const char* filename) { +SourceLanguage shd_driver_guess_source_language(const char* filename) { if (shd_string_ends_with(filename, ".ll") || shd_string_ends_with(filename, ".bc")) return SrcLLVM; else if (shd_string_ends_with(filename, ".spv")) @@ -39,7 +39,7 @@ SourceLanguage guess_source_language(const char* filename) { return SrcSlim; } -ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t len, const char* file_contents, String name, Module** mod) { +ShadyErrorCodes shd_driver_load_source_file(const CompilerConfig* config, SourceLanguage lang, size_t len, const char* file_contents, String name, Module** mod) { switch (lang) { case SrcLLVM: { #ifdef LLVM_PARSER_PRESENT @@ -70,9 +70,9 @@ ShadyErrorCodes driver_load_source_file(const CompilerConfig* config, SourceLang return NoError; } -ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, String name, Module** mod) { +ShadyErrorCodes shd_driver_load_source_file_from_filename(const CompilerConfig* config, const char* filename, String name, Module** mod) { ShadyErrorCodes err; - SourceLanguage lang = guess_source_language(filename); + SourceLanguage lang = shd_driver_guess_source_language(filename); size_t len; char* contents; assert(filename); @@ -87,13 +87,13 @@ ShadyErrorCodes driver_load_source_file_from_filename(const CompilerConfig* conf err = InputFileDoesNotExist; goto exit; } - err = driver_load_source_file(config, lang, len, contents, name, mod); + err = shd_driver_load_source_file(config, lang, len, contents, name, mod); free((void*) contents); exit: return err; } -ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { +ShadyErrorCodes shd_driver_load_source_files(DriverConfig* args, Module* mod) { if (shd_list_count(args->input_filenames) == 0) { shd_error_print("Missing input file. See --help for proper usage"); return MissingInputArg; @@ -102,7 +102,9 @@ ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { size_t num_source_files = shd_list_count(args->input_filenames); for (size_t i = 0; i < num_source_files; i++) { Module* m; - int err = driver_load_source_file_from_filename(&args->config, shd_read_list(const char*, args->input_filenames)[i], shd_read_list(const char*, args->input_filenames)[i], &m); + int err = shd_driver_load_source_file_from_filename(&args->config, + shd_read_list(const char*, args->input_filenames)[i], + shd_read_list(const char*, args->input_filenames)[i], &m); if (err) return err; link_module(mod, m); @@ -112,11 +114,11 @@ ShadyErrorCodes driver_load_source_files(DriverConfig* args, Module* mod) { return NoError; } -ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { +ShadyErrorCodes shd_driver_compile(DriverConfig* args, Module* mod) { shd_debugv_print("Parsed program successfully: \n"); shd_log_module(DEBUGV, &args->config, mod); - CompilationResult result = run_compiler_passes(&args->config, &mod); + CompilationResult result = shd_run_compiler_passes(&args->config, &mod); if (result != CompilationNoError) { shd_error_print("Compilation pipeline failed, errcode=%d\n", (int) result); exit(result); @@ -154,7 +156,7 @@ ShadyErrorCodes driver_compile(DriverConfig* args, Module* mod) { if (args->output_filename) { if (args->target == TgtAuto) - args->target = guess_target(args->output_filename); + args->target = shd_guess_target(args->output_filename); FILE* f = fopen(args->output_filename, "wb"); size_t output_size; char* output_buffer; diff --git a/src/driver/slim.c b/src/driver/slim.c index 8c97b8d01..a71afbcea 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -9,25 +9,25 @@ int main(int argc, char** argv) { shd_platform_specific_terminal_init_extras(); - DriverConfig args = default_driver_config(); - cli_parse_driver_arguments(&args, &argc, argv); - cli_parse_common_args(&argc, argv); - cli_parse_compiler_config_args(&args.config, &argc, argv); - cli_parse_input_files(args.input_filenames, &argc, argv); + DriverConfig args = shd_default_driver_config(); + shd_parse_driver_args(&args, &argc, argv); + shd_parse_common_args(&argc, argv); + shd_parse_compiler_config_args(&args.config, &argc, argv); + shd_driver_parse_input_files(args.input_filenames, &argc, argv); ArenaConfig aconfig = shd_default_arena_config(&args.config.target); IrArena* arena = new_ir_arena(&aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one - ShadyErrorCodes err = driver_load_source_files(&args, mod); + ShadyErrorCodes err = shd_driver_load_source_files(&args, mod); if (err) exit(err); - err = driver_compile(&args, mod); + err = shd_driver_compile(&args, mod); if (err) exit(err); shd_info_print("Compilation successful\n"); destroy_ir_arena(arena); - destroy_driver_config(&args); + shd_destroy_driver_config(&args); } diff --git a/src/runtime/runtime_app_common.h b/src/runtime/runtime_app_common.h index f485c22bd..eca75e227 100644 --- a/src/runtime/runtime_app_common.h +++ b/src/runtime/runtime_app_common.h @@ -47,7 +47,7 @@ static void cli_parse_common_app_arguments(CommonAppArgs* args, int* pargc, char exit(0); } - cli_pack_remaining_args(pargc, argv); + shd_pack_remaining_args(pargc, argv); } #endif diff --git a/src/runtime/runtime_cli.c b/src/runtime/runtime_cli.c index 74f2dcc66..7762f7b23 100644 --- a/src/runtime/runtime_cli.c +++ b/src/runtime/runtime_cli.c @@ -45,5 +45,5 @@ void cli_parse_runtime_config(RuntimeConfig* config, int* pargc, char** argv) { shd_error_print(" --dump-ir Dumps the final IR\n"); } - cli_pack_remaining_args(pargc, argv); + shd_pack_remaining_args(pargc, argv); } \ No newline at end of file diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index db4f0828b..78876e209 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -27,7 +27,8 @@ Program* new_program_from_module(Runtime* runtime, const CompilerConfig* base_co Program* load_program(Runtime* runtime, const CompilerConfig* base_config, const char* program_src) { Module* module; - int err = driver_load_source_file(base_config, SrcShadyIR, strlen(program_src), program_src, "my_module", &module); + int err = shd_driver_load_source_file(base_config, SrcShadyIR, strlen(program_src), program_src, "my_module", + &module); if (err != NoError) { return NULL; } @@ -40,7 +41,7 @@ Program* load_program(Runtime* runtime, const CompilerConfig* base_config, const Program* load_program_from_disk(Runtime* runtime, const CompilerConfig* base_config, const char* path) { Module* module; - int err = driver_load_source_file_from_filename(base_config, path, "my_module", &module); + int err = shd_driver_load_source_file_from_filename(base_config, path, "my_module", &module); if (err != NoError) { return NULL; } diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index fb00240cd..1aad6f6c2 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -31,14 +31,14 @@ static const char* default_shader = int main(int argc, char* argv[]) { shd_log_set_level(INFO); Args args = { - .driver_config = default_driver_config(), + .driver_config = shd_default_driver_config(), .runtime_config = default_runtime_config(), }; cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); - cli_parse_common_args(&argc, argv); + shd_parse_common_args(&argc, argv); cli_parse_runtime_config(&args.runtime_config, &argc, argv); - cli_parse_compiler_config_args(&args.driver_config.config, &argc, argv); - cli_parse_input_files(args.driver_config.input_filenames, &argc, argv); + shd_parse_compiler_config_args(&args.driver_config.config, &argc, argv); + shd_driver_parse_input_files(args.driver_config.input_filenames, &argc, argv); shd_info_print("Shady runtime test starting...\n"); @@ -52,11 +52,12 @@ int main(int argc, char* argv[]) { arena = new_ir_arena(&aconfig); if (shd_list_count(args.driver_config.input_filenames) == 0) { Module* module; - driver_load_source_file(&args.driver_config.config, SrcSlim, strlen(default_shader), default_shader, "runtime_test", &module); + shd_driver_load_source_file(&args.driver_config.config, SrcSlim, strlen(default_shader), default_shader, + "runtime_test", &module); program = new_program_from_module(runtime, &args.driver_config.config, module); } else { Module* module = new_module(arena, "my_module"); - int err = driver_load_source_files(&args.driver_config, module); + int err = shd_driver_load_source_files(&args.driver_config, module); if (err) return err; program = new_program_from_module(runtime, &args.driver_config.config, module); @@ -76,6 +77,6 @@ int main(int argc, char* argv[]) { shutdown_runtime(runtime); if (arena) destroy_ir_arena(arena); - destroy_driver_config(&args.driver_config); + shd_destroy_driver_config(&args.driver_config); return 0; } diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 88b43c664..c4c6ffecf 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -382,7 +382,7 @@ static bool compile_specialized_program(VkrSpecProgram* spec) { CompilerConfig config = get_compiler_config_for_device(spec->device, spec->key.base->base_config); config.specialization.entry_point = spec->key.entry_point; - CHECK(run_compiler_passes(&config, &spec->specialized_module) == CompilationNoError, return false); + CHECK(shd_run_compiler_passes(&config, &spec->specialized_module) == CompilationNoError, return false); Module* final_mod; emit_spirv(&config, spec->specialized_module, &spec->spirv_size, &spec->spirv_bytes, &final_mod); diff --git a/src/shady/compile.c b/src/shady/compile.c index 4dc2c4721..75b1c56a6 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -62,7 +62,7 @@ void shd_apply_opt_impl(const CompilerConfig* config, bool* todo, Module** m, Op } } -CompilationResult run_compiler_passes(CompilerConfig* config, Module** pmod) { +CompilationResult shd_run_compiler_passes(CompilerConfig* config, Module** pmod) { IrArena* initial_arena = (*pmod)->arena; // we don't want to mess with the original module diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 9d89f61bc..847cda921 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -60,7 +60,7 @@ static void cli_parse_oracle_args(int* pargc, char** argv) { } } - cli_pack_remaining_args(pargc, argv); + shd_pack_remaining_args(pargc, argv); } static Module* oracle_passes(const CompilerConfig* config, Module* initial_mod) { @@ -76,19 +76,19 @@ static Module* oracle_passes(const CompilerConfig* config, Module* initial_mod) int main(int argc, char** argv) { shd_platform_specific_terminal_init_extras(); - DriverConfig args = default_driver_config(); - cli_parse_driver_arguments(&args, &argc, argv); - cli_parse_common_args(&argc, argv); - cli_parse_compiler_config_args(&args.config, &argc, argv); + DriverConfig args = shd_default_driver_config(); + shd_parse_driver_args(&args, &argc, argv); + shd_parse_common_args(&argc, argv); + shd_parse_compiler_config_args(&args.config, &argc, argv); cli_parse_oracle_args(&argc, argv); - cli_parse_input_files(args.input_filenames, &argc, argv); + shd_driver_parse_input_files(args.input_filenames, &argc, argv); ArenaConfig aconfig = shd_default_arena_config(&args.config.target); aconfig.optimisations.weaken_non_leaking_allocas = true; IrArena* arena = new_ir_arena(&aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one - ShadyErrorCodes err = driver_load_source_files(&args, mod); + ShadyErrorCodes err = shd_driver_load_source_files(&args, mod); if (err) exit(err); @@ -100,5 +100,5 @@ int main(int argc, char** argv) { shd_info_print("Compilation successful\n"); destroy_ir_arena(arena); - destroy_driver_config(&args); + shd_destroy_driver_config(&args); } \ No newline at end of file diff --git a/test/test_builder.c b/test/test_builder.c index bb0672b3a..9232b9cf0 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -156,7 +156,7 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { } int main(int argc, char** argv) { - cli_parse_common_args(&argc, argv); + shd_parse_common_args(&argc, argv); TargetConfig target_config = shd_default_target_config(); ArenaConfig aconfig = shd_default_arena_config(&target_config); diff --git a/test/test_math.c b/test/test_math.c index 78d562af8..d90cd5fa5 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -89,7 +89,7 @@ static void test_int_literals(IrArena* a) { } int main(int argc, char** argv) { - cli_parse_common_args(&argc, argv); + shd_parse_common_args(&argc, argv); TargetConfig target_config = shd_default_target_config(); ArenaConfig aconfig = shd_default_arena_config(&target_config); diff --git a/vcc/vcc.c b/vcc/vcc.c index 4baddd5f3..ad131f679 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -12,13 +12,13 @@ int main(int argc, char** argv) { shd_platform_specific_terminal_init_extras(); - DriverConfig args = default_driver_config(); + DriverConfig args = shd_default_driver_config(); VccConfig vcc_options = vcc_init_config(&args.config); - cli_parse_driver_arguments(&args, &argc, argv); - cli_parse_common_args(&argc, argv); - cli_parse_compiler_config_args(&args.config, &argc, argv); + shd_parse_driver_args(&args, &argc, argv); + shd_parse_common_args(&argc, argv); + shd_parse_compiler_config_args(&args.config, &argc, argv); cli_parse_vcc_args(&vcc_options, &argc, argv); - cli_parse_input_files(args.input_filenames, &argc, argv); + shd_driver_parse_input_files(args.input_filenames, &argc, argv); if (shd_list_count(args.input_filenames) == 0) { shd_error_print("Missing input file. See --help for proper usage"); @@ -36,7 +36,7 @@ int main(int argc, char** argv) { if (!vcc_options.only_run_clang) { Module* mod = vcc_parse_back_into_module(&args.config, &vcc_options, "my_module"); - driver_compile(&args, mod); + shd_driver_compile(&args, mod); destroy_ir_arena(get_module_arena(mod)); } @@ -44,5 +44,5 @@ int main(int argc, char** argv) { destroy_vcc_options(vcc_options); destroy_ir_arena(arena); - destroy_driver_config(&args); + shd_destroy_driver_config(&args); } diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 5db84d161..132005047 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -42,7 +42,7 @@ void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { } } - cli_pack_remaining_args(pargc, argv); + shd_pack_remaining_args(pargc, argv); } void vcc_check_clang(void) { @@ -146,7 +146,7 @@ Module* vcc_parse_back_into_module(CompilerConfig* config, VccConfig* vcc_option if (!shd_read_file(vcc_options->tmp_filename, &len, &llvm_ir)) exit(InputFileIOError); Module* mod; - driver_load_source_file(config, SrcLLVM, len, llvm_ir, module_name, &mod); + shd_driver_load_source_file(config, SrcLLVM, len, llvm_ir, module_name, &mod); free(llvm_ir); if (vcc_options->delete_tmp_file) From 1ed4a7ea35f787b3d0e5bbf8944e432f5a80cda4 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:32:33 +0200 Subject: [PATCH 612/693] move generated node ctors to header-only --- src/shady/api/generator_grammar.c | 49 +++++++++++++++++++++++++- src/shady/constructors.c | 14 ++++---- src/shady/generator/generator.h | 1 - src/shady/generator/generator_common.c | 49 -------------------------- src/shady/generator_constructors.c | 1 - 5 files changed, 55 insertions(+), 59 deletions(-) diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 6b7c5a907..64fdf20b1 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -132,6 +132,50 @@ static void generate_header_getters_for_class(Growy* g, json_object* src, json_o } } +void generate_node_ctor(Growy* g, json_object* nodes) { + for (size_t i = 0; i < json_object_array_length(nodes); i++) { + json_object* node = json_object_array_get_idx(nodes, i); + + String name = json_object_get_string(json_object_object_get(node, "name")); + assert(name); + + if (has_custom_ctor(node)) + continue; + + if (i > 0) + shd_growy_append_formatted(g, "\n"); + + String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); + const void* alloc = NULL; + if (!snake_name) { + alloc = snake_name = to_snake_case(name); + } + + json_object* ops = json_object_object_get(node, "ops"); + if (ops) + shd_growy_append_formatted(g, "static inline const Node* %s(IrArena* arena, %s payload)", snake_name, name); + else + shd_growy_append_formatted(g, "static inline const Node* %s(IrArena* arena)", snake_name); + + shd_growy_append_formatted(g, " {\n"); + shd_growy_append_formatted(g, "\tNode node;\n"); + shd_growy_append_formatted(g, "\tmemset((void*) &node, 0, sizeof(Node));\n"); + shd_growy_append_formatted(g, "\tnode = (Node) {\n"); + shd_growy_append_formatted(g, "\t\t.arena = arena,\n"); + shd_growy_append_formatted(g, "\t\t.tag = %s_TAG,\n", name); + if (ops) + shd_growy_append_formatted(g, "\t\t.payload.%s = payload,\n", snake_name); + shd_growy_append_formatted(g, "\t\t.type = NULL,\n"); + shd_growy_append_formatted(g, "\t};\n"); + shd_growy_append_formatted(g, "\treturn _shd_create_node_helper(arena, node, NULL);\n"); + shd_growy_append_formatted(g, "}\n"); + + if (alloc) + free((void*) alloc); + } + shd_growy_append_formatted(g, "\n"); +} + void generate(Growy* g, json_object* src) { generate_header(g, src); @@ -145,7 +189,10 @@ void generate(Growy* g, json_object* src) { shd_growy_append_formatted(g, "NodeClass get_node_class_from_tag(NodeTag tag);\n\n"); generate_node_payloads(g, src, nodes); generate_node_type(g, nodes); - generate_node_ctor(g, nodes, false); + + shd_growy_append_formatted(g, "#include \n"); + shd_growy_append_formatted(g, "Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh);\n"); + generate_node_ctor(g, nodes); for (size_t i = 0; i < json_object_array_length(node_classes); i++) { json_object* node_class = json_object_array_get_idx(node_classes, i); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 51e88d5da..f434893fb 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -19,7 +19,7 @@ const Node* fold_node_operand(NodeTag tag, NodeClass, String, const Node* op); const Type* check_type_generated(IrArena* a, const Node* node); -static Node* create_node_helper(IrArena* arena, Node node, bool* pfresh) { +Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh) { pre_construction_validation(arena, &node); if (arena->config.check_types) node.type = check_type_generated(arena, &node); @@ -74,7 +74,7 @@ Node* param(IrArena* arena, const Type* type, const char* name) { .tag = Param_TAG, .payload.param = param }; - return create_node_helper(arena, node, NULL); + return _shd_create_node_helper(arena, node, NULL); } const Node* composite_helper(IrArena* a, const Type* t, Nodes contents) { @@ -123,7 +123,7 @@ Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, N .tag = Function_TAG, .payload.fun = payload }; - Node* fn = create_node_helper(arena, node, NULL); + Node* fn = _shd_create_node_helper(arena, node, NULL); register_decl_module(mod, fn); for (size_t i = 0; i < params.count; i++) { @@ -152,7 +152,7 @@ Node* basic_block(IrArena* arena, Nodes params, const char* name) { .payload.basic_block = payload }; - Node* bb = create_node_helper(arena, node, NULL); + Node* bb = _shd_create_node_helper(arena, node, NULL); for (size_t i = 0; i < params.count; i++) { Node* param = (Node*) params.nodes[i]; @@ -180,7 +180,7 @@ Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { .tag = Constant_TAG, .payload.constant = cnst }; - Node* decl = create_node_helper(arena, node, NULL); + Node* decl = _shd_create_node_helper(arena, node, NULL); register_decl_module(mod, decl); return decl; } @@ -211,7 +211,7 @@ Node* global_var(Module* mod, Nodes annotations, const Type* type, const char* n .tag = GlobalVariable_TAG, .payload.global_variable = gvar }; - Node* decl = create_node_helper(arena, node, NULL); + Node* decl = _shd_create_node_helper(arena, node, NULL); register_decl_module(mod, decl); return decl; } @@ -233,7 +233,7 @@ Type* nominal_type(Module* mod, Nodes annotations, String name) { .tag = NominalType_TAG, .payload.nom_type = payload }; - Node* decl = create_node_helper(arena, node, NULL); + Node* decl = _shd_create_node_helper(arena, node, NULL); register_decl_module(mod, decl); return decl; } diff --git a/src/shady/generator/generator.h b/src/shady/generator/generator.h index c046431f7..a9facaef1 100644 --- a/src/shady/generator/generator.h +++ b/src/shady/generator/generator.h @@ -22,7 +22,6 @@ String capitalize(String str); bool starts_with_vowel(String str); bool has_custom_ctor(json_object* node); -void generate_node_ctor(Growy* g, json_object* nodes, bool definition); json_object* lookup_node_class(json_object* src, String name); String class_to_type(json_object* src, String class, bool list); diff --git a/src/shady/generator/generator_common.c b/src/shady/generator/generator_common.c index 1e43a2c4d..3b915b8d3 100644 --- a/src/shady/generator/generator_common.c +++ b/src/shady/generator/generator_common.c @@ -5,55 +5,6 @@ bool has_custom_ctor(json_object* node) { return (constructor && strcmp(constructor, "custom") == 0); } -void generate_node_ctor(Growy* g, json_object* nodes, bool definition) { - for (size_t i = 0; i < json_object_array_length(nodes); i++) { - json_object* node = json_object_array_get_idx(nodes, i); - - String name = json_object_get_string(json_object_object_get(node, "name")); - assert(name); - - if (has_custom_ctor(node)) - continue; - - if (definition && i > 0) - shd_growy_append_formatted(g, "\n"); - - String snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); - const void* alloc = NULL; - if (!snake_name) { - alloc = snake_name = to_snake_case(name); - } - - String ap = definition ? " arena" : ""; - json_object* ops = json_object_object_get(node, "ops"); - if (ops) - shd_growy_append_formatted(g, "const Node* %s(IrArena*%s, %s%s)", snake_name, ap, name, definition ? " payload" : ""); - else - shd_growy_append_formatted(g, "const Node* %s(IrArena*%s)", snake_name, ap); - - if (definition) { - shd_growy_append_formatted(g, " {\n"); - shd_growy_append_formatted(g, "\tNode node;\n"); - shd_growy_append_formatted(g, "\tmemset((void*) &node, 0, sizeof(Node));\n"); - shd_growy_append_formatted(g, "\tnode = (Node) {\n"); - shd_growy_append_formatted(g, "\t\t.arena = arena,\n"); - shd_growy_append_formatted(g, "\t\t.tag = %s_TAG,\n", name); - if (ops) - shd_growy_append_formatted(g, "\t\t.payload.%s = payload,\n", snake_name); - shd_growy_append_formatted(g, "\t\t.type = NULL,\n"); - shd_growy_append_formatted(g, "\t};\n"); - shd_growy_append_formatted(g, "\treturn create_node_helper(arena, node, NULL);\n"); - shd_growy_append_formatted(g, "}\n"); - } else { - shd_growy_append_formatted(g, ";\n"); - } - - if (alloc) - free((void*) alloc); - } - shd_growy_append_formatted(g, "\n"); -} - json_object* lookup_node_class(json_object* src, String name) { json_object* node_classes = json_object_object_get(src, "node-classes"); for (size_t i = 0; i < json_object_array_length(node_classes); i++) { diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index da07e0ad3..81e5f1047 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -80,6 +80,5 @@ void generate(Growy* g, json_object* src) { generate_header(g, src); json_object* nodes = json_object_object_get(src, "nodes"); - generate_node_ctor(g, nodes, true); generate_pre_construction_validation(g, src); } From 076ac1f01933d4eaea3ec217e2c5fa500ed686c4 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:35:21 +0200 Subject: [PATCH 613/693] added basic code style info --- doc/code_style.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 doc/code_style.md diff --git a/doc/code_style.md b/doc/code_style.md new file mode 100644 index 000000000..60545ef20 --- /dev/null +++ b/doc/code_style.md @@ -0,0 +1,39 @@ +# Code style Guidelines + +This guide is for our own reference as much as anyone else. +If you have a good reason for breaking any of those rules we're happy to consider your contributions without prejudice. + + * 4 spaces indentation + * `Type* name` + * `snake_case` by default + * `UpperCamelCase` for types and typedefs + * Use only typedefs or append `_` to struct/union/enums names + * `LOUD_CASE` for public macros + * `{ spaces, surrounding, initializer, lists }` + * Unless you're literally contributing using a 80-column display (for which I'll ask visual proof), don't format your code as if you do. + * Include order: + * If appropriate, (Private) `self.h` should always come first + * Then other `shady/` headers + * Then in-project utility headers + * Then external headers + * Finally, standard C library headers. + * Each category of includes spaced by an empty line + +## Symbol naming + +Due to C not having namespaces, we have to deal with this painfully automatable problem ourselves. + + * Avoid exposing any symbols that don't need to be exposed (use `static` wherever you can) + * Prefixes: + * `shd_` in front of API functions (in the root `include` folder) + * `subsystem_` is acceptable for internal use + * `shd_subsystem_` is preferable where a clear delineation can be made + * `shd_new_thing` and `shd_destroy_thing` for constructors and destructors + * `static inline` functions in headers are not required to be prefixed + * Types & Typedefs may be prefixed with `Shd` + * Alternatively, subsystem-relevant ones can use another prefix, much like for functions +* Do not expose global variables to external APIs at all (provide getter functions if necessary) + +## Cursing in comments + +Can be funny but keep it somewhat family friendly. \ No newline at end of file From 62fe235e25a7b38271d8deb01128cff9f45f74bf Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 6 Oct 2024 17:50:50 +0200 Subject: [PATCH 614/693] removed manually-built node ctor helpers --- include/shady/ir.h | 13 ------- src/backend/c/emit_c.c | 4 +- src/backend/c/emit_c_value.c | 2 +- src/backend/spirv/spirv_lift_globals_ssbo.c | 3 +- src/frontend/llvm/l2s.c | 4 +- src/frontend/llvm/l2s_instr.c | 4 +- src/frontend/llvm/l2s_postprocess.c | 5 ++- src/frontend/llvm/l2s_type.c | 4 +- src/frontend/slim/infer.c | 13 ++++--- src/frontend/spirv/s2s.c | 12 ++++-- src/shady/api/generator_grammar.c | 27 ++++++++++++- src/shady/body_builder.c | 2 +- src/shady/constructors.c | 42 +-------------------- src/shady/node.c | 2 +- src/shady/passes/cleanup.c | 3 +- src/shady/passes/lift_indirect_targets.c | 5 ++- src/shady/passes/lower_callf.c | 7 ++-- src/shady/passes/lower_cf_instrs.c | 11 +++--- src/shady/passes/lower_generic_ptrs.c | 18 ++++----- src/shady/passes/lower_memcpy.c | 8 ++-- src/shady/passes/lower_subgroup_ops.c | 7 ++-- src/shady/passes/lower_subgroup_vars.c | 3 +- src/shady/passes/lower_tailcalls.c | 20 +++++----- src/shady/passes/lower_workgroups.c | 4 +- src/shady/passes/opt_inline.c | 2 +- src/shady/passes/opt_restructure.c | 15 ++++---- src/shady/passes/reconvergence_heuristics.c | 23 ++++++----- src/shady/passes/remove_critical_edges.c | 6 ++- src/shady/passes/scope2control.c | 13 ++++--- src/shady/type.c | 36 ++++++++++-------- src/shady/type.h | 2 +- src/shady/type_helpers.c | 5 ++- test/test_builder.c | 28 +++++++------- 33 files changed, 175 insertions(+), 178 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 749109a0f..84715a009 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -249,25 +249,12 @@ const Type* shd_fp64_type(IrArena* arena); const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value); -const Node* type_decl_ref_helper(IrArena*, const Node* decl); - // values Node* param(IrArena*, const Type* type, const char* name); const Node* tuple_helper(IrArena*, Nodes contents); -const Node* composite_helper(IrArena*, const Type*, Nodes contents); -const Node* fn_addr_helper(IrArena*, const Node* fn); -const Node* ref_decl_helper(IrArena*, const Node* decl); -const Node* string_lit_helper(IrArena* a, String s); -const Node* annotation_value_helper(IrArena* a, String n, const Node* v); - -// instructions -const Node* prim_op_helper(IrArena*, Op, Nodes, Nodes); const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); -// terminators -const Node* jump_helper(IrArena* a, const Node* dst, Nodes args, const Node* mem); - // decl ctors Node* function (Module*, Nodes params, const char* name, Nodes annotations, Nodes return_types); Node* constant (Module*, Nodes annotations, const Type*, const char* name); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index c489e22d1..56c326e16 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -109,8 +109,8 @@ static bool has_forward_declarations(CDialect dialect) { CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term) { String interm = unique_name(emitter->arena, "intermediary_ptr_value"); assert(ptr_type->tag == PtrType_TAG); - const Type* ut = qualified_type_helper(ptr_type, true); - const Type* vt = qualified_type_helper(ptr_type, false); + const Type* ut = shd_as_qualified_type(ptr_type, true); + const Type* vt = shd_as_qualified_type(ptr_type, false); String lhs = c_emit_type(emitter, vt, interm); shd_print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, c_emit_type(emitter, ut, NULL), to_cvalue(emitter, term)); return term_from_cvalue(interm); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 5fb2917d3..1642845db 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -822,7 +822,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer // See https://github.com/ispc/ispc/issues/2496 if (emitter->config.dialect == CDialect_ISPC) { String interm = unique_name(arena, "lea_intermediary_ptr_value"); - shd_print(p, "\n%s = %s;", c_emit_type(emitter, qualified_type_helper(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); + shd_print(p, "\n%s = %s;", c_emit_type(emitter, shd_as_qualified_type(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); acc = term_from_cvalue(interm); } diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 525d39fa0..4fc715413 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -31,7 +31,8 @@ static const Node* process(Context* ctx, const Node* node) { Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); - set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, shd_empty(a), bb_mem(functx.bb)))); + set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, + shd_empty(a)))); shd_destroy_dict(functx.rewriter.map); } return newfun; diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index aefd05bfc..d8a08b797 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -83,7 +83,7 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic while (instr) { switch (LLVMGetInstructionOpcode(instr)) { case LLVMPHI: { - const Node* nparam = param(a, qualified_type_helper(convert_type(p, LLVMTypeOf(instr)), false), "phi"); + const Node* nparam = param(a, shd_as_qualified_type(convert_type(p, LLVMTypeOf(instr)), false), "phi"); shd_dict_insert(LLVMValueRef, const Node*, p->map, instr, nparam); shd_list_append(LLVMValueRef, phis, instr); params = shd_nodes_append(a, params, nparam); @@ -158,7 +158,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { for (LLVMValueRef oparam = LLVMGetFirstParam(fn); oparam; oparam = LLVMGetNextParam(oparam)) { LLVMTypeRef ot = LLVMTypeOf(oparam); const Type* t = convert_type(p, ot); - const Node* nparam = param(a, qualified_type_helper(t, false), LLVMGetValueName(oparam)); + const Node* nparam = param(a, shd_as_qualified_type(t, false), LLVMGetValueName(oparam)); shd_dict_insert(LLVMValueRef, const Node*, p->map, oparam, nparam); params = shd_nodes_append(a, params, nparam); if (oparam == LLVMGetLastParam(fn)) diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 105f52185..a38cf3a7a 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -74,7 +74,7 @@ static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, assert(false && "failed to find the appropriate source"); next: continue; } - return jump_helper(a, dst_bb, shd_nodes(a, params_count, params), mem); + return jump_helper(a, mem, dst_bb, shd_nodes(a, params_count, params)); } static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* element_type) { @@ -274,7 +274,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); bool idk; - //element_t = qualified_type_helper(element_t, false); + //element_t = shd_as_qualified_type(element_t, false); enter_composite_indices(&element_t, &idk, shd_nodes(a, ops.count - 2, &ops.nodes[2]), true); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); r = prim_op_helper(a, reinterpret_op, shd_singleton(untyped_ptr_t), BIND_PREV_R(typed_ptr)); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 95ed2a8c5..33b01c1eb 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -30,7 +30,7 @@ static Nodes remake_params(Context* ctx, Nodes old) { if (node->payload.param.type->tag == QualifiedType_TAG) t = rewrite_node(r, node->payload.param.type); else - t = qualified_type_helper(rewrite_node(r, node->payload.param.type), false); + t = shd_as_qualified_type(rewrite_node(r, node->payload.param.type), false); } nvars[i] = param(a, t, node->payload.param.name); assert(nvars[i]->tag == Param_TAG); @@ -73,7 +73,8 @@ static const Node* process_node(Context* ctx, const Node* node) { primop_intrinsic = op; } else if (strcmp(get_annotation_name(an->payload), "EntryPoint") == 0) { for (size_t i = 0; i < new_params.count; i++) - new_params = shd_change_node_at_index(a, new_params, i, param(a, qualified_type_helper(get_unqualified_type(new_params.nodes[i]->payload.param.type), true), new_params.nodes[i]->payload.param.name)); + new_params = shd_change_node_at_index(a, new_params, i, param(a, shd_as_qualified_type( + get_unqualified_type(new_params.nodes[i]->payload.param.type), true), new_params.nodes[i]->payload.param.name)); } old_annotations = shd_nodes_append(a, old_annotations, an->payload); an = an->next; diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index b00756bbf..6a659d66f 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -36,12 +36,12 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { LLVMGetParamTypes(t, param_types); LARRAY(const Type*, cparam_types, num_params); for (size_t i = 0; i < num_params; i++) - cparam_types[i] = qualified_type_helper(convert_type(p, param_types[i]), false); + cparam_types[i] = shd_as_qualified_type(convert_type(p, param_types[i]), false); const Type* ret_type = convert_type(p, LLVMGetReturnType(t)); if (LLVMGetTypeKind(LLVMGetReturnType(t)) == LLVMVoidTypeKind) ret_type = empty_multiple_return_type(a); else - ret_type = qualified_type_helper(ret_type, false); + ret_type = shd_as_qualified_type(ret_type, false); return fn_type(a, (FnType) { .param_types = shd_nodes(a, num_params, cparam_types), .return_types = ret_type == empty_multiple_return_type(a) ? shd_empty(a) : shd_singleton(ret_type) diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 4b550a5c4..71d8e2aee 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -114,7 +114,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { const Node* instruction = NULL; if (imported_hint) { assert(is_data_type(imported_hint)); - const Node* s = qualified_type_helper(imported_hint, true); + const Node* s = shd_as_qualified_type(imported_hint, true); if (oconstant->value) instruction = infer(ctx, oconstant->value, s); } else if (oconstant->value) { @@ -136,7 +136,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { Node* ngvar = global_var(ctx->rewriter.dst_module, infer_nodes(ctx, old_gvar->annotations), imported_ty, old_gvar->name, old_gvar->address_space); register_processed(&ctx->rewriter, node, ngvar); - ngvar->payload.global_variable.init = infer(ctx, old_gvar->init, qualified_type_helper(imported_ty, true)); + ngvar->payload.global_variable.init = infer(ctx, old_gvar->init, shd_as_qualified_type(imported_ty, true)); return ngvar; } case NominalType_TAG: { @@ -172,7 +172,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec expect_uniform = deconstruct_qualified_type(&expected_type); assert(is_subtype(expected_type, type)); } - return infer(ctx, node->payload.constrained.value, qualified_type_helper(type, expect_uniform)); + return infer(ctx, node->payload.constrained.value, shd_as_qualified_type(type, expect_uniform)); } case IntLiteral_TAG: { if (expected_type) { @@ -368,7 +368,8 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe } case empty_mask_op: case mask_is_thread_active_op: { - input_types = mk_nodes(a, qualified_type_helper(mask_type(a), false), qualified_type_helper(shd_uint32_type(a), false)); + input_types = mk_nodes(a, shd_as_qualified_type(mask_type(a), false), + shd_as_qualified_type(shd_uint32_type(a), false)); break; } default: { @@ -427,7 +428,7 @@ static const Node* infer_indirect_call(Context* ctx, const Node* node, const Nod static const Node* infer_if(Context* ctx, const Node* node) { assert(node->tag == If_TAG); IrArena* a = ctx->rewriter.dst_arena; - const Node* condition = infer(ctx, node->payload.if_instr.condition, qualified_type_helper(bool_type(a), false)); + const Node* condition = infer(ctx, node->payload.if_instr.condition, shd_as_qualified_type(bool_type(a), false)); Nodes join_types = infer_nodes(ctx, node->payload.if_instr.yield_types); Context infer_if_body_ctx = *ctx; @@ -527,7 +528,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* assert(ptr_type->tag == PtrType_TAG); const Type* element_t = ptr_type->payload.ptr_type.pointed_type; assert(element_t); - const Node* value = infer(ctx, payload.value, qualified_type_helper(element_t, false)); + const Node* value = infer(ctx, payload.value, shd_as_qualified_type(element_t, false)); return store(a, (Store) { .ptr = ptr, .value = value, .mem = infer(ctx, node->payload.store.mem, NULL) }); } case Instruction_StackAlloc_TAG: { diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 24bb114c3..7926fe642 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -857,7 +857,8 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].type = Value; String param_name = get_name(parser, result); param_name = param_name ? param_name : shd_format_string_arena(parser->arena->arena, "param%d", parser->fun_arg_i); - parser->defs[result].node = param(parser->arena, qualified_type_helper(get_def_type(parser, result_t), parser->is_entry_pt), param_name); + parser->defs[result].node = param(parser->arena, + shd_as_qualified_type(get_def_type(parser, result_t), parser->is_entry_pt), param_name); break; } case SpvOpLabel: { @@ -916,7 +917,8 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].type = Value; String phi_name = get_name(parser, result); phi_name = phi_name ? phi_name : unique_name(parser->arena, "phi"); - parser->defs[result].node = param(parser->arena, qualified_type_helper(get_def_type(parser, result_t), false), phi_name); + parser->defs[result].node = param(parser->arena, + shd_as_qualified_type(get_def_type(parser, result_t), false), phi_name); assert(size % 2 == 1); int num_callsites = (size - 3) / 2; for (size_t i = 0; i < num_callsites; i++) { @@ -1287,8 +1289,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { SpvId destinations[2] = { instruction[2], instruction[3] }; BodyBuilder* bb = parser->current_block.builder; parser->current_block.finished = finish_body(bb, branch(parser->arena, (Branch) { - .true_jump = jump_helper(parser->arena, get_def_block(parser, destinations[0]), get_args_from_phi(parser, destinations[0], parser->current_block.id), bb_mem(bb)), - .false_jump = jump_helper(parser->arena, get_def_block(parser, destinations[1]), get_args_from_phi(parser, destinations[1], parser->current_block.id), bb_mem(bb)), + .true_jump = jump_helper(parser->arena, bb_mem(bb), get_def_block(parser, destinations[0]), + get_args_from_phi(parser, destinations[0], parser->current_block.id)), + .false_jump = jump_helper(parser->arena, bb_mem(bb), get_def_block(parser, destinations[1]), + get_args_from_phi(parser, destinations[1], parser->current_block.id)), .condition = get_def_ssa_value(parser, instruction[1]), })); parser->current_block.builder = NULL; diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 64fdf20b1..ddc4d1761 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -132,7 +132,7 @@ static void generate_header_getters_for_class(Growy* g, json_object* src, json_o } } -void generate_node_ctor(Growy* g, json_object* nodes) { +void generate_node_ctor(Growy* g, json_object* src, json_object* nodes) { for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); @@ -170,6 +170,29 @@ void generate_node_ctor(Growy* g, json_object* nodes) { shd_growy_append_formatted(g, "\treturn _shd_create_node_helper(arena, node, NULL);\n"); shd_growy_append_formatted(g, "}\n"); + // Generate helper variant + if (ops) { + shd_growy_append_formatted(g, "static inline const Node* %s_helper(IrArena* arena, ", snake_name); + for (size_t j = 0; j < json_object_array_length(ops); j++) { + json_object* op = json_object_array_get_idx(ops, j); + String op_name = json_object_get_string(json_object_object_get(op, "name")); + shd_growy_append_formatted(g, "\t%s %s", get_type_for_operand(src, op), op_name); + if (j + 1 < json_object_array_length(ops)) + shd_growy_append_formatted(g, ", "); + } + shd_growy_append_formatted(g, ") {\n"); + shd_growy_append_formatted(g, "\treturn %s(arena, (%s) {", snake_name, name); + for (size_t j = 0; j < json_object_array_length(ops); j++) { + json_object* op = json_object_array_get_idx(ops, j); + String op_name = json_object_get_string(json_object_object_get(op, "name")); + shd_growy_append_formatted(g, ".%s = %s", op_name, op_name); + if (j + 1 < json_object_array_length(ops)) + shd_growy_append_formatted(g, ", "); + } + shd_growy_append_formatted(g, "});\n"); + shd_growy_append_formatted(g, "}\n"); + } + if (alloc) free((void*) alloc); } @@ -192,7 +215,7 @@ void generate(Growy* g, json_object* src) { shd_growy_append_formatted(g, "#include \n"); shd_growy_append_formatted(g, "Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh);\n"); - generate_node_ctor(g, nodes); + generate_node_ctor(g, src, nodes); for (size_t i = 0; i < json_object_array_length(node_classes); i++) { json_object* node_class = json_object_array_get_idx(node_classes, i); diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 734d4af5c..e0557921d 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -344,7 +344,7 @@ begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes BodyBuilder* outer_control_case_builder = begin_body_with_mem(a, get_abstraction_mem(outer_control.case_)); LARRAY(const Node*, params, arg_types.count); for (size_t i = 0; i < arg_types.count; i++) { - params[i] = param(a, qualified_type_helper(arg_types.nodes[i], false), NULL); + params[i] = param(a, shd_as_qualified_type(arg_types.nodes[i], false), NULL); } Node* loop_header = case_(a, shd_nodes(a, arg_types.count, params)); set_abstraction_body(outer_control.case_, finish_body_with_jump(outer_control_case_builder, loop_header, initial_values)); diff --git a/src/shady/constructors.c b/src/shady/constructors.c index f434893fb..67d07988f 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -77,10 +77,6 @@ Node* param(IrArena* arena, const Type* type, const char* name) { return _shd_create_node_helper(arena, node, NULL); } -const Node* composite_helper(IrArena* a, const Type* t, Nodes contents) { - return composite(a, (Composite) { .type = t, .contents = contents }); -} - const Node* tuple_helper(IrArena* a, Nodes contents) { const Type* t = NULL; if (a->config.check_types) { @@ -92,18 +88,6 @@ const Node* tuple_helper(IrArena* a, Nodes contents) { return composite_helper(a, t, contents); } -const Node* fn_addr_helper(IrArena* a, const Node* fn) { - return fn_addr(a, (FnAddr) { .fn = fn }); -} - -const Node* ref_decl_helper(IrArena* a, const Node* decl) { - return ref_decl(a, (RefDecl) { .decl = decl }); -} - -const Node* type_decl_ref_helper(IrArena* a, const Node* decl) { - return type_decl_ref(a, (TypeDeclRef) { .decl = decl }); -} - Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, Nodes return_types) { assert(!mod->sealed); IrArena* arena = mod->arena; @@ -238,14 +222,6 @@ Type* nominal_type(Module* mod, Nodes annotations, String name) { return decl; } -const Node* prim_op_helper(IrArena* a, Op op, Nodes types, Nodes operands) { - return prim_op(a, (PrimOp) { - .op = op, - .type_arguments = types, - .operands = operands - }); -} - const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes indices) { const Node* lea = ptr_array_element_offset(a, (PtrArrayElementOffset) { .ptr = ptr, @@ -260,14 +236,6 @@ const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes in return lea; } -const Node* jump_helper(IrArena* a, const Node* dst, Nodes args, const Node* mem) { - return jump(a, (Jump) { - .target = dst, - .args = args, - .mem = mem, - }); -} - const Node* unit_type(IrArena* arena) { return record_type(arena, (RecordType) { .members = shd_empty(arena), @@ -275,15 +243,7 @@ const Node* unit_type(IrArena* arena) { } const Node* empty_multiple_return_type(IrArena* arena) { - return qualified_type_helper(unit_type(arena), true); -} - -const Node* annotation_value_helper(IrArena* a, String n, const Node* v) { - return annotation_value(a, (AnnotationValue) { .name = n, .value = v}); -} - -const Node* string_lit_helper(IrArena* a, String s) { - return string_lit(a, (StringLiteral) { .string = s }); + return shd_as_qualified_type(unit_type(arena), true); } const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w) { return int_type(a, (Int) { .width = w, .is_signed = s }); } diff --git a/src/shady/node.c b/src/shady/node.c index 548214d41..84aecfacd 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -312,7 +312,7 @@ void set_abstraction_body(Node* abs, const Node* body) { const Node* mem = insert->block_entry_mem; const Node* block = insert->block_entry_block; set_abstraction_body((Node*) block, finish_block_body(insert, body)); - body = jump_helper(a, block, shd_empty(a), mem); + body = jump_helper(a, mem, block, shd_empty(a)); // mem_abs->payload.basic_block.insert = NULL; continue; } diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 3ca1da893..b8d775b85 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -100,7 +100,8 @@ const Node* process(Context* ctx, const Node* old) { Control old_control_payload = control->payload.control; // there was a control but now there is not anymore - jump to the tail! if (rewrite_node(r, old_control_payload.inside) == NULL) { - return jump_helper(a, rewrite_node(r, old_control_payload.tail), rewrite_nodes(r, payload.args), rewrite_node(r, payload.mem)); + return jump_helper(a, rewrite_node(r, payload.mem), rewrite_node(r, old_control_payload.tail), + rewrite_nodes(r, payload.args)); } } break; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 8ffd407b1..516b96e3b 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -121,7 +121,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { register_processed_list(r, ovariables, new_params); - const Node* payload = param(a, qualified_type_helper(shd_uint32_type(a), false), "sp"); + const Node* payload = param(a, shd_as_qualified_type(shd_uint32_type(a), false), "sp"); // Keep annotations the same Nodes annotations = shd_singleton(annotation(a, (Annotation) { .name = "Exported" })); @@ -204,7 +204,8 @@ static const Node* process_node(Context* ctx, const Node* node) { const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = rewrite_nodes(&ctx->rewriter, node->payload.control.yield_types), }); - const Node* jp = gen_ext_instruction(bb, "shady.internal", ShadyOpCreateJoinPoint, qualified_type_helper(jp_type, true), mk_nodes(a, tail_ptr, sp)); + const Node* jp = gen_ext_instruction(bb, "shady.internal", ShadyOpCreateJoinPoint, + shd_as_qualified_type(jp_type, true), mk_nodes(a, tail_ptr, sp)); // dumbass hack jp = gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(jp)); diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 903cf76f3..91883e52d 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -44,9 +44,10 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { }); if (lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { - ctx2.return_jp = gen_ext_instruction(bb, "shady.internal", ShadyOpDefaultJoinPoint, qualified_type_helper(jp_type, true), shd_empty(a)); + ctx2.return_jp = gen_ext_instruction(bb, "shady.internal", ShadyOpDefaultJoinPoint, + shd_as_qualified_type(jp_type, true), shd_empty(a)); } else { - const Node* jp_variable = param(a, qualified_type_helper(jp_type, false), "return_jp"); + const Node* jp_variable = param(a, shd_as_qualified_type(jp_type, false), "return_jp"); nparams = shd_nodes_append(a, nparams, jp_variable); ctx2.return_jp = jp_variable; } @@ -56,7 +57,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(prelude, finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body))); - set_abstraction_body(fun, jump_helper(a, prelude, shd_empty(a), get_abstraction_mem(fun))); + set_abstraction_body(fun, jump_helper(a, get_abstraction_mem(fun), prelude, shd_empty(a))); return fun; } diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 3ef955f4d..40a247873 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -69,15 +69,15 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* control_case = basic_block(a, shd_singleton(jp), NULL); const Node* control_body = branch(a, (Branch) { .condition = rewrite_node(r, node->payload.if_instr.condition), - .true_jump = jump_helper(a, true_block, shd_empty(a), get_abstraction_mem(control_case)), - .false_jump = jump_helper(a, false_block, shd_empty(a), get_abstraction_mem(control_case)), + .true_jump = jump_helper(a, get_abstraction_mem(control_case), true_block, shd_empty(a)), + .false_jump = jump_helper(a, get_abstraction_mem(control_case), false_block, shd_empty(a)), .mem = get_abstraction_mem(control_case), }); set_abstraction_body(control_case, control_body); BodyBuilder* bb = begin_body_with_mem(a, nmem); Nodes results = gen_control(bb, yield_types, control_case); - return finish_body(bb, jump_helper(a, rewrite_node(r, payload.tail), results, bb_mem(bb))); + return finish_body(bb, jump_helper(a, bb_mem(bb), rewrite_node(r, payload.tail), results)); } // TODO: match case Loop_TAG: { @@ -106,7 +106,8 @@ static const Node* process_node(Context* ctx, const Node* node) { BodyBuilder* inner_bb = begin_body_with_mem(a, get_abstraction_mem(loop_header_block)); Node* inner_control_case = case_(a, shd_singleton(continue_point)); - set_abstraction_body(inner_control_case, jump_helper(a, rewrite_node(r, old_loop_block), new_params, get_abstraction_mem(inner_control_case))); + set_abstraction_body(inner_control_case, jump_helper(a, get_abstraction_mem(inner_control_case), + rewrite_node(r, old_loop_block), new_params)); Nodes args = gen_control(inner_bb, param_types, inner_control_case); set_abstraction_body(loop_header_block, finish_body(inner_bb, jump(a, (Jump) { .target = loop_header_block, .args = args, .mem = bb_mem(inner_bb) }))); @@ -121,7 +122,7 @@ static const Node* process_node(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); Nodes results = gen_control(bb, yield_types, outer_control_case); - return finish_body(bb, jump_helper(a, rewrite_node(r, payload.tail), results, bb_mem(bb))); + return finish_body(bb, jump_helper(a, bb_mem(bb), rewrite_node(r, payload.tail), results)); } case MergeSelection_TAG: { MergeSelection payload = node->payload.merge_selection; diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 13e1caeb5..ad496554c 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -89,16 +89,16 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo if (found) return *found; - const Node* ptr_param = param(a, qualified_type_helper(ctx->generic_ptr_type, uniform_ptr), "ptr"); + const Node* ptr_param = param(a, shd_as_qualified_type(ctx->generic_ptr_type, uniform_ptr), "ptr"); const Node* value_param; Nodes params = shd_singleton(ptr_param); Nodes return_ts = shd_empty(a); switch (which) { case LoadFn: - return_ts = shd_singleton(qualified_type_helper(t, uniform_ptr)); + return_ts = shd_singleton(shd_as_qualified_type(t, uniform_ptr)); break; case StoreFn: - value_param = param(a, qualified_type_helper(t, false), "value"); + value_param = param(a, shd_as_qualified_type(t, false), "value"); params = shd_nodes_append(a, params, value_param); break; } @@ -120,7 +120,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo if (!allowed(ctx, generic_ptr_tags[tag])) { Node* tag_case = case_(a, shd_empty(a)); set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(tag_case) })); - jumps[tag] = jump_helper(a, tag_case, shd_empty(a), get_abstraction_mem(r.case_)); + jumps[tag] = jump_helper(a, get_abstraction_mem(r.case_), tag_case, shd_empty(a)); continue; } Node* tag_case = case_(a, shd_empty(a)); @@ -128,7 +128,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_singleton(loaded_value))); - jumps[tag] = jump_helper(a, tag_case, shd_empty(a), get_abstraction_mem(r.case_)); + jumps[tag] = jump_helper(a, get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); @@ -140,7 +140,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo .switch_value = extracted_tag, .case_values = shd_nodes(a, max_tag, literals), .case_jumps = shd_nodes(a, max_tag, jumps), - .default_jump = jump_helper(a, default_case, shd_empty(a), get_abstraction_mem(r.case_)) + .default_jump = jump_helper(a, get_abstraction_mem(r.case_), default_case, shd_empty(a)) })); set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_singleton(final_loaded_value), .mem = bb_mem(bb) }))); break; @@ -157,7 +157,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo if (!allowed(ctx, generic_ptr_tags[tag])) { Node* tag_case = case_(a, shd_empty(a)); set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(tag_case) })); - jumps[tag] = jump_helper(a, tag_case, shd_empty(a), get_abstraction_mem(r.case_)); + jumps[tag] = jump_helper(a, get_abstraction_mem(r.case_), tag_case, shd_empty(a)); continue; } Node* tag_case = case_(a, shd_empty(a)); @@ -165,7 +165,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_empty(a))); - jumps[tag] = jump_helper(a, tag_case, shd_empty(a), get_abstraction_mem(r.case_)); + jumps[tag] = jump_helper(a, get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); @@ -177,7 +177,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo .switch_value = extracted_tag, .case_values = shd_nodes(a, max_tag, literals), .case_jumps = shd_nodes(a, max_tag, jumps), - .default_jump = jump_helper(a, default_case, shd_empty(a), get_abstraction_mem(r.case_)) + .default_jump = jump_helper(a, get_abstraction_mem(r.case_), default_case, shd_empty(a)) })); set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); break; diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index af31c9bc2..116ecb895 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -68,8 +68,8 @@ static const Node* process(Context* ctx, const Node* old) { set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { .mem = bb_mem(loop_bb), .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), - .true_jump = jump_helper(a, true_case, shd_empty(a), bb_mem(loop_bb)), - .false_jump = jump_helper(a, false_case, shd_empty(a), bb_mem(loop_bb)), + .true_jump = jump_helper(a, bb_mem(loop_bb), true_case, shd_empty(a)), + .false_jump = jump_helper(a, bb_mem(loop_bb), false_case, shd_empty(a)), }))); return yield_values_and_wrap_in_block(bb, shd_empty(a)); @@ -114,8 +114,8 @@ static const Node* process(Context* ctx, const Node* old) { set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { .mem = bb_mem(loop_bb), .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), - .true_jump = jump_helper(a, true_case, shd_empty(a), bb_mem(loop_bb)), - .false_jump = jump_helper(a, false_case, shd_empty(a), bb_mem(loop_bb)), + .true_jump = jump_helper(a, bb_mem(loop_bb), true_case, shd_empty(a)), + .false_jump = jump_helper(a, bb_mem(loop_bb), false_case, shd_empty(a)), }))); return yield_values_and_wrap_in_block(bb, shd_empty(a)); } diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 58165eb72..acb648021 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -107,7 +107,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod Module* m = ctx->rewriter.dst_module; const Node* t = get_unqualified_type(src->type); if (is_supported_natively(ctx, t)) - return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, qualified_type_helper(t, true), mk_nodes(a, scope, src)); + return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, shd_as_qualified_type(t, true), mk_nodes(a, scope, src)); if (resolve_to_int_literal(scope)->value != SpvScopeSubgroup) shd_error("TODO") @@ -117,9 +117,10 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod if (found) fn = *found; else { - const Node* src_param = param(a, qualified_type_helper(t, false), "src"); + const Node* src_param = param(a, shd_as_qualified_type(t, false), "src"); fn = function(m, shd_singleton(src_param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), - mk_nodes(a, annotation(a, (Annotation) { .name = "Generated"}), annotation(a, (Annotation) { .name = "Leaf" })), shd_singleton(qualified_type_helper(t, true))); + mk_nodes(a, annotation(a, (Annotation) { .name = "Generated"}), annotation(a, (Annotation) { .name = "Leaf" })), shd_singleton( + shd_as_qualified_type(t, true))); shd_dict_insert(const Node*, Node*, ctx->fns, t, fn); build_fn_body(ctx, fn, scope, src_param, t); } diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index d4847adf0..bd2d905db 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -29,7 +29,8 @@ static const Node* process(Context* ctx, const Node* node) { Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); - set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, post_prelude, shd_empty(a), bb_mem(functx.bb)))); + set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, + shd_empty(a)))); shd_destroy_dict(functx.rewriter.map); } return newfun; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index f91f02d79..ff3d3da1a 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -255,7 +255,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* new_jp_type = join_point_type(a, (JoinPointType) { .yield_types = rewrite_nodes(&ctx->rewriter, old_jp_type->payload.join_point_type.yield_types), }); - const Node* new_jp = param(a, qualified_type_helper(new_jp_type, true), old_jp->payload.param.name); + const Node* new_jp = param(a, shd_as_qualified_type(new_jp_type, true), old_jp->payload.param.name); register_processed(&ctx->rewriter, old_jp, new_jp); Node* new_control_case = case_(a, shd_singleton(new_jp)); register_processed(r, payload.inside, new_control_case); @@ -333,8 +333,8 @@ void generate_top_level_dispatch_fn(Context* ctx) { set_abstraction_body(c.case_, branch(a, (Branch) { .mem = get_abstraction_mem(c.case_), .condition = bail_condition, - .true_jump = jump_helper(a, bail_case, shd_empty(a), get_abstraction_mem(c.case_)), - .false_jump = jump_helper(a, proceed_case, shd_empty(a), get_abstraction_mem(c.case_)), + .true_jump = jump_helper(a, get_abstraction_mem(c.case_), bail_case, shd_empty(a)), + .false_jump = jump_helper(a, get_abstraction_mem(c.case_), proceed_case, shd_empty(a)), })); // gen_if(loop_body_builder, empty(a), bail_condition, bail_case, NULL); } @@ -363,13 +363,13 @@ void generate_top_level_dispatch_fn(Context* ctx) { set_abstraction_body(zero_case_lam, branch(a, (Branch) { .mem = get_abstraction_mem(zero_case_lam), .condition = should_run, - .true_jump = jump_helper(a, zero_if_true_lam, shd_empty(a), get_abstraction_mem(zero_case_lam)), - .false_jump = jump_helper(a, zero_if_false, shd_empty(a), get_abstraction_mem(zero_case_lam)), + .true_jump = jump_helper(a, get_abstraction_mem(zero_case_lam), zero_if_true_lam, shd_empty(a)), + .false_jump = jump_helper(a, get_abstraction_mem(zero_case_lam), zero_if_false, shd_empty(a)), })); const Node* zero_lit = shd_uint64_literal(a, 0); shd_list_append(const Node*, literals, zero_lit); - const Node* zero_jump = jump_helper(a, zero_case_lam, shd_empty(a), bb_mem(loop_body_builder)); + const Node* zero_jump = jump_helper(a, bb_mem(loop_body_builder), zero_case_lam, shd_empty(a)); shd_list_append(const Node*, jumps, zero_jump); Nodes old_decls = get_module_declarations(ctx->rewriter.src_module); @@ -401,12 +401,12 @@ void generate_top_level_dispatch_fn(Context* ctx) { set_abstraction_body(fn_case, branch(a, (Branch) { .mem = get_abstraction_mem(fn_case), .condition = should_run, - .true_jump = jump_helper(a, if_true_case, shd_empty(a), get_abstraction_mem(fn_case)), - .false_jump = jump_helper(a, if_false, shd_empty(a), get_abstraction_mem(fn_case)), + .true_jump = jump_helper(a, get_abstraction_mem(fn_case), if_true_case, shd_empty(a)), + .false_jump = jump_helper(a, get_abstraction_mem(fn_case), if_false, shd_empty(a)), })); shd_list_append(const Node*, literals, fn_lit); - const Node* j = jump_helper(a, fn_case, shd_empty(a), bb_mem(loop_body_builder)); + const Node* j = jump_helper(a, bb_mem(loop_body_builder), fn_case, shd_empty(a)); shd_list_append(const Node*, jumps, j); } } @@ -419,7 +419,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { .switch_value = next_function, .case_values = shd_nodes(a, shd_list_count(literals), shd_read_list(const Node*, literals)), .case_jumps = shd_nodes(a, shd_list_count(jumps), shd_read_list(const Node*, jumps)), - .default_jump = jump_helper(a, default_case, shd_empty(a), bb_mem(loop_body_builder)) + .default_jump = jump_helper(a, bb_mem(loop_body_builder), default_case, shd_empty(a)) }))); shd_destroy_list(literals); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 2c1fd49cc..a2fa807e5 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -83,7 +83,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* workgroup_id[3]; const Node* num_workgroups[3]; for (int dim = 0; dim < 3; dim++) { - workgroup_id[dim] = param(a, qualified_type_helper(shd_uint32_type(a), false), names[dim]); + workgroup_id[dim] = param(a, shd_as_qualified_type(shd_uint32_type(a), false), names[dim]); num_workgroups[dim] = gen_extract(bb, workgroup_num_vec3, shd_singleton(shd_uint32_literal(a, dim))); } @@ -98,7 +98,7 @@ static const Node* process(Context* ctx, const Node* node) { num_subgroups[2] = a->config.specializations.workgroup_size[2]; String names2[] = { "sgx", "sgy", "sgz" }; for (int dim = 0; dim < 3; dim++) { - subgroup_id[dim] = param(a, qualified_type_helper(shd_uint32_type(a), false), names2[dim]); + subgroup_id[dim] = param(a, shd_as_qualified_type(shd_uint32_type(a), false), names2[dim]); num_subgroups_literals[dim] = shd_uint32_literal(a, num_subgroups[dim]); } diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 37ed0cae7..ced25b059 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -176,7 +176,7 @@ static const Node* process(Context* ctx, const Node* node) { // Prepare a join point to replace the old function return Nodes nyield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); - const Node* join_point = param(a, qualified_type_helper(jp_type, true), shd_format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); + const Node* join_point = param(a, shd_as_qualified_type(jp_type, true), shd_format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); Node* control_case = case_(a, shd_singleton(join_point)); const Node* nbody = inline_call(ctx, ocallee, get_abstraction_mem(control_case), nargs, join_point); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 3ad91dd23..0e3978d3b 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -167,12 +167,13 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, // The exit ladder must exit that new loop set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) })); // After that we jump to the parent exit - return finish_body(bb, jump_helper(a, exit, shd_empty(a), bb_mem(bb))); + return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); } else { // Simply jmp to the exit once done - set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, exit, shd_empty(a), get_abstraction_mem(inner_exit_ladder_bb))); + set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, get_abstraction_mem(inner_exit_ladder_bb), exit, + shd_empty(a))); // Jump into the new structured target - return finish_body(bb, jump_helper(a, structured_target, rewrite_nodes(&ctx->rewriter, oargs), bb_mem(bb))); + return finish_body(bb, jump_helper(a, bb_mem(bb), structured_target, rewrite_nodes(&ctx->rewriter, oargs))); } } } @@ -215,7 +216,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_if(bb, shd_empty(a), condition, true_case, false_case); - return finish_body(bb, jump_helper(a, exit, shd_empty(a), bb_mem(bb))); + return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); } case Switch_TAG: { Switch payload = body->payload.br_switch; @@ -233,7 +234,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); gen_match(bb, shd_empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), shd_nodes(a, body->payload.br_switch.case_jumps.count, (const Node**) cases), default_case); - return finish_body(bb, jump_helper(a, exit, shd_empty(a), bb_mem(bb))); + return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); } // let(control(body), tail) // var phi = undef; level = N+1; structurize[body, if (level == N+1, _ => tail(load(phi))); structured_exit_terminator] @@ -283,7 +284,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { register_processed(r, get_abstraction_mem(get_structured_construct_tail(body)), get_abstraction_mem(true_case)); set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); gen_if(bb_tail, shd_empty(a), guard, true_case, NULL); - set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, exit, shd_empty(a), bb_mem(bb_tail)))); + set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, bb_mem(bb_tail), exit, shd_empty(a)))); register_processed(r, get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); return finish_body(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); @@ -302,7 +303,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { gen_store(bb, control->phis[i], args.nodes[i]); } - return finish_body(bb, jump_helper(a, exit, shd_empty(a), bb_mem(bb))); + return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); } case Return_TAG: diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index ec73bf00e..31fc858b5 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -150,13 +150,14 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (exiting_nodes_count > 1) exit_destination_alloca = gen_stack_alloc(outer_bb, shd_int32_type(arena)); - const Node* join_token_exit = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { - .yield_types = shd_empty(arena) + const Node* join_token_exit = param(arena, shd_as_qualified_type(join_point_type(arena, (JoinPointType) { + .yield_types = shd_empty(arena) }), true), "jp_exit"); - const Node* join_token_continue = param(arena, qualified_type_helper(join_point_type(arena, (JoinPointType) { - .yield_types = inner_yield_types - }), true), "jp_continue"); + const Node* join_token_continue = param(arena, + shd_as_qualified_type(join_point_type(arena, (JoinPointType) { + .yield_types = inner_yield_types + }), true), "jp_continue"); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; @@ -272,7 +273,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { exit_numbers[i] = shd_int32_literal(arena, i); set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, shd_nodes(arena, exits[i].params_count, recovered_args))); - exit_jumps[i] = jump_helper(arena, exit_bb, shd_empty(arena), bb_mem(outer_bb)); + exit_jumps[i] = jump_helper(arena, bb_mem(outer_bb), exit_bb, shd_empty(arena)); } const Node* outer_body; @@ -427,7 +428,7 @@ static const Node* process_node(Context* ctx, const Node* node) { exit_args = shd_nodes(a, old_params.count, inner_args); } - const Node* join_token = param(a, qualified_type_helper(join_point_type(a, (JoinPointType) { + const Node* join_token = param(a, shd_as_qualified_type(join_point_type(a, (JoinPointType) { .yield_types = yield_types }), true), "jp_postdom"); @@ -451,8 +452,12 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* inner_terminator = branch(a, (Branch) { .mem = get_abstraction_mem(control_case), .condition = rewrite_node(r, payload.condition), - .true_jump = jump_helper(a, rewrite_node(r, payload.true_jump->payload.jump.target), rewrite_nodes(r, payload.true_jump->payload.jump.args), get_abstraction_mem(control_case)), - .false_jump = jump_helper(a, rewrite_node(r, payload.false_jump->payload.jump.target), rewrite_nodes(r, payload.false_jump->payload.jump.args), get_abstraction_mem(control_case)), + .true_jump = jump_helper(a, get_abstraction_mem(control_case), + rewrite_node(r, payload.true_jump->payload.jump.target), + rewrite_nodes(r, payload.true_jump->payload.jump.args)), + .false_jump = jump_helper(a, get_abstraction_mem(control_case), + rewrite_node(r, payload.false_jump->payload.jump.target), + rewrite_nodes(r, payload.false_jump->payload.jump.args)), }); set_abstraction_body(control_case, inner_terminator); diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index 5e080a7dc..9e36bdb67 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -18,8 +18,10 @@ static const Node* process(Context* ctx, const Node* node) { case Jump_TAG: { Jump payload = node->payload.jump; Node* new_block = basic_block(a, shd_empty(a), NULL); - set_abstraction_body(new_block, jump_helper(a, rewrite_node(r, payload.target), rewrite_nodes(r, payload.args), get_abstraction_mem(new_block))); - return jump_helper(a, new_block, shd_empty(a), rewrite_node(r, payload.mem)); + set_abstraction_body(new_block, jump_helper(a, get_abstraction_mem(new_block), + rewrite_node(r, payload.target), + rewrite_nodes(r, payload.args))); + return jump_helper(a, rewrite_node(r, payload.mem), new_block, shd_empty(a)); } default: break; } diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 4a2f33b84..ea688bfe2 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -53,7 +53,7 @@ static Nodes remake_params(Context* ctx, Nodes old) { if (node->payload.param.type->tag == QualifiedType_TAG) t = rewrite_node(r, node->payload.param.type); else - t = qualified_type_helper(rewrite_node(r, node->payload.param.type), false); + t = shd_as_qualified_type(rewrite_node(r, node->payload.param.type), false); } nvars[i] = param(a, t, node->payload.param.name); assert(nvars[i]->tag == Param_TAG); @@ -114,7 +114,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab while(shd_dict_iter(controls->control_destinations, &i, NULL, &add_control)) { const Node* dst = add_control.destination; Node* control_case = case_(a, shd_singleton(add_control.token)); - set_abstraction_body(control_case, jump_helper(a, c, shd_empty(a), get_abstraction_mem(control_case))); + set_abstraction_body(control_case, jump_helper(a, get_abstraction_mem(control_case), c, shd_empty(a))); Node* c2 = case_(a, shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); @@ -130,10 +130,10 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab } c = c2; - set_abstraction_body(c2, finish_body(bb, jump_helper(a, find_processed(r, dst), results, bb_mem(bb)))); + set_abstraction_body(c2, finish_body(bb, jump_helper(a, bb_mem(bb), find_processed(r, dst), results))); } - const Node* body = jump_helper(a, c, shd_empty(a), get_abstraction_mem(nabs)); + const Node* body = jump_helper(a, get_abstraction_mem(nabs), c, shd_empty(a)); set_abstraction_body(nabs, body); } @@ -225,7 +225,7 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }); - const Node* join_token = param(a, qualified_type_helper(jp_type, false), get_abstraction_name_unsafe(dst)); + const Node* join_token = param(a, shd_as_qualified_type(jp_type, false), get_abstraction_name_unsafe(dst)); Node* wrapper = basic_block(a, wrapper_params, shd_format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); wrapper->payload.basic_block.body = join(a, (Join) { @@ -290,7 +290,8 @@ static const Node* process_node(Context* ctx, const Node* node) { case Jump_TAG: { Wrapped* found = shd_dict_find_value(const Node*, Wrapped, ctx->jump2wrapper, node); if (found) - return jump_helper(a, found->wrapper, rewrite_nodes(r, node->payload.jump.args), rewrite_node(r, node->payload.jump.mem)); + return jump_helper(a, rewrite_node(r, node->payload.jump.mem), found->wrapper, + rewrite_nodes(r, node->payload.jump.args)); break; } default: break; diff --git a/src/shady/type.c b/src/shady/type.c index a09577b36..da8abf6c9 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -440,7 +440,7 @@ const Type* check_type_string_lit(IrArena* arena, StringLiteral str_lit) { const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { assert(is_data_type(payload.ptr_type) && payload.ptr_type->tag == PtrType_TAG); - return qualified_type_helper(payload.ptr_type, true); + return shd_as_qualified_type(payload.ptr_type, true); } const Type* check_type_composite(IrArena* arena, Composite composite) { @@ -565,7 +565,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(first_operand_type->tag == Int_TAG); assert(second_operand_type->tag == Int_TAG); - return qualified_type_helper(maybe_packed_type_helper(first_operand_type, value_simd_width), uniform_result); + return shd_as_qualified_type(maybe_packed_type_helper(first_operand_type, value_simd_width), uniform_result); } case add_carry_op: case sub_borrow_op: @@ -598,7 +598,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { // TODO: assert unsigned result_t = record_type(arena, (RecordType) {.members = mk_nodes(arena, result_t, result_t)}); } - return qualified_type_helper(result_t, result_uniform); + return shd_as_qualified_type(result_t, result_uniform); } case not_op: { @@ -628,7 +628,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { result_uniform &= operand_uniform; } - return qualified_type_helper(first_operand_type, result_uniform); + return shd_as_qualified_type(first_operand_type, result_uniform); } case lt_op: case lte_op: @@ -653,7 +653,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { result_uniform &= operand_uniform; } - return qualified_type_helper(maybe_packed_type_helper(bool_type(arena), first_operand_width), result_uniform); + return shd_as_qualified_type(maybe_packed_type_helper(bool_type(arena), first_operand_width), + result_uniform); } case sqrt_op: case inv_sqrt_op: @@ -671,7 +672,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { bool uniform = deconstruct_qualified_type(&src_type); size_t width = deconstruct_maybe_packed_type(&src_type); assert(src_type->tag == Float_TAG); - return qualified_type_helper(maybe_packed_type_helper(src_type, width), uniform); + return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); } case pow_op: { assert(prim_op.type_arguments.count == 0); @@ -690,7 +691,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { result_uniform &= operand_uniform; } - return qualified_type_helper(first_operand_type, result_uniform); + return shd_as_qualified_type(first_operand_type, result_uniform); } case fma_op: { assert(prim_op.type_arguments.count == 0); @@ -709,7 +710,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { result_uniform &= operand_uniform; } - return qualified_type_helper(first_operand_type, result_uniform); + return shd_as_qualified_type(first_operand_type, result_uniform); } case abs_op: case sign_op: @@ -720,7 +721,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { bool uniform = deconstruct_qualified_type(&src_type); size_t width = deconstruct_maybe_packed_type(&src_type); assert(src_type->tag == Float_TAG || src_type->tag == Int_TAG && src_type->payload.int_type.is_signed); - return qualified_type_helper(maybe_packed_type_helper(src_type, width), uniform); + return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); } case align_of_op: case size_of_op: { @@ -762,7 +763,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { // todo find true supertype assert(are_types_identical(2, alternatives_types)); - return qualified_type_helper(maybe_packed_type_helper(alternatives_types[0], width), alternatives_all_uniform && condition_uniform); + return shd_as_qualified_type(maybe_packed_type_helper(alternatives_types[0], width), + alternatives_all_uniform && condition_uniform); } case insert_op: case extract_dynamic_op: @@ -789,7 +791,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { }); } - return qualified_type_helper(t, uniform); + return shd_as_qualified_type(t, uniform); } case shuffle_op: { assert(prim_op.operands.count >= 2); @@ -813,7 +815,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { int64_t index = get_int_literal_value(*resolve_to_int_literal(indices[i]), true); assert(index < 0 /* poison */ || (index >= 0 && index < total_size && "shuffle element out of range")); } - return qualified_type_helper(pack_type(arena, (PackType) { .element_type = element_t, .width = indices_count }), u); + return shd_as_qualified_type( + pack_type(arena, (PackType) {.element_type = element_t, .width = indices_count}), u); } case reinterpret_op: { assert(prim_op.type_arguments.count == 1); @@ -851,7 +854,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { // Mask management case empty_mask_op: { assert(prim_op.type_arguments.count == 0 && prim_op.operands.count == 0); - return qualified_type_helper(get_actual_mask_type(arena), true); + return shd_as_qualified_type(get_actual_mask_type(arena), true); } case mask_is_thread_active_op: { assert(prim_op.type_arguments.count == 0); @@ -1023,7 +1026,8 @@ const Type* check_type_load(IrArena* a, Load load) { const PtrType* node_ptr_type_ = &ptr_type->payload.ptr_type; const Type* elem_type = node_ptr_type_->pointed_type; elem_type = maybe_packed_type_helper(elem_type, width); - return qualified_type_helper(elem_type, ptr_uniform && is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); + return shd_as_qualified_type(elem_type, + ptr_uniform && is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); } const Type* check_type_store(IrArena* a, Store store) { @@ -1122,12 +1126,12 @@ const Type* check_type_push_stack(IrArena* a, PushStack payload) { } const Type* check_type_pop_stack(IrArena* a, PopStack payload) { - return qualified_type_helper(payload.type, false); + return shd_as_qualified_type(payload.type, false); } const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { assert(get_unqualified_type(payload.value->type) == shd_uint32_type(a)); - return qualified_type_helper(unit_type(a), true); + return shd_as_qualified_type(unit_type(a), true); } const Type* check_type_get_stack_size(IrArena* a, SHADY_UNUSED GetStackSize ss) { diff --git a/src/shady/type.h b/src/shady/type.h index aeeb81a65..9cea7d5f7 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -51,7 +51,7 @@ const Type* get_unqualified_type(const Type*); bool is_qualified_type_uniform(const Type*); bool deconstruct_qualified_type(const Type**); -const Type* qualified_type_helper(const Type*, bool uniform); +const Type* shd_as_qualified_type(const Type* type, bool uniform); Nodes strip_qualifiers(IrArena*, Nodes); Nodes add_qualifiers(IrArena*, Nodes, bool); diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 0cefbaa4b..1c932394e 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -143,7 +143,7 @@ bool deconstruct_qualified_type(const Type** type_out) { } else shd_error("Expected a value type (annotated with qual_type)") } -const Type* qualified_type_helper(const Type* type, bool uniform) { +const Type* shd_as_qualified_type(const Type* type, bool uniform) { return qualified_type(type->arena, (QualifiedType) { .type = type, .is_uniform = uniform }); } @@ -157,7 +157,8 @@ Nodes strip_qualifiers(IrArena* arena, Nodes tys) { Nodes add_qualifiers(IrArena* arena, Nodes tys, bool uniform) { LARRAY(const Type*, arr, tys.count); for (size_t i = 0; i < tys.count; i++) - arr[i] = qualified_type_helper(tys.nodes[i], uniform || !arena->config.is_simt /* SIMD arenas ban varying value types */); + arr[i] = shd_as_qualified_type(tys.nodes[i], + uniform || !arena->config.is_simt /* SIMD arenas ban varying value types */); return shd_nodes(arena, tys.count, arr); } diff --git a/test/test_builder.c b/test/test_builder.c index 9232b9cf0..cdfee4b7d 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -25,16 +25,16 @@ static void test_body_builder_constants(IrArena* a) { static void test_body_builder_fun_body(IrArena* a) { Module* m = new_module(a, "test_module"); - const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { - .address_space = AsGeneric, - .pointed_type = shd_uint32_type(a), + const Node* p1 = param(a, shd_as_qualified_type(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = shd_uint32_type(a), }), false), NULL); - const Node* p2 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { - .address_space = AsGeneric, - .pointed_type = shd_uint32_type(a), + const Node* p2 = param(a, shd_as_qualified_type(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = shd_uint32_type(a), }), false), NULL); - // const Node* p3 = param(a, qualified_type_helper(bool_type(a), false), NULL); - // const Node* p4 = param(a, qualified_type_helper(uint32_type(a), false), NULL); + // const Node* p3 = param(a, shd_as_qualified_type(bool_type(a), false), NULL); + // const Node* p4 = param(a, shd_as_qualified_type(uint32_type(a), false), NULL); Node* fun = function(m, mk_nodes(a, p1, p2), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); @@ -87,9 +87,9 @@ static void test_body_builder_fun_body(IrArena* a) { /// where there is only a mem dependency. This is useful when writing some complex polyfills. static void test_body_builder_impure_block(IrArena* a) { Module* m = new_module(a, "test_module"); - const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { - .address_space = AsGeneric, - .pointed_type = shd_uint32_type(a), + const Node* p1 = param(a, shd_as_qualified_type(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = shd_uint32_type(a), }), false), NULL); Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); @@ -126,9 +126,9 @@ static void test_body_builder_impure_block(IrArena* a) { /// where there is only a mem dependency. This is useful when writing some complex polyfills. static void test_body_builder_impure_block_with_control_flow(IrArena* a) { Module* m = new_module(a, "test_module"); - const Node* p1 = param(a, qualified_type_helper(ptr_type(a, (PtrType) { - .address_space = AsGeneric, - .pointed_type = shd_uint32_type(a), + const Node* p1 = param(a, shd_as_qualified_type(ptr_type(a, (PtrType) { + .address_space = AsGeneric, + .pointed_type = shd_uint32_type(a), }), false), NULL); Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); From cd997ef2f4f2abef115527e1db86896d829b0ae2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 13:25:05 +0200 Subject: [PATCH 615/693] added shd_ prefix to ir.c --- include/shady/ir.h | 10 ++-- samples/checkerboard/checkerboard.c | 4 +- src/backend/c/emit_c.c | 10 ++-- src/backend/c/emit_c_type.c | 4 +- src/backend/c/emit_c_value.c | 4 +- src/backend/spirv/emit_spv.c | 8 ++-- src/backend/spirv/spirv_builder.c | 6 +-- src/backend/spirv/spirv_lift_globals_ssbo.c | 4 +- src/backend/spirv/spirv_map_entrypoint_args.c | 4 +- src/driver/driver.c | 4 +- src/driver/slim.c | 4 +- src/frontend/llvm/l2s.c | 8 ++-- src/frontend/llvm/l2s_postprocess.c | 2 +- src/frontend/slim/bind.c | 4 +- src/frontend/slim/infer.c | 4 +- src/frontend/slim/normalize.c | 4 +- src/frontend/slim/slim_driver.c | 4 +- src/frontend/spirv/s2s.c | 2 +- src/runtime/runtime_program.c | 2 +- src/runtime/runtime_test.c | 4 +- src/runtime/vulkan/vk_runtime_device.c | 6 +-- src/runtime/vulkan/vk_runtime_program.c | 2 +- src/shady/compile.c | 6 +-- src/shady/constructors.c | 8 ++-- src/shady/generator_constructors.c | 2 +- src/shady/ir.c | 48 +++++++++---------- src/shady/ir_private.h | 4 +- src/shady/node.c | 4 +- src/shady/passes/cleanup.c | 2 +- src/shady/passes/eliminate_constants.c | 4 +- src/shady/passes/import.c | 4 +- src/shady/passes/lcssa.c | 4 +- src/shady/passes/lift_everything.c | 4 +- src/shady/passes/lift_indirect_targets.c | 10 ++-- src/shady/passes/lower_alloca.c | 4 +- src/shady/passes/lower_callf.c | 4 +- src/shady/passes/lower_cf_instrs.c | 4 +- src/shady/passes/lower_decay_ptrs.c | 4 +- src/shady/passes/lower_entrypoint_args.c | 4 +- src/shady/passes/lower_fill.c | 4 +- src/shady/passes/lower_generic_globals.c | 4 +- src/shady/passes/lower_generic_ptrs.c | 14 +++--- src/shady/passes/lower_int64.c | 4 +- src/shady/passes/lower_lea.c | 4 +- src/shady/passes/lower_logical_pointers.c | 10 ++-- src/shady/passes/lower_mask.c | 4 +- src/shady/passes/lower_memcpy.c | 4 +- src/shady/passes/lower_memory_layout.c | 4 +- src/shady/passes/lower_nullptr.c | 6 +-- src/shady/passes/lower_physical_ptrs.c | 10 ++-- src/shady/passes/lower_stack.c | 4 +- src/shady/passes/lower_subgroup_ops.c | 6 +-- src/shady/passes/lower_subgroup_vars.c | 4 +- src/shady/passes/lower_switch_btree.c | 4 +- src/shady/passes/lower_tailcalls.c | 4 +- src/shady/passes/lower_vec_arr.c | 4 +- src/shady/passes/lower_workgroups.c | 4 +- src/shady/passes/mark_leaf_functions.c | 4 +- src/shady/passes/normalize_builtins.c | 4 +- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_inline.c | 4 +- src/shady/passes/opt_restructure.c | 4 +- src/shady/passes/reconvergence_heuristics.c | 4 +- src/shady/passes/remove_critical_edges.c | 4 +- src/shady/passes/scope2control.c | 8 ++-- src/shady/passes/scope_heuristic.c | 4 +- src/shady/passes/setup_stack_frames.c | 4 +- src/shady/passes/specialize_entry_point.c | 4 +- src/shady/passes/specialize_execution_model.c | 4 +- src/shady/print.c | 4 +- src/shady/rewrite.h | 2 +- test/opt/opt_oracle.c | 6 +-- test/test_builder.c | 4 +- test/test_math.c | 4 +- vcc/vcc.c | 6 +-- 75 files changed, 199 insertions(+), 199 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index 84715a009..b03a0ea2a 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -42,7 +42,7 @@ bool shd_find_in_nodes(Nodes nodes, const Node* n); String string_sized(IrArena*, size_t size, const char* start); String string(IrArena*, const char*); // see also: format_string in util.h -String format_string_interned(IrArena*, const char* str, ...); +String shd_fmt_string_irarena(IrArena* arena, const char* str, ...); String unique_name(IrArena*, const char* base_name); String name_type_safe(IrArena*, const Type*); @@ -152,10 +152,10 @@ inline static bool is_function(const Node* node) { return node->tag == Function_ /// See config.h for definition of ArenaConfig typedef struct ArenaConfig_ ArenaConfig; -IrArena* new_ir_arena(const ArenaConfig*); -void destroy_ir_arena(IrArena*); -const ArenaConfig* get_arena_config(const IrArena*); -const Node* get_node_by_id(const IrArena*, NodeId); +IrArena* shd_new_ir_arena(const ArenaConfig* config); +void shd_destroy_ir_arena(IrArena* arena); +const ArenaConfig* shd_get_arena_config(const IrArena* a); +const Node* shd_get_node_by_id(const IrArena* a, NodeId id); //////////////////////////////// Getters //////////////////////////////// diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 47f753851..53e46e61a 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -66,7 +66,7 @@ int main(int argc, char **argv) shd_info_print("Device-side address is: %zu\n", buf_addr); ArenaConfig aconfig = shd_default_arena_config(&compiler_config.target); - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* m; if (shd_driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, "checkerboard", &m) != NoError) @@ -82,6 +82,6 @@ int main(int argc, char **argv) shutdown_runtime(runtime); saveppm("checkerboard.ppm", WIDTH, HEIGHT, img); - destroy_ir_arena(a); + shd_destroy_ir_arena(a); free(img); } diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 56c326e16..b008956f3 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -274,7 +274,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { if (ass == AsOutput && emitter->compiler_config->specialization.execution_model == EmFragment) { int location = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(lookup_annotation(decl, "Location"))), false); - CTerm t = term_from_cvar(format_string_interned(emitter->arena, "gl_FragData[%d]", location)); + CTerm t = term_from_cvar(shd_fmt_string_irarena(emitter->arena, "gl_FragData[%d]", location)); register_emitted(emitter, NULL, decl, t); return; } @@ -288,9 +288,9 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { // HACK return; } - emit_as = term_from_cvar(format_string_interned(emitter->arena, "__shady_thread_local_access(%s)", name)); + emit_as = term_from_cvar(shd_fmt_string_irarena(emitter->arena, "__shady_thread_local_access(%s)", name)); if (init) - init = format_string_interned(emitter->arena, "__shady_replicate_thread_local(%s)", init); + init = shd_fmt_string_irarena(emitter->arena, "__shady_replicate_thread_local(%s)", init); register_emitted(emitter, NULL, decl, emit_as); } register_emitted(emitter, NULL, decl, emit_as); @@ -317,7 +317,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { for (size_t i = 0; i < decl->payload.fun.params.count; i++) { String param_name; String variable_name = get_value_name_unsafe(decl->payload.fun.params.nodes[i]); - param_name = format_string_interned(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); + param_name = shd_fmt_string_irarena(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); register_emitted(emitter, &fn, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } @@ -535,5 +535,5 @@ void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Mo if (new_mod) *new_mod = mod; else if (initial_arena != arena) - destroy_ir_arena(arena); + shd_destroy_ir_arena(arena); } diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index 450acc61e..93486c48a 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -18,7 +18,7 @@ String c_get_record_field_name(const Type* t, size_t i) { RecordType r = t->payload.record_type; assert(i < r.members.count); if (i >= r.names.count) - return format_string_interned(t->arena, "_%d", i); + return shd_fmt_string_irarena(t->arena, "_%d", i); else return r.names.strings[i]; } @@ -66,7 +66,7 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons for (size_t i = 0; i < dom.count; i++) { String param_name; String variable_name = get_value_name_unsafe(fn->payload.fun.params.nodes[i]); - param_name = format_string_interned(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); + param_name = shd_fmt_string_irarena(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); shd_print(paramp, c_emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { shd_print(paramp, ", "); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 1642845db..7fdf98474 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -434,7 +434,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node assert(node->tag == PrimOp_TAG); IrArena* arena = emitter->arena; const PrimOp* prim_op = &node->payload.prim_op; - CTerm term = term_from_cvalue(format_string_interned(emitter->arena, "/* todo %s */", get_primop_name(prim_op->op))); + CTerm term = term_from_cvalue(shd_fmt_string_irarena(emitter->arena, "/* todo %s */", get_primop_name(prim_op->op))); const ISelTableEntry* isel_entry = lookup_entry(emitter, prim_op->op); switch (prim_op->op) { case add_carry_op: @@ -955,7 +955,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case Instruction_DebugPrintf_TAG: { DebugPrintf payload = instruction->payload.debug_printf; c_emit_mem(emitter, fn, payload.mem); - String args_list = format_string_interned(emitter->arena, "\"%s\"", instruction->payload.debug_printf.string); + String args_list = shd_fmt_string_irarena(emitter->arena, "\"%s\"", instruction->payload.debug_printf.string); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) { CValue str = to_cvalue(emitter, c_emit_value(emitter, fn, instruction->payload.debug_printf.args.nodes[i])); diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 013f2e736..bbf21e8c2 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -22,8 +22,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); -KeyHash hash_string(const char** string); -bool compare_string(const char** a, const char** b); +KeyHash shd_hash_string(const char** string); +bool shd_compare_string(const char** a, const char** b); #pragma GCC diagnostic error "-Wswitch" @@ -346,7 +346,7 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, .num_entry_pts = 0, }; - emitter.extended_instruction_sets = shd_new_dict(const char*, SpvId, (HashFn) hash_string, (CmpFn) compare_string); + emitter.extended_instruction_sets = shd_new_dict(const char*, SpvId, (HashFn) shd_hash_string, (CmpFn) shd_compare_string); emitter.void_t = spvb_void_type(emitter.file_builder); @@ -371,5 +371,5 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, if (new_mod) *new_mod = mod; else if (initial_arena != arena) - destroy_ir_arena(arena); + shd_destroy_ir_arena(arena); } diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index ad76d85e2..3ec44de31 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -96,8 +96,8 @@ struct SpvbFileBuilder_ { static KeyHash hash_u32(uint32_t* p) { return shd_hash_murmur(p, sizeof(uint32_t)); } static bool compare_u32s(uint32_t* a, uint32_t* b) { return *a == *b; } -KeyHash hash_string(const char** string); -bool compare_string(const char** a, const char** b); +KeyHash shd_hash_string(const char** string); +bool shd_compare_string(const char** a, const char** b); SpvbFileBuilder* spvb_begin() { SpvbFileBuilder* file_builder = (SpvbFileBuilder*) malloc(sizeof(SpvbFileBuilder)); @@ -117,7 +117,7 @@ SpvbFileBuilder* spvb_begin() { .fn_defs = shd_new_growy(), .capabilities_set = shd_new_set(SpvCapability, (HashFn) hash_u32, (CmpFn) compare_u32s), - .extensions_set = shd_new_set(const char*, (HashFn) hash_string, (CmpFn) compare_string), + .extensions_set = shd_new_set(const char*, (HashFn) shd_hash_string, (CmpFn) shd_compare_string), .memory_model = SpvMemoryModelGLSL450, }; diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 4fc715413..352468fb3 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -63,8 +63,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index 55c5acaa3..56eebfa95 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -58,8 +58,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* spirv_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/driver/driver.c b/src/driver/driver.c index 1b4dae8a4..60fcfe14f 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -108,7 +108,7 @@ ShadyErrorCodes shd_driver_load_source_files(DriverConfig* args, Module* mod) { if (err) return err; link_module(mod, m); - destroy_ir_arena(get_module_arena(m)); + shd_destroy_ir_arena(get_module_arena(m)); } return NoError; @@ -181,6 +181,6 @@ ShadyErrorCodes shd_driver_compile(DriverConfig* args, Module* mod) { free((void*) output_buffer); fclose(f); } - destroy_ir_arena(get_module_arena(mod)); + shd_destroy_ir_arena(get_module_arena(mod)); return NoError; } diff --git a/src/driver/slim.c b/src/driver/slim.c index a71afbcea..a18b1d6f9 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -16,7 +16,7 @@ int main(int argc, char** argv) { shd_driver_parse_input_files(args.input_filenames, &argc, argv); ArenaConfig aconfig = shd_default_arena_config(&args.config.target); - IrArena* arena = new_ir_arena(&aconfig); + IrArena* arena = shd_new_ir_arena(&aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one ShadyErrorCodes err = shd_driver_load_source_files(&args, mod); @@ -28,6 +28,6 @@ int main(int argc, char** argv) { exit(err); shd_info_print("Compilation successful\n"); - destroy_ir_arena(arena); + shd_destroy_ir_arena(arena); shd_destroy_driver_config(&args); } diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index d8a08b797..28cbd9ad4 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -267,7 +267,7 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { decl->payload.global_variable.init = convert_value(p, value); if (UNTYPED_POINTERS) { - Node* untyped_wrapper = constant(p->dst, shd_singleton(annotation(a, (Annotation) { .name = "Inline" })), ptr_t, format_string_interned(a, "%s_untyped", name)); + Node* untyped_wrapper = constant(p->dst, shd_singleton(annotation(a, (Annotation) { .name = "Inline" })), ptr_t, shd_fmt_string_irarena(a, "%s_untyped", name)); untyped_wrapper->payload.constant.value = ref_decl_helper(a, decl); untyped_wrapper->payload.constant.value = prim_op_helper(a, reinterpret_op, shd_singleton(ptr_t), shd_singleton(ref_decl_helper(a, decl))); decl = untyped_wrapper; @@ -302,7 +302,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* aconfig.allow_fold = false; aconfig.optimisations.inline_single_use_bbs = false; - IrArena* arena = new_ir_arena(&aconfig); + IrArena* arena = shd_new_ir_arena(&aconfig); Module* dirty = new_module(arena, "dirty"); Parser p = { .ctx = context, @@ -334,13 +334,13 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* aconfig.check_types = true; aconfig.allow_fold = true; - IrArena* arena2 = new_ir_arena(&aconfig); + IrArena* arena2 = shd_new_ir_arena(&aconfig); *dst = new_module(arena2, name); postprocess(&p, dirty, *dst); shd_log_fmt(DEBUGVV, "Shady module parsed from LLVM, after cleanup:"); shd_log_module(DEBUGVV, config, *dst); verify_module(config, *dst); - destroy_ir_arena(arena); + shd_destroy_ir_arena(arena); shd_destroy_dict(p.map); shd_destroy_dict(p.annotations); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 33b01c1eb..eda711bd6 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -115,7 +115,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Type* pt = ptr_type(a, (PtrType) { .address_space = old_as, .pointed_type = type }); Node* c = constant(ctx->rewriter.dst_module, shd_singleton(annotation(a, (Annotation) { .name = "Inline" - })), pt, format_string_interned(a, "%s_proxy", get_declaration_name(decl))); + })), pt, shd_fmt_string_irarena(a, "%s_proxy", get_declaration_name(decl))); c->payload.constant.value = prim_op_helper(a, convert_op, shd_singleton(pt), shd_singleton( ref_decl_helper(a, decl))); result = c; diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 7fb15e047..6385497a7 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -367,10 +367,10 @@ static const Node* bind_node(Context* ctx, const Node* node) { } Module* slim_pass_bind(SHADY_UNUSED const CompilerConfig* compiler_config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); assert(!src->arena->config.name_bound); aconfig.name_bound = true; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 71d8e2aee..f2f5a59f9 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -605,11 +605,11 @@ static const Node* process(Context* src_ctx, const Node* node) { } Module* slim_pass_infer(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); assert(!aconfig.check_types); aconfig.check_types = true; aconfig.allow_fold = true; // TODO was moved here because a refactor, does this cause issues ? - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/frontend/slim/normalize.c b/src/frontend/slim/normalize.c index 24276ec12..6c5c1a2d6 100644 --- a/src/frontend/slim/normalize.c +++ b/src/frontend/slim/normalize.c @@ -111,9 +111,9 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* slim_pass_normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); aconfig.check_op_classes = true; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process_op), diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index d2da97fb7..2bd637903 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -23,7 +23,7 @@ Module* shd_parse_slim_module(const CompilerConfig* config, const SlimParserConf aconfig.check_types = false; aconfig.validate_builtin_types = false; aconfig.allow_fold = false; - IrArena* initial_arena = new_ir_arena(&aconfig); + IrArena* initial_arena = shd_new_ir_arena(&aconfig); Module* m = new_module(initial_arena, name); slim_parse_string(pconfig, contents, m); Module** pmod = &m; @@ -41,6 +41,6 @@ Module* shd_parse_slim_module(const CompilerConfig* config, const SlimParserConf RUN_PASS(slim_pass_infer) RUN_PASS(lower_cf_instrs) - destroy_ir_arena(initial_arena); + shd_destroy_ir_arena(initial_arena); return *pmod; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 7926fe642..133a76d08 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1344,7 +1344,7 @@ bool compare_spvid(SpvId* pa, SpvId* pb) { S2SError shd_parse_spirv(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { ArenaConfig aconfig = shd_default_arena_config(&config->target); - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); *dst = new_module(a, name); SpvParser parser = { diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index 78876e209..92e862580 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -54,6 +54,6 @@ Program* load_program_from_disk(Runtime* runtime, const CompilerConfig* base_con void unload_program(Program* program) { // TODO iterate over the specialized stuff if (program->arena) // if the program owns an arena - destroy_ir_arena(program->arena); + shd_destroy_ir_arena(program->arena); free(program); } diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 1aad6f6c2..1ca797c0e 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -49,7 +49,7 @@ int main(int argc, char* argv[]) { Program* program; IrArena* arena = NULL; ArenaConfig aconfig = shd_default_arena_config(&args.driver_config.config.target); - arena = new_ir_arena(&aconfig); + arena = shd_new_ir_arena(&aconfig); if (shd_list_count(args.driver_config.input_filenames) == 0) { Module* module; shd_driver_load_source_file(&args.driver_config.config, SrcSlim, strlen(default_shader), default_shader, @@ -76,7 +76,7 @@ int main(int argc, char* argv[]) { shutdown_runtime(runtime); if (arena) - destroy_ir_arena(arena); + shd_destroy_ir_arena(arena); shd_destroy_driver_config(&args.driver_config); return 0; } diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index 64f2e6d09..ebd75b2fb 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -208,11 +208,11 @@ static bool get_physical_device_caps(SHADY_UNUSED VkrBackend* runtime, VkPhysica return false; } -KeyHash hash_string(const char** string); -bool compare_string(const char** a, const char** b); +KeyHash shd_hash_string(const char** string); +bool shd_compare_string(const char** a, const char** b); static KeyHash hash_spec_program_key(SpecProgramKey* ptr) { - return shd_hash_murmur(ptr->base, sizeof(Program*)) ^ hash_string(&ptr->entry_point); + return shd_hash_murmur(ptr->base, sizeof(Program*)) ^ shd_hash_string(&ptr->entry_point); } static bool cmp_spec_program_keys(SpecProgramKey* a, SpecProgramKey* b) { diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index c4c6ffecf..f984d4209 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -515,7 +515,7 @@ void destroy_specialized_program(VkrSpecProgram* spec) { free( (void*) spec->parameters.arg_offset); free(spec->spirv_bytes); if (get_module_arena(spec->specialized_module) != get_module_arena(spec->key.base->module)) - destroy_ir_arena(get_module_arena(spec->specialized_module)); + shd_destroy_ir_arena(get_module_arena(spec->specialized_module)); for (size_t i = 0; i < spec->resources.num_resources; i++) { ProgramResourceInfo* resource = spec->resources.resources[i]; if (resource->buffer) diff --git a/src/shady/compile.c b/src/shady/compile.c index 75b1c56a6..457ef0793 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -21,7 +21,7 @@ static void add_scheduler_source(const CompilerConfig* config, Module* dst) { Module* builtin_scheduler_mod = shd_parse_slim_module(config, &pconfig, shady_scheduler_src, "builtin_scheduler"); shd_debug_print("Adding builtin scheduler code"); link_module(dst, builtin_scheduler_mod); - destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); + shd_destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); } #ifdef NDEBUG @@ -39,7 +39,7 @@ void shd_run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* ini if (SHADY_RUN_VERIFY) verify_module(config, *pmod); if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) - destroy_ir_arena(get_module_arena(old_mod)); + shd_destroy_ir_arena(get_module_arena(old_mod)); old_mod = *pmod; if (config->optimisations.cleanup.after_every_pass) *pmod = cleanup(config, *pmod); @@ -47,7 +47,7 @@ void shd_run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* ini if (SHADY_RUN_VERIFY) verify_module(config, *pmod); if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) - destroy_ir_arena(get_module_arena(old_mod)); + shd_destroy_ir_arena(get_module_arena(old_mod)); if (config->hooks.after_pass.fn) config->hooks.after_pass.fn(config->hooks.after_pass.uptr, pass_name, *pmod); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index 67d07988f..ab858d6d9 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -10,8 +10,8 @@ #include #include -Strings import_strings(IrArena*, Strings); -bool compare_nodes(Nodes* a, Nodes* b); +Strings _shd_import_strings(IrArena* dst_arena, Strings old_strings); +bool shd_compare_nodes(Nodes* a, Nodes* b); static void pre_construction_validation(IrArena* arena, Node* node); @@ -53,7 +53,7 @@ Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh) { // place the node in the arena and return it Node* alloc = (Node*) shd_arena_alloc(arena->arena, sizeof(Node)); *alloc = node; - alloc->id = allocate_node_id(arena, alloc); + alloc->id = _shd_allocate_node_id(arena, alloc); shd_set_insert_get_result(const Node*, arena->node_set, alloc); return alloc; @@ -175,7 +175,7 @@ Node* global_var(Module* mod, Nodes annotations, const Type* type, const char* n assert(existing->tag == GlobalVariable_TAG); assert(existing->payload.global_variable.type == type); assert(existing->payload.global_variable.address_space == as); - assert(!mod->arena->config.check_types || compare_nodes((Nodes*) &existing->payload.global_variable.annotations, &annotations)); + assert(!mod->arena->config.check_types || shd_compare_nodes((Nodes*) &existing->payload.global_variable.annotations, &annotations)); return (Node*) existing; } diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 81e5f1047..674649dbe 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -29,7 +29,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { if (!list) shd_growy_append_formatted(g, "\t\tnode->payload.%s.%s = string(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); else - shd_growy_append_formatted(g, "\t\tnode->payload.%s.%s = import_strings(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); + shd_growy_append_formatted(g, "\t\tnode->payload.%s.%s = _shd_import_strings(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); } else { String cap = capitalize(class); shd_growy_append_formatted(g, "\t\t{\n"); diff --git a/src/shady/ir.c b/src/shady/ir.c index 224db104b..92a0fa32a 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -10,19 +10,19 @@ #include #include -static KeyHash hash_nodes(Nodes* nodes); -bool compare_nodes(Nodes* a, Nodes* b); +static KeyHash shd_hash_nodes(Nodes* nodes); +bool shd_compare_nodes(Nodes* a, Nodes* b); -static KeyHash hash_strings(Strings* strings); -static bool compare_strings(Strings* a, Strings* b); +static KeyHash shd_hash_strings(Strings* strings); +static bool shd_compare_strings(Strings* a, Strings* b); -KeyHash hash_string(const char** string); -bool compare_string(const char** a, const char** b); +KeyHash shd_hash_string(const char** string); +bool shd_compare_string(const char** a, const char** b); KeyHash hash_node(const Node**); bool compare_node(const Node** a, const Node** b); -IrArena* new_ir_arena(const ArenaConfig* config) { +IrArena* shd_new_ir_arena(const ArenaConfig* config) { IrArena* arena = malloc(sizeof(IrArena)); *arena = (IrArena) { .arena = shd_new_arena(), @@ -31,21 +31,21 @@ IrArena* new_ir_arena(const ArenaConfig* config) { .modules = shd_new_list(Module*), .node_set = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .string_set = shd_new_set(const char*, (HashFn) hash_string, (CmpFn) compare_string), + .string_set = shd_new_set(const char*, (HashFn) shd_hash_string, (CmpFn) shd_compare_string), - .nodes_set = shd_new_set(Nodes, (HashFn) hash_nodes, (CmpFn) compare_nodes), - .strings_set = shd_new_set(Strings, (HashFn) hash_strings, (CmpFn) compare_strings), + .nodes_set = shd_new_set(Nodes, (HashFn) shd_hash_nodes, (CmpFn) shd_compare_nodes), + .strings_set = shd_new_set(Strings, (HashFn) shd_hash_strings, (CmpFn) shd_compare_strings), .ids = shd_new_growy(), }; return arena; } -const Node* get_node_by_id(const IrArena* a, NodeId id) { +const Node* shd_get_node_by_id(const IrArena* a, NodeId id) { return ((const Node**) shd_growy_data(a->ids))[id]; } -void destroy_ir_arena(IrArena* arena) { +void shd_destroy_ir_arena(IrArena* arena) { for (size_t i = 0; i < shd_list_count(arena->modules); i++) { destroy_module(shd_read_list(Module*, arena->modules)[i]); } @@ -60,11 +60,11 @@ void destroy_ir_arena(IrArena* arena) { free(arena); } -const ArenaConfig* get_arena_config(const IrArena* a) { +const ArenaConfig* shd_get_arena_config(const IrArena* a) { return &a->config; } -NodeId allocate_node_id(IrArena* arena, const Node* n) { +NodeId _shd_allocate_node_id(IrArena* arena, const Node* n) { shd_growy_append_object(arena->ids, n); return shd_growy_size(arena->ids) / sizeof(const Node*); } @@ -197,7 +197,7 @@ const char* string(IrArena* arena, const char* str) { } // TODO merge with strings() -Strings import_strings(IrArena* dst_arena, Strings old_strings) { +Strings _shd_import_strings(IrArena* dst_arena, Strings old_strings) { size_t count = old_strings.count; LARRAY(String, arr, count); for (size_t i = 0; i < count; i++) @@ -217,7 +217,7 @@ static void intern_in_arena(InternInArenaPayload* uptr, size_t len, char* tmp) { *uptr->result = interned; } -String format_string_interned(IrArena* arena, const char* str, ...) { +String shd_fmt_string_irarena(IrArena* arena, const char* str, ...) { String result = NULL; InternInArenaPayload p = { .a = arena, .result = &result }; va_list args; @@ -228,43 +228,43 @@ String format_string_interned(IrArena* arena, const char* str, ...) { } const char* unique_name(IrArena* arena, const char* str) { - return format_string_interned(arena, "%s_%d", str, allocate_node_id(arena, NULL)); + return shd_fmt_string_irarena(arena, "%s_%d", str, _shd_allocate_node_id(arena, NULL)); } -KeyHash hash_nodes(Nodes* nodes) { +KeyHash shd_hash_nodes(Nodes* nodes) { return shd_hash_murmur(nodes->nodes, sizeof(const Node*) * nodes->count); } -bool compare_nodes(Nodes* a, Nodes* b) { +bool shd_compare_nodes(Nodes* a, Nodes* b) { if (a->count != b->count) return false; if (a->count == 0) return true; assert(a->nodes != NULL && b->nodes != NULL); return memcmp(a->nodes, b->nodes, sizeof(Node*) * (a->count)) == 0; // actually compare the data } -KeyHash hash_strings(Strings* strings) { +KeyHash shd_hash_strings(Strings* strings) { return shd_hash_murmur(strings->strings, sizeof(char*) * strings->count); } -bool compare_strings(Strings* a, Strings* b) { +bool shd_compare_strings(Strings* a, Strings* b) { if (a->count != b->count) return false; if (a->count == 0) return true; assert(a->strings != NULL && b->strings != NULL); return memcmp(a->strings, b->strings, sizeof(const char*) * a->count) == 0; } -KeyHash hash_string(const char** string) { +KeyHash shd_hash_string(const char** string) { if (!*string) return 0; return shd_hash_murmur(*string, strlen(*string)); } -bool compare_string(const char** a, const char** b) { +bool shd_compare_string(const char** a, const char** b) { if (*a == NULL || *b == NULL) return (!*a) == (!*b); return strlen(*a) == strlen(*b) && strcmp(*a, *b) == 0; } -Nodes list_to_nodes(IrArena* arena, struct List* list) { +Nodes shd_list_to_nodes(IrArena* arena, struct List* list) { return shd_nodes(arena, shd_list_count(list), shd_read_list(const Node*, list)); } diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index 0c1e3dbcd..865989c56 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -43,9 +43,9 @@ struct BodyBuilder_ { Node* tail_block; }; -NodeId allocate_node_id(IrArena*, const Node* n); +NodeId _shd_allocate_node_id(IrArena* arena, const Node* n); struct List; -Nodes list_to_nodes(IrArena*, struct List*); +Nodes shd_list_to_nodes(IrArena* arena, struct List* list); #endif diff --git a/src/shady/node.c b/src/shady/node.c index 84aecfacd..af4d45a95 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -20,7 +20,7 @@ String get_value_name_safe(const Node* v) { if (name && strlen(name) > 0) return name; //if (v->tag == Variable_TAG) - return format_string_interned(v->arena, "%%%d", v->id); + return shd_fmt_string_irarena(v->arena, "%%%d", v->id); //return node_tags[v->tag]; } @@ -291,7 +291,7 @@ String get_abstraction_name_safe(const Node* abs) { String name = get_abstraction_name_unsafe(abs); if (name) return name; - return format_string_interned(abs->arena, "%%%d", abs->id); + return shd_fmt_string_irarena(abs->arena, "%%%d", abs->id); } const Node* finish_block_body(BodyBuilder* bb, const Node* terminator); diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index b8d775b85..771ec8925 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -137,7 +137,7 @@ OptPass opt_mem2reg; RewritePass import; Module* cleanup(const CompilerConfig* config, Module* const src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); if (!aconfig.check_types) return src; bool todo; diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 247c27939..bf625e31a 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -33,8 +33,8 @@ static const Node* process(Context* ctx, const Node* node) { } static Module* eliminate_constants_(SHADY_UNUSED const CompilerConfig* config, Module* src, bool all) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 36386510e..d63053fe8 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -61,8 +61,8 @@ const Node* import_node(Rewriter* r, const Node* node) { } Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) recreate_node_identity), diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index a4518038a..87b02b23f 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -189,8 +189,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lcssa(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index a00c99904..437ef63f4 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -100,8 +100,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); bool todo = true; Module* dst; while (todo) { diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 516b96e3b..a9931bf59 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -222,7 +222,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); IrArena* a = NULL; Module* dst; @@ -230,7 +230,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { while (true) { shd_debugv_print("lift_indirect_target: round %d\n", round++); IrArena* oa = a; - a = new_ir_arena(&aconfig); + a = shd_new_ir_arena(&aconfig); dst = new_module(a, get_module_name(src)); bool todo = false; Context ctx = { @@ -253,7 +253,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { verify_module(config, dst); src = dst; if (oa) - destroy_ir_arena(oa); + shd_destroy_ir_arena(oa); if (!todo) { break; } @@ -261,11 +261,11 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { // this will be safe now since we won't lift any more code after this pass aconfig.optimisations.weaken_non_leaking_allocas = true; - IrArena* a2 = new_ir_arena(&aconfig); + IrArena* a2 = shd_new_ir_arena(&aconfig); dst = new_module(a2, get_module_name(src)); Rewriter r = create_importer(src, dst); rewrite_module(&r); destroy_rewriter(&r); - destroy_ir_arena(a); + shd_destroy_ir_arena(a); return dst; } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 5b60dc2cf..c45613f12 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -164,8 +164,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 91883e52d..2a99ec3f0 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -147,8 +147,8 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { } Module* lower_callf(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) lower_callf_process), diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 40a247873..5c4a3577e 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -235,8 +235,8 @@ KeyHash hash_node(const Node**); bool compare_node(const Node**, const Node**); Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index 6abe1040f..548feea25 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -34,8 +34,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_decay_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 0db6f56e6..22561ba95 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -91,8 +91,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_entrypoint_args(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index 85c8884c8..79d5b7f06 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -32,8 +32,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 1c6d6acd9..30e921b2f 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -43,8 +43,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_generic_globals(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index ad496554c..1d9dce58d 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -81,8 +81,8 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo IrArena* a = ctx->rewriter.dst_arena; String name; switch (which) { - case LoadFn: name = format_string_interned(a, "generated_load_Generic_%s%s", name_type_safe(a, t), uniform_ptr ? "_uniform" : ""); break; - case StoreFn: name = format_string_interned(a, "generated_store_Generic_%s", name_type_safe(a, t)); break; + case LoadFn: name = shd_fmt_string_irarena(a, "generated_load_Generic_%s%s", name_type_safe(a, t), uniform_ptr ? "_uniform" : ""); break; + case StoreFn: name = shd_fmt_string_irarena(a, "generated_store_Generic_%s", name_type_safe(a, t)); break; } const Node** found = shd_dict_find_value(String, const Node*, ctx->fns, name); @@ -270,16 +270,16 @@ static const Node* process(Context* ctx, const Node* old) { return recreate_node_identity(&ctx->rewriter, old); } -KeyHash hash_string(const char** string); -bool compare_string(const char** a, const char** b); +KeyHash shd_hash_string(const char** string); +bool shd_compare_string(const char** a, const char** b); Module* lower_generic_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), - .fns = shd_new_dict(String, const Node*, (HashFn) hash_string, (CmpFn) compare_string), + .fns = shd_new_dict(String, const Node*, (HashFn) shd_hash_string, (CmpFn) shd_compare_string), .generic_ptr_type = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false}), .config = config, }; diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index b3a7c6b16..efa9339ee 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -80,8 +80,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_int(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index cc84294f2..9b82b76a5 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -166,8 +166,8 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_lea(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index e735cd3fa..4cac7349d 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -48,7 +48,7 @@ static const Node* process(Context* ctx, const Node* old) { switch (old->tag) { case PtrType_TAG: { PtrType payload = old->payload.ptr_type; - if (!get_arena_config(a)->address_spaces[payload.address_space].physical) + if (!shd_get_arena_config(a)->address_spaces[payload.address_space].physical) payload.is_reference = true; payload.pointed_type = rewrite_node(r, payload.pointed_type); return ptr_type(a, payload); @@ -87,7 +87,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* osrc = shd_first(payload.operands); const Type* osrc_t = osrc->type; deconstruct_qualified_type(&osrc_t); - if (osrc_t->tag == PtrType_TAG && !get_arena_config(a)->address_spaces[osrc_t->payload.ptr_type.address_space].physical) + if (osrc_t->tag == PtrType_TAG && !shd_get_arena_config(a)->address_spaces[osrc_t->payload.ptr_type.address_space].physical) return rewrite_node(r, osrc); break; } @@ -123,7 +123,7 @@ static const Node* process(Context* ctx, const Node* old) { } case GlobalVariable_TAG: { AddressSpace as = old->payload.global_variable.address_space; - if (get_arena_config(a)->address_spaces[as].physical) + if (shd_get_arena_config(a)->address_spaces[as].physical) break; Nodes annotations = rewrite_nodes(r, old->payload.global_variable.annotations); annotations = shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Logical" })); @@ -138,11 +138,11 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_logical_pointers(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); aconfig.address_spaces[AsInput].physical = false; aconfig.address_spaces[AsOutput].physical = false; aconfig.address_spaces[AsUniformConstant].physical = false; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 198a84f30..6f122261c 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -49,9 +49,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); aconfig.specializations.subgroup_mask_representation = SubgroupMaskInt64; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); const Type* mask_type = get_actual_mask_type(a); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 116ecb895..69f1139fa 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -126,8 +126,8 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_memcpy(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index e78edfa54..03a8868c4 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -49,8 +49,8 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index c744ceb3c..c7587d3ff 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -23,7 +23,7 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { const Node* nul = gen_reinterpret_cast(bb, t, shd_uint64_literal(a, 0)); Node* decl = constant(ctx->rewriter.dst_module, shd_singleton(annotation(a, (Annotation) { .name = "Generated", - })), t, format_string_interned(a, "nullptr_%s", name_type_safe(a, t))); + })), t, shd_fmt_string_irarena(a, "nullptr_%s", name_type_safe(a, t))); decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(nul)); const Node* ref = ref_decl_helper(a, decl); shd_dict_insert(const Type*, const Node*, ctx->map, t, ref); @@ -49,8 +49,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 16165db7f..e7169e4e1 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -92,7 +92,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type } if (config->printf_trace.memory_accesses) { AddressSpace as = get_unqualified_type(arr->type)->payload.ptr_type.address_space; - String template = format_string_interned(a, "loaded %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); + String template = shd_fmt_string_irarena(a, "loaded %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); const Node* widened = acc; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, shd_uint32_type(a), acc); @@ -195,7 +195,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element } if (config->printf_trace.memory_accesses) { AddressSpace as = get_unqualified_type(arr->type)->payload.ptr_type.address_space; - String template = format_string_interned(a, "stored %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); + String template = shd_fmt_string_irarena(a, "stored %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); const Node* widened = value; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, shd_uint32_type(a), value); @@ -468,7 +468,7 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { const Node* size_of = gen_primop_e(bb, size_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_empty(a)); const Node* size_in_words = bytes_to_words(bb, size_of); - Node* constant_decl = constant(m, annotations, ptr_size_type, format_string_interned(a, "memory_%s_size", as_name)); + Node* constant_decl = constant(m, annotations, ptr_size_type, shd_fmt_string_irarena(a, "memory_%s_size", as_name)); constant_decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(size_in_words)); const Type* words_array_type = arr_type(a, (ArrType) { @@ -482,12 +482,12 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { } Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); aconfig.address_spaces[AsPrivate].physical = false; aconfig.address_spaces[AsShared].physical = false; aconfig.address_spaces[AsSubgroup].physical = false; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index ed697d6fb..c8754d248 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -175,8 +175,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index acb648021..b497632aa 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -118,7 +118,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod fn = *found; else { const Node* src_param = param(a, shd_as_qualified_type(t, false), "src"); - fn = function(m, shd_singleton(src_param), format_string_interned(a, "subgroup_first_%s", name_type_safe(a, t)), + fn = function(m, shd_singleton(src_param), shd_fmt_string_irarena(a, "subgroup_first_%s", name_type_safe(a, t)), mk_nodes(a, annotation(a, (Annotation) { .name = "Generated"}), annotation(a, (Annotation) { .name = "Leaf" })), shd_singleton( shd_as_qualified_type(t, true))); shd_dict_insert(const Node*, Node*, ctx->fns, t, fn); @@ -149,8 +149,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); assert(!config->lower.emulate_subgroup_ops && "TODO"); Context ctx = { diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index bd2d905db..7c245b50c 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -88,8 +88,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 357d2144a..382f54634 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -181,8 +181,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_switch_btree(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index ff3d3da1a..83ccd02ec 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -438,8 +438,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); struct Dict* ptrs = shd_new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 182b60470..b3d12872f 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -54,9 +54,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_vec_arr(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); aconfig.validate_builtin_types = false; // TODO: hacky - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index a2fa807e5..1ffc820c0 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -189,8 +189,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_workgroups(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index abc6e98f3..d51c14848 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -152,8 +152,8 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 5d6045c12..e5897697f 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -93,9 +93,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); aconfig.validate_builtin_types = true; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index de40268bd..4aaa4b375 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -156,7 +156,7 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t k->new = new; return new; } - if (!k->non_logical_use && get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { + if (!k->non_logical_use && shd_get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { *ctx->todo |= old->tag != LocalAlloc_TAG; const Node* new = local_alloc(a, (LocalAlloc) { .type = rewrite_node(r, old_type), .mem = nmem }); k->new = new; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index ced25b059..15d61a774 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -244,8 +244,8 @@ void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { } Module* opt_inline(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); opt_simplify_cf(config, src, dst); return dst; diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 0e3978d3b..ad96887f5 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -416,8 +416,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 31fc858b5..2c1ba5fa2 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -482,9 +482,9 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); aconfig.optimisations.inline_single_use_bbs = true; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index 9e36bdb67..db69162d6 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -30,8 +30,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* remove_critical_edges(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index ea688bfe2..673786bd6 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -162,7 +162,7 @@ static const Nodes* find_scope_info(const Node* abs) { return info; } -bool compare_nodes(Nodes* a, Nodes* b); +bool shd_compare_nodes(Nodes* a, Nodes* b); static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge edge) { assert(edge.type == JumpEdge && edge.jump); @@ -204,7 +204,7 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed continue; } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { shd_error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); - } else if (compare_nodes(dom_lexical_scope, dst_lexical_scope)) { + } else if (shd_compare_nodes(dom_lexical_scope, dst_lexical_scope)) { // if (cfg_is_dominated(target_cfnode, dom)) { if (!cfg_is_dominated(dom, dst_cfnode) && dst_cfnode != dom) { // assert(false); @@ -301,9 +301,9 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* scope2control(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); aconfig.optimisations.inline_single_use_bbs = true; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index 6921719ca..73038a7c9 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -200,8 +200,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* scope_heuristic(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index f59dd1b8a..72ce6466c 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -60,8 +60,8 @@ static const Node* process(Context* ctx, const Node* node) { } Module* setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); - IrArena* a = new_ir_arena(&aconfig); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 628c4a97f..0e8f526a8 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -105,9 +105,9 @@ static void specialize_arena_config(const CompilerConfig* config, Module* src, A } Module* specialize_entry_point(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); specialize_arena_config(config, src, &aconfig); - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 580d520bd..2b7f275bd 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -41,9 +41,9 @@ static void specialize_arena_config(const CompilerConfig* config, Module* m, Are } Module* specialize_execution_model(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); specialize_arena_config(config, src, &aconfig); - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); size_t subgroup_size = config->specialization.subgroup_size; diff --git a/src/shady/print.c b/src/shady/print.c index a409c7f02..6b877c420 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1028,9 +1028,9 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { print_def = false; } else if (is_param(node) || is_basic_block(node) || node->tag == RefDecl_TAG || node->tag == FnAddr_TAG) { print_def = false; - r = format_string_interned(node->arena, "%%%d", node->id); + r = shd_fmt_string_irarena(node->arena, "%%%d", node->id); } else { - r = format_string_interned(node->arena, "%%%d", node->id); + r = shd_fmt_string_irarena(node->arena, "%%%d", node->id); } shd_dict_insert(const Node*, String, ctx->emitted, node, r); diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index fa2760bcf..2ea77fd90 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -21,7 +21,7 @@ Nodes rewrite_nodes_with_fn(Rewriter* rewriter, Nodes values, RewriteNodeFn fn); Nodes rewrite_ops(Rewriter*, NodeClass, String, Nodes); Nodes rewrite_ops_with_fn(Rewriter* rewriter, NodeClass,String, Nodes values, RewriteOpFn fn); -Strings import_strings(IrArena*, Strings); +Strings _shd_import_strings(IrArena* dst_arena, Strings old_strings); struct Rewriter_ { RewriteNodeFn rewrite_fn; diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 847cda921..ef7bcdd76 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -85,7 +85,7 @@ int main(int argc, char** argv) { ArenaConfig aconfig = shd_default_arena_config(&args.config.target); aconfig.optimisations.weaken_non_leaking_allocas = true; - IrArena* arena = new_ir_arena(&aconfig); + IrArena* arena = shd_new_ir_arena(&aconfig); Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one ShadyErrorCodes err = shd_driver_load_source_files(&args, mod); @@ -93,12 +93,12 @@ int main(int argc, char** argv) { exit(err); Module* mod2 = oracle_passes(&args.config, mod); - destroy_ir_arena(get_module_arena(mod2)); + shd_destroy_ir_arena(get_module_arena(mod2)); if (err) exit(err); shd_info_print("Compilation successful\n"); - destroy_ir_arena(arena); + shd_destroy_ir_arena(arena); shd_destroy_driver_config(&args); } \ No newline at end of file diff --git a/test/test_builder.c b/test/test_builder.c index cdfee4b7d..4fdf53521 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -160,10 +160,10 @@ int main(int argc, char** argv) { TargetConfig target_config = shd_default_target_config(); ArenaConfig aconfig = shd_default_arena_config(&target_config); - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); test_body_builder_constants(a); test_body_builder_fun_body(a); test_body_builder_impure_block(a); test_body_builder_impure_block_with_control_flow(a); - destroy_ir_arena(a); + shd_destroy_ir_arena(a); } diff --git a/test/test_math.c b/test/test_math.c index d90cd5fa5..07eb4c0e9 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -95,7 +95,7 @@ int main(int argc, char** argv) { ArenaConfig aconfig = shd_default_arena_config(&target_config); aconfig.check_types = true; aconfig.allow_fold = true; - IrArena* a = new_ir_arena(&aconfig); + IrArena* a = shd_new_ir_arena(&aconfig); test_int_literals(a); - destroy_ir_arena(a); + shd_destroy_ir_arena(a); } diff --git a/vcc/vcc.c b/vcc/vcc.c index ad131f679..67d7701f8 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -26,7 +26,7 @@ int main(int argc, char** argv) { } ArenaConfig aconfig = shd_default_arena_config(&args.config.target); - IrArena* arena = new_ir_arena(&aconfig); + IrArena* arena = shd_new_ir_arena(&aconfig); vcc_check_clang(); @@ -37,12 +37,12 @@ int main(int argc, char** argv) { if (!vcc_options.only_run_clang) { Module* mod = vcc_parse_back_into_module(&args.config, &vcc_options, "my_module"); shd_driver_compile(&args, mod); - destroy_ir_arena(get_module_arena(mod)); + shd_destroy_ir_arena(get_module_arena(mod)); } shd_info_print("Done\n"); destroy_vcc_options(vcc_options); - destroy_ir_arena(arena); + shd_destroy_ir_arena(arena); shd_destroy_driver_config(&args); } From be5c7743df71e711d1fe5af4345254f8510514b4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 13:40:33 +0200 Subject: [PATCH 616/693] move memory_layout to the public API --- include/shady/memory_layout.h | 35 +++++++++++++++ src/backend/spirv/emit_spv_type.c | 15 ++++--- src/backend/spirv/emit_spv_value.c | 17 +++---- src/backend/spirv/spirv_lift_globals_ssbo.c | 2 +- src/backend/spirv/spirv_map_entrypoint_args.c | 2 +- src/frontend/slim/slim_driver.c | 2 +- src/runtime/runtime_program.c | 2 - src/runtime/vulkan/vk_runtime_program.c | 15 +++---- src/shady/passes/lower_entrypoint_args.c | 4 +- src/shady/passes/lower_generic_ptrs.c | 2 +- src/shady/passes/lower_memcpy.c | 6 +-- src/shady/passes/lower_memory_layout.c | 14 +++--- src/shady/passes/lower_physical_ptrs.c | 13 +++--- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/transform/internal_constants.c | 2 +- src/shady/transform/internal_constants.h | 2 +- src/shady/transform/memory_layout.c | 44 ++++++++----------- src/shady/transform/memory_layout.h | 28 ------------ 18 files changed, 102 insertions(+), 105 deletions(-) create mode 100644 include/shady/memory_layout.h delete mode 100644 src/shady/transform/memory_layout.h diff --git a/include/shady/memory_layout.h b/include/shady/memory_layout.h new file mode 100644 index 000000000..3ce4014ef --- /dev/null +++ b/include/shady/memory_layout.h @@ -0,0 +1,35 @@ +#ifndef SHADY_MEMORY_LAYOUT_H +#define SHADY_MEMORY_LAYOUT_H + +#include "shady/ir.h" +#include "shady/config.h" + +typedef struct { + const Type* type; + size_t size_in_bytes; + size_t alignment_in_bytes; +} TypeMemLayout; + +typedef struct { + TypeMemLayout mem_layout; + size_t offset_in_bytes; +} FieldLayout; + +TypeMemLayout shd_get_mem_layout(IrArena* a, const Type* type); + +TypeMemLayout shd_get_record_layout(IrArena* a, const Node* record_type, FieldLayout* fields); +size_t shd_get_record_field_offset_in_bytes(IrArena* a, const Type* t, size_t i); + +static inline const Node* size_t_type(IrArena* a) { + return int_type(a, (Int) { .width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false }); +} + +static inline const Node* size_t_literal(IrArena* a, uint64_t value) { + return int_literal(a, (IntLiteral) { .width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false, .value = value }); +} + +const Node* shd_bytes_to_words(BodyBuilder* bb, const Node* bytes); +uint64_t shd_bytes_to_words_static(const IrArena* a, uint64_t bytes); +IntSizes shd_float_to_int_width(FloatSizes width); + +#endif diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 30149bd5b..c04b73eb5 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -1,14 +1,15 @@ #include "emit_spv.h" -#include "type.h" + +#include "shady/memory_layout.h" + +#include "../shady/type.h" +#include "../shady/rewrite.h" #include "portability.h" #include "log.h" #include "dict.h" -#include "../shady/rewrite.h" -#include "../shady/transform/memory_layout.h" - -#include "assert.h" +#include #pragma GCC diagnostic error "-Wswitch" @@ -81,7 +82,7 @@ void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id) { spvb_decorate(emitter->file_builder, id, SpvDecorationBlock, 0, NULL); } LARRAY(FieldLayout, fields, member_types.count); - get_record_layout(emitter->arena, type, fields); + shd_get_record_layout(emitter->arena, type, fields); for (size_t i = 0; i < member_types.count; i++) { spvb_decorate_member(emitter->file_builder, id, i, SpvDecorationOffset, 1, (uint32_t[]) { fields[i].offset_in_bytes }); } @@ -180,7 +181,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { } else { new = spvb_runtime_array_type(emitter->file_builder, element_type); } - TypeMemLayout elem_mem_layout = get_mem_layout(emitter->arena, type->payload.arr_type.element_type); + TypeMemLayout elem_mem_layout = shd_get_mem_layout(emitter->arena, type->payload.arr_type.element_type); spvb_decorate(emitter->file_builder, new, SpvDecorationArrayStride, 1, (uint32_t[]) { elem_mem_layout.size_in_bytes }); break; } diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 7a5ce1c7c..da77b551f 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -1,21 +1,22 @@ #include "emit_spv.h" -#include "log.h" -#include "dict.h" -#include "portability.h" +#include "shady/memory_layout.h" #include "../shady/type.h" -#include "../shady/transform/memory_layout.h" #include "../shady/transform/ir_gen_helpers.h" #include "../shady/analysis/cfg.h" #include "../shady/analysis/scheduler.h" -#include -#include +#include "log.h" +#include "dict.h" +#include "portability.h" #include "spirv/unified1/NonSemanticDebugPrintf.h" #include "spirv/unified1/GLSL.std.450.h" +#include +#include + typedef enum { Custom, Plain, } InstrClass; @@ -395,7 +396,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui uint32_t operands[2]; if (ptr_type->payload.ptr_type.address_space == AsGlobal) { // TODO only do this in VK mode ? - TypeMemLayout layout = get_mem_layout(emitter->arena, elem_type); + TypeMemLayout layout = shd_get_mem_layout(emitter->arena, elem_type); operands[operands_count + 0] = SpvMemoryAccessAlignedMask; operands[operands_count + 1] = (uint32_t) layout.alignment_in_bytes; operands_count += 2; @@ -416,7 +417,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui uint32_t operands[2]; if (ptr_type->payload.ptr_type.address_space == AsGlobal) { // TODO only do this in VK mode ? - TypeMemLayout layout = get_mem_layout(emitter->arena, elem_type); + TypeMemLayout layout = shd_get_mem_layout(emitter->arena, elem_type); operands[operands_count + 0] = SpvMemoryAccessAlignedMask; operands[operands_count + 1] = (uint32_t) layout.alignment_in_bytes; operands_count += 2; diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 352468fb3..c3f2ec9c6 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -1,8 +1,8 @@ #include "shady/pass.h" +#include "shady/memory_layout.h" #include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" -#include "../shady/transform/memory_layout.h" #include "dict.h" #include "portability.h" diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index 56eebfa95..00df946db 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -1,8 +1,8 @@ #include "shady/pass.h" +#include "shady/memory_layout.h" #include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" -#include "../shady/transform/memory_layout.h" #include "portability.h" #include "log.h" diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index 2bd637903..92752e2e6 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -32,7 +32,7 @@ Module* shd_parse_slim_module(const CompilerConfig* config, const SlimParserConf shd_debugv_print("Parsed slim module:\n"); shd_log_module(DEBUGV, config, *pmod); - generate_dummy_constants(config, *pmod); + shd_generate_dummy_constants(config, *pmod); RUN_PASS(slim_pass_bind) RUN_PASS(slim_pass_normalize) diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index 92e862580..5cbb5ed9c 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -10,8 +10,6 @@ #include #include -#include "../shady/transform/memory_layout.h" - Program* new_program_from_module(Runtime* runtime, const CompilerConfig* base_config, Module* mod) { Program* program = calloc(1, sizeof(Program)); program->runtime = runtime; diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index f984d4209..e63f18e96 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -1,18 +1,17 @@ #include "vk_runtime_private.h" #include "shady/driver.h" +#include "shady/memory_layout.h" + +#include "type.h" #include "log.h" #include "portability.h" #include "dict.h" #include "list.h" #include "growy.h" - #include "arena.h" #include "util.h" -#include "type.h" - -#include "../../shady/transform/memory_layout.h" #include #include @@ -64,14 +63,14 @@ static void write_value(unsigned char* tgt, const Node* value) { if (struct_t->tag == RecordType_TAG) { LARRAY(FieldLayout, fields, values.count); - get_record_layout(a, struct_t, fields); + shd_get_record_layout(a, struct_t, fields); for (size_t i = 0; i < values.count; i++) { // TypeMemLayout layout = get_mem_layout(value->arena, get_unqualified_type(element->type)); write_value(tgt + fields->offset_in_bytes, values.nodes[i]); } } else if (struct_t->tag == ArrType_TAG) { for (size_t i = 0; i < values.count; i++) { - TypeMemLayout layout = get_mem_layout(value->arena, get_unqualified_type(values.nodes[i]->type)); + TypeMemLayout layout = shd_get_mem_layout(value->arena, get_unqualified_type(values.nodes[i]->type)); write_value(tgt, values.nodes[i]); tgt += layout.size_in_bytes; } @@ -123,7 +122,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay const Type* member_t = struct_t->payload.record_type.members.nodes[j]; assert(member_t->tag == PtrType_TAG); member_t = get_pointee_type(member_t->arena, member_t); - TypeMemLayout layout = get_mem_layout(program->specialized_module->arena, member_t); + TypeMemLayout layout = shd_get_mem_layout(get_module_arena(program->specialized_module), member_t); ProgramResourceInfo* constant_res_info = shd_arena_alloc(program->arena, sizeof(ProgramResourceInfo)); *constant_res_info = (ProgramResourceInfo) { @@ -356,7 +355,7 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) IrArena* a = get_module_arena(mod); LARRAY(FieldLayout, fields, num_args); - get_record_layout(a, args_struct_type, fields); + shd_get_record_layout(a, args_struct_type, fields); size_t* offset_size_buffer = calloc(1, 2 * num_args * sizeof(size_t)); if (!offset_size_buffer) { diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 22561ba95..b8c56edaa 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -1,8 +1,8 @@ #include "shady/pass.h" +#include "shady/memory_layout.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" -#include "../transform/memory_layout.h" #include "portability.h" #include "log.h" @@ -51,7 +51,7 @@ static const Node* generate_arg_struct(Rewriter* rewriter, const Node* old_entry Nodes annotations = mk_nodes(a, annotation_value(a, (AnnotationValue) { .name = "EntryPointArgs", .value = fn_addr_helper(a, new_entry_point) })); const Node* type = generate_arg_struct_type(rewriter, old_entry_point->payload.fun.params); - String name = shd_format_string_arena(a->arena, "__%s_args", old_entry_point->payload.fun.name); + String name = shd_fmt_string_irarena(a, "__%s_args", old_entry_point->payload.fun.name); Node* var = global_var(rewriter->dst_module, annotations, type, name, AsExternal); return ref_decl_helper(a, var); diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 1d9dce58d..8db9997e2 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -1,9 +1,9 @@ #include "shady/pass.h" +#include "shady/memory_layout.h" #include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" -#include "../transform/memory_layout.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 69f1139fa..81f4eb2bd 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -1,7 +1,7 @@ #include "shady/pass.h" +#include "shady/memory_layout.h" #include "../transform/ir_gen_helpers.h" -#include "../transform/memory_layout.h" #include "../type.h" #include "../ir_private.h" @@ -48,7 +48,7 @@ static const Node* process(Context* ctx, const Node* old) { src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, payload.count)); - const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), bytes_to_words(bb, num_in_bytes)); + const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num_in_bytes)); begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); @@ -95,7 +95,7 @@ static const Node* process(Context* ctx, const Node* old) { dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); const Node* num = rewrite_node(&ctx->rewriter, payload.count); - const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), bytes_to_words(bb, num)); + const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num)); begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 03a8868c4..7471ed9dd 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -1,6 +1,6 @@ #include "shady/pass.h" +#include "shady/memory_layout.h" -#include "../transform/memory_layout.h" #include "../type.h" #include "log.h" @@ -20,13 +20,13 @@ static const Node* process(Context* ctx, const Node* old) { switch (old->payload.prim_op.op) { case size_of_op: { const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); - TypeMemLayout layout = get_mem_layout(a, t); - return int_literal(a, (IntLiteral) {.width = a->config.memory.ptr_size, .is_signed = false, .value = layout.size_in_bytes}); + TypeMemLayout layout = shd_get_mem_layout(a, t); + return int_literal(a, (IntLiteral) {.width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false, .value = layout.size_in_bytes}); } case align_of_op: { const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); - TypeMemLayout layout = get_mem_layout(a, t); - return int_literal(a, (IntLiteral) {.width = a->config.memory.ptr_size, .is_signed = false, .value = layout.alignment_in_bytes}); + TypeMemLayout layout = shd_get_mem_layout(a, t); + return int_literal(a, (IntLiteral) {.width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false, .value = layout.alignment_in_bytes}); } case offset_of_op: { const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); @@ -34,8 +34,8 @@ static const Node* process(Context* ctx, const Node* old) { const IntLiteral* literal = resolve_to_int_literal(n); assert(literal); t = get_maybe_nominal_type_body(t); - uint64_t offset_in_bytes = (uint64_t) get_record_field_offset_in_bytes(a, t, literal->value); - const Node* offset_literal = int_literal(a, (IntLiteral) { .width = a->config.memory.ptr_size, .is_signed = false, .value = offset_in_bytes }); + uint64_t offset_in_bytes = (uint64_t) shd_get_record_field_offset_in_bytes(a, t, literal->value); + const Node* offset_literal = int_literal(a, (IntLiteral) { .width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false, .value = offset_in_bytes }); return offset_literal; } default: break; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index e7169e4e1..8bc4ff4cb 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -1,10 +1,9 @@ #include "shady/pass.h" +#include "shady/memory_layout.h" #include "../ir_private.h" #include "../type.h" - #include "../transform/ir_gen_helpers.h" -#include "../transform/memory_layout.h" #include "log.h" #include "portability.h" @@ -78,7 +77,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* acc = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); size_t length_in_bytes = int_size_in_bytes(element_type->payload.int_type.width); size_t word_size_in_bytes = int_size_in_bytes(a->config.memory.word_size); - const Node* offset = bytes_to_words(bb, address); + const Node* offset = shd_bytes_to_words(bb, address); const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { @@ -102,7 +101,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type return acc; } case Float_TAG: { - const Type* unsigned_int_t = int_type(a, (Int) {.width = float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); + const Type* unsigned_int_t = int_type(a, (Int) {.width = shd_float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); const Node* unsigned_int = gen_deserialisation(ctx, bb, unsigned_int_t, arr, address); return gen_reinterpret_cast(bb, element_type, unsigned_int); } @@ -172,7 +171,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element // const Node* acc = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); size_t length_in_bytes = int_size_in_bytes(element_type->payload.int_type.width); size_t word_size_in_bytes = int_size_in_bytes(a->config.memory.word_size); - const Node* offset = bytes_to_words(bb, address); + const Node* offset = shd_bytes_to_words(bb, address); const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { @@ -204,7 +203,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element return; } case Float_TAG: { - const Type* unsigned_int_t = int_type(a, (Int) {.width = float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); + const Type* unsigned_int_t = int_type(a, (Int) {.width = shd_float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, shd_singleton(unsigned_int_t), shd_singleton(value)); return gen_serialisation(ctx, bb, unsigned_int_t, arr, address, unsigned_value); } @@ -466,7 +465,7 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { // compute the size BodyBuilder* bb = begin_block_pure(a); const Node* size_of = gen_primop_e(bb, size_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_empty(a)); - const Node* size_in_words = bytes_to_words(bb, size_of); + const Node* size_in_words = shd_bytes_to_words(bb, size_of); Node* constant_decl = constant(m, annotations, ptr_size_type, shd_fmt_string_irarena(a, "memory_%s_size", as_name)); constant_decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(size_in_words)); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index b497632aa..99476ddb2 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -1,8 +1,8 @@ #include "shady/pass.h" +#include "shady/memory_layout.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" -#include "../transform/memory_layout.h" #include "portability.h" #include "log.h" diff --git a/src/shady/transform/internal_constants.c b/src/shady/transform/internal_constants.c index 67cf592de..d3597670c 100644 --- a/src/shady/transform/internal_constants.c +++ b/src/shady/transform/internal_constants.c @@ -5,7 +5,7 @@ #include -void generate_dummy_constants(SHADY_UNUSED const CompilerConfig* config, Module* mod) { +void shd_generate_dummy_constants(SHADY_UNUSED const CompilerConfig* config, Module* mod) { IrArena* arena = get_module_arena(mod); Nodes annotations = mk_nodes(arena, annotation(arena, (Annotation) { .name = "RetainAfterSpecialization" }), annotation(arena, (Annotation) { .name = "Exported" })); #define X(constant_name, T, placeholder) \ diff --git a/src/shady/transform/internal_constants.h b/src/shady/transform/internal_constants.h index 3e7a7dce1..46fb99ee5 100644 --- a/src/shady/transform/internal_constants.h +++ b/src/shady/transform/internal_constants.h @@ -8,6 +8,6 @@ X(SUBGROUP_SIZE, shd_uint32_type(arena), shd_uint32_literal(arena, 64)) \ X(SUBGROUPS_PER_WG, shd_uint32_type(arena), shd_uint32_literal(arena, 1)) \ typedef struct CompilerConfig_ CompilerConfig; -void generate_dummy_constants(const CompilerConfig* config, Module*); +void shd_generate_dummy_constants(const CompilerConfig* config, Module* mod); #endif diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 31c04563b..6c0bf432d 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -1,4 +1,4 @@ -#include "memory_layout.h" +#include "shady/memory_layout.h" #include "ir_gen_helpers.h" #include "log.h" @@ -21,7 +21,7 @@ static int maxof(int a, int b) { return b; } -TypeMemLayout get_record_layout(IrArena* a, const Node* record_type, FieldLayout* fields) { +TypeMemLayout shd_get_record_layout(IrArena* a, const Node* record_type, FieldLayout* fields) { assert(record_type->tag == RecordType_TAG); size_t offset = 0; @@ -29,7 +29,7 @@ TypeMemLayout get_record_layout(IrArena* a, const Node* record_type, FieldLayout Nodes member_types = record_type->payload.record_type.members; for (size_t i = 0; i < member_types.count; i++) { - TypeMemLayout member_layout = get_mem_layout(a, member_types.nodes[i]); + TypeMemLayout member_layout = shd_get_mem_layout(a, member_types.nodes[i]); offset = round_up(offset, member_layout.alignment_in_bytes); if (fields) { fields[i].mem_layout = member_layout; @@ -47,17 +47,17 @@ TypeMemLayout get_record_layout(IrArena* a, const Node* record_type, FieldLayout }; } -size_t get_record_field_offset_in_bytes(IrArena* a, const Type* t, size_t i) { +size_t shd_get_record_field_offset_in_bytes(IrArena* a, const Type* t, size_t i) { assert(t->tag == RecordType_TAG); Nodes member_types = t->payload.record_type.members; assert(i < member_types.count); LARRAY(FieldLayout, fields, member_types.count); - get_record_layout(a, t, fields); + shd_get_record_layout(a, t, fields); return fields[i].offset_in_bytes; } -TypeMemLayout get_mem_layout(IrArena* a, const Type* type) { - size_t base_word_size = int_size_in_bytes(a->config.memory.word_size); +TypeMemLayout shd_get_mem_layout(IrArena* a, const Type* type) { + size_t base_word_size = int_size_in_bytes(shd_get_arena_config(a)->memory.word_size); assert(is_type(type)); switch (type->tag) { case FnType_TAG: shd_error("Functions have an opaque memory representation"); @@ -66,7 +66,7 @@ TypeMemLayout get_mem_layout(IrArena* a, const Type* type) { case AsSubgroup: case AsShared: case AsGlobal: - case AsGeneric: return get_mem_layout(a, int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false })); // TODO: use per-as layout + case AsGeneric: return shd_get_mem_layout(a, int_type(a, (Int) { .width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false })); // TODO: use per-as layout default: shd_error("Pointers in address space '%s' does not have a defined memory layout", get_address_space_name(type->payload.ptr_type.address_space)); } case Int_TAG: return (TypeMemLayout) { @@ -88,7 +88,7 @@ TypeMemLayout get_mem_layout(IrArena* a, const Type* type) { const Node* size = type->payload.arr_type.size; assert(size && "We can't know the full layout of arrays of unknown size !"); size_t actual_size = get_int_literal_value(*resolve_to_int_literal(size), false); - TypeMemLayout element_layout = get_mem_layout(a, type->payload.arr_type.element_type); + TypeMemLayout element_layout = shd_get_mem_layout(a, type->payload.arr_type.element_type); return (TypeMemLayout) { .type = type, .size_in_bytes = actual_size * element_layout.size_in_bytes, @@ -97,42 +97,34 @@ TypeMemLayout get_mem_layout(IrArena* a, const Type* type) { } case PackType_TAG: { size_t width = type->payload.pack_type.width; - TypeMemLayout element_layout = get_mem_layout(a, type->payload.pack_type.element_type); + TypeMemLayout element_layout = shd_get_mem_layout(a, type->payload.pack_type.element_type); return (TypeMemLayout) { .type = type, .size_in_bytes = width * element_layout.size_in_bytes /* TODO Vulkan vec3 -> vec4 alignment rules ? */, .alignment_in_bytes = element_layout.alignment_in_bytes }; } - case QualifiedType_TAG: return get_mem_layout(a, type->payload.qualified_type.type); - case TypeDeclRef_TAG: return get_mem_layout(a, type->payload.type_decl_ref.decl->payload.nom_type.body); - case RecordType_TAG: return get_record_layout(a, type, NULL); + case QualifiedType_TAG: return shd_get_mem_layout(a, type->payload.qualified_type.type); + case TypeDeclRef_TAG: return shd_get_mem_layout(a, type->payload.type_decl_ref.decl->payload.nom_type.body); + case RecordType_TAG: return shd_get_record_layout(a, type, NULL); default: shd_error("not a known type"); } } -const Node* size_t_type(IrArena* a) { - return int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); -} - -const Node* size_t_literal(IrArena* a, uint64_t value) { - return int_literal(a, (IntLiteral) { .width = a->config.memory.ptr_size, .is_signed = false, .value = value }); -} - -const Node* bytes_to_words(BodyBuilder* bb, const Node* bytes) { +const Node* shd_bytes_to_words(BodyBuilder* bb, const Node* bytes) { IrArena* a = bytes->arena; - const Type* word_type = int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }); + const Type* word_type = int_type(a, (Int) { .width = shd_get_arena_config(a)->memory.word_size, .is_signed = false }); size_t word_width = get_type_bitwidth(word_type); const Node* bytes_per_word = size_t_literal(a, word_width / 8); return gen_primop_e(bb, div_op, shd_empty(a), mk_nodes(a, bytes, bytes_per_word)); } -uint64_t bytes_to_words_static(const IrArena* a, uint64_t bytes) { - uint64_t word_width = int_size_in_bytes(a->config.memory.word_size); +uint64_t shd_bytes_to_words_static(const IrArena* a, uint64_t bytes) { + uint64_t word_width = int_size_in_bytes(shd_get_arena_config(a)->memory.word_size); return bytes / word_width; } -IntSizes float_to_int_width(FloatSizes width) { +IntSizes shd_float_to_int_width(FloatSizes width) { switch (width) { case FloatTy16: return IntTy16; case FloatTy32: return IntTy32; diff --git a/src/shady/transform/memory_layout.h b/src/shady/transform/memory_layout.h deleted file mode 100644 index 25aa8b703..000000000 --- a/src/shady/transform/memory_layout.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SHADY_MEMORY_LAYOUT_H -#define SHADY_MEMORY_LAYOUT_H - -#include "../ir_private.h" - -typedef struct { - const Type* type; - size_t size_in_bytes; - size_t alignment_in_bytes; -} TypeMemLayout; - -typedef struct { - TypeMemLayout mem_layout; - size_t offset_in_bytes; -} FieldLayout; - -TypeMemLayout get_mem_layout(IrArena*, const Type*); - -TypeMemLayout get_record_layout(IrArena* a, const Node* record_type, FieldLayout* fields); -size_t get_record_field_offset_in_bytes(IrArena*, const Type*, size_t); - -const Type* size_t_type(IrArena* a); -const Node* size_t_literal(IrArena* a, uint64_t value); -const Node* bytes_to_words(BodyBuilder* bb, const Node* bytes); -uint64_t bytes_to_words_static(const IrArena*, uint64_t bytes); -IntSizes float_to_int_width(FloatSizes width); - -#endif From daec66506464776adb28cac7d57d02d949acf621 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 13:45:14 +0200 Subject: [PATCH 617/693] prefix print stuff with shd_ --- include/shady/be/dump.h | 4 ++-- src/shady/generator_print.c | 8 +++---- src/shady/print.c | 47 +++++++++++++++++-------------------- test/opt/opt_oracle.c | 4 ++-- test/test_builder.c | 6 ++--- 5 files changed, 33 insertions(+), 36 deletions(-) diff --git a/include/shady/be/dump.h b/include/shady/be/dump.h index de0b5e561..56b319293 100644 --- a/include/shady/be/dump.h +++ b/include/shady/be/dump.h @@ -1,8 +1,8 @@ #ifndef SHD_BE_DUMP_H #define SHD_BE_DUMP_H -void dump_module(Module*); -void dump_node(const Node* node); +void shd_dump_module(Module* mod); +void shd_dump_node(const Node* node); void dump_cfgs(FILE* output, Module* mod); void dump_loop_trees(FILE* output, Module* mod); diff --git a/src/shady/generator_print.c b/src/shady/generator_print.c index 2151a1be2..14ddfb98d 100644 --- a/src/shady/generator_print.c +++ b/src/shady/generator_print.c @@ -2,7 +2,7 @@ void generate_node_print_fns(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); - shd_growy_append_formatted(g, "void print_node_generated(PrinterCtx* ctx, const Node* node) {\n"); + shd_growy_append_formatted(g, "void _shd_print_node_generated(PrinterCtx* ctx, const Node* node) {\n"); shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { @@ -35,7 +35,7 @@ void generate_node_print_fns(Growy* g, json_object* src) { String cap_class = capitalize(op_class); if (is_list) { shd_growy_append_formatted(g, "\t\t{\n"); - shd_growy_append_formatted(g, "\t\t\tprint_node_operand_list(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); + shd_growy_append_formatted(g, "\t\t\t_shd_print_node_operand_list(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); // growy_append_formatted(g, "\t\t\tsize_t count = node->payload.%s.%s.count;\n", snake_name, op_name); // growy_append_formatted(g, "\t\t\tfor (size_t i = 0; i < count; i++) {\n"); // growy_append_formatted(g, "\t\t\t\tprint_node_operand(printer, node, \"%s\", Nc%s, i, node->payload.%s.%s.nodes[i], config);\n", op_name, cap_class, snake_name, op_name); @@ -43,7 +43,7 @@ void generate_node_print_fns(Growy* g, json_object* src) { shd_growy_append_formatted(g, "\t\t}\n"); } else { shd_growy_append_formatted(g, "\t\t{\n"); - shd_growy_append_formatted(g, "\t\t\tprint_node_operand(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); + shd_growy_append_formatted(g, "\t\t\t_shd_print_node_operand(ctx, node, \"%s\", Nc%s, node->payload.%s.%s);\n", op_name, cap_class, snake_name, op_name); shd_growy_append_formatted(g, "\t\t}\n"); } free((void*) cap_class); @@ -61,7 +61,7 @@ void generate_node_print_fns(Growy* g, json_object* src) { if (!isalnum(s[k])) s[k] = '_'; } - shd_growy_append_formatted(g, "\t\tprint_node_operand_%s(ctx, node, \"%s\", node->payload.%s.%s);\n", s, op_name, snake_name, op_name); + shd_growy_append_formatted(g, "\t\t_shd_print_node_operand_%s(ctx, node, \"%s\", node->payload.%s.%s);\n", s, op_name, snake_name, op_name); free(s); } diff --git a/src/shady/print.c b/src/shady/print.c index 6b877c420..63973b834 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -102,7 +102,7 @@ void shd_print_module_into_str(Module* mod, char** str_ptr, size_t* size) { *str_ptr = shd_growy_deconstruct(g); } -void dump_node(const Node* node) { +void shd_dump_node(const Node* node) { Printer* p = shd_new_printer_from_file(stdout); if (node) shd_print(p, "%%%d ", node->id); @@ -110,7 +110,7 @@ void dump_node(const Node* node) { printf("\n"); } -void dump_module(Module* mod) { +void shd_dump_module(Module* mod) { Printer* p = shd_new_printer_from_file(stdout); shd_print_module(p, (NodePrintConfig) {.color = true}, mod); shd_destroy_printer(p); @@ -165,10 +165,10 @@ void shd_log_module(LogLevel level, const CompilerConfig* compiler_cfg, Module* static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op); -void print_node_operand(PrinterCtx* ctx, const Node* node, String op_name, NodeClass op_class, const Node* op); -void print_node_operand_list(PrinterCtx* ctx, const Node* node, String op_name, NodeClass op_class, Nodes ops); +void _shd_print_node_operand(PrinterCtx* ctx, const Node* node, String op_name, NodeClass op_class, const Node* op); +void _shd_print_node_operand_list(PrinterCtx* ctx, const Node* node, String op_name, NodeClass op_class, Nodes ops); -void print_node_generated(PrinterCtx* ctx, const Node* node); +void _shd_print_node_generated(PrinterCtx* ctx, const Node* node); #pragma GCC diagnostic error "-Wswitch" @@ -487,8 +487,7 @@ static bool print_type(PrinterCtx* ctx, const Node* node) { printf("%s", get_declaration_name(node->payload.type_decl_ref.decl)); break; } - default: - print_node_generated(ctx, node); + default:_shd_print_node_generated(ctx, node); break; } printf(RESET); @@ -642,8 +641,7 @@ static bool print_value(PrinterCtx* ctx, const Node* node) { printf("%s", (char*) get_declaration_name(node->payload.fn_addr.fn)); printf(RESET); return true; - default: - print_node_generated(ctx, node); + default:_shd_print_node_generated(ctx, node); break; } return false; @@ -677,7 +675,7 @@ static void print_instruction(PrinterCtx* ctx, const Node* node) { // print_args_list(ctx, node->payload.call.args); // break; // } - default: print_node_generated(ctx, node); + default: _shd_print_node_generated(ctx, node); } //printf("\n"); } @@ -881,8 +879,7 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { print_args_list(ctx, node->payload.merge_selection.args); printf(";"); break;*/ - default: - print_node_generated(ctx, node); + default:_shd_print_node_generated(ctx, node); return; } emit_node(ctx, get_terminator_mem(node)); @@ -1090,7 +1087,7 @@ static bool print_node_impl(PrinterCtx* ctx, const Node* node) { printf(RESET); return true; } else { - print_node_generated(ctx, node); + _shd_print_node_generated(ctx, node); } return false; } @@ -1151,7 +1148,7 @@ static void print_operand_helper(PrinterCtx* ctx, NodeClass nc, const Node* op) } } -void print_node_operand(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, const Node* op) { +void _shd_print_node_operand(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, const Node* op) { print_operand_name_helper(ctx, name); if (op_class == NcBasic_block) shd_print(ctx->printer, BYELLOW); @@ -1159,7 +1156,7 @@ void print_node_operand(PrinterCtx* ctx, const Node* n, String name, NodeClass o shd_print(ctx->printer, RESET); } -void print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, Nodes ops) { +void _shd_print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, NodeClass op_class, Nodes ops) { print_operand_name_helper(ctx, name); shd_print(ctx->printer, "["); for (size_t i = 0; i < ops.count; i++) { @@ -1170,33 +1167,33 @@ void print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, NodeCl shd_print(ctx->printer, "]"); } -void print_node_operand_AddressSpace(PrinterCtx* ctx, const Node* n, String name, AddressSpace as) { +void _shd_print_node_operand_AddressSpace(PrinterCtx* ctx, const Node* n, String name, AddressSpace as) { print_operand_name_helper(ctx, name); shd_print(ctx->printer, "%s", get_address_space_name(as)); } -void print_node_operand_Op(PrinterCtx* ctx, const Node* n, String name, Op op) { +void _shd_print_node_operand_Op(PrinterCtx* ctx, const Node* n, String name, Op op) { print_operand_name_helper(ctx, name); shd_print(ctx->printer, "%s", get_primop_name(op)); } -void print_node_operand_RecordSpecialFlag(PrinterCtx* ctx, const Node* n, String name, RecordSpecialFlag flags) { +void _shd_print_node_operand_RecordSpecialFlag(PrinterCtx* ctx, const Node* n, String name, RecordSpecialFlag flags) { print_operand_name_helper(ctx, name); if (flags & DecorateBlock) shd_print(ctx->printer, "DecorateBlock"); } -void print_node_operand_uint32_t(PrinterCtx* ctx, const Node* n, String name, uint32_t i) { +void _shd_print_node_operand_uint32_t(PrinterCtx* ctx, const Node* n, String name, uint32_t i) { print_operand_name_helper(ctx, name); shd_print(ctx->printer, "%u", i); } -void print_node_operand_uint64_t(PrinterCtx* ctx, const Node* n, String name, uint64_t i) { +void _shd_print_node_operand_uint64_t(PrinterCtx* ctx, const Node* n, String name, uint64_t i) { print_operand_name_helper(ctx, name); shd_print(ctx->printer, "%zu", i); } -void print_node_operand_IntSizes(PrinterCtx* ctx, const Node* n, String name, IntSizes s) { +void _shd_print_node_operand_IntSizes(PrinterCtx* ctx, const Node* n, String name, IntSizes s) { print_operand_name_helper(ctx, name); switch (s) { case IntTy8: shd_print(ctx->printer, "8"); break; @@ -1206,7 +1203,7 @@ void print_node_operand_IntSizes(PrinterCtx* ctx, const Node* n, String name, In } } -void print_node_operand_FloatSizes(PrinterCtx* ctx, const Node* n, String name, FloatSizes s) { +void _shd_print_node_operand_FloatSizes(PrinterCtx* ctx, const Node* n, String name, FloatSizes s) { print_operand_name_helper(ctx, name); switch (s) { case FloatTy16: shd_print(ctx->printer, "16"); break; @@ -1215,12 +1212,12 @@ void print_node_operand_FloatSizes(PrinterCtx* ctx, const Node* n, String name, } } -void print_node_operand_String(PrinterCtx* ctx, const Node* n, String name, String s ){ +void _shd_print_node_operand_String(PrinterCtx* ctx, const Node* n, String name, String s ){ print_operand_name_helper(ctx, name); shd_print(ctx->printer, "\"%s\"", s); } -void print_node_operand_Strings(PrinterCtx* ctx, const Node* n, String name, Strings ops) { +void _shd_print_node_operand_Strings(PrinterCtx* ctx, const Node* n, String name, Strings ops) { print_operand_name_helper(ctx, name); shd_print(ctx->printer, "["); for (size_t i = 0; i < ops.count; i++) { @@ -1231,7 +1228,7 @@ void print_node_operand_Strings(PrinterCtx* ctx, const Node* n, String name, Str shd_print(ctx->printer, "]"); } -void print_node_operand_bool(PrinterCtx* ctx, const Node* n, String name, bool b) { +void _shd_print_node_operand_bool(PrinterCtx* ctx, const Node* n, String name, bool b) { print_operand_name_helper(ctx, name); if (b) shd_print(ctx->printer, "true"); diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index ef7bcdd76..a12d4fc8f 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -40,10 +40,10 @@ static void check_module(Module* mod) { if (!expect_memstuff) shd_error_print("no more "); shd_error_print("memory primops in the output.\n"); - dump_module(mod); + shd_dump_module(mod); exit(-1); } - dump_module(mod); + shd_dump_module(mod); exit(0); } diff --git a/test/test_builder.c b/test/test_builder.c index 4fdf53521..dfdfa9ada 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -56,7 +56,7 @@ static void test_body_builder_fun_body(IrArena* a) { set_abstraction_body(fun, finish_body(bb, return_terminator)); // set_abstraction_body(fun, finish_body_with_return(bb, singleton(sum))); - dump_module(m); + shd_dump_module(m); // Follow the CFG and the mems to make sure we arrive back at the initial start ! CFG* cfg = build_fn_cfg(fun); @@ -109,7 +109,7 @@ static void test_body_builder_impure_block(IrArena* a) { }); set_abstraction_body(fun, finish_body(bb, return_terminator)); - dump_module(m); + shd_dump_module(m); bool found_store = false; const Node* mem = get_terminator_mem(return_terminator); @@ -152,7 +152,7 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { }); set_abstraction_body(fun, finish_body(bb, return_terminator)); - dump_module(m); + shd_dump_module(m); } int main(int argc, char** argv) { From 3a36021c24f01b9088f4f4dd198365973c624369 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 13:49:55 +0200 Subject: [PATCH 618/693] annotation.c: add shd_ prefix --- include/shady/ir.h | 17 ++++++++-------- src/backend/c/emit_c.c | 4 ++-- src/backend/c/emit_c_type.c | 2 +- src/backend/spirv/emit_spv.c | 20 +++++++++---------- src/backend/spirv/spirv_map_entrypoint_args.c | 2 +- src/frontend/llvm/l2s_postprocess.c | 4 ++-- src/frontend/slim/infer.c | 2 +- src/runtime/vulkan/vk_runtime_program.c | 14 ++++++------- src/shady/annotation.c | 20 +++++++++---------- src/shady/builtins.c | 4 ++-- src/shady/passes/eliminate_constants.c | 2 +- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_callf.c | 6 +++--- src/shady/passes/lower_cf_instrs.c | 2 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 4 ++-- src/shady/passes/lower_subgroup_vars.c | 2 +- src/shady/passes/lower_tailcalls.c | 8 ++++---- src/shady/passes/lower_workgroups.c | 12 +++++------ src/shady/passes/normalize_builtins.c | 8 ++++---- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_inline.c | 10 +++++----- src/shady/passes/opt_restructure.c | 8 ++++---- src/shady/passes/reconvergence_heuristics.c | 6 +++--- src/shady/passes/setup_stack_frames.c | 2 +- src/shady/passes/specialize_entry_point.c | 18 ++++++++--------- src/shady/print.c | 6 +++--- src/shady/rewrite.c | 2 +- src/shady/transform/ir_gen_helpers.c | 8 ++++---- src/shady/type.c | 6 +++--- 31 files changed, 104 insertions(+), 103 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index b03a0ea2a..a75f6d46e 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -29,6 +29,7 @@ Strings shd_strings(IrArena* arena, size_t count, const char** in_strs); Nodes shd_empty(IrArena* a); Nodes shd_singleton(const Node* n); + #define mk_nodes(arena, ...) shd_nodes(arena, sizeof((const Node*[]) { __VA_ARGS__ }) / sizeof(const Node*), (const Node*[]) { __VA_ARGS__ }) const Node* shd_first(Nodes nodes); @@ -111,7 +112,7 @@ EXECUTION_MODELS(EM) #undef EM } ExecutionModel; -ExecutionModel execution_model_from_string(const char*); +ExecutionModel shd_execution_model_from_string(const char*); typedef enum { NotSpecial, @@ -175,14 +176,14 @@ String get_address_space_name(AddressSpace); /// (amongst threads in the same subgroup) bool is_addr_space_uniform(IrArena*, AddressSpace); -const Node* lookup_annotation(const Node* decl, const char* name); -const Node* lookup_annotation_list(Nodes, const char* name); -const Node* get_annotation_value(const Node* annotation); -Nodes get_annotation_values(const Node* annotation); +const Node* shd_lookup_annotation(const Node* decl, const char* name); +const Node* shd_lookup_annotation_list(Nodes annotations, const char* name); +const Node* shd_get_annotation_value(const Node* annotation); +Nodes shd_get_annotation_values(const Node* annotation); /// Gets the string literal attached to an annotation, if present. -const char* get_annotation_string_payload(const Node* annotation); -bool lookup_annotation_with_string_payload(const Node* decl, const char* annotation_name, const char* expected_payload); -Nodes filter_out_annotation(IrArena*, Nodes, const char* name); +const char* shd_get_annotation_string_payload(const Node* annotation); +bool shd_lookup_annotation_with_string_payload(const Node* decl, const char* annotation_name, const char* expected_payload); +Nodes shd_filter_out_annotation(IrArena* arena, Nodes annotations, const char* name); const Node* get_abstraction_mem(const Node* abs); String get_abstraction_name (const Node* abs); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index b008956f3..56f990dab 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -273,7 +273,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { } if (ass == AsOutput && emitter->compiler_config->specialization.execution_model == EmFragment) { - int location = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(lookup_annotation(decl, "Location"))), false); + int location = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "Location"))), false); CTerm t = term_from_cvar(shd_fmt_string_irarena(emitter->arena, "gl_FragData[%d]", location)); register_emitted(emitter, NULL, decl, t); return; @@ -328,7 +328,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { fn_body = shd_format_string_arena(emitter->arena->arena, "if ((lanemask() >> programIndex) & 1u) { %s}", fn_body); // I hate everything about this too. } else if (emitter->config.dialect == CDialect_CUDA) { - if (lookup_annotation(decl, "EntryPoint")) { + if (shd_lookup_annotation(decl, "EntryPoint")) { // fn_body = format_string_arena(emitter->arena->arena, "\n__shady_entry_point_init();%s", fn_body); if (emitter->use_private_globals) { fn_body = shd_format_string_arena(emitter->arena->arena, "\n__shady_PrivateGlobals __shady_private_globals_alloc;\n __shady_PrivateGlobals* __shady_private_globals = &__shady_private_globals_alloc;\n%s", fn_body); diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index 93486c48a..ecd3d4653 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -48,7 +48,7 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons assert(!fn || fn->type == fn_type); Nodes codom = fn_type->payload.fn_type.return_types; - const Node* entry_point = fn ? lookup_annotation(fn, "EntryPoint") : NULL; + const Node* entry_point = fn ? shd_lookup_annotation(fn, "EntryPoint") : NULL; Growy* paramg = shd_new_growy(); Printer* paramp = shd_new_printer_from_growy(paramg); diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index bbf21e8c2..10a84540c 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -167,7 +167,7 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { assert(is_annotation(a)); String name = get_annotation_name(a); if (strcmp(name, "Builtin") == 0) { - String builtin_name = get_annotation_string_payload(a); + String builtin_name = shd_get_annotation_string_payload(a); assert(builtin_name); assert(b == BuiltinsCount && "Only one @Builtin annotation permitted."); b = shd_get_builtin_by_name(builtin_name); @@ -176,15 +176,15 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { uint32_t decoration_payload[] = { d }; spvb_decorate(emitter->file_builder, given_id, SpvDecorationBuiltIn, 1, decoration_payload); } else if (strcmp(name, "Location") == 0) { - size_t loc = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(a)), false); + size_t loc = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(a)), false); assert(loc >= 0); spvb_decorate(emitter->file_builder, given_id, SpvDecorationLocation, 1, (uint32_t[]) { loc }); } else if (strcmp(name, "DescriptorSet") == 0) { - size_t loc = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(a)), false); + size_t loc = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(a)), false); assert(loc >= 0); spvb_decorate(emitter->file_builder, given_id, SpvDecorationDescriptorSet, 1, (uint32_t[]) { loc }); } else if (strcmp(name, "DescriptorBinding") == 0) { - size_t loc = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(a)), false); + size_t loc = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(a)), false); assert(loc >= 0); spvb_decorate(emitter->file_builder, given_id, SpvDecorationBinding, 1, (uint32_t[]) { loc }); } @@ -197,8 +197,8 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { case SpvStorageClassStorageBuffer: case SpvStorageClassUniform: case SpvStorageClassUniformConstant: { - const Node* descriptor_set = lookup_annotation(decl, "DescriptorSet"); - const Node* descriptor_binding = lookup_annotation(decl, "DescriptorBinding"); + const Node* descriptor_set = shd_lookup_annotation(decl, "DescriptorSet"); + const Node* descriptor_binding = shd_lookup_annotation(decl, "DescriptorBinding"); assert(descriptor_set && descriptor_binding && "DescriptorSet and/or DescriptorBinding annotations are missing"); break; } @@ -266,19 +266,19 @@ static void emit_entry_points(Emitter* emitter, Nodes declarations) { if (decl->tag != Function_TAG) continue; SpvId fn_id = spv_find_emitted(emitter, NULL, decl); - const Node* entry_point = lookup_annotation(decl, "EntryPoint"); + const Node* entry_point = shd_lookup_annotation(decl, "EntryPoint"); if (entry_point) { - ExecutionModel execution_model = execution_model_from_string(get_string_literal(emitter->arena, get_annotation_value(entry_point))); + ExecutionModel execution_model = shd_execution_model_from_string(get_string_literal(emitter->arena, shd_get_annotation_value(entry_point))); assert(execution_model != EmNone); spvb_entry_point(emitter->file_builder, emit_exec_model(execution_model), fn_id, decl->payload.fun.name, interface_size, interface_arr); emitter->num_entry_pts++; - const Node* workgroup_size = lookup_annotation(decl, "WorkgroupSize"); + const Node* workgroup_size = shd_lookup_annotation(decl, "WorkgroupSize"); if (execution_model == EmCompute) assert(workgroup_size); if (workgroup_size) { - Nodes values = get_annotation_values(workgroup_size); + Nodes values = shd_get_annotation_values(workgroup_size); assert(values.count == 3); uint32_t wg_x_dim = (uint32_t) get_int_literal_value(*resolve_to_int_literal(values.nodes[0]), false); uint32_t wg_y_dim = (uint32_t) get_int_literal_value(*resolve_to_int_literal(values.nodes[1]), false); diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index 00df946db..d8ee9f58b 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -32,7 +32,7 @@ static const Node* rewrite_args_type(Rewriter* rewriter, const Node* old_type) { static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case GlobalVariable_TAG: - if (lookup_annotation(node, "EntryPointArgs")) { + if (shd_lookup_annotation(node, "EntryPointArgs")) { if (node->payload.global_variable.address_space != AsExternal) shd_error("EntryPointArgs address space must be extern"); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index eda711bd6..93deb737f 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -64,7 +64,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Op op; size_t i; for (i = 0; i < PRIMOPS_COUNT; i++) { - if (strcmp(get_primop_name(i), get_annotation_string_payload(an->payload)) == 0) { + if (strcmp(get_primop_name(i), shd_get_annotation_string_payload(an->payload)) == 0) { op = (Op) i; break; } @@ -106,7 +106,7 @@ static const Node* process_node(Context* ctx, const Node* node) { if (strcmp(get_annotation_name(an->payload), "Builtin") == 0) old_init = NULL; if (strcmp(get_annotation_name(an->payload), "AddressSpace") == 0) - as = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(an->payload)), false); + as = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(an->payload)), false); an = an->next; } Node* decl = global_var(ctx->rewriter.dst_module, annotations, type, get_declaration_name(node), as); diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index f2f5a59f9..24950a213 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -85,7 +85,7 @@ static const Node* infer_type(Context* ctx, const Type* type) { static const Node* infer_decl(Context* ctx, const Node* node) { assert(is_declaration(node)); - if (lookup_annotation(node, "SkipOnInfer")) + if (shd_lookup_annotation(node, "SkipOnInfer")) return NULL; IrArena* a = ctx->rewriter.dst_arena; diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index e63f18e96..555cfb15d 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -94,7 +94,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay const Node* decl = decls.nodes[i]; if (decl->tag != GlobalVariable_TAG) continue; - if (lookup_annotation(decl, "Constants")) { + if (shd_lookup_annotation(decl, "Constants")) { AddressSpace as = decl->payload.global_variable.address_space; switch (as) { case AsShaderStorageBufferObject: @@ -102,8 +102,8 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay default: continue; } - int set = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(lookup_annotation(decl, "DescriptorSet"))), false); - int binding = get_int_literal_value(*resolve_to_int_literal(get_annotation_value(lookup_annotation(decl, "DescriptorBinding"))), false); + int set = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "DescriptorSet"))), false); + int binding = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "DescriptorBinding"))), false); ProgramResourceInfo* res_info = shd_arena_alloc(program->arena, sizeof(ProgramResourceInfo)); *res_info = (ProgramResourceInfo) { @@ -140,9 +140,9 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay Nodes annotations = get_declaration_annotations(decl); for (size_t k = 0; k < annotations.count; k++) { const Node* a = annotations.nodes[k]; - if ((strcmp(get_annotation_name(a), "InitialValue") == 0) && resolve_to_int_literal(shd_first(get_annotation_values(a)))->value == j) { + if ((strcmp(get_annotation_name(a), "InitialValue") == 0) && resolve_to_int_literal(shd_first(shd_get_annotation_values(a)))->value == j) { constant_res_info->default_data = calloc(1, layout.size_in_bytes); - write_value(constant_res_info->default_data, get_annotation_values(a).nodes[1]); + write_value(constant_res_info->default_data, shd_get_annotation_values(a).nodes[1]); //printf("wowie"); } } @@ -286,7 +286,7 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) switch (node->tag) { case GlobalVariable_TAG: { - const Node* entry_point_args_annotation = lookup_annotation(node, "EntryPointArgs"); + const Node* entry_point_args_annotation = shd_lookup_annotation(node, "EntryPointArgs"); if (entry_point_args_annotation) { if (node->payload.global_variable.type->tag != RecordType_TAG) { shd_error_print("EntryPointArgs must be a struct\n"); @@ -304,7 +304,7 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) break; } case Function_TAG: { - if (lookup_annotation(node, "EntryPoint")) { + if (shd_lookup_annotation(node, "EntryPoint")) { if (node->payload.fun.params.count != 0) { shd_error_print("EntryPoint cannot have parameters\n"); return false; diff --git a/src/shady/annotation.c b/src/shady/annotation.c index cc349bfa7..d38891a1d 100644 --- a/src/shady/annotation.c +++ b/src/shady/annotation.c @@ -19,12 +19,12 @@ static const Node* search_annotations(const Node* decl, const char* name, size_t return NULL; } -const Node* lookup_annotation(const Node* decl, const char* name) { +const Node* shd_lookup_annotation(const Node* decl, const char* name) { size_t i = 0; return search_annotations(decl, name, &i); } -const Node* lookup_annotation_list(Nodes annotations, const char* name) { +const Node* shd_lookup_annotation_list(Nodes annotations, const char* name) { for (size_t i = 0; i < annotations.count; i++) { if (strcmp(get_annotation_name(annotations.nodes[i]), name) == 0) { return annotations.nodes[i]; @@ -33,14 +33,14 @@ const Node* lookup_annotation_list(Nodes annotations, const char* name) { return NULL; } -const Node* get_annotation_value(const Node* annotation) { +const Node* shd_get_annotation_value(const Node* annotation) { assert(annotation); if (annotation->tag != AnnotationValue_TAG) shd_error("This annotation does not have a single payload"); return annotation->payload.annotation_value.value; } -Nodes get_annotation_values(const Node* annotation) { +Nodes shd_get_annotation_values(const Node* annotation) { assert(annotation); if (annotation->tag != AnnotationValues_TAG) shd_error("This annotation does not have multiple payloads"); @@ -48,25 +48,25 @@ Nodes get_annotation_values(const Node* annotation) { } /// Gets the string literal attached to an annotation, if present. -const char* get_annotation_string_payload(const Node* annotation) { - const Node* payload = get_annotation_value(annotation); +const char* shd_get_annotation_string_payload(const Node* annotation) { + const Node* payload = shd_get_annotation_value(annotation); if (!payload) return NULL; if (payload->tag != StringLiteral_TAG) shd_error("Wrong annotation payload tag, expected a string literal") return payload->payload.string_lit.string; } -bool lookup_annotation_with_string_payload(const Node* decl, const char* annotation_name, const char* expected_payload) { +bool shd_lookup_annotation_with_string_payload(const Node* decl, const char* annotation_name, const char* expected_payload) { size_t i = 0; while (true) { const Node* next = search_annotations(decl, annotation_name, &i); if (!next) return false; - if (strcmp(get_annotation_string_payload(next), expected_payload) == 0) + if (strcmp(shd_get_annotation_string_payload(next), expected_payload) == 0) return true; } } -Nodes filter_out_annotation(IrArena* arena, Nodes annotations, const char* name) { +Nodes shd_filter_out_annotation(IrArena* arena, Nodes annotations, const char* name) { LARRAY(const Node*, new_annotations, annotations.count); size_t new_count = 0; for (size_t i = 0; i < annotations.count; i++) { @@ -77,7 +77,7 @@ Nodes filter_out_annotation(IrArena* arena, Nodes annotations, const char* name) return shd_nodes(arena, new_count, new_annotations); } -ExecutionModel execution_model_from_string(const char* string) { +ExecutionModel shd_execution_model_from_string(const char* string) { #define EM(n, _) if (strcmp(string, #n) == 0) return Em##n; EXECUTION_MODELS(EM) #undef EM diff --git a/src/shady/builtins.c b/src/shady/builtins.c index a73f6dc5a..d3269c983 100644 --- a/src/shady/builtins.c +++ b/src/shady/builtins.c @@ -66,10 +66,10 @@ Builtin shd_get_builtin_by_spv_id(SpvBuiltIn id) { } Builtin shd_get_decl_builtin(const Node* decl) { - const Node* a = lookup_annotation(decl, "Builtin"); + const Node* a = shd_lookup_annotation(decl, "Builtin"); if (!a) return BuiltinsCount; - String payload = get_annotation_string_payload(a); + String payload = shd_get_annotation_string_payload(a); return shd_get_builtin_by_name(payload); } diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index bf625e31a..a5d453102 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -16,7 +16,7 @@ static const Node* process(Context* ctx, const Node* node) { case Constant_TAG: if (!node->payload.constant.value) break; - if (!ctx->all && !lookup_annotation(node, "Inline")) + if (!ctx->all && !shd_lookup_annotation(node, "Inline")) break; return NULL; case RefDecl_TAG: { diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index a9931bf59..580f95c0d 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -172,7 +172,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Context fn_ctx = *ctx; fn_ctx.cfg = build_fn_cfg(node); fn_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); - fn_ctx.disable_lowering = lookup_annotation(node, "Internal"); + fn_ctx.disable_lowering = shd_lookup_annotation(node, "Internal"); ctx = &fn_ctx; Node* new = recreate_decl_header_identity(&ctx->rewriter, node); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index c45613f12..71fed4126 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -83,7 +83,7 @@ static const Node* process(Context* ctx, const Node* node) { return fun; Context ctx2 = *ctx; - ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; + ctx2.disable_lowering = shd_lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; if (ctx2.disable_lowering) { set_abstraction_body(fun, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); return fun; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 2a99ec3f0..d0ef549e5 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -25,7 +25,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { if (old->tag == Function_TAG) { Context ctx2 = *ctx; - ctx2.disable_lowering = lookup_annotation(old, "Leaf"); + ctx2.disable_lowering = shd_lookup_annotation(old, "Leaf"); ctx2.return_jp = NULL; if (!ctx2.disable_lowering && get_abstraction_body(old)) { @@ -43,7 +43,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .yield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, old->payload.fun.return_types)) }); - if (lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { + if (shd_lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { ctx2.return_jp = gen_ext_instruction(bb, "shady.internal", ShadyOpDefaultJoinPoint, shd_as_qualified_type(jp_type, true), shd_empty(a)); } else { @@ -107,7 +107,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { Call payload = old->payload.call; const Node* ocallee = payload.callee; // if we know the callee and it's a leaf - then we don't change the call - if (ocallee->tag == FnAddr_TAG && lookup_annotation(ocallee->payload.fn_addr.fn, "Leaf")) + if (ocallee->tag == FnAddr_TAG && shd_lookup_annotation(ocallee->payload.fn_addr.fn, "Leaf")) break; const Type* ocallee_type = ocallee->type; diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 5c4a3577e..889e5b097 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -25,7 +25,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Context sub_ctx = *ctx; if (node->tag == Function_TAG) { Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); - sub_ctx.disable_lowering = lookup_annotation(fun, "Structured"); + sub_ctx.disable_lowering = shd_lookup_annotation(fun, "Structured"); sub_ctx.current_fn = fun; sub_ctx.cfg = build_fn_cfg(node); set_abstraction_body(fun, rewrite_node(&sub_ctx.rewriter, node->payload.fun.body)); diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index b8c56edaa..3c24437e5 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -77,7 +77,7 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Function_TAG: - if (lookup_annotation(node, "EntryPoint") && node->payload.fun.params.count > 0) { + if (shd_lookup_annotation(node, "EntryPoint") && node->payload.fun.params.count > 0) { Node* new_entry_point = rewrite_entry_point_fun(ctx, node); const Node* arg_struct = generate_arg_struct(&ctx->rewriter, node, new_entry_point); set_abstraction_body(new_entry_point, rewrite_body(ctx, node, new_entry_point, arg_struct)); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 8bc4ff4cb..79516ebd5 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -336,7 +336,7 @@ static const Node* process_node(Context* ctx, const Node* old) { case GlobalVariable_TAG: { const GlobalVariable* old_gvar = &old->payload.global_variable; // Global variables into emulated address spaces become integer constants (to index into arrays used for emulation of said address space) - if (!lookup_annotation(old, "Logical") && is_as_emulated(ctx, old_gvar->address_space)) { + if (!shd_lookup_annotation(old, "Logical") && is_as_emulated(ctx, old_gvar->address_space)) { assert(false); } break; @@ -374,7 +374,7 @@ static Nodes collect_globals(Context* ctx, AddressSpace as) { const Node* decl = old_decls.nodes[i]; if (decl->tag != GlobalVariable_TAG) continue; if (decl->payload.global_variable.address_space != as) continue; - if (lookup_annotation(decl, "Logical")) continue; + if (shd_lookup_annotation(decl, "Logical")) continue; collected[members_count] = decl; members_count++; } diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 7c245b50c..5938554de 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -61,7 +61,7 @@ static const Node* process(Context* ctx, const Node* node) { .size = ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_declaration(ctx->rewriter.src_module, "SUBGROUPS_PER_WG"))) }); - assert(lookup_annotation(node, "Logical") && "All subgroup variables should be logical by now!"); + assert(shd_lookup_annotation(node, "Logical") && "All subgroup variables should be logical by now!"); Node* new = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations), atype, node->payload.global_variable.name, AsShared); register_processed(&ctx->rewriter, node, new); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 83ccd02ec..221b7e998 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -114,10 +114,10 @@ static const Node* process(Context* ctx, const Node* old) { ctx2.uses = create_fn_uses_map(old, (NcDeclaration | NcType)); ctx = &ctx2; - const Node* entry_point_annotation = lookup_annotation_list(old->payload.fun.annotations, "EntryPoint"); + const Node* entry_point_annotation = shd_lookup_annotation_list(old->payload.fun.annotations, "EntryPoint"); // Leave leaf-calls alone :) - ctx2.disable_lowering = lookup_annotation(old, "Leaf") || !old->payload.fun.body; + ctx2.disable_lowering = shd_lookup_annotation(old, "Leaf") || !old->payload.fun.body; if (ctx2.disable_lowering) { Node* fun = recreate_decl_header_identity(&ctx2.rewriter, old); if (old->payload.fun.body) { @@ -142,7 +142,7 @@ static const Node* process(Context* ctx, const Node* old) { String new_name = shd_format_string_arena(a->arena, "%s_indirect", old->payload.fun.name); - Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, 0, NULL), new_name, filter_out_annotation(a, new_annotations, "EntryPoint"), shd_nodes(a, 0, NULL)); + Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, 0, NULL), new_name, shd_filter_out_annotation(a, new_annotations, "EntryPoint"), shd_nodes(a, 0, NULL)); register_processed(&ctx->rewriter, old, fun); if (entry_point_annotation) @@ -376,7 +376,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { for (size_t i = 0; i < old_decls.count; i++) { const Node* decl = old_decls.nodes[i]; if (decl->tag == Function_TAG) { - if (lookup_annotation(decl, "Leaf")) + if (shd_lookup_annotation(decl, "Leaf")) continue; const Node* fn_lit = shd_uint32_literal(a, get_fn_ptr(ctx, decl)); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 1ffc820c0..6573427ce 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -34,10 +34,10 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case GlobalVariable_TAG: { - const Node* ba = lookup_annotation(node, "Builtin"); + const Node* ba = shd_lookup_annotation(node, "Builtin"); if (ba) { - Nodes filtered_as = rewrite_nodes(&ctx->rewriter, filter_out_annotation(a, node->payload.global_variable.annotations, "Builtin")); - Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); + Nodes filtered_as = rewrite_nodes(&ctx->rewriter, shd_filter_out_annotation(a, node->payload.global_variable.annotations, "Builtin")); + Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); switch (b) { case BuiltinSubgroupId: case BuiltinWorkgroupId: @@ -56,8 +56,8 @@ static const Node* process(Context* ctx, const Node* node) { case Function_TAG: { Context ctx2 = *ctx; ctx2.is_entry_point = false; - const Node* epa = lookup_annotation(node, "EntryPoint"); - if (epa && strcmp(get_annotation_string_payload(epa), "Compute") == 0) { + const Node* epa = shd_lookup_annotation(node, "EntryPoint"); + if (epa && strcmp(shd_get_annotation_string_payload(epa), "Compute") == 0) { ctx2.is_entry_point = true; assert(node->payload.fun.return_types.count == 0 && "entry points do not return at this stage"); @@ -67,7 +67,7 @@ static const Node* process(Context* ctx, const Node* node) { register_processed(&ctx->rewriter, node, wrapper); // recreate the old entry point, but this time it's not the entry point anymore - Nodes nannotations = filter_out_annotation(a, wannotations, "EntryPoint"); + Nodes nannotations = shd_filter_out_annotation(a, wannotations, "EntryPoint"); Nodes nparams = recreate_params(&ctx->rewriter, node->payload.fun.params); Node* inner = function(m, nparams, shd_format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, shd_empty(a)); register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index e5897697f..0d8961970 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -18,9 +18,9 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { switch (src->tag) { case GlobalVariable_TAG: { GlobalVariable global_variable = src->payload.global_variable; - const Node* ba = lookup_annotation_list(global_variable.annotations, "Builtin"); + const Node* ba = shd_lookup_annotation_list(global_variable.annotations, "Builtin"); if (ba) { - Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); assert(b != BuiltinsCount); const Type* expected_t = shd_get_builtin_type(a, b); const Type* actual_t = rewrite_node(&ctx->rewriter, src)->payload.global_variable.type; @@ -58,9 +58,9 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case GlobalVariable_TAG: { GlobalVariable global_variable = node->payload.global_variable; - const Node* ba = lookup_annotation_list(global_variable.annotations, "Builtin"); + const Node* ba = shd_lookup_annotation_list(global_variable.annotations, "Builtin"); if (ba) { - Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); assert(b != BuiltinsCount); if (ctx->builtins[b]) return ctx->builtins[b]; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 4aaa4b375..a30156773 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -177,7 +177,7 @@ static const Node* process(Context* ctx, const Node* old) { Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); Context fun_ctx = *ctx; fun_ctx.uses = create_fn_uses_map(old, (NcDeclaration | NcType)); - fun_ctx.disable_lowering = lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); + fun_ctx.disable_lowering = shd_lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); if (old->payload.fun.body) set_abstraction_body(fun, rewrite_node(&fun_ctx.rewriter, old->payload.fun.body)); destroy_uses_map(fun_ctx.uses); diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 15d61a774..7eb64f18c 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -33,9 +33,9 @@ static const Node* ignore_immediate_fn_addr(const Node* node) { } static bool is_call_potentially_inlineable(const Node* src_fn, const Node* dst_fn) { - if (lookup_annotation(src_fn, "Internal")) + if (shd_lookup_annotation(src_fn, "Internal")) return false; - if (lookup_annotation(dst_fn, "NoInline")) + if (shd_lookup_annotation(dst_fn, "NoInline")) return false; if (!dst_fn->payload.fun.body) return false; @@ -43,11 +43,11 @@ static bool is_call_potentially_inlineable(const Node* src_fn, const Node* dst_f } static bool is_call_safely_removable(const Node* fn) { - if (lookup_annotation(fn, "Internal")) + if (shd_lookup_annotation(fn, "Internal")) return false; - if (lookup_annotation(fn, "EntryPoint")) + if (shd_lookup_annotation(fn, "EntryPoint")) return false; - if (lookup_annotation(fn, "Exported")) + if (shd_lookup_annotation(fn, "Exported")) return false; return true; } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index ad96887f5..7230818ab 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -343,9 +343,9 @@ static const Node* process(Context* ctx, const Node* node) { Context ctx2 = *ctx; ctx2.dfs_stack = NULL; ctx2.control_stack = NULL; - bool is_builtin = lookup_annotation(node, "Builtin"); + bool is_builtin = shd_lookup_annotation(node, "Builtin"); bool is_leaf = false; - if (is_builtin || !node->payload.fun.body || lookup_annotation(node, "Structured") || setjmp(ctx2.bail)) { + if (is_builtin || !node->payload.fun.body || shd_lookup_annotation(node, "Structured") || setjmp(ctx2.bail)) { ctx2.lower = false; ctx2.rewriter.map = ctx->rewriter.map; if (node->payload.fun.body) @@ -384,7 +384,7 @@ static const Node* process(Context* ctx, const Node* node) { cj.fn(cj.payload); } - new->payload.fun.annotations = filter_out_annotation(a, new->payload.fun.annotations, "MaybeLeaf"); + new->payload.fun.annotations = shd_filter_out_annotation(a, new->payload.fun.annotations, "MaybeLeaf"); return new; } @@ -401,7 +401,7 @@ static const Node* process(Context* ctx, const Node* node) { if (callee->tag == FnAddr_TAG) { const Node* fn = rewrite_node(&ctx->rewriter, callee->payload.fn_addr.fn); // leave leaf calls alone - if (lookup_annotation(fn, "Leaf")) { + if (shd_lookup_annotation(fn, "Leaf")) { break; } } diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 2c1ba5fa2..b24376e5e 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -312,7 +312,7 @@ static const Node* process_node(Context* ctx, const Node* node) { case Function_TAG: { ctx = &new_context; ctx->current_fn = NULL; - if (!(lookup_annotation(node, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) + if (!(shd_lookup_annotation(node, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) break; ctx->current_fn = node; @@ -334,12 +334,12 @@ static const Node* process_node(Context* ctx, const Node* node) { break; } case BasicBlock_TAG: - if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) + if (!ctx->current_fn || !(shd_lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) break; return process_abstraction(ctx, node); case Branch_TAG: { Branch payload = node->payload.branch; - if (!ctx->current_fn || !(lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) + if (!ctx->current_fn || !(shd_lookup_annotation(ctx->current_fn, "Restructure") || ctx->config->input_cf.restructure_with_heuristics)) break; assert(ctx->fwd_cfg); diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 72ce6466c..8906ab149 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -27,7 +27,7 @@ static const Node* process(Context* ctx, const Node* node) { case Function_TAG: { Node* fun = recreate_decl_header_identity(r, node); Context ctx2 = *ctx; - ctx2.disable_lowering = lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; + ctx2.disable_lowering = shd_lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); if (!ctx2.disable_lowering) { diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 0e8f526a8..b8307caf2 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -31,9 +31,9 @@ static const Node* process(Context* ctx, const Node* node) { break; } case GlobalVariable_TAG: { - const Node* ba = lookup_annotation(node, "Builtin"); + const Node* ba = shd_lookup_annotation(node, "Builtin"); if (ba) { - Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); switch (b) { case BuiltinWorkgroupSize: return NULL; @@ -85,15 +85,15 @@ static void specialize_arena_config(const CompilerConfig* config, Module* src, A shd_error("Entry point not found") if (old_entry_point_decl->tag != Function_TAG) shd_error("%s is not a function", config->specialization.entry_point); - const Node* ep = lookup_annotation(old_entry_point_decl, "EntryPoint"); + const Node* ep = shd_lookup_annotation(old_entry_point_decl, "EntryPoint"); if (!ep) shd_error("%s is not annotated with @EntryPoint", config->specialization.entry_point); - switch (execution_model_from_string(get_annotation_string_payload(ep))) { - case EmNone: shd_error("Unknown entry point type: %s", get_annotation_string_payload(ep)) + switch (shd_execution_model_from_string(shd_get_annotation_string_payload(ep))) { + case EmNone: shd_error("Unknown entry point type: %s", shd_get_annotation_string_payload(ep)) case EmCompute: { - const Node* old_wg_size_annotation = lookup_annotation(old_entry_point_decl, "WorkgroupSize"); - assert(old_wg_size_annotation && old_wg_size_annotation->tag == AnnotationValues_TAG && get_annotation_values(old_wg_size_annotation).count == 3); - Nodes wg_size_nodes = get_annotation_values(old_wg_size_annotation); + const Node* old_wg_size_annotation = shd_lookup_annotation(old_entry_point_decl, "WorkgroupSize"); + assert(old_wg_size_annotation && old_wg_size_annotation->tag == AnnotationValues_TAG && shd_get_annotation_values(old_wg_size_annotation).count == 3); + Nodes wg_size_nodes = shd_get_annotation_values(old_wg_size_annotation); target->specializations.workgroup_size[0] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[0]), false); target->specializations.workgroup_size[1] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[1]), false); target->specializations.workgroup_size[2] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[2]), false); @@ -121,7 +121,7 @@ Module* specialize_entry_point(const CompilerConfig* config, Module* src) { Nodes old_decls = get_module_declarations(src); for (size_t i = 0; i < old_decls.count; i++) { const Node* old_decl = old_decls.nodes[i]; - if (lookup_annotation(old_decl, "RetainAfterSpecialization")) + if (shd_lookup_annotation(old_decl, "RetainAfterSpecialization")) rewrite_node(&ctx.rewriter, old_decl); } diff --git a/src/shady/print.c b/src/shady/print.c index 63973b834..6c315d3a3 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -887,11 +887,11 @@ static void print_terminator(PrinterCtx* ctx, const Node* node) { static void print_decl(PrinterCtx* ctx, const Node* node) { assert(is_declaration(node)); - if (!ctx->config.print_generated && lookup_annotation(node, "Generated")) + if (!ctx->config.print_generated && shd_lookup_annotation(node, "Generated")) return; - if (!ctx->config.print_internal && lookup_annotation(node, "Internal")) + if (!ctx->config.print_internal && shd_lookup_annotation(node, "Internal")) return; - if (!ctx->config.print_builtin && lookup_annotation(node, "Builtin")) + if (!ctx->config.print_builtin && shd_lookup_annotation(node, "Builtin")) return; PrinterCtx sub_ctx = *ctx; diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 751501a3c..50c4afbc9 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -243,7 +243,7 @@ void rewrite_module(Rewriter* rewriter) { assert(rewriter->dst_module != rewriter->src_module); Nodes old_decls = get_module_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { - if (!lookup_annotation(old_decls.nodes[i], "Exported")) continue; + if (!shd_lookup_annotation(old_decls.nodes[i], "Exported")) continue; rewrite_op_helper(rewriter, NcDeclaration, "decl", old_decls.nodes[i]); } } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 5ecf0f2de..0f11158e2 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -150,10 +150,10 @@ const Node* get_builtin(Module* m, Builtin b) { const Node* decl = decls.nodes[i]; if (decl->tag != GlobalVariable_TAG) continue; - const Node* a = lookup_annotation(decl, "Builtin"); + const Node* a = shd_lookup_annotation(decl, "Builtin"); if (!a) continue; - String builtin_name = get_annotation_string_payload(a); + String builtin_name = shd_get_annotation_string_payload(a); assert(builtin_name); if (strcmp(builtin_name, shd_get_builtin_name(b)) == 0) return decl; @@ -188,9 +188,9 @@ bool is_builtin_load_op(const Node* n, Builtin* out) { if (src->tag == RefDecl_TAG) src = src->payload.ref_decl.decl; if (src->tag == GlobalVariable_TAG) { - const Node* a = lookup_annotation(src, "Builtin"); + const Node* a = shd_lookup_annotation(src, "Builtin"); if (a) { - String bn = get_annotation_string_payload(a); + String bn = shd_get_annotation_string_payload(a); assert(bn); Builtin b = shd_get_builtin_by_name(bn); if (b != BuiltinsCount) { diff --git a/src/shady/type.c b/src/shady/type.c index da8abf6c9..afecc8703 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -1246,9 +1246,9 @@ const Type* check_type_basic_block(IrArena* arena, BasicBlock bb) { const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_variable) { assert(is_type(global_variable.type)); - const Node* ba = lookup_annotation_list(global_variable.annotations, "Builtin"); + const Node* ba = shd_lookup_annotation_list(global_variable.annotations, "Builtin"); if (ba && arena->config.validate_builtin_types) { - Builtin b = shd_get_builtin_by_name(get_annotation_string_payload(ba)); + Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); assert(b != BuiltinsCount); const Type* t = shd_get_builtin_type(arena, b); if (t != global_variable.type) { @@ -1266,7 +1266,7 @@ const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_var return ptr_type(arena, (PtrType) { .pointed_type = global_variable.type, .address_space = global_variable.address_space, - .is_reference = lookup_annotation_list(global_variable.annotations, "Logical"), + .is_reference = shd_lookup_annotation_list(global_variable.annotations, "Logical"), }); } From 7b4b9525925a0cc6d09ac3e287421b8cc5394fb6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 13:52:18 +0200 Subject: [PATCH 619/693] add _shd prefix to more internal stuff --- src/shady/api/generator_type.c | 2 +- src/shady/constructors.c | 8 ++++---- src/shady/fold.c | 4 ++-- src/shady/fold.h | 2 +- src/shady/generator_constructors.c | 2 +- src/shady/generator_type.c | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/shady/api/generator_type.c b/src/shady/api/generator_type.c index 46a596995..aa72bda2e 100644 --- a/src/shady/api/generator_type.c +++ b/src/shady/api/generator_type.c @@ -30,5 +30,5 @@ void generate(Growy* g, json_object* src) { free(alloc); } - shd_growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node);\n"); + shd_growy_append_formatted(g, "const Type* _shd_check_type_generated(IrArena* a, const Node* node);\n"); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index ab858d6d9..feea55827 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -15,14 +15,14 @@ bool shd_compare_nodes(Nodes* a, Nodes* b); static void pre_construction_validation(IrArena* arena, Node* node); -const Node* fold_node_operand(NodeTag tag, NodeClass, String, const Node* op); +const Node* _shd_fold_node_operand(NodeTag tag, NodeClass nc, String opname, const Node* op); -const Type* check_type_generated(IrArena* a, const Node* node); +const Type* _shd_check_type_generated(IrArena* a, const Node* node); Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh) { pre_construction_validation(arena, &node); if (arena->config.check_types) - node.type = check_type_generated(arena, &node); + node.type = _shd_check_type_generated(arena, &node); if (pfresh) *pfresh = false; @@ -39,7 +39,7 @@ Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh) { *pfresh = true; if (arena->config.allow_fold) { - Node* folded = (Node*) fold_node(arena, ptr); + Node* folded = (Node*) _shd_fold_node(arena, ptr); if (folded != ptr) { // The folding process simplified the node, we store a mapping to that simplified node and bail out ! shd_set_insert_get_result(Node*, arena->node_set, folded); diff --git a/src/shady/fold.c b/src/shady/fold.c index 350401c80..111c78438 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -393,7 +393,7 @@ static bool is_unreachable_destination(const Node* j) { return b->tag == Unreachable_TAG; } -const Node* fold_node(IrArena* arena, const Node* node) { +const Node* _shd_fold_node(IrArena* arena, const Node* node) { const Node* const original_node = node; node = fold_memory_poison(arena, node); node = fold_simplify_ptr_operand(node); @@ -470,7 +470,7 @@ const Node* fold_node(IrArena* arena, const Node* node) { return node; } -const Node* fold_node_operand(NodeTag tag, NodeClass nc, String opname, const Node* op) { +const Node* _shd_fold_node_operand(NodeTag tag, NodeClass nc, String opname, const Node* op) { if (!op) return NULL; if (op->tag == MemAndValue_TAG) { diff --git a/src/shady/fold.h b/src/shady/fold.h index b8359dfc8..f21854e4b 100644 --- a/src/shady/fold.h +++ b/src/shady/fold.h @@ -3,6 +3,6 @@ #include "ir_private.h" -const Node* fold_node(IrArena* arena, const Node* instruction); +const Node* _shd_fold_node(IrArena* arena, const Node* node); #endif diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index 674649dbe..a0e27c447 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -45,7 +45,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { if (!list) shd_growy_append_formatted(g, "\t\t\tconst Node** pop = &node->payload.%s.%s;\n", snake_name, op_name); - shd_growy_append_formatted(g, "\t\t\t*pop = fold_node_operand(%s_TAG, Nc%s, \"%s\", *pop);\n", name, cap, op_name); + shd_growy_append_formatted(g, "\t\t\t*pop = _shd_fold_node_operand(%s_TAG, Nc%s, \"%s\", *pop);\n", name, cap, op_name); if (!(json_object_get_boolean(json_object_object_get(op, "nullable")) || json_object_get_boolean(json_object_object_get(op, "ignore")))) { shd_growy_append_formatted(g, "%s\t\t\tif (!*pop) {\n", extra); diff --git a/src/shady/generator_type.c b/src/shady/generator_type.c index f25d87d5c..eb247892c 100644 --- a/src/shady/generator_type.c +++ b/src/shady/generator_type.c @@ -5,7 +5,7 @@ void generate(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); - shd_growy_append_formatted(g, "const Type* check_type_generated(IrArena* a, const Node* node) {\n"); + shd_growy_append_formatted(g, "const Type* _shd_check_type_generated(IrArena* a, const Node* node) {\n"); shd_growy_append_formatted(g, "\tswitch(node->tag) {\n"); for (size_t i = 0; i < json_object_array_length(nodes); i++) { json_object* node = json_object_array_get_idx(nodes, i); From 0d27ff0271a27c9c837f9e2fc2db09b8ec5dfcfa Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 13:56:39 +0200 Subject: [PATCH 620/693] rewrite: added shd_ prefix --- src/backend/spirv/emit_spv_type.c | 12 +- src/backend/spirv/spirv_lift_globals_ssbo.c | 26 ++--- src/backend/spirv/spirv_map_entrypoint_args.c | 16 +-- src/frontend/llvm/l2s_postprocess.c | 34 +++--- src/frontend/slim/bind.c | 92 +++++++-------- src/frontend/slim/infer.c | 44 +++---- src/frontend/slim/normalize.c | 14 +-- src/shady/passes/cleanup.c | 34 +++--- src/shady/passes/eliminate_constants.c | 10 +- src/shady/passes/import.c | 24 ++-- src/shady/passes/lcssa.c | 30 ++--- src/shady/passes/lift_everything.c | 36 +++--- src/shady/passes/lift_indirect_targets.c | 52 ++++----- src/shady/passes/lower_alloca.c | 20 ++-- src/shady/passes/lower_callf.c | 44 +++---- src/shady/passes/lower_cf_instrs.c | 52 ++++----- src/shady/passes/lower_decay_ptrs.c | 10 +- src/shady/passes/lower_entrypoint_args.c | 20 ++-- src/shady/passes/lower_fill.c | 12 +- src/shady/passes/lower_generic_globals.c | 20 ++-- src/shady/passes/lower_generic_ptrs.c | 22 ++-- src/shady/passes/lower_int64.c | 10 +- src/shady/passes/lower_lea.c | 24 ++-- src/shady/passes/lower_logical_pointers.c | 36 +++--- src/shady/passes/lower_mask.c | 12 +- src/shady/passes/lower_memcpy.c | 24 ++-- src/shady/passes/lower_memory_layout.c | 16 +-- src/shady/passes/lower_nullptr.c | 10 +- src/shady/passes/lower_physical_ptrs.c | 38 +++--- src/shady/passes/lower_stack.c | 32 +++--- src/shady/passes/lower_subgroup_ops.c | 12 +- src/shady/passes/lower_subgroup_vars.c | 32 +++--- src/shady/passes/lower_switch_btree.c | 16 +-- src/shady/passes/lower_tailcalls.c | 68 +++++------ src/shady/passes/lower_vec_arr.c | 16 +-- src/shady/passes/lower_workgroups.c | 42 +++---- src/shady/passes/mark_leaf_functions.c | 18 +-- src/shady/passes/normalize_builtins.c | 18 +-- src/shady/passes/opt_demote_alloca.c | 42 +++---- src/shady/passes/opt_inline.c | 36 +++--- src/shady/passes/opt_mem2reg.c | 16 +-- src/shady/passes/opt_restructure.c | 62 +++++----- src/shady/passes/reconvergence_heuristics.c | 66 +++++------ src/shady/passes/remove_critical_edges.c | 14 +-- src/shady/passes/scope2control.c | 32 +++--- src/shady/passes/scope_heuristic.c | 24 ++-- src/shady/passes/setup_stack_frames.c | 18 +-- src/shady/passes/specialize_entry_point.c | 12 +- src/shady/passes/specialize_execution_model.c | 10 +- src/shady/rewrite.c | 108 +++++++++--------- src/shady/rewrite.h | 59 +++++----- src/shady/transform/ir_gen_helpers.c | 2 +- 52 files changed, 772 insertions(+), 777 deletions(-) diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index c04b73eb5..4ca1a4514 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -42,20 +42,20 @@ SpvStorageClass spv_emit_addr_space(Emitter* emitter, AddressSpace address_space static const Node* rewrite_normalize(Rewriter* rewriter, const Node* node) { if (!is_type(node)) { - register_processed(rewriter, node, node); + shd_register_processed(rewriter, node, node); return node; } switch (node->tag) { - case QualifiedType_TAG: return qualified_type(rewriter->dst_arena, (QualifiedType) { .type = rewrite_node(rewriter, node->payload.qualified_type.type), .is_uniform = false }); - default: return recreate_node_identity(rewriter, node); + case QualifiedType_TAG: return qualified_type(rewriter->dst_arena, (QualifiedType) { .type = shd_rewrite_node(rewriter, node->payload.qualified_type.type), .is_uniform = false }); + default: return shd_recreate_node(rewriter, node); } } const Type* spv_normalize_type(Emitter* emitter, const Type* type) { - Rewriter rewriter = create_node_rewriter(emitter->module, emitter->module, rewrite_normalize); - const Node* rewritten = rewrite_node(&rewriter, type); - destroy_rewriter(&rewriter); + Rewriter rewriter = shd_create_node_rewriter(emitter->module, emitter->module, rewrite_normalize); + const Node* rewritten = shd_rewrite_node(&rewriter, type); + shd_destroy_rewriter(&rewriter); return rewritten; } diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index c3f2ec9c6..a7d1785fb 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -21,16 +21,16 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Function_TAG: { - Node* newfun = recreate_decl_header_identity(r, node); + Node* newfun = shd_recreate_node_head(r, node); if (get_abstraction_body(node)) { Context functx = *ctx; functx.rewriter.map = shd_clone_dict(functx.rewriter.map); shd_dict_clear(functx.rewriter.map); - register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); + shd_register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); - register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); - set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); + shd_register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); + set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, shd_empty(a)))); shd_destroy_dict(functx.rewriter.map); @@ -42,7 +42,7 @@ static const Node* process(Context* ctx, const Node* node) { if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) break; assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); - const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), shd_int32_literal(a, 0), shd_singleton(rewrite_node(&ctx->rewriter, odecl))); + const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), shd_int32_literal(a, 0), shd_singleton(shd_rewrite_node(&ctx->rewriter, odecl))); const Node* ptr = gen_load(ctx->bb, ptr_addr); return ptr; } @@ -56,10 +56,10 @@ static const Node* process(Context* ctx, const Node* node) { if (is_declaration(node)) { Context declctx = *ctx; declctx.bb = NULL; - return recreate_node_identity(&declctx.rewriter, node); + return shd_recreate_node(&declctx.rewriter, node); } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -68,7 +68,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; @@ -89,10 +89,10 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) continue; - member_tys[lifted_globals_count] = rewrite_node(&ctx.rewriter, odecl->type); + member_tys[lifted_globals_count] = shd_rewrite_node(&ctx.rewriter, odecl->type); member_names[lifted_globals_count] = get_declaration_name(odecl); - register_processed(&ctx.rewriter, odecl, shd_int32_literal(a, lifted_globals_count)); + shd_register_processed(&ctx.rewriter, odecl, shd_int32_literal(a, lifted_globals_count)); lifted_globals_count++; } @@ -105,7 +105,7 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul ctx.lifted_globals_decl = global_var(dst, annotations, lifted_globals_struct_t, "lifted_globals", AsShaderStorageBufferObject); } - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); lifted_globals_count = 0; for (size_t i = 0; i < old_decls.count; i++) { @@ -115,12 +115,12 @@ Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Modul if (odecl->payload.global_variable.init) ctx.lifted_globals_decl->payload.global_variable.annotations = shd_nodes_append(a, ctx.lifted_globals_decl->payload.global_variable.annotations, annotation_values(a, (AnnotationValues) { .name = "InitialValue", - .values = mk_nodes(a, shd_int32_literal(a, lifted_globals_count), rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) + .values = mk_nodes(a, shd_int32_literal(a, lifted_globals_count), shd_rewrite_node(&ctx.rewriter, odecl->payload.global_variable.init)) })); lifted_globals_count++; } - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index d8ee9f58b..e6ac76aab 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -19,12 +19,12 @@ static const Node* rewrite_args_type(Rewriter* rewriter, const Node* old_type) { shd_error("EntryPointArgs type must be a plain record type"); const Node* new_type = record_type(a, (RecordType) { - .members = rewrite_nodes(rewriter, old_type->payload.record_type.members), + .members = shd_rewrite_nodes(rewriter, old_type->payload.record_type.members), .names = old_type->payload.record_type.names, .special = DecorateBlock }); - register_processed(rewriter, old_type, new_type); + shd_register_processed(rewriter, old_type, new_type); return new_type; } @@ -36,7 +36,7 @@ static const Node* process(Context* ctx, const Node* node) { if (node->payload.global_variable.address_space != AsExternal) shd_error("EntryPointArgs address space must be extern"); - Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations); + Nodes annotations = shd_rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations); const Node* type = rewrite_args_type(&ctx->rewriter, node->payload.global_variable.type); const Node* new_var = global_var(ctx->rewriter.dst_module, @@ -46,7 +46,7 @@ static const Node* process(Context* ctx, const Node* node) { AsPushConstant ); - register_processed(&ctx->rewriter, node, new_var); + shd_register_processed(&ctx->rewriter, node, new_var); return new_var; } @@ -54,7 +54,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* spirv_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -62,10 +62,10 @@ Module* spirv_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Mod IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 93deb737f..9876b9c05 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -28,9 +28,9 @@ static Nodes remake_params(Context* ctx, Nodes old) { const Type* t = NULL; if (node->payload.param.type) { if (node->payload.param.type->tag == QualifiedType_TAG) - t = rewrite_node(r, node->payload.param.type); + t = shd_rewrite_node(r, node->payload.param.type); else - t = shd_as_qualified_type(rewrite_node(r, node->payload.param.type), false); + t = shd_as_qualified_type(shd_rewrite_node(r, node->payload.param.type), false); } nvars[i] = param(a, t, node->payload.param.name); assert(nvars[i]->tag == Param_TAG); @@ -46,7 +46,7 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(false); } case Constant_TAG: { - Node* new = (Node*) recreate_node_identity(r, node); + Node* new = (Node*) shd_recreate_node(r, node); BodyBuilder* bb = begin_block_pure(a); const Node* value = new->payload.constant.value; value = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(value)); @@ -79,17 +79,17 @@ static const Node* process_node(Context* ctx, const Node* node) { old_annotations = shd_nodes_append(a, old_annotations, an->payload); an = an->next; } - register_processed_list(r, node->payload.fun.params, new_params); - Nodes new_annotations = rewrite_nodes(r, old_annotations); - Node* decl = function(ctx->rewriter.dst_module, new_params, get_abstraction_name(node), new_annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); - register_processed(&ctx->rewriter, node, decl); + shd_register_processed_list(r, node->payload.fun.params, new_params); + Nodes new_annotations = shd_rewrite_nodes(r, old_annotations); + Node* decl = function(ctx->rewriter.dst_module, new_params, get_abstraction_name(node), new_annotations, shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); + shd_register_processed(&ctx->rewriter, node, decl); if (primop_intrinsic != PRIMOPS_COUNT) { set_abstraction_body(decl, fn_ret(a, (Return) { .args = shd_singleton(prim_op_helper(a, primop_intrinsic, shd_empty(a), get_abstraction_params(decl))), .mem = get_abstraction_mem(decl), })); } else if (get_abstraction_body(node)) - set_abstraction_body(decl, rewrite_node(r, get_abstraction_body(node))); + set_abstraction_body(decl, shd_rewrite_node(r, get_abstraction_body(node))); return decl; } case GlobalVariable_TAG: { @@ -97,12 +97,12 @@ static const Node* process_node(Context* ctx, const Node* node) { // return NULL; AddressSpace as = node->payload.global_variable.address_space; const Node* old_init = node->payload.global_variable.init; - Nodes annotations = rewrite_nodes(r, node->payload.global_variable.annotations); - const Type* type = rewrite_node(r, node->payload.global_variable.type); + Nodes annotations = shd_rewrite_nodes(r, node->payload.global_variable.annotations); + const Type* type = shd_rewrite_node(r, node->payload.global_variable.type); ParsedAnnotation* an = find_annotation(ctx->p, node); AddressSpace old_as = as; while (an) { - annotations = shd_nodes_append(a, annotations, rewrite_node(r, an->payload)); + annotations = shd_nodes_append(a, annotations, shd_rewrite_node(r, an->payload)); if (strcmp(get_annotation_name(an->payload), "Builtin") == 0) old_init = NULL; if (strcmp(get_annotation_name(an->payload), "AddressSpace") == 0) @@ -121,21 +121,21 @@ static const Node* process_node(Context* ctx, const Node* node) { result = c; } - register_processed(r, node, result); + shd_register_processed(r, node, result); if (old_init) - decl->payload.global_variable.init = rewrite_node(r, old_init); + decl->payload.global_variable.init = shd_rewrite_node(r, old_init); return result; } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } void postprocess(Parser* p, Module* src, Module* dst) { assert(src != dst); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = p->config, .p = p, .arena = shd_new_arena(), @@ -143,7 +143,7 @@ void postprocess(Parser* p, Module* src, Module* dst) { ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); shd_destroy_arena(ctx.arena); - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); } diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 6385497a7..981c9e032 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -60,7 +60,7 @@ static Resolved resolve_using_name(Context* ctx, const char* name) { Context top_ctx = *ctx; top_ctx.current_function = NULL; top_ctx.local_variables = NULL; - const Node* decl = rewrite_node(&top_ctx.rewriter, old_decl); + const Node* decl = shd_rewrite_node(&top_ctx.rewriter, old_decl); return (Resolved) { .is_var = decl->tag == GlobalVariable_TAG, .node = decl @@ -98,20 +98,20 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { const Node* src_ptr = get_node_address_maybe(ctx, shd_first(payload.operands)); if (src_ptr == NULL) return NULL; - const Node* index = rewrite_node(&ctx->rewriter, payload.operands.nodes[1]); + const Node* index = shd_rewrite_node(&ctx->rewriter, payload.operands.nodes[1]); return mem_and_value(a, (MemAndValue) { - .mem = rewrite_node(r, payload.mem), + .mem = shd_rewrite_node(r, payload.mem), .value = ptr_composite_element(a, (PtrCompositeElement) { .ptr = src_ptr, .index = index }), }); } else if (payload.opcode == SlimOpDereference) { assert(payload.operands.count == 1); return mem_and_value(a, (MemAndValue) { - .mem = rewrite_node(r, payload.mem), - .value = rewrite_node(&ctx->rewriter, shd_first(payload.operands)), + .mem = shd_rewrite_node(r, payload.mem), + .value = shd_rewrite_node(&ctx->rewriter, shd_first(payload.operands)), }); } else if (payload.opcode == SlimOpUnbound) { if (payload.mem) - rewrite_node(&ctx->rewriter, payload.mem); + shd_rewrite_node(&ctx->rewriter, payload.mem); Resolved entry = resolve_using_name(ctx, get_string_literal(a, shd_first(payload.operands))); // can't take the address if it's not a var! if (!entry.is_var) @@ -135,13 +135,13 @@ static const Node* get_node_address(Context* ctx, const Node* node) { static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; - BodyBuilder* bb = instr.mem ? begin_body_with_mem(a, rewrite_node(r, instr.mem)) : begin_block_pure(a); + BodyBuilder* bb = instr.mem ? begin_body_with_mem(a, shd_rewrite_node(r, instr.mem)) : begin_block_pure(a); switch (instr.opcode) { case SlimOpBindVal: { size_t names_count = instr.operands.count - 1; const Node** names = &instr.operands.nodes[1]; - const Node* value = rewrite_node(r, shd_first(instr.operands)); + const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); Nodes results = deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = get_string_literal(a, names[i]); @@ -154,13 +154,13 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { size_t names_count = (instr.operands.count - 1) / 2; const Node** names = &instr.operands.nodes[1]; const Node** types = &instr.operands.nodes[1 + names_count]; - const Node* value = rewrite_node(r, shd_first(instr.operands)); + const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); Nodes results = deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = get_string_literal(a, names[i]); const Type* type_annotation = types[i]; assert(type_annotation); - const Node* alloca = stack_alloc(a, (StackAlloc) { .type = rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); + const Node* alloca = stack_alloc(a, (StackAlloc) { .type = shd_rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; set_value_name(ptr, name); bind_instruction_outputs_count(bb, store(a, (Store) { .ptr = ptr, .value = results.nodes[0], .mem = bb_mem(bb) }), 0); @@ -177,9 +177,9 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { LARRAY(Node*, bbs, names_count); for (size_t i = 0; i < names_count; i++) { String name = get_string_literal(a, names[i]); - Nodes nparams = recreate_params(r, get_abstraction_params(conts[i])); + Nodes nparams = shd_recreate_params(r, get_abstraction_params(conts[i])); bbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(conts[i])); - register_processed(r, conts[i], bbs[i]); + shd_register_processed(r, conts[i], bbs[i]); add_binding(ctx, false, name, bbs[i]); shd_log_fmt(DEBUGV, "Bound continuation '%s'\n", name); } @@ -193,7 +193,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { if (param_name) add_binding(&cont_ctx, false, param_name, bb_param); } - set_abstraction_body(bbs[i], rewrite_node(&cont_ctx.rewriter, get_abstraction_body(conts[i]))); + set_abstraction_body(bbs[i], shd_rewrite_node(&cont_ctx.rewriter, get_abstraction_body(conts[i]))); } } } @@ -206,38 +206,38 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { switch (decl->tag) { case GlobalVariable_TAG: { const GlobalVariable* ogvar = &decl->payload.global_variable; - Node* bound = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, ogvar->annotations), rewrite_node(&ctx->rewriter, ogvar->type), ogvar->name, ogvar->address_space); - register_processed(&ctx->rewriter, decl, bound); - bound->payload.global_variable.init = rewrite_node(&ctx->rewriter, decl->payload.global_variable.init); + Node* bound = global_var(ctx->rewriter.dst_module, shd_rewrite_nodes(&ctx->rewriter, ogvar->annotations), shd_rewrite_node(&ctx->rewriter, ogvar->type), ogvar->name, ogvar->address_space); + shd_register_processed(&ctx->rewriter, decl, bound); + bound->payload.global_variable.init = shd_rewrite_node(&ctx->rewriter, decl->payload.global_variable.init); return bound; } case Constant_TAG: { const Constant* cnst = &decl->payload.constant; - Node* bound = constant(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, cnst->annotations), rewrite_node(&ctx->rewriter, decl->payload.constant.type_hint), cnst->name); - register_processed(&ctx->rewriter, decl, bound); - bound->payload.constant.value = rewrite_node(&ctx->rewriter, decl->payload.constant.value); + Node* bound = constant(ctx->rewriter.dst_module, shd_rewrite_nodes(&ctx->rewriter, cnst->annotations), shd_rewrite_node(&ctx->rewriter, decl->payload.constant.type_hint), cnst->name); + shd_register_processed(&ctx->rewriter, decl, bound); + bound->payload.constant.value = shd_rewrite_node(&ctx->rewriter, decl->payload.constant.value); return bound; } case Function_TAG: { - Nodes new_fn_params = recreate_params(&ctx->rewriter, decl->payload.fun.params); - Node* bound = function(ctx->rewriter.dst_module, new_fn_params, decl->payload.fun.name, rewrite_nodes(&ctx->rewriter, decl->payload.fun.annotations), rewrite_nodes(&ctx->rewriter, decl->payload.fun.return_types)); - register_processed(&ctx->rewriter, decl, bound); + Nodes new_fn_params = shd_recreate_params(&ctx->rewriter, decl->payload.fun.params); + Node* bound = function(ctx->rewriter.dst_module, new_fn_params, decl->payload.fun.name, shd_rewrite_nodes(&ctx->rewriter, decl->payload.fun.annotations), shd_rewrite_nodes(&ctx->rewriter, decl->payload.fun.return_types)); + shd_register_processed(&ctx->rewriter, decl, bound); Context fn_ctx = *ctx; for (size_t i = 0; i < new_fn_params.count; i++) { add_binding(&fn_ctx, false, decl->payload.fun.params.nodes[i]->payload.param.name, new_fn_params.nodes[i]); } - register_processed_list(&ctx->rewriter, decl->payload.fun.params, new_fn_params); + shd_register_processed_list(&ctx->rewriter, decl->payload.fun.params, new_fn_params); if (decl->payload.fun.body) { fn_ctx.current_function = bound; - set_abstraction_body(bound, rewrite_node(&fn_ctx.rewriter, decl->payload.fun.body)); + set_abstraction_body(bound, shd_rewrite_node(&fn_ctx.rewriter, decl->payload.fun.body)); } return bound; } case NominalType_TAG: { - Node* bound = nominal_type(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, decl->payload.nom_type.annotations), decl->payload.nom_type.name); - register_processed(&ctx->rewriter, decl, bound); - bound->payload.nom_type.body = rewrite_node(&ctx->rewriter, decl->payload.nom_type.body); + Node* bound = nominal_type(ctx->rewriter.dst_module, shd_rewrite_nodes(&ctx->rewriter, decl->payload.nom_type.annotations), decl->payload.nom_type.name); + shd_register_processed(&ctx->rewriter, decl, bound); + bound->payload.nom_type.body = shd_rewrite_node(&ctx->rewriter, decl->payload.nom_type.body); return bound; } default: shd_error("unknown declaration kind"); @@ -288,7 +288,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { case Param_TAG: shd_error("the binders should be handled such that this node is never reached"); case BasicBlock_TAG: { assert(is_basic_block(node)); - Nodes new_params = recreate_params(&ctx->rewriter, node->payload.basic_block.params); + Nodes new_params = shd_recreate_params(&ctx->rewriter, node->payload.basic_block.params); String name = node->payload.basic_block.name; Node* new_bb = basic_block(a, new_params, name); Context bb_ctx = *ctx; @@ -300,9 +300,9 @@ static const Node* bind_node(Context* ctx, const Node* node) { if (param_name) add_binding(ctx, false, param_name, new_params.nodes[i]); } - register_processed(&ctx->rewriter, node, new_bb); - register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new_params); - set_abstraction_body(new_bb, rewrite_node(&ctx->rewriter, node->payload.basic_block.body)); + shd_register_processed(&ctx->rewriter, node, new_bb); + shd_register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new_params); + set_abstraction_body(new_bb, shd_rewrite_node(&ctx->rewriter, node->payload.basic_block.body)); return new_bb; } case ExtInstr_TAG: { @@ -311,42 +311,42 @@ static const Node* bind_node(Context* ctx, const Node* node) { switch ((SlimFrontEndOpCodes) payload.opcode) { case SlimOpDereference: if (!is_used_as_value(ctx, node)) - return rewrite_node(r, payload.mem); + return shd_rewrite_node(r, payload.mem); return load(a, (Load) { - .ptr = rewrite_node(r, shd_first(payload.operands)), - .mem = rewrite_node(r, payload.mem), + .ptr = shd_rewrite_node(r, shd_first(payload.operands)), + .mem = shd_rewrite_node(r, payload.mem), }); case SlimOpAssign: { const Node* target_ptr = get_node_address(ctx, payload.operands.nodes[0]); assert(target_ptr); - const Node* value = rewrite_node(r, payload.operands.nodes[1]); - return store(a, (Store) { .ptr = target_ptr, .value = value, .mem = rewrite_node(r, payload.mem) }); + const Node* value = shd_rewrite_node(r, payload.operands.nodes[1]); + return store(a, (Store) { .ptr = target_ptr, .value = value, .mem = shd_rewrite_node(r, payload.mem) }); } case SlimOpAddrOf: { const Node* target_ptr = get_node_address(ctx, payload.operands.nodes[0]); - return mem_and_value(a, (MemAndValue) { .value = target_ptr, .mem = rewrite_node(r, payload.mem) }); + return mem_and_value(a, (MemAndValue) { .value = target_ptr, .mem = shd_rewrite_node(r, payload.mem) }); } case SlimOpSubscript: { const Node* ptr = get_node_address_maybe(ctx, node); if (ptr) return load(a, (Load) { .ptr = ptr, - .mem = rewrite_node(r, payload.mem) + .mem = shd_rewrite_node(r, payload.mem) }); return mem_and_value(a, (MemAndValue) { .value = prim_op(a, (PrimOp) { .op = extract_op, - .operands = mk_nodes(a, rewrite_node(r, payload.operands.nodes[0]), rewrite_node(r, payload.operands.nodes[1])) + .operands = mk_nodes(a, shd_rewrite_node(r, payload.operands.nodes[0]), shd_rewrite_node(r, payload.operands.nodes[1])) }), - .mem = rewrite_node(r, payload.mem) } + .mem = shd_rewrite_node(r, payload.mem) } ); } case SlimOpUnbound: { const Node* mem = NULL; if (payload.mem) { if (!is_used_as_value(ctx, node)) - return rewrite_node(r, payload.mem); - mem = rewrite_node(r, payload.mem); + return shd_rewrite_node(r, payload.mem); + mem = shd_rewrite_node(r, payload.mem); } Resolved entry = resolve_using_name(ctx, get_string_literal(a, shd_first(payload.operands))); if (entry.is_var) { @@ -363,7 +363,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* slim_pass_bind(SHADY_UNUSED const CompilerConfig* compiler_config, Module* src) { @@ -374,14 +374,14 @@ Module* slim_pass_bind(SHADY_UNUSED const CompilerConfig* compiler_config, Modul Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) bind_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) bind_node), .local_variables = NULL, .current_function = NULL, .uses = create_module_uses_map(src, 0), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); destroy_uses_map(ctx.uses); return dst; } diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 24950a213..2b73f09b6 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -38,13 +38,13 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Node* static const Node* infer(Context* ctx, const Node* node, const Type* expect) { Context ctx2 = *ctx; ctx2.expected_type = expect; - return rewrite_node(&ctx2.rewriter, node); + return shd_rewrite_node(&ctx2.rewriter, node); } static Nodes infer_nodes(Context* ctx, Nodes nodes) { Context ctx2 = *ctx; ctx2.expected_type = NULL; - return rewrite_nodes(&ctx->rewriter, nodes); + return shd_rewrite_nodes(&ctx->rewriter, nodes); } #define rewrite_node shd_error("don't use this directly, use the 'infer' and 'infer_node' helpers") @@ -79,7 +79,7 @@ static const Node* infer_type(Context* ctx, const Type* type) { // element_type = unit_type(a); return ptr_type(a, (PtrType) { .pointed_type = element_type, .address_space = type->payload.ptr_type.address_space }); } - default: return recreate_node_identity(&ctx->rewriter, type); + default: return shd_recreate_node(&ctx->rewriter, type); } } @@ -98,12 +98,12 @@ static const Node* infer_decl(Context* ctx, const Node* node) { const Param* old_param = &node->payload.fun.params.nodes[i]->payload.param; const Type* imported_param_type = infer(ctx, old_param->type, NULL); nparams[i] = param(a, imported_param_type, old_param->name); - register_processed(&body_context.rewriter, node->payload.fun.params.nodes[i], nparams[i]); + shd_register_processed(&body_context.rewriter, node->payload.fun.params.nodes[i], nparams[i]); } Nodes nret_types = annotate_all_types(a, infer_nodes(ctx, node->payload.fun.return_types), false); Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, node->payload.fun.params.count, nparams), string(a, node->payload.fun.name), infer_nodes(ctx, node->payload.fun.annotations), nret_types); - register_processed(&ctx->rewriter, node, fun); + shd_register_processed(&ctx->rewriter, node, fun); body_context.current_fn = fun; set_abstraction_body(fun, infer(&body_context, node->payload.fun.body, NULL)); return fun; @@ -125,7 +125,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { assert(imported_hint); Node* nconstant = constant(ctx->rewriter.dst_module, infer_nodes(ctx, oconstant->annotations), imported_hint, oconstant->name); - register_processed(&ctx->rewriter, node, nconstant); + shd_register_processed(&ctx->rewriter, node, nconstant); nconstant->payload.constant.value = instruction; return nconstant; @@ -134,7 +134,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { const GlobalVariable* old_gvar = &node->payload.global_variable; const Type* imported_ty = infer(ctx, old_gvar->type, NULL); Node* ngvar = global_var(ctx->rewriter.dst_module, infer_nodes(ctx, old_gvar->annotations), imported_ty, old_gvar->name, old_gvar->address_space); - register_processed(&ctx->rewriter, node, ngvar); + shd_register_processed(&ctx->rewriter, node, ngvar); ngvar->payload.global_variable.init = infer(ctx, old_gvar->init, shd_as_qualified_type(imported_ty, true)); return ngvar; @@ -142,7 +142,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { case NominalType_TAG: { const NominalType* onom_type = &node->payload.nom_type; Node* nnominal_type = nominal_type(ctx->rewriter.dst_module, infer_nodes(ctx, onom_type->annotations), onom_type->name); - register_processed(&ctx->rewriter, node, nnominal_type); + shd_register_processed(&ctx->rewriter, node, nnominal_type); nnominal_type->payload.nom_type.body = infer(ctx, onom_type->body, NULL); return nnominal_type; } @@ -278,7 +278,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg_type) { @@ -302,12 +302,12 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg param_type = inferred_arg_type.nodes[i]; assert(is_subtype(param_type, inferred_arg_type.nodes[i])); nparams[i] = param(a, param_type, old_param->name); - register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); + shd_register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); } } Node* new_case = basic_block(a, shd_nodes(a, inferred_arg_type.count, nparams), get_abstraction_name_unsafe(node)); - register_processed(r, node, new_case); + shd_register_processed(r, node, new_case); set_abstraction_body(new_case, infer(&body_context, node->payload.basic_block.body, NULL)); return new_case; } @@ -325,12 +325,12 @@ static const Node* _infer_basic_block(Context* ctx, const Node* node) { const Type* param_type = infer(ctx, old_param->type, NULL); assert(param_type); nparams[i] = param(a, param_type, old_param->name); - register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); + shd_register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); } Node* bb = basic_block(a, shd_nodes(a, node->payload.basic_block.params.count, nparams), node->payload.basic_block.name); assert(bb); - register_processed(&ctx->rewriter, node, bb); + shd_register_processed(&ctx->rewriter, node, bb); set_abstraction_body(bb, infer(&body_context, node->payload.basic_block.body, NULL)); return bb; @@ -498,10 +498,10 @@ static const Node* infer_control(Context* ctx, const Node* node) { }); jpt = qualified_type(a, (QualifiedType) { .is_uniform = true, .type = jpt }); const Node* jp = param(a, jpt, ojp->payload.param.name); - register_processed(&joinable_ctx.rewriter, ojp, jp); + shd_register_processed(&joinable_ctx.rewriter, ojp, jp); Node* new_case = basic_block(a, shd_singleton(jp), NULL); - register_processed(&joinable_ctx.rewriter, olam, new_case); + shd_register_processed(&joinable_ctx.rewriter, olam, new_case); set_abstraction_body(new_case, infer(&joinable_ctx, get_abstraction_body(olam), NULL)); return control(a, (Control) { @@ -517,7 +517,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* switch (is_instruction(node)) { case PrimOp_TAG: return infer_primop(ctx, node, expected_type); case Call_TAG: return infer_indirect_call(ctx, node, expected_type); - case Instruction_Comment_TAG: return recreate_node_identity(&ctx->rewriter, node); + case Instruction_Comment_TAG: return shd_recreate_node(&ctx->rewriter, node); case Instruction_Load_TAG: { return load(a, (Load) { .ptr = infer(ctx, node->payload.load.ptr, NULL), .mem = infer(ctx, node->payload.load.mem, NULL) }); } @@ -540,7 +540,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* default: break; case NotAnInstruction: shd_error("not an instruction"); } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } static const Node* infer_terminator(Context* ctx, const Node* node) { @@ -566,7 +566,7 @@ static const Node* infer_terminator(Context* ctx, const Node* node) { } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } static const Node* process(Context* src_ctx, const Node* node) { @@ -599,7 +599,7 @@ static const Node* process(Context* src_ctx, const Node* node) { } else if (is_basic_block(node)) { return _infer_basic_block(&ctx, node); }else if (is_mem(node)) { - return recreate_node_identity(&ctx.rewriter, node); + return shd_recreate_node(&ctx.rewriter, node); } assert(false); } @@ -613,11 +613,11 @@ Module* slim_pass_infer(SHADY_UNUSED const CompilerConfig* config, Module* src) Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; //ctx.rewriter.config.search_map = false; //ctx.rewriter.config.write_map = false; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/frontend/slim/normalize.c b/src/frontend/slim/normalize.c index 6c5c1a2d6..460121052 100644 --- a/src/frontend/slim/normalize.c +++ b/src/frontend/slim/normalize.c @@ -27,7 +27,7 @@ static const Node* force_to_be_value(Context* ctx, const Node* node) { case Function_TAG: { return fn_addr_helper(a, process_node(ctx, node)); } - case Param_TAG: return find_processed(&ctx->rewriter, node); + case Param_TAG: return shd_find_processed(&ctx->rewriter, node); default: break; } @@ -87,7 +87,7 @@ static const Node* process_op(Context* ctx, NodeClass op_class, SHADY_UNUSED Str } static const Node* process_node(Context* ctx, const Node* node) { - const Node** already_done = search_processed(&ctx->rewriter, node); + const Node** already_done = shd_search_processed(&ctx->rewriter, node); if (already_done) return *already_done; @@ -104,9 +104,9 @@ static const Node* process_node(Context* ctx, const Node* node) { default: break; } - const Node* new = recreate_node_identity(&ctx->rewriter, node); + const Node* new = shd_recreate_node(&ctx->rewriter, node); if (is_instruction(new)) - register_processed(r, node, new); + shd_register_processed(r, node, new); return new; } @@ -116,13 +116,13 @@ Module* slim_pass_normalize(SHADY_UNUSED const CompilerConfig* config, Module* s IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_op_rewriter(src, dst, (RewriteOpFn) process_op), + .rewriter = shd_create_op_rewriter(src, dst, (RewriteOpFn) process_op), }; ctx.rewriter.config.search_map = false; ctx.rewriter.config.write_map = false; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 771ec8925..8d466a544 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -48,7 +48,7 @@ const Node* process(Context* ctx, const Node* old) { if (old->tag == Function_TAG || old->tag == Constant_TAG) { Context c = *ctx; c.map = create_fn_uses_map(old, NcType | NcDeclaration); - const Node* new = recreate_node_identity(&c.rewriter, old); + const Node* new = shd_recreate_node(&c.rewriter, old); destroy_uses_map(c.map); return new; } @@ -65,13 +65,13 @@ const Node* process(Context* ctx, const Node* old) { } case Jump_TAG: { const Node* otarget = old->payload.jump.target; - const Node* ntarget = rewrite_node(r, otarget); + const Node* ntarget = shd_rewrite_node(r, otarget); if (!ntarget) { // it's been inlined away! just steal the body - Nodes nargs = rewrite_nodes(r, old->payload.jump.args); - register_processed_list(r, get_abstraction_params(otarget), nargs); - register_processed(r, get_abstraction_mem(otarget), rewrite_node(r, old->payload.jump.mem)); - return rewrite_node(r, get_abstraction_body(otarget)); + Nodes nargs = shd_rewrite_nodes(r, old->payload.jump.args); + shd_register_processed_list(r, get_abstraction_params(otarget), nargs); + shd_register_processed(r, get_abstraction_mem(otarget), shd_rewrite_node(r, old->payload.jump.mem)); + return shd_rewrite_node(r, get_abstraction_body(otarget)); } break; } @@ -84,10 +84,10 @@ const Node* process(Context* ctx, const Node* old) { Join payload_join = term->payload.join; if (payload_join.join_point == shd_first(get_abstraction_params(control_inside))) { // if we immediately consume the join point and it's never leaked, this control block does nothing and can be eliminated - register_processed(r, get_abstraction_mem(control_inside), rewrite_node(r, payload.mem)); - register_processed(r, control_inside, NULL); + shd_register_processed(r, get_abstraction_mem(control_inside), shd_rewrite_node(r, payload.mem)); + shd_register_processed(r, control_inside, NULL); *ctx->todo = true; - return rewrite_node(r, term); + return shd_rewrite_node(r, term); } } } @@ -99,22 +99,22 @@ const Node* process(Context* ctx, const Node* old) { if (control) { Control old_control_payload = control->payload.control; // there was a control but now there is not anymore - jump to the tail! - if (rewrite_node(r, old_control_payload.inside) == NULL) { - return jump_helper(a, rewrite_node(r, payload.mem), rewrite_node(r, old_control_payload.tail), - rewrite_nodes(r, payload.args)); + if (shd_rewrite_node(r, old_control_payload.inside) == NULL) { + return jump_helper(a, shd_rewrite_node(r, payload.mem), shd_rewrite_node(r, old_control_payload.tail), + shd_rewrite_nodes(r, payload.args)); } } break; } case Load_TAG: { if (!is_used_as_value(ctx->map, old)) - return rewrite_node(r, old->payload.load.mem); + return shd_rewrite_node(r, old->payload.load.mem); break; } default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } OptPass simplify; @@ -126,9 +126,9 @@ bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { *m = new_module(a, get_module_name(*m)); bool todo = false; Context ctx = { .todo = &todo }; - ctx.rewriter = create_node_rewriter(src, *m, (RewriteNodeFn) process); - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + ctx.rewriter = shd_create_node_rewriter(src, *m, (RewriteNodeFn) process); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return todo; } diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index a5d453102..ec512ec76 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -22,14 +22,14 @@ static const Node* process(Context* ctx, const Node* node) { case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; if (decl->tag == Constant_TAG && decl->payload.constant.value) { - return rewrite_node(&ctx->rewriter, decl->payload.constant.value); + return shd_rewrite_node(&ctx->rewriter, decl->payload.constant.value); } break; } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } static Module* eliminate_constants_(SHADY_UNUSED const CompilerConfig* config, Module* src, bool all) { @@ -37,12 +37,12 @@ static Module* eliminate_constants_(SHADY_UNUSED const CompilerConfig* config, M IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .all = all, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index d63053fe8..8dddec2d7 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -21,7 +21,7 @@ const Node* import_node(Rewriter* r, const Node* node) { if (is_declaration(node)) { Node* existing = get_declaration(r->dst_module, get_declaration_name(node)); if (existing) { - const Node* imported_t = rewrite_node(r, node->type); + const Node* imported_t = shd_rewrite_node(r, node->type); if (imported_t != existing->type) { shd_error_print("Incompatible types for to-be-merged declaration: %s ", get_declaration_name(node)); shd_log_node(ERROR, existing->type); @@ -41,23 +41,23 @@ const Node* import_node(Rewriter* r, const Node* node) { switch (is_declaration(node)) { case NotADeclaration: assert(false); case Declaration_Function_TAG: - replace_or_compare(&existing->payload.fun.body, rewrite_node(r, node->payload.fun.body)); + replace_or_compare(&existing->payload.fun.body, shd_rewrite_node(r, node->payload.fun.body)); break; case Declaration_Constant_TAG: - replace_or_compare(&existing->payload.constant.value, rewrite_node(r, node->payload.constant.value)); + replace_or_compare(&existing->payload.constant.value, shd_rewrite_node(r, node->payload.constant.value)); break; case Declaration_GlobalVariable_TAG: - replace_or_compare(&existing->payload.global_variable.init, rewrite_node(r, node->payload.global_variable.init)); + replace_or_compare(&existing->payload.global_variable.init, shd_rewrite_node(r, node->payload.global_variable.init)); break; case Declaration_NominalType_TAG: - replace_or_compare(&existing->payload.nom_type.body, rewrite_node(r, node->payload.nom_type.body)); + replace_or_compare(&existing->payload.nom_type.body, shd_rewrite_node(r, node->payload.nom_type.body)); break; } return existing; } } - return recreate_node_identity(r, node); + return shd_recreate_node(r, node); } Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -65,18 +65,18 @@ Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) recreate_node_identity), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) shd_recreate_node), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } void link_module(Module* dst, Module* src) { Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) import_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) import_node), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); } diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 87b02b23f..0d7906824 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -69,7 +69,7 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No shd_log_fmt(DEBUGV, "lcssa: "); shd_log_node(DEBUGV, fv); shd_log_fmt(DEBUGV, " (%%%d) is used outside of the loop that defines it %s %s\n", fv->id, loop_name(defining_loop), loop_name(bb_loop)); - const Node* narg = rewrite_node(&ctx->rewriter, fv); + const Node* narg = shd_rewrite_node(&ctx->rewriter, fv); const Node* nparam = param(a, narg->type, "lcssa_phi"); *nparams = shd_nodes_append(a, *nparams, nparam); *lparams = shd_nodes_append(a, *lparams, fv); @@ -109,14 +109,14 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* for (size_t i = 0; i < children_count; i++) { Nodes nargs; find_liftable_loop_values(ctx, old_children[i], &new_params[i], &lifted_params[i], &nargs); - Nodes nparams = recreate_params(&ctx->rewriter, get_abstraction_params(old_children[i])); + Nodes nparams = shd_recreate_params(&ctx->rewriter, get_abstraction_params(old_children[i])); new_children[i] = basic_block(a, shd_concat_nodes(a, nparams, new_params[i]), get_abstraction_name(old_children[i])); - register_processed(&ctx->rewriter, old_children[i], new_children[i]); - register_processed_list(&ctx->rewriter, get_abstraction_params(old_children[i]), nparams); + shd_register_processed(&ctx->rewriter, old_children[i], new_children[i]); + shd_register_processed_list(&ctx->rewriter, get_abstraction_params(old_children[i]), nparams); shd_dict_insert(const Node*, Nodes, ctx->lifted_arguments, old_children[i], nargs); } - const Node* new = rewrite_node(&ctx->rewriter, body); + const Node* new = shd_rewrite_node(&ctx->rewriter, body); ctx->rewriter.map = shd_clone_dict(ctx->rewriter.map); @@ -124,7 +124,7 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* for (size_t j = 0; j < lifted_params[i].count; j++) { shd_dict_remove(const Node*, ctx->rewriter.map, lifted_params[i].nodes[j]); } - register_processed_list(&ctx->rewriter, lifted_params[i], new_params[i]); + shd_register_processed_list(&ctx->rewriter, lifted_params[i], new_params[i]); new_children[i]->payload.basic_block.body = process_abstraction_body(ctx, old_children[i], get_abstraction_body(old_children[i])); } @@ -144,7 +144,7 @@ const Node* process_node(Context* ctx, const Node* old) { Context not_a_fn_ctx = *ctx; ctx = ¬_a_fn_ctx; ctx->cfg = NULL; - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } case Function_TAG: { Context fn_ctx = *ctx; @@ -155,7 +155,7 @@ const Node* process_node(Context* ctx, const Node* old) { ctx->scheduler = new_scheduler(ctx->cfg); ctx->loop_tree = build_loop_tree(ctx->cfg); - Node* new = recreate_decl_header_identity(&ctx->rewriter, old); + Node* new = shd_recreate_node_head(&ctx->rewriter, old); new->payload.fun.body = process_abstraction_body(ctx, old, get_abstraction_body(old)); destroy_loop_tree(ctx->loop_tree); @@ -165,15 +165,15 @@ const Node* process_node(Context* ctx, const Node* old) { } case Jump_TAG: { Jump payload = old->payload.jump; - Nodes nargs = rewrite_nodes(&ctx->rewriter, old->payload.jump.args); + Nodes nargs = shd_rewrite_nodes(&ctx->rewriter, old->payload.jump.args); Nodes* lifted_args = shd_dict_find_value(const Node*, Nodes, ctx->lifted_arguments, old->payload.jump.target); if (lifted_args) { nargs = shd_concat_nodes(a, nargs, *lifted_args); } return jump(a, (Jump) { - .target = rewrite_node(&ctx->rewriter, old->payload.jump.target), + .target = shd_rewrite_node(&ctx->rewriter, old->payload.jump.target), .args = nargs, - .mem = rewrite_node(r, payload.mem), + .mem = shd_rewrite_node(r, payload.mem), }); } case BasicBlock_TAG: { @@ -182,7 +182,7 @@ const Node* process_node(Context* ctx, const Node* old) { default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } KeyHash hash_node(Node**); @@ -194,14 +194,14 @@ Module* lcssa(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .current_fn = NULL, .lifted_arguments = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node) }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_dict(ctx.lifted_arguments); return dst; } diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index 437ef63f4..ea233df1f 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -30,8 +30,8 @@ static const Node* process(Context* ctx, const Node* node) { fn_ctx.cfg = build_fn_cfg(node); fn_ctx.scheduler = new_scheduler(fn_ctx.cfg); - Node* new_fn = recreate_decl_header_identity(r, node); - recreate_decl_body_identity(&fn_ctx.rewriter, node, new_fn); + Node* new_fn = shd_recreate_node_head(r, node); + shd_recreate_node_body(&fn_ctx.rewriter, node, new_fn); destroy_scheduler(fn_ctx.scheduler); destroy_cfg(fn_ctx.cfg); @@ -45,21 +45,21 @@ static const Node* process(Context* ctx, const Node* node) { // insert_dict(const Node*, Dict*, ctx->lift, node, frontier); Nodes additional_args = shd_empty(a); - Nodes new_params = recreate_params(r, get_abstraction_params(node)); - register_processed_list(r, get_abstraction_params(node), new_params); + Nodes new_params = shd_recreate_params(r, get_abstraction_params(node)); + shd_register_processed_list(r, get_abstraction_params(node), new_params); size_t i = 0; const Node* value; Context bb_ctx = *ctx; - bb_ctx.rewriter = create_children_rewriter(&ctx->rewriter); + bb_ctx.rewriter = shd_create_children_rewriter(&ctx->rewriter); while (shd_dict_iter(frontier, &i, &value, NULL)) { if (is_value(value)) { additional_args = shd_nodes_append(a, additional_args, value); - const Type* t = rewrite_node(r, value->type); + const Type* t = shd_rewrite_node(r, value->type); const Node* p = param(a, t, NULL); new_params = shd_nodes_append(a, new_params, p); - register_processed(&bb_ctx.rewriter, value, p); + shd_register_processed(&bb_ctx.rewriter, value, p); } } @@ -76,27 +76,27 @@ static const Node* process(Context* ctx, const Node* node) { break; } - register_processed(&fn_ctx->rewriter, node, new_bb); - set_abstraction_body(new_bb, rewrite_node(&bb_ctx.rewriter, get_abstraction_body(node))); - destroy_rewriter(&bb_ctx.rewriter); + shd_register_processed(&fn_ctx->rewriter, node, new_bb); + set_abstraction_body(new_bb, shd_rewrite_node(&bb_ctx.rewriter, get_abstraction_body(node))); + shd_destroy_rewriter(&bb_ctx.rewriter); return new_bb; } case Jump_TAG: { Jump payload = node->payload.jump; - rewrite_node(r, payload.target); + shd_rewrite_node(r, payload.target); Nodes* additional_args = shd_dict_find_value(const Node*, Nodes, ctx->lift, payload.target); assert(additional_args); return jump(a, (Jump) { - .mem = rewrite_node(r, payload.mem), - .target = rewrite_node(r, payload.target), - .args = shd_concat_nodes(a, rewrite_nodes(r, payload.args), rewrite_nodes(r, *additional_args)) + .mem = shd_rewrite_node(r, payload.mem), + .target = shd_rewrite_node(r, payload.target), + .args = shd_concat_nodes(a, shd_rewrite_nodes(r, payload.args), shd_rewrite_nodes(r, *additional_args)) }); } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -108,12 +108,12 @@ Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) todo = false; dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .lift = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), }; - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); shd_destroy_dict(ctx.lift); - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); src = dst; } return dst; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 580f95c0d..efb930393 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -49,7 +49,7 @@ typedef struct { static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, Nodes spilled_vars) { for (size_t i = 0; i < spilled_vars.count; i++) { const Node* ovar = spilled_vars.nodes[i]; - const Node* nvar = rewrite_node(&ctx->rewriter, ovar); + const Node* nvar = shd_rewrite_node(&ctx->rewriter, ovar); const Type* t = nvar->type; deconstruct_qualified_type(&t); assert(t->tag != PtrType_TAG || !t->payload.ptr_type.is_reference && "References cannot be spilled"); @@ -91,7 +91,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { destroy_scheduler(scheduler); Context lifting_ctx = *ctx; - lifting_ctx.rewriter = create_decl_rewriter(&ctx->rewriter); + lifting_ctx.rewriter = shd_create_decl_rewriter(&ctx->rewriter); Rewriter* r = &lifting_ctx.rewriter; Nodes ovariables = get_abstraction_params(liftee); @@ -111,7 +111,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { // Create and register new parameters for the lifted continuation LARRAY(const Node*, new_params_arr, ovariables.count); for (size_t i = 0; i < ovariables.count; i++) - new_params_arr[i] = param(a, rewrite_node(&ctx->rewriter, ovariables.nodes[i]->type), get_value_name_unsafe(ovariables.nodes[i])); + new_params_arr[i] = param(a, shd_rewrite_node(&ctx->rewriter, ovariables.nodes[i]->type), get_value_name_unsafe(ovariables.nodes[i])); Nodes new_params = shd_nodes(a, ovariables.count, new_params_arr); LiftedCont* lifted_cont = calloc(sizeof(LiftedCont), 1); @@ -119,7 +119,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { lifted_cont->save_values = frontier; shd_dict_insert(const Node*, LiftedCont*, ctx->lifted, liftee, lifted_cont); - register_processed_list(r, ovariables, new_params); + shd_register_processed_list(r, ovariables, new_params); const Node* payload = param(a, shd_as_qualified_type(shd_uint32_type(a), false), "sp"); @@ -136,7 +136,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { const Node* ovar = frontier.nodes[i]; // assert(ovar->tag == Variable_TAG); - const Type* value_type = rewrite_node(r, ovar->type); + const Type* value_type = shd_rewrite_node(r, ovar->type); //String param_name = get_value_name_unsafe(ovar); const Node* recovered_value = gen_pop_value_stack(bb, get_unqualified_type(value_type)); @@ -146,13 +146,13 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { if (is_qualified_type_uniform(ovar->type)) recovered_value = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = shd_singleton(recovered_value) }); - register_processed(r, ovar, recovered_value); + shd_register_processed(r, ovar, recovered_value); } - register_processed(r, get_abstraction_mem(liftee), bb_mem(bb)); - register_processed(r, liftee, new_fn); - const Node* substituted = rewrite_node(r, obody); - destroy_rewriter(r); + shd_register_processed(r, get_abstraction_mem(liftee), bb_mem(bb)); + shd_register_processed(r, liftee, new_fn); + const Node* substituted = shd_rewrite_node(r, obody); + shd_destroy_rewriter(r); assert(is_terminator(substituted)); set_abstraction_body(new_fn, finish_body(bb, substituted)); @@ -175,8 +175,8 @@ static const Node* process_node(Context* ctx, const Node* node) { fn_ctx.disable_lowering = shd_lookup_annotation(node, "Internal"); ctx = &fn_ctx; - Node* new = recreate_decl_header_identity(&ctx->rewriter, node); - recreate_decl_body_identity(&ctx->rewriter, node, new); + Node* new = shd_recreate_node_head(&ctx->rewriter, node); + shd_recreate_node_body(&ctx->rewriter, node, new); destroy_uses_map(ctx->uses); destroy_cfg(ctx->cfg); @@ -187,7 +187,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } if (ctx->disable_lowering) - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); switch (node->tag) { case Control_TAG: { @@ -196,29 +196,29 @@ static const Node* process_node(Context* ctx, const Node* node) { *ctx->todo = true; const Node* otail = get_structured_construct_tail(node); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.control.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, node->payload.control.mem)); LiftedCont* lifted_tail = lambda_lift(ctx, ctx->cfg, otail); const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); const Type* jp_type = join_point_type(a, (JoinPointType) { - .yield_types = rewrite_nodes(&ctx->rewriter, node->payload.control.yield_types), + .yield_types = shd_rewrite_nodes(&ctx->rewriter, node->payload.control.yield_types), }); const Node* jp = gen_ext_instruction(bb, "shady.internal", ShadyOpCreateJoinPoint, shd_as_qualified_type(jp_type, true), mk_nodes(a, tail_ptr, sp)); // dumbass hack jp = gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(jp)); - register_processed(r, shd_first(get_abstraction_params(oinside)), jp); - register_processed(r, get_abstraction_mem(oinside), bb_mem(bb)); - register_processed(r, oinside, NULL); - return finish_body(bb, rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); + shd_register_processed(r, shd_first(get_abstraction_params(oinside)), jp); + shd_register_processed(r, get_abstraction_mem(oinside), bb_mem(bb)); + shd_register_processed(r, oinside, NULL); + return finish_body(bb, shd_rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); } break; } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { @@ -234,14 +234,14 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { dst = new_module(a, get_module_name(src)); bool todo = false; Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .lifted = shd_new_dict(const Node*, LiftedCont*, (HashFn) hash_node, (CmpFn) compare_node), .config = config, .todo = &todo }; - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); size_t iter = 0; LiftedCont* lifted_cont; @@ -249,7 +249,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { free(lifted_cont); } shd_destroy_dict(ctx.lifted); - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); verify_module(config, dst); src = dst; if (oa) @@ -263,9 +263,9 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { aconfig.optimisations.weaken_non_leaking_allocas = true; IrArena* a2 = shd_new_ir_arena(&aconfig); dst = new_module(a2, get_module_name(src)); - Rewriter r = create_importer(src, dst); - rewrite_module(&r); - destroy_rewriter(&r); + Rewriter r = shd_create_importer(src, dst); + shd_rewrite_module(&r); + shd_destroy_rewriter(&r); shd_destroy_ir_arena(a); return dst; } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 71fed4126..eda2d2494 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -52,7 +52,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { if (found) break; - const Type* element_type = rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); + const Type* element_type = shd_rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); assert(is_data_type(element_type)); const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, shd_singleton(type_decl_ref_helper(a, vctx->nom_t)), shd_singleton(shd_int32_literal(a, shd_list_count(vctx->members)))); shd_list_append(const Type*, vctx->members, element_type); @@ -78,14 +78,14 @@ static const Node* process(Context* ctx, const Node* node) { Module* m = r->dst_module; switch (node->tag) { case Function_TAG: { - Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); + Node* fun = shd_recreate_node_head(&ctx->rewriter, node); if (!node->payload.fun.body) return fun; Context ctx2 = *ctx; ctx2.disable_lowering = shd_lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; if (ctx2.disable_lowering) { - set_abstraction_body(fun, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); + set_abstraction_body(fun, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body)); return fun; } @@ -120,8 +120,8 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); // make sure to use the new mem from then on - register_processed(r, get_abstraction_mem(node), bb_mem(bb)); - set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); + shd_register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); shd_destroy_dict(ctx2.prepared_offsets); return fun; @@ -137,7 +137,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_error_die(); } - BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, node->payload.stack_alloc.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, node->payload.stack_alloc.mem)); if (!ctx->stack_size_on_entry) { //String tmp_name = format_string_arena(a->arena, "stack_ptr_before_alloca_%s", get_abstraction_name(fun)); assert(false); @@ -160,7 +160,7 @@ static const Node* process(Context* ctx, const Node* node) { } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -168,11 +168,11 @@ Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .stack_ptr_t = int_type(a, (Int) { .is_signed = false, .width = IntTy32 }), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index d0ef549e5..11f25d114 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -30,17 +30,17 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { if (!ctx2.disable_lowering && get_abstraction_body(old)) { Nodes oparams = get_abstraction_params(old); - Nodes nparams = recreate_params(&ctx->rewriter, oparams); - register_processed_list(&ctx->rewriter, oparams, nparams); + Nodes nparams = shd_recreate_params(&ctx->rewriter, oparams); + shd_register_processed_list(&ctx->rewriter, oparams, nparams); - Nodes nannots = rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); + Nodes nannots = shd_rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); Node* prelude = case_(a, shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(prelude)); // Supplement an additional parameter for the join point const Type* jp_type = join_point_type(a, (JoinPointType) { - .yield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, old->payload.fun.return_types)) + .yield_types = strip_qualifiers(a, shd_rewrite_nodes(&ctx->rewriter, old->payload.fun.return_types)) }); if (shd_lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { @@ -53,27 +53,27 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { } Node* fun = function(ctx->rewriter.dst_module, nparams, get_abstraction_name(old), nannots, shd_empty(a)); - register_processed(&ctx->rewriter, old, fun); + shd_register_processed(&ctx->rewriter, old, fun); - register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(prelude, finish_body(bb, rewrite_node(&ctx2.rewriter, old->payload.fun.body))); + shd_register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + set_abstraction_body(prelude, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body))); set_abstraction_body(fun, jump_helper(a, get_abstraction_mem(fun), prelude, shd_empty(a))); return fun; } - Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); + Node* fun = shd_recreate_node_head(&ctx->rewriter, old); if (old->payload.fun.body) - set_abstraction_body(fun, rewrite_node(&ctx2.rewriter, old->payload.fun.body)); + set_abstraction_body(fun, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body)); return fun; } if (ctx->disable_lowering) - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); switch (old->tag) { case FnType_TAG: { - Nodes param_types = rewrite_nodes(r, old->payload.fn_type.param_types); - Nodes returned_types = rewrite_nodes(&ctx->rewriter, old->payload.fn_type.return_types); + Nodes param_types = shd_rewrite_nodes(r, old->payload.fn_type.param_types); + Nodes returned_types = shd_rewrite_nodes(&ctx->rewriter, old->payload.fn_type.return_types); const Type* jp_type = qualified_type(a, (QualifiedType) { .type = join_point_type(a, (JoinPointType) { .yield_types = strip_qualifiers(a, returned_types) }), .is_uniform = false @@ -85,11 +85,11 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { }); } case Return_TAG: { - Nodes nargs = rewrite_nodes(&ctx->rewriter, old->payload.fn_ret.args); + Nodes nargs = shd_rewrite_nodes(&ctx->rewriter, old->payload.fn_ret.args); const Node* return_jp = ctx->return_jp; if (return_jp) { - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, old->payload.fn_ret.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, old->payload.fn_ret.mem)); return_jp = gen_primop_ce(bb, subgroup_assume_uniform_op, 1, (const Node* []) { return_jp }); // Join up at the return address instead of returning return finish_body(bb, join(a, (Join) { @@ -114,11 +114,11 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { bool callee_uniform = deconstruct_qualified_type(&ocallee_type); ocallee_type = get_pointee_type(a, ocallee_type); assert(ocallee_type->tag == FnType_TAG); - Nodes returned_types = rewrite_nodes(&ctx->rewriter, ocallee_type->payload.fn_type.return_types); + Nodes returned_types = shd_rewrite_nodes(&ctx->rewriter, ocallee_type->payload.fn_type.return_types); // Rewrite the callee and its arguments - const Node* ncallee = rewrite_node(&ctx->rewriter, ocallee); - Nodes nargs = rewrite_nodes(&ctx->rewriter, payload.args); + const Node* ncallee = shd_rewrite_node(&ctx->rewriter, ocallee); + Nodes nargs = shd_rewrite_nodes(&ctx->rewriter, payload.args); // Create the body of the control that receives the appropriately typed join point const Type* jp_type = qualified_type(a, (QualifiedType) { @@ -138,12 +138,12 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .mem = get_abstraction_mem(control_case), }); set_abstraction_body(control_case, control_body); - BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, gen_control(bb, strip_qualifiers(a, returned_types), control_case)); } default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } Module* lower_callf(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -151,10 +151,10 @@ Module* lower_callf(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) lower_callf_process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) lower_callf_process), .disable_lowering = false, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 889e5b097..cf785d14f 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -24,11 +24,11 @@ static const Node* process_node(Context* ctx, const Node* node) { Context sub_ctx = *ctx; if (node->tag == Function_TAG) { - Node* fun = recreate_decl_header_identity(&ctx->rewriter, node); + Node* fun = shd_recreate_node_head(&ctx->rewriter, node); sub_ctx.disable_lowering = shd_lookup_annotation(fun, "Structured"); sub_ctx.current_fn = fun; sub_ctx.cfg = build_fn_cfg(node); - set_abstraction_body(fun, rewrite_node(&sub_ctx.rewriter, node->payload.fun.body)); + set_abstraction_body(fun, shd_rewrite_node(&sub_ctx.rewriter, node->payload.fun.body)); destroy_cfg(sub_ctx.cfg); return fun; } else if (node->tag == Constant_TAG) { @@ -38,14 +38,14 @@ static const Node* process_node(Context* ctx, const Node* node) { } if (ctx->disable_lowering) - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); switch (node->tag) { case If_TAG: { If payload = node->payload.if_instr; bool has_false_branch = payload.if_false; - Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.if_instr.yield_types); - const Node* nmem = rewrite_node(r, node->payload.if_instr.mem); + Nodes yield_types = shd_rewrite_nodes(&ctx->rewriter, node->payload.if_instr.yield_types); + const Node* nmem = shd_rewrite_node(r, node->payload.if_instr.mem); const Type* jp_type = qualified_type(a, (QualifiedType) { .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), @@ -55,11 +55,11 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes jps = shd_singleton(jp); shd_dict_insert(const Node*, Nodes, ctx->structured_join_tokens, node, jps); - const Node* true_block = rewrite_node(r, payload.if_true); + const Node* true_block = shd_rewrite_node(r, payload.if_true); const Node* false_block; if (has_false_branch) { - false_block = rewrite_node(r, payload.if_false); + false_block = shd_rewrite_node(r, payload.if_false); } else { assert(yield_types.count == 0); false_block = basic_block(a, shd_nodes(a, 0, NULL), unique_name(a, "if_false")); @@ -68,7 +68,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* control_case = basic_block(a, shd_singleton(jp), NULL); const Node* control_body = branch(a, (Branch) { - .condition = rewrite_node(r, node->payload.if_instr.condition), + .condition = shd_rewrite_node(r, node->payload.if_instr.condition), .true_jump = jump_helper(a, get_abstraction_mem(control_case), true_block, shd_empty(a)), .false_jump = jump_helper(a, get_abstraction_mem(control_case), false_block, shd_empty(a)), .mem = get_abstraction_mem(control_case), @@ -77,15 +77,15 @@ static const Node* process_node(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body_with_mem(a, nmem); Nodes results = gen_control(bb, yield_types, control_case); - return finish_body(bb, jump_helper(a, bb_mem(bb), rewrite_node(r, payload.tail), results)); + return finish_body(bb, jump_helper(a, bb_mem(bb), shd_rewrite_node(r, payload.tail), results)); } // TODO: match case Loop_TAG: { Loop payload = node->payload.loop_instr; const Node* old_loop_block = payload.body; - Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.yield_types); - Nodes param_types = rewrite_nodes(&ctx->rewriter, get_param_types(a, get_abstraction_params(old_loop_block))); + Nodes yield_types = shd_rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.yield_types); + Nodes param_types = shd_rewrite_nodes(&ctx->rewriter, get_param_types(a, get_abstraction_params(old_loop_block))); param_types = strip_qualifiers(a, param_types); const Type* break_jp_type = qualified_type(a, (QualifiedType) { @@ -101,13 +101,13 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes jps = mk_nodes(a, break_point, continue_point); shd_dict_insert(const Node*, Nodes, ctx->structured_join_tokens, node, jps); - Nodes new_params = recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_block)); + Nodes new_params = shd_recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_block)); Node* loop_header_block = basic_block(a, new_params, unique_name(a, "loop_header")); BodyBuilder* inner_bb = begin_body_with_mem(a, get_abstraction_mem(loop_header_block)); Node* inner_control_case = case_(a, shd_singleton(continue_point)); set_abstraction_body(inner_control_case, jump_helper(a, get_abstraction_mem(inner_control_case), - rewrite_node(r, old_loop_block), new_params)); + shd_rewrite_node(r, old_loop_block), new_params)); Nodes args = gen_control(inner_bb, param_types, inner_control_case); set_abstraction_body(loop_header_block, finish_body(inner_bb, jump(a, (Jump) { .target = loop_header_block, .args = args, .mem = bb_mem(inner_bb) }))); @@ -115,14 +115,14 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* outer_control_case = case_(a, shd_singleton(break_point)); const Node* first_iteration_jump = jump(a, (Jump) { .target = loop_header_block, - .args = rewrite_nodes(r, payload.initial_args), + .args = shd_rewrite_nodes(r, payload.initial_args), .mem = get_abstraction_mem(outer_control_case), }); set_abstraction_body(outer_control_case, first_iteration_jump); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); Nodes results = gen_control(bb, yield_types, outer_control_case); - return finish_body(bb, jump_helper(a, bb_mem(bb), rewrite_node(r, payload.tail), results)); + return finish_body(bb, jump_helper(a, bb_mem(bb), shd_rewrite_node(r, payload.tail), results)); } case MergeSelection_TAG: { MergeSelection payload = node->payload.merge_selection; @@ -151,10 +151,10 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(jps && jps->count == 1); const Node* jp = shd_first(*jps); assert(jp); - const Node* nmem = rewrite_node(r, payload.mem); + const Node* nmem = shd_rewrite_node(r, payload.mem); return join(a, (Join) { .join_point = jp, - .args = rewrite_nodes(&ctx->rewriter, payload.args), + .args = shd_rewrite_nodes(&ctx->rewriter, payload.args), .mem = nmem }); } @@ -185,10 +185,10 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(jps && jps->count == 2); const Node* jp = jps->nodes[1]; assert(jp); - const Node* nmem = rewrite_node(r, payload.mem); + const Node* nmem = shd_rewrite_node(r, payload.mem); return join(a, (Join) { .join_point = jp, - .args = rewrite_nodes(&ctx->rewriter, payload.args), + .args = shd_rewrite_nodes(&ctx->rewriter, payload.args), .mem = nmem, }); } @@ -219,16 +219,16 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(jps && jps->count == 2); const Node* jp = shd_first(*jps); assert(jp); - const Node* nmem = rewrite_node(r, payload.mem); + const Node* nmem = shd_rewrite_node(r, payload.mem); return join(a, (Join) { .join_point = jp, - .args = rewrite_nodes(&ctx->rewriter, payload.args), + .args = shd_rewrite_nodes(&ctx->rewriter, payload.args), .mem = nmem, }); } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } KeyHash hash_node(const Node**); @@ -239,11 +239,11 @@ Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .structured_join_tokens = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_dict(ctx.structured_join_tokens); return dst; } diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index 548feea25..d4b755474 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -20,7 +20,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* arr_t = node->payload.ptr_type.pointed_type; if (arr_t->tag == ArrType_TAG && !arr_t->payload.arr_type.size) { return ptr_type(arena, (PtrType) { - .pointed_type = rewrite_node(&ctx->rewriter, arr_t->payload.arr_type.element_type), + .pointed_type = shd_rewrite_node(&ctx->rewriter, arr_t->payload.arr_type.element_type), .address_space = node->payload.ptr_type.address_space, }); } @@ -30,7 +30,7 @@ static const Node* process(Context* ctx, const Node* node) { } rebuild: - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_decay_ptrs(const CompilerConfig* config, Module* src) { @@ -38,10 +38,10 @@ Module* lower_decay_ptrs(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 3c24437e5..99d8f5049 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -16,10 +16,10 @@ typedef struct { static Node* rewrite_entry_point_fun(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; - Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); + Nodes annotations = shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); Node* fun = function(ctx->rewriter.dst_module, shd_empty(a), node->payload.fun.name, annotations, shd_empty(a)); - register_processed(&ctx->rewriter, node, fun); + shd_register_processed(&ctx->rewriter, node, fun); return fun; } @@ -31,7 +31,7 @@ static const Node* generate_arg_struct_type(Rewriter* rewriter, Nodes params) { LARRAY(String, names, params.count); for (int i = 0; i < params.count; ++i) { - const Type* type = rewrite_node(rewriter, params.nodes[i]->type); + const Type* type = shd_rewrite_node(rewriter, params.nodes[i]->type); if (!deconstruct_qualified_type(&type)) shd_error("EntryPoint parameters must be uniform"); @@ -67,11 +67,11 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const for (int i = 0; i < params.count; ++i) { const Node* addr = gen_lea(bb, arg_struct, shd_int32_literal(a, 0), shd_singleton(shd_int32_literal(a, i))); const Node* val = gen_load(bb, addr); - register_processed(&ctx->rewriter, params.nodes[i], val); + shd_register_processed(&ctx->rewriter, params.nodes[i], val); } - register_processed(&ctx->rewriter, get_abstraction_mem(old_entry_point), bb_mem(bb)); - return finish_body(bb, rewrite_node(&ctx->rewriter, old_entry_point->payload.fun.body)); + shd_register_processed(&ctx->rewriter, get_abstraction_mem(old_entry_point), bb_mem(bb)); + return finish_body(bb, shd_rewrite_node(&ctx->rewriter, old_entry_point->payload.fun.body)); } static const Node* process(Context* ctx, const Node* node) { @@ -87,7 +87,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_entrypoint_args(const CompilerConfig* config, Module* src) { @@ -95,10 +95,10 @@ Module* lower_entrypoint_args(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index 79d5b7f06..fdf93aa36 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -16,9 +16,9 @@ static const Node* process(Context* ctx, const Node* node) { IrArena* a = r->dst_arena; switch (node->tag) { case Fill_TAG: { - const Type* composite_t = rewrite_node(r, node->payload.fill.type); + const Type* composite_t = shd_rewrite_node(r, node->payload.fill.type); size_t actual_size = get_int_literal_value(*resolve_to_int_literal(get_fill_type_size(composite_t)), false); - const Node* value = rewrite_node(r, node->payload.fill.value); + const Node* value = shd_rewrite_node(r, node->payload.fill.value); LARRAY(const Node*, copies, actual_size); for (size_t i = 0; i < actual_size; i++) { copies[i] = value; @@ -28,7 +28,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(r, node); + return shd_recreate_node(r, node); } Module* lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -36,9 +36,9 @@ Module* lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 30e921b2f..43d4d2ad1 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -17,21 +17,21 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case RefDecl_TAG: { // make sure we rewrite the decl first, and then look if it rewrote the ref to it! - rewrite_node(r, node->payload.ref_decl.decl); - const Node** f = search_processed(r, node); + shd_rewrite_node(r, node->payload.ref_decl.decl); + const Node** f = shd_search_processed(r, node); if (f) return *f; break; } case GlobalVariable_TAG: { if (node->payload.global_variable.address_space == AsGeneric) { AddressSpace dst_as = AsGlobal; - const Type* t = rewrite_node(&ctx->rewriter, node->payload.global_variable.type); - Node* new_global = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations), t, node->payload.global_variable.name, dst_as); - register_processed(&ctx->rewriter, node, new_global); + const Type* t = shd_rewrite_node(&ctx->rewriter, node->payload.global_variable.type); + Node* new_global = global_var(ctx->rewriter.dst_module, shd_rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations), t, node->payload.global_variable.name, dst_as); + shd_register_processed(&ctx->rewriter, node, new_global); const Type* dst_t = ptr_type(a, (PtrType) { .pointed_type = t, .address_space = AsGeneric }); const Node* converted = prim_op_helper(a, convert_op, shd_singleton(dst_t), shd_singleton(ref_decl_helper(a, new_global))); - register_processed(&ctx->rewriter, ref_decl_helper(node->arena, node), converted); + shd_register_processed(&ctx->rewriter, ref_decl_helper(node->arena, node), converted); return new_global; } break; @@ -39,7 +39,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_generic_globals(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -47,9 +47,9 @@ Module* lower_generic_globals(SHADY_UNUSED const CompilerConfig* config, Module* IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 8db9997e2..280415739 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -211,9 +211,9 @@ static const Node* process(Context* ctx, const Node* old) { u &= is_addr_space_uniform(a, old_ptr_t->payload.ptr_type.address_space); if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { return call(a, (Call) { - .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, u, rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), - .args = shd_singleton(rewrite_node(&ctx->rewriter, payload.ptr)), - .mem = rewrite_node(r, payload.mem) + .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, u, shd_rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), + .args = shd_singleton(shd_rewrite_node(&ctx->rewriter, payload.ptr)), + .mem = shd_rewrite_node(r, payload.mem) }); } break; @@ -224,9 +224,9 @@ static const Node* process(Context* ctx, const Node* old) { deconstruct_qualified_type(&old_ptr_t); if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { return call(a, (Call) { - .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, StoreFn, false, rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), - .args = mk_nodes(a, rewrite_node(r, payload.ptr), rewrite_node(r, payload.value)), - .mem = rewrite_node(r, payload.mem), + .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, StoreFn, false, shd_rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), + .args = mk_nodes(a, shd_rewrite_node(r, payload.ptr), shd_rewrite_node(r, payload.value)), + .mem = shd_rewrite_node(r, payload.mem), }); } break; @@ -246,7 +246,7 @@ static const Node* process(Context* ctx, const Node* old) { // TODO: find another way to annotate this ? // String x = format_string_arena(a->arena, "Generated generic ptr convert src %d tag %d", src_as, tag); // gen_comment(bb, x); - const Node* src_ptr = rewrite_node(&ctx->rewriter, old_src); + const Node* src_ptr = shd_rewrite_node(&ctx->rewriter, old_src); const Node* generic_ptr = gen_reinterpret_cast(bb, ctx->generic_ptr_type, src_ptr); const Node* ptr_mask = size_t_literal(a, (UINT64_MAX >> (uint64_t) (generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr & 0x001111 ... 111 @@ -267,7 +267,7 @@ static const Node* process(Context* ctx, const Node* old) { default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } KeyHash shd_hash_string(const char** string); @@ -278,13 +278,13 @@ Module* lower_generic_ptrs(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .fns = shd_new_dict(String, const Node*, (HashFn) shd_hash_string, (CmpFn) shd_compare_string), .generic_ptr_type = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false}), .config = config, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_dict(ctx.fns); return dst; } diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index efa9339ee..6a73db87a 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -57,7 +57,7 @@ static const Node* process(Context* ctx, const Node* node) { LARRAY(const Node*, his, old_nodes.count); switch(op) { case add_op: if (should_convert(ctx, shd_first(old_nodes)->type)) { - Nodes new_nodes = rewrite_nodes(&ctx->rewriter, old_nodes); + Nodes new_nodes = shd_rewrite_nodes(&ctx->rewriter, old_nodes); // TODO: convert into and then out of unsigned BodyBuilder* bb = begin_block_pure(a); extract_low_hi_halves_list(bb, new_nodes, lows, his); @@ -76,7 +76,7 @@ static const Node* process(Context* ctx, const Node* node) { } rebuild: - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_int(const CompilerConfig* config, Module* src) { @@ -84,10 +84,10 @@ Module* lower_int(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 9b82b76a5..137ef093f 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -129,10 +129,10 @@ static const Node* process(Context* ctx, const Node* old) { break; BodyBuilder* bb = begin_block_pure(a); // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); - const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, rewrite_node(r, lea.ptr)); - const Type* new_base_t = rewrite_node(&ctx->rewriter, old_base_ptr_t); - const Node* result = lower_ptr_offset(ctx, bb, new_base_t, cast_base, rewrite_node(r, lea.offset)); - const Type* new_ptr_t = rewrite_node(&ctx->rewriter, old_result_t); + const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, shd_rewrite_node(r, lea.ptr)); + const Type* new_base_t = shd_rewrite_node(&ctx->rewriter, old_base_ptr_t); + const Node* result = lower_ptr_offset(ctx, bb, new_base_t, cast_base, shd_rewrite_node(r, lea.offset)); + const Type* new_ptr_t = shd_rewrite_node(&ctx->rewriter, old_result_t); const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); return yield_values_and_wrap_in_block(bb, shd_singleton(cast_result)); } @@ -152,17 +152,17 @@ static const Node* process(Context* ctx, const Node* old) { break; BodyBuilder* bb = begin_block_pure(a); // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); - const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, rewrite_node(r, lea.ptr)); - const Type* new_base_t = rewrite_node(&ctx->rewriter, old_base_ptr_t); - const Node* result = lower_ptr_index(ctx, bb, new_base_t, cast_base, rewrite_node(r, lea.index)); - const Type* new_ptr_t = rewrite_node(&ctx->rewriter, old_result_t); + const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, shd_rewrite_node(r, lea.ptr)); + const Type* new_base_t = shd_rewrite_node(&ctx->rewriter, old_base_ptr_t); + const Node* result = lower_ptr_index(ctx, bb, new_base_t, cast_base, shd_rewrite_node(r, lea.index)); + const Type* new_ptr_t = shd_rewrite_node(&ctx->rewriter, old_result_t); const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); return yield_values_and_wrap_in_block(bb, shd_singleton(cast_result)); } default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } Module* lower_lea(const CompilerConfig* config, Module* src) { @@ -170,10 +170,10 @@ Module* lower_lea(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 4cac7349d..65350fe3f 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -50,7 +50,7 @@ static const Node* process(Context* ctx, const Node* old) { PtrType payload = old->payload.ptr_type; if (!shd_get_arena_config(a)->address_spaces[payload.address_space].physical) payload.is_reference = true; - payload.pointed_type = rewrite_node(r, payload.pointed_type); + payload.pointed_type = shd_rewrite_node(r, payload.pointed_type); return ptr_type(a, payload); } /*case PtrArrayElementOffset_TAG: { @@ -72,13 +72,13 @@ static const Node* process(Context* ctx, const Node* old) { const Type* optr_t = payload.ptr->type; deconstruct_qualified_type(&optr_t); assert(optr_t->tag == PtrType_TAG); - const Type* expected_type = rewrite_node(r, optr_t); - const Node* ptr = rewrite_node(r, payload.ptr); + const Type* expected_type = shd_rewrite_node(r, optr_t); + const Node* ptr = shd_rewrite_node(r, payload.ptr); const Type* actual_type = get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); - return bind_last_instruction_and_wrap_in_block(bb, ptr_composite_element(a, (PtrCompositeElement) { .ptr = ptr, .index = rewrite_node(r, payload.index)})); + return bind_last_instruction_and_wrap_in_block(bb, ptr_composite_element(a, (PtrCompositeElement) { .ptr = ptr, .index = shd_rewrite_node(r, payload.index)})); } case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; @@ -88,7 +88,7 @@ static const Node* process(Context* ctx, const Node* old) { const Type* osrc_t = osrc->type; deconstruct_qualified_type(&osrc_t); if (osrc_t->tag == PtrType_TAG && !shd_get_arena_config(a)->address_spaces[osrc_t->payload.ptr_type.address_space].physical) - return rewrite_node(r, osrc); + return shd_rewrite_node(r, osrc); break; } default: break; @@ -100,41 +100,41 @@ static const Node* process(Context* ctx, const Node* old) { const Type* optr_t = payload.ptr->type; deconstruct_qualified_type(&optr_t); assert(optr_t->tag == PtrType_TAG); - const Type* expected_type = rewrite_node(r, optr_t); - const Node* ptr = rewrite_node(r, payload.ptr); + const Type* expected_type = shd_rewrite_node(r, optr_t); + const Node* ptr = shd_rewrite_node(r, payload.ptr); const Type* actual_type = get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); - return load(a, (Load) { .ptr = yield_value_and_wrap_in_block(bb, ptr), .mem = rewrite_node(r, payload.mem) }); + return load(a, (Load) { .ptr = yield_value_and_wrap_in_block(bb, ptr), .mem = shd_rewrite_node(r, payload.mem) }); } case Store_TAG: { Store payload = old->payload.store; const Type* optr_t = payload.ptr->type; deconstruct_qualified_type(&optr_t); assert(optr_t->tag == PtrType_TAG); - const Type* expected_type = rewrite_node(r, optr_t); - const Node* ptr = rewrite_node(r, payload.ptr); + const Type* expected_type = shd_rewrite_node(r, optr_t); + const Node* ptr = shd_rewrite_node(r, payload.ptr); const Type* actual_type = get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); - return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { .ptr = ptr, .value = rewrite_node(r, payload.value), .mem = rewrite_node(r, payload.mem) })); + return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { .ptr = ptr, .value = shd_rewrite_node(r, payload.value), .mem = shd_rewrite_node(r, payload.mem) })); } case GlobalVariable_TAG: { AddressSpace as = old->payload.global_variable.address_space; if (shd_get_arena_config(a)->address_spaces[as].physical) break; - Nodes annotations = rewrite_nodes(r, old->payload.global_variable.annotations); + Nodes annotations = shd_rewrite_nodes(r, old->payload.global_variable.annotations); annotations = shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Logical" })); - Node* new = global_var(ctx->rewriter.dst_module, annotations, rewrite_node(r, old->payload.global_variable.type), old->payload.global_variable.name, as); - recreate_decl_body_identity(r, old, new); + Node* new = global_var(ctx->rewriter.dst_module, annotations, shd_rewrite_node(r, old->payload.global_variable.type), old->payload.global_variable.name, as); + shd_recreate_node_body(r, old, new); return new; } default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } Module* lower_logical_pointers(const CompilerConfig* config, Module* src) { @@ -145,10 +145,10 @@ Module* lower_logical_pointers(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 6f122261c..17e8d34dc 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -26,8 +26,8 @@ static const Node* process(Context* ctx, const Node* node) { // extract the relevant bit case mask_is_thread_active_op: { BodyBuilder* bb = begin_block_pure(a); - const Node* mask = rewrite_node(&ctx->rewriter, old_nodes.nodes[0]); - const Node* index = rewrite_node(&ctx->rewriter, old_nodes.nodes[1]); + const Node* mask = shd_rewrite_node(&ctx->rewriter, old_nodes.nodes[0]); + const Node* index = shd_rewrite_node(&ctx->rewriter, old_nodes.nodes[1]); index = gen_conversion(bb, get_actual_mask_type(ctx->rewriter.dst_arena), index); const Node* acc = mask; // acc >>= index @@ -45,7 +45,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -58,11 +58,11 @@ Module* lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* src) { assert(mask_type->tag == Int_TAG); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .zero = int_literal(a, (IntLiteral) { .width = mask_type->payload.int_type.width, .value = 0 }), .one = int_literal(a, (IntLiteral) { .width = mask_type->payload.int_type.width, .value = 1 }), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 81f4eb2bd..f568a5f7f 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -25,9 +25,9 @@ static const Node* process(Context* ctx, const Node* old) { CopyBytes payload = old->payload.copy_bytes; const Type* word_type = int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); - const Node* dst_addr = rewrite_node(&ctx->rewriter, payload.dst); + const Node* dst_addr = shd_rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; deconstruct_qualified_type(&dst_addr_type); assert(dst_addr_type->tag == PtrType_TAG); @@ -37,7 +37,7 @@ static const Node* process(Context* ctx, const Node* old) { }); dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); - const Node* src_addr = rewrite_node(&ctx->rewriter, payload.src); + const Node* src_addr = shd_rewrite_node(&ctx->rewriter, payload.src); const Type* src_addr_type = src_addr->type; deconstruct_qualified_type(&src_addr_type); assert(src_addr_type->tag == PtrType_TAG); @@ -47,7 +47,7 @@ static const Node* process(Context* ctx, const Node* old) { }); src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); - const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), rewrite_node(&ctx->rewriter, payload.count)); + const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), shd_rewrite_node(&ctx->rewriter, payload.count)); const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num_in_bytes)); begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); @@ -76,15 +76,15 @@ static const Node* process(Context* ctx, const Node* old) { } case FillBytes_TAG: { FillBytes payload = old->payload.fill_bytes; - const Node* src_value = rewrite_node(&ctx->rewriter, payload.src); + const Node* src_value = shd_rewrite_node(&ctx->rewriter, payload.src); const Type* src_type = src_value->type; deconstruct_qualified_type(&src_type); assert(src_type->tag == Int_TAG); const Type* word_type = src_type;// int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); - const Node* dst_addr = rewrite_node(&ctx->rewriter, payload.dst); + const Node* dst_addr = shd_rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; deconstruct_qualified_type(&dst_addr_type); assert(dst_addr_type->tag == PtrType_TAG); @@ -94,7 +94,7 @@ static const Node* process(Context* ctx, const Node* old) { }); dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); - const Node* num = rewrite_node(&ctx->rewriter, payload.count); + const Node* num = shd_rewrite_node(&ctx->rewriter, payload.count); const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num)); begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); @@ -122,7 +122,7 @@ static const Node* process(Context* ctx, const Node* old) { default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } Module* lower_memcpy(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -131,9 +131,9 @@ Module* lower_memcpy(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process) + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process) }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 7471ed9dd..2a41dfadc 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -19,18 +19,18 @@ static const Node* process(Context* ctx, const Node* old) { case PrimOp_TAG: { switch (old->payload.prim_op.op) { case size_of_op: { - const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); + const Type* t = shd_rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); TypeMemLayout layout = shd_get_mem_layout(a, t); return int_literal(a, (IntLiteral) {.width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false, .value = layout.size_in_bytes}); } case align_of_op: { - const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); + const Type* t = shd_rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); TypeMemLayout layout = shd_get_mem_layout(a, t); return int_literal(a, (IntLiteral) {.width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false, .value = layout.alignment_in_bytes}); } case offset_of_op: { - const Type* t = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); - const Node* n = rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.operands)); + const Type* t = shd_rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); + const Node* n = shd_rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.operands)); const IntLiteral* literal = resolve_to_int_literal(n); assert(literal); t = get_maybe_nominal_type_body(t); @@ -45,7 +45,7 @@ static const Node* process(Context* ctx, const Node* old) { default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } Module* lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -54,9 +54,9 @@ Module* lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* s Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process) + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process) }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index c7587d3ff..ee46dc9c3 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -35,14 +35,14 @@ static const Node* process(Context* ctx, const Node* node) { IrArena* a = r->dst_arena; switch (node->tag) { case NullPtr_TAG: { - const Type* t = rewrite_node(r, node->payload.null_ptr.ptr_type); + const Type* t = shd_rewrite_node(r, node->payload.null_ptr.ptr_type); assert(t->tag == PtrType_TAG); return make_nullptr(ctx, t); } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } KeyHash hash_node(Node**); @@ -53,11 +53,11 @@ Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_dict(ctx.map); return dst; } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 79516ebd5..6b1a2cbc1 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -298,9 +298,9 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; - BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); - const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); - const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); + BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); + const Type* element_type = shd_rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); + const Node* pointer_as_offset = shd_rewrite_node(&ctx->rewriter, payload.ptr); const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, false, ptr_type->payload.ptr_type.address_space); Nodes results = gen_call(bb, fn_addr_helper(a, fn), shd_singleton(pointer_as_offset)); return yield_values_and_wrap_in_block(bb, results); @@ -312,13 +312,13 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; - BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); - const Type* element_type = rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); - const Node* pointer_as_offset = rewrite_node(&ctx->rewriter, payload.ptr); + const Type* element_type = shd_rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); + const Node* pointer_as_offset = shd_rewrite_node(&ctx->rewriter, payload.ptr); const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, true, ptr_type->payload.ptr_type.address_space); - const Node* value = rewrite_node(&ctx->rewriter, payload.value); + const Node* value = shd_rewrite_node(&ctx->rewriter, payload.value); gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, pointer_as_offset, value)); return yield_values_and_wrap_in_block(bb, shd_empty(a)); } @@ -343,14 +343,14 @@ static const Node* process_node(Context* ctx, const Node* old) { } case Function_TAG: { if (strcmp(get_abstraction_name(old), "generated_init") == 0) { - Node* new = recreate_decl_header_identity(&ctx->rewriter, old); + Node* new = shd_recreate_node_head(&ctx->rewriter, old); BodyBuilder *bb = begin_body_with_mem(a, get_abstraction_mem(new)); for (AddressSpace as = 0; as < NumAddressSpaces; as++) { if (is_as_emulated(ctx, as)) store_init_data(ctx, as, ctx->collected[as], bb); } - register_processed(&ctx->rewriter, get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(new, finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body))); + shd_register_processed(&ctx->rewriter, get_abstraction_mem(old), bb_mem(bb)); + set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } break; @@ -358,7 +358,7 @@ static const Node* process_node(Context* ctx, const Node* old) { default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } KeyHash hash_node(Node**); @@ -397,12 +397,12 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect const Node* decl = collected.nodes[i]; const Type* type = decl->payload.global_variable.type; - member_tys[i] = rewrite_node(&ctx->rewriter, type); + member_tys[i] = shd_rewrite_node(&ctx->rewriter, type); member_names[i] = decl->payload.global_variable.name; // Turn the old global variable into a pointer (which are also now integers) const Type* emulated_ptr_type = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); - Nodes annotations = rewrite_nodes(&ctx->rewriter, decl->payload.global_variable.annotations); + Nodes annotations = shd_rewrite_nodes(&ctx->rewriter, decl->payload.global_variable.annotations); Node* new_address = constant(ctx->rewriter.dst_module, annotations, emulated_ptr_type, decl->payload.global_variable.name); // we need to compute the actual pointer by getting the offset and dividing it @@ -411,7 +411,7 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect const Node* offset = gen_primop_e(bb, offset_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_singleton(size_t_literal(a, i))); new_address->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(offset)); - register_processed(&ctx->rewriter, decl, new_address); + shd_register_processed(&ctx->rewriter, decl, new_address); } const Type* record_t = record_type(a, (RecordType) { @@ -433,9 +433,9 @@ static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, Body assert(old_decl->tag == GlobalVariable_TAG); const Node* old_init = old_decl->payload.global_variable.init; if (old_init) { - const Node* value = rewrite_node(r, old_init); + const Node* value = shd_rewrite_node(r, old_init); const Node* fn = gen_serdes_fn(ctx, get_unqualified_type(value->type), false, true, old_decl->payload.global_variable.address_space); - gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, rewrite_node(r, ref_decl_helper(oa, old_decl)), value)); + gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, shd_rewrite_node(r, ref_decl_helper(oa, old_decl)), value)); } } } @@ -490,7 +490,7 @@ Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, }; @@ -509,8 +509,8 @@ Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { } } - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); for (size_t i = 0; i < NumAddressSpaces; i++) { if (is_as_emulated(&ctx, i)) { diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index c8754d248..a5bd0944d 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -94,7 +94,7 @@ static const Node* process_node(Context* ctx, const Node* old) { IrArena* a = r->dst_arena; if (old->tag == Function_TAG && strcmp(get_abstraction_name(old), "generated_init") == 0) { - Node* new = recreate_decl_header_identity(&ctx->rewriter, old); + Node* new = shd_recreate_node_head(&ctx->rewriter, old); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); // Make sure to zero-init the stack pointers @@ -104,8 +104,8 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* stack_pointer = ctx->stack_pointer; gen_store(bb, stack_pointer, shd_uint32_literal(a, 0)); } - register_processed(r, get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(new, finish_body(bb, rewrite_node(&ctx->rewriter, old->payload.fun.body))); + shd_register_processed(r, get_abstraction_mem(old), bb_mem(bb)); + set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } @@ -113,22 +113,22 @@ static const Node* process_node(Context* ctx, const Node* old) { case GetStackSize_TAG: { assert(ctx->stack); GetStackSize payload = old->payload.get_stack_size; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); const Node* sp = gen_load(bb, ctx->stack_pointer); return yield_values_and_wrap_in_block(bb, shd_singleton(sp)); } case SetStackSize_TAG: { assert(ctx->stack); SetStackSize payload = old->payload.set_stack_size; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - const Node* val = rewrite_node(r, old->payload.set_stack_size.value); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + const Node* val = shd_rewrite_node(r, old->payload.set_stack_size.value); gen_store(bb, ctx->stack_pointer, val); return yield_values_and_wrap_in_block(bb, shd_empty(a)); } case GetStackBaseAddr_TAG: { assert(ctx->stack); GetStackBaseAddr payload = old->payload.get_stack_base_addr; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); const Node* stack_pointer = ctx->stack_pointer; const Node* stack_size = gen_load(bb, stack_pointer); const Node* stack_base_ptr = gen_lea(bb, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); @@ -140,13 +140,13 @@ static const Node* process_node(Context* ctx, const Node* old) { case PushStack_TAG:{ assert(ctx->stack); PushStack payload = old->payload.push_stack; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - const Type* element_type = rewrite_node(&ctx->rewriter, get_unqualified_type(old->payload.push_stack.value->type)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + const Type* element_type = shd_rewrite_node(&ctx->rewriter, get_unqualified_type(old->payload.push_stack.value->type)); bool push = true; const Node* fn = gen_fn(ctx, element_type, push); - Nodes args = shd_singleton(rewrite_node(&ctx->rewriter, old->payload.push_stack.value)); + Nodes args = shd_singleton(shd_rewrite_node(&ctx->rewriter, old->payload.push_stack.value)); gen_call(bb, fn_addr_helper(a, fn), args); return yield_values_and_wrap_in_block(bb, shd_empty(a)); @@ -154,8 +154,8 @@ static const Node* process_node(Context* ctx, const Node* old) { case PopStack_TAG: { assert(ctx->stack); PopStack payload = old->payload.pop_stack; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - const Type* element_type = rewrite_node(&ctx->rewriter, old->payload.pop_stack.type); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + const Type* element_type = shd_rewrite_node(&ctx->rewriter, old->payload.pop_stack.type); bool push = false; @@ -168,7 +168,7 @@ static const Node* process_node(Context* ctx, const Node* old) { default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } KeyHash hash_node(Node**); @@ -180,7 +180,7 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, @@ -209,8 +209,8 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { ctx.stack_pointer = ref_decl_helper(a, stack_ptr_decl); } - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_dict(ctx.push); shd_destroy_dict(ctx.pop); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 99476ddb2..e1729b27b 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -135,14 +135,14 @@ static const Node* process(Context* ctx, const Node* node) { case ExtInstr_TAG: { ExtInstr payload = node->payload.ext_instr; if (strcmp(payload.set, "spirv.core") == 0 && payload.opcode == SpvOpGroupNonUniformBroadcastFirst) { - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, shd_singleton( - build_subgroup_first(ctx, bb, rewrite_node(r, payload.operands.nodes[0]), rewrite_node(r, payload.operands.nodes[1])))); + build_subgroup_first(ctx, bb, shd_rewrite_node(r, payload.operands.nodes[0]), shd_rewrite_node(r, payload.operands.nodes[1])))); } } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } KeyHash hash_node(Node**); @@ -154,12 +154,12 @@ Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); assert(!config->lower.emulate_subgroup_ops && "TODO"); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .fns = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node) }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_dict(ctx.fns); return dst; } diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 5938554de..42ea36878 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -19,16 +19,16 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Function_TAG: { - Node* newfun = recreate_decl_header_identity(r, node); + Node* newfun = shd_recreate_node_head(r, node); if (get_abstraction_body(node)) { Context functx = *ctx; functx.rewriter.map = shd_clone_dict(functx.rewriter.map); shd_dict_clear(functx.rewriter.map); - register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); + shd_register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); - register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); - set_abstraction_body(post_prelude, rewrite_node(&functx.rewriter, get_abstraction_body(node))); + shd_register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); + set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, shd_empty(a)))); shd_destroy_dict(functx.rewriter.map); @@ -38,7 +38,7 @@ static const Node* process(Context* ctx, const Node* node) { case PtrType_TAG: { AddressSpace as = node->payload.ptr_type.address_space; if (as == AsSubgroup) { - return ptr_type(a, (PtrType) { .pointed_type = rewrite_op(&ctx->rewriter, NcType, "pointed_type", node->payload.ptr_type.pointed_type), .address_space = AsShared, .is_reference = node->payload.ptr_type.is_reference }); + return ptr_type(a, (PtrType) { .pointed_type = shd_rewrite_op(&ctx->rewriter, NcType, "pointed_type", node->payload.ptr_type.pointed_type), .address_space = AsShared, .is_reference = node->payload.ptr_type.is_reference }); } break; } @@ -46,7 +46,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* odecl = node->payload.ref_decl.decl; if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsSubgroup) break; - const Node* ndecl = rewrite_node(&ctx->rewriter, odecl); + const Node* ndecl = shd_rewrite_node(&ctx->rewriter, odecl); assert(ctx->bb); const Node* index = gen_builtin_load(ctx->rewriter.dst_module, ctx->bb, BuiltinSubgroupId); const Node* slice = gen_lea(ctx->bb, ref_decl_helper(a, ndecl), shd_int32_literal(a, 0), mk_nodes(a, index)); @@ -55,20 +55,20 @@ static const Node* process(Context* ctx, const Node* node) { case GlobalVariable_TAG: { AddressSpace as = node->payload.global_variable.address_space; if (as == AsSubgroup) { - const Type* ntype = rewrite_node(&ctx->rewriter, node->payload.global_variable.type); + const Type* ntype = shd_rewrite_node(&ctx->rewriter, node->payload.global_variable.type); const Type* atype = arr_type(a, (ArrType) { .element_type = ntype, - .size = ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_declaration(ctx->rewriter.src_module, "SUBGROUPS_PER_WG"))) + .size = ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, get_declaration(ctx->rewriter.src_module, "SUBGROUPS_PER_WG"))) }); assert(shd_lookup_annotation(node, "Logical") && "All subgroup variables should be logical by now!"); - Node* new = global_var(ctx->rewriter.dst_module, rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations), atype, node->payload.global_variable.name, AsShared); - register_processed(&ctx->rewriter, node, new); + Node* new = global_var(ctx->rewriter.dst_module, shd_rewrite_nodes(&ctx->rewriter, node->payload.global_variable.annotations), atype, node->payload.global_variable.name, AsShared); + shd_register_processed(&ctx->rewriter, node, new); if (node->payload.global_variable.init) { new->payload.global_variable.init = fill(a, (Fill) { .type = atype, - .value = rewrite_node(&ctx->rewriter, node->payload.global_variable.init) + .value = shd_rewrite_node(&ctx->rewriter, node->payload.global_variable.init) }); } return new; @@ -81,10 +81,10 @@ static const Node* process(Context* ctx, const Node* node) { if (is_declaration(node)) { Context declctx = *ctx; declctx.bb = NULL; - return recreate_node_identity(&declctx.rewriter, node); + return shd_recreate_node(&declctx.rewriter, node); } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { @@ -92,10 +92,10 @@ Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 382f54634..335d20482 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -136,9 +136,9 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Match_TAG: { Match payload = node->payload.match_instr; - Nodes yield_types = rewrite_nodes(&ctx->rewriter, node->payload.match_instr.yield_types); - Nodes literals = rewrite_nodes(&ctx->rewriter, node->payload.match_instr.literals); - Nodes cases = rewrite_nodes(&ctx->rewriter, node->payload.match_instr.cases); + Nodes yield_types = shd_rewrite_nodes(&ctx->rewriter, node->payload.match_instr.yield_types); + Nodes literals = shd_rewrite_nodes(&ctx->rewriter, node->payload.match_instr.literals); + Nodes cases = shd_rewrite_nodes(&ctx->rewriter, node->payload.match_instr.cases); // TODO handle degenerate no-cases case ? // TODO or maybe do that in fold() @@ -153,7 +153,7 @@ static const Node* process(Context* ctx, const Node* node) { root = insert(root, t); } - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); const Node* run_default_case = gen_stack_alloc(bb, bool_type(a)); gen_store(bb, run_default_case, false_lit(a)); @@ -177,7 +177,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_switch_btree(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -186,9 +186,9 @@ Module* lower_switch_btree(SHADY_UNUSED const CompilerConfig* config, Module* sr Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 221b7e998..caf536510 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -73,8 +73,8 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { Context ctx2 = *ctx; IrArena* a = ctx->rewriter.dst_arena; // For the lifted entry point, we keep _all_ annotations - Nodes rewritten_params = recreate_params(&ctx2.rewriter, old->payload.fun.params); - Node* new_entry_pt = function(ctx2.rewriter.dst_module, rewritten_params, old->payload.fun.name, rewrite_nodes(&ctx2.rewriter, old->payload.fun.annotations), shd_nodes(a, 0, NULL)); + Nodes rewritten_params = shd_recreate_params(&ctx2.rewriter, old->payload.fun.params); + Node* new_entry_pt = function(ctx2.rewriter.dst_module, rewritten_params, old->payload.fun.name, shd_rewrite_nodes(&ctx2.rewriter, old->payload.fun.annotations), shd_nodes(a, 0, NULL)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_entry_pt)); @@ -119,14 +119,14 @@ static const Node* process(Context* ctx, const Node* old) { // Leave leaf-calls alone :) ctx2.disable_lowering = shd_lookup_annotation(old, "Leaf") || !old->payload.fun.body; if (ctx2.disable_lowering) { - Node* fun = recreate_decl_header_identity(&ctx2.rewriter, old); + Node* fun = shd_recreate_node_head(&ctx2.rewriter, old); if (old->payload.fun.body) { BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); if (entry_point_annotation) { gen_call(bb, fn_addr_helper(a, ctx2.init_fn), shd_empty(a)); } - register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); + shd_register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); } destroy_uses_map(ctx2.uses); @@ -136,14 +136,14 @@ static const Node* process(Context* ctx, const Node* old) { assert(ctx->config->dynamic_scheduling && "Dynamic scheduling is disabled, but we encountered a non-leaf function"); - Nodes new_annotations = rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); + Nodes new_annotations = shd_rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); new_annotations = shd_nodes_append(a, new_annotations, annotation_value(a, (AnnotationValue) { .name = "FnId", .value = lower_fn_addr(ctx, old) })); new_annotations = shd_nodes_append(a, new_annotations, annotation(a, (Annotation) { .name = "Leaf" })); String new_name = shd_format_string_arena(a->arena, "%s_indirect", old->payload.fun.name); Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, 0, NULL), new_name, shd_filter_out_annotation(a, new_annotations, "EntryPoint"), shd_nodes(a, 0, NULL)); - register_processed(&ctx->rewriter, old, fun); + shd_register_processed(&ctx->rewriter, old, fun); if (entry_point_annotation) lift_entry_point(ctx, old, fun); @@ -152,17 +152,17 @@ static const Node* process(Context* ctx, const Node* old) { // Params become stack pops ! for (size_t i = 0; i < old->payload.fun.params.count; i++) { const Node* old_param = old->payload.fun.params.nodes[i]; - const Type* new_param_type = rewrite_node(&ctx->rewriter, get_unqualified_type(old_param->type)); + const Type* new_param_type = shd_rewrite_node(&ctx->rewriter, get_unqualified_type(old_param->type)); const Node* popped = gen_pop_value_stack(bb, new_param_type); // TODO use the uniform stack instead ? or no ? if (is_qualified_type_uniform(old_param->type)) popped = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = shd_empty(a), .operands = shd_singleton(popped) }); if (old_param->payload.param.name) set_value_name((Node*) popped, old_param->payload.param.name); - register_processed(&ctx->rewriter, old_param, popped); + shd_register_processed(&ctx->rewriter, old_param, popped); } - register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); + shd_register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); destroy_uses_map(ctx2.uses); destroy_cfg(ctx2.cfg); return fun; @@ -172,9 +172,9 @@ static const Node* process(Context* ctx, const Node* old) { Call payload = old->payload.call; assert(payload.callee->tag == FnAddr_TAG && "Only direct calls should survive this pass"); return call(a, (Call) { - .callee = fn_addr_helper(a, rewrite_node(&ctx->rewriter, payload.callee->payload.fn_addr.fn)), - .args = rewrite_nodes(&ctx->rewriter, payload.args), - .mem = rewrite_node(r, payload.mem) + .callee = fn_addr_helper(a, shd_rewrite_node(&ctx->rewriter, payload.callee->payload.fn_addr.fn)), + .args = shd_rewrite_nodes(&ctx->rewriter, payload.args), + .mem = shd_rewrite_node(r, payload.mem) }); } case JoinPointType_TAG: return type_decl_ref(a, (TypeDeclRef) { @@ -184,7 +184,7 @@ static const Node* process(Context* ctx, const Node* old) { ExtInstr payload = old->payload.ext_instr; if (strcmp(payload.set, "shady.internal") == 0) { String callee_name = NULL; - Nodes args = rewrite_nodes(r, payload.operands); + Nodes args = shd_rewrite_nodes(r, payload.operands); switch ((ShadyJoinPointOpcodes ) payload.opcode) { case ShadyOpDefaultJoinPoint: callee_name = "builtin_entry_join_point"; @@ -195,7 +195,7 @@ static const Node* process(Context* ctx, const Node* old) { break; } return call(a, (Call) { - .mem = rewrite_node(r, payload.mem), + .mem = shd_rewrite_node(r, payload.mem), .callee = access_decl(r, callee_name), .args = args, }); @@ -206,9 +206,9 @@ static const Node* process(Context* ctx, const Node* old) { //if (ctx->disable_lowering) // return recreate_node_identity(&ctx->rewriter, old); TailCall payload = old->payload.tail_call; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, payload.args)); - const Node* target = rewrite_node(&ctx->rewriter, payload.callee); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + gen_push_values_stack(bb, shd_rewrite_nodes(&ctx->rewriter, payload.args)); + const Node* target = shd_rewrite_node(&ctx->rewriter, payload.callee); target = gen_conversion(bb, shd_uint32_type(a), target); gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); @@ -219,14 +219,14 @@ static const Node* process(Context* ctx, const Node* old) { //if (ctx->disable_lowering) // return recreate_node_identity(&ctx->rewriter, old); - const Node* jp = rewrite_node(&ctx->rewriter, old->payload.join.join_point); + const Node* jp = shd_rewrite_node(&ctx->rewriter, old->payload.join.join_point); const Node* jp_type = jp->type; deconstruct_qualified_type(&jp_type); if (jp_type->tag == JoinPointType_TAG) break; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - gen_push_values_stack(bb, rewrite_nodes(&ctx->rewriter, old->payload.join.args)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + gen_push_values_stack(bb, shd_rewrite_nodes(&ctx->rewriter, old->payload.join.args)); const Node* jp_payload = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 2))); gen_push_value_stack(bb, jp_payload); const Node* dst = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 1))); @@ -253,20 +253,20 @@ static const Node* process(Context* ctx, const Node* old) { deconstruct_qualified_type(&old_jp_type); assert(old_jp_type->tag == JoinPointType_TAG); const Node* new_jp_type = join_point_type(a, (JoinPointType) { - .yield_types = rewrite_nodes(&ctx->rewriter, old_jp_type->payload.join_point_type.yield_types), + .yield_types = shd_rewrite_nodes(&ctx->rewriter, old_jp_type->payload.join_point_type.yield_types), }); const Node* new_jp = param(a, shd_as_qualified_type(new_jp_type, true), old_jp->payload.param.name); - register_processed(&ctx->rewriter, old_jp, new_jp); + shd_register_processed(&ctx->rewriter, old_jp, new_jp); Node* new_control_case = case_(a, shd_singleton(new_jp)); - register_processed(r, payload.inside, new_control_case); - set_abstraction_body(new_control_case, rewrite_node(&ctx->rewriter, get_abstraction_body(payload.inside))); + shd_register_processed(r, payload.inside, new_control_case); + set_abstraction_body(new_control_case, shd_rewrite_node(&ctx->rewriter, get_abstraction_body(payload.inside))); // BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - Nodes nyield_types = rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types); + Nodes nyield_types = shd_rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types); return control(a, (Control) { .yield_types = nyield_types, .inside = new_control_case, - .tail = rewrite_node(r, get_structured_construct_tail(old)), - .mem = rewrite_node(r, payload.mem), + .tail = shd_rewrite_node(r, get_structured_construct_tail(old)), + .mem = shd_rewrite_node(r, payload.mem), }); //return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, new_body)); } @@ -275,7 +275,7 @@ static const Node* process(Context* ctx, const Node* old) { default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } void generate_top_level_dispatch_fn(Context* ctx) { @@ -387,7 +387,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } - gen_call(if_builder, fn_addr_helper(a, rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); + gen_call(if_builder, fn_addr_helper(a, shd_rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); Node* if_false = case_(a, shd_empty(a)); @@ -452,7 +452,7 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) Node* top_dispatcher_fn = NULL; Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .disable_lowering = false, .assigned_fn_ptrs = ptrs, @@ -462,13 +462,13 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) .init_fn = init_fn, }; - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); // Generate the top dispatcher, but only if it is used for realsies if (*ctx.top_dispatcher_fn) generate_top_level_dispatch_fn(&ctx); shd_destroy_dict(ptrs); - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index b3d12872f..35e2903af 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -16,10 +16,10 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { deconstruct_qualified_type(&dst_type); size_t width = deconstruct_maybe_packed_type(&dst_type); if (width == 1) - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); LARRAY(const Node*, elements, width); BodyBuilder* bb = begin_block_pure(a); - Nodes noperands = rewrite_nodes(&ctx->rewriter, old->payload.prim_op.operands); + Nodes noperands = shd_rewrite_nodes(&ctx->rewriter, old->payload.prim_op.operands); for (size_t i = 0; i < width; i++) { LARRAY(const Node*, nops, noperands.count); for (size_t j = 0; j < noperands.count; j++) @@ -27,7 +27,7 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { elements[i] = gen_primop_e(bb, old->payload.prim_op.op, shd_empty(a), shd_nodes(a, noperands.count, nops)); } const Type* t = arr_type(a, (ArrType) { - .element_type = rewrite_node(&ctx->rewriter, dst_type), + .element_type = shd_rewrite_node(&ctx->rewriter, dst_type), .size = shd_int32_literal(a, width) }); return yield_values_and_wrap_in_block(bb, shd_singleton(composite_helper(a, t, shd_nodes(a, width, elements)))); @@ -39,7 +39,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case PackType_TAG: { return arr_type(a, (ArrType) { - .element_type = rewrite_node(&ctx->rewriter, node->payload.pack_type.element_type), + .element_type = shd_rewrite_node(&ctx->rewriter, node->payload.pack_type.element_type), .size = shd_int32_literal(a, node->payload.pack_type.width) }); } @@ -50,7 +50,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_vec_arr(const CompilerConfig* config, Module* src) { @@ -59,10 +59,10 @@ Module* lower_vec_arr(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 6573427ce..b5fa1c6cb 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -36,16 +36,16 @@ static const Node* process(Context* ctx, const Node* node) { case GlobalVariable_TAG: { const Node* ba = shd_lookup_annotation(node, "Builtin"); if (ba) { - Nodes filtered_as = rewrite_nodes(&ctx->rewriter, shd_filter_out_annotation(a, node->payload.global_variable.annotations, "Builtin")); + Nodes filtered_as = shd_rewrite_nodes(&ctx->rewriter, shd_filter_out_annotation(a, node->payload.global_variable.annotations, "Builtin")); Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); switch (b) { case BuiltinSubgroupId: case BuiltinWorkgroupId: case BuiltinGlobalInvocationId: case BuiltinLocalInvocationId: - return global_var(m, filtered_as, rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsPrivate); + return global_var(m, filtered_as, shd_rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsPrivate); case BuiltinNumWorkgroups: - return global_var(m, filtered_as, rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsExternal); + return global_var(m, filtered_as, shd_rewrite_node(&ctx->rewriter, node->payload.global_variable.type), node->payload.global_variable.name, AsExternal); default: break; } @@ -61,21 +61,21 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.is_entry_point = true; assert(node->payload.fun.return_types.count == 0 && "entry points do not return at this stage"); - Nodes wannotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); - Nodes wparams = recreate_params(&ctx->rewriter, node->payload.fun.params); + Nodes wannotations = shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); + Nodes wparams = shd_recreate_params(&ctx->rewriter, node->payload.fun.params); Node* wrapper = function(m, wparams, get_abstraction_name(node), wannotations, shd_empty(a)); - register_processed(&ctx->rewriter, node, wrapper); + shd_register_processed(&ctx->rewriter, node, wrapper); // recreate the old entry point, but this time it's not the entry point anymore Nodes nannotations = shd_filter_out_annotation(a, wannotations, "EntryPoint"); - Nodes nparams = recreate_params(&ctx->rewriter, node->payload.fun.params); + Nodes nparams = shd_recreate_params(&ctx->rewriter, node->payload.fun.params); Node* inner = function(m, nparams, shd_format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, shd_empty(a)); - register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); - register_processed(&ctx->rewriter, get_abstraction_mem(node), get_abstraction_mem(inner)); - set_abstraction_body(inner, recreate_node_identity(&ctx->rewriter, node->payload.fun.body)); + shd_register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); + shd_register_processed(&ctx->rewriter, get_abstraction_mem(node), get_abstraction_mem(inner)); + set_abstraction_body(inner, shd_recreate_node(&ctx->rewriter, node->payload.fun.body)); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(wrapper)); - const Node* num_workgroups_var = rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); + const Node* num_workgroups_var = shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); const Node* workgroup_num_vec3 = gen_load(bb, ref_decl_helper(a, num_workgroups_var)); // prepare variables for iterating over workgroups @@ -127,19 +127,19 @@ static const Node* process(Context* ctx, const Node* node) { // BodyBuilder* bb2 = begin_block_with_side_effects(a, bb_mem(builders[5])); BodyBuilder* bb2 = builders[5]; // write the workgroup ID - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); + gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); // write the local ID const Node* local_id[3]; // local_id[0] = SUBGROUP_SIZE * subgroup_id[0] + subgroup_local_id local_id[0] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); local_id[1] = subgroup_id[1]; local_id[2] = subgroup_id[2]; - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); + gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); // write the global ID const Node* global_id[3]; for (int dim = 0; dim < 3; dim++) global_id[dim] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); - gen_store(bb2, ref_decl_helper(a, rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); + gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID gen_call(bb2, fn_addr_helper(a, inner), wparams); @@ -168,7 +168,7 @@ static const Node* process(Context* ctx, const Node* node) { set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); return wrapper; } - return recreate_node_identity(&ctx2.rewriter, node); + return shd_recreate_node(&ctx2.rewriter, node); } case Load_TAG: { Load payload = node->payload.load; @@ -176,8 +176,8 @@ static const Node* process(Context* ctx, const Node* node) { if (ptr->tag == RefDecl_TAG) ptr = ptr->payload.ref_decl.decl; if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - const Node* loaded = shd_first(bind_instruction(bb, recreate_node_identity(&ctx->rewriter, node))); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + const Node* loaded = shd_first(bind_instruction(bb, shd_recreate_node(&ctx->rewriter, node))); const Node* uniformized = shd_first(gen_primop(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(loaded))); return yield_values_and_wrap_in_block(bb, shd_singleton(uniformized)); } @@ -185,7 +185,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* lower_workgroups(const CompilerConfig* config, Module* src) { @@ -193,12 +193,12 @@ Module* lower_workgroups(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .globals = calloc(sizeof(Node*), PRIMOPS_COUNT), }; - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); free(ctx.globals); - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index d51c14848..3ccb20806 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -102,12 +102,12 @@ static const Node* process(Context* ctx, const Node* node) { fn_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); ctx = &fn_ctx; - Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); - Node* new = function(ctx->rewriter.dst_module, recreate_params(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); + Nodes annotations = shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); + Node* new = function(ctx->rewriter.dst_module, shd_recreate_params(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); for (size_t i = 0; i < new->payload.fun.params.count; i++) - register_processed(&ctx->rewriter, node->payload.fun.params.nodes[i], new->payload.fun.params.nodes[i]); - register_processed(&ctx->rewriter, node, new); - recreate_decl_body_identity(&ctx->rewriter, node, new); + shd_register_processed(&ctx->rewriter, node->payload.fun.params.nodes[i], new->payload.fun.params.nodes[i]); + shd_register_processed(&ctx->rewriter, node, new); + shd_recreate_node_body(&ctx->rewriter, node, new); if (fn_ctx.is_leaf) { shd_debugv_print("Function %s is a leaf function!\n", get_abstraction_name(node)); @@ -145,7 +145,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } KeyHash hash_node(Node**); @@ -156,13 +156,13 @@ Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* s IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .fns = shd_new_dict(const Node*, FnInfo, (HashFn) hash_node, (CmpFn) compare_node), .graph = new_callgraph(src) }; - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); shd_destroy_dict(ctx.fns); destroy_callgraph(ctx.graph); - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 0d8961970..d141ee66a 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -23,7 +23,7 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); assert(b != BuiltinsCount); const Type* expected_t = shd_get_builtin_type(a, b); - const Type* actual_t = rewrite_node(&ctx->rewriter, src)->payload.global_variable.type; + const Type* actual_t = shd_rewrite_node(&ctx->rewriter, src)->payload.global_variable.type; if (expected_t != actual_t) { shd_log_fmt(INFO, "normalize_builtins: found builtin decl '%s' not matching expected type: '", global_variable.name); shd_log_node(INFO, expected_t); @@ -65,9 +65,9 @@ static const Node* process(Context* ctx, const Node* node) { if (ctx->builtins[b]) return ctx->builtins[b]; const Type* t = shd_get_builtin_type(a, b); - Node* ndecl = global_var(r->dst_module, rewrite_nodes(r, global_variable.annotations), t, global_variable.name, + Node* ndecl = global_var(r->dst_module, shd_rewrite_nodes(r, global_variable.annotations), t, global_variable.name, shd_get_builtin_address_space(b)); - register_processed(r, node, ndecl); + shd_register_processed(r, node, ndecl); // no 'init' for builtins, right ? assert(!global_variable.init); ctx->builtins[b] = ndecl; @@ -79,8 +79,8 @@ static const Node* process(Context* ctx, const Node* node) { const Type* req_cast = get_req_cast(ctx, node->payload.load.ptr); if (req_cast) { assert(is_data_type(req_cast)); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.load.mem)); - const Node* r1 = shd_first(bind_instruction(bb, recreate_node_identity(r, node))); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, node->payload.load.mem)); + const Node* r1 = shd_first(bind_instruction(bb, shd_recreate_node(r, node))); const Node* r2 = shd_first(gen_primop(bb, reinterpret_op, shd_singleton(req_cast), shd_singleton(r1))); return yield_values_and_wrap_in_block(bb, shd_singleton(r2)); } @@ -89,7 +89,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -98,11 +98,11 @@ Module* normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* sr IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .builtins = calloc(sizeof(Node*), BuiltinsCount) }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); free(ctx.builtins); return dst; } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index a30156773..5246e0439 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -138,10 +138,10 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t IrArena* a = ctx->rewriter.dst_arena; Rewriter* r = &ctx->rewriter; - const Node* nmem = rewrite_node(r, old->tag == StackAlloc_TAG ? old->payload.stack_alloc.mem : old->payload.local_alloc.mem); + const Node* nmem = shd_rewrite_node(r, old->tag == StackAlloc_TAG ? old->payload.stack_alloc.mem : old->payload.local_alloc.mem); AllocaInfo* k = shd_arena_alloc(ctx->arena, sizeof(AllocaInfo)); - *k = (AllocaInfo) { .type = rewrite_node(r, old_type) }; + *k = (AllocaInfo) { .type = shd_rewrite_node(r, old_type) }; assert(ctx->uses); visit_ptr_uses(old, old_type, k, ctx->uses); shd_dict_insert(const Node*, AllocaInfo*, ctx->alloca_info, old, k); @@ -151,19 +151,19 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t if (!k->leaks) { if (!k->read_from/* this should include killing dead stores! */) { *ctx->todo |= true; - const Node* new = undef(a, (Undef) { .type = get_unqualified_type(rewrite_node(r, old->type)) }); + const Node* new = undef(a, (Undef) { .type = get_unqualified_type(shd_rewrite_node(r, old->type)) }); new = mem_and_value(a, (MemAndValue) { .value = new, .mem = nmem }); k->new = new; return new; } if (!k->non_logical_use && shd_get_arena_config(a)->optimisations.weaken_non_leaking_allocas) { *ctx->todo |= old->tag != LocalAlloc_TAG; - const Node* new = local_alloc(a, (LocalAlloc) { .type = rewrite_node(r, old_type), .mem = nmem }); + const Node* new = local_alloc(a, (LocalAlloc) { .type = shd_rewrite_node(r, old_type), .mem = nmem }); k->new = new; return new; } } - const Node* new = recreate_node_identity(r, old); + const Node* new = shd_recreate_node(r, old); k->new = new; return new; } @@ -174,31 +174,31 @@ static const Node* process(Context* ctx, const Node* old) { switch (old->tag) { case Function_TAG: { - Node* fun = recreate_decl_header_identity(&ctx->rewriter, old); + Node* fun = shd_recreate_node_head(&ctx->rewriter, old); Context fun_ctx = *ctx; fun_ctx.uses = create_fn_uses_map(old, (NcDeclaration | NcType)); fun_ctx.disable_lowering = shd_lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); if (old->payload.fun.body) - set_abstraction_body(fun, rewrite_node(&fun_ctx.rewriter, old->payload.fun.body)); + set_abstraction_body(fun, shd_rewrite_node(&fun_ctx.rewriter, old->payload.fun.body)); destroy_uses_map(fun_ctx.uses); return fun; } case Constant_TAG: { Context fun_ctx = *ctx; fun_ctx.uses = NULL; - return recreate_node_identity(&fun_ctx.rewriter, old); + return shd_recreate_node(&fun_ctx.rewriter, old); } case Load_TAG: { Load payload = old->payload.load; - rewrite_node(r, payload.mem); + shd_rewrite_node(r, payload.mem); PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { - const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.ptr->type))); + const Type* access_type = get_pointer_type_element(get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { - if (k.src_alloca->new == rewrite_node(r, payload.ptr)) + if (k.src_alloca->new == shd_rewrite_node(r, payload.ptr)) break; *ctx->todo |= true; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); const Node* data = gen_load(bb, k.src_alloca->new); data = gen_reinterpret_cast(bb, access_type, data); return yield_value_and_wrap_in_block(bb, data); @@ -208,16 +208,16 @@ static const Node* process(Context* ctx, const Node* old) { } case Store_TAG: { Store payload = old->payload.store; - rewrite_node(r, payload.mem); + shd_rewrite_node(r, payload.mem); PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { - const Type* access_type = get_pointer_type_element(get_unqualified_type(rewrite_node(r, payload.ptr->type))); + const Type* access_type = get_pointer_type_element(get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { - if (k.src_alloca->new == rewrite_node(r, payload.ptr)) + if (k.src_alloca->new == shd_rewrite_node(r, payload.ptr)) break; *ctx->todo |= true; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - const Node* data = gen_reinterpret_cast(bb, access_type, rewrite_node(r, payload.value)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + const Node* data = gen_reinterpret_cast(bb, access_type, shd_rewrite_node(r, payload.value)); gen_store(bb, k.src_alloca->new, data); return yield_values_and_wrap_in_block(bb, shd_empty(a)); } @@ -228,7 +228,7 @@ static const Node* process(Context* ctx, const Node* old) { case StackAlloc_TAG: return handle_alloc(ctx, old, old->payload.stack_alloc.type); default: break; } - return recreate_node_identity(&ctx->rewriter, old); + return shd_recreate_node(&ctx->rewriter, old); } KeyHash hash_node(const Node**); @@ -240,14 +240,14 @@ bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { IrArena* a = get_module_arena(src); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .arena = shd_new_arena(), .alloca_info = shd_new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), .todo = &todo }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_dict(ctx.alloca_info); shd_destroy_arena(ctx.arena); *m = dst; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 7eb64f18c..acd24ac7d 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -118,10 +118,10 @@ static const Node* inline_call(Context* ctx, const Node* ocallee, const Node* nm inline_context.inlined_call = &inlined_call; Nodes oparams = get_abstraction_params(ocallee); - register_processed_list(&inline_context.rewriter, oparams, nargs); - register_processed(&inline_context.rewriter, get_abstraction_mem(ocallee), nmem); + shd_register_processed_list(&inline_context.rewriter, oparams, nargs); + shd_register_processed(&inline_context.rewriter, get_abstraction_mem(ocallee), nmem); - const Node* nbody = rewrite_node(&inline_context.rewriter, get_abstraction_body(ocallee)); + const Node* nbody = shd_rewrite_node(&inline_context.rewriter, get_abstraction_body(ocallee)); shd_destroy_dict(inline_context.rewriter.map); @@ -145,9 +145,9 @@ static const Node* process(Context* ctx, const Node* node) { } } - Nodes annotations = rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); - Node* new = function(ctx->rewriter.dst_module, recreate_params(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); - register_processed(r, node, new); + Nodes annotations = shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); + Node* new = function(ctx->rewriter.dst_module, shd_recreate_params(&ctx->rewriter, node->payload.fun.params), node->payload.fun.name, annotations, shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); + shd_register_processed(r, node, new); Context fn_ctx = *ctx; fn_ctx.rewriter.map = shd_clone_dict(fn_ctx.rewriter.map); @@ -155,8 +155,8 @@ static const Node* process(Context* ctx, const Node* node) { fn_ctx.fun = new; fn_ctx.inlined_call = NULL; for (size_t i = 0; i < new->payload.fun.params.count; i++) - register_processed(&fn_ctx.rewriter, node->payload.fun.params.nodes[i], new->payload.fun.params.nodes[i]); - recreate_decl_body_identity(&fn_ctx.rewriter, node, new); + shd_register_processed(&fn_ctx.rewriter, node->payload.fun.params.nodes[i], new->payload.fun.params.nodes[i]); + shd_recreate_node_body(&fn_ctx.rewriter, node, new); shd_destroy_dict(fn_ctx.rewriter.map); return new; } @@ -171,10 +171,10 @@ static const Node* process(Context* ctx, const Node* node) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined && is_call_potentially_inlineable(ctx->old_fun, ocallee)) { shd_debugv_print("Inlining call to %s\n", get_abstraction_name(ocallee)); - Nodes nargs = rewrite_nodes(&ctx->rewriter, payload.args); + Nodes nargs = shd_rewrite_nodes(&ctx->rewriter, payload.args); // Prepare a join point to replace the old function return - Nodes nyield_types = strip_qualifiers(a, rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); + Nodes nyield_types = strip_qualifiers(a, shd_rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); const Node* join_point = param(a, shd_as_qualified_type(jp_type, true), shd_format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); @@ -182,7 +182,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* nbody = inline_call(ctx, ocallee, get_abstraction_mem(control_case), nargs, join_point); set_abstraction_body(control_case, nbody); - BodyBuilder* bb = begin_block_with_side_effects(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, control_case)); } } @@ -199,7 +199,7 @@ static const Node* process(Context* ctx, const Node* node) { case Return_TAG: { Return payload = node->payload.fn_ret; if (ctx->inlined_call) - return join(a, (Join) { .mem = rewrite_node(r, payload.mem), .join_point = ctx->inlined_call->return_jp, .args = rewrite_nodes(r, payload.args )}); + return join(a, (Join) { .mem = shd_rewrite_node(r, payload.mem), .join_point = ctx->inlined_call->return_jp, .args = shd_rewrite_nodes(r, payload.args)}); break; } case TailCall_TAG: { @@ -211,8 +211,8 @@ static const Node* process(Context* ctx, const Node* node) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined) { shd_debugv_print("Inlining tail call to %s\n", get_abstraction_name(ocallee)); - Nodes nargs = rewrite_nodes(&ctx->rewriter, node->payload.tail_call.args); - return inline_call(ctx, ocallee, rewrite_node(r, node->payload.tail_call.mem), nargs, NULL); + Nodes nargs = shd_rewrite_nodes(&ctx->rewriter, node->payload.tail_call.args); + return inline_call(ctx, ocallee, shd_rewrite_node(r, node->payload.tail_call.mem), nargs, NULL); } } break; @@ -220,7 +220,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } KeyHash hash_node(const Node**); @@ -228,7 +228,7 @@ bool compare_node(const Node**, const Node**); void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .graph = NULL, .fun = NULL, @@ -236,11 +236,11 @@ void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { }; ctx.graph = new_callgraph(src); - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); if (ctx.graph) destroy_callgraph(ctx.graph); - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); } Module* opt_inline(const CompilerConfig* config, Module* src) { diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 85553f374..14bd452d9 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -91,10 +91,10 @@ static const Node* process(Context* ctx, const Node* node) { IrArena* a = r->dst_arena; switch (node->tag) { case Function_TAG: { - Node* new = recreate_decl_header_identity(r, node); + Node* new = shd_recreate_node_head(r, node); Context fun_ctx = *ctx; fun_ctx.cfg = build_fn_cfg(node); - recreate_decl_body_identity(&fun_ctx.rewriter, node, new); + shd_recreate_node_body(&fun_ctx.rewriter, node, new); destroy_cfg(fun_ctx.cfg); return new; } @@ -107,16 +107,16 @@ static const Node* process(Context* ctx, const Node* node) { const Node* ovalue = get_last_stored_value(ctx, payload.ptr, payload.mem, get_unqualified_type(node->type)); if (ovalue) { *ctx->todo = true; - const Node* value = rewrite_node(r, ovalue); + const Node* value = shd_rewrite_node(r, ovalue); if (is_qualified_type_uniform(node->type)) value = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(value)); - return mem_and_value(a, (MemAndValue) { .mem = rewrite_node(r, payload.mem), .value = value }); + return mem_and_value(a, (MemAndValue) { .mem = shd_rewrite_node(r, payload.mem), .value = value }); } } default: break; } - return recreate_node_identity(r, node); + return shd_recreate_node(r, node); } OptPass opt_mem2reg; @@ -129,11 +129,11 @@ bool opt_mem2reg(SHADY_UNUSED const CompilerConfig* config, Module** m) { bool todo = false; dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .todo = &todo }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); assert(dst); *m = dst; return todo; diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 7230818ab..d052f5eff 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -121,7 +121,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, } prior_encounter->loop_header = true; return merge_continue(a, (MergeContinue) { - .args = rewrite_nodes(r, oargs), + .args = shd_rewrite_nodes(r, oargs), .mem = mem, }); } else { @@ -142,8 +142,8 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; for (size_t i = 0; i < oargs.count; i++) { - nparams[i] = param(a, rewrite_node(&ctx->rewriter, oparams.nodes[i]->type), "arg"); - register_processed(&ctx2.rewriter, oparams.nodes[i], nparams[i]); + nparams[i] = param(a, shd_rewrite_node(&ctx->rewriter, oparams.nodes[i]->type), "arg"); + shd_register_processed(&ctx2.rewriter, oparams.nodes[i], nparams[i]); } // We use a basic block for the exit ladder because we don't know what the ladder needs to do ahead of time @@ -151,7 +151,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, // Just jumps to the actual ladder Node* structured_target = case_(a, shd_nodes(a, oargs.count, nparams)); - register_processed(&ctx2.rewriter, get_abstraction_mem(old_target), get_abstraction_mem(structured_target)); + shd_register_processed(&ctx2.rewriter, get_abstraction_mem(old_target), get_abstraction_mem(structured_target)); const Node* structured = structure(&ctx2, get_abstraction_body(old_target), inner_exit_ladder_bb); assert(is_terminator(structured)); set_abstraction_body(structured_target, structured); @@ -163,7 +163,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, if (dfs_entry.loop_header) { // Use the structured target as the body of a loop - gen_loop(bb, shd_empty(a), rewrite_nodes(&ctx->rewriter, oargs), structured_target); + gen_loop(bb, shd_empty(a), shd_rewrite_nodes(&ctx->rewriter, oargs), structured_target); // The exit ladder must exit that new loop set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) })); // After that we jump to the parent exit @@ -173,7 +173,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, get_abstraction_mem(inner_exit_ladder_bb), exit, shd_empty(a))); // Jump into the new structured target - return finish_body(bb, jump_helper(a, bb_mem(bb), structured_target, rewrite_nodes(&ctx->rewriter, oargs))); + return finish_body(bb, jump_helper(a, bb_mem(bb), structured_target, shd_rewrite_nodes(&ctx->rewriter, oargs))); } } } @@ -198,15 +198,15 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { case NotATerminator: case Jump_TAG: { Jump payload = body->payload.jump; - return handle_bb_callsite(ctx, payload, rewrite_node(r, payload.mem), exit); + return handle_bb_callsite(ctx, payload, shd_rewrite_node(r, payload.mem), exit); } // br(cond, true_bb, false_bb, args) // becomes // let(if(cond, _ => handle_bb_callsite[true_bb, args], _ => handle_bb_callsite[false_bb, args]), _ => unreachable) case Branch_TAG: { Branch payload = body->payload.branch; - const Node* condition = rewrite_node(&ctx->rewriter, payload.condition); - rewrite_node(r, payload.mem); + const Node* condition = shd_rewrite_node(&ctx->rewriter, payload.condition); + shd_rewrite_node(r, payload.mem); Node* true_case = case_(a, shd_empty(a)); set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, get_abstraction_mem(true_case), make_selection_merge_case(a))); @@ -214,14 +214,14 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { Node* false_case = case_(a, shd_empty(a)); set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, get_abstraction_mem(false_case), make_selection_merge_case(a))); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); gen_if(bb, shd_empty(a), condition, true_case, false_case); return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); } case Switch_TAG: { Switch payload = body->payload.br_switch; - const Node* switch_value = rewrite_node(r, payload.switch_value); - rewrite_node(r, payload.mem); + const Node* switch_value = shd_rewrite_node(r, payload.switch_value); + shd_rewrite_node(r, payload.mem); Node* default_case = case_(a, shd_empty(a)); set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, get_abstraction_mem(default_case), make_selection_merge_case(a))); @@ -232,8 +232,8 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, get_abstraction_mem(cases[i]), make_selection_merge_case(a))); } - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - gen_match(bb, shd_empty(a), switch_value, rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), shd_nodes(a, body->payload.br_switch.case_jumps.count, (const Node**) cases), default_case); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + gen_match(bb, shd_empty(a), switch_value, shd_rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), shd_nodes(a, body->payload.br_switch.case_jumps.count, (const Node**) cases), default_case); return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); } // let(control(body), tail) @@ -245,8 +245,8 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { assert(old_control_params.count == 1); // Create N temporary variables to hold the join point arguments - BodyBuilder* bb_prelude = begin_body_with_mem(a, rewrite_node(r, payload.mem)); - Nodes yield_types = rewrite_nodes(&ctx->rewriter, body->payload.control.yield_types); + BodyBuilder* bb_prelude = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + Nodes yield_types = shd_rewrite_nodes(&ctx->rewriter, body->payload.control.yield_types); LARRAY(const Node*, phis, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { const Type* type = yield_types.nodes[i]; @@ -274,19 +274,19 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { LARRAY(const Node*, phi_values, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { phi_values[i] = gen_load(bb_tail, phis[i]); - register_processed(&ctx->rewriter, get_abstraction_params(get_structured_construct_tail(body)).nodes[i], phi_values[i]); + shd_register_processed(&ctx->rewriter, get_abstraction_params(get_structured_construct_tail(body)).nodes[i], phi_values[i]); } // Wrap the tail in a guarded if, to handle 'far' joins const Node* level_value = gen_load(bb_tail, ctx->level_ptr); const Node* guard = prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, shd_int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }); Node* true_case = case_(a, shd_empty(a)); - register_processed(r, get_abstraction_mem(get_structured_construct_tail(body)), get_abstraction_mem(true_case)); + shd_register_processed(r, get_abstraction_mem(get_structured_construct_tail(body)), get_abstraction_mem(true_case)); set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); gen_if(bb_tail, shd_empty(a), guard, true_case, NULL); set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, bb_mem(bb_tail), exit, shd_empty(a)))); - register_processed(r, get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); + shd_register_processed(r, get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); return finish_body(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); } case Join_TAG: { @@ -295,10 +295,10 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { if (!control) longjmp(ctx->bail, 1); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); gen_store(bb, ctx->level_ptr, shd_int32_literal(a, control->depth - 1)); - Nodes args = rewrite_nodes(&ctx->rewriter, body->payload.join.args); + Nodes args = shd_rewrite_nodes(&ctx->rewriter, body->payload.join.args); for (size_t i = 0; i < args.count; i++) { gen_store(bb, control->phis[i], args.nodes[i]); } @@ -307,7 +307,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { } case Return_TAG: - case Unreachable_TAG: return recreate_node_identity(&ctx->rewriter, body); + case Unreachable_TAG: return shd_recreate_node(&ctx->rewriter, body); case TailCall_TAG: longjmp(ctx->bail, 1); @@ -336,7 +336,7 @@ static const Node* process(Context* ctx, const Node* node) { } if (node->tag == Function_TAG) { - Node* new = recreate_decl_header_identity(&ctx->rewriter, node); + Node* new = shd_recreate_node_head(&ctx->rewriter, node); size_t alloc_stack_size_now = shd_list_count(ctx->cleanup_stack); @@ -349,7 +349,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.lower = false; ctx2.rewriter.map = ctx->rewriter.map; if (node->payload.fun.body) - set_abstraction_body(new, rewrite_node(&ctx2.rewriter, node->payload.fun.body)); + set_abstraction_body(new, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body)); // builtin functions are always considered leaf functions is_leaf = is_builtin || !node->payload.fun.body; } else { @@ -366,7 +366,7 @@ static const Node* process(Context* ctx, const Node* node) { TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; - register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); + shd_register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new, finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. @@ -390,7 +390,7 @@ static const Node* process(Context* ctx, const Node* node) { } if (!ctx->lower) - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); // These should all be manually visited by 'structure' // assert(!is_terminator(node) && !is_instruction(node)); @@ -399,7 +399,7 @@ static const Node* process(Context* ctx, const Node* node) { case Instruction_Call_TAG: { const Node* callee = node->payload.call.callee; if (callee->tag == FnAddr_TAG) { - const Node* fn = rewrite_node(&ctx->rewriter, callee->payload.fn_addr.fn); + const Node* fn = shd_rewrite_node(&ctx->rewriter, callee->payload.fn_addr.fn); // leave leaf calls alone if (shd_lookup_annotation(fn, "Leaf")) { break; @@ -412,7 +412,7 @@ static const Node* process(Context* ctx, const Node* node) { case BasicBlock_TAG: shd_error("All basic blocks should be processed explicitly") default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -421,11 +421,11 @@ Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .cleanup_stack = shd_new_list(TmpAllocCleanupClosure), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_list(ctx.cleanup_stack); return dst; } diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index b24376e5e..290fdc15c 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -125,7 +125,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { size_t exiting_nodes_count = shd_list_count(exiting_nodes); if (exiting_nodes_count > 0) { - Nodes nparams = recreate_params(rewriter, get_abstraction_params(node)); + Nodes nparams = shd_recreate_params(rewriter, get_abstraction_params(node)); Node* loop_container = basic_block(arena, nparams, node->payload.basic_block.name); BodyBuilder* outer_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_container)); Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); @@ -133,7 +133,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(Exit, exits, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; - Nodes exit_param_types = rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); + Nodes exit_param_types = shd_rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); ExitValue* exit_params = shd_arena_alloc(ctx->arena, sizeof(ExitValue) * exit_param_types.count); for (size_t j = 0; j < exit_param_types.count; j++) { @@ -162,13 +162,13 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); - Nodes exit_wrapper_params = recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); + Nodes exit_wrapper_params = shd_recreate_params(&ctx->rewriter, get_abstraction_params(exiting_node->node)); Node* wrapper = basic_block(arena, exit_wrapper_params, shd_format_string_arena(arena->arena, "exit_wrapper_%d", i)); exits[i].wrapper = wrapper; } - Nodes continue_wrapper_params = recreate_params(rewriter, get_abstraction_params(node)); + Nodes continue_wrapper_params = shd_recreate_params(rewriter, get_abstraction_params(node)); Node* continue_wrapper = basic_block(arena, continue_wrapper_params, "continue"); const Node* continue_wrapper_body = join(arena, (Join) { .join_point = join_token_continue, @@ -181,16 +181,16 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(const Node**, cached_exits, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; - cached_exits[i] = search_processed(rewriter, exiting_node->node); + cached_exits[i] = shd_search_processed(rewriter, exiting_node->node); if (cached_exits[i]) shd_dict_remove(const Node*, rewriter->map, exiting_node->node); - register_processed(rewriter, exiting_node->node, exits[i].wrapper); + shd_register_processed(rewriter, exiting_node->node, exits[i].wrapper); } // ditto for the loop entry and the continue wrapper - const Node** cached_entry = search_processed(rewriter, node); + const Node** cached_entry = shd_search_processed(rewriter, node); if (cached_entry) shd_dict_remove(const Node*, rewriter->map, node); - register_processed(rewriter, node, continue_wrapper); + shd_register_processed(rewriter, node, continue_wrapper); // make sure we haven't started rewriting this... // for (size_t i = 0; i < old_params.count; i++) { @@ -199,11 +199,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { struct Dict* old_map = rewriter->map; rewriter->map = shd_clone_dict(rewriter->map); - Nodes inner_loop_params = recreate_params(rewriter, get_abstraction_params(node)); - register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); + Nodes inner_loop_params = shd_recreate_params(rewriter, get_abstraction_params(node)); + shd_register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); Node* inner_control_case = case_(arena, shd_singleton(join_token_continue)); - register_processed(rewriter, get_abstraction_mem(node), get_abstraction_mem(inner_control_case)); - const Node* loop_body = rewrite_node(rewriter, get_abstraction_body(node)); + shd_register_processed(rewriter, get_abstraction_mem(node), get_abstraction_mem(inner_control_case)); + const Node* loop_body = shd_rewrite_node(rewriter, get_abstraction_body(node)); // save the context for (size_t i = 0; i < exiting_nodes_count; i++) { @@ -231,11 +231,11 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t i = 0; i < exiting_nodes_count; i++) { shd_dict_remove(const Node*, rewriter->map, shd_read_list(CFNode *, exiting_nodes)[i]->node); if (cached_exits[i]) - register_processed(rewriter, shd_read_list(CFNode*, exiting_nodes)[i]->node, *cached_exits[i]); + shd_register_processed(rewriter, shd_read_list(CFNode*, exiting_nodes)[i]->node, *cached_exits[i]); } shd_dict_remove(const Node*, rewriter->map, node); if (cached_entry) - register_processed(rewriter, node, *cached_entry); + shd_register_processed(rewriter, node, *cached_entry); Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); BodyBuilder* inner_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_outer)); @@ -262,7 +262,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Node* exit_bb = basic_block(arena, shd_empty(arena), shd_format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); - const Node* recreated_exit = rewrite_node(rewriter, exiting_node->node); + const Node* recreated_exit = shd_rewrite_node(rewriter, exiting_node->node); LARRAY(const Node*, recovered_args, exits[i].params_count); for (size_t j = 0; j < exits[i].params_count; j++) { @@ -297,7 +297,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { shd_destroy_list(exiting_nodes); } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } static const Node* process_node(Context* ctx, const Node* node) { @@ -395,7 +395,7 @@ static const Node* process_node(Context* ctx, const Node* node) { assert(idom_lt_node); assert(current_node); - Node* fn = (Node*) find_processed(r, ctx->current_fn); + Node* fn = (Node*) shd_find_processed(r, ctx->current_fn); //Regular if/then/else case. Control flow joins at the immediate post dominator. Nodes yield_types; @@ -414,7 +414,7 @@ static const Node* process_node(Context* ctx, const Node* node) { for (size_t j = 0; j < old_params.count; j++) { //TODO: Is this correct? assert(old_params.nodes[j]->tag == Param_TAG); - const Node* qualified_type = rewrite_node(r, old_params.nodes[j]->payload.param.type); + const Node* qualified_type = shd_rewrite_node(r, old_params.nodes[j]->payload.param.type); //const Node* qualified_type = rewrite_node(rewriter, old_params.nodes[j]->type); //This should always contain a qualified type? @@ -439,35 +439,35 @@ static const Node* process_node(Context* ctx, const Node* node) { .mem = get_abstraction_mem(pre_join), })); - const Node** cached = search_processed(r, post_dominator); + const Node** cached = shd_search_processed(r, post_dominator); if (cached) shd_dict_remove(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); for (size_t i = 0; i < old_params.count; i++) { - assert(!search_processed(r, old_params.nodes[i])); + assert(!shd_search_processed(r, old_params.nodes[i])); } - register_processed(r, post_dominator, pre_join); + shd_register_processed(r, post_dominator, pre_join); Node* control_case = case_(a, shd_singleton(join_token)); const Node* inner_terminator = branch(a, (Branch) { .mem = get_abstraction_mem(control_case), - .condition = rewrite_node(r, payload.condition), + .condition = shd_rewrite_node(r, payload.condition), .true_jump = jump_helper(a, get_abstraction_mem(control_case), - rewrite_node(r, payload.true_jump->payload.jump.target), - rewrite_nodes(r, payload.true_jump->payload.jump.args)), + shd_rewrite_node(r, payload.true_jump->payload.jump.target), + shd_rewrite_nodes(r, payload.true_jump->payload.jump.args)), .false_jump = jump_helper(a, get_abstraction_mem(control_case), - rewrite_node(r, payload.false_jump->payload.jump.target), - rewrite_nodes(r, payload.false_jump->payload.jump.args)), + shd_rewrite_node(r, payload.false_jump->payload.jump.target), + shd_rewrite_nodes(r, payload.false_jump->payload.jump.args)), }); set_abstraction_body(control_case, inner_terminator); shd_dict_remove(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); if (cached) - register_processed(r, post_dominator, *cached); + shd_register_processed(r, post_dominator, *cached); - const Node* join_target = rewrite_node(r, post_dominator); + const Node* join_target = shd_rewrite_node(r, post_dominator); - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, node->payload.branch.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, node->payload.branch.mem)); Nodes results = gen_control(bb, yield_types, control_case); // make sure what was uniform still is for (size_t j = 0; j < old_params.count; j++) { @@ -478,7 +478,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } default: break; } - return recreate_node_identity(r, node); + return shd_recreate_node(r, node); } Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { @@ -488,7 +488,7 @@ Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .current_fn = NULL, .fwd_cfg = NULL, @@ -497,8 +497,8 @@ Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { .arena = shd_new_arena(), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); shd_destroy_arena(ctx.arena); return dst; } diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index db69162d6..8d856fba3 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -19,14 +19,14 @@ static const Node* process(Context* ctx, const Node* node) { Jump payload = node->payload.jump; Node* new_block = basic_block(a, shd_empty(a), NULL); set_abstraction_body(new_block, jump_helper(a, get_abstraction_mem(new_block), - rewrite_node(r, payload.target), - rewrite_nodes(r, payload.args))); - return jump_helper(a, rewrite_node(r, payload.mem), new_block, shd_empty(a)); + shd_rewrite_node(r, payload.target), + shd_rewrite_nodes(r, payload.args))); + return jump_helper(a, shd_rewrite_node(r, payload.mem), new_block, shd_empty(a)); } default: break; } - return recreate_node_identity(r, node); + return shd_recreate_node(r, node); } Module* remove_critical_edges(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -34,9 +34,9 @@ Module* remove_critical_edges(SHADY_UNUSED const CompilerConfig* config, Module* IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 673786bd6..f507043c4 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -51,9 +51,9 @@ static Nodes remake_params(Context* ctx, Nodes old) { const Type* t = NULL; if (node->payload.param.type) { if (node->payload.param.type->tag == QualifiedType_TAG) - t = rewrite_node(r, node->payload.param.type); + t = shd_rewrite_node(r, node->payload.param.type); else - t = shd_as_qualified_type(rewrite_node(r, node->payload.param.type), false); + t = shd_as_qualified_type(shd_rewrite_node(r, node->payload.param.type), false); } nvars[i] = param(a, t, node->payload.param.name); assert(nvars[i]->tag == Param_TAG); @@ -89,15 +89,15 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab const Node* obb = dominated->node; assert(obb->tag == BasicBlock_TAG); Nodes nparams = remake_params(ctx, get_abstraction_params(obb)); - register_processed_list(r, get_abstraction_params(obb), nparams); + shd_register_processed_list(r, get_abstraction_params(obb), nparams); nbbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(obb)); - register_processed(r, obb, nbbs[i]); + shd_register_processed(r, obb, nbbs[i]); } // We introduce a dummy case now because we don't know yet whether the body of the abstraction will be wrapped Node* c = case_(a, shd_empty(a)); Node* oc = c; - register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); + shd_register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); for (size_t k = 0; k < num_dom; k++) { CFNode* dominated = shd_read_list(CFNode*, n->dominates)[k]; @@ -107,7 +107,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab Controls* controls = get_or_create_controls(ctx, oabs); - set_abstraction_body(oc, rewrite_node(r, obody)); + set_abstraction_body(oc, shd_rewrite_node(r, obody)); size_t i = 0; AddControl add_control; @@ -130,7 +130,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab } c = c2; - set_abstraction_body(c2, finish_body(bb, jump_helper(a, bb_mem(bb), find_processed(r, dst), results))); + set_abstraction_body(c2, finish_body(bb, jump_helper(a, bb_mem(bb), shd_find_processed(r, dst), results))); } const Node* body = jump_helper(a, get_abstraction_mem(nabs), c, shd_empty(a)); @@ -220,7 +220,7 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed } else { Nodes wrapper_params = remake_params(ctx, get_abstraction_params(dst)); Nodes join_args = wrapper_params; - Nodes yield_types = rewrite_nodes(r, strip_qualifiers(a, get_param_types(a, get_abstraction_params(dst)))); + Nodes yield_types = shd_rewrite_nodes(r, strip_qualifiers(a, get_param_types(a, get_abstraction_params(dst)))); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = yield_types @@ -272,7 +272,7 @@ static const Node* process_node(Context* ctx, const Node* node) { case Function_TAG: { CFG* cfg = build_fn_cfg(node); prepare_function(ctx, cfg, node); - Node* decl = recreate_decl_header_identity(r, node); + Node* decl = shd_recreate_node_head(r, node); wrap_in_controls(ctx, cfg, decl, node); destroy_cfg(cfg); return decl; @@ -283,21 +283,21 @@ static const Node* process_node(Context* ctx, const Node* node) { // Eliminate now-useless scope instructions case ExtInstr_TAG: { if (strcmp(node->payload.ext_instr.set, "shady.scope") == 0) { - return rewrite_node(r, node->payload.ext_instr.mem); + return shd_rewrite_node(r, node->payload.ext_instr.mem); } break; } case Jump_TAG: { Wrapped* found = shd_dict_find_value(const Node*, Wrapped, ctx->jump2wrapper, node); if (found) - return jump_helper(a, rewrite_node(r, node->payload.jump.mem), found->wrapper, - rewrite_nodes(r, node->payload.jump.args)); + return jump_helper(a, shd_rewrite_node(r, node->payload.jump.mem), found->wrapper, + shd_rewrite_nodes(r, node->payload.jump.args)); break; } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* scope2control(const CompilerConfig* config, Module* src) { @@ -306,7 +306,7 @@ Module* scope2control(const CompilerConfig* config, Module* src) { IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process_node), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .arena = shd_new_arena(), .controls = shd_new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), @@ -315,7 +315,7 @@ Module* scope2control(const CompilerConfig* config, Module* src) { ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; - rewrite_module(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); size_t i = 0; Controls* controls; @@ -331,7 +331,7 @@ Module* scope2control(const CompilerConfig* config, Module* src) { shd_destroy_dict(ctx.controls); shd_destroy_dict(ctx.jump2wrapper); shd_destroy_arena(ctx.arena); - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index 73038a7c9..1f75a7485 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -172,31 +172,31 @@ static const Node* process(Context* ctx, const Node* node) { Context fn_ctx = *ctx; fn_ctx.cfg = build_fn_cfg(node); fn_ctx.depth_per_rpo = compute_scope_depth(a, fn_ctx.cfg); - Node* new_fn = recreate_decl_header_identity(r, node); + Node* new_fn = shd_recreate_node_head(r, node); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), shd_empty(a)); - register_processed(r, get_abstraction_mem(node), bb_mem(bb)); - set_abstraction_body(new_fn, finish_body(bb, rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); + shd_register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + set_abstraction_body(new_fn, finish_body(bb, shd_rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); destroy_cfg(fn_ctx.cfg); free(fn_ctx.depth_per_rpo); return new_fn; } case BasicBlock_TAG: { - Nodes nparams = recreate_params(r, get_abstraction_params(node)); - register_processed_list(r, get_abstraction_params(node), nparams); + Nodes nparams = shd_recreate_params(r, get_abstraction_params(node)); + shd_register_processed_list(r, get_abstraction_params(node), nparams); Node* new_bb = basic_block(a, nparams, get_abstraction_name_unsafe(node)); - register_processed(r, node, new_bb); + shd_register_processed(r, node, new_bb); BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_bb)); CFNode* n = cfg_lookup(ctx->cfg, node); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); - register_processed(r, get_abstraction_mem(node), bb_mem(bb)); - set_abstraction_body(new_bb, finish_body(bb, rewrite_node(r, get_abstraction_body(node)))); + shd_register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + set_abstraction_body(new_bb, finish_body(bb, shd_rewrite_node(r, get_abstraction_body(node)))); return new_bb; } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } Module* scope_heuristic(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -204,9 +204,9 @@ Module* scope_heuristic(SHADY_UNUSED const CompilerConfig* config, Module* src) IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 8906ab149..46041622a 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -25,7 +25,7 @@ static const Node* process(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; switch (node->tag) { case Function_TAG: { - Node* fun = recreate_decl_header_identity(r, node); + Node* fun = shd_recreate_node_head(r, node); Context ctx2 = *ctx; ctx2.disable_lowering = shd_lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; @@ -34,16 +34,16 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.stack_size_on_entry = gen_get_stack_size(bb); set_value_name((Node*) ctx2.stack_size_on_entry, shd_format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun))); } - register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); + shd_register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); if (node->payload.fun.body) - set_abstraction_body(fun, finish_body(bb, rewrite_node(&ctx2.rewriter, node->payload.fun.body))); + set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body))); else cancel_body(bb); return fun; } case Return_TAG: { Return payload = node->payload.fn_ret; - BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); + BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); if (!ctx->disable_lowering) { assert(ctx->stack_size_on_entry); // Restore SP before calling exit @@ -51,12 +51,12 @@ static const Node* process(Context* ctx, const Node* node) { } return finish_body(bb, fn_ret(a, (Return) { .mem = bb_mem(bb), - .args = rewrite_nodes(r, payload.args), + .args = shd_rewrite_nodes(r, payload.args), })); } default: break; } - return recreate_node_identity(r, node); + return shd_recreate_node(r, node); } Module* setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* src) { @@ -64,10 +64,10 @@ Module* setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* sr IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index b8307caf2..e27126a07 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -44,7 +44,7 @@ static const Node* process(Context* ctx, const Node* node) { break; } case Constant_TAG: { - Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); + Node* ncnst = (Node*) shd_recreate_node(&ctx->rewriter, node); if (strcmp(get_declaration_name(ncnst), "SUBGROUPS_PER_WG") == 0) { // SUBGROUPS_PER_WG = (NUMBER OF INVOCATIONS IN SUBGROUP / SUBGROUP SIZE) // Note: this computations assumes only full subgroups are launched, if subgroups can launch partially filled then this relationship does not hold. @@ -61,7 +61,7 @@ static const Node* process(Context* ctx, const Node* node) { } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } static const Node* find_entry_point(Module* m, const CompilerConfig* config) { @@ -111,20 +111,20 @@ Module* specialize_entry_point(const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; const Node* old_entry_point_decl = find_entry_point(src, config); - rewrite_node(&ctx.rewriter, old_entry_point_decl); + shd_rewrite_node(&ctx.rewriter, old_entry_point_decl); Nodes old_decls = get_module_declarations(src); for (size_t i = 0; i < old_decls.count; i++) { const Node* old_decl = old_decls.nodes[i]; if (shd_lookup_annotation(old_decl, "RetainAfterSpecialization")) - rewrite_node(&ctx.rewriter, old_decl); + shd_rewrite_node(&ctx.rewriter, old_decl); } - destroy_rewriter(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 2b7f275bd..81057bd38 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -18,7 +18,7 @@ static const Node* process(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { case Constant_TAG: { - Node* ncnst = (Node*) recreate_node_identity(&ctx->rewriter, node); + Node* ncnst = (Node*) shd_recreate_node(&ctx->rewriter, node); if (strcmp(get_declaration_name(ncnst), "SUBGROUP_SIZE") == 0) { ncnst->payload.constant.value = shd_uint32_literal(a, ctx->config->specialization.subgroup_size); } @@ -26,7 +26,7 @@ static const Node* process(Context* ctx, const Node* node) { } default: break; } - return recreate_node_identity(&ctx->rewriter, node); + return shd_recreate_node(&ctx->rewriter, node); } static void specialize_arena_config(const CompilerConfig* config, Module* m, ArenaConfig* target) { @@ -50,11 +50,11 @@ Module* specialize_execution_model(const CompilerConfig* config, Module* src) { assert(subgroup_size); Context ctx = { - .rewriter = create_node_rewriter(src, dst, (RewriteNodeFn) process), + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, }; - rewrite_module(&ctx.rewriter); - destroy_rewriter(&ctx.rewriter); + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 50c4afbc9..2fbed77c0 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -13,7 +13,7 @@ KeyHash hash_node(Node**); bool compare_node(Node**, Node**); -Rewriter create_rewriter_base(Module* src, Module* dst) { +Rewriter shd_create_rewriter_base(Module* src, Module* dst) { return (Rewriter) { .src_arena = src->arena, .dst_arena = dst->arena, @@ -30,31 +30,31 @@ Rewriter create_rewriter_base(Module* src, Module* dst) { }; } -Rewriter create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn) { - Rewriter r = create_rewriter_base(src, dst); +Rewriter shd_create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn) { + Rewriter r = shd_create_rewriter_base(src, dst); r.rewrite_fn = fn; return r; } -Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn) { - Rewriter r = create_rewriter_base(src, dst); +Rewriter shd_create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn) { + Rewriter r = shd_create_rewriter_base(src, dst); r.config.write_map = false; r.rewrite_op_fn = fn; return r; } -void destroy_rewriter(Rewriter* r) { +void shd_destroy_rewriter(Rewriter* r) { assert(r->map); shd_destroy_dict(r->map); if (r->own_decls) shd_destroy_dict(r->decls_map); } -Rewriter create_importer(Module* src, Module* dst) { - return create_node_rewriter(src, dst, recreate_node_identity); +Rewriter shd_create_importer(Module* src, Module* dst) { + return shd_create_node_rewriter(src, dst, shd_recreate_node); } -Rewriter create_children_rewriter(Rewriter* parent) { +Rewriter shd_create_children_rewriter(Rewriter* parent) { Rewriter r = *parent; r.map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); r.parent = parent; @@ -62,7 +62,7 @@ Rewriter create_children_rewriter(Rewriter* parent) { return r; } -Rewriter create_decl_rewriter(Rewriter* parent) { +Rewriter shd_create_decl_rewriter(Rewriter* parent) { Rewriter r = *parent; r.map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); r.own_decls = false; @@ -77,13 +77,13 @@ static bool should_memoize(const Node* node) { return true; } -const Node* rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNodeFn fn) { +const Node* shd_rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNodeFn fn) { assert(rewriter->rewrite_fn); if (!node) return NULL; const Node** found = NULL; if (rewriter->config.search_map) { - found = search_processed(rewriter, node); + found = shd_search_processed(rewriter, node); } if (found) return *found; @@ -93,35 +93,35 @@ const Node* rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNo if (is_declaration(node)) return rewritten; if (rewriter->config.write_map && should_memoize(node)) { - register_processed(rewriter, node, rewritten); + shd_register_processed(rewriter, node, rewritten); } return rewritten; } -Nodes rewrite_nodes_with_fn(Rewriter* rewriter, Nodes values, RewriteNodeFn fn) { +Nodes shd_rewrite_nodes_with_fn(Rewriter* rewriter, Nodes values, RewriteNodeFn fn) { LARRAY(const Node*, arr, values.count); for (size_t i = 0; i < values.count; i++) - arr[i] = rewrite_node_with_fn(rewriter, values.nodes[i], fn); + arr[i] = shd_rewrite_node_with_fn(rewriter, values.nodes[i], fn); return shd_nodes(rewriter->dst_arena, values.count, arr); } -const Node* rewrite_node(Rewriter* rewriter, const Node* node) { +const Node* shd_rewrite_node(Rewriter* rewriter, const Node* node) { assert(rewriter->rewrite_fn); - return rewrite_node_with_fn(rewriter, node, rewriter->rewrite_fn); + return shd_rewrite_node_with_fn(rewriter, node, rewriter->rewrite_fn); } -Nodes rewrite_nodes(Rewriter* rewriter, Nodes old_nodes) { +Nodes shd_rewrite_nodes(Rewriter* rewriter, Nodes old_nodes) { assert(rewriter->rewrite_fn); - return rewrite_nodes_with_fn(rewriter, old_nodes, rewriter->rewrite_fn); + return shd_rewrite_nodes_with_fn(rewriter, old_nodes, rewriter->rewrite_fn); } -const Node* rewrite_op_with_fn(Rewriter* rewriter, NodeClass class, String op_name, const Node* node, RewriteOpFn fn) { +const Node* shd_rewrite_op_with_fn(Rewriter* rewriter, NodeClass class, String op_name, const Node* node, RewriteOpFn fn) { assert(rewriter->rewrite_op_fn); if (!node) return NULL; const Node** found = NULL; if (rewriter->config.search_map) { - found = search_processed(rewriter, node); + found = shd_search_processed(rewriter, node); } if (found) return *found; @@ -130,40 +130,40 @@ const Node* rewrite_op_with_fn(Rewriter* rewriter, NodeClass class, String op_na if (is_declaration(node)) return rewritten; if (rewriter->config.write_map && should_memoize(node)) { - register_processed(rewriter, node, rewritten); + shd_register_processed(rewriter, node, rewritten); } return rewritten; } -Nodes rewrite_ops_with_fn(Rewriter* rewriter, NodeClass class, String op_name, Nodes values, RewriteOpFn fn) { +Nodes shd_rewrite_ops_with_fn(Rewriter* rewriter, NodeClass class, String op_name, Nodes values, RewriteOpFn fn) { LARRAY(const Node*, arr, values.count); for (size_t i = 0; i < values.count; i++) - arr[i] = rewrite_op_with_fn(rewriter, class, op_name, values.nodes[i], fn); + arr[i] = shd_rewrite_op_with_fn(rewriter, class, op_name, values.nodes[i], fn); return shd_nodes(rewriter->dst_arena, values.count, arr); } -const Node* rewrite_op(Rewriter* rewriter, NodeClass class, String op_name, const Node* node) { +const Node* shd_rewrite_op(Rewriter* rewriter, NodeClass class, String op_name, const Node* node) { assert(rewriter->rewrite_op_fn); - return rewrite_op_with_fn(rewriter, class, op_name, node, rewriter->rewrite_op_fn); + return shd_rewrite_op_with_fn(rewriter, class, op_name, node, rewriter->rewrite_op_fn); } -Nodes rewrite_ops(Rewriter* rewriter, NodeClass class, String op_name, Nodes old_nodes) { +Nodes shd_rewrite_ops(Rewriter* rewriter, NodeClass class, String op_name, Nodes old_nodes) { assert(rewriter->rewrite_op_fn); - return rewrite_ops_with_fn(rewriter, class, op_name, old_nodes, rewriter->rewrite_op_fn); + return shd_rewrite_ops_with_fn(rewriter, class, op_name, old_nodes, rewriter->rewrite_op_fn); } static const Node* rewrite_op_helper(Rewriter* rewriter, NodeClass class, String op_name, const Node* node) { if (rewriter->rewrite_op_fn) - return rewrite_op_with_fn(rewriter, class, op_name, node, rewriter->rewrite_op_fn); + return shd_rewrite_op_with_fn(rewriter, class, op_name, node, rewriter->rewrite_op_fn); assert(rewriter->rewrite_fn); - return rewrite_node_with_fn(rewriter, node, rewriter->rewrite_fn); + return shd_rewrite_node_with_fn(rewriter, node, rewriter->rewrite_fn); } static Nodes rewrite_ops_helper(Rewriter* rewriter, NodeClass class, String op_name, Nodes old_nodes) { if (rewriter->rewrite_op_fn) - return rewrite_ops_with_fn(rewriter, class, op_name, old_nodes, rewriter->rewrite_op_fn); + return shd_rewrite_ops_with_fn(rewriter, class, op_name, old_nodes, rewriter->rewrite_op_fn); assert(rewriter->rewrite_fn); - return rewrite_nodes_with_fn(rewriter, old_nodes, rewriter->rewrite_fn); + return shd_rewrite_nodes_with_fn(rewriter, old_nodes, rewriter->rewrite_fn); } static const Node** search_processed_(const Rewriter* ctx, const Node* old, bool deep) { @@ -185,17 +185,17 @@ static const Node** search_processed_(const Rewriter* ctx, const Node* old, bool return NULL; } -const Node** search_processed(const Rewriter* ctx, const Node* old) { +const Node** shd_search_processed(const Rewriter* ctx, const Node* old) { return search_processed_(ctx, old, true); } -const Node* find_processed(const Rewriter* ctx, const Node* old) { - const Node** found = search_processed(ctx, old); +const Node* shd_find_processed(const Rewriter* ctx, const Node* old) { + const Node** found = shd_search_processed(ctx, old); assert(found && "this node was supposed to have been processed before"); return *found; } -void register_processed(Rewriter* ctx, const Node* old, const Node* new) { +void shd_register_processed(Rewriter* ctx, const Node* old, const Node* new) { assert(old->arena == ctx->src_arena); assert(new ? new->arena == ctx->dst_arena : true); #ifndef NDEBUG @@ -226,10 +226,10 @@ void register_processed(Rewriter* ctx, const Node* old, const Node* new) { assert(r); } -void register_processed_list(Rewriter* rewriter, Nodes old, Nodes new) { +void shd_register_processed_list(Rewriter* rewriter, Nodes old, Nodes new) { assert(old.count == new.count); for (size_t i = 0; i < old.count; i++) - register_processed(rewriter, old.nodes[i], new.nodes[i]); + shd_register_processed(rewriter, old.nodes[i], new.nodes[i]); } KeyHash hash_node(Node**); @@ -239,7 +239,7 @@ bool compare_node(Node**, Node**); #include "rewrite_generated.c" -void rewrite_module(Rewriter* rewriter) { +void shd_rewrite_module(Rewriter* rewriter) { assert(rewriter->dst_module != rewriter->src_module); Nodes old_decls = get_module_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { @@ -248,21 +248,21 @@ void rewrite_module(Rewriter* rewriter) { } } -const Node* recreate_param(Rewriter* rewriter, const Node* old) { +const Node* shd_recreate_param(Rewriter* rewriter, const Node* old) { assert(old->tag == Param_TAG); return param(rewriter->dst_arena, rewrite_op_helper(rewriter, NcType, "type", old->payload.param.type), old->payload.param.name); } -Nodes recreate_params(Rewriter* rewriter, Nodes oparams) { +Nodes shd_recreate_params(Rewriter* rewriter, Nodes oparams) { LARRAY(const Node*, nparams, oparams.count); for (size_t i = 0; i < oparams.count; i++) { - nparams[i] = recreate_param(rewriter, oparams.nodes[i]); + nparams[i] = shd_recreate_param(rewriter, oparams.nodes[i]); assert(nparams[i]->tag == Param_TAG); } return shd_nodes(rewriter->dst_arena, oparams.count, nparams); } -Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { +Node* shd_recreate_node_head(Rewriter* rewriter, const Node* old) { Node* new = NULL; switch (is_declaration(old)) { case GlobalVariable_TAG: { @@ -286,11 +286,11 @@ Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { } case Function_TAG: { Nodes new_annotations = rewrite_ops_helper(rewriter, NcAnnotation, "annotations", old->payload.fun.annotations); - Nodes new_params = recreate_params(rewriter, old->payload.fun.params); + Nodes new_params = shd_recreate_params(rewriter, old->payload.fun.params); Nodes nyield_types = rewrite_ops_helper(rewriter, NcType, "return_types", old->payload.fun.return_types); new = function(rewriter->dst_module, new_params, old->payload.fun.name, new_annotations, nyield_types); assert(new && new->tag == Function_TAG); - register_processed_list(rewriter, old->payload.fun.params, new->payload.fun.params); + shd_register_processed_list(rewriter, old->payload.fun.params, new->payload.fun.params); break; } case NominalType_TAG: { @@ -301,11 +301,11 @@ Node* recreate_decl_header_identity(Rewriter* rewriter, const Node* old) { case NotADeclaration: shd_error("not a decl"); } assert(new); - register_processed(rewriter, old, new); + shd_register_processed(rewriter, old, new); return new; } -void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) { +void shd_recreate_node_body(Rewriter* rewriter, const Node* old, Node* new) { assert(is_declaration(new)); switch (is_declaration(old)) { case GlobalVariable_TAG: { @@ -330,7 +330,7 @@ void recreate_decl_body_identity(Rewriter* rewriter, const Node* old, Node* new) } } -const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { +const Node* shd_recreate_node(Rewriter* rewriter, const Node* node) { if (node == NULL) return NULL; @@ -345,8 +345,8 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { case Constant_TAG: case GlobalVariable_TAG: case NominalType_TAG: { - Node* new = recreate_decl_header_identity(rewriter, node); - recreate_decl_body_identity(rewriter, node, new); + Node* new = shd_recreate_node_head(rewriter, node); + shd_recreate_node_body(rewriter, node, new); return new; } case Param_TAG: @@ -355,10 +355,10 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { shd_log_fmt(ERROR, ", params should be rewritten by the abstraction rewrite logic"); shd_error_die(); case BasicBlock_TAG: { - Nodes params = recreate_params(rewriter, node->payload.basic_block.params); - register_processed_list(rewriter, node->payload.basic_block.params, params); + Nodes params = shd_recreate_params(rewriter, node->payload.basic_block.params); + shd_register_processed_list(rewriter, node->payload.basic_block.params, params); Node* bb = basic_block(arena, params, node->payload.basic_block.name); - register_processed(rewriter, node, bb); + shd_register_processed(rewriter, node, bb); const Node* nterminator = rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.basic_block.body); set_abstraction_body(bb, nterminator); return bb; @@ -367,7 +367,7 @@ const Node* recreate_node_identity(Rewriter* rewriter, const Node* node) { assert(false); } -void dump_rewriter_map(Rewriter* r) { +void shd_dump_rewriter_map(Rewriter* r) { size_t i = 0; const Node* src, *dst; while (shd_dict_iter(r->map, &i, &src, &dst)) { diff --git a/src/shady/rewrite.h b/src/shady/rewrite.h index 2ea77fd90..34067a7a4 100644 --- a/src/shady/rewrite.h +++ b/src/shady/rewrite.h @@ -8,20 +8,18 @@ typedef struct Rewriter_ Rewriter; typedef const Node* (*RewriteNodeFn)(Rewriter*, const Node*); typedef const Node* (*RewriteOpFn)(Rewriter*, NodeClass, String, const Node*); -const Node* rewrite_node(Rewriter*, const Node*); -const Node* rewrite_node_with_fn(Rewriter*, const Node*, RewriteNodeFn); +const Node* shd_rewrite_node(Rewriter* rewriter, const Node* node); +const Node* shd_rewrite_node_with_fn(Rewriter* rewriter, const Node* node, RewriteNodeFn fn); -const Node* rewrite_op(Rewriter*, NodeClass, String, const Node*); -const Node* rewrite_op_with_fn(Rewriter*, NodeClass, String, const Node*, RewriteOpFn); +const Node* shd_rewrite_op(Rewriter* rewriter, NodeClass class, String op_name, const Node* node); +const Node* shd_rewrite_op_with_fn(Rewriter* rewriter, NodeClass class, String op_name, const Node* node, RewriteOpFn fn); /// Applies the rewriter to all nodes in the collection -Nodes rewrite_nodes(Rewriter*, Nodes); -Nodes rewrite_nodes_with_fn(Rewriter* rewriter, Nodes values, RewriteNodeFn fn); +Nodes shd_rewrite_nodes(Rewriter* rewriter, Nodes old_nodes); +Nodes shd_rewrite_nodes_with_fn(Rewriter* rewriter, Nodes values, RewriteNodeFn fn); -Nodes rewrite_ops(Rewriter*, NodeClass, String, Nodes); -Nodes rewrite_ops_with_fn(Rewriter* rewriter, NodeClass,String, Nodes values, RewriteOpFn fn); - -Strings _shd_import_strings(IrArena* dst_arena, Strings old_strings); +Nodes shd_rewrite_ops(Rewriter* rewriter, NodeClass class, String op_name, Nodes old_nodes); +Nodes shd_rewrite_ops_with_fn(Rewriter* rewriter, NodeClass class, String op_name, Nodes values, RewriteOpFn fn); struct Rewriter_ { RewriteNodeFn rewrite_fn; @@ -42,38 +40,35 @@ struct Rewriter_ { struct Dict* decls_map; }; -Rewriter create_rewriter_base(Module* src, Module* dst); -Rewriter create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn); -Rewriter create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn); -Rewriter create_importer(Module* src, Module* dst); +Rewriter shd_create_rewriter_base(Module* src, Module* dst); +Rewriter shd_create_node_rewriter(Module* src, Module* dst, RewriteNodeFn fn); +Rewriter shd_create_op_rewriter(Module* src, Module* dst, RewriteOpFn fn); +Rewriter shd_create_importer(Module* src, Module* dst); -Rewriter create_children_rewriter(Rewriter* parent); -Rewriter create_decl_rewriter(Rewriter* parent); -void destroy_rewriter(Rewriter*); +Rewriter shd_create_children_rewriter(Rewriter* parent); +Rewriter shd_create_decl_rewriter(Rewriter* parent); +void shd_destroy_rewriter(Rewriter* r); -void rewrite_module(Rewriter*); +void shd_rewrite_module(Rewriter* rewriter); /// Rewrites a node using the rewriter to provide the node and type operands -const Node* recreate_node_identity(Rewriter*, const Node*); +const Node* shd_recreate_node(Rewriter* rewriter, const Node* node); /// Rewrites a constant / function header -Node* recreate_decl_header_identity(Rewriter*, const Node*); -void recreate_decl_body_identity(Rewriter*, const Node*, Node*); +Node* shd_recreate_node_head(Rewriter* rewriter, const Node* old); +void shd_recreate_node_body(Rewriter* rewriter, const Node* old, Node* new); /// Rewrites a variable under a new identity -const Node* recreate_param(Rewriter* rewriter, const Node* old); -Nodes recreate_params(Rewriter* rewriter, Nodes oparams); -Nodes recreate_vars(IrArena* arena, Nodes ovars, const Node* instruction); -Node* clone_bb_head(Rewriter*, const Node* bb); -//const Node* rebind_let(Rewriter*, const Node* ninstruction, const Node* ocase); +const Node* shd_recreate_param(Rewriter* rewriter, const Node* old); +Nodes shd_recreate_params(Rewriter* rewriter, Nodes oparams); /// Looks up if the node was already processed -const Node** search_processed(const Rewriter*, const Node*); -/// Same as search_processed but asserts if it fails to find a mapping -const Node* find_processed(const Rewriter*, const Node*); -void register_processed(Rewriter*, const Node*, const Node*); -void register_processed_list(Rewriter*, Nodes, Nodes); +const Node** shd_search_processed(const Rewriter* ctx, const Node* old); +/// Same as shd_search_processed but asserts if it fails to find a mapping +const Node* shd_find_processed(const Rewriter* ctx, const Node* old); +void shd_register_processed(Rewriter* ctx, const Node* old, const Node* new); +void shd_register_processed_list(Rewriter* rewriter, Nodes old, Nodes new); -void dump_rewriter_map(Rewriter*); +void shd_dump_rewriter_map(Rewriter* r); #endif diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 0f11158e2..19abff629 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -208,7 +208,7 @@ const Node* find_or_process_decl(Rewriter* rewriter, const char* name) { for (size_t i = 0; i < old_decls.count; i++) { const Node* decl = old_decls.nodes[i]; if (strcmp(get_declaration_name(decl), name) == 0) { - return rewrite_node(rewriter, decl); + return shd_rewrite_node(rewriter, decl); } } assert(false); From a1e4df55c90972fa5975fcb2949952d4489c8874 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 14:01:11 +0200 Subject: [PATCH 621/693] moved rewrite.h to public API --- include/shady/pass.h | 2 +- {src => include}/shady/rewrite.h | 0 src/backend/spirv/emit_spv_type.c | 2 +- src/frontend/llvm/l2s_postprocess.c | 2 +- src/shady/fold.c | 2 +- src/shady/passes/lcssa.c | 2 +- src/shady/passes/scope2control.c | 2 +- src/shady/rewrite.c | 2 +- src/shady/transform/ir_gen_helpers.c | 2 +- 9 files changed, 8 insertions(+), 8 deletions(-) rename {src => include}/shady/rewrite.h (100%) diff --git a/include/shady/pass.h b/include/shady/pass.h index ebea68ca1..6ede5f46d 100644 --- a/include/shady/pass.h +++ b/include/shady/pass.h @@ -2,7 +2,7 @@ #define SHADY_PASS_H #include "shady/config.h" -#include "rewrite.h" +#include "shady/rewrite.h" typedef Module* (RewritePass)(const CompilerConfig* config, Module* src); typedef bool (OptPass)(const CompilerConfig* config, Module** m); diff --git a/src/shady/rewrite.h b/include/shady/rewrite.h similarity index 100% rename from src/shady/rewrite.h rename to include/shady/rewrite.h diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 4ca1a4514..981d00772 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -3,7 +3,7 @@ #include "shady/memory_layout.h" #include "../shady/type.h" -#include "../shady/rewrite.h" +#include "shady/rewrite.h" #include "portability.h" #include "log.h" diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 9876b9c05..80c148627 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -6,7 +6,7 @@ #include "log.h" #include "arena.h" -#include "../shady/rewrite.h" +#include "shady/rewrite.h" #include "../shady/type.h" KeyHash hash_node(Node**); diff --git a/src/shady/fold.c b/src/shady/fold.c index 111c78438..233441f77 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -4,7 +4,7 @@ #include "type.h" #include "portability.h" -#include "rewrite.h" +#include "shady/rewrite.h" #include "transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 0d7906824..ffaedaa04 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -1,7 +1,7 @@ #include "shady/ir.h" #include "shady/pass.h" -#include "../rewrite.h" +#include "shady/rewrite.h" #include "../ir_private.h" #include "../analysis/cfg.h" #include "../analysis/scheduler.h" diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index f507043c4..4440f9227 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -7,7 +7,7 @@ #include "arena.h" #include "util.h" -#include "../rewrite.h" +#include "shady/rewrite.h" #include "../type.h" #include "../ir_private.h" #include "../analysis/cfg.h" diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 2fbed77c0..bc6818fe2 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -1,4 +1,4 @@ -#include "rewrite.h" +#include "shady/rewrite.h" #include "log.h" #include "ir_private.h" diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 19abff629..da74b1e38 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -7,7 +7,7 @@ #include "../ir_private.h" #include "../type.h" -#include "../rewrite.h" +#include "shady/rewrite.h" #include #include From d21456dfe9423eeff45764fe72da53f5a779de5f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 14:05:20 +0200 Subject: [PATCH 622/693] move visit.h to public API --- include/shady/visit.h | 28 ++++++++++++++++++++++ src/shady/analysis/callgraph.c | 6 ++--- src/shady/analysis/free_frontier.c | 4 ++-- src/shady/analysis/leak.c | 2 +- src/shady/analysis/scheduler.c | 4 ++-- src/shady/analysis/uses.c | 4 ++-- src/shady/analysis/verify.c | 8 +++---- src/shady/constructors.c | 2 +- src/shady/generator_visit.c | 6 ++--- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_alloca.c | 6 ++--- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/setup_stack_frames.c | 2 +- src/shady/print.c | 4 ++-- src/shady/visit.c | 26 ++++++++++---------- src/shady/visit.h | 30 ------------------------ test/opt/opt_oracle.c | 6 ++--- 17 files changed, 70 insertions(+), 72 deletions(-) create mode 100644 include/shady/visit.h delete mode 100644 src/shady/visit.h diff --git a/include/shady/visit.h b/include/shady/visit.h new file mode 100644 index 000000000..04ed20103 --- /dev/null +++ b/include/shady/visit.h @@ -0,0 +1,28 @@ +#ifndef SHADY_VISIT_H +#define SHADY_VISIT_H + +#include "shady/ir.h" + +typedef struct Visitor_ Visitor; +typedef void (*VisitNodeFn)(Visitor*, const Node*); +typedef void (*VisitOpFn)(Visitor*, NodeClass, String, const Node*, size_t); + +struct Visitor_ { + VisitNodeFn visit_node_fn; + VisitOpFn visit_op_fn; +}; + +void shd_visit_node_operands(Visitor* visitor, NodeClass exclude, const Node* node); +void shd_visit_module(Visitor* visitor, Module* mod); + +void shd_visit_node(Visitor* visitor, const Node* node); +void shd_visit_nodes(Visitor* visitor, Nodes nodes); + +void shd_visit_op(Visitor* visitor, NodeClass op_class, String op_name, const Node* op, size_t i); +void shd_visit_ops(Visitor* visitor, NodeClass op_class, String op_name, Nodes ops); + +// visits the abstractions in the function, starting with the entry block (ie the function itself) +void shd_visit_function_rpo(Visitor* visitor, const Node* function); +void shd_visit_function_bodies_rpo(Visitor* visitor, const Node* function); + +#endif diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index 7c0c9b3e3..a25e9133b 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -6,7 +6,7 @@ #include "portability.h" #include "log.h" -#include "../visit.h" +#include "shady/visit.h" #include #include @@ -82,7 +82,7 @@ static void search_for_callsites(CGVisitor* visitor, const Node* node) { } default: break; } - visit_node_operands(&visitor->visitor, ~NcMem, node); + shd_visit_node_operands(&visitor->visitor, ~NcMem, node); } static CGNode* analyze_fn(CallGraph* graph, const Node* fn) { @@ -106,7 +106,7 @@ static CGNode* analyze_fn(CallGraph* graph, const Node* fn) { }; if (get_abstraction_body(fn)) { - visit_function_rpo(&v.visitor, fn); + shd_visit_function_rpo(&v.visitor, fn); } return new; diff --git a/src/shady/analysis/free_frontier.c b/src/shady/analysis/free_frontier.c index 652068f61..c31f93302 100644 --- a/src/shady/analysis/free_frontier.c +++ b/src/shady/analysis/free_frontier.c @@ -1,6 +1,6 @@ #include "free_frontier.h" -#include "visit.h" +#include "shady/visit.h" #include "dict.h" typedef struct { @@ -20,7 +20,7 @@ static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { if (where) { FreeFrontierVisitor vv = *v; if (cfg_is_dominated(where, v->start)) { - visit_node_operands(&vv.v, NcAbstraction | NcDeclaration | NcType, node); + shd_visit_node_operands(&vv.v, NcAbstraction | NcDeclaration | NcType, node); } else { if (is_abstraction(node)) { struct Dict* other_ff = free_frontier(v->scheduler, v->cfg, node); diff --git a/src/shady/analysis/leak.c b/src/shady/analysis/leak.c index ee253c46c..49b9d38a7 100644 --- a/src/shady/analysis/leak.c +++ b/src/shady/analysis/leak.c @@ -3,7 +3,7 @@ #include #include -#include "../visit.h" +#include "shady/visit.h" void visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, VisitEnclosingAbsCallback fn) { const Use* use = get_first_use(map, n); diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c index f639929e8..facb462ff 100644 --- a/src/shady/analysis/scheduler.c +++ b/src/shady/analysis/scheduler.c @@ -1,6 +1,6 @@ #include "scheduler.h" -#include "visit.h" +#include "shady/visit.h" #include "dict.h" #include @@ -73,7 +73,7 @@ CFNode* schedule_instruction(Scheduler* s, const Node* n) { schedule_after(&s2.result, cfg_lookup(s->cfg, n->payload.abs_mem.abs)); } - visit_node_operands(&s2.v, 0, n); + shd_visit_node_operands(&s2.v, 0, n); shd_dict_insert(const Node*, CFNode*, s->scheduled, n, s2.result); return s2.result; } diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index 8361c600a..bef4a3bb4 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -2,7 +2,7 @@ #include "log.h" -#include "../visit.h" +#include "shady/visit.h" #include #include @@ -39,7 +39,7 @@ static void uses_visit_node(UsesMapVisitor* v, const Node* n) { shd_set_insert_get_result(const Node*, v->seen, n); UsesMapVisitor nv = *v; nv.user = n; - visit_node_operands(&nv.v, v->exclude, n); + shd_visit_node_operands(&nv.v, v->exclude, n); } } diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 914f6fb6c..e6f0d6303 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -6,7 +6,7 @@ #include "dict.h" #include "list.h" -#include "../visit.h" +#include "shady/visit.h" #include "../ir_private.h" #include "../type.h" @@ -23,7 +23,7 @@ static void visit_verify_same_arena(ArenaVerifyVisitor* visitor, const Node* nod if (shd_dict_find_key(const Node*, visitor->once, node)) return; shd_set_insert_get_result(const Node*, visitor->once, node); - visit_node_operands(&visitor->visitor, 0, node); + shd_visit_node_operands(&visitor->visitor, 0, node); } KeyHash hash_node(const Node**); @@ -38,7 +38,7 @@ static void verify_same_arena(Module* mod) { .arena = arena, .once = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node) }; - visit_module(&visitor.visitor, mod); + shd_visit_module(&visitor.visitor, mod); shd_destroy_dict(visitor.once); } @@ -132,7 +132,7 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { shd_error_die(); } } - visit_node_operands(&ctx->visitor, NcTerminator | NcDeclaration, node); + shd_visit_node_operands(&ctx->visitor, NcTerminator | NcDeclaration, node); } static void verify_bodies(const CompilerConfig* config, Module* mod) { diff --git a/src/shady/constructors.c b/src/shady/constructors.c index feea55827..d706f81c2 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -5,7 +5,7 @@ #include "portability.h" #include "dict.h" -#include "visit.h" +#include "shady/visit.h" #include #include diff --git a/src/shady/generator_visit.c b/src/shady/generator_visit.c index b7bcde003..5be736aba 100644 --- a/src/shady/generator_visit.c +++ b/src/shady/generator_visit.c @@ -4,7 +4,7 @@ void generate(Growy* g, json_object* src) { generate_header(g, src); json_object* nodes = json_object_object_get(src, "nodes"); - shd_growy_append_formatted(g, "void visit_node_operands(Visitor* visitor, NodeClass exclude, const Node* node) {\n"); + shd_growy_append_formatted(g, "void shd_visit_node_operands(Visitor* visitor, NodeClass exclude, const Node* node) {\n"); shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { @@ -33,9 +33,9 @@ void generate(Growy* g, json_object* src) { if (!ignore) { shd_growy_append_formatted(g, "\t\tif ((exclude & Nc%s) == 0)\n", class_cap); if (list) - shd_growy_append_formatted(g, "\t\t\tvisit_ops(visitor, Nc%s, \"%s\", payload.%s);\n", class_cap, op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tshd_visit_ops(visitor, Nc%s, \"%s\", payload.%s);\n", class_cap, op_name, op_name); else - shd_growy_append_formatted(g, "\t\t\tvisit_op(visitor, Nc%s, \"%s\", payload.%s, 0);\n", class_cap, op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tshd_visit_op(visitor, Nc%s, \"%s\", payload.%s, 0);\n", class_cap, op_name, op_name); } free((void*) class_cap); } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index efb930393..602f2f5e9 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -3,7 +3,7 @@ #include "../type.h" #include "../ir_private.h" -#include "../visit.h" +#include "shady/visit.h" #include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index eda2d2494..d3743b9b1 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -1,6 +1,6 @@ #include "shady/pass.h" -#include "../visit.h" +#include "shady/visit.h" #include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -66,7 +66,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { default: break; } - visit_node_operands(&vctx->visitor, ~NcMem, node); + shd_visit_node_operands(&vctx->visitor, ~NcMem, node); } KeyHash hash_node(Node**); @@ -107,7 +107,7 @@ static const Node* process(Context* ctx, const Node* node) { .members = shd_new_list(const Node*), .prepared_offsets = ctx2.prepared_offsets, }; - visit_function_bodies_rpo(&vctx.visitor, node); + shd_visit_function_bodies_rpo(&vctx.visitor, node); vctx.nom_t->payload.nom_type.body = record_type(a, (RecordType) { .members = shd_nodes(a, vctx.num_slots, shd_read_list(const Node*, vctx.members)), diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 5246e0439..64a355b4c 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -1,6 +1,6 @@ #include "shady/pass.h" -#include "../visit.h" +#include "shady/visit.h" #include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 46041622a..04d01032c 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -1,6 +1,6 @@ #include "shady/pass.h" -#include "../visit.h" +#include "shady/visit.h" #include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/print.c b/src/shady/print.c index 6c315d3a3..b630d9039 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -13,7 +13,7 @@ #include "printer.h" #include "type.h" -#include "visit.h" +#include "shady/visit.h" #include #include @@ -1125,7 +1125,7 @@ static void print_mem(PrinterCtx* ctx, const Node* mem) { case Mem_MemAndValue_TAG: return print_mem(ctx, mem->payload.mem_and_value.mem); default: { assert(is_instruction(mem)); - visit_node_operands((Visitor*) &pv, 0, mem); + shd_visit_node_operands((Visitor*) &pv, 0, mem); return; } } diff --git a/src/shady/visit.c b/src/shady/visit.c index ad8345b4a..2a67b0f8e 100644 --- a/src/shady/visit.c +++ b/src/shady/visit.c @@ -1,23 +1,23 @@ #include "shady/ir.h" #include "log.h" -#include "visit.h" +#include "shady/visit.h" #include "analysis/cfg.h" #include -void visit_node(Visitor* visitor, const Node* node) { +void shd_visit_node(Visitor* visitor, const Node* node) { assert(visitor->visit_node_fn); if (node) visitor->visit_node_fn(visitor, node); } -void visit_nodes(Visitor* visitor, Nodes nodes) { +void shd_visit_nodes(Visitor* visitor, Nodes nodes) { for (size_t i = 0; i < nodes.count; i++) { - visit_node(visitor, nodes.nodes[i]); + shd_visit_node(visitor, nodes.nodes[i]); } } -void visit_op(Visitor* visitor, NodeClass op_class, String op_name, const Node* op, size_t i) { +void shd_visit_op(Visitor* visitor, NodeClass op_class, String op_name, const Node* op, size_t i) { if (!op) return; if (visitor->visit_op_fn) @@ -26,23 +26,23 @@ void visit_op(Visitor* visitor, NodeClass op_class, String op_name, const Node* visitor->visit_node_fn(visitor, op); } -void visit_ops(Visitor* visitor, NodeClass op_class, String op_name, Nodes ops) { +void shd_visit_ops(Visitor* visitor, NodeClass op_class, String op_name, Nodes ops) { for (size_t i = 0; i < ops.count; i++) - visit_op(visitor, op_class, op_name, ops.nodes[i], i); + shd_visit_op(visitor, op_class, op_name, ops.nodes[i], i); } -void visit_function_rpo(Visitor* visitor, const Node* function) { +void shd_visit_function_rpo(Visitor* visitor, const Node* function) { assert(function->tag == Function_TAG); CFG* cfg = build_fn_cfg(function); assert(cfg->rpo[0]->node == function); for (size_t i = 0; i < cfg->size; i++) { const Node* node = cfg->rpo[i]->node; - visit_node(visitor, node); + shd_visit_node(visitor, node); } destroy_cfg(cfg); } -void visit_function_bodies_rpo(Visitor* visitor, const Node* function) { +void shd_visit_function_bodies_rpo(Visitor* visitor, const Node* function) { assert(function->tag == Function_TAG); CFG* cfg = build_fn_cfg(function); assert(cfg->rpo[0]->node == function); @@ -50,7 +50,7 @@ void visit_function_bodies_rpo(Visitor* visitor, const Node* function) { const Node* node = cfg->rpo[i]->node; assert(is_abstraction(node)); if (get_abstraction_body(node)) - visit_node(visitor, get_abstraction_body(node)); + shd_visit_node(visitor, get_abstraction_body(node)); } destroy_cfg(cfg); } @@ -59,7 +59,7 @@ void visit_function_bodies_rpo(Visitor* visitor, const Node* function) { #include "visit_generated.c" -void visit_module(Visitor* visitor, Module* mod) { +void shd_visit_module(Visitor* visitor, Module* mod) { Nodes decls = get_module_declarations(mod); - visit_nodes(visitor, decls); + shd_visit_nodes(visitor, decls); } diff --git a/src/shady/visit.h b/src/shady/visit.h deleted file mode 100644 index 0926115a0..000000000 --- a/src/shady/visit.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SHADY_VISIT_H -#define SHADY_VISIT_H - -#include "shady/ir.h" - -typedef struct Visitor_ Visitor; -typedef void (*VisitNodeFn)(Visitor*, const Node*); -typedef void (*VisitOpFn)(Visitor*, NodeClass, String, const Node*, size_t); - -struct Visitor_ { - VisitNodeFn visit_node_fn; - VisitOpFn visit_op_fn; -}; - -void visit_node_operands(Visitor*, NodeClass exclude, const Node*); -void visit_module(Visitor* visitor, Module*); - -void visit_node(Visitor* visitor, const Node*); -void visit_nodes(Visitor* visitor, Nodes nodes); - -void visit_op(Visitor* visitor, NodeClass, String, const Node*, size_t i); -void visit_ops(Visitor* visitor, NodeClass, String, Nodes nodes); - -// visits the abstractions in the function, starting with the entry block (ie the function itself) -void visit_function_rpo(Visitor* visitor, const Node* function); -void visit_function_bodies_rpo(Visitor* visitor, const Node* function); -// use this in visit_node_operands to avoid visiting nodes in non-rpo order -#define IGNORE_ABSTRACTIONS_MASK NcBasic_block | NcDeclaration | NcAbstraction - -#endif diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index a12d4fc8f..ba8bc0c68 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -1,9 +1,9 @@ #include "shady/ir.h" #include "shady/driver.h" #include "shady/print.h" +#include "shady/visit.h" #include "../shady/passes/passes.h" -#include "../shady/visit.h" #include "log.h" #include "portability.h" @@ -29,12 +29,12 @@ static void search_for_memstuff(Visitor* v, const Node* n) { default: break; } - visit_node_operands(v, ~(NcMem | NcDeclaration | NcTerminator), n); + shd_visit_node_operands(v, ~(NcMem | NcDeclaration | NcTerminator), n); } static void check_module(Module* mod) { Visitor v = { .visit_node_fn = search_for_memstuff }; - visit_module(&v, mod); + shd_visit_module(&v, mod); if (expect_memstuff != found_memstuff) { shd_error_print("Expected "); if (!expect_memstuff) From e8826a53b46394b2e05ace937f589aa937ca34b3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 14:08:52 +0200 Subject: [PATCH 623/693] prefix hash/cmp node --- src/backend/c/emit_c.c | 10 +++++----- src/backend/spirv/emit_spv.c | 10 +++++----- src/frontend/llvm/l2s.c | 6 +++--- src/frontend/llvm/l2s_postprocess.c | 4 ++-- src/shady/analysis/callgraph.c | 6 +++--- src/shady/analysis/cfg.c | 10 +++++----- src/shady/analysis/free_frontier.c | 8 ++++---- src/shady/analysis/looptree.c | 6 +++--- src/shady/analysis/scheduler.c | 6 +++--- src/shady/analysis/uses.c | 8 ++++---- src/shady/analysis/verify.c | 6 +++--- src/shady/generator_node.c | 4 ++-- src/shady/ir.c | 6 +++--- src/shady/node.c | 12 ++++++------ src/shady/passes/lcssa.c | 6 +++--- src/shady/passes/lift_everything.c | 6 +++--- src/shady/passes/lift_indirect_targets.c | 6 +++--- src/shady/passes/lower_alloca.c | 6 +++--- src/shady/passes/lower_cf_instrs.c | 6 +++--- src/shady/passes/lower_nullptr.c | 6 +++--- src/shady/passes/lower_physical_ptrs.c | 12 ++++++------ src/shady/passes/lower_stack.c | 8 ++++---- src/shady/passes/lower_subgroup_ops.c | 6 +++--- src/shady/passes/lower_tailcalls.c | 6 +++--- src/shady/passes/mark_leaf_functions.c | 6 +++--- src/shady/passes/opt_demote_alloca.c | 6 +++--- src/shady/passes/opt_inline.c | 4 ++-- src/shady/passes/scope2control.c | 10 +++++----- src/shady/print.c | 6 +++--- src/shady/rewrite.c | 16 ++++++++-------- 30 files changed, 109 insertions(+), 109 deletions(-) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 56f990dab..d9b8ec1aa 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -22,8 +22,8 @@ #pragma GCC diagnostic error "-Wswitch" -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); void register_emitted(Emitter* emitter, FnEmitter* fn, const Node* node, CTerm as) { //assert(as.value || as.var); @@ -307,7 +307,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { if (body) { FnEmitter fn = { .cfg = build_fn_cfg(decl), - .emitted_terms = shd_new_dict(Node*, CTerm, (HashFn) hash_node, (CmpFn) compare_node), + .emitted_terms = shd_new_dict(Node*, CTerm, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; fn.scheduler = new_scheduler(fn.cfg); fn.instruction_printers = calloc(sizeof(Printer*), fn.cfg->size); @@ -437,8 +437,8 @@ void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Mo .type_decls = shd_new_printer_from_growy(type_decls_g), .fn_decls = shd_new_printer_from_growy(fn_decls_g), .fn_defs = shd_new_printer_from_growy(fn_defs_g), - .emitted_terms = shd_new_dict(Node*, CTerm, (HashFn) hash_node, (CmpFn) compare_node), - .emitted_types = shd_new_dict(Node*, String, (HashFn) hash_node, (CmpFn) compare_node), + .emitted_terms = shd_new_dict(Node*, CTerm, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), + .emitted_types = shd_new_dict(Node*, String, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; // builtins magic (hack) for CUDA diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 10a84540c..ce0f9d45a 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -19,8 +19,8 @@ #include #include -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); KeyHash shd_hash_string(const char** string); bool shd_compare_string(const char** a, const char** b); @@ -84,7 +84,7 @@ static void emit_function(Emitter* emitter, const Node* node) { SpvId fn_id = spv_find_emitted(emitter, NULL, node); FnBuilder fn_builder = { .base = spvb_begin_fn(emitter->file_builder, fn_id, spv_emit_type(emitter, fn_type), spv_types_to_codom(emitter, node->payload.fun.return_types)), - .emitted = shd_new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), + .emitted = shd_new_dict(Node*, SpvId, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .cfg = build_fn_cfg(node), }; fn_builder.scheduler = new_scheduler(fn_builder.cfg); @@ -341,8 +341,8 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, .arena = arena, .configuration = config, .file_builder = file_builder, - .global_node_ids = shd_new_dict(Node*, SpvId, (HashFn) hash_node, (CmpFn) compare_node), - .bb_builders = shd_new_dict(Node*, BBBuilder, (HashFn) hash_node, (CmpFn) compare_node), + .global_node_ids = shd_new_dict(Node*, SpvId, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), + .bb_builders = shd_new_dict(Node*, BBBuilder, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .num_entry_pts = 0, }; diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 28cbd9ad4..2b50e673d 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -33,8 +33,8 @@ static bool cmp_opaque_ptr(OpaqueRef* a, OpaqueRef* b) { return *a == *b; } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); #ifdef LLVM_VERSION_MAJOR int vcc_get_linked_major_llvm_version() { @@ -180,7 +180,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { Node* f = function(p->dst, params, LLVMGetValueName(fn), annotations, fn_type->payload.fn_type.return_types); FnParseCtx fn_parse_ctx = { .fn = f, - .phis = shd_new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), + .phis = shd_new_dict(const Node*, struct List*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .bbs = shd_new_dict(LLVMBasicBlockRef, BBParseCtx*, (HashFn) shd_hash_ptr, (CmpFn) shd_compare_ptrs), .jumps_todo = shd_new_list(JumpTodo), }; diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 80c148627..9e5d41002 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -9,8 +9,8 @@ #include "shady/rewrite.h" #include "../shady/type.h" -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); typedef struct { Rewriter rewriter; diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index a25e9133b..6798e42c2 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -12,8 +12,8 @@ #include #include -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); +KeyHash shd_hash_node(const Node**); +bool shd_compare_node(const Node**, const Node**); KeyHash hash_cgedge(CGEdge* n) { return shd_hash_murmur(n, sizeof(CGEdge)); @@ -197,7 +197,7 @@ static void tarjan(struct Dict* verts) { CallGraph* new_callgraph(Module* mod) { CallGraph* graph = calloc(sizeof(CallGraph), 1); *graph = (CallGraph) { - .fn2cgn = shd_new_dict(const Node*, CGNode*, (HashFn) hash_node, (CmpFn) compare_node) + .fn2cgn = shd_new_dict(const Node*, CGNode*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node) }; const UsesMap* uses = create_module_uses_map(mod, NcType); diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index c8ecc5d19..f3014de0c 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -28,8 +28,8 @@ struct List* build_cfgs(Module* mod, CFGBuildConfig config) { return cfgs; } -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); +KeyHash shd_hash_node(const Node**); +bool shd_compare_node(const Node**, const Node**); typedef struct { Arena* arena; @@ -69,7 +69,7 @@ static CFNode* new_cfnode(Arena* a) { .rpo_index = SIZE_MAX, .idom = NULL, .dominates = NULL, - .structurally_dominates = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .structurally_dominates = shd_new_set(const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; return new; } @@ -381,8 +381,8 @@ CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { .arena = arena, .function = function, .entry = entry, - .nodes = shd_new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), - .join_point_values = shd_new_dict(const Node*, const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .nodes = shd_new_dict(const Node*, CFNode*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), + .join_point_values = shd_new_dict(const Node*, const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .contents = shd_new_list(CFNode*), .config = config, }; diff --git a/src/shady/analysis/free_frontier.c b/src/shady/analysis/free_frontier.c index c31f93302..c252388ff 100644 --- a/src/shady/analysis/free_frontier.c +++ b/src/shady/analysis/free_frontier.c @@ -38,8 +38,8 @@ static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { } } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); struct Dict* free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs) { FreeFrontierVisitor ffv = { @@ -49,8 +49,8 @@ struct Dict* free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs) { .scheduler = scheduler, .cfg = cfg, .start = cfg_lookup(cfg, abs), - .frontier = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), - .seen = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .frontier = shd_new_set(const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), + .seen = shd_new_set(const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; if (get_abstraction_body(abs)) visit_free_frontier(&ffv, get_abstraction_body(abs)); diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index 0f67a41be..1bc2627b9 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -23,8 +23,8 @@ typedef struct { struct List* stack; } LoopTreeBuilder; -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); +KeyHash shd_hash_node(const Node**); +bool shd_compare_node(const Node**, const Node**); LTNode* new_lf_node(int type, LTNode* parent, int depth, struct List* cf_nodes) { LTNode* n = calloc(sizeof(LTNode), 1); @@ -221,7 +221,7 @@ LoopTree* build_loop_tree(CFG* s) { shd_destroy_list(global_heads); shd_destroy_list(ltb.stack); - lt->map = shd_new_dict(const Node*, LTNode*, (HashFn) hash_node, (CmpFn) compare_node); + lt->map = shd_new_dict(const Node*, LTNode*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); build_map_recursive(lt->map, lt->root); return lt; diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c index facb462ff..07c2e87cb 100644 --- a/src/shady/analysis/scheduler.c +++ b/src/shady/analysis/scheduler.c @@ -5,8 +5,8 @@ #include "dict.h" #include -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); struct Scheduler_ { Visitor v; @@ -51,7 +51,7 @@ Scheduler* new_scheduler(CFG* cfg) { .visit_op_fn = (VisitOpFn) visit_operand, }, .cfg = cfg, - .scheduled = shd_new_dict(const Node*, CFNode*, (HashFn) hash_node, (CmpFn) compare_node), + .scheduled = shd_new_dict(const Node*, CFNode*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; return s; } diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index bef4a3bb4..bbf93496a 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -8,8 +8,8 @@ #include #include -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); struct UsesMap_ { struct Dict* map; @@ -66,7 +66,7 @@ static void uses_visit_op(UsesMapVisitor* v, NodeClass class, String op_name, co static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeClass exclude) { UsesMap* uses = calloc(sizeof(UsesMap), 1); *uses = (UsesMap) { - .map = shd_new_dict(const Node*, Use*, (HashFn) hash_node, (CmpFn) compare_node), + .map = shd_new_dict(const Node*, Use*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .a = shd_new_arena(), }; @@ -74,7 +74,7 @@ static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeCl .v = { .visit_op_fn = (VisitOpFn) uses_visit_op }, .map = uses, .exclude = exclude, - .seen = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .seen = shd_new_set(const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; if (root) uses_visit_node(&v, root); diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index e6f0d6303..0aabd064c 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -26,8 +26,8 @@ static void visit_verify_same_arena(ArenaVerifyVisitor* visitor, const Node* nod shd_visit_node_operands(&visitor->visitor, 0, node); } -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); +KeyHash shd_hash_node(const Node**); +bool shd_compare_node(const Node**, const Node**); static void verify_same_arena(Module* mod) { const IrArena* arena = get_module_arena(mod); @@ -36,7 +36,7 @@ static void verify_same_arena(Module* mod) { .visit_node_fn = (VisitNodeFn) visit_verify_same_arena, }, .arena = arena, - .once = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node) + .once = shd_new_set(const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node) }; shd_visit_module(&visitor.visitor, mod); shd_destroy_dict(visitor.once); diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 9d2d8a8de..1c6f00a04 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -34,7 +34,7 @@ static void generate_node_has_payload_array(Growy* g, json_object* nodes) { } static void generate_node_payload_hash_fn(Growy* g, json_object* src, json_object* nodes) { - shd_growy_append_formatted(g, "KeyHash hash_node_payload(const Node* node) {\n"); + shd_growy_append_formatted(g, "KeyHash _shd_hash_node_payload(const Node* node) {\n"); shd_growy_append_formatted(g, "\tKeyHash hash = 0;\n"); shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); @@ -73,7 +73,7 @@ static void generate_node_payload_hash_fn(Growy* g, json_object* src, json_objec } static void generate_node_payload_cmp_fn(Growy* g, json_object* src, json_object* nodes) { - shd_growy_append_formatted(g, "bool compare_node_payload(const Node* a, const Node* b) {\n"); + shd_growy_append_formatted(g, "bool _shd_compare_node_payload(const Node* a, const Node* b) {\n"); shd_growy_append_formatted(g, "\tbool eq = true;\n"); shd_growy_append_formatted(g, "\tswitch (a->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); diff --git a/src/shady/ir.c b/src/shady/ir.c index 92a0fa32a..7bdd348ba 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -19,8 +19,8 @@ static bool shd_compare_strings(Strings* a, Strings* b); KeyHash shd_hash_string(const char** string); bool shd_compare_string(const char** a, const char** b); -KeyHash hash_node(const Node**); -bool compare_node(const Node** a, const Node** b); +KeyHash shd_hash_node(const Node**); +bool shd_compare_node(const Node** a, const Node** b); IrArena* shd_new_ir_arena(const ArenaConfig* config) { IrArena* arena = malloc(sizeof(IrArena)); @@ -30,7 +30,7 @@ IrArena* shd_new_ir_arena(const ArenaConfig* config) { .modules = shd_new_list(Module*), - .node_set = shd_new_set(const Node*, (HashFn) hash_node, (CmpFn) compare_node), + .node_set = shd_new_set(const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .string_set = shd_new_set(const char*, (HashFn) shd_hash_string, (CmpFn) shd_compare_string), .nodes_set = shd_new_set(Nodes, (HashFn) shd_hash_nodes, (CmpFn) shd_compare_nodes), diff --git a/src/shady/node.c b/src/shady/node.c index af4d45a95..2cbacbcde 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -329,9 +329,9 @@ void set_abstraction_body(Node* abs, const Node* body) { } } -KeyHash hash_node_payload(const Node* node); +KeyHash _shd_hash_node_payload(const Node* node); -KeyHash hash_node(Node** pnode) { +KeyHash shd_hash_node(Node** pnode) { const Node* node = *pnode; KeyHash combined; @@ -347,7 +347,7 @@ KeyHash hash_node(Node** pnode) { KeyHash payload_hash = 0; if (node_type_has_payload[node->tag]) { - payload_hash = hash_node_payload(node); + payload_hash = _shd_hash_node_payload(node); } combined = tag_hash ^ payload_hash; @@ -355,9 +355,9 @@ KeyHash hash_node(Node** pnode) { return combined; } -bool compare_node_payload(const Node*, const Node*); +bool _shd_compare_node_payload(const Node*, const Node*); -bool compare_node(Node** pa, Node** pb) { +bool shd_compare_node(Node** pa, Node** pb) { if ((*pa)->tag != (*pb)->tag) return false; if (is_nominal((*pa))) return *pa == *pb; @@ -369,7 +369,7 @@ bool compare_node(Node** pa, Node** pb) { #define field(w) eq &= memcmp(&a->payload.w, &b->payload.w, sizeof(a->payload.w)) == 0; if (node_type_has_payload[a->tag]) { - return compare_node_payload(a, b); + return _shd_compare_node_payload(a, b); } else return true; } diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index ffaedaa04..88396743d 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -185,8 +185,8 @@ const Node* process_node(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); Module* lcssa(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); @@ -197,7 +197,7 @@ Module* lcssa(const CompilerConfig* config, Module* src) { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .current_fn = NULL, - .lifted_arguments = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node) + .lifted_arguments = shd_new_dict(const Node*, Nodes, (HashFn) shd_hash_node, (CmpFn) shd_compare_node) }; shd_rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index ea233df1f..43950aa3d 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -11,8 +11,8 @@ #include "dict.h" #include "portability.h" -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); typedef struct { Rewriter rewriter; @@ -109,7 +109,7 @@ Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), - .lift = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), + .lift = shd_new_dict(const Node*, Nodes, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; shd_rewrite_module(&ctx.rewriter); shd_destroy_dict(ctx.lift); diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 602f2f5e9..66ed7f95a 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -21,8 +21,8 @@ #include -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); typedef struct Context_ { Rewriter rewriter; @@ -235,7 +235,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { bool todo = false; Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), - .lifted = shd_new_dict(const Node*, LiftedCont*, (HashFn) hash_node, (CmpFn) compare_node), + .lifted = shd_new_dict(const Node*, LiftedCont*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .config = config, .todo = &todo diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index d3743b9b1..db0d69a72 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -69,8 +69,8 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { shd_visit_node_operands(&vctx->visitor, ~NcMem, node); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); static const Node* process(Context* ctx, const Node* node) { Rewriter* r = &ctx->rewriter; @@ -90,7 +90,7 @@ static const Node* process(Context* ctx, const Node* node) { } BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); - ctx2.prepared_offsets = shd_new_dict(const Node*, StackSlot, (HashFn) hash_node, (CmpFn) compare_node); + ctx2.prepared_offsets = shd_new_dict(const Node*, StackSlot, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); ctx2.base_stack_addr_on_entry = gen_get_stack_base_addr(bb); ctx2.stack_size_on_entry = gen_get_stack_size(bb); set_value_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index cf785d14f..ac79093df 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -231,8 +231,8 @@ static const Node* process_node(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); +KeyHash shd_hash_node(const Node**); +bool shd_compare_node(const Node**, const Node**); Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); @@ -240,7 +240,7 @@ Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), - .structured_join_tokens = shd_new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), + .structured_join_tokens = shd_new_dict(const Node*, Nodes, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; shd_rewrite_module(&ctx.rewriter); shd_destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index ee46dc9c3..c98c0aa39 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -45,8 +45,8 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); @@ -54,7 +54,7 @@ Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), - .map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .map = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; shd_rewrite_module(&ctx.rewriter); shd_destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 6b1a2cbc1..517308f28 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -361,8 +361,8 @@ static const Node* process_node(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); static Nodes collect_globals(Context* ctx, AddressSpace as) { IrArena* a = ctx->rewriter.dst_arena; @@ -502,10 +502,10 @@ Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { for (size_t i = 0; i < NumAddressSpaces; i++) { if (is_as_emulated(&ctx, i)) { - ctx.serialisation_varying[i] = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); - ctx.deserialisation_varying[i] = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); - ctx.serialisation_uniform[i] = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); - ctx.deserialisation_uniform[i] = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + ctx.serialisation_varying[i] = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); + ctx.deserialisation_varying[i] = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); + ctx.serialisation_uniform[i] = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); + ctx.deserialisation_uniform[i] = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); } } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index a5bd0944d..9ded42e7f 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -171,8 +171,8 @@ static const Node* process_node(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); @@ -184,8 +184,8 @@ Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { .config = config, - .push = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), - .pop = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .push = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), + .pop = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; if (config->per_thread_stack_size > 0) { diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index e1729b27b..827900c72 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -145,8 +145,8 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); @@ -156,7 +156,7 @@ Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, - .fns = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node) + .fns = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node) }; shd_rewrite_module(&ctx.rewriter); shd_destroy_rewriter(&ctx.rewriter); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index caf536510..ab9b9f5ad 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -434,15 +434,15 @@ void generate_top_level_dispatch_fn(Context* ctx) { }))); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = new_module(a, get_module_name(src)); - struct Dict* ptrs = shd_new_dict(const Node*, FnPtr, (HashFn) hash_node, (CmpFn) compare_node); + struct Dict* ptrs = shd_new_dict(const Node*, FnPtr, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); Node* init_fn = function(dst, shd_nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), shd_nodes(a, 0, NULL)); set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = shd_empty(a), .mem = get_abstraction_mem(init_fn) })); diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index 3ccb20806..eca7ed822 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -148,8 +148,8 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); @@ -157,7 +157,7 @@ Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* s Module* dst = new_module(a, get_module_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), - .fns = shd_new_dict(const Node*, FnInfo, (HashFn) hash_node, (CmpFn) compare_node), + .fns = shd_new_dict(const Node*, FnInfo, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .graph = new_callgraph(src) }; shd_rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 64a355b4c..41fe651e8 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -231,8 +231,8 @@ static const Node* process(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); +KeyHash shd_hash_node(const Node**); +bool shd_compare_node(const Node**, const Node**); bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { bool todo = false; @@ -243,7 +243,7 @@ bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, .arena = shd_new_arena(), - .alloca_info = shd_new_dict(const Node*, AllocaInfo*, (HashFn) hash_node, (CmpFn) compare_node), + .alloca_info = shd_new_dict(const Node*, AllocaInfo*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .todo = &todo }; shd_rewrite_module(&ctx.rewriter); diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index acd24ac7d..ac80d83f0 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -223,8 +223,8 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -KeyHash hash_node(const Node**); -bool compare_node(const Node**, const Node**); +KeyHash shd_hash_node(const Node**); +bool shd_compare_node(const Node**, const Node**); void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { Context ctx = { diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 4440f9227..08d2ebe4c 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -17,8 +17,8 @@ #include -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); typedef struct { Rewriter rewriter; @@ -68,7 +68,7 @@ static Controls* get_or_create_controls(Context* ctx, const Node* fn_or_bb) { IrArena* a = ctx->rewriter.dst_arena; Controls* controls = shd_arena_alloc(ctx->arena, sizeof(Controls)); *controls = (Controls) { - .control_destinations = shd_new_dict(const Node*, AddControl, (HashFn) hash_node, (CmpFn) compare_node), + .control_destinations = shd_new_dict(const Node*, AddControl, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; shd_dict_insert(const Node*, Controls*, ctx->controls, fn_or_bb, controls); return controls; @@ -309,8 +309,8 @@ Module* scope2control(const CompilerConfig* config, Module* src) { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, .arena = shd_new_arena(), - .controls = shd_new_dict(const Node*, Controls*, (HashFn) hash_node, (CmpFn) compare_node), - .jump2wrapper = shd_new_dict(const Node*, Wrapped, (HashFn) hash_node, (CmpFn) compare_node), + .controls = shd_new_dict(const Node*, Controls*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), + .jump2wrapper = shd_new_dict(const Node*, Wrapped, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; ctx.rewriter.rewrite_fn = (RewriteNodeFn) process_node; diff --git a/src/shady/print.c b/src/shady/print.c index b630d9039..3e66aeaa9 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -37,8 +37,8 @@ struct PrinterCtx_ { struct Dict* emitted; }; -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); static bool print_node_impl(PrinterCtx* ctx, const Node* node); static void print_terminator(PrinterCtx* ctx, const Node* node); @@ -51,7 +51,7 @@ static PrinterCtx make_printer_ctx(Printer* printer, NodePrintConfig config) { PrinterCtx ctx = { .printer = printer, .config = config, - .emitted = shd_new_dict(const Node*, String, (HashFn) hash_node, (CmpFn) compare_node), + .emitted = shd_new_dict(const Node*, String, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .root_growy = shd_new_growy(), }; ctx.root_printer = shd_new_printer_from_growy(ctx.root_growy); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index bc6818fe2..71d7b18dd 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -10,8 +10,8 @@ #include #include -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); Rewriter shd_create_rewriter_base(Module* src, Module* dst) { return (Rewriter) { @@ -23,9 +23,9 @@ Rewriter shd_create_rewriter_base(Module* src, Module* dst) { .search_map = true, .write_map = true, }, - .map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .map = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .own_decls = true, - .decls_map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node), + .decls_map = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .parent = NULL, }; } @@ -56,7 +56,7 @@ Rewriter shd_create_importer(Module* src, Module* dst) { Rewriter shd_create_children_rewriter(Rewriter* parent) { Rewriter r = *parent; - r.map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + r.map = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); r.parent = parent; r.own_decls = false; return r; @@ -64,7 +64,7 @@ Rewriter shd_create_children_rewriter(Rewriter* parent) { Rewriter shd_create_decl_rewriter(Rewriter* parent) { Rewriter r = *parent; - r.map = shd_new_dict(const Node*, Node*, (HashFn) hash_node, (CmpFn) compare_node); + r.map = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); r.own_decls = false; return r; } @@ -232,8 +232,8 @@ void shd_register_processed_list(Rewriter* rewriter, Nodes old, Nodes new) { shd_register_processed(rewriter, old.nodes[i], new.nodes[i]); } -KeyHash hash_node(Node**); -bool compare_node(Node**, Node**); +KeyHash shd_hash_node(Node** pnode); +bool shd_compare_node(Node** pa, Node** pb); #pragma GCC diagnostic error "-Wswitch" From ecd8946d1075f3dad98e0977225ed7afa40a9c85 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 14:39:12 +0200 Subject: [PATCH 624/693] split ir.h into multiple components --- include/shady/be/dump.h | 5 + include/shady/body_builder.h | 66 +++++++ include/shady/ir.h | 279 +++-------------------------- include/shady/ir/annotation.h | 15 ++ include/shady/ir/arena.h | 14 ++ include/shady/ir/base.h | 54 ++++++ include/shady/ir/execution_model.h | 18 ++ include/shady/ir/float.h | 26 +++ include/shady/ir/grammar.h | 25 +++ include/shady/ir/int.h | 49 +++++ include/shady/ir/mem.h | 9 + include/shady/ir/module.h | 17 ++ include/shady/ir/primop.h | 12 ++ src/shady/analysis/cfg.h | 2 + src/shady/node.c | 2 +- 15 files changed, 342 insertions(+), 251 deletions(-) create mode 100644 include/shady/body_builder.h create mode 100644 include/shady/ir/annotation.h create mode 100644 include/shady/ir/arena.h create mode 100644 include/shady/ir/base.h create mode 100644 include/shady/ir/execution_model.h create mode 100644 include/shady/ir/float.h create mode 100644 include/shady/ir/grammar.h create mode 100644 include/shady/ir/int.h create mode 100644 include/shady/ir/mem.h create mode 100644 include/shady/ir/module.h create mode 100644 include/shady/ir/primop.h diff --git a/include/shady/be/dump.h b/include/shady/be/dump.h index 56b319293..197046235 100644 --- a/include/shady/be/dump.h +++ b/include/shady/be/dump.h @@ -1,6 +1,11 @@ #ifndef SHD_BE_DUMP_H #define SHD_BE_DUMP_H +#include "shady/ir/base.h" +#include "shady/ir/module.h" + +#include + void shd_dump_module(Module* mod); void shd_dump_node(const Node* node); diff --git a/include/shady/body_builder.h b/include/shady/body_builder.h new file mode 100644 index 000000000..37da64ace --- /dev/null +++ b/include/shady/body_builder.h @@ -0,0 +1,66 @@ +#ifndef SHADY_BODY_BUILDER_H +#define SHADY_BODY_BUILDER_H + +#include "shady/ir/base.h" + +typedef struct BodyBuilder_ BodyBuilder; + +/// Used to build a chain of let +BodyBuilder* begin_body_with_mem(IrArena*, const Node*); +BodyBuilder* begin_block_pure(IrArena*); +BodyBuilder* begin_block_with_side_effects(IrArena*, const Node*); + +/// Appends an instruction to the builder, may apply optimisations. +/// If the arena is typed, returns a list of variables bound to the values yielded by that instruction +Nodes bind_instruction(BodyBuilder*, const Node* instruction); +const Node* bind_instruction_single(BodyBuilder*, const Node* instruction); +Nodes bind_instruction_named(BodyBuilder*, const Node* instruction, String const output_names[]); + +Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count); + +Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, Node*); +Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, Node*); +Nodes gen_loop(BodyBuilder*, Nodes, Nodes, Node*); + +typedef struct { + Nodes results; + Node* case_; + const Node* jp; +} begin_control_t; +begin_control_t begin_control(BodyBuilder*, Nodes); + +typedef struct { + Nodes results; + Node* loop_body; + Nodes params; + const Node* continue_jp; + const Node* break_jp; +} begin_loop_helper_t; +begin_loop_helper_t begin_loop_helper(BodyBuilder*, Nodes, Nodes, Nodes); + +Nodes gen_control(BodyBuilder*, Nodes, Node*); + +const Node* bb_mem(BodyBuilder*); + +/// Like append bind_instruction, but you explicitly give it information about any yielded values +/// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! +Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count); + +const Node* finish_body(BodyBuilder*, const Node* terminator); +const Node* finish_body_with_return(BodyBuilder*, Nodes args); +const Node* finish_body_with_unreachable(BodyBuilder*); +const Node* finish_body_with_selection_merge(BodyBuilder*, Nodes args); +const Node* finish_body_with_loop_continue(BodyBuilder*, Nodes args); +const Node* finish_body_with_loop_break(BodyBuilder*, Nodes args); +const Node* finish_body_with_join(BodyBuilder*, const Node* jp, Nodes args); +const Node* finish_body_with_jump(BodyBuilder*, const Node* target, Nodes args); + +void cancel_body(BodyBuilder*); + +const Node* yield_value_and_wrap_in_block(BodyBuilder*, const Node*); +const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); +const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); + +const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder*, Nodes); + +#endif diff --git a/include/shady/ir.h b/include/shady/ir.h index a75f6d46e..8789e2d00 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -1,143 +1,19 @@ #ifndef SHADY_IR_H #define SHADY_IR_H -#include -#include -#include -#include - -typedef struct IrArena_ IrArena; -typedef struct Node_ Node; -typedef struct Node_ Type; -typedef uint32_t NodeId; -typedef const char* String; - -//////////////////////////////// Lists & Strings //////////////////////////////// - -typedef struct Nodes_ { - size_t count; - const Node** nodes; -} Nodes; - -typedef struct Strings_ { - size_t count; - String* strings; -} Strings; - -Nodes shd_nodes(IrArena*, size_t count, const Node*[]); -Strings shd_strings(IrArena* arena, size_t count, const char** in_strs); - -Nodes shd_empty(IrArena* a); -Nodes shd_singleton(const Node* n); - -#define mk_nodes(arena, ...) shd_nodes(arena, sizeof((const Node*[]) { __VA_ARGS__ }) / sizeof(const Node*), (const Node*[]) { __VA_ARGS__ }) - -const Node* shd_first(Nodes nodes); - -Nodes shd_nodes_append(IrArena*, Nodes, const Node*); -Nodes shd_nodes_prepend(IrArena*, Nodes, const Node*); -Nodes shd_concat_nodes(IrArena* arena, Nodes a, Nodes b); -Nodes shd_change_node_at_index(IrArena* arena, Nodes old, size_t i, const Node* n); -bool shd_find_in_nodes(Nodes nodes, const Node* n); - -String string_sized(IrArena*, size_t size, const char* start); -String string(IrArena*, const char*); -// see also: format_string in util.h -String shd_fmt_string_irarena(IrArena* arena, const char* str, ...); -String unique_name(IrArena*, const char* base_name); -String name_type_safe(IrArena*, const Type*); - -//////////////////////////////// Modules //////////////////////////////// - -typedef struct Module_ Module; - -Module* new_module(IrArena*, String name); - -IrArena* get_module_arena(const Module*); -String get_module_name(const Module*); -Nodes get_module_declarations(const Module*); -Node* get_declaration(const Module*, String); - -void link_module(Module* dst, Module* src); +#include "shady/ir/base.h" +#include "shady/ir/module.h" //////////////////////////////// Grammar //////////////////////////////// // The bulk of the language grammar is defined through json files. // We define some support enums here. -typedef enum { - IntTy8, - IntTy16, - IntTy32, - IntTy64, -} IntSizes; - -enum { - IntSizeMin = IntTy8, - IntSizeMax = IntTy64, -}; - -static inline int int_size_in_bytes(IntSizes s) { - switch (s) { - case IntTy8: return 1; - case IntTy16: return 2; - case IntTy32: return 4; - case IntTy64: return 8; - } -} - -typedef enum { - FloatTy16, - FloatTy32, - FloatTy64 -} FloatSizes; - -static inline int float_size_in_bytes(FloatSizes s) { - switch (s) { - case FloatTy16: return 2; - case FloatTy32: return 4; - case FloatTy64: return 8; - } -} - -#define EXECUTION_MODELS(EM) \ -EM(Compute, 1) \ -EM(Fragment, 0) \ -EM(Vertex, 0) \ - -typedef enum { - EmNone, -#define EM(name, _) Em##name, -EXECUTION_MODELS(EM) -#undef EM -} ExecutionModel; - -ExecutionModel shd_execution_model_from_string(const char*); - -typedef enum { - NotSpecial, - /// for instructions with multiple yield values. Must be deconstructed by a let, cannot appear anywhere else - MultipleReturn, - /// Gets the 'Block' SPIR-V annotation, needed for UBO/SSBO variables - DecorateBlock -} RecordSpecialFlag; - -#ifdef __GNUC__ -#define SHADY_DESIGNATED_INIT __attribute__((designated_init)) -#else -#define SHADY_DESIGNATED_INIT -#endif - -// see primops.json -#include "primops_generated.h" - -String get_primop_name(Op op); -bool has_primop_got_side_effects(Op op); - -typedef struct BodyBuilder_ BodyBuilder; - -// see grammar.json -#include "grammar_generated.h" +#include "shady/ir/int.h" +#include "shady/ir/float.h" +#include "shady/ir/execution_model.h" +#include "shady/ir/primop.h" +#include "shady/ir/grammar.h" extern const char* node_tags[]; extern const bool node_type_has_payload[]; @@ -150,13 +26,7 @@ inline static bool is_function(const Node* node) { return node->tag == Function_ //////////////////////////////// IR Arena //////////////////////////////// -/// See config.h for definition of ArenaConfig -typedef struct ArenaConfig_ ArenaConfig; - -IrArena* shd_new_ir_arena(const ArenaConfig* config); -void shd_destroy_ir_arena(IrArena* arena); -const ArenaConfig* shd_get_arena_config(const IrArena* a); -const Node* shd_get_node_by_id(const IrArena* a, NodeId id); +#include "shady/ir/arena.h" //////////////////////////////// Getters //////////////////////////////// @@ -165,47 +35,35 @@ String get_value_name_safe(const Node*); String get_value_name_unsafe(const Node*); void set_value_name(const Node* var, String name); -const IntLiteral* resolve_to_int_literal(const Node* node); -int64_t get_int_literal_value(IntLiteral, bool sign_extend); -const FloatLiteral* resolve_to_float_literal(const Node* node); -double get_float_literal_value(FloatLiteral); -const char* get_string_literal(IrArena*, const Node*); - String get_address_space_name(AddressSpace); /// Returns false iff pointers in that address space can contain different data at the same address /// (amongst threads in the same subgroup) bool is_addr_space_uniform(IrArena*, AddressSpace); -const Node* shd_lookup_annotation(const Node* decl, const char* name); -const Node* shd_lookup_annotation_list(Nodes annotations, const char* name); -const Node* shd_get_annotation_value(const Node* annotation); -Nodes shd_get_annotation_values(const Node* annotation); -/// Gets the string literal attached to an annotation, if present. -const char* shd_get_annotation_string_payload(const Node* annotation); -bool shd_lookup_annotation_with_string_payload(const Node* decl, const char* annotation_name, const char* expected_payload); -Nodes shd_filter_out_annotation(IrArena* arena, Nodes annotations, const char* name); - -const Node* get_abstraction_mem(const Node* abs); -String get_abstraction_name (const Node* abs); -String get_abstraction_name_unsafe(const Node* abs); -String get_abstraction_name_safe(const Node* abs); - -void set_abstraction_body (Node* abs, const Node* body); +#include "shady/ir/annotation.h" const Node* maybe_tuple_helper(IrArena* a, Nodes values); const Node* extract_helper(const Node* composite, const Node* index); const Node* maybe_tuple_helper(IrArena* a, Nodes values); -const Node* get_parent_mem(const Node* mem); -const Node* get_original_mem(const Node* mem); +const Node* tuple_helper(IrArena*, Nodes contents); +const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); + +#include "shady/ir/mem.h" + +const IntLiteral* resolve_to_int_literal(const Node* node); +int64_t get_int_literal_value(IntLiteral, bool sign_extend); +const FloatLiteral* resolve_to_float_literal(const Node* node); +double get_float_literal_value(FloatLiteral); +const char* get_string_literal(IrArena*, const Node*); typedef struct { bool enter_loads; bool allow_incompatible_types; bool assume_globals_immutability; } NodeResolveConfig; -NodeResolveConfig default_node_resolve_config(); +NodeResolveConfig default_node_resolve_config(void); const Node* chase_ptr_to_source(const Node*, NodeResolveConfig config); const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config); @@ -222,45 +80,22 @@ const Node* unit_type(IrArena*); /// For typing instructions that return nothing (equivalent to C's void f()) const Node* empty_multiple_return_type(IrArena*); -const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w); - -const Type* shd_int8_type(IrArena* arena); -const Type* shd_int16_type(IrArena* arena); -const Type* shd_int32_type(IrArena* arena); -const Type* shd_int64_type(IrArena* arena); - -const Type* shd_uint8_type(IrArena* arena); -const Type* shd_uint16_type(IrArena* arena); -const Type* shd_uint32_type(IrArena* arena); -const Type* shd_uint64_type(IrArena* arena); - -const Type* shd_int8_literal(IrArena* arena, int8_t i); -const Type* shd_int16_literal(IrArena* arena, int16_t i); -const Type* shd_int32_literal(IrArena* arena, int32_t i); -const Type* shd_int64_literal(IrArena* arena, int64_t i); - -const Type* shd_uint8_literal(IrArena* arena, uint8_t i); -const Type* shd_uint16_literal(IrArena* arena, uint16_t i); -const Type* shd_uint32_literal(IrArena* arena, uint32_t i); -const Type* shd_uint64_literal(IrArena* arena, uint64_t i); - -const Type* shd_fp16_type(IrArena* arena); -const Type* shd_fp32_type(IrArena* arena); -const Type* shd_fp64_type(IrArena* arena); - -const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value); +Type* nominal_type(Module*, Nodes annotations, String name); // values Node* param(IrArena*, const Type* type, const char* name); -const Node* tuple_helper(IrArena*, Nodes contents); -const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); - // decl ctors Node* function (Module*, Nodes params, const char* name, Nodes annotations, Nodes return_types); Node* constant (Module*, Nodes annotations, const Type*, const char* name); Node* global_var (Module*, Nodes annotations, const Type*, String, AddressSpace); -Type* nominal_type(Module*, Nodes annotations, String name); + +const Node* get_abstraction_mem(const Node* abs); +String get_abstraction_name (const Node* abs); +String get_abstraction_name_unsafe(const Node* abs); +String get_abstraction_name_safe(const Node* abs); + +void set_abstraction_body (Node* abs, const Node* body); // basic blocks Node* basic_block(IrArena*, Nodes params, const char* name); @@ -268,62 +103,6 @@ static inline Node* case_(IrArena* a, Nodes params) { return basic_block(a, params, NULL); } -/// Used to build a chain of let -BodyBuilder* begin_body_with_mem(IrArena*, const Node*); -BodyBuilder* begin_block_pure(IrArena*); -BodyBuilder* begin_block_with_side_effects(IrArena*, const Node*); - -/// Appends an instruction to the builder, may apply optimisations. -/// If the arena is typed, returns a list of variables bound to the values yielded by that instruction -Nodes bind_instruction(BodyBuilder*, const Node* instruction); -const Node* bind_instruction_single(BodyBuilder*, const Node* instruction); -Nodes bind_instruction_named(BodyBuilder*, const Node* instruction, String const output_names[]); - -Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count); - -Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, Node*); -Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, Node*); -Nodes gen_loop(BodyBuilder*, Nodes, Nodes, Node*); - -typedef struct { - Nodes results; - Node* case_; - const Node* jp; -} begin_control_t; -begin_control_t begin_control(BodyBuilder*, Nodes); - -typedef struct { - Nodes results; - Node* loop_body; - Nodes params; - const Node* continue_jp; - const Node* break_jp; -} begin_loop_helper_t; -begin_loop_helper_t begin_loop_helper(BodyBuilder*, Nodes, Nodes, Nodes); - -Nodes gen_control(BodyBuilder*, Nodes, Node*); - -const Node* bb_mem(BodyBuilder*); - -/// Like append bind_instruction, but you explicitly give it information about any yielded values -/// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! -Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count); - -const Node* finish_body(BodyBuilder*, const Node* terminator); -const Node* finish_body_with_return(BodyBuilder*, Nodes args); -const Node* finish_body_with_unreachable(BodyBuilder*); -const Node* finish_body_with_selection_merge(BodyBuilder*, Nodes args); -const Node* finish_body_with_loop_continue(BodyBuilder*, Nodes args); -const Node* finish_body_with_loop_break(BodyBuilder*, Nodes args); -const Node* finish_body_with_join(BodyBuilder*, const Node* jp, Nodes args); -const Node* finish_body_with_jump(BodyBuilder*, const Node* target, Nodes args); - -void cancel_body(BodyBuilder*); - -const Node* yield_value_and_wrap_in_block(BodyBuilder*, const Node*); -const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); -const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); - -const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder*, Nodes); +#include "shady/body_builder.h" #endif diff --git a/include/shady/ir/annotation.h b/include/shady/ir/annotation.h new file mode 100644 index 000000000..3c481fd9c --- /dev/null +++ b/include/shady/ir/annotation.h @@ -0,0 +1,15 @@ +#ifndef SHADY_IR_ANNOTATION_H +#define SHADY_IR_ANNOTATION_H + +#include "shady/ir/base.h" + +const Node* shd_lookup_annotation(const Node* decl, const char* name); +const Node* shd_lookup_annotation_list(Nodes annotations, const char* name); +const Node* shd_get_annotation_value(const Node* annotation); +Nodes shd_get_annotation_values(const Node* annotation); +/// Gets the string literal attached to an annotation, if present. +const char* shd_get_annotation_string_payload(const Node* annotation); +bool shd_lookup_annotation_with_string_payload(const Node* decl, const char* annotation_name, const char* expected_payload); +Nodes shd_filter_out_annotation(IrArena* arena, Nodes annotations, const char* name); + +#endif diff --git a/include/shady/ir/arena.h b/include/shady/ir/arena.h new file mode 100644 index 000000000..a992873bd --- /dev/null +++ b/include/shady/ir/arena.h @@ -0,0 +1,14 @@ +#ifndef SHADY_IR_ARENA_H +#define SHADY_IR_ARENA_H + +#include "shady/ir/base.h" + +/// See config.h for definition of ArenaConfig +typedef struct ArenaConfig_ ArenaConfig; + +IrArena* shd_new_ir_arena(const ArenaConfig* config); +void shd_destroy_ir_arena(IrArena* arena); +const ArenaConfig* shd_get_arena_config(const IrArena* a); +const Node* shd_get_node_by_id(const IrArena* a, NodeId id); + +#endif diff --git a/include/shady/ir/base.h b/include/shady/ir/base.h new file mode 100644 index 000000000..e2103ea3b --- /dev/null +++ b/include/shady/ir/base.h @@ -0,0 +1,54 @@ +#ifndef SHADY_IR_BASE_H +#define SHADY_IR_BASE_H + +#include +#include +#include + +#ifdef __GNUC__ +#define SHADY_DESIGNATED_INIT __attribute__((designated_init)) +#else +#define SHADY_DESIGNATED_INIT +#endif + +typedef struct IrArena_ IrArena; +typedef struct Node_ Node; +typedef struct Node_ Type; +typedef uint32_t NodeId; +typedef const char* String; + +typedef struct Nodes_ { + size_t count; + const Node** nodes; +} Nodes; + +typedef struct Strings_ { + size_t count; + String* strings; +} Strings; + +Nodes shd_nodes(IrArena*, size_t count, const Node*[]); +Strings shd_strings(IrArena* arena, size_t count, const char** in_strs); + +Nodes shd_empty(IrArena* a); +Nodes shd_singleton(const Node* n); + +#define mk_nodes(arena, ...) shd_nodes(arena, sizeof((const Node*[]) { __VA_ARGS__ }) / sizeof(const Node*), (const Node*[]) { __VA_ARGS__ }) + +const Node* shd_first(Nodes nodes); + +Nodes shd_nodes_append(IrArena*, Nodes, const Node*); +Nodes shd_nodes_prepend(IrArena*, Nodes, const Node*); +Nodes shd_concat_nodes(IrArena* arena, Nodes a, Nodes b); +Nodes shd_change_node_at_index(IrArena* arena, Nodes old, size_t i, const Node* n); +bool shd_find_in_nodes(Nodes nodes, const Node* n); + +String string_sized(IrArena*, size_t size, const char* start); +String string(IrArena*, const char*); + +// see also: format_string in util.h +String shd_fmt_string_irarena(IrArena* arena, const char* str, ...); +String unique_name(IrArena*, const char* base_name); +String name_type_safe(IrArena*, const Type*); + +#endif diff --git a/include/shady/ir/execution_model.h b/include/shady/ir/execution_model.h new file mode 100644 index 000000000..3586d730c --- /dev/null +++ b/include/shady/ir/execution_model.h @@ -0,0 +1,18 @@ +#ifndef SHADY_IR_EXECUTION_MODEL_H +#define SHADY_IR_EXECUTION_MODEL_H + +#define EXECUTION_MODELS(EM) \ +EM(Compute, 1) \ +EM(Fragment, 0) \ +EM(Vertex, 0) \ + +typedef enum { + EmNone, +#define EM(name, _) Em##name, + EXECUTION_MODELS(EM) +#undef EM +} ExecutionModel; + +ExecutionModel shd_execution_model_from_string(const char*); + +#endif diff --git a/include/shady/ir/float.h b/include/shady/ir/float.h new file mode 100644 index 000000000..df406cabc --- /dev/null +++ b/include/shady/ir/float.h @@ -0,0 +1,26 @@ +#ifndef SHADY_IR_FLOAT_H +#define SHADY_IR_FLOAT_H + +#include "shady/ir/base.h" + +typedef enum { + FloatTy16, + FloatTy32, + FloatTy64 +} FloatSizes; + +static inline int float_size_in_bytes(FloatSizes s) { + switch (s) { + case FloatTy16: return 2; + case FloatTy32: return 4; + case FloatTy64: return 8; + } +} + +const Type* shd_fp16_type(IrArena* arena); +const Type* shd_fp32_type(IrArena* arena); +const Type* shd_fp64_type(IrArena* arena); + +const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value); + +#endif diff --git a/include/shady/ir/grammar.h b/include/shady/ir/grammar.h new file mode 100644 index 000000000..03667f6f2 --- /dev/null +++ b/include/shady/ir/grammar.h @@ -0,0 +1,25 @@ +#ifndef SHADY_IR_GRAMMAR_H +#define SHADY_IR_GRAMMAR_H + +#include "shady/ir/base.h" + +// These structs are referenced in the actual grammar + +typedef enum { + NotSpecial, + /// for instructions with multiple yield values. Must be deconstructed by a let, cannot appear anywhere else + MultipleReturn, + /// Gets the 'Block' SPIR-V annotation, needed for UBO/SSBO variables + DecorateBlock +} RecordSpecialFlag; + +#include "shady/ir/int.h" +#include "shady/ir/float.h" +#include "shady/ir/primop.h" + +typedef struct BodyBuilder_ BodyBuilder; + +// see grammar.json +#include "grammar_generated.h" + +#endif diff --git a/include/shady/ir/int.h b/include/shady/ir/int.h new file mode 100644 index 000000000..d7a3b5672 --- /dev/null +++ b/include/shady/ir/int.h @@ -0,0 +1,49 @@ +#ifndef SHADY_IR_INT_H +#define SHADY_IR_INT_H + +#include "shady/ir/base.h" + +typedef enum { + IntTy8, + IntTy16, + IntTy32, + IntTy64, +} IntSizes; + +enum { + IntSizeMin = IntTy8, + IntSizeMax = IntTy64, +}; + +static inline int int_size_in_bytes(IntSizes s) { + switch (s) { + case IntTy8: return 1; + case IntTy16: return 2; + case IntTy32: return 4; + case IntTy64: return 8; + } +} + +const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w); + +const Type* shd_int8_type(IrArena* arena); +const Type* shd_int16_type(IrArena* arena); +const Type* shd_int32_type(IrArena* arena); +const Type* shd_int64_type(IrArena* arena); + +const Type* shd_uint8_type(IrArena* arena); +const Type* shd_uint16_type(IrArena* arena); +const Type* shd_uint32_type(IrArena* arena); +const Type* shd_uint64_type(IrArena* arena); + +const Node* shd_int8_literal(IrArena* arena, int8_t i); +const Node* shd_int16_literal(IrArena* arena, int16_t i); +const Node* shd_int32_literal(IrArena* arena, int32_t i); +const Node* shd_int64_literal(IrArena* arena, int64_t i); + +const Node* shd_uint8_literal(IrArena* arena, uint8_t u); +const Node* shd_uint16_literal(IrArena* arena, uint16_t u); +const Node* shd_uint32_literal(IrArena* arena, uint32_t u); +const Node* shd_uint64_literal(IrArena* arena, uint64_t u); + +#endif diff --git a/include/shady/ir/mem.h b/include/shady/ir/mem.h new file mode 100644 index 000000000..47d7bd276 --- /dev/null +++ b/include/shady/ir/mem.h @@ -0,0 +1,9 @@ +#ifndef SHADY_IR_MEM_H +#define SHADY_IR_MEM_H + +#include "shady/ir/base.h" + +const Node* get_parent_mem(const Node* mem); +const Node* get_original_mem(const Node* mem); + +#endif diff --git a/include/shady/ir/module.h b/include/shady/ir/module.h new file mode 100644 index 000000000..1e1741107 --- /dev/null +++ b/include/shady/ir/module.h @@ -0,0 +1,17 @@ +#ifndef SHADY_IR_MODULE_H +#define SHADY_IR_MODULE_H + +#include "shady/ir/base.h" + +typedef struct Module_ Module; + +Module* new_module(IrArena*, String name); + +IrArena* get_module_arena(const Module*); +String get_module_name(const Module*); +Nodes get_module_declarations(const Module*); +Node* get_declaration(const Module*, String); + +void link_module(Module* dst, Module* src); + +#endif diff --git a/include/shady/ir/primop.h b/include/shady/ir/primop.h new file mode 100644 index 000000000..08735adad --- /dev/null +++ b/include/shady/ir/primop.h @@ -0,0 +1,12 @@ +#ifndef SHADY_IR_PRIMOP_H +#define SHADY_IR_PRIMOP_H + +#include "shady/ir/base.h" + +// see primops.json +#include "primops_generated.h" + +String get_primop_name(Op op); +bool has_primop_got_side_effects(Op op); + +#endif diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index 897472e52..df6e88768 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -3,6 +3,8 @@ #include "shady/ir.h" +#include + typedef struct CFNode_ CFNode; typedef enum { diff --git a/src/shady/node.c b/src/shady/node.c index 2cbacbcde..8d8ca2ddf 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -145,7 +145,7 @@ const Node* resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config) { return NULL; } -NodeResolveConfig default_node_resolve_config() { +NodeResolveConfig default_node_resolve_config(void) { return (NodeResolveConfig) { .enter_loads = true, .allow_incompatible_types = false, From 6fcb7f89406b63434bdc9806d2ac3bf17372000d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 14:41:27 +0200 Subject: [PATCH 625/693] move memory_layout.h to shady/ir/ --- include/shady/{ => ir}/memory_layout.h | 2 +- src/backend/spirv/emit_spv_type.c | 2 +- src/backend/spirv/emit_spv_value.c | 2 +- src/backend/spirv/spirv_lift_globals_ssbo.c | 2 +- src/backend/spirv/spirv_map_entrypoint_args.c | 2 +- src/runtime/vulkan/vk_runtime_program.c | 2 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 2 +- src/shady/passes/lower_memcpy.c | 2 +- src/shady/passes/lower_memory_layout.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/transform/memory_layout.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) rename include/shady/{ => ir}/memory_layout.h (97%) diff --git a/include/shady/memory_layout.h b/include/shady/ir/memory_layout.h similarity index 97% rename from include/shady/memory_layout.h rename to include/shady/ir/memory_layout.h index 3ce4014ef..b6cd96d42 100644 --- a/include/shady/memory_layout.h +++ b/include/shady/ir/memory_layout.h @@ -1,7 +1,7 @@ #ifndef SHADY_MEMORY_LAYOUT_H #define SHADY_MEMORY_LAYOUT_H -#include "shady/ir.h" +#include "shady/ir/base.h" #include "shady/config.h" typedef struct { diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 981d00772..d03481d6f 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -1,6 +1,6 @@ #include "emit_spv.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../shady/type.h" #include "shady/rewrite.h" diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index da77b551f..a9db82f22 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -1,6 +1,6 @@ #include "emit_spv.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index a7d1785fb..6c0628c0f 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -1,5 +1,5 @@ #include "shady/pass.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index e6ac76aab..3358c3140 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -1,5 +1,5 @@ #include "shady/pass.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 555cfb15d..f4c196c2e 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -1,7 +1,7 @@ #include "vk_runtime_private.h" #include "shady/driver.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "type.h" diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 99d8f5049..ff8e8c78d 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -1,5 +1,5 @@ #include "shady/pass.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 280415739..52bd3ef99 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -1,5 +1,5 @@ #include "shady/pass.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../type.h" #include "../ir_private.h" diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index f568a5f7f..5f8e21251 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -1,5 +1,5 @@ #include "shady/pass.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../transform/ir_gen_helpers.h" #include "../type.h" diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 2a41dfadc..e5f210bc4 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -1,5 +1,5 @@ #include "shady/pass.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../type.h" diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 517308f28..ba2c0cdaf 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -1,5 +1,5 @@ #include "shady/pass.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../ir_private.h" #include "../type.h" diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 827900c72..c640cdc91 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -1,5 +1,5 @@ #include "shady/pass.h" -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "../type.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 6c0bf432d..6454cfb20 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -1,4 +1,4 @@ -#include "shady/memory_layout.h" +#include "shady/ir/memory_layout.h" #include "ir_gen_helpers.h" #include "log.h" From a2f3903af0f03b44ad2b3d1f4cb487c0d03e66f5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 14:46:36 +0200 Subject: [PATCH 626/693] move memory_layout.h to shady/ir/ --- include/shady/config.h | 6 +++++- include/shady/ir/arena.h | 5 +---- include/shady/ir/base.h | 1 + include/shady/ir/memory_layout.h | 1 + include/shady/ir/module.h | 2 -- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/shady/config.h b/include/shady/config.h index 15c73f5ed..eabf5169a 100644 --- a/include/shady/config.h +++ b/include/shady/config.h @@ -1,7 +1,10 @@ #ifndef SHD_CONFIG_H #define SHD_CONFIG_H -#include "shady/ir.h" +#include "shady/ir/base.h" +#include "shady/ir/int.h" +#include "shady/ir/grammar.h" +#include "shady/ir/execution_model.h" typedef struct { IntSizes ptr_size; @@ -55,6 +58,7 @@ struct ArenaConfig_ { }; ArenaConfig shd_default_arena_config(const TargetConfig* target); +const ArenaConfig* shd_get_arena_config(const IrArena* a); typedef struct CompilerConfig_ CompilerConfig; struct CompilerConfig_ { diff --git a/include/shady/ir/arena.h b/include/shady/ir/arena.h index a992873bd..e700e6cf2 100644 --- a/include/shady/ir/arena.h +++ b/include/shady/ir/arena.h @@ -2,13 +2,10 @@ #define SHADY_IR_ARENA_H #include "shady/ir/base.h" - -/// See config.h for definition of ArenaConfig -typedef struct ArenaConfig_ ArenaConfig; +#include "shady/config.h" IrArena* shd_new_ir_arena(const ArenaConfig* config); void shd_destroy_ir_arena(IrArena* arena); -const ArenaConfig* shd_get_arena_config(const IrArena* a); const Node* shd_get_node_by_id(const IrArena* a, NodeId id); #endif diff --git a/include/shady/ir/base.h b/include/shady/ir/base.h index e2103ea3b..156604327 100644 --- a/include/shady/ir/base.h +++ b/include/shady/ir/base.h @@ -12,6 +12,7 @@ #endif typedef struct IrArena_ IrArena; +typedef struct Module_ Module; typedef struct Node_ Node; typedef struct Node_ Type; typedef uint32_t NodeId; diff --git a/include/shady/ir/memory_layout.h b/include/shady/ir/memory_layout.h index b6cd96d42..ba45a6d4c 100644 --- a/include/shady/ir/memory_layout.h +++ b/include/shady/ir/memory_layout.h @@ -2,6 +2,7 @@ #define SHADY_MEMORY_LAYOUT_H #include "shady/ir/base.h" +#include "shady/ir/grammar.h" #include "shady/config.h" typedef struct { diff --git a/include/shady/ir/module.h b/include/shady/ir/module.h index 1e1741107..50dc5b4c9 100644 --- a/include/shady/ir/module.h +++ b/include/shady/ir/module.h @@ -3,8 +3,6 @@ #include "shady/ir/base.h" -typedef struct Module_ Module; - Module* new_module(IrArena*, String name); IrArena* get_module_arena(const Module*); From 738cb387933af2097bde6e92e8916e92ab40a123 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 14:56:11 +0200 Subject: [PATCH 627/693] remove a bunch of dependencies on old ir.h --- include/shady/be/c.h | 2 +- include/shady/be/spirv.h | 2 +- include/shady/driver.h | 2 +- include/shady/fe/slim.h | 1 + include/shady/pass.h | 2 ++ include/shady/print.h | 4 ++-- include/shady/rewrite.h | 2 +- include/shady/visit.h | 2 +- samples/checkerboard/checkerboard.c | 1 + src/shady/passes/eliminate_constants.c | 1 + vcc/vcc.c | 7 +++---- 11 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/shady/be/c.h b/include/shady/be/c.h index 2281675a2..db18d4c7d 100644 --- a/include/shady/be/c.h +++ b/include/shady/be/c.h @@ -1,7 +1,7 @@ #ifndef SHD_BE_C_H #define SHD_BE_C_H -#include "shady/ir.h" +#include "shady/ir/base.h" typedef enum { CDialect_C11, diff --git a/include/shady/be/spirv.h b/include/shady/be/spirv.h index 46795dc73..7f70e1dad 100644 --- a/include/shady/be/spirv.h +++ b/include/shady/be/spirv.h @@ -1,7 +1,7 @@ #ifndef SHD_BE_SPIRV_H #define SHD_BE_SPIRV_H -#include "shady/ir.h" +#include "shady/ir/base.h" typedef struct CompilerConfig_ CompilerConfig; void emit_spirv(const CompilerConfig* config, Module*, size_t* output_size, char** output, Module** new_mod); diff --git a/include/shady/driver.h b/include/shady/driver.h index bf0ce3a77..b485cd52f 100644 --- a/include/shady/driver.h +++ b/include/shady/driver.h @@ -1,7 +1,7 @@ #ifndef SHADY_CLI #define SHADY_CLI -#include "shady/ir.h" +#include "shady/ir/base.h" #include "shady/config.h" #include "shady/be/c.h" diff --git a/include/shady/fe/slim.h b/include/shady/fe/slim.h index 7beec0b4c..34502654e 100644 --- a/include/shady/fe/slim.h +++ b/include/shady/fe/slim.h @@ -1,6 +1,7 @@ #ifndef SHADY_SLIM_H #define SHADY_SLIM_H +#include "shady/ir/module.h" #include "shady/config.h" typedef enum { diff --git a/include/shady/pass.h b/include/shady/pass.h index 6ede5f46d..1db0a2515 100644 --- a/include/shady/pass.h +++ b/include/shady/pass.h @@ -1,6 +1,8 @@ #ifndef SHADY_PASS_H #define SHADY_PASS_H +#include "shady/ir/arena.h" +#include "shady/ir/module.h" #include "shady/config.h" #include "shady/rewrite.h" diff --git a/include/shady/print.h b/include/shady/print.h index 646c102fa..76fbd3f74 100644 --- a/include/shady/print.h +++ b/include/shady/print.h @@ -1,10 +1,10 @@ #ifndef SHADY_PRINT #define SHADY_PRINT -#include "shady/ir.h" +#include "shady/ir/base.h" #include "shady/be/dump.h" + #include "printer.h" -#include typedef struct { bool print_builtin; diff --git a/include/shady/rewrite.h b/include/shady/rewrite.h index 34067a7a4..fbe41a43d 100644 --- a/include/shady/rewrite.h +++ b/include/shady/rewrite.h @@ -1,7 +1,7 @@ #ifndef SHADY_REWRITE_H #define SHADY_REWRITE_H -#include "shady/ir.h" +#include "shady/ir/grammar.h" typedef struct Rewriter_ Rewriter; diff --git a/include/shady/visit.h b/include/shady/visit.h index 04ed20103..c8e9d1b03 100644 --- a/include/shady/visit.h +++ b/include/shady/visit.h @@ -1,7 +1,7 @@ #ifndef SHADY_VISIT_H #define SHADY_VISIT_H -#include "shady/ir.h" +#include "shady/ir/grammar.h" typedef struct Visitor_ Visitor; typedef void (*VisitNodeFn)(Visitor*, const Node*); diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 53e46e61a..214eb6e01 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -2,6 +2,7 @@ #include #include +#include "shady/ir/arena.h" #include "shady/runtime.h" #include "shady/driver.h" diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index ec512ec76..baaeb4f7d 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/annotation.h" #include "portability.h" #include "log.h" diff --git a/vcc/vcc.c b/vcc/vcc.c index 67d7701f8..e64d40a3e 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -1,14 +1,13 @@ #include "vcc/driver.h" +#include "shady/ir/arena.h" +#include "shady/ir/module.h" + #include "log.h" #include "list.h" #include "util.h" -#include "growy.h" #include "portability.h" -#include -#include - int main(int argc, char** argv) { shd_platform_specific_terminal_init_extras(); From 19cebc19c69b88d812b8eb3e82c0d93fc474fdd0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 15:01:15 +0200 Subject: [PATCH 628/693] moved builtins.h to shady/ir/ --- include/shady/{builtins.h => ir/builtin.h} | 8 +++++--- src/backend/c/emit_c.h | 2 +- src/backend/spirv/emit_spv.c | 2 +- src/frontend/spirv/s2s.c | 2 +- src/shady/builtins.c | 4 +++- src/shady/transform/ir_gen_helpers.h | 2 +- src/shady/type.c | 2 +- 7 files changed, 13 insertions(+), 9 deletions(-) rename include/shady/{builtins.h => ir/builtin.h} (95%) diff --git a/include/shady/builtins.h b/include/shady/ir/builtin.h similarity index 95% rename from include/shady/builtins.h rename to include/shady/ir/builtin.h index 78e64d09e..470ad2459 100644 --- a/include/shady/builtins.h +++ b/include/shady/ir/builtin.h @@ -1,7 +1,9 @@ -#ifndef SHADY_EMIT_BUILTINS -#define SHADY_EMIT_BUILTINS +#ifndef SHADY_IR_BUILTIN_H +#define SHADY_IR_BUILTIN_H -#include "shady/ir.h" +#include "shady/ir/grammar.h" +#include "shady/ir/int.h" +#include "shady/ir/float.h" #define shd_u32vec3_type(arena) pack_type(arena, (PackType) { .width = 3, .element_type = shd_uint32_type(arena) }) #define shd_i32vec3_type(arena) pack_type(arena, (PackType) { .width = 3, .element_type = shd_int32_type(arena) }) diff --git a/src/backend/c/emit_c.h b/src/backend/c/emit_c.h index 0e80798af..e06288ebf 100644 --- a/src/backend/c/emit_c.h +++ b/src/backend/c/emit_c.h @@ -2,7 +2,7 @@ #define SHADY_EMIT_C #include "shady/ir.h" -#include "shady/builtins.h" +#include "shady/ir/builtin.h" #include "shady/be/c.h" #include "growy.h" diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index ce0f9d45a..3e16c20bb 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -1,6 +1,6 @@ #include "emit_spv.h" -#include "shady/builtins.h" +#include "shady/ir/builtin.h" #include "../shady/ir_private.h" #include "../shady/analysis/cfg.h" diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 133a76d08..c65e40eda 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1,5 +1,5 @@ #include "s2s.h" -#include "shady/builtins.h" +#include "shady/ir/builtin.h" // this avoids polluting the namespace #define SpvHasResultAndType ShadySpvHasResultAndType diff --git a/src/shady/builtins.c b/src/shady/builtins.c index d3269c983..34dc75ae5 100644 --- a/src/shady/builtins.c +++ b/src/shady/builtins.c @@ -1,4 +1,6 @@ -#include "shady/builtins.h" +#include "shady/ir/builtin.h" +#include "shady/ir/annotation.h" + #include "spirv/unified1/spirv.h" #include "log.h" diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index c974520a4..824212669 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -2,7 +2,7 @@ #define SHADY_IR_GEN_HELPERS_H #include "shady/ir.h" -#include "shady/builtins.h" +#include "shady/ir/builtin.h" void gen_push_value_stack(BodyBuilder* bb, const Node* value); void gen_push_values_stack(BodyBuilder* bb, Nodes values); diff --git a/src/shady/type.c b/src/shady/type.c index afecc8703..9e698eeae 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -6,7 +6,7 @@ #include "dict.h" #include "util.h" -#include "shady/builtins.h" +#include "shady/ir/builtin.h" #include #include From 2271fefaa4cd640a572a7451832bb1c225ed901d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 15:14:42 +0200 Subject: [PATCH 629/693] move most type helpers to shady/ir/type.h --- include/shady/ir.h | 4 +- include/shady/ir/memory_layout.h | 2 + include/shady/ir/type.h | 69 ++++++++++++++++++++++++++++++++ src/shady/type.h | 61 ---------------------------- 4 files changed, 72 insertions(+), 64 deletions(-) create mode 100644 include/shady/ir/type.h diff --git a/include/shady/ir.h b/include/shady/ir.h index 8789e2d00..b007e3a96 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -51,6 +51,7 @@ const Node* tuple_helper(IrArena*, Nodes contents); const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); #include "shady/ir/mem.h" +#include "shady/ir/type.h" const IntLiteral* resolve_to_int_literal(const Node* node); int64_t get_int_literal_value(IntLiteral, bool sign_extend); @@ -74,9 +75,6 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi /// Empty type: there are no values of this type. /// Useful for the codomain of things that don't return at all const Type* noret_type(IrArena*); -/// Unit type, carries no information (equivalent to C's void) -/// There is exactly one possible value of this type: () -const Node* unit_type(IrArena*); /// For typing instructions that return nothing (equivalent to C's void f()) const Node* empty_multiple_return_type(IrArena*); diff --git a/include/shady/ir/memory_layout.h b/include/shady/ir/memory_layout.h index ba45a6d4c..4cceac96c 100644 --- a/include/shady/ir/memory_layout.h +++ b/include/shady/ir/memory_layout.h @@ -33,4 +33,6 @@ const Node* shd_bytes_to_words(BodyBuilder* bb, const Node* bytes); uint64_t shd_bytes_to_words_static(const IrArena* a, uint64_t bytes); IntSizes shd_float_to_int_width(FloatSizes width); +size_t get_type_bitwidth(const Type* t); + #endif diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h new file mode 100644 index 000000000..a38cfd299 --- /dev/null +++ b/include/shady/ir/type.h @@ -0,0 +1,69 @@ +#ifndef SHADY_IR_TYPE_H +#define SHADY_IR_TYPE_H + +#include "shady/ir/base.h" + +/// Unit type, carries no information (equivalent to C's void) +/// There is exactly one possible value of this type: () +const Node* unit_type(IrArena*); + +/// Is this a type that a value in the language can have ? +bool is_value_type(const Type*); + +/// Is this a valid data type (for usage in other types and as type arguments) ? +bool is_data_type(const Type*); + +/// Returns the (possibly qualified) pointee type from a (possibly qualified) ptr type +const Type* get_pointee_type(IrArena*, const Type*); + +const Type* maybe_multiple_return(IrArena* arena, Nodes types); +Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); + +/// Collects the annotated types in the list of variables +/// NB: this is different from get_values_types, that function uses node.type, whereas this one uses node.payload.var.type +/// This means this function works in untyped modules where node.type is NULL. +Nodes get_param_types(IrArena* arena, Nodes variables); + +Nodes get_values_types(IrArena*, Nodes); + +// Qualified type helpers +/// Ensures an operand has divergence-annotated type and extracts it +const Type* get_unqualified_type(const Type*); +bool is_qualified_type_uniform(const Type*); +bool deconstruct_qualified_type(const Type**); + +const Type* shd_as_qualified_type(const Type* type, bool uniform); + +Nodes strip_qualifiers(IrArena*, Nodes); +Nodes add_qualifiers(IrArena*, Nodes, bool); + +// Pack (vector) type helpers +const Type* get_packed_type_element(const Type*); +size_t get_packed_type_width(const Type*); +size_t deconstruct_packed_type(const Type**); + +/// Helper for creating pack types, wraps type in a pack_type if width > 1 +const Type* maybe_packed_type_helper(const Type*, size_t width); + +/// 'Maybe' variants that work with any types, and assume width=1 for non-packed types +/// Useful for writing generic type checking code ! +const Type* get_maybe_packed_type_element(const Type*); +size_t get_maybe_packed_type_width(const Type*); +size_t deconstruct_maybe_packed_type(const Type**); + +// Pointer type helpers +const Type* get_pointer_type_element(const Type*); +AddressSpace deconstruct_pointer_type(const Type**); + +// Nominal type helpers +const Node* get_nominal_type_decl(const Type*); +const Type* get_nominal_type_body(const Type*); +const Node* get_maybe_nominal_type_decl(const Type*); +const Type* get_maybe_nominal_type_body(const Type*); + +// Composite type helpers +Nodes get_composite_type_element_types(const Type*); +const Node* get_fill_type_element_type(const Type*); +const Node* get_fill_type_size(const Type*); + +#endif diff --git a/src/shady/type.h b/src/shady/type.h index 9cea7d5f7..81b5fc5b4 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -6,14 +6,6 @@ bool is_subtype(const Type* supertype, const Type* type); void check_subtype(const Type* supertype, const Type* type); -/// Is this a type that a value in the language can have ? -bool is_value_type(const Type*); - -/// Is this a valid data type (for usage in other types and as type arguments) ? -bool is_data_type(const Type*); - -size_t get_type_bitwidth(const Type* t); - bool is_arithm_type(const Type*); bool is_shiftable_type(const Type*); bool has_boolean_ops(const Type*); @@ -29,60 +21,7 @@ bool is_conversion_legal(const Type* src_type, const Type* dst_type); const Type* get_actual_mask_type(IrArena* arena); -const Type* maybe_multiple_return(IrArena* arena, Nodes types); -Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); - -/// Returns the (possibly qualified) pointee type from a (possibly qualified) ptr type -const Type* get_pointee_type(IrArena*, const Type*); - void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack); -/// Collects the annotated types in the list of variables -/// NB: this is different from get_values_types, that function uses node.type, whereas this one uses node.payload.var.type -/// This means this function works in untyped modules where node.type is NULL. -Nodes get_param_types(IrArena* arena, Nodes variables); - -Nodes get_values_types(IrArena*, Nodes); - -// Qualified type helpers -/// Ensures an operand has divergence-annotated type and extracts it -const Type* get_unqualified_type(const Type*); -bool is_qualified_type_uniform(const Type*); -bool deconstruct_qualified_type(const Type**); - -const Type* shd_as_qualified_type(const Type* type, bool uniform); - -Nodes strip_qualifiers(IrArena*, Nodes); -Nodes add_qualifiers(IrArena*, Nodes, bool); - -// Pack (vector) type helpers -const Type* get_packed_type_element(const Type*); -size_t get_packed_type_width(const Type*); -size_t deconstruct_packed_type(const Type**); - -/// Helper for creating pack types, wraps type in a pack_type if width > 1 -const Type* maybe_packed_type_helper(const Type*, size_t width); - -/// 'Maybe' variants that work with any types, and assume width=1 for non-packed types -/// Useful for writing generic type checking code ! -const Type* get_maybe_packed_type_element(const Type*); -size_t get_maybe_packed_type_width(const Type*); -size_t deconstruct_maybe_packed_type(const Type**); - -// Pointer type helpers -const Type* get_pointer_type_element(const Type*); -AddressSpace deconstruct_pointer_type(const Type**); - -// Nominal type helpers -const Node* get_nominal_type_decl(const Type*); -const Type* get_nominal_type_body(const Type*); -const Node* get_maybe_nominal_type_decl(const Type*); -const Type* get_maybe_nominal_type_body(const Type*); - -// Composite type helpers -Nodes get_composite_type_element_types(const Type*); -const Node* get_fill_type_element_type(const Type*); -const Node* get_fill_type_size(const Type*); - #endif From 4cb7ef75c7e00dafaa51f55beea066272168206f Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 16:35:59 +0200 Subject: [PATCH 630/693] remove global variables from ir.h --- include/shady/ir.h | 3 --- include/shady/ir/grammar.h | 2 ++ src/backend/c/emit_c_value.c | 2 +- src/backend/spirv/emit_spv_control_flow.c | 2 +- src/backend/spirv/emit_spv_type.c | 2 +- src/backend/spirv/emit_spv_value.c | 2 +- src/frontend/spirv/s2s.c | 2 ++ src/shady/fold.c | 4 +++- src/shady/node.c | 8 ++++++++ src/shady/passes/import.c | 4 ++-- src/shady/transform/ir_gen_helpers.c | 10 ++++++---- src/shady/type.c | 2 +- 12 files changed, 28 insertions(+), 15 deletions(-) diff --git a/include/shady/ir.h b/include/shady/ir.h index b007e3a96..c9381eb24 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -15,9 +15,6 @@ #include "shady/ir/primop.h" #include "shady/ir/grammar.h" -extern const char* node_tags[]; -extern const bool node_type_has_payload[]; - //////////////////////////////// Node categories //////////////////////////////// bool is_nominal(const Node* node); diff --git a/include/shady/ir/grammar.h b/include/shady/ir/grammar.h index 03667f6f2..70bbd5ca1 100644 --- a/include/shady/ir/grammar.h +++ b/include/shady/ir/grammar.h @@ -22,4 +22,6 @@ typedef struct BodyBuilder_ BodyBuilder; // see grammar.json #include "grammar_generated.h" +const char* shd_get_node_tag_string(NodeTag tag); + #endif diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 7fdf98474..c16042346 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -69,7 +69,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No case Param_TAG: shd_error("tried to emit a param: all params should be emitted by their binding abstraction !"); default: { assert(!is_instruction(value)); - shd_error("Unhandled value for code generation: %s", node_tags[value->tag]); + shd_error("Unhandled value for code generation: %s", shd_get_node_tag_string(value->tag)); } case Value_IntLiteral_TAG: { if (value->payload.int_literal.is_signed) diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index dabebefda..3753abc75 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -255,7 +255,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi case Terminator_Control_TAG: case TailCall_TAG: case Join_TAG: shd_error("Lower me"); - case NotATerminator: shd_error("TODO: emit terminator %s", node_tags[terminator->tag]); + case NotATerminator: shd_error("TODO: emit terminator %s", shd_get_node_tag_string(terminator->tag)); } SHADY_UNREACHABLE; } diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index d03481d6f..cdfe8472c 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -88,7 +88,7 @@ void spv_emit_nominal_type_body(Emitter* emitter, const Type* type, SpvId id) { } break; } - default: shd_error("not a suitable nominal type body (tag=%s)", node_tags[type->tag]); + default: shd_error("not a suitable nominal type body (tag=%s)", shd_get_node_tag_string(type->tag)); } } diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index a9db82f22..bcb8aa747 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -556,7 +556,7 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder break; } default: { - shd_error("Unhandled value for code generation: %s", node_tags[node->tag]); + shd_error("Unhandled value for code generation: %s", shd_get_node_tag_string(node->tag)); } } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index c65e40eda..c44169beb 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1,5 +1,7 @@ #include "s2s.h" + #include "shady/ir/builtin.h" +#include "shady/ir/memory_layout.h" // this avoids polluting the namespace #define SpvHasResultAndType ShadySpvHasResultAndType diff --git a/src/shady/fold.c b/src/shady/fold.c index 233441f77..1a5664d01 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -1,10 +1,12 @@ #include "fold.h" +#include "shady/ir/memory_layout.h" +#include "shady/rewrite.h" + #include "log.h" #include "type.h" #include "portability.h" -#include "shady/rewrite.h" #include "transform/ir_gen_helpers.h" diff --git a/src/shady/node.c b/src/shady/node.c index 8d8ca2ddf..df6022acd 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -329,6 +329,14 @@ void set_abstraction_body(Node* abs, const Node* body) { } } +const char* node_tags[]; + +const char* shd_get_node_tag_string(NodeTag tag) { + return node_tags[tag]; +} + +const bool node_type_has_payload[]; + KeyHash _shd_hash_node_payload(const Node* node); KeyHash shd_hash_node(Node** pnode) { diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 8dddec2d7..fe3d1241e 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -32,9 +32,9 @@ const Node* import_node(Rewriter* r, const Node* node) { } if (node->tag != existing->tag) { shd_error_print("Incompatible node types for to-be-merged declaration: %s ", get_declaration_name(node)); - shd_error_print("%s", node_tags[existing->tag]); + shd_error_print("%s", shd_get_node_tag_string(existing->tag)); shd_error_print(" vs "); - shd_error_print("%s", node_tags[node->tag]); + shd_error_print("%s", shd_get_node_tag_string(node->tag)); shd_error_print(".\n"); shd_error_die(); } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index da74b1e38..ea4a51479 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -1,14 +1,16 @@ #include "ir_gen_helpers.h" +#include "shady/rewrite.h" +#include "shady/ir/memory_layout.h" + +#include "../ir_private.h" +#include "../type.h" + #include "list.h" #include "portability.h" #include "log.h" #include "util.h" -#include "../ir_private.h" -#include "../type.h" -#include "shady/rewrite.h" - #include #include diff --git a/src/shady/type.c b/src/shady/type.c index 9e698eeae..9a8b50e8b 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -204,7 +204,7 @@ String name_type_safe(IrArena* arena, const Type* t) { case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; default: break; } - return unique_name(arena, node_tags[t->tag]); + return unique_name(arena, shd_get_node_tag_string(t->tag)); } /// Is this a type that a value in the language can have ? From e16433b0cba79a20bba31ad206519ee0648aa435 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 17:05:58 +0200 Subject: [PATCH 631/693] split off the final ir.h declarations --- include/shady/analysis/literal.h | 20 ++++++ include/shady/ir.h | 94 +++------------------------- include/shady/ir/composite.h | 16 +++++ include/shady/ir/debug.h | 11 ++++ include/shady/ir/decl.h | 9 +++ include/shady/ir/float.h | 11 ++-- include/shady/ir/grammar.h | 29 +++++++-- include/shady/ir/int.h | 17 ++--- include/shady/ir/primop.h | 5 +- include/shady/ir/type.h | 9 ++- src/shady/transform/ir_gen_helpers.h | 2 + src/shady/type.h | 3 - 12 files changed, 107 insertions(+), 119 deletions(-) create mode 100644 include/shady/analysis/literal.h create mode 100644 include/shady/ir/composite.h create mode 100644 include/shady/ir/debug.h create mode 100644 include/shady/ir/decl.h diff --git a/include/shady/analysis/literal.h b/include/shady/analysis/literal.h new file mode 100644 index 000000000..783481f39 --- /dev/null +++ b/include/shady/analysis/literal.h @@ -0,0 +1,20 @@ +#ifndef SHADY_ANALYSIS_LITERAL_H +#define SHADY_ANALYSIS_LITERAL_H + +#include "shady/ir/base.h" + +const char* get_string_literal(IrArena*, const Node*); + +typedef struct { + bool enter_loads; + bool allow_incompatible_types; + bool assume_globals_immutability; +} NodeResolveConfig; + +NodeResolveConfig default_node_resolve_config(void); +const Node* chase_ptr_to_source(const Node*, NodeResolveConfig config); +const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config); + +const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config); + +#endif diff --git a/include/shady/ir.h b/include/shady/ir.h index c9381eb24..ae8090fd9 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -2,102 +2,24 @@ #define SHADY_IR_H #include "shady/ir/base.h" -#include "shady/ir/module.h" - -//////////////////////////////// Grammar //////////////////////////////// -// The bulk of the language grammar is defined through json files. -// We define some support enums here. +#include "shady/ir/arena.h" +#include "shady/ir/module.h" +#include "shady/ir/grammar.h" #include "shady/ir/int.h" #include "shady/ir/float.h" +#include "shady/ir/composite.h" #include "shady/ir/execution_model.h" #include "shady/ir/primop.h" -#include "shady/ir/grammar.h" - -//////////////////////////////// Node categories //////////////////////////////// - -bool is_nominal(const Node* node); - -inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } - -//////////////////////////////// IR Arena //////////////////////////////// - -#include "shady/ir/arena.h" - -//////////////////////////////// Getters //////////////////////////////// - -/// Get the name out of a global variable, function or constant -String get_value_name_safe(const Node*); -String get_value_name_unsafe(const Node*); -void set_value_name(const Node* var, String name); - -String get_address_space_name(AddressSpace); -/// Returns false iff pointers in that address space can contain different data at the same address -/// (amongst threads in the same subgroup) -bool is_addr_space_uniform(IrArena*, AddressSpace); - +#include "shady/ir/debug.h" #include "shady/ir/annotation.h" - -const Node* maybe_tuple_helper(IrArena* a, Nodes values); -const Node* extract_helper(const Node* composite, const Node* index); - -const Node* maybe_tuple_helper(IrArena* a, Nodes values); - -const Node* tuple_helper(IrArena*, Nodes contents); -const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); - #include "shady/ir/mem.h" #include "shady/ir/type.h" - -const IntLiteral* resolve_to_int_literal(const Node* node); -int64_t get_int_literal_value(IntLiteral, bool sign_extend); -const FloatLiteral* resolve_to_float_literal(const Node* node); -double get_float_literal_value(FloatLiteral); -const char* get_string_literal(IrArena*, const Node*); - -typedef struct { - bool enter_loads; - bool allow_incompatible_types; - bool assume_globals_immutability; -} NodeResolveConfig; -NodeResolveConfig default_node_resolve_config(void); -const Node* chase_ptr_to_source(const Node*, NodeResolveConfig config); -const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config); - -const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config); - -//////////////////////////////// Constructors //////////////////////////////// - -/// Empty type: there are no values of this type. -/// Useful for the codomain of things that don't return at all -const Type* noret_type(IrArena*); -/// For typing instructions that return nothing (equivalent to C's void f()) -const Node* empty_multiple_return_type(IrArena*); - -Type* nominal_type(Module*, Nodes annotations, String name); - -// values -Node* param(IrArena*, const Type* type, const char* name); - -// decl ctors -Node* function (Module*, Nodes params, const char* name, Nodes annotations, Nodes return_types); -Node* constant (Module*, Nodes annotations, const Type*, const char* name); -Node* global_var (Module*, Nodes annotations, const Type*, String, AddressSpace); - -const Node* get_abstraction_mem(const Node* abs); -String get_abstraction_name (const Node* abs); -String get_abstraction_name_unsafe(const Node* abs); -String get_abstraction_name_safe(const Node* abs); - -void set_abstraction_body (Node* abs, const Node* body); - -// basic blocks -Node* basic_block(IrArena*, Nodes params, const char* name); -static inline Node* case_(IrArena* a, Nodes params) { - return basic_block(a, params, NULL); -} +#include "shady/ir/function.h" +#include "shady/ir/decl.h" #include "shady/body_builder.h" +#include "shady/analysis/literal.h" #endif diff --git a/include/shady/ir/composite.h b/include/shady/ir/composite.h new file mode 100644 index 000000000..4912fc0b4 --- /dev/null +++ b/include/shady/ir/composite.h @@ -0,0 +1,16 @@ +#ifndef SHADY_IR_COMPOSITE_H +#define SHADY_IR_COMPOSITE_H + +#include "shady/ir/grammar.h" + +const Node* maybe_tuple_helper(IrArena* a, Nodes values); +const Node* extract_helper(const Node* composite, const Node* index); + +const Node* maybe_tuple_helper(IrArena* a, Nodes values); + +const Node* tuple_helper(IrArena*, Nodes contents); + +void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); +void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack); + +#endif diff --git a/include/shady/ir/debug.h b/include/shady/ir/debug.h new file mode 100644 index 000000000..233c8550f --- /dev/null +++ b/include/shady/ir/debug.h @@ -0,0 +1,11 @@ +#ifndef SHADY_IR_DEBUG_H +#define SHADY_IR_DEBUG_H + +#include "shady/ir/base.h" + +/// Get the name out of a global variable, function or constant +String get_value_name_safe(const Node*); +String get_value_name_unsafe(const Node*); +void set_value_name(const Node* var, String name); + +#endif diff --git a/include/shady/ir/decl.h b/include/shady/ir/decl.h new file mode 100644 index 000000000..2d1a5205c --- /dev/null +++ b/include/shady/ir/decl.h @@ -0,0 +1,9 @@ +#ifndef SHADY_IR_DECL_H +#define SHADY_IR_DECL_H + +#include "shady/ir/base.h" + +Node* constant(Module*, Nodes annotations, const Type*, const char* name); +Node* global_var(Module*, Nodes annotations, const Type*, String, AddressSpace); + +#endif diff --git a/include/shady/ir/float.h b/include/shady/ir/float.h index df406cabc..08751e0af 100644 --- a/include/shady/ir/float.h +++ b/include/shady/ir/float.h @@ -1,13 +1,7 @@ #ifndef SHADY_IR_FLOAT_H #define SHADY_IR_FLOAT_H -#include "shady/ir/base.h" - -typedef enum { - FloatTy16, - FloatTy32, - FloatTy64 -} FloatSizes; +#include "shady/ir/grammar.h" static inline int float_size_in_bytes(FloatSizes s) { switch (s) { @@ -23,4 +17,7 @@ const Type* shd_fp64_type(IrArena* arena); const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value); +const FloatLiteral* resolve_to_float_literal(const Node* node); +double get_float_literal_value(FloatLiteral); + #endif diff --git a/include/shady/ir/grammar.h b/include/shady/ir/grammar.h index 70bbd5ca1..849696f54 100644 --- a/include/shady/ir/grammar.h +++ b/include/shady/ir/grammar.h @@ -3,7 +3,26 @@ #include "shady/ir/base.h" -// These structs are referenced in the actual grammar +// These enums and structs are used in the node payloads so they must live here +// instead of in the relevant header + +typedef enum { + IntTy8, + IntTy16, + IntTy32, + IntTy64, +} IntSizes; + +enum { + IntSizeMin = IntTy8, + IntSizeMax = IntTy64, +}; + +typedef enum { + FloatTy16, + FloatTy32, + FloatTy64 +} FloatSizes; typedef enum { NotSpecial, @@ -13,15 +32,15 @@ typedef enum { DecorateBlock } RecordSpecialFlag; -#include "shady/ir/int.h" -#include "shady/ir/float.h" -#include "shady/ir/primop.h" - typedef struct BodyBuilder_ BodyBuilder; +// see primops.json +#include "primops_generated.h" + // see grammar.json #include "grammar_generated.h" +bool is_nominal(const Node* node); const char* shd_get_node_tag_string(NodeTag tag); #endif diff --git a/include/shady/ir/int.h b/include/shady/ir/int.h index d7a3b5672..efba0f8ad 100644 --- a/include/shady/ir/int.h +++ b/include/shady/ir/int.h @@ -1,19 +1,7 @@ #ifndef SHADY_IR_INT_H #define SHADY_IR_INT_H -#include "shady/ir/base.h" - -typedef enum { - IntTy8, - IntTy16, - IntTy32, - IntTy64, -} IntSizes; - -enum { - IntSizeMin = IntTy8, - IntSizeMax = IntTy64, -}; +#include "shady/ir/grammar.h" static inline int int_size_in_bytes(IntSizes s) { switch (s) { @@ -46,4 +34,7 @@ const Node* shd_uint16_literal(IrArena* arena, uint16_t u); const Node* shd_uint32_literal(IrArena* arena, uint32_t u); const Node* shd_uint64_literal(IrArena* arena, uint64_t u); +const IntLiteral* resolve_to_int_literal(const Node* node); +int64_t get_int_literal_value(IntLiteral, bool sign_extend); + #endif diff --git a/include/shady/ir/primop.h b/include/shady/ir/primop.h index 08735adad..fcaa0e149 100644 --- a/include/shady/ir/primop.h +++ b/include/shady/ir/primop.h @@ -1,10 +1,7 @@ #ifndef SHADY_IR_PRIMOP_H #define SHADY_IR_PRIMOP_H -#include "shady/ir/base.h" - -// see primops.json -#include "primops_generated.h" +#include "shady/ir/grammar.h" String get_primop_name(Op op); bool has_primop_got_side_effects(Op op); diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index a38cfd299..96b451abd 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -1,12 +1,19 @@ #ifndef SHADY_IR_TYPE_H #define SHADY_IR_TYPE_H -#include "shady/ir/base.h" +#include "shady/ir/grammar.h" /// Unit type, carries no information (equivalent to C's void) /// There is exactly one possible value of this type: () const Node* unit_type(IrArena*); +Type* nominal_type(Module*, Nodes annotations, String name); + +String get_address_space_name(AddressSpace); +/// Returns false iff pointers in that address space can contain different data at the same address +/// (amongst threads in the same subgroup) +bool is_addr_space_uniform(IrArena*, AddressSpace); + /// Is this a type that a value in the language can have ? bool is_value_type(const Type*); diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 824212669..e74eaefc4 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -4,6 +4,8 @@ #include "shady/ir.h" #include "shady/ir/builtin.h" +const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); + void gen_push_value_stack(BodyBuilder* bb, const Node* value); void gen_push_values_stack(BodyBuilder* bb, Nodes values); const Node* gen_pop_value_stack(BodyBuilder*, const Type* type); diff --git a/src/shady/type.h b/src/shady/type.h index 81b5fc5b4..31303b734 100644 --- a/src/shady/type.h +++ b/src/shady/type.h @@ -21,7 +21,4 @@ bool is_conversion_legal(const Type* src_type, const Type* dst_type); const Type* get_actual_mask_type(IrArena* arena); -void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); -void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack); - #endif From 1cfe756d36420ccc424bf0804b705c3ea6eae913 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 17:08:29 +0200 Subject: [PATCH 632/693] ir/primop.h: added shd_ prefix --- include/shady/ir/primop.h | 6 ++++-- src/backend/c/emit_c_value.c | 2 +- src/frontend/llvm/l2s_instr.c | 2 +- src/frontend/llvm/l2s_postprocess.c | 2 +- src/frontend/slim/parser.c | 2 +- src/frontend/spirv/s2s.c | 2 +- src/shady/api/generator_primops.c | 1 - src/shady/generator_primops.c | 2 +- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/primops.c | 4 ++-- src/shady/print.c | 2 +- 12 files changed, 15 insertions(+), 14 deletions(-) diff --git a/include/shady/ir/primop.h b/include/shady/ir/primop.h index fcaa0e149..643ff0870 100644 --- a/include/shady/ir/primop.h +++ b/include/shady/ir/primop.h @@ -3,7 +3,9 @@ #include "shady/ir/grammar.h" -String get_primop_name(Op op); -bool has_primop_got_side_effects(Op op); +OpClass shd_get_primop_class(Op op); + +String shd_get_primop_name(Op op); +bool shd_has_primop_got_side_effects(Op op); #endif diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index c16042346..29d103775 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -434,7 +434,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node assert(node->tag == PrimOp_TAG); IrArena* arena = emitter->arena; const PrimOp* prim_op = &node->payload.prim_op; - CTerm term = term_from_cvalue(shd_fmt_string_irarena(emitter->arena, "/* todo %s */", get_primop_name(prim_op->op))); + CTerm term = term_from_cvalue(shd_fmt_string_irarena(emitter->arena, "/* todo %s */", shd_get_primop_name(prim_op->op))); const ISelTableEntry* isel_entry = lookup_entry(emitter, prim_op->op); switch (prim_op->op) { case add_carry_op: diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index a38cf3a7a..e116c5bec 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -546,7 +546,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B Op op; size_t i; for (i = 0; i < PRIMOPS_COUNT; i++) { - if (strcmp(get_primop_name(i), opname) == 0) { + if (strcmp(shd_get_primop_name(i), opname) == 0) { op = (Op) i; break; } diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 9e5d41002..25f43c42e 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -64,7 +64,7 @@ static const Node* process_node(Context* ctx, const Node* node) { Op op; size_t i; for (i = 0; i < PRIMOPS_COUNT; i++) { - if (strcmp(get_primop_name(i), shd_get_annotation_string_payload(an->payload)) == 0) { + if (strcmp(shd_get_primop_name(i), shd_get_annotation_string_payload(an->payload)) == 0) { op = (Op) i; break; } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index f38d16f29..48df6bb9a 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -272,7 +272,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { Op op = PRIMOPS_COUNT; for (size_t i = 0; i < PRIMOPS_COUNT; i++) { - if (strcmp(id, get_primop_name(i)) == 0) { + if (strcmp(id, shd_get_primop_name(i)) == 0) { op = i; break; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index c44169beb..e3f044376 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1132,7 +1132,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { char* primop = strtok(NULL, ":"); Op op = PRIMOPS_COUNT; for (size_t i = 0; i < PRIMOPS_COUNT; i++) { - if (strcmp(get_primop_name(i), primop) == 0) { + if (strcmp(shd_get_primop_name(i), primop) == 0) { op = i; break; } diff --git a/src/shady/api/generator_primops.c b/src/shady/api/generator_primops.c index ddad3887f..7805ba4b4 100644 --- a/src/shady/api/generator_primops.c +++ b/src/shady/api/generator_primops.c @@ -20,5 +20,4 @@ void generate(Growy* g, json_object* src) { json_object* op_classes = json_object_object_get(src, "prim-ops-classes"); generate_bit_enum(g, "OpClass", "Oc", op_classes); - shd_growy_append_formatted(g, "OpClass get_primop_class(Op);\n\n"); } diff --git a/src/shady/generator_primops.c b/src/shady/generator_primops.c index 9d1f9890a..c20793f1e 100644 --- a/src/shady/generator_primops.c +++ b/src/shady/generator_primops.c @@ -41,5 +41,5 @@ void generate(Growy* g, json_object* shd) { generate_primops_names_array(g, primops); generate_primops_side_effects_array(g, primops); - generate_bit_enum_classifier(g, "get_primop_class", "OpClass", "Oc", "Op", "", "_op", primops); + generate_bit_enum_classifier(g, "shd_get_primop_class", "OpClass", "Oc", "Op", "", "_op", primops); } diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 35e2903af..8b7f0aab5 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -44,7 +44,7 @@ static const Node* process(Context* ctx, const Node* node) { }); } case PrimOp_TAG: { - if (get_primop_class(node->payload.prim_op.op) & (OcArithmetic | OcLogic | OcCompare | OcShift | OcMath)) + if (shd_get_primop_class(node->payload.prim_op.op) & (OcArithmetic | OcLogic | OcCompare | OcShift | OcMath)) return scalarify_primop(ctx, node); } default: break; diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 41fe651e8..f3ea3ac31 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -84,7 +84,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca } default: break; } - if (has_primop_got_side_effects(payload.op)) + if (shd_has_primop_got_side_effects(payload.op)) k->leaks = true; } /*else if (use->user->tag == Lea_TAG) { // TODO: follow where those derived pointers are used and establish whether they leak themselves diff --git a/src/shady/primops.c b/src/shady/primops.c index 46b96f14c..a8a860317 100644 --- a/src/shady/primops.c +++ b/src/shady/primops.c @@ -6,10 +6,10 @@ #include "primops_generated.c" -String get_primop_name(Op op) { +String shd_get_primop_name(Op op) { return primop_names[op]; } -bool has_primop_got_side_effects(Op op) { +bool shd_has_primop_got_side_effects(Op op) { return primop_side_effects[op]; } diff --git a/src/shady/print.c b/src/shady/print.c index 3e66aeaa9..0785486c0 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1174,7 +1174,7 @@ void _shd_print_node_operand_AddressSpace(PrinterCtx* ctx, const Node* n, String void _shd_print_node_operand_Op(PrinterCtx* ctx, const Node* n, String name, Op op) { print_operand_name_helper(ctx, name); - shd_print(ctx->printer, "%s", get_primop_name(op)); + shd_print(ctx->printer, "%s", shd_get_primop_name(op)); } void _shd_print_node_operand_RecordSpecialFlag(PrinterCtx* ctx, const Node* n, String name, RecordSpecialFlag flags) { From fc9ada6c96f68c8310f99a5cd0cd461c6d22e51d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 17:13:36 +0200 Subject: [PATCH 633/693] more shd_ prefixing --- include/shady/analysis/literal.h | 10 +-- include/shady/ir/debug.h | 6 +- include/shady/ir/float.h | 4 +- include/shady/ir/grammar.h | 2 +- include/shady/ir/int.h | 4 +- include/shady/ir/module.h | 10 +-- src/backend/c/emit_c.c | 12 ++-- src/backend/c/emit_c_control_flow.c | 2 +- src/backend/c/emit_c_type.c | 4 +- src/backend/c/emit_c_value.c | 16 ++--- src/backend/spirv/emit_spv.c | 26 +++---- src/backend/spirv/emit_spv_control_flow.c | 2 +- src/backend/spirv/emit_spv_value.c | 6 +- src/backend/spirv/spirv_lift_globals_ssbo.c | 10 +-- src/backend/spirv/spirv_map_entrypoint_args.c | 4 +- src/driver/driver.c | 4 +- src/driver/slim.c | 2 +- src/frontend/llvm/l2s.c | 12 ++-- src/frontend/llvm/l2s_annotations.c | 10 +-- src/frontend/llvm/l2s_instr.c | 8 +-- src/frontend/llvm/l2s_meta.c | 8 +-- src/frontend/llvm/l2s_postprocess.c | 6 +- src/frontend/llvm/l2s_type.c | 2 +- src/frontend/llvm/l2s_value.c | 6 +- src/frontend/slim/bind.c | 22 +++--- src/frontend/slim/infer.c | 6 +- src/frontend/slim/normalize.c | 4 +- src/frontend/slim/parser.c | 22 +++--- src/frontend/slim/slim_driver.c | 2 +- src/frontend/spirv/s2s.c | 10 +-- src/runtime/runtime_program.c | 4 +- src/runtime/runtime_test.c | 2 +- src/runtime/vulkan/vk_runtime_program.c | 20 +++--- src/shady/analysis/callgraph.c | 4 +- src/shady/analysis/cfg.c | 8 +-- src/shady/analysis/cfg_dump.c | 10 +-- src/shady/analysis/looptree.c | 2 +- src/shady/analysis/uses.c | 2 +- src/shady/analysis/verify.c | 6 +- src/shady/body_builder.c | 8 +-- src/shady/compile.c | 10 +-- src/shady/constructors.c | 12 ++-- src/shady/fold.c | 26 +++---- src/shady/generator_node.c | 2 +- src/shady/ir.c | 2 +- src/shady/ir_private.h | 4 +- src/shady/module.c | 20 +++--- src/shady/node.c | 70 +++++++++---------- src/shady/passes/cleanup.c | 12 ++-- src/shady/passes/eliminate_constants.c | 4 +- src/shady/passes/import.c | 6 +- src/shady/passes/lcssa.c | 10 +-- src/shady/passes/lift_everything.c | 6 +- src/shady/passes/lift_indirect_targets.c | 18 ++--- src/shady/passes/lower_alloca.c | 12 ++-- src/shady/passes/lower_callf.c | 14 ++-- src/shady/passes/lower_cf_instrs.c | 18 ++--- src/shady/passes/lower_decay_ptrs.c | 4 +- src/shady/passes/lower_entrypoint_args.c | 10 +-- src/shady/passes/lower_fill.c | 6 +- src/shady/passes/lower_generic_globals.c | 4 +- src/shady/passes/lower_generic_ptrs.c | 36 +++++----- src/shady/passes/lower_int64.c | 4 +- src/shady/passes/lower_lea.c | 8 +-- src/shady/passes/lower_logical_pointers.c | 4 +- src/shady/passes/lower_mask.c | 4 +- src/shady/passes/lower_memcpy.c | 20 +++--- src/shady/passes/lower_memory_layout.c | 6 +- src/shady/passes/lower_nullptr.c | 4 +- src/shady/passes/lower_physical_ptrs.c | 18 ++--- src/shady/passes/lower_stack.c | 12 ++-- src/shady/passes/lower_subgroup_ops.c | 8 +-- src/shady/passes/lower_subgroup_vars.c | 10 +-- src/shady/passes/lower_switch_btree.c | 6 +- src/shady/passes/lower_tailcalls.c | 56 +++++++-------- src/shady/passes/lower_vec_arr.c | 4 +- src/shady/passes/lower_workgroups.c | 16 ++--- src/shady/passes/mark_leaf_functions.c | 14 ++-- src/shady/passes/normalize_builtins.c | 4 +- src/shady/passes/opt_demote_alloca.c | 4 +- src/shady/passes/opt_inline.c | 20 +++--- src/shady/passes/opt_mem2reg.c | 4 +- src/shady/passes/opt_restructure.c | 36 +++++----- src/shady/passes/reconvergence_heuristics.c | 32 ++++----- src/shady/passes/remove_critical_edges.c | 6 +- src/shady/passes/scope2control.c | 30 ++++---- src/shady/passes/scope_heuristic.c | 14 ++-- src/shady/passes/setup_stack_frames.c | 10 +-- src/shady/passes/specialize_entry_point.c | 14 ++-- src/shady/passes/specialize_execution_model.c | 4 +- src/shady/print.c | 6 +- src/shady/rewrite.c | 2 +- src/shady/transform/internal_constants.c | 2 +- src/shady/transform/ir_gen_helpers.c | 6 +- src/shady/transform/memory_layout.c | 2 +- src/shady/type.c | 6 +- src/shady/type_helpers.c | 6 +- src/shady/visit.c | 2 +- test/opt/opt_oracle.c | 6 +- test/test_builder.c | 20 +++--- test/test_math.c | 8 +-- vcc/vcc.c | 2 +- zhady/shady.i | 15 ++++ 103 files changed, 542 insertions(+), 527 deletions(-) diff --git a/include/shady/analysis/literal.h b/include/shady/analysis/literal.h index 783481f39..31a1494fe 100644 --- a/include/shady/analysis/literal.h +++ b/include/shady/analysis/literal.h @@ -3,7 +3,7 @@ #include "shady/ir/base.h" -const char* get_string_literal(IrArena*, const Node*); +const char* shd_get_string_literal(IrArena* arena, const Node* node); typedef struct { bool enter_loads; @@ -11,10 +11,10 @@ typedef struct { bool assume_globals_immutability; } NodeResolveConfig; -NodeResolveConfig default_node_resolve_config(void); -const Node* chase_ptr_to_source(const Node*, NodeResolveConfig config); -const Node* resolve_ptr_to_value(const Node* node, NodeResolveConfig config); +NodeResolveConfig shd_default_node_resolve_config(void); +const Node* shd_chase_ptr_to_source(const Node* ptr, NodeResolveConfig config); +const Node* shd_resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config); -const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config); +const Node* shd_resolve_node_to_definition(const Node* node, NodeResolveConfig config); #endif diff --git a/include/shady/ir/debug.h b/include/shady/ir/debug.h index 233c8550f..ee3659249 100644 --- a/include/shady/ir/debug.h +++ b/include/shady/ir/debug.h @@ -4,8 +4,8 @@ #include "shady/ir/base.h" /// Get the name out of a global variable, function or constant -String get_value_name_safe(const Node*); -String get_value_name_unsafe(const Node*); -void set_value_name(const Node* var, String name); +String shd_get_value_name_safe(const Node* v); +String shd_get_value_name_unsafe(const Node* v); +void shd_set_value_name(const Node* var, String name); #endif diff --git a/include/shady/ir/float.h b/include/shady/ir/float.h index 08751e0af..4d32d36d8 100644 --- a/include/shady/ir/float.h +++ b/include/shady/ir/float.h @@ -17,7 +17,7 @@ const Type* shd_fp64_type(IrArena* arena); const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value); -const FloatLiteral* resolve_to_float_literal(const Node* node); -double get_float_literal_value(FloatLiteral); +const FloatLiteral* shd_resolve_to_float_literal(const Node* node); +double shd_get_float_literal_value(FloatLiteral literal); #endif diff --git a/include/shady/ir/grammar.h b/include/shady/ir/grammar.h index 849696f54..32c1e1be3 100644 --- a/include/shady/ir/grammar.h +++ b/include/shady/ir/grammar.h @@ -40,7 +40,7 @@ typedef struct BodyBuilder_ BodyBuilder; // see grammar.json #include "grammar_generated.h" -bool is_nominal(const Node* node); +bool shd_is_node_nominal(const Node* node); const char* shd_get_node_tag_string(NodeTag tag); #endif diff --git a/include/shady/ir/int.h b/include/shady/ir/int.h index efba0f8ad..0ef5679b3 100644 --- a/include/shady/ir/int.h +++ b/include/shady/ir/int.h @@ -34,7 +34,7 @@ const Node* shd_uint16_literal(IrArena* arena, uint16_t u); const Node* shd_uint32_literal(IrArena* arena, uint32_t u); const Node* shd_uint64_literal(IrArena* arena, uint64_t u); -const IntLiteral* resolve_to_int_literal(const Node* node); -int64_t get_int_literal_value(IntLiteral, bool sign_extend); +const IntLiteral* shd_resolve_to_int_literal(const Node* node); +int64_t shd_get_int_literal_value(IntLiteral literal, bool sign_extend); #endif diff --git a/include/shady/ir/module.h b/include/shady/ir/module.h index 50dc5b4c9..0a2d6ba33 100644 --- a/include/shady/ir/module.h +++ b/include/shady/ir/module.h @@ -3,12 +3,12 @@ #include "shady/ir/base.h" -Module* new_module(IrArena*, String name); +Module* shd_new_module(IrArena* arena, String name); -IrArena* get_module_arena(const Module*); -String get_module_name(const Module*); -Nodes get_module_declarations(const Module*); -Node* get_declaration(const Module*, String); +IrArena* shd_module_get_arena(const Module* m); +String shd_module_get_name(const Module* m); +Nodes shd_module_get_declarations(const Module* m); +Node* shd_module_get_declaration(const Module* m, String name); void link_module(Module* dst, Module* src); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index d9b8ec1aa..67d6bd1fb 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -273,7 +273,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { } if (ass == AsOutput && emitter->compiler_config->specialization.execution_model == EmFragment) { - int location = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "Location"))), false); + int location = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "Location"))), false); CTerm t = term_from_cvar(shd_fmt_string_irarena(emitter->arena, "gl_FragData[%d]", location)); register_emitted(emitter, NULL, decl, t); return; @@ -316,7 +316,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { for (size_t i = 0; i < decl->payload.fun.params.count; i++) { String param_name; - String variable_name = get_value_name_unsafe(decl->payload.fun.params.nodes[i]); + String variable_name = shd_get_value_name_unsafe(decl->payload.fun.params.nodes[i]); param_name = shd_fmt_string_irarena(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); register_emitted(emitter, &fn, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } @@ -393,7 +393,7 @@ static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { Printer* p = shd_new_printer_from_growy(g); shd_print(p, "typedef struct __shady_PrivateGlobals {\n"); - Nodes decls = get_module_declarations(m); + Nodes decls = shd_module_get_declarations(m); size_t count = 0; for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; @@ -422,9 +422,9 @@ CEmitterConfig default_c_emitter_config(void) { } void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod) { - IrArena* initial_arena = get_module_arena(mod); + IrArena* initial_arena = shd_module_get_arena(mod); mod = run_backend_specific_passes(compiler_config, &config, mod); - IrArena* arena = get_module_arena(mod); + IrArena* arena = shd_module_get_arena(mod); Growy* type_decls_g = shd_new_growy(); Growy* fn_decls_g = shd_new_growy(); @@ -460,7 +460,7 @@ void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Mo } } - Nodes decls = get_module_declarations(mod); + Nodes decls = shd_module_get_declarations(mod); for (size_t i = 0; i < decls.count; i++) c_emit_decl(&emitter, decls.nodes[i]); diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index b5b73d2be..df541c55f 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -144,7 +144,7 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { Nodes variables = params; LARRAY(String, arr, variables.count); for (size_t i = 0; i < variables.count; i++) { - arr[i] = get_value_name_unsafe(variables.nodes[i]); + arr[i] = shd_get_value_name_unsafe(variables.nodes[i]); if (!arr[i]) arr[i] = unique_name(emitter->arena, "phi"); } diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index ecd3d4653..b7334d233 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -65,7 +65,7 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons } for (size_t i = 0; i < dom.count; i++) { String param_name; - String variable_name = get_value_name_unsafe(fn->payload.fun.params.nodes[i]); + String variable_name = shd_get_value_name_unsafe(fn->payload.fun.params.nodes[i]); param_name = shd_fmt_string_irarena(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); shd_print(paramp, c_emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { @@ -261,7 +261,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { shd_printer_indent(p); String inner_decl_rhs; if (size) - inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[%zu]", get_int_literal_value(*resolve_to_int_literal(size), false)); + inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[%zu]", shd_get_int_literal_value(*shd_resolve_to_int_literal(size), false)); else inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[0]"); shd_print(p, "\n%s;", c_emit_type(emitter, type->payload.arr_type.element_type, inner_decl_rhs)); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 29d103775..8a9119527 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -27,7 +27,7 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e uint8_t* tmp = malloc(sizeof(uint8_t) * c.count); bool ends_zero = false; for (size_t i = 0; i < c.count; i++) { - tmp[i] = get_int_literal_value(*resolve_to_int_literal(c.nodes[i]), false); + tmp[i] = shd_get_int_literal_value(*shd_resolve_to_int_literal(c.nodes[i]), false); if (tmp[i] == 0) { if (i == c.count - 1) ends_zero = true; @@ -514,7 +514,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node t = get_nominal_type_body(t); } const Node* index = shd_first(prim_op->operands); - uint64_t index_literal = get_int_literal_value(*resolve_to_int_literal(index), false); + uint64_t index_literal = shd_get_int_literal_value(*shd_resolve_to_int_literal(index), false); String member_name = c_get_record_field_name(t, index_literal); term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "offsetof(%s, %s)", c_emit_type(emitter, t, NULL), member_name)); break; @@ -629,7 +629,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node const Type* t = get_unqualified_type(shd_first(prim_op->operands)->type); for (size_t i = (insert ? 2 : 1); i < prim_op->operands.count; i++) { const Node* index = prim_op->operands.nodes[i]; - const IntLiteral* static_index = resolve_to_int_literal(index); + const IntLiteral* static_index = shd_resolve_to_int_literal(index); switch (is_type(t)) { case Type_TypeDeclRef_TAG: { @@ -686,7 +686,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node String suffixes = "xyzw"; shd_print(p, "\n%s = vec%d(", c_emit_type(emitter, node->type, dst), prim_op->operands.count - 2); for (size_t i = 2; i < prim_op->operands.count; i++) { - const IntLiteral* selector = resolve_to_int_literal(prim_op->operands.nodes[i]); + const IntLiteral* selector = shd_resolve_to_int_literal(prim_op->operands.nodes[i]); if (selector->value < left_size) shd_print(p, "%s.%c\n", lhs_e, suffixes[selector->value]); else @@ -731,7 +731,7 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E } case SpvOpGroupNonUniformElect: { assert(instr.operands.count == 1); - const IntLiteral* scope = resolve_to_int_literal(shd_first(instr.operands)); + const IntLiteral* scope = shd_resolve_to_int_literal(shd_first(instr.operands)); assert(scope && scope->value == SpvScopeSubgroup); switch (emitter->config.dialect) { case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_elect_first()")); @@ -827,7 +827,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer } assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a record need to be constant"); - size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); + size_t static_index = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); String field_name = c_get_record_field_name(pointee_type, static_index); acc = term_from_cvar(shd_format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); curr_ptr_type = ptr_type(arena, (PtrType) { @@ -837,7 +837,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer break; } case Type_PackType_TAG: { - size_t static_index = get_int_literal_value(*resolve_to_int_literal(selector), false); + size_t static_index = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); String suffixes = "xyzw"; acc = term_from_cvar(shd_format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); curr_ptr_type = ptr_type(arena, (PtrType) { @@ -864,7 +864,7 @@ static CTerm emit_ptr_array_element_offset(Emitter* emitter, FnEmitter* fn, Prin const Type* curr_ptr_type = get_unqualified_type(src_qtype); assert(curr_ptr_type->tag == PtrType_TAG); - const IntLiteral* offset_static_value = resolve_to_int_literal(lea.offset); + const IntLiteral* offset_static_value = shd_resolve_to_int_literal(lea.offset); if (!offset_static_value || offset_static_value->value != 0) { CTerm offset = c_emit_value(emitter, fn, lea.offset); // we sadly need to drop to the value level (aka explicit pointer arithmetic) to do this diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 3e16c20bb..04ce0726f 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -29,7 +29,7 @@ bool shd_compare_string(const char** a, const char** b); void spv_register_emitted(Emitter* emitter, FnBuilder* fn_builder, const Node* node, SpvId id) { if (is_value(node)) { - String name = get_value_name_unsafe(node); + String name = shd_get_value_name_unsafe(node); if (name) spvb_name(emitter->file_builder, id, name); } @@ -62,7 +62,7 @@ static void emit_basic_block(Emitter* emitter, FnBuilder* fn_builder, const CFNo SpvId bb_id = get_block_builder_id(bb_builder); spvb_add_bb(fn_builder->base, bb_builder); - String name = get_abstraction_name_safe(bb_node); + String name = shd_get_abstraction_name_safe(bb_node); if (name) spvb_name(emitter->file_builder, bb_id, name); @@ -131,7 +131,7 @@ static void emit_function(Emitter* emitter, const Node* node) { spvb_define_function(emitter->file_builder, fn_builder.base); } else { Growy* g = shd_new_growy(); - spvb_literal_name(g, get_abstraction_name(node)); + spvb_literal_name(g, shd_get_abstraction_name(node)); shd_growy_append_bytes(g, 4, (char*) &(uint32_t) { SpvLinkageTypeImport }); spvb_decorate(emitter->file_builder, fn_id, SpvDecorationLinkageAttributes, shd_growy_size(g) / 4, (uint32_t*) shd_growy_data(g)); shd_destroy_growy(g); @@ -176,15 +176,15 @@ SpvId spv_emit_decl(Emitter* emitter, const Node* decl) { uint32_t decoration_payload[] = { d }; spvb_decorate(emitter->file_builder, given_id, SpvDecorationBuiltIn, 1, decoration_payload); } else if (strcmp(name, "Location") == 0) { - size_t loc = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(a)), false); + size_t loc = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_annotation_value(a)), false); assert(loc >= 0); spvb_decorate(emitter->file_builder, given_id, SpvDecorationLocation, 1, (uint32_t[]) { loc }); } else if (strcmp(name, "DescriptorSet") == 0) { - size_t loc = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(a)), false); + size_t loc = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_annotation_value(a)), false); assert(loc >= 0); spvb_decorate(emitter->file_builder, given_id, SpvDecorationDescriptorSet, 1, (uint32_t[]) { loc }); } else if (strcmp(name, "DescriptorBinding") == 0) { - size_t loc = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(a)), false); + size_t loc = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_annotation_value(a)), false); assert(loc >= 0); spvb_decorate(emitter->file_builder, given_id, SpvDecorationBinding, 1, (uint32_t[]) { loc }); } @@ -268,7 +268,7 @@ static void emit_entry_points(Emitter* emitter, Nodes declarations) { const Node* entry_point = shd_lookup_annotation(decl, "EntryPoint"); if (entry_point) { - ExecutionModel execution_model = shd_execution_model_from_string(get_string_literal(emitter->arena, shd_get_annotation_value(entry_point))); + ExecutionModel execution_model = shd_execution_model_from_string(shd_get_string_literal(emitter->arena, shd_get_annotation_value(entry_point))); assert(execution_model != EmNone); spvb_entry_point(emitter->file_builder, emit_exec_model(execution_model), fn_id, decl->payload.fun.name, interface_size, interface_arr); @@ -280,9 +280,9 @@ static void emit_entry_points(Emitter* emitter, Nodes declarations) { if (workgroup_size) { Nodes values = shd_get_annotation_values(workgroup_size); assert(values.count == 3); - uint32_t wg_x_dim = (uint32_t) get_int_literal_value(*resolve_to_int_literal(values.nodes[0]), false); - uint32_t wg_y_dim = (uint32_t) get_int_literal_value(*resolve_to_int_literal(values.nodes[1]), false); - uint32_t wg_z_dim = (uint32_t) get_int_literal_value(*resolve_to_int_literal(values.nodes[2]), false); + uint32_t wg_x_dim = (uint32_t) shd_get_int_literal_value(*shd_resolve_to_int_literal(values.nodes[0]), false); + uint32_t wg_y_dim = (uint32_t) shd_get_int_literal_value(*shd_resolve_to_int_literal(values.nodes[1]), false); + uint32_t wg_z_dim = (uint32_t) shd_get_int_literal_value(*shd_resolve_to_int_literal(values.nodes[2]), false); spvb_execution_mode(emitter->file_builder, fn_id, SpvExecutionModeLocalSize, 3, (uint32_t[3]) { wg_x_dim, wg_y_dim, wg_z_dim }); } @@ -328,9 +328,9 @@ static Module* run_backend_specific_passes(const CompilerConfig* config, Module* } void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, char** output, Module** new_mod) { - IrArena* initial_arena = get_module_arena(mod); + IrArena* initial_arena = shd_module_get_arena(mod); mod = run_backend_specific_passes(config, mod); - IrArena* arena = get_module_arena(mod); + IrArena* arena = shd_module_get_arena(mod); FileBuilder file_builder = spvb_begin(); spvb_set_version(file_builder, config->target_spirv_version.major, config->target_spirv_version.minor); @@ -352,7 +352,7 @@ void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, spvb_extension(file_builder, "SPV_KHR_non_semantic_info"); - Nodes decls = get_module_declarations(mod); + Nodes decls = shd_module_get_declarations(mod); emit_decls(&emitter, decls); emit_entry_points(&emitter, decls); diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 3753abc75..f20f9eca6 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -65,7 +65,7 @@ static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_bui size_t literal_case_entry_size = literal_width + 1; LARRAY(uint32_t, literals_and_cases, match.cases.count * literal_case_entry_size); for (size_t i = 0; i < match.cases.count; i++) { - uint64_t value = (uint64_t) get_int_literal_value(*resolve_to_int_literal(match.literals.nodes[i]), false); + uint64_t value = (uint64_t) shd_get_int_literal_value(*shd_resolve_to_int_literal(match.literals.nodes[i]), false); if (inspectee_t->payload.int_type.width == IntTy64) { literals_and_cases[i * literal_case_entry_size + 0] = (SpvId) (uint32_t) (value & 0xFFFFFFFF); literals_and_cases[i * literal_case_entry_size + 1] = (SpvId) (uint32_t) (value >> 32); diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index bcb8aa747..92e87d6b6 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -242,7 +242,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b LARRAY(uint32_t, indices, indices_count); for (size_t i = 0; i < indices_count; i++) { // TODO: fallback to Dynamic variants transparently - indices[i] = get_int_literal_value(*resolve_to_int_literal(args.nodes[i + indices_start]), false); + indices[i] = shd_get_int_literal_value(*shd_resolve_to_int_literal(args.nodes[i + indices_start]), false); } if (insert) @@ -256,7 +256,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b SpvId b = spv_emit_value(emitter, fn_builder, args.nodes[1]); LARRAY(uint32_t, indices, args.count - 2); for (size_t i = 0; i < args.count - 2; i++) { - int64_t indice = get_int_literal_value(*resolve_to_int_literal(args.nodes[i + 2]), true); + int64_t indice = shd_get_int_literal_value(*shd_resolve_to_int_literal(args.nodes[i + 2]), true); if (indice == -1) indices[i] = 0xFFFFFFFF; else @@ -313,7 +313,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b case SpvOpGroupNonUniformIAdd: { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformArithmetic); SpvId scope = spv_emit_value(emitter, fn_builder, shd_first(instr.operands)); - SpvGroupOperation group_op = get_int_literal_value(*resolve_to_int_literal(instr.operands.nodes[2]), false); + SpvGroupOperation group_op = shd_get_int_literal_value(*shd_resolve_to_int_literal(instr.operands.nodes[2]), false); return spvb_group_non_uniform_group_op(bb_builder, spv_emit_type(emitter, instr.result_t), instr.opcode, scope, group_op, spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), NULL); } case SpvOpGroupNonUniformElect: { diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 6c0628c0f..2313519df 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -27,9 +27,9 @@ static const Node* process(Context* ctx, const Node* node) { functx.rewriter.map = shd_clone_dict(functx.rewriter.map); shd_dict_clear(functx.rewriter.map); shd_register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); - functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); + functx.bb = begin_body_with_mem(a, shd_get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); - shd_register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); + shd_register_processed(&functx.rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(post_prelude)); set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, shd_empty(a)))); @@ -63,16 +63,16 @@ static const Node* process(Context* ctx, const Node* node) { } Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config }; - Nodes old_decls = get_module_declarations(src); + Nodes old_decls = shd_module_get_declarations(src); LARRAY(const Type*, member_tys, old_decls.count); LARRAY(String, member_names, old_decls.count); diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index 3358c3140..9bb79c999 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -58,9 +58,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* spirv_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config diff --git a/src/driver/driver.c b/src/driver/driver.c index 60fcfe14f..36b5fa6ba 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -108,7 +108,7 @@ ShadyErrorCodes shd_driver_load_source_files(DriverConfig* args, Module* mod) { if (err) return err; link_module(mod, m); - shd_destroy_ir_arena(get_module_arena(m)); + shd_destroy_ir_arena(shd_module_get_arena(m)); } return NoError; @@ -181,6 +181,6 @@ ShadyErrorCodes shd_driver_compile(DriverConfig* args, Module* mod) { free((void*) output_buffer); fclose(f); } - shd_destroy_ir_arena(get_module_arena(mod)); + shd_destroy_ir_arena(shd_module_get_arena(mod)); return NoError; } diff --git a/src/driver/slim.c b/src/driver/slim.c index a18b1d6f9..ae6c8fa97 100644 --- a/src/driver/slim.c +++ b/src/driver/slim.c @@ -17,7 +17,7 @@ int main(int argc, char** argv) { ArenaConfig aconfig = shd_default_arena_config(&args.config.target); IrArena* arena = shd_new_ir_arena(&aconfig); - Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one + Module* mod = shd_new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one ShadyErrorCodes err = shd_driver_load_source_files(&args, mod); if (err) diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 2b50e673d..3d88e846e 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -45,7 +45,7 @@ int vcc_get_linked_major_llvm_version() { #endif static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { - bb_ctx->builder = begin_body_with_mem(bb_ctx->nbb->arena, get_abstraction_mem(bb_ctx->nbb)); + bb_ctx->builder = begin_body_with_mem(bb_ctx->nbb->arena, shd_get_abstraction_mem(bb_ctx->nbb)); LLVMValueRef instr; LLVMBasicBlockRef bb = bb_ctx->bb; for (instr = bb_ctx->instr; instr; instr = LLVMGetNextInstruction(instr)) { @@ -72,7 +72,7 @@ static void write_bb_tail(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { } static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasicBlockRef bb) { - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); shd_debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); if (shd_log_get_level() >= DEBUG) LLVMDumpValue((LLVMValueRef)bb); @@ -151,7 +151,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { const Node** found = shd_dict_find_value(LLVMValueRef, const Node*, p->map, fn); if (found) return *found; - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); shd_debug_print("Converting function: %s\n", LLVMGetValueName(fn)); Nodes params = shd_empty(a); @@ -240,7 +240,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { const Node* convert_global(Parser* p, LLVMValueRef global) { const Node** found = shd_dict_find_value(LLVMValueRef, const Node*, p->map, global); if (found) return *found; - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); String name = LLVMGetValueName(global); String intrinsic = is_llvm_intrinsic(global); @@ -303,7 +303,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* aconfig.optimisations.inline_single_use_bbs = false; IrArena* arena = shd_new_ir_arena(&aconfig); - Module* dirty = new_module(arena, "dirty"); + Module* dirty = shd_new_module(arena, "dirty"); Parser p = { .ctx = context, .config = config, @@ -335,7 +335,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* aconfig.check_types = true; aconfig.allow_fold = true; IrArena* arena2 = shd_new_ir_arena(&aconfig); - *dst = new_module(arena2, name); + *dst = shd_new_module(arena2, name); postprocess(&p, dirty, *dst); shd_log_fmt(DEBUGVV, "Shady module parsed from LLVM, after cleanup:"); shd_log_module(DEBUGVV, config, *dst); diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index deb421a44..23f999383 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -61,10 +61,10 @@ static bool is_io_as(AddressSpace as) { } void process_llvm_annotations(Parser* p, LLVMValueRef global) { - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); const Type* t = convert_type(p, LLVMGlobalGetValueType(global)); assert(t->tag == ArrType_TAG); - size_t arr_size = get_int_literal_value(*resolve_to_int_literal(t->payload.arr_type.size), false); + size_t arr_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(t->payload.arr_type.size), false); assert(arr_size > 0); const Node* value = convert_value(p, LLVMGetInitializer(global)); assert(value->tag == Composite_TAG && value->payload.composite.contents.count == arr_size); @@ -82,16 +82,16 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { annotation_payload = annotation_payload->payload.global_variable.init; } - NodeResolveConfig resolve_config = default_node_resolve_config(); + NodeResolveConfig resolve_config = shd_default_node_resolve_config(); // both of those assumptions are hacky but this front-end is a hacky deal anyways. resolve_config.assume_globals_immutability = true; resolve_config.allow_incompatible_types = true; - const char* ostr = get_string_literal(a, chase_ptr_to_source(annotation_payload, resolve_config)); + const char* ostr = shd_get_string_literal(a, shd_chase_ptr_to_source(annotation_payload, resolve_config)); char* str = calloc(strlen(ostr) + 1, 1); memcpy(str, ostr, strlen(ostr) + 1); if (strcmp(strtok(str, "::"), "shady") == 0) { const Node* target = entry->payload.composite.contents.nodes[0]; - target = resolve_node_to_definition(target, resolve_config); + target = shd_resolve_node_to_definition(target, resolve_config); char* keyword = strtok(NULL, "::"); if (strcmp(keyword, "entry_point") == 0) { diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index e116c5bec..a7e94ef3b 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -11,7 +11,7 @@ #include "llvm-c/DebugInfo.h" static Nodes convert_operands(Parser* p, size_t num_ops, LLVMValueRef v) { - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); LARRAY(const Node*, ops, num_ops); for (size_t i = 0; i < num_ops; i++) { LLVMValueRef op = LLVMGetOperand(v, i); @@ -90,7 +90,7 @@ static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* eleme const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { Node* fn = fn_ctx ? fn_ctx->fn : NULL; - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); int num_ops = LLVMGetNumOperands(instr); size_t num_results = 1; Nodes result_types = shd_empty(a); @@ -465,9 +465,9 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B meta = meta->payload.global_variable.init; assert(meta && meta->tag == Composite_TAG); const Node* name_node = meta->payload.composite.contents.nodes[2]; - String name = get_string_literal(target->arena, name_node); + String name = shd_get_string_literal(target->arena, name_node); assert(name); - set_value_name((Node*) target, name); + shd_set_value_name((Node*) target, name); return NULL; } if (strcmp(intrinsic, "llvm.dbg.label") == 0) { diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index af71ad0fd..1f9c5d46c 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -7,7 +7,7 @@ #include "llvm-c/DebugInfo.h" static Nodes convert_mdnode_operands(Parser* p, LLVMValueRef mdnode) { - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); assert(LLVMIsAMDNode(mdnode)); unsigned count = LLVMGetMDNodeNumOperands(mdnode); @@ -23,7 +23,7 @@ static Nodes convert_mdnode_operands(Parser* p, LLVMValueRef mdnode) { static const Node* convert_named_tuple_metadata(Parser* p, LLVMValueRef v, String node_name) { // printf("%s\n", name); - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); String name = LLVMGetValueName(v); if (!name || strlen(name) == 0) name = unique_name(a, node_name); @@ -102,7 +102,7 @@ LLVM_DI_WITH_PARENT_SCOPES(N) } Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); Nodes str = shd_empty(a); LLVMMetadataRef scope = LLVMDILocationGetScope(dbgloc); @@ -123,7 +123,7 @@ Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { } const Node* convert_metadata(Parser* p, LLVMMetadataRef meta) { - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); LLVMMetadataKind kind = LLVMGetMetadataKind(meta); LLVMValueRef v = LLVMMetadataAsValue(p->ctx, meta); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 25f43c42e..961a289d3 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -81,12 +81,12 @@ static const Node* process_node(Context* ctx, const Node* node) { } shd_register_processed_list(r, node->payload.fun.params, new_params); Nodes new_annotations = shd_rewrite_nodes(r, old_annotations); - Node* decl = function(ctx->rewriter.dst_module, new_params, get_abstraction_name(node), new_annotations, shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); + Node* decl = function(ctx->rewriter.dst_module, new_params, shd_get_abstraction_name(node), new_annotations, shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); shd_register_processed(&ctx->rewriter, node, decl); if (primop_intrinsic != PRIMOPS_COUNT) { set_abstraction_body(decl, fn_ret(a, (Return) { .args = shd_singleton(prim_op_helper(a, primop_intrinsic, shd_empty(a), get_abstraction_params(decl))), - .mem = get_abstraction_mem(decl), + .mem = shd_get_abstraction_mem(decl), })); } else if (get_abstraction_body(node)) set_abstraction_body(decl, shd_rewrite_node(r, get_abstraction_body(node))); @@ -106,7 +106,7 @@ static const Node* process_node(Context* ctx, const Node* node) { if (strcmp(get_annotation_name(an->payload), "Builtin") == 0) old_init = NULL; if (strcmp(get_annotation_name(an->payload), "AddressSpace") == 0) - as = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(an->payload)), false); + as = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_annotation_value(an->payload)), false); an = an->next; } Node* decl = global_var(ctx->rewriter.dst_module, annotations, type, get_declaration_name(node), as); diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index 6a659d66f..c968b78be 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -9,7 +9,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { const Type** found = shd_dict_find_value(LLVMTypeRef, const Type*, p->map, t); if (found) return *found; - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); switch (LLVMGetTypeKind(t)) { case LLVMVoidTypeKind: return unit_type(a); diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index 9cc68ba88..64dfc1908 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -46,7 +46,7 @@ static const Node* data_composite(const Type* t, size_t size, LLVMValueRef v) { const Node* convert_value(Parser* p, LLVMValueRef v) { const Type** found = shd_dict_find_value(LLVMTypeRef, const Type*, p->map, v); if (found) return *found; - IrArena* a = get_module_arena(p->dst); + IrArena* a = shd_module_get_arena(p->dst); const Node* r = NULL; const Type* t = LLVMGetValueKind(v) != LLVMMetadataAsValueValueKind ? convert_type(p, LLVMTypeOf(v)) : NULL; @@ -89,7 +89,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { } case LLVMConstantDataArrayValueKind: { assert(t->tag == ArrType_TAG); - size_t arr_size = get_int_literal_value(*resolve_to_int_literal(t->payload.arr_type.size), false); + size_t arr_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(t->payload.arr_type.size), false); assert(arr_size >= 0 && arr_size < INT32_MAX && "sanity check"); return data_composite(t, arr_size, v); } @@ -128,7 +128,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { return get_default_zero_value(a, convert_type(p, LLVMTypeOf(v))); case LLVMConstantArrayValueKind: { assert(t->tag == ArrType_TAG); - size_t arr_size = get_int_literal_value(*resolve_to_int_literal(t->payload.arr_type.size), false); + size_t arr_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(t->payload.arr_type.size), false); assert(arr_size >= 0 && arr_size < INT32_MAX && "sanity check"); LARRAY(const Node*, elements, arr_size); for (size_t i = 0; i < arr_size; i++) { diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 981c9e032..88572c811 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -42,7 +42,7 @@ static Resolved resolve_using_name(Context* ctx, const char* name) { } } - Nodes new_decls = get_module_declarations(ctx->rewriter.dst_module); + Nodes new_decls = shd_module_get_declarations(ctx->rewriter.dst_module); for (size_t i = 0; i < new_decls.count; i++) { const Node* decl = new_decls.nodes[i]; if (strcmp(get_declaration_name(decl), name) == 0) { @@ -53,7 +53,7 @@ static Resolved resolve_using_name(Context* ctx, const char* name) { } } - Nodes old_decls = get_module_declarations(ctx->rewriter.src_module); + Nodes old_decls = shd_module_get_declarations(ctx->rewriter.src_module); for (size_t i = 0; i < old_decls.count; i++) { const Node* old_decl = old_decls.nodes[i]; if (strcmp(get_declaration_name(old_decl), name) == 0) { @@ -112,7 +112,7 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { } else if (payload.opcode == SlimOpUnbound) { if (payload.mem) shd_rewrite_node(&ctx->rewriter, payload.mem); - Resolved entry = resolve_using_name(ctx, get_string_literal(a, shd_first(payload.operands))); + Resolved entry = resolve_using_name(ctx, shd_get_string_literal(a, shd_first(payload.operands))); // can't take the address if it's not a var! if (!entry.is_var) return NULL; @@ -144,7 +144,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); Nodes results = deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { - String name = get_string_literal(a, names[i]); + String name = shd_get_string_literal(a, names[i]); shd_log_fmt(DEBUGV, "Bound immutable variable '%s'\n", name); add_binding(ctx, false, name, results.nodes[i]); } @@ -157,12 +157,12 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); Nodes results = deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { - String name = get_string_literal(a, names[i]); + String name = shd_get_string_literal(a, names[i]); const Type* type_annotation = types[i]; assert(type_annotation); const Node* alloca = stack_alloc(a, (StackAlloc) { .type = shd_rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; - set_value_name(ptr, name); + shd_set_value_name(ptr, name); bind_instruction_outputs_count(bb, store(a, (Store) { .ptr = ptr, .value = results.nodes[0], .mem = bb_mem(bb) }), 0); add_binding(ctx, true, name, ptr); @@ -176,9 +176,9 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { const Node** conts = &instr.operands.nodes[0 + names_count]; LARRAY(Node*, bbs, names_count); for (size_t i = 0; i < names_count; i++) { - String name = get_string_literal(a, names[i]); + String name = shd_get_string_literal(a, names[i]); Nodes nparams = shd_recreate_params(r, get_abstraction_params(conts[i])); - bbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(conts[i])); + bbs[i] = basic_block(a, nparams, shd_get_abstraction_name_unsafe(conts[i])); shd_register_processed(r, conts[i], bbs[i]); add_binding(ctx, false, name, bbs[i]); shd_log_fmt(DEBUGV, "Bound continuation '%s'\n", name); @@ -348,7 +348,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { return shd_rewrite_node(r, payload.mem); mem = shd_rewrite_node(r, payload.mem); } - Resolved entry = resolve_using_name(ctx, get_string_literal(a, shd_first(payload.operands))); + Resolved entry = resolve_using_name(ctx, shd_get_string_literal(a, shd_first(payload.operands))); if (entry.is_var) { return load(a, (Load) { .ptr = entry.node, .mem = mem }); } else if (mem) { @@ -367,11 +367,11 @@ static const Node* bind_node(Context* ctx, const Node* node) { } Module* slim_pass_bind(SHADY_UNUSED const CompilerConfig* compiler_config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); assert(!src->arena->config.name_bound); aconfig.name_bound = true; IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) bind_node), diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 2b73f09b6..fad579bf8 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -306,7 +306,7 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg } } - Node* new_case = basic_block(a, shd_nodes(a, inferred_arg_type.count, nparams), get_abstraction_name_unsafe(node)); + Node* new_case = basic_block(a, shd_nodes(a, inferred_arg_type.count, nparams), shd_get_abstraction_name_unsafe(node)); shd_register_processed(r, node, new_case); set_abstraction_body(new_case, infer(&body_context, node->payload.basic_block.body, NULL)); return new_case; @@ -605,12 +605,12 @@ static const Node* process(Context* src_ctx, const Node* node) { } Module* slim_pass_infer(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); assert(!aconfig.check_types); aconfig.check_types = true; aconfig.allow_fold = true; // TODO was moved here because a refactor, does this cause issues ? IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/frontend/slim/normalize.c b/src/frontend/slim/normalize.c index 460121052..1d8b8b76d 100644 --- a/src/frontend/slim/normalize.c +++ b/src/frontend/slim/normalize.c @@ -111,10 +111,10 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* slim_pass_normalize(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.check_op_classes = true; IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_op_rewriter(src, dst, (RewriteOpFn) process_op), }; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 48df6bb9a..0c9e53cbb 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -316,7 +316,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { } else if (strcmp(id, "debug_printf") == 0) { Nodes ops = expect_operands(ctx, bb); return bind_instruction_single(bb, debug_printf(arena, (DebugPrintf) { - .string = get_string_literal(arena, shd_first(ops)), + .string = shd_get_string_literal(arena, shd_first(ops)), .args = shd_nodes(arena, ops.count - 1, &ops.nodes[1]), .mem = bb_mem(bb), })); @@ -599,7 +599,7 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { if (expr->tag == IntLiteral_TAG) { return int_literal(arena, (IntLiteral) { // We always treat that value like an signed integer, because it makes no sense to negate an unsigned number ! - .value = -get_int_literal_value(*resolve_to_int_literal(expr), true) + .value = -shd_get_int_literal_value(*shd_resolve_to_int_literal(expr), true) }); } else { return bind_instruction_single(bb, prim_op(arena, (PrimOp) { @@ -751,14 +751,14 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { const Node* (*merge)(const Node*) = config->front_end ? make_selection_merge : NULL; Node* true_case = case_(arena, shd_nodes(arena, 0, NULL)); - set_abstraction_body(true_case, expect_body(ctx, get_abstraction_mem(true_case), merge)); + set_abstraction_body(true_case, expect_body(ctx, shd_get_abstraction_mem(true_case), merge)); // else defaults to an empty body bool has_else = accept_token(ctx, else_tok); Node* false_case = NULL; if (has_else) { false_case = case_(arena, shd_nodes(arena, 0, NULL)); - set_abstraction_body(false_case, expect_body(ctx, get_abstraction_mem(false_case), merge)); + set_abstraction_body(false_case, expect_body(ctx, shd_get_abstraction_mem(false_case), merge)); } return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, true_case, false_case)); } @@ -771,7 +771,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { // by default loops continue forever const Node* (*default_loop_end_behaviour)(const Node*) = config->front_end ? make_loop_continue : NULL; Node* loop_case = case_(arena, parameters); - set_abstraction_body(loop_case, expect_body(ctx, get_abstraction_mem(loop_case), default_loop_end_behaviour)); + set_abstraction_body(loop_case, expect_body(ctx, shd_get_abstraction_mem(loop_case), default_loop_end_behaviour)); return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, loop_case)); } case control_tok: { @@ -785,7 +785,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { }), str); expect(accept_token(ctx, rpar_tok), "')'"); Node* control_case = case_(arena, shd_singleton(jp)); - set_abstraction_body(control_case, expect_body(ctx, get_abstraction_mem(control_case), NULL)); + set_abstraction_body(control_case, expect_body(ctx, shd_get_abstraction_mem(control_case), NULL)); return maybe_tuple_helper(arena, gen_control(bb, yield_types, control_case)); } default: break; @@ -1012,7 +1012,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t } Node* terminator_case = case_(arena, shd_empty(arena)); - BodyBuilder* terminator_bb = begin_body_with_mem(arena, get_abstraction_mem(terminator_case)); + BodyBuilder* terminator_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(terminator_case)); const Node* terminator = accept_terminator(ctx, terminator_bb); if (terminator) @@ -1028,7 +1028,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t set_abstraction_body(terminator_case, finish_body(terminator_bb, terminator)); Node* cont_wrapper_case = case_(arena, shd_empty(arena)); - BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(cont_wrapper_case)); + BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(cont_wrapper_case)); Nodes ids = shd_empty(arena); Nodes conts = shd_empty(arena); @@ -1041,7 +1041,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t Nodes parameters; expect_parameters(ctx, ¶meters, NULL, bb); Node* continuation = basic_block(arena, parameters, name); - set_abstraction_body(continuation, expect_body(ctx, get_abstraction_mem(continuation), NULL)); + set_abstraction_body(continuation, expect_body(ctx, shd_get_abstraction_mem(continuation), NULL)); ids = shd_nodes_append(arena, ids, string_lit_helper(arena, name)); conts = shd_nodes_append(arena, conts, continuation); } @@ -1149,7 +1149,7 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { Node* fn = function(mod, parameters, name, annotations, types); if (!accept_token(ctx, semi_tok)) - set_abstraction_body(fn, expect_body(ctx, get_abstraction_mem(fn), types.count == 0 ? make_return_void : NULL)); + set_abstraction_body(fn, expect_body(ctx, shd_get_abstraction_mem(fn), types.count == 0 ? make_return_void : NULL)); return fn; } @@ -1234,7 +1234,7 @@ static const Node* accept_nominal_type_decl(ctxparams, Nodes annotations) { } void slim_parse_string(const SlimParserConfig* config, const char* contents, Module* mod) { - IrArena* arena = get_module_arena(mod); + IrArena* arena = shd_module_get_arena(mod); Tokenizer* tokenizer = shd_new_tokenizer(contents); while (true) { diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index 92752e2e6..4bdd559a6 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -24,7 +24,7 @@ Module* shd_parse_slim_module(const CompilerConfig* config, const SlimParserConf aconfig.validate_builtin_types = false; aconfig.allow_fold = false; IrArena* initial_arena = shd_new_ir_arena(&aconfig); - Module* m = new_module(initial_arena, name); + Module* m = shd_new_module(initial_arena, name); slim_parse_string(pconfig, contents, m); Module** pmod = &m; Module* old_mod = NULL; diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index e3f044376..cc9d18223 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -196,7 +196,7 @@ bool parse_spv_header(SpvParser* parser) { String decode_spv_string_literal(SpvParser* parser, uint32_t* at) { // TODO: assumes little endian - return string(get_module_arena(parser->mod), (const char*) at); + return string(shd_module_get_arena(parser->mod), (const char*) at); } AddressSpace convert_storage_class(SpvStorageClass class) { @@ -901,7 +901,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { Node* block = basic_block(parser->arena, params, bb_name); parser->defs[result].node = block; - BodyBuilder* bb = begin_body_with_mem(parser->arena, get_abstraction_mem(block)); + BodyBuilder* bb = begin_body_with_mem(parser->arena, shd_get_abstraction_mem(block)); parser->current_block.builder = bb; parser->current_block.finished = NULL; while (parser->current_block.builder) { @@ -1122,7 +1122,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { if (callee->tag == Function_TAG) { const Node* fn = callee; //callee->payload.fn_addr.fn; - String fn_name = get_abstraction_name(fn); + String fn_name = shd_get_abstraction_name(fn); if (shd_string_starts_with(fn_name, "__shady")) { char* copy = malloc(strlen(fn_name) + 1); memcpy(copy, fn_name, strlen(fn_name) + 1); @@ -1347,14 +1347,14 @@ bool compare_spvid(SpvId* pa, SpvId* pb) { S2SError shd_parse_spirv(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { ArenaConfig aconfig = shd_default_arena_config(&config->target); IrArena* a = shd_new_ir_arena(&aconfig); - *dst = new_module(a, name); + *dst = shd_new_module(a, name); SpvParser parser = { .cursor = 0, .len = len / sizeof(uint32_t), .words = (uint32_t*) data, .mod = *dst, - .arena = get_module_arena(*dst), + .arena = shd_module_get_arena(*dst), .decorations_arena = shd_new_arena(), .phi_arguments = shd_new_dict(SpvId, SpvPhiArgs*, (HashFn) hash_spvid, (CmpFn) compare_spvid), diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index 5cbb5ed9c..0641b826f 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -32,7 +32,7 @@ Program* load_program(Runtime* runtime, const CompilerConfig* base_config, const } Program* program = new_program_from_module(runtime, base_config, module); - program->arena = get_module_arena(module); + program->arena = shd_module_get_arena(module); return program; } @@ -45,7 +45,7 @@ Program* load_program_from_disk(Runtime* runtime, const CompilerConfig* base_con } Program* program = new_program_from_module(runtime, base_config, module); - program->arena = get_module_arena(module); + program->arena = shd_module_get_arena(module); return program; } diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 1ca797c0e..29aad2219 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -56,7 +56,7 @@ int main(int argc, char* argv[]) { "runtime_test", &module); program = new_program_from_module(runtime, &args.driver_config.config, module); } else { - Module* module = new_module(arena, "my_module"); + Module* module = shd_new_module(arena, "my_module"); int err = shd_driver_load_source_files(&args.driver_config, module); if (err) return err; diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index f4c196c2e..5f3320a5b 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -89,7 +89,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay Growy* bindings_lists[MAX_DESCRIPTOR_SETS] = { 0 }; Growy* resources = shd_new_growy(); - Nodes decls = get_module_declarations(program->specialized_module); + Nodes decls = shd_module_get_declarations(program->specialized_module); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag != GlobalVariable_TAG) continue; @@ -102,8 +102,8 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay default: continue; } - int set = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "DescriptorSet"))), false); - int binding = get_int_literal_value(*resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "DescriptorBinding"))), false); + int set = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "DescriptorSet"))), false); + int binding = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "DescriptorBinding"))), false); ProgramResourceInfo* res_info = shd_arena_alloc(program->arena, sizeof(ProgramResourceInfo)); *res_info = (ProgramResourceInfo) { @@ -122,7 +122,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay const Type* member_t = struct_t->payload.record_type.members.nodes[j]; assert(member_t->tag == PtrType_TAG); member_t = get_pointee_type(member_t->arena, member_t); - TypeMemLayout layout = shd_get_mem_layout(get_module_arena(program->specialized_module), member_t); + TypeMemLayout layout = shd_get_mem_layout(shd_module_get_arena(program->specialized_module), member_t); ProgramResourceInfo* constant_res_info = shd_arena_alloc(program->arena, sizeof(ProgramResourceInfo)); *constant_res_info = (ProgramResourceInfo) { @@ -140,7 +140,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay Nodes annotations = get_declaration_annotations(decl); for (size_t k = 0; k < annotations.count; k++) { const Node* a = annotations.nodes[k]; - if ((strcmp(get_annotation_name(a), "InitialValue") == 0) && resolve_to_int_literal(shd_first(shd_get_annotation_values(a)))->value == j) { + if ((strcmp(get_annotation_name(a), "InitialValue") == 0) && shd_resolve_to_int_literal(shd_first(shd_get_annotation_values(a)))->value == j) { constant_res_info->default_data = calloc(1, layout.size_in_bytes); write_value(constant_res_info->default_data, shd_get_annotation_values(a).nodes[1]); //printf("wowie"); @@ -275,7 +275,7 @@ static CompilerConfig get_compiler_config_for_device(VkrDevice* device, const Co } static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) { - Nodes decls = get_module_declarations(mod); + Nodes decls = shd_module_get_declarations(mod); const Node* args_struct_annotation; const Node* args_struct_type = NULL; @@ -352,7 +352,7 @@ static bool extract_parameters_info(ProgramParamsInfo* parameters, Module* mod) return false; } - IrArena* a = get_module_arena(mod); + IrArena* a = shd_module_get_arena(mod); LARRAY(FieldLayout, fields, num_args); shd_get_record_layout(a, args_struct_type, fields); @@ -391,7 +391,7 @@ static bool compile_specialized_program(VkrSpecProgram* spec) { spec->specialized_module = final_mod; if (spec->key.base->runtime->config.dump_spv) { - String module_name = get_module_name(spec->specialized_module); + String module_name = shd_module_get_name(spec->specialized_module); String file_name = shd_format_string_new("%s.spv", module_name); shd_write_file(file_name, spec->spirv_size, (const char*) spec->spirv_bytes); free((void*) file_name); @@ -513,8 +513,8 @@ void destroy_specialized_program(VkrSpecProgram* spec) { vkDestroyShaderModule(spec->device->device, spec->shader_module, NULL); free( (void*) spec->parameters.arg_offset); free(spec->spirv_bytes); - if (get_module_arena(spec->specialized_module) != get_module_arena(spec->key.base->module)) - shd_destroy_ir_arena(get_module_arena(spec->specialized_module)); + if (shd_module_get_arena(spec->specialized_module) != shd_module_get_arena(spec->key.base->module)) + shd_destroy_ir_arena(shd_module_get_arena(spec->specialized_module)); for (size_t i = 0; i < spec->resources.num_resources; i++) { ProgramResourceInfo* resource = spec->resources.resources[i]; if (resource->buffer) diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index 6798e42c2..0a62690ae 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -202,13 +202,13 @@ CallGraph* new_callgraph(Module* mod) { const UsesMap* uses = create_module_uses_map(mod, NcType); - Nodes decls = get_module_declarations(mod); + Nodes decls = shd_module_get_declarations(mod); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag == Function_TAG) { CGNode* node = analyze_fn(graph, decl); - const Use* use = get_first_use(uses, fn_addr_helper(get_module_arena(mod), decl)); + const Use* use = get_first_use(uses, fn_addr_helper(shd_module_get_arena(mod), decl)); for (;use;use = use->next_use) { if (use->user->tag == Call_TAG && strcmp(use->operand_name, "callee") == 0) continue; diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index f3014de0c..6f95fa507 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -17,7 +17,7 @@ struct List* build_cfgs(Module* mod, CFGBuildConfig config) { struct List* cfgs = shd_new_list(CFG*); - Nodes decls = get_module_declarations(mod); + Nodes decls = shd_module_get_declarations(mod); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag != Function_TAG) continue; @@ -344,15 +344,15 @@ static void validate_cfg(CFG* cfg) { if (node != cfg->entry /* this exception exists since we might build CFGs rooted in cases */) { if (structured_body_uses > 0) { if (structured_body_uses > 1) { - shd_error_print("Basic block %s is used as a structural target more than once (structured_body_uses: %zu)", get_abstraction_name_safe(node->node), structured_body_uses); + shd_error_print("Basic block %s is used as a structural target more than once (structured_body_uses: %zu)", shd_get_abstraction_name_safe(node->node), structured_body_uses); shd_error_die(); } if (num_jumps > 0) { - shd_error_print("Basic block %s is used as structural target, but is also jumped into (num_jumps: %zu)", get_abstraction_name_safe(node->node), num_jumps); + shd_error_print("Basic block %s is used as structural target, but is also jumped into (num_jumps: %zu)", shd_get_abstraction_name_safe(node->node), num_jumps); shd_error_die(); } if (!is_tail && num_exits > 0) { - shd_error_print("Basic block %s is not a merge target yet is used as once (num_exits: %zu)", get_abstraction_name_safe(node->node), num_exits); + shd_error_print("Basic block %s is not a merge target yet is used as once (num_exits: %zu)", shd_get_abstraction_name_safe(node->node), num_exits); shd_error_die(); } } diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index ba5c590d6..220cae796 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -67,7 +67,7 @@ static void dump_cf_node(FILE* output, const CFNode* n) { Growy* g = shd_new_growy(); Printer* p = shd_new_printer_from_growy(g); - String abs_name = get_abstraction_name_safe(bb); + String abs_name = shd_get_abstraction_name_safe(bb); shd_print(p, "%s: \n%d: ", abs_name, bb->id); @@ -84,7 +84,7 @@ static void dump_cf_node(FILE* output, const CFNode* n) { print_node_helper(p, body); shd_print(p, "\\l"); } - shd_print(p, "rpo: %d, idom: %s, sdom: %s", n->rpo_index, n->idom ? get_abstraction_name_safe(n->idom->node) : "null", n->structured_idom ? get_abstraction_name_safe(n->structured_idom->node) : "null"); + shd_print(p, "rpo: %d, idom: %s, sdom: %s", n->rpo_index, n->idom ? shd_get_abstraction_name_safe(n->idom->node) : "null", n->structured_idom ? shd_get_abstraction_name_safe(n->structured_idom->node) : "null"); String label = shd_printer_growy_unwrap(p); fprintf(output, "bb_%zu [nojustify=true, label=\"%s\", color=\"%s\", shape=box];\n", (size_t) n, label, color); @@ -102,7 +102,7 @@ static void dump_cfg(FILE* output, CFG* cfg) { const Node* entry = cfg->entry->node; fprintf(output, "subgraph cluster_%d {\n", entry->id); - fprintf(output, "label = \"%s\";\n", get_abstraction_name_safe(entry)); + fprintf(output, "label = \"%s\";\n", shd_get_abstraction_name_safe(entry)); for (size_t i = 0; i < shd_list_count(cfg->contents); i++) { const CFNode* n = shd_read_list(const CFNode*, cfg->contents)[i]; dump_cf_node(output, n); @@ -170,7 +170,7 @@ void dump_cfgs_auto(Module* mod) { } static void dump_domtree_cfnode(Printer* p, CFNode* idom) { - String name = get_abstraction_name_safe(idom->node); + String name = shd_get_abstraction_name_safe(idom->node); if (name) shd_print(p, "bb_%zu [label=\"%s\", shape=box];\n", (size_t) idom, name); else @@ -184,7 +184,7 @@ static void dump_domtree_cfnode(Printer* p, CFNode* idom) { } void dump_domtree_cfg(Printer* p, CFG* s) { - shd_print(p, "subgraph cluster_%s {\n", get_abstraction_name_safe(s->entry->node)); + shd_print(p, "subgraph cluster_%s {\n", shd_get_abstraction_name_safe(s->entry->node)); dump_domtree_cfnode(p, s->entry); shd_print(p, "}\n"); } diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index 1bc2627b9..6a3ddff74 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -259,7 +259,7 @@ static void dump_lt_node(FILE* f, const LTNode* n) { for (size_t i = 0; i < shd_list_count(n->cf_nodes); i++) { const Node* bb = shd_read_list(const CFNode*, n->cf_nodes)[i]->node; - fprintf(f, "bb_%d[label=\"%s\"];\n", extra_uniqueness++, get_abstraction_name_safe(bb)); + fprintf(f, "bb_%d[label=\"%s\"];\n", extra_uniqueness++, shd_get_abstraction_name_safe(bb)); } for (size_t i = 0; i < shd_list_count(n->lf_children); i++) { diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index bbf93496a..235fe8391 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -79,7 +79,7 @@ static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeCl if (root) uses_visit_node(&v, root); if (m) { - Nodes nodes = get_module_declarations(m); + Nodes nodes = shd_module_get_declarations(m); for (size_t i = 0; i < nodes.count; i++) uses_visit_node(&v, nodes.nodes[i]); } diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 0aabd064c..1db4cd349 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -30,7 +30,7 @@ KeyHash shd_hash_node(const Node**); bool shd_compare_node(const Node**, const Node**); static void verify_same_arena(Module* mod) { - const IrArena* arena = get_module_arena(mod); + const IrArena* arena = shd_module_get_arena(mod); ArenaVerifyVisitor visitor = { .visitor = { .visit_node_fn = (VisitNodeFn) visit_verify_same_arena, @@ -151,7 +151,7 @@ static void verify_bodies(const CompilerConfig* config, Module* mod) { } shd_destroy_list(cfgs); - Nodes decls = get_module_declarations(mod); + Nodes decls = shd_module_get_declarations(mod); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; verify_nominal_node(NULL, decl); @@ -162,7 +162,7 @@ void verify_module(const CompilerConfig* config, Module* mod) { verify_same_arena(mod); // before we normalize the IR, scopes are broken because decls appear where they should not // TODO add a normalized flag to the IR and check grammar is adhered to strictly - if (get_module_arena(mod)->config.check_types) { + if (shd_module_get_arena(mod)->config.check_types) { verify_scoping(config, mod); verify_bodies(config, mod); } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index e0557921d..d1a6c41b4 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -34,7 +34,7 @@ BodyBuilder* begin_body_with_mem(IrArena* a, const Node* mem) { BodyBuilder* begin_block_with_side_effects(IrArena* a, const Node* mem) { Node* block = basic_block(a, shd_empty(a), NULL); - BodyBuilder* builder = begin_body_with_mem(a, get_abstraction_mem(block)); + BodyBuilder* builder = begin_body_with_mem(a, shd_get_abstraction_mem(block)); builder->tail_block = block; builder->block_entry_block = block; builder->block_entry_mem = mem; @@ -270,7 +270,7 @@ Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constru break; } } - bb->mem = get_abstraction_mem(tail); + bb->mem = shd_get_abstraction_mem(tail); shd_list_append(StackEntry , bb->stack, entry); bb->tail_block = tail; return entry.vars; @@ -341,14 +341,14 @@ begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes assert(arg_types.count == initial_values.count); IrArena* a = bb->arena; begin_control_t outer_control = begin_control(bb, yield_types); - BodyBuilder* outer_control_case_builder = begin_body_with_mem(a, get_abstraction_mem(outer_control.case_)); + BodyBuilder* outer_control_case_builder = begin_body_with_mem(a, shd_get_abstraction_mem(outer_control.case_)); LARRAY(const Node*, params, arg_types.count); for (size_t i = 0; i < arg_types.count; i++) { params[i] = param(a, shd_as_qualified_type(arg_types.nodes[i], false), NULL); } Node* loop_header = case_(a, shd_nodes(a, arg_types.count, params)); set_abstraction_body(outer_control.case_, finish_body_with_jump(outer_control_case_builder, loop_header, initial_values)); - BodyBuilder* loop_header_builder = begin_body_with_mem(a, get_abstraction_mem(loop_header)); + BodyBuilder* loop_header_builder = begin_body_with_mem(a, shd_get_abstraction_mem(loop_header)); begin_control_t inner_control = begin_control(loop_header_builder, arg_types); set_abstraction_body(loop_header, finish_body_with_jump(loop_header_builder, loop_header, inner_control.results)); diff --git a/src/shady/compile.c b/src/shady/compile.c index 457ef0793..57be9d7f8 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -21,7 +21,7 @@ static void add_scheduler_source(const CompilerConfig* config, Module* dst) { Module* builtin_scheduler_mod = shd_parse_slim_module(config, &pconfig, shady_scheduler_src, "builtin_scheduler"); shd_debug_print("Adding builtin scheduler code"); link_module(dst, builtin_scheduler_mod); - shd_destroy_ir_arena(get_module_arena(builtin_scheduler_mod)); + shd_destroy_ir_arena(shd_module_get_arena(builtin_scheduler_mod)); } #ifdef NDEBUG @@ -38,16 +38,16 @@ void shd_run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* ini shd_debugvv_print("After pass %s: \n", pass_name); if (SHADY_RUN_VERIFY) verify_module(config, *pmod); - if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) - shd_destroy_ir_arena(get_module_arena(old_mod)); + if (shd_module_get_arena(old_mod) != shd_module_get_arena(*pmod) && shd_module_get_arena(old_mod) != initial_arena) + shd_destroy_ir_arena(shd_module_get_arena(old_mod)); old_mod = *pmod; if (config->optimisations.cleanup.after_every_pass) *pmod = cleanup(config, *pmod); shd_log_module(DEBUGVV, config, *pmod); if (SHADY_RUN_VERIFY) verify_module(config, *pmod); - if (get_module_arena(old_mod) != get_module_arena(*pmod) && get_module_arena(old_mod) != initial_arena) - shd_destroy_ir_arena(get_module_arena(old_mod)); + if (shd_module_get_arena(old_mod) != shd_module_get_arena(*pmod) && shd_module_get_arena(old_mod) != initial_arena) + shd_destroy_ir_arena(shd_module_get_arena(old_mod)); if (config->hooks.after_pass.fn) config->hooks.after_pass.fn(config->hooks.after_pass.uptr, pass_name, *pmod); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index d706f81c2..f6faa25c5 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -30,7 +30,7 @@ Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh) { Node* ptr = &node; Node** found = shd_dict_find_key(Node*, arena->node_set, ptr); // sanity check nominal nodes to be unique, check for duplicates in structural nodes - if (is_nominal(&node)) + if (shd_is_node_nominal(&node)) assert(!found); else if (found) return *found; @@ -108,7 +108,7 @@ Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, N .payload.fun = payload }; Node* fn = _shd_create_node_helper(arena, node, NULL); - register_decl_module(mod, fn); + _shd_module_add_decl(mod, fn); for (size_t i = 0; i < params.count; i++) { Node* param = (Node*) params.nodes[i]; @@ -165,12 +165,12 @@ Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { .payload.constant = cnst }; Node* decl = _shd_create_node_helper(arena, node, NULL); - register_decl_module(mod, decl); + _shd_module_add_decl(mod, decl); return decl; } Node* global_var(Module* mod, Nodes annotations, const Type* type, const char* name, AddressSpace as) { - const Node* existing = get_declaration(mod, name); + const Node* existing = shd_module_get_declaration(mod, name); if (existing) { assert(existing->tag == GlobalVariable_TAG); assert(existing->payload.global_variable.type == type); @@ -196,7 +196,7 @@ Node* global_var(Module* mod, Nodes annotations, const Type* type, const char* n .payload.global_variable = gvar }; Node* decl = _shd_create_node_helper(arena, node, NULL); - register_decl_module(mod, decl); + _shd_module_add_decl(mod, decl); return decl; } @@ -218,7 +218,7 @@ Type* nominal_type(Module* mod, Nodes annotations, String name) { .payload.nom_type = payload }; Node* decl = _shd_create_node_helper(arena, node, NULL); - register_decl_module(mod, decl); + _shd_module_add_decl(mod, decl); return decl; } diff --git a/src/shady/fold.c b/src/shady/fold.c index 1a5664d01..9f76685ef 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -18,15 +18,15 @@ static const Node* quote_single(IrArena* a, const Node* value) { } static bool is_zero(const Node* node) { - const IntLiteral* lit = resolve_to_int_literal(node); - if (lit && get_int_literal_value(*lit, false) == 0) + const IntLiteral* lit = shd_resolve_to_int_literal(node); + if (lit && shd_get_int_literal_value(*lit, false) == 0) return true; return false; } static bool is_one(const Node* node) { - const IntLiteral* lit = resolve_to_int_literal(node); - if (lit && get_int_literal_value(*lit, false) == 1) + const IntLiteral* lit = shd_resolve_to_int_literal(node); + if (lit && shd_get_int_literal_value(*lit, false) == 1) return true; return false; } @@ -46,14 +46,14 @@ static inline const Node* fold_constant_math(const Node* node) { IntSizes int_width; bool is_signed; for (size_t i = 0; i < payload.operands.count; i++) { - int_literals[i] = resolve_to_int_literal(payload.operands.nodes[i]); + int_literals[i] = shd_resolve_to_int_literal(payload.operands.nodes[i]); all_int_literals &= int_literals[i] != NULL; if (int_literals[i]) { int_width = int_literals[i]->width; is_signed = int_literals[i]->is_signed; } - float_literals[i] = resolve_to_float_literal(payload.operands.nodes[i]); + float_literals[i] = shd_resolve_to_float_literal(payload.operands.nodes[i]); if (float_literals[i]) float_width = float_literals[i]->width; all_float_literals &= float_literals[i] != NULL; @@ -61,12 +61,12 @@ static inline const Node* fold_constant_math(const Node* node) { #define UN_OP(primop, op) case primop##_op: \ if (all_int_literals) return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = is_signed, .width = int_width, .value = op int_literals[0]->value})); \ -else if (all_float_literals) return quote_single(arena, shd_fp_literal_helper(arena, float_width, op get_float_literal_value(*float_literals[0]))); \ +else if (all_float_literals) return quote_single(arena, shd_fp_literal_helper(arena, float_width, op shd_get_float_literal_value(*float_literals[0]))); \ else break; #define BIN_OP(primop, op) case primop##_op: \ if (all_int_literals) return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = is_signed, .width = int_width, .value = int_literals[0]->value op int_literals[1]->value })); \ -else if (all_float_literals) return quote_single(arena, shd_fp_literal_helper(arena, float_width, get_float_literal_value(*float_literals[0]) op get_float_literal_value(*float_literals[1]))); \ +else if (all_float_literals) return quote_single(arena, shd_fp_literal_helper(arena, float_width, shd_get_float_literal_value(*float_literals[0]) op shd_get_float_literal_value(*float_literals[1]))); \ break; if (all_int_literals || all_float_literals) { @@ -80,7 +80,7 @@ break; if (all_int_literals) return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = is_signed, .width = int_width, .value = int_literals[0]->value % int_literals[1]->value })); else - return quote_single(arena, shd_fp_literal_helper(arena, float_width, fmod(get_float_literal_value(*float_literals[0]), get_float_literal_value(*float_literals[1])))); + return quote_single(arena, shd_fp_literal_helper(arena, float_width, fmod(shd_get_float_literal_value(*float_literals[0]), shd_get_float_literal_value(*float_literals[1])))); case reinterpret_op: { const Type* dst_t = shd_first(payload.type_arguments); uint64_t raw_value = int_literals[0] ? int_literals[0]->value : float_literals[0]->value; @@ -100,21 +100,21 @@ break; bitmask = ~(UINT64_MAX << get_type_bitwidth(dst_t)); if (dst_t->tag == Int_TAG) { if (all_int_literals) { - uint64_t old_value = get_int_literal_value(*int_literals[0], int_literals[0]->is_signed); + uint64_t old_value = shd_get_int_literal_value(*int_literals[0], int_literals[0]->is_signed); uint64_t value = old_value & bitmask; return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = dst_t->payload.int_type.is_signed, .width = dst_t->payload.int_type.width, .value = value })); } else if (all_float_literals) { - double old_value = get_float_literal_value(*float_literals[0]); + double old_value = shd_get_float_literal_value(*float_literals[0]); int64_t value = old_value; return quote_single(arena, int_literal(arena, (IntLiteral) { .is_signed = dst_t->payload.int_type.is_signed, .width = dst_t->payload.int_type.width, .value = value })); } } else if (dst_t->tag == Float_TAG) { if (all_int_literals) { - uint64_t old_value = get_int_literal_value(*int_literals[0], int_literals[0]->is_signed); + uint64_t old_value = shd_get_int_literal_value(*int_literals[0], int_literals[0]->is_signed); double value = old_value; return quote_single(arena, shd_fp_literal_helper(arena, dst_t->payload.float_type.width, value)); } else if (all_float_literals) { - double old_value = get_float_literal_value(*float_literals[0]); + double old_value = shd_get_float_literal_value(*float_literals[0]); return quote_single(arena, float_literal(arena, (FloatLiteral) { .width = dst_t->payload.float_type.width, .value = old_value })); } } diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 1c6f00a04..d1f49ae22 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -113,7 +113,7 @@ static void generate_node_payload_cmp_fn(Growy* g, json_object* src, json_object } static void generate_node_is_nominal(Growy* g, json_object* nodes) { - shd_growy_append_formatted(g, "bool is_nominal(const Node* node) {\n"); + shd_growy_append_formatted(g, "bool shd_is_node_nominal(const Node* node) {\n"); shd_growy_append_formatted(g, "\tswitch (node->tag) { \n"); assert(json_object_get_type(nodes) == json_type_array); for (size_t i = 0; i < json_object_array_length(nodes); i++) { diff --git a/src/shady/ir.c b/src/shady/ir.c index 7bdd348ba..05e5bb55d 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -47,7 +47,7 @@ const Node* shd_get_node_by_id(const IrArena* a, NodeId id) { void shd_destroy_ir_arena(IrArena* arena) { for (size_t i = 0; i < shd_list_count(arena->modules); i++) { - destroy_module(shd_read_list(Module*, arena->modules)[i]); + shd_destroy_module(shd_read_list(Module*, arena->modules)[i]); } shd_destroy_list(arena->modules); diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index 865989c56..3e4776b99 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -31,8 +31,8 @@ struct Module_ { bool sealed; }; -void register_decl_module(Module*, Node*); -void destroy_module(Module* m); +void _shd_module_add_decl(Module* m, Node* node); +void shd_destroy_module(Module* m); struct BodyBuilder_ { IrArena* arena; diff --git a/src/shady/module.c b/src/shady/module.c index 680d85d0e..b762ff1cd 100644 --- a/src/shady/module.c +++ b/src/shady/module.c @@ -5,7 +5,7 @@ #include -Module* new_module(IrArena* arena, String name) { +Module* shd_new_module(IrArena* arena, String name) { Module* m = shd_arena_alloc(arena->arena, sizeof(Module)); *m = (Module) { .arena = arena, @@ -16,28 +16,28 @@ Module* new_module(IrArena* arena, String name) { return m; } -IrArena* get_module_arena(const Module* m) { +IrArena* shd_module_get_arena(const Module* m) { return m->arena; } -String get_module_name(const Module* m) { +String shd_module_get_name(const Module* m) { return m->name; } -Nodes get_module_declarations(const Module* m) { +Nodes shd_module_get_declarations(const Module* m) { size_t count = shd_list_count(m->decls); const Node** start = shd_read_list(const Node*, m->decls); - return shd_nodes(get_module_arena(m), count, start); + return shd_nodes(shd_module_get_arena(m), count, start); } -void register_decl_module(Module* m, Node* node) { +void _shd_module_add_decl(Module* m, Node* node) { assert(is_declaration(node)); - assert(!get_declaration(m, get_declaration_name(node)) && "duplicate declaration"); + assert(!shd_module_get_declaration(m, get_declaration_name(node)) && "duplicate declaration"); shd_list_append(Node*, m->decls, node); } -Node* get_declaration(const Module* m, String name) { - Nodes existing_decls = get_module_declarations(m); +Node* shd_module_get_declaration(const Module* m, String name) { + Nodes existing_decls = shd_module_get_declarations(m); for (size_t i = 0; i < existing_decls.count; i++) { if (strcmp(get_declaration_name(existing_decls.nodes[i]), name) == 0) return (Node*) existing_decls.nodes[i]; @@ -45,6 +45,6 @@ Node* get_declaration(const Module* m, String name) { return NULL; } -void destroy_module(Module* m) { +void shd_destroy_module(Module* m) { shd_destroy_list(m->decls); } diff --git a/src/shady/node.c b/src/shady/node.c index df6022acd..0523ac4c7 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -8,15 +8,15 @@ #include #include -String get_value_name_unsafe(const Node* v) { +String shd_get_value_name_unsafe(const Node* v) { assert(v && is_value(v)); if (v->tag == Param_TAG) return v->payload.param.name; return NULL; } -String get_value_name_safe(const Node* v) { - String name = get_value_name_unsafe(v); +String shd_get_value_name_safe(const Node* v) { + String name = shd_get_value_name_unsafe(v); if (name && strlen(name) > 0) return name; //if (v->tag == Variable_TAG) @@ -24,13 +24,13 @@ String get_value_name_safe(const Node* v) { //return node_tags[v->tag]; } -void set_value_name(const Node* var, String name) { +void shd_set_value_name(const Node* var, String name) { // TODO: annotations // if (var->tag == Variablez_TAG) // var->payload.varz.name = string(var->arena, name); } -int64_t get_int_literal_value(IntLiteral literal, bool sign_extend) { +int64_t shd_get_int_literal_value(IntLiteral literal, bool sign_extend) { if (sign_extend) { switch (literal.width) { case IntTy8: return (int64_t) (int8_t) (literal.value & 0xFF); @@ -51,7 +51,7 @@ int64_t get_int_literal_value(IntLiteral literal, bool sign_extend) { } static_assert(sizeof(float) == sizeof(uint64_t) / 2, "floats aren't the size we expect"); -double get_float_literal_value(FloatLiteral literal) { +double shd_get_float_literal_value(FloatLiteral literal) { double r; switch (literal.width) { case FloatTy16: @@ -73,15 +73,15 @@ double get_float_literal_value(FloatLiteral literal) { } static bool is_zero(const Node* node) { - const IntLiteral* lit = resolve_to_int_literal(node); - if (lit && get_int_literal_value(*lit, false) == 0) + const IntLiteral* lit = shd_resolve_to_int_literal(node); + if (lit && shd_get_int_literal_value(*lit, false) == 0) return true; return false; } -const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { +const Node* shd_chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { while (true) { - ptr = resolve_node_to_definition(ptr, config); + ptr = shd_resolve_node_to_definition(ptr, config); switch (ptr->tag) { case PtrArrayElementOffset_TAG: break; case PtrCompositeElement_TAG: { @@ -121,9 +121,9 @@ const Node* chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { return ptr; } -const Node* resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config) { +const Node* shd_resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config) { while (ptr) { - ptr = resolve_node_to_definition(ptr, config); + ptr = shd_resolve_node_to_definition(ptr, config); switch (ptr->tag) { case PrimOp_TAG: { switch (ptr->payload.prim_op.op) { @@ -145,7 +145,7 @@ const Node* resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config) { return NULL; } -NodeResolveConfig default_node_resolve_config(void) { +NodeResolveConfig shd_default_node_resolve_config(void) { return (NodeResolveConfig) { .enter_loads = true, .allow_incompatible_types = false, @@ -153,7 +153,7 @@ NodeResolveConfig default_node_resolve_config(void) { }; } -const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig config) { +const Node* shd_resolve_node_to_definition(const Node* node, NodeResolveConfig config) { while (node) { switch (node->tag) { case Constant_TAG: @@ -165,7 +165,7 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi case Load_TAG: { if (config.enter_loads) { const Node* source = node->payload.load.ptr; - const Node* result = resolve_ptr_to_value(source, config); + const Node* result = shd_resolve_ptr_to_value(source, config); if (!result) break; node = result; @@ -192,8 +192,8 @@ const Node* resolve_node_to_definition(const Node* node, NodeResolveConfig confi return node; } -const IntLiteral* resolve_to_int_literal(const Node* node) { - node = resolve_node_to_definition(node, default_node_resolve_config()); +const IntLiteral* shd_resolve_to_int_literal(const Node* node) { + node = shd_resolve_node_to_definition(node, shd_default_node_resolve_config()); if (!node) return NULL; if (node->tag == IntLiteral_TAG) @@ -201,8 +201,8 @@ const IntLiteral* resolve_to_int_literal(const Node* node) { return NULL; } -const FloatLiteral* resolve_to_float_literal(const Node* node) { - node = resolve_node_to_definition(node, default_node_resolve_config()); +const FloatLiteral* shd_resolve_to_float_literal(const Node* node) { + node = shd_resolve_node_to_definition(node, shd_default_node_resolve_config()); if (!node) return NULL; if (node->tag == FloatLiteral_TAG) @@ -210,30 +210,30 @@ const FloatLiteral* resolve_to_float_literal(const Node* node) { return NULL; } -const char* get_string_literal(IrArena* arena, const Node* node) { +const char* shd_get_string_literal(IrArena* arena, const Node* node) { if (!node) return NULL; if (node->type && get_unqualified_type(node->type)->tag == PtrType_TAG) { - NodeResolveConfig nrc = default_node_resolve_config(); - const Node* ptr = chase_ptr_to_source(node, nrc); - const Node* value = resolve_ptr_to_value(ptr, nrc); + NodeResolveConfig nrc = shd_default_node_resolve_config(); + const Node* ptr = shd_chase_ptr_to_source(node, nrc); + const Node* value = shd_resolve_ptr_to_value(ptr, nrc); if (value) - return get_string_literal(arena, value); + return shd_get_string_literal(arena, value); } switch (node->tag) { case Declaration_GlobalVariable_TAG: { const Node* init = node->payload.global_variable.init; if (init) { - return get_string_literal(arena, init); + return shd_get_string_literal(arena, init); } break; } case Declaration_Constant_TAG: { - return get_string_literal(arena, node->payload.constant.value); + return shd_get_string_literal(arena, node->payload.constant.value); } case RefDecl_TAG: { const Node* decl = node->payload.ref_decl.decl; - return get_string_literal(arena, decl); + return shd_get_string_literal(arena, decl); } /*case Lea_TAG: { Lea lea = node->payload.lea; @@ -255,7 +255,7 @@ const char* get_string_literal(IrArena* arena, const Node* node) { for (size_t i = 0; i < contents.count; i++) { const Node* value = contents.nodes[i]; assert(value->tag == IntLiteral_TAG && value->payload.int_literal.width == IntTy8); - chars[i] = (unsigned char) get_int_literal_value(*resolve_to_int_literal(value), false); + chars[i] = (unsigned char) shd_get_int_literal_value(*shd_resolve_to_int_literal(value), false); } assert(chars[contents.count - 1] == 0); return string(arena, chars); @@ -265,11 +265,11 @@ const char* get_string_literal(IrArena* arena, const Node* node) { return NULL; } -const Node* get_abstraction_mem(const Node* abs) { +const Node* shd_get_abstraction_mem(const Node* abs) { return abs_mem(abs->arena, (AbsMem) { .abs = abs }); } -String get_abstraction_name(const Node* abs) { +String shd_get_abstraction_name(const Node* abs) { assert(is_abstraction(abs)); switch (abs->tag) { case Function_TAG: return abs->payload.fun.name; @@ -278,7 +278,7 @@ String get_abstraction_name(const Node* abs) { } } -String get_abstraction_name_unsafe(const Node* abs) { +String shd_get_abstraction_name_unsafe(const Node* abs) { assert(is_abstraction(abs)); switch (abs->tag) { case Function_TAG: return abs->payload.fun.name; @@ -287,8 +287,8 @@ String get_abstraction_name_unsafe(const Node* abs) { } } -String get_abstraction_name_safe(const Node* abs) { - String name = get_abstraction_name_unsafe(abs); +String shd_get_abstraction_name_safe(const Node* abs) { + String name = shd_get_abstraction_name_unsafe(abs); if (name) return name; return shd_fmt_string_irarena(abs->arena, "%%%d", abs->id); @@ -343,7 +343,7 @@ KeyHash shd_hash_node(Node** pnode) { const Node* node = *pnode; KeyHash combined; - if (is_nominal(node)) { + if (shd_is_node_nominal(node)) { size_t ptr = (size_t) node; uint32_t upper = ptr >> 32; uint32_t lower = ptr; @@ -367,7 +367,7 @@ bool _shd_compare_node_payload(const Node*, const Node*); bool shd_compare_node(Node** pa, Node** pb) { if ((*pa)->tag != (*pb)->tag) return false; - if (is_nominal((*pa))) + if (shd_is_node_nominal((*pa))) return *pa == *pb; const Node* a = *pa; diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 8d466a544..32b1ba4b7 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -57,7 +57,7 @@ const Node* process(Context* ctx, const Node* old) { case BasicBlock_TAG: { size_t uses = count_calls(ctx->map, old); if (uses <= 1 && a->config.optimisations.inline_single_use_bbs) { - shd_log_fmt(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", get_abstraction_name_safe(old), uses); + shd_log_fmt(DEBUGVV, "Eliminating basic block '%s' since it's used only %d times.\n", shd_get_abstraction_name_safe(old), uses); *ctx->todo = true; return NULL; } @@ -70,7 +70,7 @@ const Node* process(Context* ctx, const Node* old) { // it's been inlined away! just steal the body Nodes nargs = shd_rewrite_nodes(r, old->payload.jump.args); shd_register_processed_list(r, get_abstraction_params(otarget), nargs); - shd_register_processed(r, get_abstraction_mem(otarget), shd_rewrite_node(r, old->payload.jump.mem)); + shd_register_processed(r, shd_get_abstraction_mem(otarget), shd_rewrite_node(r, old->payload.jump.mem)); return shd_rewrite_node(r, get_abstraction_body(otarget)); } break; @@ -84,7 +84,7 @@ const Node* process(Context* ctx, const Node* old) { Join payload_join = term->payload.join; if (payload_join.join_point == shd_first(get_abstraction_params(control_inside))) { // if we immediately consume the join point and it's never leaked, this control block does nothing and can be eliminated - shd_register_processed(r, get_abstraction_mem(control_inside), shd_rewrite_node(r, payload.mem)); + shd_register_processed(r, shd_get_abstraction_mem(control_inside), shd_rewrite_node(r, payload.mem)); shd_register_processed(r, control_inside, NULL); *ctx->todo = true; return shd_rewrite_node(r, term); @@ -122,8 +122,8 @@ OptPass simplify; bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { Module* src = *m; - IrArena* a = get_module_arena(src); - *m = new_module(a, get_module_name(*m)); + IrArena* a = shd_module_get_arena(src); + *m = shd_new_module(a, shd_module_get_name(*m)); bool todo = false; Context ctx = { .todo = &todo }; ctx.rewriter = shd_create_node_rewriter(src, *m, (RewriteNodeFn) process); @@ -137,7 +137,7 @@ OptPass opt_mem2reg; RewritePass import; Module* cleanup(const CompilerConfig* config, Module* const src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); if (!aconfig.check_types) return src; bool todo; diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index baaeb4f7d..51e364a18 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -34,9 +34,9 @@ static const Node* process(Context* ctx, const Node* node) { } static Module* eliminate_constants_(SHADY_UNUSED const CompilerConfig* config, Module* src, bool all) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .all = all, diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index fe3d1241e..8b0b4b5f5 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -19,7 +19,7 @@ static void replace_or_compare(const Node** dst, const Node* with) { const Node* import_node(Rewriter* r, const Node* node) { if (is_declaration(node)) { - Node* existing = get_declaration(r->dst_module, get_declaration_name(node)); + Node* existing = shd_module_get_declaration(r->dst_module, get_declaration_name(node)); if (existing) { const Node* imported_t = shd_rewrite_node(r, node->type); if (imported_t != existing->type) { @@ -61,9 +61,9 @@ const Node* import_node(Rewriter* r, const Node* node) { } Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) shd_recreate_node), }; diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index 88396743d..c75c5d512 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -43,7 +43,7 @@ static const LTNode* get_loop(const LTNode* n) { static String loop_name(const LTNode* n) { if (n && n->type == LF_HEAD && shd_list_count(n->cf_nodes) > 0) { - return get_abstraction_name(shd_read_list(CFNode*, n->cf_nodes)[0]->node); + return shd_get_abstraction_name(shd_read_list(CFNode*, n->cf_nodes)[0]->node); } return ""; } @@ -88,7 +88,7 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* ctx = &ctx2; if (!ctx->cfg) { - shd_error_print("LCSSA: Trying to process an abstraction that's not part of a function ('%s')!", get_abstraction_name(old)); + shd_error_print("LCSSA: Trying to process an abstraction that's not part of a function ('%s')!", shd_get_abstraction_name(old)); shd_log_module(ERROR, ctx->config, ctx->rewriter.src_module); shd_error_die(); } @@ -110,7 +110,7 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* Nodes nargs; find_liftable_loop_values(ctx, old_children[i], &new_params[i], &lifted_params[i], &nargs); Nodes nparams = shd_recreate_params(&ctx->rewriter, get_abstraction_params(old_children[i])); - new_children[i] = basic_block(a, shd_concat_nodes(a, nparams, new_params[i]), get_abstraction_name(old_children[i])); + new_children[i] = basic_block(a, shd_concat_nodes(a, nparams, new_params[i]), shd_get_abstraction_name(old_children[i])); shd_register_processed(&ctx->rewriter, old_children[i], new_children[i]); shd_register_processed_list(&ctx->rewriter, get_abstraction_params(old_children[i]), nparams); shd_dict_insert(const Node*, Nodes, ctx->lifted_arguments, old_children[i], nargs); @@ -189,9 +189,9 @@ KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); Module* lcssa(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index 43950aa3d..a59b60f6c 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -65,7 +65,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_destroy_dict(frontier); shd_dict_insert(const Node*, Nodes, ctx->lift, node, additional_args); - Node* new_bb = basic_block(a, new_params, get_abstraction_name_unsafe(node)); + Node* new_bb = basic_block(a, new_params, shd_get_abstraction_name_unsafe(node)); Context* fn_ctx = ctx; while (fn_ctx->rewriter.parent) { @@ -100,13 +100,13 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); bool todo = true; Module* dst; while (todo) { todo = false; - dst = new_module(a, get_module_name(src)); + dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .lift = shd_new_dict(const Node*, Nodes, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 66ed7f95a..28133aa0a 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -79,7 +79,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { IrArena* a = ctx->rewriter.dst_arena; const Node* obody = get_abstraction_body(liftee); - String name = get_abstraction_name_safe(liftee); + String name = shd_get_abstraction_name_safe(liftee); Scheduler* scheduler = new_scheduler(cfg); struct Dict* frontier_set = free_frontier(scheduler, cfg, liftee); @@ -95,7 +95,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { Rewriter* r = &lifting_ctx.rewriter; Nodes ovariables = get_abstraction_params(liftee); - shd_debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", get_abstraction_name_safe(liftee), recover_context_size); + shd_debugv_print("lambda_lift: free (to-be-spilled) variables at '%s' (count=%d): ", shd_get_abstraction_name_safe(liftee), recover_context_size); for (size_t i = 0; i < recover_context_size; i++) { const Node* item = frontier.nodes[i]; if (!is_value(item)) { @@ -111,7 +111,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { // Create and register new parameters for the lifted continuation LARRAY(const Node*, new_params_arr, ovariables.count); for (size_t i = 0; i < ovariables.count; i++) - new_params_arr[i] = param(a, shd_rewrite_node(&ctx->rewriter, ovariables.nodes[i]->type), get_value_name_unsafe(ovariables.nodes[i])); + new_params_arr[i] = param(a, shd_rewrite_node(&ctx->rewriter, ovariables.nodes[i]->type), shd_get_value_name_unsafe(ovariables.nodes[i])); Nodes new_params = shd_nodes(a, ovariables.count, new_params_arr); LiftedCont* lifted_cont = calloc(sizeof(LiftedCont), 1); @@ -130,7 +130,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { lifted_cont->lifted_fn = new_fn; // Recover that stuff inside the new body - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); gen_set_stack_size(bb, payload); for (size_t i = recover_context_size - 1; i < recover_context_size; i--) { const Node* ovar = frontier.nodes[i]; @@ -149,7 +149,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { shd_register_processed(r, ovar, recovered_value); } - shd_register_processed(r, get_abstraction_mem(liftee), bb_mem(bb)); + shd_register_processed(r, shd_get_abstraction_mem(liftee), bb_mem(bb)); shd_register_processed(r, liftee, new_fn); const Node* substituted = shd_rewrite_node(r, obody); shd_destroy_rewriter(r); @@ -210,7 +210,7 @@ static const Node* process_node(Context* ctx, const Node* node) { jp = gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(jp)); shd_register_processed(r, shd_first(get_abstraction_params(oinside)), jp); - shd_register_processed(r, get_abstraction_mem(oinside), bb_mem(bb)); + shd_register_processed(r, shd_get_abstraction_mem(oinside), bb_mem(bb)); shd_register_processed(r, oinside, NULL); return finish_body(bb, shd_rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); } @@ -222,7 +222,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = NULL; Module* dst; @@ -231,7 +231,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { shd_debugv_print("lift_indirect_target: round %d\n", round++); IrArena* oa = a; a = shd_new_ir_arena(&aconfig); - dst = new_module(a, get_module_name(src)); + dst = shd_new_module(a, shd_module_get_name(src)); bool todo = false; Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), @@ -262,7 +262,7 @@ Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { // this will be safe now since we won't lift any more code after this pass aconfig.optimisations.weaken_non_leaking_allocas = true; IrArena* a2 = shd_new_ir_arena(&aconfig); - dst = new_module(a2, get_module_name(src)); + dst = shd_new_module(a2, shd_module_get_name(src)); Rewriter r = shd_create_importer(src, dst); shd_rewrite_module(&r); shd_destroy_rewriter(&r); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index db0d69a72..073ff2475 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -89,13 +89,13 @@ static const Node* process(Context* ctx, const Node* node) { return fun; } - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); ctx2.prepared_offsets = shd_new_dict(const Node*, StackSlot, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); ctx2.base_stack_addr_on_entry = gen_get_stack_base_addr(bb); ctx2.stack_size_on_entry = gen_get_stack_size(bb); - set_value_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); + shd_set_value_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); - Node* nom_t = nominal_type(m, shd_empty(a), shd_format_string_arena(a->arena, "%s_stack_frame", get_abstraction_name(node))); + Node* nom_t = nominal_type(m, shd_empty(a), shd_format_string_arena(a->arena, "%s_stack_frame", shd_get_abstraction_name(node))); VContext vctx = { .visitor = { .visit_node_fn = (VisitNodeFn) search_operand_for_alloca, @@ -120,7 +120,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); // make sure to use the new mem from then on - shd_register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); shd_destroy_dict(ctx2.prepared_offsets); @@ -164,9 +164,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 11f25d114..cee0fe3d7 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -36,7 +36,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { Nodes nannots = shd_rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); Node* prelude = case_(a, shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(prelude)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(prelude)); // Supplement an additional parameter for the join point const Type* jp_type = join_point_type(a, (JoinPointType) { @@ -52,12 +52,12 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { ctx2.return_jp = jp_variable; } - Node* fun = function(ctx->rewriter.dst_module, nparams, get_abstraction_name(old), nannots, shd_empty(a)); + Node* fun = function(ctx->rewriter.dst_module, nparams, shd_get_abstraction_name(old), nannots, shd_empty(a)); shd_register_processed(&ctx->rewriter, old, fun); - shd_register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(prelude, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body))); - set_abstraction_body(fun, jump_helper(a, get_abstraction_mem(fun), prelude, shd_empty(a))); + set_abstraction_body(fun, jump_helper(a, shd_get_abstraction_mem(fun), prelude, shd_empty(a))); return fun; } @@ -135,7 +135,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { const Node* control_body = tail_call(a, (TailCall) { .callee = ncallee, .args = nargs, - .mem = get_abstraction_mem(control_case), + .mem = shd_get_abstraction_mem(control_case), }); set_abstraction_body(control_case, control_body); BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); @@ -147,9 +147,9 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { } Module* lower_callf(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) lower_callf_process), .disable_lowering = false, diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index ac79093df..f3b7e4d51 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -63,15 +63,15 @@ static const Node* process_node(Context* ctx, const Node* node) { } else { assert(yield_types.count == 0); false_block = basic_block(a, shd_nodes(a, 0, NULL), unique_name(a, "if_false")); - set_abstraction_body((Node*) false_block, join(a, (Join) { .join_point = jp, .args = shd_nodes(a, 0, NULL), .mem = get_abstraction_mem(false_block) })); + set_abstraction_body((Node*) false_block, join(a, (Join) { .join_point = jp, .args = shd_nodes(a, 0, NULL), .mem = shd_get_abstraction_mem(false_block) })); } Node* control_case = basic_block(a, shd_singleton(jp), NULL); const Node* control_body = branch(a, (Branch) { .condition = shd_rewrite_node(r, node->payload.if_instr.condition), - .true_jump = jump_helper(a, get_abstraction_mem(control_case), true_block, shd_empty(a)), - .false_jump = jump_helper(a, get_abstraction_mem(control_case), false_block, shd_empty(a)), - .mem = get_abstraction_mem(control_case), + .true_jump = jump_helper(a, shd_get_abstraction_mem(control_case), true_block, shd_empty(a)), + .false_jump = jump_helper(a, shd_get_abstraction_mem(control_case), false_block, shd_empty(a)), + .mem = shd_get_abstraction_mem(control_case), }); set_abstraction_body(control_case, control_body); @@ -104,9 +104,9 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes new_params = shd_recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_block)); Node* loop_header_block = basic_block(a, new_params, unique_name(a, "loop_header")); - BodyBuilder* inner_bb = begin_body_with_mem(a, get_abstraction_mem(loop_header_block)); + BodyBuilder* inner_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_header_block)); Node* inner_control_case = case_(a, shd_singleton(continue_point)); - set_abstraction_body(inner_control_case, jump_helper(a, get_abstraction_mem(inner_control_case), + set_abstraction_body(inner_control_case, jump_helper(a, shd_get_abstraction_mem(inner_control_case), shd_rewrite_node(r, old_loop_block), new_params)); Nodes args = gen_control(inner_bb, param_types, inner_control_case); @@ -116,7 +116,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* first_iteration_jump = jump(a, (Jump) { .target = loop_header_block, .args = shd_rewrite_nodes(r, payload.initial_args), - .mem = get_abstraction_mem(outer_control_case), + .mem = shd_get_abstraction_mem(outer_control_case), }); set_abstraction_body(outer_control_case, first_iteration_jump); @@ -235,9 +235,9 @@ KeyHash shd_hash_node(const Node**); bool shd_compare_node(const Node**, const Node**); Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .structured_join_tokens = shd_new_dict(const Node*, Nodes, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index d4b755474..d4f18cd81 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -34,9 +34,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_decay_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index ff8e8c78d..b9569c0bd 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -37,7 +37,7 @@ static const Node* generate_arg_struct_type(Rewriter* rewriter, Nodes params) { shd_error("EntryPoint parameters must be uniform"); types[i] = type; - names[i] = get_value_name_safe(params.nodes[i]); + names[i] = shd_get_value_name_safe(params.nodes[i]); } return record_type(a, (RecordType) { @@ -60,7 +60,7 @@ static const Node* generate_arg_struct(Rewriter* rewriter, const Node* old_entry static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const Node* new, const Node* arg_struct) { IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new)); Nodes params = old_entry_point->payload.fun.params; @@ -70,7 +70,7 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const shd_register_processed(&ctx->rewriter, params.nodes[i], val); } - shd_register_processed(&ctx->rewriter, get_abstraction_mem(old_entry_point), bb_mem(bb)); + shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(old_entry_point), bb_mem(bb)); return finish_body(bb, shd_rewrite_node(&ctx->rewriter, old_entry_point->payload.fun.body)); } @@ -91,9 +91,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_entrypoint_args(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index fdf93aa36..c6bc4c2a4 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -17,7 +17,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Fill_TAG: { const Type* composite_t = shd_rewrite_node(r, node->payload.fill.type); - size_t actual_size = get_int_literal_value(*resolve_to_int_literal(get_fill_type_size(composite_t)), false); + size_t actual_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(get_fill_type_size(composite_t)), false); const Node* value = shd_rewrite_node(r, node->payload.fill.value); LARRAY(const Node*, copies, actual_size); for (size_t i = 0; i < actual_size; i++) { @@ -32,9 +32,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 43d4d2ad1..dfdf70375 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -43,9 +43,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_generic_globals(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 52bd3ef99..7cfdace08 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -108,7 +108,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo size_t max_tag = sizeof(generic_ptr_tags) / sizeof(generic_ptr_tags[0]); switch (which) { case LoadFn: { - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); begin_control_t r = begin_control(bb, shd_singleton(t)); const Node* final_loaded_value = shd_first(r.results); @@ -119,34 +119,34 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { Node* tag_case = case_(a, shd_empty(a)); - set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(tag_case) })); - jumps[tag] = jump_helper(a, get_abstraction_mem(r.case_), tag_case, shd_empty(a)); + set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(tag_case) })); + jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); continue; } Node* tag_case = case_(a, shd_empty(a)); - BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(tag_case)); + BodyBuilder* case_bb = begin_body_with_mem(a, shd_get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_singleton(loaded_value))); - jumps[tag] = jump_helper(a, get_abstraction_mem(r.case_), tag_case, shd_empty(a)); + jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, shd_empty(a)); - set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); + set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); set_abstraction_body(r.case_, br_switch(a, (Switch) { - .mem = get_abstraction_mem(r.case_), + .mem = shd_get_abstraction_mem(r.case_), .switch_value = extracted_tag, .case_values = shd_nodes(a, max_tag, literals), .case_jumps = shd_nodes(a, max_tag, jumps), - .default_jump = jump_helper(a, get_abstraction_mem(r.case_), default_case, shd_empty(a)) + .default_jump = jump_helper(a, shd_get_abstraction_mem(r.case_), default_case, shd_empty(a)) })); set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_singleton(final_loaded_value), .mem = bb_mem(bb) }))); break; } case StoreFn: { - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); begin_control_t r = begin_control(bb, shd_empty(a)); @@ -156,28 +156,28 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { Node* tag_case = case_(a, shd_empty(a)); - set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(tag_case) })); - jumps[tag] = jump_helper(a, get_abstraction_mem(r.case_), tag_case, shd_empty(a)); + set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(tag_case) })); + jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); continue; } Node* tag_case = case_(a, shd_empty(a)); - BodyBuilder* case_bb = begin_body_with_mem(a, get_abstraction_mem(tag_case)); + BodyBuilder* case_bb = begin_body_with_mem(a, shd_get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_empty(a))); - jumps[tag] = jump_helper(a, get_abstraction_mem(r.case_), tag_case, shd_empty(a)); + jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, shd_empty(a)); - set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); + set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); set_abstraction_body(r.case_, br_switch(a, (Switch) { - .mem = get_abstraction_mem(r.case_), + .mem = shd_get_abstraction_mem(r.case_), .switch_value = extracted_tag, .case_values = shd_nodes(a, max_tag, literals), .case_jumps = shd_nodes(a, max_tag, jumps), - .default_jump = jump_helper(a, get_abstraction_mem(r.case_), default_case, shd_empty(a)) + .default_jump = jump_helper(a, shd_get_abstraction_mem(r.case_), default_case, shd_empty(a)) })); set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); break; @@ -274,9 +274,9 @@ KeyHash shd_hash_string(const char** string); bool shd_compare_string(const char** a, const char** b); Module* lower_generic_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .fns = shd_new_dict(String, const Node*, (HashFn) shd_hash_string, (CmpFn) shd_compare_string), diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 6a73db87a..b99a91285 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -80,9 +80,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_int(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 137ef093f..f6ef84203 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -61,7 +61,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po case RecordType_TAG: { Nodes member_types = pointed_type->payload.record_type.members; - const IntLiteral* selector_value = resolve_to_int_literal(index); + const IntLiteral* selector_value = shd_resolve_to_int_literal(index); assert(selector_value && "selector value must be known for LEA into a record"); size_t n = selector_value->value; assert(n < member_types.count); @@ -88,7 +88,7 @@ static const Node* lower_ptr_offset(Context* ctx, BodyBuilder* bb, const Type* p const Node* ptr = base; - const IntLiteral* offset_value = resolve_to_int_literal(offset); + const IntLiteral* offset_value = shd_resolve_to_int_literal(offset); bool offset_is_zero = offset_value && offset_value->value == 0; if (!offset_is_zero) { const Type* element_type = pointer_type->payload.ptr_type.pointed_type; @@ -166,9 +166,9 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_lea(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 65350fe3f..c68093f4c 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -138,12 +138,12 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_logical_pointers(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.address_spaces[AsInput].physical = false; aconfig.address_spaces[AsOutput].physical = false; aconfig.address_spaces[AsUniformConstant].physical = false; IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 17e8d34dc..658be4c25 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -49,10 +49,10 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.specializations.subgroup_mask_representation = SubgroupMaskInt64; IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); const Type* mask_type = get_actual_mask_type(a); assert(mask_type->tag == Int_TAG); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 5f8e21251..ab2c011e5 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -53,17 +53,17 @@ static const Node* process(Context* ctx, const Node* old) { begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); const Node* index = shd_first(l.params); - set_value_name(index, "memcpy_i"); + shd_set_value_name(index, "memcpy_i"); Node* loop_case = l.loop_body; - BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); + BodyBuilder* loop_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_case)); const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, shd_empty(a))); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); - set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); + set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = shd_get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); Node* false_case = case_(a, shd_empty(a)); - set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = get_abstraction_mem(false_case), .args = shd_empty(a) })); + set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = shd_get_abstraction_mem(false_case), .args = shd_empty(a) })); set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { .mem = bb_mem(loop_bb), @@ -100,16 +100,16 @@ static const Node* process(Context* ctx, const Node* old) { begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); const Node* index = shd_first(l.params); - set_value_name(index, "memset_i"); + shd_set_value_name(index, "memset_i"); Node* loop_case = l.loop_body; - BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_case)); + BodyBuilder* loop_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_case)); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); - set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); + set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = shd_get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); Node* false_case = case_(a, shd_empty(a)); - set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = get_abstraction_mem(false_case), .args = shd_empty(a) })); + set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = shd_get_abstraction_mem(false_case), .args = shd_empty(a) })); set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { .mem = bb_mem(loop_bb), @@ -126,9 +126,9 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_memcpy(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process) diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index e5f210bc4..9eb77623b 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -31,7 +31,7 @@ static const Node* process(Context* ctx, const Node* old) { case offset_of_op: { const Type* t = shd_rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.type_arguments)); const Node* n = shd_rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.operands)); - const IntLiteral* literal = resolve_to_int_literal(n); + const IntLiteral* literal = shd_resolve_to_int_literal(n); assert(literal); t = get_maybe_nominal_type_body(t); uint64_t offset_in_bytes = (uint64_t) shd_get_record_field_offset_in_bytes(a, t, literal->value); @@ -49,9 +49,9 @@ static const Node* process(Context* ctx, const Node* old) { } Module* lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process) diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index c98c0aa39..62cad432d 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -49,9 +49,9 @@ KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .map = shd_new_dict(const Node*, Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index ba2c0cdaf..cc636234f 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -127,7 +127,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type shd_log_node(ERROR, element_type); shd_error_print(" is not known a compile-time!\n"); } - size_t components_count = get_int_literal_value(*resolve_to_int_literal(size), 0); + size_t components_count = shd_get_int_literal_value(*shd_resolve_to_int_literal(size), 0); const Type* component_type = get_fill_type_element_type(element_type); LARRAY(const Node*, components, components_count); const Node* offset = address; @@ -231,7 +231,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element shd_log_node(ERROR, element_type); shd_error_print(" is not known a compile-time!\n"); } - size_t components_count = get_int_literal_value(*resolve_to_int_literal(size), 0); + size_t components_count = shd_get_int_literal_value(*shd_resolve_to_int_literal(size), 0); const Type* component_type = get_fill_type_element_type(element_type); const Node* offset = address; for (size_t i = 0; i < components_count; i++) { @@ -273,7 +273,7 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { gen_serialisation(ctx, bb, element_type, base, address_param, value_param); @@ -342,14 +342,14 @@ static const Node* process_node(Context* ctx, const Node* old) { break; } case Function_TAG: { - if (strcmp(get_abstraction_name(old), "generated_init") == 0) { + if (strcmp(shd_get_abstraction_name(old), "generated_init") == 0) { Node* new = shd_recreate_node_head(&ctx->rewriter, old); - BodyBuilder *bb = begin_body_with_mem(a, get_abstraction_mem(new)); + BodyBuilder *bb = begin_body_with_mem(a, shd_get_abstraction_mem(new)); for (AddressSpace as = 0; as < NumAddressSpaces; as++) { if (is_as_emulated(ctx, as)) store_init_data(ctx, as, ctx->collected[as], bb); } - shd_register_processed(&ctx->rewriter, get_abstraction_mem(old), bb_mem(bb)); + shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } @@ -366,7 +366,7 @@ bool shd_compare_node(Node** pa, Node** pb); static Nodes collect_globals(Context* ctx, AddressSpace as) { IrArena* a = ctx->rewriter.dst_arena; - Nodes old_decls = get_module_declarations(ctx->rewriter.src_module); + Nodes old_decls = shd_module_get_declarations(ctx->rewriter.src_module); LARRAY(const Type*, collected, old_decls.count); size_t members_count = 0; @@ -481,13 +481,13 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { } Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.address_spaces[AsPrivate].physical = false; aconfig.address_spaces[AsShared].physical = false; aconfig.address_spaces[AsSubgroup].physical = false; IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 9ded42e7f..39f97aa6c 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -44,7 +44,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); const Node* element_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); element_size = gen_conversion(bb, shd_uint32_type(a), element_size); @@ -93,9 +93,9 @@ static const Node* process_node(Context* ctx, const Node* old) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; - if (old->tag == Function_TAG && strcmp(get_abstraction_name(old), "generated_init") == 0) { + if (old->tag == Function_TAG && strcmp(shd_get_abstraction_name(old), "generated_init") == 0) { Node* new = shd_recreate_node_head(&ctx->rewriter, old); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new)); // Make sure to zero-init the stack pointers // TODO isn't this redundant with thoose things having an initial value already ? @@ -104,7 +104,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* stack_pointer = ctx->stack_pointer; gen_store(bb, stack_pointer, shd_uint32_literal(a, 0)); } - shd_register_processed(r, get_abstraction_mem(old), bb_mem(bb)); + shd_register_processed(r, shd_get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } @@ -175,9 +175,9 @@ KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index c640cdc91..4f99cb314 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -86,7 +86,7 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co static void build_fn_body(Context* ctx, Node* fn, const Node* scope, const Node* param, const Type* t) { IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fn)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fn)); const Node* result = generate(ctx, bb, scope, t, param); if (result) { set_abstraction_body(fn, finish_body(bb, fn_ret(a, (Return) { @@ -109,7 +109,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod if (is_supported_natively(ctx, t)) return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, shd_as_qualified_type(t, true), mk_nodes(a, scope, src)); - if (resolve_to_int_literal(scope)->value != SpvScopeSubgroup) + if (shd_resolve_to_int_literal(scope)->value != SpvScopeSubgroup) shd_error("TODO") Node* fn = NULL; @@ -149,9 +149,9 @@ KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); assert(!config->lower.emulate_subgroup_ops && "TODO"); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 42ea36878..c605805bf 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -25,9 +25,9 @@ static const Node* process(Context* ctx, const Node* node) { functx.rewriter.map = shd_clone_dict(functx.rewriter.map); shd_dict_clear(functx.rewriter.map); shd_register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); - functx.bb = begin_body_with_mem(a, get_abstraction_mem(newfun)); + functx.bb = begin_body_with_mem(a, shd_get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); - shd_register_processed(&functx.rewriter, get_abstraction_mem(node), get_abstraction_mem(post_prelude)); + shd_register_processed(&functx.rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(post_prelude)); set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, shd_empty(a)))); @@ -58,7 +58,7 @@ static const Node* process(Context* ctx, const Node* node) { const Type* ntype = shd_rewrite_node(&ctx->rewriter, node->payload.global_variable.type); const Type* atype = arr_type(a, (ArrType) { .element_type = ntype, - .size = ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, get_declaration(ctx->rewriter.src_module, "SUBGROUPS_PER_WG"))) + .size = ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_module_get_declaration(ctx->rewriter.src_module, "SUBGROUPS_PER_WG"))) }); assert(shd_lookup_annotation(node, "Logical") && "All subgroup variables should be logical by now!"); @@ -88,9 +88,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 335d20482..11c5d5346 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -148,7 +148,7 @@ static const Node* process(Context* ctx, const Node* node) { TreeNode* root = NULL; for (size_t i = 0; i < literals.count; i++) { TreeNode* t = shd_arena_alloc(arena, sizeof(TreeNode)); - t->key = get_int_literal_value(*resolve_to_int_literal(literals.nodes[i]), false); + t->key = shd_get_int_literal_value(*shd_resolve_to_int_literal(literals.nodes[i]), false); t->lam = cases.nodes[i]; root = insert(root, t); } @@ -181,9 +181,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_switch_btree(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index ab9b9f5ad..e35f8fbe6 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -76,7 +76,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { Nodes rewritten_params = shd_recreate_params(&ctx2.rewriter, old->payload.fun.params); Node* new_entry_pt = function(ctx2.rewriter.dst_module, rewritten_params, old->payload.fun.name, shd_rewrite_nodes(&ctx2.rewriter, old->payload.fun.annotations), shd_nodes(a, 0, NULL)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_entry_pt)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_entry_pt)); gen_call(bb, fn_addr_helper(a, ctx->init_fn), shd_empty(a)); gen_call(bb, access_decl(&ctx->rewriter, "builtin_init_scheduler"), shd_empty(a)); @@ -121,11 +121,11 @@ static const Node* process(Context* ctx, const Node* old) { if (ctx2.disable_lowering) { Node* fun = shd_recreate_node_head(&ctx2.rewriter, old); if (old->payload.fun.body) { - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); if (entry_point_annotation) { gen_call(bb, fn_addr_helper(a, ctx2.init_fn), shd_empty(a)); } - shd_register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); } @@ -148,7 +148,7 @@ static const Node* process(Context* ctx, const Node* old) { if (entry_point_annotation) lift_entry_point(ctx, old, fun); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); // Params become stack pops ! for (size_t i = 0; i < old->payload.fun.params.count; i++) { const Node* old_param = old->payload.fun.params.nodes[i]; @@ -158,10 +158,10 @@ static const Node* process(Context* ctx, const Node* old) { if (is_qualified_type_uniform(old_param->type)) popped = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = shd_empty(a), .operands = shd_singleton(popped) }); if (old_param->payload.param.name) - set_value_name((Node*) popped, old_param->payload.param.name); + shd_set_value_name((Node*) popped, old_param->payload.param.name); shd_register_processed(&ctx->rewriter, old_param, popped); } - shd_register_processed(&ctx2.rewriter, get_abstraction_mem(old), bb_mem(bb)); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); destroy_uses_map(ctx2.uses); destroy_cfg(ctx2.cfg); @@ -284,7 +284,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { assert((*ctx->top_dispatcher_fn)->tag == Function_TAG); IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* dispatcher_body_builder = begin_body_with_mem(a, get_abstraction_mem(*ctx->top_dispatcher_fn)); + BodyBuilder* dispatcher_body_builder = begin_body_with_mem(a, shd_get_abstraction_mem(*ctx->top_dispatcher_fn)); bool count_iterations = ctx->config->shader_diagnostics.max_top_iterations > 0; @@ -298,7 +298,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { Node* loop_inside_case = l.loop_body; if (count_iterations) iterations_count_param = shd_first(l.params); - BodyBuilder* loop_body_builder = begin_body_with_mem(a, get_abstraction_mem(loop_inside_case)); + BodyBuilder* loop_body_builder = begin_body_with_mem(a, shd_get_abstraction_mem(loop_inside_case)); const Node* next_function = gen_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); const Node* get_active_branch_fn = access_decl(&ctx->rewriter, "builtin_get_active_branch"); @@ -322,19 +322,19 @@ void generate_top_level_dispatch_fn(Context* ctx) { begin_control_t c = begin_control(loop_body_builder, shd_empty(a)); const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); Node* bail_case = case_(a, shd_empty(a)); - const Node* break_terminator = join(a, (Join) { .args = shd_empty(a), .join_point = l.break_jp, .mem = get_abstraction_mem(bail_case) }); + const Node* break_terminator = join(a, (Join) { .args = shd_empty(a), .join_point = l.break_jp, .mem = shd_get_abstraction_mem(bail_case) }); set_abstraction_body(bail_case, break_terminator); Node* proceed_case = case_(a, shd_empty(a)); set_abstraction_body(proceed_case, join(a, (Join) { .join_point = c.jp, - .mem = get_abstraction_mem(proceed_case), + .mem = shd_get_abstraction_mem(proceed_case), .args = shd_empty(a), })); set_abstraction_body(c.case_, branch(a, (Branch) { - .mem = get_abstraction_mem(c.case_), + .mem = shd_get_abstraction_mem(c.case_), .condition = bail_condition, - .true_jump = jump_helper(a, get_abstraction_mem(c.case_), bail_case, shd_empty(a)), - .false_jump = jump_helper(a, get_abstraction_mem(c.case_), proceed_case, shd_empty(a)), + .true_jump = jump_helper(a, shd_get_abstraction_mem(c.case_), bail_case, shd_empty(a)), + .false_jump = jump_helper(a, shd_get_abstraction_mem(c.case_), proceed_case, shd_empty(a)), })); // gen_if(loop_body_builder, empty(a), bail_condition, bail_case, NULL); } @@ -345,7 +345,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { // Build 'zero' case (exits the program) Node* zero_case_lam = case_(a, shd_nodes(a, 0, NULL)); Node* zero_if_true_lam = case_(a, shd_empty(a)); - BodyBuilder* zero_if_case_builder = begin_body_with_mem(a, get_abstraction_mem(zero_if_true_lam)); + BodyBuilder* zero_if_case_builder = begin_body_with_mem(a, shd_get_abstraction_mem(zero_if_true_lam)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); @@ -353,7 +353,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { set_abstraction_body(zero_if_true_lam, finish_body_with_join(zero_if_case_builder, l.break_jp, shd_empty(a))); Node* zero_if_false = case_(a, shd_empty(a)); - BodyBuilder* zero_false_builder = begin_body_with_mem(a, get_abstraction_mem(zero_if_false)); + BodyBuilder* zero_false_builder = begin_body_with_mem(a, shd_get_abstraction_mem(zero_if_false)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, zero_false_builder, BuiltinSubgroupId); gen_debug_printf(zero_false_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); @@ -361,10 +361,10 @@ void generate_top_level_dispatch_fn(Context* ctx) { set_abstraction_body(zero_if_false, finish_body_with_join(zero_false_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); set_abstraction_body(zero_case_lam, branch(a, (Branch) { - .mem = get_abstraction_mem(zero_case_lam), + .mem = shd_get_abstraction_mem(zero_case_lam), .condition = should_run, - .true_jump = jump_helper(a, get_abstraction_mem(zero_case_lam), zero_if_true_lam, shd_empty(a)), - .false_jump = jump_helper(a, get_abstraction_mem(zero_case_lam), zero_if_false, shd_empty(a)), + .true_jump = jump_helper(a, shd_get_abstraction_mem(zero_case_lam), zero_if_true_lam, shd_empty(a)), + .false_jump = jump_helper(a, shd_get_abstraction_mem(zero_case_lam), zero_if_false, shd_empty(a)), })); const Node* zero_lit = shd_uint64_literal(a, 0); @@ -372,7 +372,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* zero_jump = jump_helper(a, bb_mem(loop_body_builder), zero_case_lam, shd_empty(a)); shd_list_append(const Node*, jumps, zero_jump); - Nodes old_decls = get_module_declarations(ctx->rewriter.src_module); + Nodes old_decls = shd_module_get_declarations(ctx->rewriter.src_module); for (size_t i = 0; i < old_decls.count; i++) { const Node* decl = old_decls.nodes[i]; if (decl->tag == Function_TAG) { @@ -382,7 +382,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* fn_lit = shd_uint32_literal(a, get_fn_ptr(ctx, decl)); Node* if_true_case = case_(a, shd_empty(a)); - BodyBuilder* if_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); + BodyBuilder* if_builder = begin_body_with_mem(a, shd_get_abstraction_mem(if_true_case)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); @@ -392,17 +392,17 @@ void generate_top_level_dispatch_fn(Context* ctx) { Node* if_false = case_(a, shd_empty(a)); set_abstraction_body(if_false, join(a, (Join) { - .mem = get_abstraction_mem(if_false), + .mem = shd_get_abstraction_mem(if_false), .join_point = l.continue_jp, .args = count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a) })); Node* fn_case = case_(a, shd_nodes(a, 0, NULL)); set_abstraction_body(fn_case, branch(a, (Branch) { - .mem = get_abstraction_mem(fn_case), + .mem = shd_get_abstraction_mem(fn_case), .condition = should_run, - .true_jump = jump_helper(a, get_abstraction_mem(fn_case), if_true_case, shd_empty(a)), - .false_jump = jump_helper(a, get_abstraction_mem(fn_case), if_false, shd_empty(a)), + .true_jump = jump_helper(a, shd_get_abstraction_mem(fn_case), if_true_case, shd_empty(a)), + .false_jump = jump_helper(a, shd_get_abstraction_mem(fn_case), if_false, shd_empty(a)), })); shd_list_append(const Node*, literals, fn_lit); @@ -412,7 +412,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { } Node* default_case = case_(a, shd_nodes(a, 0, NULL)); - set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(default_case) })); + set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, br_switch(a, (Switch) { .mem = bb_mem(loop_body_builder), @@ -438,14 +438,14 @@ KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); struct Dict* ptrs = shd_new_dict(const Node*, FnPtr, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); Node* init_fn = function(dst, shd_nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), shd_nodes(a, 0, NULL)); - set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = shd_empty(a), .mem = get_abstraction_mem(init_fn) })); + set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(init_fn) })); FnPtr next_fn_ptr = 1; diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 8b7f0aab5..45eaf5684 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -54,10 +54,10 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_vec_arr(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.validate_builtin_types = false; // TODO: hacky IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index b5fa1c6cb..86d0fb94c 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -22,7 +22,7 @@ static void add_bounds_check(BodyBuilder* bb, const Node* i, const Node* max) { Node* out_of_bounds_case = case_(a, shd_empty(a)); set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) { .args = shd_empty(a), - .mem = get_abstraction_mem(out_of_bounds_case) + .mem = shd_get_abstraction_mem(out_of_bounds_case) })); gen_if(bb, shd_empty(a), gen_primop_e(bb, gte_op, shd_empty(a), mk_nodes(a, i, max)), out_of_bounds_case, NULL); } @@ -63,18 +63,18 @@ static const Node* process(Context* ctx, const Node* node) { Nodes wannotations = shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); Nodes wparams = shd_recreate_params(&ctx->rewriter, node->payload.fun.params); - Node* wrapper = function(m, wparams, get_abstraction_name(node), wannotations, shd_empty(a)); + Node* wrapper = function(m, wparams, shd_get_abstraction_name(node), wannotations, shd_empty(a)); shd_register_processed(&ctx->rewriter, node, wrapper); // recreate the old entry point, but this time it's not the entry point anymore Nodes nannotations = shd_filter_out_annotation(a, wannotations, "EntryPoint"); Nodes nparams = shd_recreate_params(&ctx->rewriter, node->payload.fun.params); - Node* inner = function(m, nparams, shd_format_string_arena(a->arena, "%s_wrapped", get_abstraction_name(node)), nannotations, shd_empty(a)); + Node* inner = function(m, nparams, shd_format_string_arena(a->arena, "%s_wrapped", shd_get_abstraction_name(node)), nannotations, shd_empty(a)); shd_register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); - shd_register_processed(&ctx->rewriter, get_abstraction_mem(node), get_abstraction_mem(inner)); + shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(inner)); set_abstraction_body(inner, shd_recreate_node(&ctx->rewriter, node->payload.fun.body)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(wrapper)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(wrapper)); const Node* num_workgroups_var = shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); const Node* workgroup_num_vec3 = gen_load(bb, ref_decl_helper(a, num_workgroups_var)); @@ -118,7 +118,7 @@ static const Node* process(Context* ctx, const Node* node) { for (int dim = 0; dim < 3; dim++) { Node* loop_body = case_(a, shd_singleton(params[dim])); cases[scope * 3 + dim] = loop_body; - BodyBuilder* loop_bb = begin_body_with_mem(a, get_abstraction_mem(loop_body)); + BodyBuilder* loop_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_body)); builders[scope * 3 + dim] = loop_bb; add_bounds_check(loop_bb, params[dim], maxes[dim]); } @@ -189,9 +189,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* lower_workgroups(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index eca7ed822..90598c5f6 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -48,7 +48,7 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { if (fn_node->is_address_captured || fn_node->is_recursive || fn_node->calls_indirect) { info->is_leaf = false; info->done = true; - shd_debugv_print("Function %s can't be a leaf function because", get_abstraction_name(fn_node->fn)); + shd_debugv_print("Function %s can't be a leaf function because", shd_get_abstraction_name(fn_node->fn)); bool and = false; if (fn_node->is_address_captured) { shd_debugv_print("its address is captured"); @@ -74,7 +74,7 @@ static bool is_leaf_fn(Context* ctx, CGNode* fn_node) { CGEdge e; while (shd_dict_iter(fn_node->callees, &iter, &e, NULL)) { if (!is_leaf_fn(ctx, e.dst_fn)) { - shd_debugv_print("Function %s can't be a leaf function because its callee %s is not a leaf function.\n", get_abstraction_name(fn_node->fn), get_abstraction_name(e.dst_fn->fn)); + shd_debugv_print("Function %s can't be a leaf function because its callee %s is not a leaf function.\n", shd_get_abstraction_name(fn_node->fn), shd_get_abstraction_name(e.dst_fn->fn)); info->is_leaf = false; info->done = true; } @@ -110,7 +110,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_recreate_node_body(&ctx->rewriter, node, new); if (fn_ctx.is_leaf) { - shd_debugv_print("Function %s is a leaf function!\n", get_abstraction_name(node)); + shd_debugv_print("Function %s is a leaf function!\n", shd_get_abstraction_name(node)); new->payload.fun.annotations = shd_nodes_append(a, annotations, annotation(a, (Annotation) { .name = "Leaf", })); @@ -122,7 +122,7 @@ static const Node* process(Context* ctx, const Node* node) { } case Control_TAG: { if (!is_control_static(ctx->uses, node)) { - shd_debugv_print("Function %s can't be a leaf function because the join point ", get_abstraction_name(ctx->cfg->entry->node)); + shd_debugv_print("Function %s can't be a leaf function because the join point ", shd_get_abstraction_name(ctx->cfg->entry->node)); shd_log_node(DEBUGV, shd_first(get_abstraction_params(node->payload.control.inside))); shd_debugv_print("escapes its control block, preventing restructuring.\n"); ctx->is_leaf = false; @@ -136,7 +136,7 @@ static const Node* process(Context* ctx, const Node* node) { if (control && is_control_static(ctx->uses, control)) break; } - shd_debugv_print("Function %s can't be a leaf function because it joins with ", get_abstraction_name(ctx->cfg->entry->node)); + shd_debugv_print("Function %s can't be a leaf function because it joins with ", shd_get_abstraction_name(ctx->cfg->entry->node)); shd_log_node(DEBUGV, old_jp); shd_debugv_print("which is not bound by a control node within that function.\n"); ctx->is_leaf = false; @@ -152,9 +152,9 @@ KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .fns = shd_new_dict(const Node*, FnInfo, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index d141ee66a..d92acc26f 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -93,10 +93,10 @@ static const Node* process(Context* ctx, const Node* node) { } Module* normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.validate_builtin_types = true; IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .builtins = calloc(sizeof(Node*), BuiltinsCount) diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index f3ea3ac31..d9a03356a 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -237,8 +237,8 @@ bool shd_compare_node(const Node**, const Node**); bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { bool todo = false; Module* src = *m; - IrArena* a = get_module_arena(src); - Module* dst = new_module(a, get_module_name(src)); + IrArena* a = shd_module_get_arena(src); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index ac80d83f0..4f3a88796 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -90,7 +90,7 @@ static FnInliningCriteria get_inlining_heuristic(const CompilerConfig* config, C crit.can_be_eliminated = false; shd_debugv_print("inlining heuristic for '%s': num_calls=%d num_inlineable_calls=%d safely_removable=%d address_leaks=%d recursive=%d inlineable=%d can_be_eliminated=%d\n", - get_abstraction_name(fn_node->fn), + shd_get_abstraction_name(fn_node->fn), crit.num_calls, crit.num_inlineable_calls, is_call_safely_removable(fn_node->fn), @@ -106,7 +106,7 @@ static FnInliningCriteria get_inlining_heuristic(const CompilerConfig* config, C static const Node* inline_call(Context* ctx, const Node* ocallee, const Node* nmem, Nodes nargs, const Node* return_to) { assert(is_abstraction(ocallee)); - shd_log_fmt(DEBUG, "Inlining '%s' inside '%s'\n", get_abstraction_name(ocallee), get_abstraction_name(ctx->fun)); + shd_log_fmt(DEBUG, "Inlining '%s' inside '%s'\n", shd_get_abstraction_name(ocallee), shd_get_abstraction_name(ctx->fun)); Context inline_context = *ctx; inline_context.rewriter.map = shd_clone_dict(inline_context.rewriter.map); @@ -119,7 +119,7 @@ static const Node* inline_call(Context* ctx, const Node* ocallee, const Node* nm Nodes oparams = get_abstraction_params(ocallee); shd_register_processed_list(&inline_context.rewriter, oparams, nargs); - shd_register_processed(&inline_context.rewriter, get_abstraction_mem(ocallee), nmem); + shd_register_processed(&inline_context.rewriter, shd_get_abstraction_mem(ocallee), nmem); const Node* nbody = shd_rewrite_node(&inline_context.rewriter, get_abstraction_body(ocallee)); @@ -140,7 +140,7 @@ static const Node* process(Context* ctx, const Node* node) { if (ctx->graph) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, node); if (get_inlining_heuristic(ctx->config, fn_node).can_be_eliminated) { - shd_debugv_print("Eliminating %s because it has exactly one caller\n", get_abstraction_name(fn_node->fn)); + shd_debugv_print("Eliminating %s because it has exactly one caller\n", shd_get_abstraction_name(fn_node->fn)); return NULL; } } @@ -170,16 +170,16 @@ static const Node* process(Context* ctx, const Node* node) { if (ocallee->tag == Function_TAG) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined && is_call_potentially_inlineable(ctx->old_fun, ocallee)) { - shd_debugv_print("Inlining call to %s\n", get_abstraction_name(ocallee)); + shd_debugv_print("Inlining call to %s\n", shd_get_abstraction_name(ocallee)); Nodes nargs = shd_rewrite_nodes(&ctx->rewriter, payload.args); // Prepare a join point to replace the old function return Nodes nyield_types = strip_qualifiers(a, shd_rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); - const Node* join_point = param(a, shd_as_qualified_type(jp_type, true), shd_format_string_arena(a->arena, "inlined_return_%s", get_abstraction_name(ocallee))); + const Node* join_point = param(a, shd_as_qualified_type(jp_type, true), shd_format_string_arena(a->arena, "inlined_return_%s", shd_get_abstraction_name(ocallee))); Node* control_case = case_(a, shd_singleton(join_point)); - const Node* nbody = inline_call(ctx, ocallee, get_abstraction_mem(control_case), nargs, join_point); + const Node* nbody = inline_call(ctx, ocallee, shd_get_abstraction_mem(control_case), nargs, join_point); set_abstraction_body(control_case, nbody); BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); @@ -210,7 +210,7 @@ static const Node* process(Context* ctx, const Node* node) { if (ocallee->tag == Function_TAG) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, ocallee); if (get_inlining_heuristic(ctx->config, fn_node).can_be_inlined) { - shd_debugv_print("Inlining tail call to %s\n", get_abstraction_name(ocallee)); + shd_debugv_print("Inlining tail call to %s\n", shd_get_abstraction_name(ocallee)); Nodes nargs = shd_rewrite_nodes(&ctx->rewriter, node->payload.tail_call.args); return inline_call(ctx, ocallee, shd_rewrite_node(r, node->payload.tail_call.mem), nargs, NULL); } @@ -244,9 +244,9 @@ void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { } Module* opt_inline(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); opt_simplify_cf(config, src, dst); return dst; } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 14bd452d9..15de7a85b 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -123,11 +123,11 @@ OptPass opt_mem2reg; bool opt_mem2reg(SHADY_UNUSED const CompilerConfig* config, Module** m) { Module* src = *m; - IrArena* a = get_module_arena(src); + IrArena* a = shd_module_get_arena(src); Module* dst = NULL; bool todo = false; - dst = new_module(a, get_module_name(src)); + dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .todo = &todo diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index d052f5eff..70d3ba639 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -84,13 +84,13 @@ static DFSStackEntry* encountered_before(Context* ctx, const Node* bb, size_t* p static const Node* make_unreachable_case(IrArena* a) { Node* c = case_(a, shd_empty(a)); - set_abstraction_body(c, unreachable(a, (Unreachable) { .mem = get_abstraction_mem(c) })); + set_abstraction_body(c, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(c) })); return c; } static const Node* make_selection_merge_case(IrArena* a) { Node* c = case_(a, shd_empty(a)); - set_abstraction_body(c, merge_selection(a, (MergeSelection) { .args = shd_empty(a), .mem = get_abstraction_mem(c) })); + set_abstraction_body(c, merge_selection(a, (MergeSelection) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(c) })); return c; } @@ -151,7 +151,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, // Just jumps to the actual ladder Node* structured_target = case_(a, shd_nodes(a, oargs.count, nparams)); - shd_register_processed(&ctx2.rewriter, get_abstraction_mem(old_target), get_abstraction_mem(structured_target)); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old_target), shd_get_abstraction_mem(structured_target)); const Node* structured = structure(&ctx2, get_abstraction_body(old_target), inner_exit_ladder_bb); assert(is_terminator(structured)); set_abstraction_body(structured_target, structured); @@ -165,12 +165,12 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, // Use the structured target as the body of a loop gen_loop(bb, shd_empty(a), shd_rewrite_nodes(&ctx->rewriter, oargs), structured_target); // The exit ladder must exit that new loop - set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = get_abstraction_mem(inner_exit_ladder_bb) })); + set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(inner_exit_ladder_bb) })); // After that we jump to the parent exit return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); } else { // Simply jmp to the exit once done - set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, get_abstraction_mem(inner_exit_ladder_bb), exit, + set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, shd_get_abstraction_mem(inner_exit_ladder_bb), exit, shd_empty(a))); // Jump into the new structured target return finish_body(bb, jump_helper(a, bb_mem(bb), structured_target, shd_rewrite_nodes(&ctx->rewriter, oargs))); @@ -209,10 +209,10 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { shd_rewrite_node(r, payload.mem); Node* true_case = case_(a, shd_empty(a)); - set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, get_abstraction_mem(true_case), make_selection_merge_case(a))); + set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, shd_get_abstraction_mem(true_case), make_selection_merge_case(a))); Node* false_case = case_(a, shd_empty(a)); - set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, get_abstraction_mem(false_case), make_selection_merge_case(a))); + set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, shd_get_abstraction_mem(false_case), make_selection_merge_case(a))); BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); gen_if(bb, shd_empty(a), condition, true_case, false_case); @@ -224,12 +224,12 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { shd_rewrite_node(r, payload.mem); Node* default_case = case_(a, shd_empty(a)); - set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, get_abstraction_mem(default_case), make_selection_merge_case(a))); + set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, shd_get_abstraction_mem(default_case), make_selection_merge_case(a))); LARRAY(Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { cases[i] = case_(a, shd_empty(a)); - set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, get_abstraction_mem(cases[i]), make_selection_merge_case(a))); + set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, shd_get_abstraction_mem(cases[i]), make_selection_merge_case(a))); } BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); @@ -270,7 +270,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() Node* tail = case_(a, shd_empty(a)); - BodyBuilder* bb_tail = begin_body_with_mem(a, get_abstraction_mem(tail)); + BodyBuilder* bb_tail = begin_body_with_mem(a, shd_get_abstraction_mem(tail)); LARRAY(const Node*, phi_values, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { phi_values[i] = gen_load(bb_tail, phis[i]); @@ -281,12 +281,12 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { const Node* level_value = gen_load(bb_tail, ctx->level_ptr); const Node* guard = prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, shd_int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }); Node* true_case = case_(a, shd_empty(a)); - shd_register_processed(r, get_abstraction_mem(get_structured_construct_tail(body)), get_abstraction_mem(true_case)); + shd_register_processed(r, shd_get_abstraction_mem(get_structured_construct_tail(body)), shd_get_abstraction_mem(true_case)); set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); gen_if(bb_tail, shd_empty(a), guard, true_case, NULL); set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, bb_mem(bb_tail), exit, shd_empty(a)))); - shd_register_processed(r, get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); + shd_register_processed(r, shd_get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); return finish_body(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); } case Join_TAG: { @@ -328,7 +328,7 @@ static const Node* process(Context* ctx, const Node* node) { if (is_declaration(node)) { String name = get_declaration_name(node); - Nodes decls = get_module_declarations(ctx->rewriter.dst_module); + Nodes decls = shd_module_get_declarations(ctx->rewriter.dst_module); for (size_t i = 0; i < decls.count; i++) { if (strcmp(get_declaration_name(decls.nodes[i]), name) == 0) return decls.nodes[i]; @@ -354,11 +354,11 @@ static const Node* process(Context* ctx, const Node* node) { is_leaf = is_builtin || !node->payload.fun.body; } else { ctx2.lower = true; - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new)); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); const Node* ptr = gen_local_alloc(bb, shd_int32_type(a)); - set_value_name(ptr, "cf_depth"); + shd_set_value_name(ptr, "cf_depth"); gen_store(bb, ptr, shd_int32_literal(a, 0)); ctx2.level_ptr = ptr; ctx2.fn = new; @@ -366,7 +366,7 @@ static const Node* process(Context* ctx, const Node* node) { TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; - shd_register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new, finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. @@ -416,9 +416,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 290fdc15c..be73f90f5 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -120,14 +120,14 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { gather_exiting_nodes(ctx->current_looptree, current_node, current_node, exiting_nodes); for (size_t i = 0; i < shd_list_count(exiting_nodes); i++) { - shd_debugv_print("Node %s exits the loop headed at %s\n", get_abstraction_name_safe(shd_read_list(CFNode *, exiting_nodes)[i]->node), get_abstraction_name_safe(node)); + shd_debugv_print("Node %s exits the loop headed at %s\n", shd_get_abstraction_name_safe(shd_read_list(CFNode * , exiting_nodes)[i]->node), shd_get_abstraction_name_safe(node)); } size_t exiting_nodes_count = shd_list_count(exiting_nodes); if (exiting_nodes_count > 0) { Nodes nparams = shd_recreate_params(rewriter, get_abstraction_params(node)); Node* loop_container = basic_block(arena, nparams, node->payload.basic_block.name); - BodyBuilder* outer_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_container)); + BodyBuilder* outer_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(loop_container)); Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); LARRAY(Exit, exits, exiting_nodes_count); @@ -173,7 +173,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { const Node* continue_wrapper_body = join(arena, (Join) { .join_point = join_token_continue, .args = continue_wrapper_params, - .mem = get_abstraction_mem(continue_wrapper), + .mem = shd_get_abstraction_mem(continue_wrapper), }); set_abstraction_body(continue_wrapper, continue_wrapper_body); @@ -202,7 +202,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Nodes inner_loop_params = shd_recreate_params(rewriter, get_abstraction_params(node)); shd_register_processed_list(rewriter, get_abstraction_params(node), inner_loop_params); Node* inner_control_case = case_(arena, shd_singleton(join_token_continue)); - shd_register_processed(rewriter, get_abstraction_mem(node), get_abstraction_mem(inner_control_case)); + shd_register_processed(rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(inner_control_case)); const Node* loop_body = shd_rewrite_node(rewriter, get_abstraction_body(node)); // save the context @@ -210,7 +210,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = get_abstraction_params(exits[i].wrapper); - BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, get_abstraction_mem(exits[i].wrapper)); + BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(exits[i].wrapper)); for (size_t j = 0; j < exits[i].params_count; j++) gen_store(exit_wrapper_bb, exits[i].params[j].alloca, exit_wrapper_params.nodes[j]); @@ -238,7 +238,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { shd_register_processed(rewriter, node, *cached_entry); Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); - BodyBuilder* inner_bb = begin_body_with_mem(arena, get_abstraction_mem(loop_outer)); + BodyBuilder* inner_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(loop_outer)); Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); // make sure what was uniform still is for (size_t j = 0; j < inner_control_results.count; j++) { @@ -250,7 +250,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { set_abstraction_body(outer_control_case, jump(arena, (Jump) { .target = loop_outer, .args = nparams, - .mem = get_abstraction_mem(outer_control_case), + .mem = shd_get_abstraction_mem(outer_control_case), })); gen_control(outer_bb, shd_empty(arena), outer_control_case); @@ -259,8 +259,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; - Node* exit_bb = basic_block(arena, shd_empty(arena), shd_format_string_arena(arena->arena, "exit_recover_values_%s", get_abstraction_name_safe(exiting_node->node))); - BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, get_abstraction_mem(exit_bb)); + Node* exit_bb = basic_block(arena, shd_empty(arena), shd_format_string_arena(arena->arena, "exit_recover_values_%s", shd_get_abstraction_name_safe(exiting_node->node))); + BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(exit_bb)); const Node* recreated_exit = shd_rewrite_node(rewriter, exiting_node->node); @@ -432,11 +432,11 @@ static const Node* process_node(Context* ctx, const Node* node) { .yield_types = yield_types }), true), "jp_postdom"); - Node* pre_join = basic_block(a, exit_args, shd_format_string_arena(a->arena, "merge_%s_%s", get_abstraction_name_safe(ctx->current_abstraction), get_abstraction_name_safe(post_dominator))); + Node* pre_join = basic_block(a, exit_args, shd_format_string_arena(a->arena, "merge_%s_%s", shd_get_abstraction_name_safe(ctx->current_abstraction), shd_get_abstraction_name_safe(post_dominator))); set_abstraction_body(pre_join, join(a, (Join) { .join_point = join_token, .args = exit_args, - .mem = get_abstraction_mem(pre_join), + .mem = shd_get_abstraction_mem(pre_join), })); const Node** cached = shd_search_processed(r, post_dominator); @@ -450,12 +450,12 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* control_case = case_(a, shd_singleton(join_token)); const Node* inner_terminator = branch(a, (Branch) { - .mem = get_abstraction_mem(control_case), + .mem = shd_get_abstraction_mem(control_case), .condition = shd_rewrite_node(r, payload.condition), - .true_jump = jump_helper(a, get_abstraction_mem(control_case), + .true_jump = jump_helper(a, shd_get_abstraction_mem(control_case), shd_rewrite_node(r, payload.true_jump->payload.jump.target), shd_rewrite_nodes(r, payload.true_jump->payload.jump.args)), - .false_jump = jump_helper(a, get_abstraction_mem(control_case), + .false_jump = jump_helper(a, shd_get_abstraction_mem(control_case), shd_rewrite_node(r, payload.false_jump->payload.jump.target), shd_rewrite_nodes(r, payload.false_jump->payload.jump.args)), }); @@ -482,10 +482,10 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.optimisations.inline_single_use_bbs = true; IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index 8d856fba3..eab6fa0f0 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -18,7 +18,7 @@ static const Node* process(Context* ctx, const Node* node) { case Jump_TAG: { Jump payload = node->payload.jump; Node* new_block = basic_block(a, shd_empty(a), NULL); - set_abstraction_body(new_block, jump_helper(a, get_abstraction_mem(new_block), + set_abstraction_body(new_block, jump_helper(a, shd_get_abstraction_mem(new_block), shd_rewrite_node(r, payload.target), shd_rewrite_nodes(r, payload.args))); return jump_helper(a, shd_rewrite_node(r, payload.mem), new_block, shd_empty(a)); @@ -30,9 +30,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* remove_critical_edges(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 08d2ebe4c..486a2f8fe 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -90,14 +90,14 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab assert(obb->tag == BasicBlock_TAG); Nodes nparams = remake_params(ctx, get_abstraction_params(obb)); shd_register_processed_list(r, get_abstraction_params(obb), nparams); - nbbs[i] = basic_block(a, nparams, get_abstraction_name_unsafe(obb)); + nbbs[i] = basic_block(a, nparams, shd_get_abstraction_name_unsafe(obb)); shd_register_processed(r, obb, nbbs[i]); } // We introduce a dummy case now because we don't know yet whether the body of the abstraction will be wrapped Node* c = case_(a, shd_empty(a)); Node* oc = c; - shd_register_processed(r, get_abstraction_mem(oabs), get_abstraction_mem(c)); + shd_register_processed(r, shd_get_abstraction_mem(oabs), shd_get_abstraction_mem(c)); for (size_t k = 0; k < num_dom; k++) { CFNode* dominated = shd_read_list(CFNode*, n->dominates)[k]; @@ -114,10 +114,10 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab while(shd_dict_iter(controls->control_destinations, &i, NULL, &add_control)) { const Node* dst = add_control.destination; Node* control_case = case_(a, shd_singleton(add_control.token)); - set_abstraction_body(control_case, jump_helper(a, get_abstraction_mem(control_case), c, shd_empty(a))); + set_abstraction_body(control_case, jump_helper(a, shd_get_abstraction_mem(control_case), c, shd_empty(a))); Node* c2 = case_(a, shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(c2)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(c2)); const Type* jp_type = add_control.token->type; deconstruct_qualified_type(&jp_type); assert(jp_type->tag == JoinPointType_TAG); @@ -133,7 +133,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab set_abstraction_body(c2, finish_body(bb, jump_helper(a, bb_mem(bb), shd_find_processed(r, dst), results))); } - const Node* body = jump_helper(a, get_abstraction_mem(nabs), c, shd_empty(a)); + const Node* body = jump_helper(a, shd_get_abstraction_mem(nabs), c, shd_empty(a)); set_abstraction_body(nabs, body); } @@ -184,7 +184,7 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed shd_log_node(WARN, dst); shd_warn_print(" in lexical_scopes map. Is debug information enabled ?\n"); } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { - shd_debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", get_abstraction_name_safe(src), get_abstraction_name_safe(dst)); + shd_debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", shd_get_abstraction_name_safe(src), shd_get_abstraction_name_safe(dst)); CFNode* src_cfnode = cfg_lookup(cfg, src); assert(src_cfnode->node); @@ -196,21 +196,21 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed CFNode* dom = src_cfnode->idom; while (dom) { - shd_debug_print("Considering %s as a location for control\n", get_abstraction_name_safe(dom->node)); + shd_debug_print("Considering %s as a location for control\n", shd_get_abstraction_name_safe(dom->node)); Nodes* dom_lexical_scope = find_scope_info(dom->node); if (!dom_lexical_scope) { - shd_warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", get_abstraction_name_safe(dom->node)); + shd_warn_print("Basic block %s did not have an entry in the lexical_scopes map. Is debug information enabled ?\n", shd_get_abstraction_name_safe(dom->node)); dom = dom->idom; continue; } else if (lexical_scope_is_nested(*dst_lexical_scope, *dom_lexical_scope)) { - shd_error_print("We went up too far: %s is a parent of the jump destination scope.\n", get_abstraction_name_safe(dom->node)); + shd_error_print("We went up too far: %s is a parent of the jump destination scope.\n", shd_get_abstraction_name_safe(dom->node)); } else if (shd_compare_nodes(dom_lexical_scope, dst_lexical_scope)) { // if (cfg_is_dominated(target_cfnode, dom)) { if (!cfg_is_dominated(dom, dst_cfnode) && dst_cfnode != dom) { // assert(false); } - shd_debug_print("We need to introduce a control block at %s, pointing at %s\n.", get_abstraction_name_safe(dom->node), get_abstraction_name_safe(dst)); + shd_debug_print("We need to introduce a control block at %s, pointing at %s\n.", shd_get_abstraction_name_safe(dom->node), shd_get_abstraction_name_safe(dst)); Controls* controls = get_or_create_controls(ctx, dom->node); AddControl* found = shd_dict_find_value(const Node, AddControl, controls->control_destinations, dst); @@ -225,13 +225,13 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }); - const Node* join_token = param(a, shd_as_qualified_type(jp_type, false), get_abstraction_name_unsafe(dst)); + const Node* join_token = param(a, shd_as_qualified_type(jp_type, false), shd_get_abstraction_name_unsafe(dst)); - Node* wrapper = basic_block(a, wrapper_params, shd_format_string_arena(a->arena, "wrapper_to_%s", get_abstraction_name_safe(dst))); + Node* wrapper = basic_block(a, wrapper_params, shd_format_string_arena(a->arena, "wrapper_to_%s", shd_get_abstraction_name_safe(dst))); wrapper->payload.basic_block.body = join(a, (Join) { .args = join_args, .join_point = join_token, - .mem = get_abstraction_mem(wrapper), + .mem = shd_get_abstraction_mem(wrapper), }); AddControl add_control = { @@ -301,10 +301,10 @@ static const Node* process_node(Context* ctx, const Node* node) { } Module* scope2control(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.optimisations.inline_single_use_bbs = true; IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), .config = config, diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index 1f75a7485..f7a7ad79e 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -173,9 +173,9 @@ static const Node* process(Context* ctx, const Node* node) { fn_ctx.cfg = build_fn_cfg(node); fn_ctx.depth_per_rpo = compute_scope_depth(a, fn_ctx.cfg); Node* new_fn = shd_recreate_node_head(r, node); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_fn)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), shd_empty(a)); - shd_register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new_fn, finish_body(bb, shd_rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); destroy_cfg(fn_ctx.cfg); free(fn_ctx.depth_per_rpo); @@ -184,12 +184,12 @@ static const Node* process(Context* ctx, const Node* node) { case BasicBlock_TAG: { Nodes nparams = shd_recreate_params(r, get_abstraction_params(node)); shd_register_processed_list(r, get_abstraction_params(node), nparams); - Node* new_bb = basic_block(a, nparams, get_abstraction_name_unsafe(node)); + Node* new_bb = basic_block(a, nparams, shd_get_abstraction_name_unsafe(node)); shd_register_processed(r, node, new_bb); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(new_bb)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_bb)); CFNode* n = cfg_lookup(ctx->cfg, node); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); - shd_register_processed(r, get_abstraction_mem(node), bb_mem(bb)); + shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); set_abstraction_body(new_bb, finish_body(bb, shd_rewrite_node(r, get_abstraction_body(node)))); return new_bb; } @@ -200,9 +200,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* scope_heuristic(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), }; diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 04d01032c..9bf12829d 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -29,12 +29,12 @@ static const Node* process(Context* ctx, const Node* node) { Context ctx2 = *ctx; ctx2.disable_lowering = shd_lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); if (!ctx2.disable_lowering) { ctx2.stack_size_on_entry = gen_get_stack_size(bb); - set_value_name((Node*) ctx2.stack_size_on_entry, shd_format_string_arena(a->arena, "saved_stack_ptr_entering_%s", get_abstraction_name(fun))); + shd_set_value_name((Node*) ctx2.stack_size_on_entry, shd_format_string_arena(a->arena, "saved_stack_ptr_entering_%s", shd_get_abstraction_name(fun))); } - shd_register_processed(&ctx2.rewriter, get_abstraction_mem(node), bb_mem(bb)); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), bb_mem(bb)); if (node->payload.fun.body) set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body))); else @@ -60,9 +60,9 @@ static const Node* process(Context* ctx, const Node* node) { } Module* setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index e27126a07..171393b26 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -68,7 +68,7 @@ static const Node* find_entry_point(Module* m, const CompilerConfig* config) { if (!config->specialization.entry_point) return NULL; const Node* found = NULL; - Nodes old_decls = get_module_declarations(m); + Nodes old_decls = shd_module_get_declarations(m); for (size_t i = 0; i < old_decls.count; i++) { if (strcmp(get_declaration_name(old_decls.nodes[i]), config->specialization.entry_point) == 0) { assert(!found); @@ -94,9 +94,9 @@ static void specialize_arena_config(const CompilerConfig* config, Module* src, A const Node* old_wg_size_annotation = shd_lookup_annotation(old_entry_point_decl, "WorkgroupSize"); assert(old_wg_size_annotation && old_wg_size_annotation->tag == AnnotationValues_TAG && shd_get_annotation_values(old_wg_size_annotation).count == 3); Nodes wg_size_nodes = shd_get_annotation_values(old_wg_size_annotation); - target->specializations.workgroup_size[0] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[0]), false); - target->specializations.workgroup_size[1] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[1]), false); - target->specializations.workgroup_size[2] = get_int_literal_value(*resolve_to_int_literal(wg_size_nodes.nodes[2]), false); + target->specializations.workgroup_size[0] = shd_get_int_literal_value(*shd_resolve_to_int_literal(wg_size_nodes.nodes[0]), false); + target->specializations.workgroup_size[1] = shd_get_int_literal_value(*shd_resolve_to_int_literal(wg_size_nodes.nodes[1]), false); + target->specializations.workgroup_size[2] = shd_get_int_literal_value(*shd_resolve_to_int_literal(wg_size_nodes.nodes[2]), false); assert(target->specializations.workgroup_size[0] * target->specializations.workgroup_size[1] * target->specializations.workgroup_size[2] > 0); break; } @@ -105,10 +105,10 @@ static void specialize_arena_config(const CompilerConfig* config, Module* src, A } Module* specialize_entry_point(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); specialize_arena_config(config, src, &aconfig); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), @@ -118,7 +118,7 @@ Module* specialize_entry_point(const CompilerConfig* config, Module* src) { const Node* old_entry_point_decl = find_entry_point(src, config); shd_rewrite_node(&ctx.rewriter, old_entry_point_decl); - Nodes old_decls = get_module_declarations(src); + Nodes old_decls = shd_module_get_declarations(src); for (size_t i = 0; i < old_decls.count; i++) { const Node* old_decl = old_decls.nodes[i]; if (shd_lookup_annotation(old_decl, "RetainAfterSpecialization")) diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 81057bd38..51ddb7005 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -41,10 +41,10 @@ static void specialize_arena_config(const CompilerConfig* config, Module* m, Are } Module* specialize_execution_model(const CompilerConfig* config, Module* src) { - ArenaConfig aconfig = *shd_get_arena_config(get_module_arena(src)); + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); specialize_arena_config(config, src, &aconfig); IrArena* a = shd_new_ir_arena(&aconfig); - Module* dst = new_module(a, get_module_name(src)); + Module* dst = shd_new_module(a, shd_module_get_name(src)); size_t subgroup_size = config->specialization.subgroup_size; assert(subgroup_size); diff --git a/src/shady/print.c b/src/shady/print.c index 0785486c0..bc5e0adb6 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -526,7 +526,7 @@ static bool print_value(PrinterCtx* ctx, const Node* node) { } case Value_Param_TAG: printf(YELLOW); - String name = get_value_name_unsafe(node); + String name = shd_get_value_name_unsafe(node); if (name && strlen(name) > 0) printf("%s_", name); printf("%%%d", node->id); @@ -539,7 +539,7 @@ static bool print_value(PrinterCtx* ctx, const Node* node) { break; case IntLiteral_TAG: printf(BBLUE); - uint64_t v = get_int_literal_value(node->payload.int_literal, false); + uint64_t v = shd_get_int_literal_value(node->payload.int_literal, false); switch (node->payload.int_literal.width) { case IntTy8: printf("%" PRIu8, (uint8_t) v); break; case IntTy16: printf("%" PRIu16, (uint16_t) v); break; @@ -1093,7 +1093,7 @@ static bool print_node_impl(PrinterCtx* ctx, const Node* node) { } static void print_mod_impl(PrinterCtx* ctx, Module* mod) { - Nodes decls = get_module_declarations(mod); + Nodes decls = shd_module_get_declarations(mod); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; print_decl(ctx, decl); diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index 71d7b18dd..d638b0a77 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -241,7 +241,7 @@ bool shd_compare_node(Node** pa, Node** pb); void shd_rewrite_module(Rewriter* rewriter) { assert(rewriter->dst_module != rewriter->src_module); - Nodes old_decls = get_module_declarations(rewriter->src_module); + Nodes old_decls = shd_module_get_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { if (!shd_lookup_annotation(old_decls.nodes[i], "Exported")) continue; rewrite_op_helper(rewriter, NcDeclaration, "decl", old_decls.nodes[i]); diff --git a/src/shady/transform/internal_constants.c b/src/shady/transform/internal_constants.c index d3597670c..a5250c287 100644 --- a/src/shady/transform/internal_constants.c +++ b/src/shady/transform/internal_constants.c @@ -6,7 +6,7 @@ #include void shd_generate_dummy_constants(SHADY_UNUSED const CompilerConfig* config, Module* mod) { - IrArena* arena = get_module_arena(mod); + IrArena* arena = shd_module_get_arena(mod); Nodes annotations = mk_nodes(arena, annotation(arena, (Annotation) { .name = "RetainAfterSpecialization" }), annotation(arena, (Annotation) { .name = "Exported" })); #define X(constant_name, T, placeholder) \ Node* constant_name##_var = constant(mod, annotations, T, #constant_name); \ diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index ea4a51479..bd0f74030 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -147,7 +147,7 @@ void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { } const Node* get_builtin(Module* m, Builtin b) { - Nodes decls = get_module_declarations(m); + Nodes decls = shd_module_get_declarations(m); for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag != GlobalVariable_TAG) @@ -170,7 +170,7 @@ const Node* get_or_create_builtin(Module* m, Builtin b, String n) { return decl; AddressSpace as = shd_get_builtin_address_space(b); - IrArena* a = get_module_arena(m); + IrArena* a = shd_module_get_arena(m); decl = global_var(m, shd_singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, shd_get_builtin_name(b)))), shd_get_builtin_type(a, b), n ? n : shd_format_string_arena(a->arena, "builtin_%s", @@ -206,7 +206,7 @@ bool is_builtin_load_op(const Node* n, Builtin* out) { } const Node* find_or_process_decl(Rewriter* rewriter, const char* name) { - Nodes old_decls = get_module_declarations(rewriter->src_module); + Nodes old_decls = shd_module_get_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { const Node* decl = old_decls.nodes[i]; if (strcmp(get_declaration_name(decl), name) == 0) { diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 6454cfb20..dc13b6d6a 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -87,7 +87,7 @@ TypeMemLayout shd_get_mem_layout(IrArena* a, const Type* type) { case ArrType_TAG: { const Node* size = type->payload.arr_type.size; assert(size && "We can't know the full layout of arrays of unknown size !"); - size_t actual_size = get_int_literal_value(*resolve_to_int_literal(size), false); + size_t actual_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(size), false); TypeMemLayout element_layout = shd_get_mem_layout(a, type->payload.arr_type.element_type); return (TypeMemLayout) { .type = type, diff --git a/src/shady/type.c b/src/shady/type.c index 9a8b50e8b..8f7a2f302 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -106,7 +106,7 @@ bool is_subtype(const Type* supertype, const Type* type) { return false; // unsized arrays are supertypes of sized arrays (even though they're not datatypes...) // TODO: maybe change this so it's only valid when talking about to pointer-to-arrays - const IntLiteral* size_literal = resolve_to_int_literal(supertype->payload.arr_type.size); + const IntLiteral* size_literal = shd_resolve_to_int_literal(supertype->payload.arr_type.size); if (size_literal && size_literal->value == 0) return true; return supertype->payload.arr_type.size == type->payload.arr_type.size || !supertype->payload.arr_type.size; @@ -812,7 +812,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { bool u = lhs_u & rhs_u; for (size_t i = 0; i < indices_count; i++) { u &= is_qualified_type_uniform(indices[i]->type); - int64_t index = get_int_literal_value(*resolve_to_int_literal(indices[i]), true); + int64_t index = shd_get_int_literal_value(*shd_resolve_to_int_literal(indices[i]), true); assert(index < 0 /* poison */ || (index >= 0 && index < total_size && "shuffle element out of range")); } return shd_as_qualified_type( @@ -1060,7 +1060,7 @@ const Type* check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffse bool offset_uniform = deconstruct_qualified_type(&offset_type); assert(offset_type->tag == Int_TAG && "lea expects an integer offset"); - const IntLiteral* lit = resolve_to_int_literal(lea.offset); + const IntLiteral* lit = shd_resolve_to_int_literal(lea.offset); bool offset_is_zero = lit && lit->value == 0; assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); assert(offset_is_zero || is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); diff --git a/src/shady/type_helpers.c b/src/shady/type_helpers.c index 1c932394e..e2dc0e801 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/type_helpers.c @@ -62,7 +62,7 @@ void enter_composite(const Type** datatype, bool* uniform, const Node* selector, try_again: switch (current_type->tag) { case RecordType_TAG: { - size_t selector_value = get_int_literal_value(*resolve_to_int_literal(selector), false); + size_t selector_value = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); assert(selector_value < current_type->payload.record_type.members.count); current_type = current_type->payload.record_type.members.nodes[selector_value]; break; @@ -80,7 +80,7 @@ void enter_composite(const Type** datatype, bool* uniform, const Node* selector, case PackType_TAG: { assert(allow_entering_pack); assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a pack type need to be constant"); - size_t selector_value = get_int_literal_value(*resolve_to_int_literal(selector), false); + size_t selector_value = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); assert(selector_value < current_type->payload.pack_type.width); current_type = current_type->payload.pack_type.element_type; break; @@ -260,7 +260,7 @@ Nodes get_composite_type_element_types(const Type* type) { } case Type_ArrType_TAG: case Type_PackType_TAG: { - size_t size = get_int_literal_value(*resolve_to_int_literal(get_fill_type_size(type)), false); + size_t size = shd_get_int_literal_value(*shd_resolve_to_int_literal(get_fill_type_size(type)), false); if (size >= 1024) { shd_warn_print("Potential performance issue: creating a really big array of composites of types (size=%d)!\n", size); } diff --git a/src/shady/visit.c b/src/shady/visit.c index 2a67b0f8e..5c4d6da54 100644 --- a/src/shady/visit.c +++ b/src/shady/visit.c @@ -60,6 +60,6 @@ void shd_visit_function_bodies_rpo(Visitor* visitor, const Node* function) { #include "visit_generated.c" void shd_visit_module(Visitor* visitor, Module* mod) { - Nodes decls = get_module_declarations(mod); + Nodes decls = shd_module_get_declarations(mod); shd_visit_nodes(visitor, decls); } diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index ba8bc0c68..0554f8b33 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -64,7 +64,7 @@ static void cli_parse_oracle_args(int* pargc, char** argv) { } static Module* oracle_passes(const CompilerConfig* config, Module* initial_mod) { - IrArena* initial_arena = get_module_arena(initial_mod); + IrArena* initial_arena = shd_module_get_arena(initial_mod); Module** pmod = &initial_mod; RUN_PASS(cleanup) @@ -86,14 +86,14 @@ int main(int argc, char** argv) { ArenaConfig aconfig = shd_default_arena_config(&args.config.target); aconfig.optimisations.weaken_non_leaking_allocas = true; IrArena* arena = shd_new_ir_arena(&aconfig); - Module* mod = new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one + Module* mod = shd_new_module(arena, "my_module"); // TODO name module after first filename, or perhaps the last one ShadyErrorCodes err = shd_driver_load_source_files(&args, mod); if (err) exit(err); Module* mod2 = oracle_passes(&args.config, mod); - shd_destroy_ir_arena(get_module_arena(mod2)); + shd_destroy_ir_arena(shd_module_get_arena(mod2)); if (err) exit(err); diff --git a/test/test_builder.c b/test/test_builder.c index dfdfa9ada..5d2c69124 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -20,11 +20,11 @@ static void test_body_builder_constants(IrArena* a) { const Node* result = yield_value_and_wrap_in_block(bb, sum); CHECK(sum == result, exit(-1)); CHECK(result->tag == IntLiteral_TAG, exit(-1)); - CHECK(get_int_literal_value(result->payload.int_literal, false) == 42, exit(-1)); + CHECK(shd_get_int_literal_value(result->payload.int_literal, false) == 42, exit(-1)); } static void test_body_builder_fun_body(IrArena* a) { - Module* m = new_module(a, "test_module"); + Module* m = shd_new_module(a, "test_module"); const Node* p1 = param(a, shd_as_qualified_type(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = shd_uint32_type(a), @@ -36,12 +36,12 @@ static void test_body_builder_fun_body(IrArena* a) { // const Node* p3 = param(a, shd_as_qualified_type(bool_type(a), false), NULL); // const Node* p4 = param(a, shd_as_qualified_type(uint32_type(a), false), NULL); Node* fun = function(m, mk_nodes(a, p1, p2), "fun", shd_empty(a), shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); const Node* p1_value = gen_load(bb, p1); CHECK(p1_value->tag == Load_TAG, exit(-1)); Node* true_case = case_(a, shd_empty(a)); - BodyBuilder* tc_builder = begin_body_with_mem(a, get_abstraction_mem(true_case)); + BodyBuilder* tc_builder = begin_body_with_mem(a, shd_get_abstraction_mem(true_case)); gen_store(tc_builder, p1, shd_uint32_literal(a, 0)); set_abstraction_body(true_case, finish_body_with_selection_merge(tc_builder, shd_empty(a))); gen_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, shd_uint32_literal(a, 0))), true_case, NULL); @@ -79,20 +79,20 @@ static void test_body_builder_fun_body(IrArena* a) { break; } while (1); mem = get_original_mem(mem); - CHECK(mem == get_abstraction_mem(fun), exit(-1)); + CHECK(mem == shd_get_abstraction_mem(fun), exit(-1)); destroy_cfg(cfg); } /// There is some "magic" code in body_builder and set_abstraction_body to enable inserting control-flow /// where there is only a mem dependency. This is useful when writing some complex polyfills. static void test_body_builder_impure_block(IrArena* a) { - Module* m = new_module(a, "test_module"); + Module* m = shd_new_module(a, "test_module"); const Node* p1 = param(a, shd_as_qualified_type(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = shd_uint32_type(a), }), false), NULL); Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); const Node* first_load = gen_load(bb, p1); @@ -125,19 +125,19 @@ static void test_body_builder_impure_block(IrArena* a) { /// There is some "magic" code in body_builder and set_abstraction_body to enable inserting control-flow /// where there is only a mem dependency. This is useful when writing some complex polyfills. static void test_body_builder_impure_block_with_control_flow(IrArena* a) { - Module* m = new_module(a, "test_module"); + Module* m = shd_new_module(a, "test_module"); const Node* p1 = param(a, shd_as_qualified_type(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = shd_uint32_type(a), }), false), NULL); Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, get_abstraction_mem(fun)); + BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); const Node* first_load = gen_load(bb, p1); BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); Node* if_true_case = case_(a, shd_empty(a)); - BodyBuilder* if_true_builder = begin_body_with_mem(a, get_abstraction_mem(if_true_case)); + BodyBuilder* if_true_builder = begin_body_with_mem(a, shd_get_abstraction_mem(if_true_case)); gen_store(if_true_builder, p1, shd_uint32_literal(a, 0)); set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_true_builder, shd_empty(a))); gen_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, shd_uint32_literal(a, 0))), if_true_case, NULL); diff --git a/test/test_math.c b/test/test_math.c index 07eb4c0e9..6c89a61bd 100644 --- a/test/test_math.c +++ b/test/test_math.c @@ -32,7 +32,7 @@ static bool check_same_bytes(char* a, char* b, size_t size) { } static void check_int_literal_against_reference(IrArena* a, const Node* lit, IntLiteral reference) { - const IntLiteral* ptr = resolve_to_int_literal(lit); + const IntLiteral* ptr = shd_resolve_to_int_literal(lit); CHECK(ptr, exit(-1)); IntLiteral got = *ptr; CHECK(got.is_signed == reference.is_signed, exit(-1)); @@ -76,13 +76,13 @@ static void test_int_literals(IrArena* a) { .width = IntTy64, .is_signed = true }; - uint64_t extracted_literal_value = get_int_literal_value(reference_literal, true); + uint64_t extracted_literal_value = shd_get_int_literal_value(reference_literal, true); int16_t reference_minus_one_i16 = test_value; CHECK(check_same_bytes((char*) &extracted_literal_value, (char*) &reference_minus_one_i16, sizeof(uint16_t)), exit(-1)); - uint64_t minus_one_u32 = get_int_literal_value(reference_literal, true); + uint64_t minus_one_u32 = shd_get_int_literal_value(reference_literal, true); int32_t reference_minus_one_i32 = test_value; CHECK(check_same_bytes((char*) &minus_one_u32, (char*) &reference_minus_one_i32, sizeof(uint32_t)), exit(-1)); - uint64_t minus_one_u64 = get_int_literal_value(reference_literal, true); + uint64_t minus_one_u64 = shd_get_int_literal_value(reference_literal, true); int64_t reference_minus_one_i64 = test_value; CHECK(check_same_bytes((char*) &minus_one_u64, (char*) &reference_minus_one_i64, sizeof(uint64_t)), exit(-1)); } diff --git a/vcc/vcc.c b/vcc/vcc.c index e64d40a3e..fe2587a1f 100644 --- a/vcc/vcc.c +++ b/vcc/vcc.c @@ -36,7 +36,7 @@ int main(int argc, char** argv) { if (!vcc_options.only_run_clang) { Module* mod = vcc_parse_back_into_module(&args.config, &vcc_options, "my_module"); shd_driver_compile(&args, mod); - shd_destroy_ir_arena(get_module_arena(mod)); + shd_destroy_ir_arena(shd_module_get_arena(mod)); } shd_info_print("Done\n"); diff --git a/zhady/shady.i b/zhady/shady.i index 1b688b2b4..aaf87f699 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -5,6 +5,21 @@ %module shady %{ #include "shady/ir.h" + +* arena + +* m + +* m + +* m + +* mname + +* v + +* arena* node + #include "shady/runtime.h" #include "shady/driver.h" #include "shady/config.h" From 3021dd562614f5495ec8bae676d51eeff85363d2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 17:14:21 +0200 Subject: [PATCH 634/693] add missing function.h --- include/shady/ir/function.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 include/shady/ir/function.h diff --git a/include/shady/ir/function.h b/include/shady/ir/function.h new file mode 100644 index 000000000..aa170353c --- /dev/null +++ b/include/shady/ir/function.h @@ -0,0 +1,32 @@ +#ifndef SHADY_IR_FUNCTION_H +#define SHADY_IR_FUNCTION_H + +#include "shady/ir/grammar.h" + +Node* param(IrArena*, const Type* type, const char* name); + +Node* function(Module*, Nodes params, const char* name, Nodes annotations, Nodes return_types); + +// basic blocks +Node* basic_block(IrArena*, Nodes params, const char* name); +static inline Node* case_(IrArena* a, Nodes params) { + return basic_block(a, params, NULL); +} + +/// Empty type: there are no values of this type. +/// Useful for the codomain of things that don't return at all +const Type* noret_type(IrArena*); + +/// For typing instructions that return nothing (equivalent to C's void f()) +const Type* empty_multiple_return_type(IrArena*); + +inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } + +const Node* shd_get_abstraction_mem(const Node* abs); +String shd_get_abstraction_name(const Node* abs); +String shd_get_abstraction_name_unsafe(const Node* abs); +String shd_get_abstraction_name_safe(const Node* abs); + +void set_abstraction_body(Node* abs, const Node* body); + +#endif From d6ed5c514c6e474751a574b771f7d0f3449c45b7 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 17:20:50 +0200 Subject: [PATCH 635/693] yet more shd_ prefixing --- include/shady/grammar.json | 4 ++ include/shady/ir/function.h | 10 ++--- include/shady/ir/mem.h | 4 +- include/shady/ir/memory_layout.h | 2 +- include/shady/ir/module.h | 2 +- include/shady/ir/type.h | 6 ++- src/backend/spirv/spirv_lift_globals_ssbo.c | 6 +-- src/driver/driver.c | 2 +- src/frontend/llvm/l2s.c | 2 +- src/frontend/llvm/l2s_postprocess.c | 4 +- src/frontend/slim/bind.c | 6 +-- src/frontend/slim/infer.c | 8 ++-- src/frontend/slim/parser.c | 16 ++++---- src/frontend/spirv/s2s.c | 6 +-- src/shady/analysis/cfg_dump.c | 2 +- src/shady/body_builder.c | 8 ++-- src/shady/compile.c | 2 +- src/shady/constructors.c | 10 ----- src/shady/fold.c | 4 +- src/shady/node.c | 6 +-- src/shady/node_helpers.c | 6 +-- src/shady/passes/import.c | 2 +- src/shady/passes/lift_everything.c | 2 +- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_alloca.c | 4 +- src/shady/passes/lower_callf.c | 8 ++-- src/shady/passes/lower_cf_instrs.c | 20 +++++----- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 40 ++++++++++---------- src/shady/passes/lower_memcpy.c | 20 +++++----- src/shady/passes/lower_physical_ptrs.c | 6 +-- src/shady/passes/lower_stack.c | 6 +-- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_subgroup_vars.c | 6 +-- src/shady/passes/lower_tailcalls.c | 42 ++++++++++----------- src/shady/passes/lower_workgroups.c | 8 ++-- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_inline.c | 2 +- src/shady/passes/opt_mem2reg.c | 2 +- src/shady/passes/opt_restructure.c | 28 +++++++------- src/shady/passes/reconvergence_heuristics.c | 18 ++++----- src/shady/passes/remove_critical_edges.c | 6 +-- src/shady/passes/scope2control.c | 10 ++--- src/shady/passes/scope_heuristic.c | 4 +- src/shady/passes/setup_stack_frames.c | 2 +- src/shady/rewrite.c | 4 +- src/shady/transform/ir_gen_helpers.c | 2 +- src/shady/transform/memory_layout.c | 2 +- src/shady/type.c | 8 ++-- test/test_builder.c | 20 +++++----- 50 files changed, 196 insertions(+), 200 deletions(-) diff --git a/include/shady/grammar.json b/include/shady/grammar.json index 97316354c..d6a278783 100644 --- a/include/shady/grammar.json +++ b/include/shady/grammar.json @@ -150,6 +150,10 @@ { "name": "NoRet", "snake_name": "noret_type", + "description": [ + "Empty type: there are no values of this type.", + "Useful for the codomain of things that don't return at all" + ], "class": "type", "type": false }, diff --git a/include/shady/ir/function.h b/include/shady/ir/function.h index aa170353c..d301ef651 100644 --- a/include/shady/ir/function.h +++ b/include/shady/ir/function.h @@ -13,12 +13,10 @@ static inline Node* case_(IrArena* a, Nodes params) { return basic_block(a, params, NULL); } -/// Empty type: there are no values of this type. -/// Useful for the codomain of things that don't return at all -const Type* noret_type(IrArena*); - /// For typing instructions that return nothing (equivalent to C's void f()) -const Type* empty_multiple_return_type(IrArena*); +static inline const Type* empty_multiple_return_type(IrArena* arena) { + return shd_as_qualified_type(unit_type(arena), true); +} inline static bool is_function(const Node* node) { return node->tag == Function_TAG; } @@ -27,6 +25,6 @@ String shd_get_abstraction_name(const Node* abs); String shd_get_abstraction_name_unsafe(const Node* abs); String shd_get_abstraction_name_safe(const Node* abs); -void set_abstraction_body(Node* abs, const Node* body); +void shd_set_abstraction_body(Node* abs, const Node* body); #endif diff --git a/include/shady/ir/mem.h b/include/shady/ir/mem.h index 47d7bd276..5d0c83cb5 100644 --- a/include/shady/ir/mem.h +++ b/include/shady/ir/mem.h @@ -3,7 +3,7 @@ #include "shady/ir/base.h" -const Node* get_parent_mem(const Node* mem); -const Node* get_original_mem(const Node* mem); +const Node* shd_get_parent_mem(const Node* mem); +const Node* shd_get_original_mem(const Node* mem); #endif diff --git a/include/shady/ir/memory_layout.h b/include/shady/ir/memory_layout.h index 4cceac96c..c1178c00f 100644 --- a/include/shady/ir/memory_layout.h +++ b/include/shady/ir/memory_layout.h @@ -33,6 +33,6 @@ const Node* shd_bytes_to_words(BodyBuilder* bb, const Node* bytes); uint64_t shd_bytes_to_words_static(const IrArena* a, uint64_t bytes); IntSizes shd_float_to_int_width(FloatSizes width); -size_t get_type_bitwidth(const Type* t); +size_t shd_get_type_bitwidth(const Type* t); #endif diff --git a/include/shady/ir/module.h b/include/shady/ir/module.h index 0a2d6ba33..0dac817d7 100644 --- a/include/shady/ir/module.h +++ b/include/shady/ir/module.h @@ -10,6 +10,6 @@ String shd_module_get_name(const Module* m); Nodes shd_module_get_declarations(const Module* m); Node* shd_module_get_declaration(const Module* m, String name); -void link_module(Module* dst, Module* src); +void shd_module_link(Module* dst, Module* src); #endif diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index 96b451abd..5a309d661 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -5,7 +5,11 @@ /// Unit type, carries no information (equivalent to C's void) /// There is exactly one possible value of this type: () -const Node* unit_type(IrArena*); +static inline const Node* unit_type(IrArena* arena) { + return record_type(arena, (RecordType) { + .members = shd_empty(arena), + }); +} Type* nominal_type(Module*, Nodes annotations, String name); diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 2313519df..70d82787e 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -30,9 +30,9 @@ static const Node* process(Context* ctx, const Node* node) { functx.bb = begin_body_with_mem(a, shd_get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); shd_register_processed(&functx.rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(post_prelude)); - set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); - set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, - shd_empty(a)))); + shd_set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); + shd_set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, + shd_empty(a)))); shd_destroy_dict(functx.rewriter.map); } return newfun; diff --git a/src/driver/driver.c b/src/driver/driver.c index 36b5fa6ba..f96a8cbec 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -107,7 +107,7 @@ ShadyErrorCodes shd_driver_load_source_files(DriverConfig* args, Module* mod) { shd_read_list(const char*, args->input_filenames)[i], &m); if (err) return err; - link_module(mod, m); + shd_module_link(mod, m); shd_destroy_ir_arena(shd_module_get_arena(m)); } diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 3d88e846e..579682582 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -68,7 +68,7 @@ static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { static void write_bb_tail(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { LLVMBasicBlockRef bb = bb_ctx->bb; LLVMValueRef instr = LLVMGetLastInstruction(bb); - set_abstraction_body(bb_ctx->nbb, finish_body(bb_ctx->builder, convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr))); + shd_set_abstraction_body(bb_ctx->nbb, finish_body(bb_ctx->builder, convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr))); } static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasicBlockRef bb) { diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 961a289d3..d01c456e1 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -84,12 +84,12 @@ static const Node* process_node(Context* ctx, const Node* node) { Node* decl = function(ctx->rewriter.dst_module, new_params, shd_get_abstraction_name(node), new_annotations, shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.return_types)); shd_register_processed(&ctx->rewriter, node, decl); if (primop_intrinsic != PRIMOPS_COUNT) { - set_abstraction_body(decl, fn_ret(a, (Return) { + shd_set_abstraction_body(decl, fn_ret(a, (Return) { .args = shd_singleton(prim_op_helper(a, primop_intrinsic, shd_empty(a), get_abstraction_params(decl))), .mem = shd_get_abstraction_mem(decl), })); } else if (get_abstraction_body(node)) - set_abstraction_body(decl, shd_rewrite_node(r, get_abstraction_body(node))); + shd_set_abstraction_body(decl, shd_rewrite_node(r, get_abstraction_body(node))); return decl; } case GlobalVariable_TAG: { diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 88572c811..4e53a848c 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -193,7 +193,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { if (param_name) add_binding(&cont_ctx, false, param_name, bb_param); } - set_abstraction_body(bbs[i], shd_rewrite_node(&cont_ctx.rewriter, get_abstraction_body(conts[i]))); + shd_set_abstraction_body(bbs[i], shd_rewrite_node(&cont_ctx.rewriter, get_abstraction_body(conts[i]))); } } } @@ -230,7 +230,7 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { if (decl->payload.fun.body) { fn_ctx.current_function = bound; - set_abstraction_body(bound, shd_rewrite_node(&fn_ctx.rewriter, decl->payload.fun.body)); + shd_set_abstraction_body(bound, shd_rewrite_node(&fn_ctx.rewriter, decl->payload.fun.body)); } return bound; } @@ -302,7 +302,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { } shd_register_processed(&ctx->rewriter, node, new_bb); shd_register_processed_list(&ctx->rewriter, node->payload.basic_block.params, new_params); - set_abstraction_body(new_bb, shd_rewrite_node(&ctx->rewriter, node->payload.basic_block.body)); + shd_set_abstraction_body(new_bb, shd_rewrite_node(&ctx->rewriter, node->payload.basic_block.body)); return new_bb; } case ExtInstr_TAG: { diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index fad579bf8..951de283a 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -105,7 +105,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, node->payload.fun.params.count, nparams), string(a, node->payload.fun.name), infer_nodes(ctx, node->payload.fun.annotations), nret_types); shd_register_processed(&ctx->rewriter, node, fun); body_context.current_fn = fun; - set_abstraction_body(fun, infer(&body_context, node->payload.fun.body, NULL)); + shd_set_abstraction_body(fun, infer(&body_context, node->payload.fun.body, NULL)); return fun; } case Constant_TAG: { @@ -308,7 +308,7 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg Node* new_case = basic_block(a, shd_nodes(a, inferred_arg_type.count, nparams), shd_get_abstraction_name_unsafe(node)); shd_register_processed(r, node, new_case); - set_abstraction_body(new_case, infer(&body_context, node->payload.basic_block.body, NULL)); + shd_set_abstraction_body(new_case, infer(&body_context, node->payload.basic_block.body, NULL)); return new_case; } @@ -332,7 +332,7 @@ static const Node* _infer_basic_block(Context* ctx, const Node* node) { assert(bb); shd_register_processed(&ctx->rewriter, node, bb); - set_abstraction_body(bb, infer(&body_context, node->payload.basic_block.body, NULL)); + shd_set_abstraction_body(bb, infer(&body_context, node->payload.basic_block.body, NULL)); return bb; } @@ -502,7 +502,7 @@ static const Node* infer_control(Context* ctx, const Node* node) { Node* new_case = basic_block(a, shd_singleton(jp), NULL); shd_register_processed(&joinable_ctx.rewriter, olam, new_case); - set_abstraction_body(new_case, infer(&joinable_ctx, get_abstraction_body(olam), NULL)); + shd_set_abstraction_body(new_case, infer(&joinable_ctx, get_abstraction_body(olam), NULL)); return control(a, (Control) { .yield_types = yield_types, diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 0c9e53cbb..18f2b8053 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -751,14 +751,14 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { const Node* (*merge)(const Node*) = config->front_end ? make_selection_merge : NULL; Node* true_case = case_(arena, shd_nodes(arena, 0, NULL)); - set_abstraction_body(true_case, expect_body(ctx, shd_get_abstraction_mem(true_case), merge)); + shd_set_abstraction_body(true_case, expect_body(ctx, shd_get_abstraction_mem(true_case), merge)); // else defaults to an empty body bool has_else = accept_token(ctx, else_tok); Node* false_case = NULL; if (has_else) { false_case = case_(arena, shd_nodes(arena, 0, NULL)); - set_abstraction_body(false_case, expect_body(ctx, shd_get_abstraction_mem(false_case), merge)); + shd_set_abstraction_body(false_case, expect_body(ctx, shd_get_abstraction_mem(false_case), merge)); } return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, true_case, false_case)); } @@ -771,7 +771,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { // by default loops continue forever const Node* (*default_loop_end_behaviour)(const Node*) = config->front_end ? make_loop_continue : NULL; Node* loop_case = case_(arena, parameters); - set_abstraction_body(loop_case, expect_body(ctx, shd_get_abstraction_mem(loop_case), default_loop_end_behaviour)); + shd_set_abstraction_body(loop_case, expect_body(ctx, shd_get_abstraction_mem(loop_case), default_loop_end_behaviour)); return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, loop_case)); } case control_tok: { @@ -785,7 +785,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { }), str); expect(accept_token(ctx, rpar_tok), "')'"); Node* control_case = case_(arena, shd_singleton(jp)); - set_abstraction_body(control_case, expect_body(ctx, shd_get_abstraction_mem(control_case), NULL)); + shd_set_abstraction_body(control_case, expect_body(ctx, shd_get_abstraction_mem(control_case), NULL)); return maybe_tuple_helper(arena, gen_control(bb, yield_types, control_case)); } default: break; @@ -1025,7 +1025,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t syntax_error("expected terminator: return, jump, branch ..."); } - set_abstraction_body(terminator_case, finish_body(terminator_bb, terminator)); + shd_set_abstraction_body(terminator_case, finish_body(terminator_bb, terminator)); Node* cont_wrapper_case = case_(arena, shd_empty(arena)); BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(cont_wrapper_case)); @@ -1041,7 +1041,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t Nodes parameters; expect_parameters(ctx, ¶meters, NULL, bb); Node* continuation = basic_block(arena, parameters, name); - set_abstraction_body(continuation, expect_body(ctx, shd_get_abstraction_mem(continuation), NULL)); + shd_set_abstraction_body(continuation, expect_body(ctx, shd_get_abstraction_mem(continuation), NULL)); ids = shd_nodes_append(arena, ids, string_lit_helper(arena, name)); conts = shd_nodes_append(arena, conts, continuation); } @@ -1050,7 +1050,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t gen_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), shd_concat_nodes(arena, ids, conts)); expect(accept_token(ctx, rbracket_tok), "']'"); - set_abstraction_body(cont_wrapper_case, finish_body_with_jump(cont_wrapper_bb, terminator_case, shd_empty(arena))); + shd_set_abstraction_body(cont_wrapper_case, finish_body_with_jump(cont_wrapper_bb, terminator_case, shd_empty(arena))); return finish_body_with_jump(bb, cont_wrapper_case, shd_empty(arena)); } @@ -1149,7 +1149,7 @@ static const Node* accept_fn_decl(ctxparams, Nodes annotations) { Node* fn = function(mod, parameters, name, annotations, types); if (!accept_token(ctx, semi_tok)) - set_abstraction_body(fn, expect_body(ctx, shd_get_abstraction_mem(fn), types.count == 0 ? make_return_void : NULL)); + shd_set_abstraction_body(fn, expect_body(ctx, shd_get_abstraction_mem(fn), types.count == 0 ? make_return_void : NULL)); return fn; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index cc9d18223..21833f6ea 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -673,7 +673,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpConstant: { parser->defs[result].type = Value; const Type* t = get_def_type(parser, result_t); - int width = get_type_bitwidth(t); + int width = shd_get_type_bitwidth(t); switch (is_type(t)) { case Int_TAG: { uint64_t v; @@ -848,7 +848,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { // steal the body of the first block, it can't be jumped to anyways! if (first_block) - set_abstraction_body(fun, first_block->payload.basic_block.body); + shd_set_abstraction_body(fun, first_block->payload.basic_block.body); parser->fun = old_fun; break; } @@ -911,7 +911,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { instruction_offset += s; } assert(parser->current_block.finished); - set_abstraction_body(block, parser->current_block.finished); + shd_set_abstraction_body(block, parser->current_block.finished); parser->current_block = old; break; } diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 220cae796..9615925ee 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -43,7 +43,7 @@ static const Nodes* find_scope_info(const Node* abs) { if (!info || info->count > mem->payload.ext_instr.operands.count) info = &mem->payload.ext_instr.operands; } - mem = get_parent_mem(mem); + mem = shd_get_parent_mem(mem); } return info; } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index d1a6c41b4..92cfa4f9c 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -66,7 +66,7 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp if (bb->arena->config.check_types) { assert(is_mem(instruction)); } - if (is_mem(instruction) && /* avoid things like ExtInstr with null mem input! */ get_parent_mem(instruction)) + if (is_mem(instruction) && /* avoid things like ExtInstr with null mem input! */ shd_get_parent_mem(instruction)) bb->mem = instruction; return deconstruct_composite(bb->arena, bb, instruction, outputs_count); } @@ -115,7 +115,7 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { break; } } - set_abstraction_body((Node*) get_structured_construct_tail(terminator), t2); + shd_set_abstraction_body((Node*) get_structured_construct_tail(terminator), t2); } return terminator; } @@ -347,10 +347,10 @@ begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes params[i] = param(a, shd_as_qualified_type(arg_types.nodes[i], false), NULL); } Node* loop_header = case_(a, shd_nodes(a, arg_types.count, params)); - set_abstraction_body(outer_control.case_, finish_body_with_jump(outer_control_case_builder, loop_header, initial_values)); + shd_set_abstraction_body(outer_control.case_, finish_body_with_jump(outer_control_case_builder, loop_header, initial_values)); BodyBuilder* loop_header_builder = begin_body_with_mem(a, shd_get_abstraction_mem(loop_header)); begin_control_t inner_control = begin_control(loop_header_builder, arg_types); - set_abstraction_body(loop_header, finish_body_with_jump(loop_header_builder, loop_header, inner_control.results)); + shd_set_abstraction_body(loop_header, finish_body_with_jump(loop_header_builder, loop_header, inner_control.results)); return (begin_loop_helper_t) { .results = outer_control.results, diff --git a/src/shady/compile.c b/src/shady/compile.c index 57be9d7f8..3dbe739b8 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -20,7 +20,7 @@ static void add_scheduler_source(const CompilerConfig* config, Module* dst) { }; Module* builtin_scheduler_mod = shd_parse_slim_module(config, &pconfig, shady_scheduler_src, "builtin_scheduler"); shd_debug_print("Adding builtin scheduler code"); - link_module(dst, builtin_scheduler_mod); + shd_module_link(dst, builtin_scheduler_mod); shd_destroy_ir_arena(shd_module_get_arena(builtin_scheduler_mod)); } diff --git a/src/shady/constructors.c b/src/shady/constructors.c index f6faa25c5..86366b1d6 100644 --- a/src/shady/constructors.c +++ b/src/shady/constructors.c @@ -236,16 +236,6 @@ const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes in return lea; } -const Node* unit_type(IrArena* arena) { - return record_type(arena, (RecordType) { - .members = shd_empty(arena), - }); -} - -const Node* empty_multiple_return_type(IrArena* arena) { - return shd_as_qualified_type(unit_type(arena), true); -} - const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w) { return int_type(a, (Int) { .width = w, .is_signed = s }); } const Type* shd_int8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = true }); } diff --git a/src/shady/fold.c b/src/shady/fold.c index 9f76685ef..2f86ae75d 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -94,10 +94,10 @@ break; case convert_op: { const Type* dst_t = shd_first(payload.type_arguments); uint64_t bitmask = 0; - if (get_type_bitwidth(dst_t) == 64) + if (shd_get_type_bitwidth(dst_t) == 64) bitmask = UINT64_MAX; else - bitmask = ~(UINT64_MAX << get_type_bitwidth(dst_t)); + bitmask = ~(UINT64_MAX << shd_get_type_bitwidth(dst_t)); if (dst_t->tag == Int_TAG) { if (all_int_literals) { uint64_t old_value = shd_get_int_literal_value(*int_literals[0], int_literals[0]->is_signed); diff --git a/src/shady/node.c b/src/shady/node.c index 0523ac4c7..4ae44de24 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -296,14 +296,14 @@ String shd_get_abstraction_name_safe(const Node* abs) { const Node* finish_block_body(BodyBuilder* bb, const Node* terminator); -void set_abstraction_body(Node* abs, const Node* body) { +void shd_set_abstraction_body(Node* abs, const Node* body) { assert(is_abstraction(abs)); assert(!body || is_terminator(body)); IrArena* a = abs->arena; if (body) { while (true) { - const Node* mem0 = get_original_mem(get_terminator_mem(body)); + const Node* mem0 = shd_get_original_mem(get_terminator_mem(body)); assert(mem0->tag == AbsMem_TAG); Node* mem_abs = mem0->payload.abs_mem.abs; if (is_basic_block(mem_abs)) { @@ -311,7 +311,7 @@ void set_abstraction_body(Node* abs, const Node* body) { if (insert && mem_abs != abs) { const Node* mem = insert->block_entry_mem; const Node* block = insert->block_entry_block; - set_abstraction_body((Node*) block, finish_block_body(insert, body)); + shd_set_abstraction_body((Node*) block, finish_block_body(insert, body)); body = jump_helper(a, mem, block, shd_empty(a)); // mem_abs->payload.basic_block.insert = NULL; continue; diff --git a/src/shady/node_helpers.c b/src/shady/node_helpers.c index 7ca4114d3..f8bd9f04f 100644 --- a/src/shady/node_helpers.c +++ b/src/shady/node_helpers.c @@ -4,7 +4,7 @@ #pragma GCC diagnostic error "-Wswitch" -const Node* get_parent_mem(const Node* mem) { +const Node* shd_get_parent_mem(const Node* mem) { assert(is_mem(mem)); switch (is_mem(mem)) { case NotAMem: return NULL; @@ -58,9 +58,9 @@ const Node* get_parent_mem(const Node* mem) { } } -const Node* get_original_mem(const Node* mem) { +const Node* shd_get_original_mem(const Node* mem) { while (true) { - const Node* nmem = get_parent_mem(mem); + const Node* nmem = shd_get_parent_mem(mem); if (nmem) { mem = nmem; continue; diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 8b0b4b5f5..0acf19f38 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -73,7 +73,7 @@ Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { return dst; } -void link_module(Module* dst, Module* src) { +void shd_module_link(Module* dst, Module* src) { Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) import_node), }; diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index a59b60f6c..c8c7d16cc 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -77,7 +77,7 @@ static const Node* process(Context* ctx, const Node* node) { } shd_register_processed(&fn_ctx->rewriter, node, new_bb); - set_abstraction_body(new_bb, shd_rewrite_node(&bb_ctx.rewriter, get_abstraction_body(node))); + shd_set_abstraction_body(new_bb, shd_rewrite_node(&bb_ctx.rewriter, get_abstraction_body(node))); shd_destroy_rewriter(&bb_ctx.rewriter); return new_bb; } diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 28133aa0a..4deac2290 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -155,7 +155,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { shd_destroy_rewriter(r); assert(is_terminator(substituted)); - set_abstraction_body(new_fn, finish_body(bb, substituted)); + shd_set_abstraction_body(new_fn, finish_body(bb, substituted)); return lifted_cont; } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 073ff2475..23f7ea224 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -85,7 +85,7 @@ static const Node* process(Context* ctx, const Node* node) { Context ctx2 = *ctx; ctx2.disable_lowering = shd_lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; if (ctx2.disable_lowering) { - set_abstraction_body(fun, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body)); + shd_set_abstraction_body(fun, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body)); return fun; } @@ -121,7 +121,7 @@ static const Node* process(Context* ctx, const Node* node) { // make sure to use the new mem from then on shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); - set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); + shd_set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); shd_destroy_dict(ctx2.prepared_offsets); return fun; diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index cee0fe3d7..8373ce59b 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -56,14 +56,14 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { shd_register_processed(&ctx->rewriter, old, fun); shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(prelude, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body))); - set_abstraction_body(fun, jump_helper(a, shd_get_abstraction_mem(fun), prelude, shd_empty(a))); + shd_set_abstraction_body(prelude, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body))); + shd_set_abstraction_body(fun, jump_helper(a, shd_get_abstraction_mem(fun), prelude, shd_empty(a))); return fun; } Node* fun = shd_recreate_node_head(&ctx->rewriter, old); if (old->payload.fun.body) - set_abstraction_body(fun, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body)); + shd_set_abstraction_body(fun, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body)); return fun; } @@ -137,7 +137,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .args = nargs, .mem = shd_get_abstraction_mem(control_case), }); - set_abstraction_body(control_case, control_body); + shd_set_abstraction_body(control_case, control_body); BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, gen_control(bb, strip_qualifiers(a, returned_types), control_case)); } diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index f3b7e4d51..8871309f9 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -28,7 +28,7 @@ static const Node* process_node(Context* ctx, const Node* node) { sub_ctx.disable_lowering = shd_lookup_annotation(fun, "Structured"); sub_ctx.current_fn = fun; sub_ctx.cfg = build_fn_cfg(node); - set_abstraction_body(fun, shd_rewrite_node(&sub_ctx.rewriter, node->payload.fun.body)); + shd_set_abstraction_body(fun, shd_rewrite_node(&sub_ctx.rewriter, node->payload.fun.body)); destroy_cfg(sub_ctx.cfg); return fun; } else if (node->tag == Constant_TAG) { @@ -63,7 +63,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } else { assert(yield_types.count == 0); false_block = basic_block(a, shd_nodes(a, 0, NULL), unique_name(a, "if_false")); - set_abstraction_body((Node*) false_block, join(a, (Join) { .join_point = jp, .args = shd_nodes(a, 0, NULL), .mem = shd_get_abstraction_mem(false_block) })); + shd_set_abstraction_body((Node*) false_block, join(a, (Join) { .join_point = jp, .args = shd_nodes(a, 0, NULL), .mem = shd_get_abstraction_mem(false_block) })); } Node* control_case = basic_block(a, shd_singleton(jp), NULL); @@ -73,7 +73,7 @@ static const Node* process_node(Context* ctx, const Node* node) { .false_jump = jump_helper(a, shd_get_abstraction_mem(control_case), false_block, shd_empty(a)), .mem = shd_get_abstraction_mem(control_case), }); - set_abstraction_body(control_case, control_body); + shd_set_abstraction_body(control_case, control_body); BodyBuilder* bb = begin_body_with_mem(a, nmem); Nodes results = gen_control(bb, yield_types, control_case); @@ -106,11 +106,11 @@ static const Node* process_node(Context* ctx, const Node* node) { BodyBuilder* inner_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_header_block)); Node* inner_control_case = case_(a, shd_singleton(continue_point)); - set_abstraction_body(inner_control_case, jump_helper(a, shd_get_abstraction_mem(inner_control_case), - shd_rewrite_node(r, old_loop_block), new_params)); + shd_set_abstraction_body(inner_control_case, jump_helper(a, shd_get_abstraction_mem(inner_control_case), + shd_rewrite_node(r, old_loop_block), new_params)); Nodes args = gen_control(inner_bb, param_types, inner_control_case); - set_abstraction_body(loop_header_block, finish_body(inner_bb, jump(a, (Jump) { .target = loop_header_block, .args = args, .mem = bb_mem(inner_bb) }))); + shd_set_abstraction_body(loop_header_block, finish_body(inner_bb, jump(a, (Jump) { .target = loop_header_block, .args = args, .mem = bb_mem(inner_bb) }))); Node* outer_control_case = case_(a, shd_singleton(break_point)); const Node* first_iteration_jump = jump(a, (Jump) { @@ -118,7 +118,7 @@ static const Node* process_node(Context* ctx, const Node* node) { .args = shd_rewrite_nodes(r, payload.initial_args), .mem = shd_get_abstraction_mem(outer_control_case), }); - set_abstraction_body(outer_control_case, first_iteration_jump); + shd_set_abstraction_body(outer_control_case, first_iteration_jump); BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); Nodes results = gen_control(bb, yield_types, outer_control_case); @@ -126,7 +126,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } case MergeSelection_TAG: { MergeSelection payload = node->payload.merge_selection; - const Node* root_mem = get_original_mem(payload.mem); + const Node* root_mem = shd_get_original_mem(payload.mem); assert(root_mem->tag == AbsMem_TAG); CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; @@ -160,7 +160,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } case MergeContinue_TAG: { MergeContinue payload = node->payload.merge_continue; - const Node* root_mem = get_original_mem(payload.mem); + const Node* root_mem = shd_get_original_mem(payload.mem); assert(root_mem->tag == AbsMem_TAG); CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; @@ -194,7 +194,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } case MergeBreak_TAG: { MergeBreak payload = node->payload.merge_break; - const Node* root_mem = get_original_mem(payload.mem); + const Node* root_mem = shd_get_original_mem(payload.mem); assert(root_mem->tag == AbsMem_TAG); CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index b9569c0bd..33b5d992d 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -80,7 +80,7 @@ static const Node* process(Context* ctx, const Node* node) { if (shd_lookup_annotation(node, "EntryPoint") && node->payload.fun.params.count > 0) { Node* new_entry_point = rewrite_entry_point_fun(ctx, node); const Node* arg_struct = generate_arg_struct(&ctx->rewriter, node, new_entry_point); - set_abstraction_body(new_entry_point, rewrite_body(ctx, node, new_entry_point, arg_struct)); + shd_set_abstraction_body(new_entry_point, rewrite_body(ctx, node, new_entry_point, arg_struct)); return new_entry_point; } break; diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 7cfdace08..8ca62c868 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -50,13 +50,13 @@ static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t const Node* generic_ptr_type = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false}); // first_non_tag_bit = nptr >> (64 - 2 - 1) - const Node* first_non_tag_bit = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth - 1))); + const Node* first_non_tag_bit = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, shd_get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth - 1))); // first_non_tag_bit &= 1 first_non_tag_bit = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); // needs_sign_extension = first_non_tag_bit == 1 const Node* needs_sign_extension = gen_primop_e(bb, eq_op, shd_empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); // sign_extension_patch = needs_sign_extension ? ((1 << 2) - 1) << (64 - 2) : 0 - const Node* sign_extension_patch = gen_primop_e(bb, select_op, shd_empty(a), mk_nodes(a, needs_sign_extension, size_t_literal(a, ((size_t) ((1 << max_tag) - 1)) << (get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth)), size_t_literal(a, 0))); + const Node* sign_extension_patch = gen_primop_e(bb, select_op, shd_empty(a), mk_nodes(a, needs_sign_extension, size_t_literal(a, ((size_t) ((1 << max_tag) - 1)) << (shd_get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth)), size_t_literal(a, 0))); // patched_ptr = nptr & 0b00111 ... 111 const Node* patched_ptr = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, SIZE_MAX >> generic_ptr_tag_bitwidth))); // patched_ptr = patched_ptr | sign_extension_patch @@ -119,7 +119,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { Node* tag_case = case_(a, shd_empty(a)); - set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(tag_case) })); + shd_set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(tag_case) })); jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); continue; } @@ -127,22 +127,22 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo BodyBuilder* case_bb = begin_body_with_mem(a, shd_get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); - set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_singleton(loaded_value))); + shd_set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_singleton(loaded_value))); jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example - const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); + const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, shd_empty(a)); - set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); - set_abstraction_body(r.case_, br_switch(a, (Switch) { + shd_set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); + shd_set_abstraction_body(r.case_, br_switch(a, (Switch) { .mem = shd_get_abstraction_mem(r.case_), .switch_value = extracted_tag, .case_values = shd_nodes(a, max_tag, literals), .case_jumps = shd_nodes(a, max_tag, jumps), .default_jump = jump_helper(a, shd_get_abstraction_mem(r.case_), default_case, shd_empty(a)) })); - set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_singleton(final_loaded_value), .mem = bb_mem(bb) }))); + shd_set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_singleton(final_loaded_value), .mem = bb_mem(bb) }))); break; } case StoreFn: { @@ -156,7 +156,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo literals[tag] = size_t_literal(a, tag); if (!allowed(ctx, generic_ptr_tags[tag])) { Node* tag_case = case_(a, shd_empty(a)); - set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(tag_case) })); + shd_set_abstraction_body(tag_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(tag_case) })); jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); continue; } @@ -164,22 +164,22 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo BodyBuilder* case_bb = begin_body_with_mem(a, shd_get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); - set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_empty(a))); + shd_set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_empty(a))); jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example - const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); + const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, shd_empty(a)); - set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); - set_abstraction_body(r.case_, br_switch(a, (Switch) { - .mem = shd_get_abstraction_mem(r.case_), - .switch_value = extracted_tag, - .case_values = shd_nodes(a, max_tag, literals), - .case_jumps = shd_nodes(a, max_tag, jumps), - .default_jump = jump_helper(a, shd_get_abstraction_mem(r.case_), default_case, shd_empty(a)) + shd_set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); + shd_set_abstraction_body(r.case_, br_switch(a, (Switch) { + .mem = shd_get_abstraction_mem(r.case_), + .switch_value = extracted_tag, + .case_values = shd_nodes(a, max_tag, literals), + .case_jumps = shd_nodes(a, max_tag, jumps), + .default_jump = jump_helper(a, shd_get_abstraction_mem(r.case_), default_case, shd_empty(a)) })); - set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); + shd_set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); break; } } @@ -251,7 +251,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* ptr_mask = size_t_literal(a, (UINT64_MAX >> (uint64_t) (generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr & 0x001111 ... 111 generic_ptr = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, generic_ptr, ptr_mask)); - const Node* shifted_tag = size_t_literal(a, (tag << (uint64_t) (get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); + const Node* shifted_tag = size_t_literal(a, (tag << (uint64_t) (shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr | 01000000 ... 000 generic_ptr = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, generic_ptr, shifted_tag)); return yield_values_and_wrap_in_block(bb, shd_singleton(generic_ptr)); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index ab2c011e5..93fc46fee 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -61,11 +61,11 @@ static const Node* process(Context* ctx, const Node* old) { const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); - set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = shd_get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); + shd_set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = shd_get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); Node* false_case = case_(a, shd_empty(a)); - set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = shd_get_abstraction_mem(false_case), .args = shd_empty(a) })); + shd_set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = shd_get_abstraction_mem(false_case), .args = shd_empty(a) })); - set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { + shd_set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { .mem = bb_mem(loop_bb), .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), .true_jump = jump_helper(a, bb_mem(loop_bb), true_case, shd_empty(a)), @@ -107,15 +107,15 @@ static const Node* process(Context* ctx, const Node* old) { const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); - set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = shd_get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); + shd_set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = shd_get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); Node* false_case = case_(a, shd_empty(a)); - set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = shd_get_abstraction_mem(false_case), .args = shd_empty(a) })); + shd_set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = shd_get_abstraction_mem(false_case), .args = shd_empty(a) })); - set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { - .mem = bb_mem(loop_bb), - .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), - .true_jump = jump_helper(a, bb_mem(loop_bb), true_case, shd_empty(a)), - .false_jump = jump_helper(a, bb_mem(loop_bb), false_case, shd_empty(a)), + shd_set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { + .mem = bb_mem(loop_bb), + .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), + .true_jump = jump_helper(a, bb_mem(loop_bb), true_case, shd_empty(a)), + .false_jump = jump_helper(a, bb_mem(loop_bb), false_case, shd_empty(a)), }))); return yield_values_and_wrap_in_block(bb, shd_empty(a)); } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index cc636234f..19c6d7155 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -277,11 +277,11 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { gen_serialisation(ctx, bb, element_type, base, address_param, value_param); - set_abstraction_body(fun, finish_body_with_return(bb, shd_empty(a))); + shd_set_abstraction_body(fun, finish_body_with_return(bb, shd_empty(a))); } else { const Node* loaded_value = gen_deserialisation(ctx, bb, element_type, base, address_param); assert(loaded_value); - set_abstraction_body(fun, finish_body_with_return(bb, shd_singleton(loaded_value))); + shd_set_abstraction_body(fun, finish_body_with_return(bb, shd_singleton(loaded_value))); } return fun; } @@ -350,7 +350,7 @@ static const Node* process_node(Context* ctx, const Node* old) { store_init_data(ctx, as, ctx->collected[as], bb); } shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); + shd_set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } break; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 39f97aa6c..7dcb8bf73 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -81,10 +81,10 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { } if (push) { - set_abstraction_body(fun, finish_body_with_return(bb, shd_empty(a))); + shd_set_abstraction_body(fun, finish_body_with_return(bb, shd_empty(a))); } else { assert(popped_value); - set_abstraction_body(fun, finish_body_with_return(bb, shd_singleton(popped_value))); + shd_set_abstraction_body(fun, finish_body_with_return(bb, shd_singleton(popped_value))); } return fun; } @@ -105,7 +105,7 @@ static const Node* process_node(Context* ctx, const Node* old) { gen_store(bb, stack_pointer, shd_uint32_literal(a, 0)); } shd_register_processed(r, shd_get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); + shd_set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 4f99cb314..604dd196f 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -89,7 +89,7 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* scope, const Node* BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fn)); const Node* result = generate(ctx, bb, scope, t, param); if (result) { - set_abstraction_body(fn, finish_body(bb, fn_ret(a, (Return) { + shd_set_abstraction_body(fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_singleton(result), .mem = bb_mem(bb), }))); diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index c605805bf..2094ed8e9 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -28,9 +28,9 @@ static const Node* process(Context* ctx, const Node* node) { functx.bb = begin_body_with_mem(a, shd_get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); shd_register_processed(&functx.rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(post_prelude)); - set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); - set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, - shd_empty(a)))); + shd_set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); + shd_set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, + shd_empty(a)))); shd_destroy_dict(functx.rewriter.map); } return newfun; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index e35f8fbe6..1d64a538b 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -98,7 +98,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { gen_call(bb, fn_addr_helper(a, *ctx->top_dispatcher_fn), shd_empty(a)); - set_abstraction_body(new_entry_pt, finish_body(bb, fn_ret(a, (Return) { + shd_set_abstraction_body(new_entry_pt, finish_body(bb, fn_ret(a, (Return) { .args = shd_nodes(a, 0, NULL), .mem = bb_mem(bb), }))); @@ -126,7 +126,7 @@ static const Node* process(Context* ctx, const Node* old) { gen_call(bb, fn_addr_helper(a, ctx2.init_fn), shd_empty(a)); } shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); + shd_set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); } destroy_uses_map(ctx2.uses); @@ -162,7 +162,7 @@ static const Node* process(Context* ctx, const Node* old) { shd_register_processed(&ctx->rewriter, old_param, popped); } shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); - set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); + shd_set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); destroy_uses_map(ctx2.uses); destroy_cfg(ctx2.cfg); return fun; @@ -259,7 +259,7 @@ static const Node* process(Context* ctx, const Node* old) { shd_register_processed(&ctx->rewriter, old_jp, new_jp); Node* new_control_case = case_(a, shd_singleton(new_jp)); shd_register_processed(r, payload.inside, new_control_case); - set_abstraction_body(new_control_case, shd_rewrite_node(&ctx->rewriter, get_abstraction_body(payload.inside))); + shd_set_abstraction_body(new_control_case, shd_rewrite_node(&ctx->rewriter, get_abstraction_body(payload.inside))); // BodyBuilder* bb = begin_body_with_mem(a, rewrite_node(r, payload.mem)); Nodes nyield_types = shd_rewrite_nodes(&ctx->rewriter, old->payload.control.yield_types); return control(a, (Control) { @@ -323,14 +323,14 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); Node* bail_case = case_(a, shd_empty(a)); const Node* break_terminator = join(a, (Join) { .args = shd_empty(a), .join_point = l.break_jp, .mem = shd_get_abstraction_mem(bail_case) }); - set_abstraction_body(bail_case, break_terminator); + shd_set_abstraction_body(bail_case, break_terminator); Node* proceed_case = case_(a, shd_empty(a)); - set_abstraction_body(proceed_case, join(a, (Join) { + shd_set_abstraction_body(proceed_case, join(a, (Join) { .join_point = c.jp, .mem = shd_get_abstraction_mem(proceed_case), .args = shd_empty(a), })); - set_abstraction_body(c.case_, branch(a, (Branch) { + shd_set_abstraction_body(c.case_, branch(a, (Branch) { .mem = shd_get_abstraction_mem(c.case_), .condition = bail_condition, .true_jump = jump_helper(a, shd_get_abstraction_mem(c.case_), bail_case, shd_empty(a)), @@ -350,7 +350,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } - set_abstraction_body(zero_if_true_lam, finish_body_with_join(zero_if_case_builder, l.break_jp, shd_empty(a))); + shd_set_abstraction_body(zero_if_true_lam, finish_body_with_join(zero_if_case_builder, l.break_jp, shd_empty(a))); Node* zero_if_false = case_(a, shd_empty(a)); BodyBuilder* zero_false_builder = begin_body_with_mem(a, shd_get_abstraction_mem(zero_if_false)); @@ -358,13 +358,13 @@ void generate_top_level_dispatch_fn(Context* ctx) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, zero_false_builder, BuiltinSubgroupId); gen_debug_printf(zero_false_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } - set_abstraction_body(zero_if_false, finish_body_with_join(zero_false_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); + shd_set_abstraction_body(zero_if_false, finish_body_with_join(zero_false_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); - set_abstraction_body(zero_case_lam, branch(a, (Branch) { - .mem = shd_get_abstraction_mem(zero_case_lam), - .condition = should_run, - .true_jump = jump_helper(a, shd_get_abstraction_mem(zero_case_lam), zero_if_true_lam, shd_empty(a)), - .false_jump = jump_helper(a, shd_get_abstraction_mem(zero_case_lam), zero_if_false, shd_empty(a)), + shd_set_abstraction_body(zero_case_lam, branch(a, (Branch) { + .mem = shd_get_abstraction_mem(zero_case_lam), + .condition = should_run, + .true_jump = jump_helper(a, shd_get_abstraction_mem(zero_case_lam), zero_if_true_lam, shd_empty(a)), + .false_jump = jump_helper(a, shd_get_abstraction_mem(zero_case_lam), zero_if_false, shd_empty(a)), })); const Node* zero_lit = shd_uint64_literal(a, 0); @@ -388,17 +388,17 @@ void generate_top_level_dispatch_fn(Context* ctx) { gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } gen_call(if_builder, fn_addr_helper(a, shd_rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); - set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); + shd_set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); Node* if_false = case_(a, shd_empty(a)); - set_abstraction_body(if_false, join(a, (Join) { + shd_set_abstraction_body(if_false, join(a, (Join) { .mem = shd_get_abstraction_mem(if_false), .join_point = l.continue_jp, .args = count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a) })); Node* fn_case = case_(a, shd_nodes(a, 0, NULL)); - set_abstraction_body(fn_case, branch(a, (Branch) { + shd_set_abstraction_body(fn_case, branch(a, (Branch) { .mem = shd_get_abstraction_mem(fn_case), .condition = should_run, .true_jump = jump_helper(a, shd_get_abstraction_mem(fn_case), if_true_case, shd_empty(a)), @@ -412,9 +412,9 @@ void generate_top_level_dispatch_fn(Context* ctx) { } Node* default_case = case_(a, shd_nodes(a, 0, NULL)); - set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); + shd_set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); - set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, br_switch(a, (Switch) { + shd_set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, br_switch(a, (Switch) { .mem = bb_mem(loop_body_builder), .switch_value = next_function, .case_values = shd_nodes(a, shd_list_count(literals), shd_read_list(const Node*, literals)), @@ -428,7 +428,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { if (ctx->config->printf_trace.god_function) gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", shd_empty(a)); - set_abstraction_body(*ctx->top_dispatcher_fn, finish_body(dispatcher_body_builder, fn_ret(a, (Return) { + shd_set_abstraction_body(*ctx->top_dispatcher_fn, finish_body(dispatcher_body_builder, fn_ret(a, (Return) { .args = shd_nodes(a, 0, NULL), .mem = bb_mem(dispatcher_body_builder), }))); @@ -445,7 +445,7 @@ Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) struct Dict* ptrs = shd_new_dict(const Node*, FnPtr, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); Node* init_fn = function(dst, shd_nodes(a, 0, NULL), "generated_init", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), shd_nodes(a, 0, NULL)); - set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(init_fn) })); + shd_set_abstraction_body(init_fn, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(init_fn) })); FnPtr next_fn_ptr = 1; diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 86d0fb94c..d194b6529 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -20,7 +20,7 @@ typedef struct { static void add_bounds_check(BodyBuilder* bb, const Node* i, const Node* max) { IrArena* a = bb->arena; Node* out_of_bounds_case = case_(a, shd_empty(a)); - set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) { + shd_set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(out_of_bounds_case) })); @@ -72,7 +72,7 @@ static const Node* process(Context* ctx, const Node* node) { Node* inner = function(m, nparams, shd_format_string_arena(a->arena, "%s_wrapped", shd_get_abstraction_name(node)), nannotations, shd_empty(a)); shd_register_processed_list(&ctx->rewriter, node->payload.fun.params, nparams); shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(inner)); - set_abstraction_body(inner, shd_recreate_node(&ctx->rewriter, node->payload.fun.body)); + shd_set_abstraction_body(inner, shd_recreate_node(&ctx->rewriter, node->payload.fun.body)); BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(wrapper)); const Node* num_workgroups_var = shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); @@ -157,7 +157,7 @@ static const Node* process(Context* ctx, const Node* node) { Node* loop_body = cases[depth]; BodyBuilder* body_bb = builders[depth]; - set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) { + shd_set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) { .args = shd_singleton(gen_primop_e(body_bb, add_op, shd_empty(a), mk_nodes(a, params[dim], shd_uint32_literal(a, 1)))), .mem = bb_mem(body_bb) }))); @@ -165,7 +165,7 @@ static const Node* process(Context* ctx, const Node* node) { } } - set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); + shd_set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); return wrapper; } return shd_recreate_node(&ctx2.rewriter, node); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index d9a03356a..02eb71da1 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -179,7 +179,7 @@ static const Node* process(Context* ctx, const Node* old) { fun_ctx.uses = create_fn_uses_map(old, (NcDeclaration | NcType)); fun_ctx.disable_lowering = shd_lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); if (old->payload.fun.body) - set_abstraction_body(fun, shd_rewrite_node(&fun_ctx.rewriter, old->payload.fun.body)); + shd_set_abstraction_body(fun, shd_rewrite_node(&fun_ctx.rewriter, old->payload.fun.body)); destroy_uses_map(fun_ctx.uses); return fun; } diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 4f3a88796..edf255d8b 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -180,7 +180,7 @@ static const Node* process(Context* ctx, const Node* node) { Node* control_case = case_(a, shd_singleton(join_point)); const Node* nbody = inline_call(ctx, ocallee, shd_get_abstraction_mem(control_case), nargs, join_point); - set_abstraction_body(control_case, nbody); + shd_set_abstraction_body(control_case, nbody); BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, control_case)); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 15de7a85b..d71def1b6 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -81,7 +81,7 @@ static const Node* get_last_stored_value(Context* ctx, const Node* ptr, const No } default: break; } - mem = get_parent_mem(mem); + mem = shd_get_parent_mem(mem); } return NULL; } diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/opt_restructure.c index 70d3ba639..70b92bd54 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/opt_restructure.c @@ -84,13 +84,13 @@ static DFSStackEntry* encountered_before(Context* ctx, const Node* bb, size_t* p static const Node* make_unreachable_case(IrArena* a) { Node* c = case_(a, shd_empty(a)); - set_abstraction_body(c, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(c) })); + shd_set_abstraction_body(c, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(c) })); return c; } static const Node* make_selection_merge_case(IrArena* a) { Node* c = case_(a, shd_empty(a)); - set_abstraction_body(c, merge_selection(a, (MergeSelection) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(c) })); + shd_set_abstraction_body(c, merge_selection(a, (MergeSelection) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(c) })); return c; } @@ -154,7 +154,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old_target), shd_get_abstraction_mem(structured_target)); const Node* structured = structure(&ctx2, get_abstraction_body(old_target), inner_exit_ladder_bb); assert(is_terminator(structured)); - set_abstraction_body(structured_target, structured); + shd_set_abstraction_body(structured_target, structured); // forget we rewrote all that shd_destroy_dict(tmp_processed); @@ -165,13 +165,13 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, // Use the structured target as the body of a loop gen_loop(bb, shd_empty(a), shd_rewrite_nodes(&ctx->rewriter, oargs), structured_target); // The exit ladder must exit that new loop - set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(inner_exit_ladder_bb) })); + shd_set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(inner_exit_ladder_bb) })); // After that we jump to the parent exit return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); } else { // Simply jmp to the exit once done - set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, shd_get_abstraction_mem(inner_exit_ladder_bb), exit, - shd_empty(a))); + shd_set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, shd_get_abstraction_mem(inner_exit_ladder_bb), exit, + shd_empty(a))); // Jump into the new structured target return finish_body(bb, jump_helper(a, bb_mem(bb), structured_target, shd_rewrite_nodes(&ctx->rewriter, oargs))); } @@ -209,10 +209,10 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { shd_rewrite_node(r, payload.mem); Node* true_case = case_(a, shd_empty(a)); - set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, shd_get_abstraction_mem(true_case), make_selection_merge_case(a))); + shd_set_abstraction_body(true_case, handle_bb_callsite(ctx, payload.true_jump->payload.jump, shd_get_abstraction_mem(true_case), make_selection_merge_case(a))); Node* false_case = case_(a, shd_empty(a)); - set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, shd_get_abstraction_mem(false_case), make_selection_merge_case(a))); + shd_set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, shd_get_abstraction_mem(false_case), make_selection_merge_case(a))); BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); gen_if(bb, shd_empty(a), condition, true_case, false_case); @@ -224,12 +224,12 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { shd_rewrite_node(r, payload.mem); Node* default_case = case_(a, shd_empty(a)); - set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, shd_get_abstraction_mem(default_case), make_selection_merge_case(a))); + shd_set_abstraction_body(default_case, handle_bb_callsite(ctx, payload.default_jump->payload.jump, shd_get_abstraction_mem(default_case), make_selection_merge_case(a))); LARRAY(Node*, cases, body->payload.br_switch.case_jumps.count); for (size_t i = 0; i < body->payload.br_switch.case_jumps.count; i++) { cases[i] = case_(a, shd_empty(a)); - set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, shd_get_abstraction_mem(cases[i]), make_selection_merge_case(a))); + shd_set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, shd_get_abstraction_mem(cases[i]), make_selection_merge_case(a))); } BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); @@ -282,9 +282,9 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { const Node* guard = prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, shd_int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }); Node* true_case = case_(a, shd_empty(a)); shd_register_processed(r, shd_get_abstraction_mem(get_structured_construct_tail(body)), shd_get_abstraction_mem(true_case)); - set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); + shd_set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); gen_if(bb_tail, shd_empty(a), guard, true_case, NULL); - set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, bb_mem(bb_tail), exit, shd_empty(a)))); + shd_set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, bb_mem(bb_tail), exit, shd_empty(a)))); shd_register_processed(r, shd_get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); return finish_body(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); @@ -349,7 +349,7 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.lower = false; ctx2.rewriter.map = ctx->rewriter.map; if (node->payload.fun.body) - set_abstraction_body(new, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body)); + shd_set_abstraction_body(new, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body)); // builtin functions are always considered leaf functions is_leaf = is_builtin || !node->payload.fun.body; } else { @@ -367,7 +367,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), bb_mem(bb)); - set_abstraction_body(new, finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); + shd_set_abstraction_body(new, finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. shd_list_pop_impl(ctx->cleanup_stack); diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index be73f90f5..0a1b2e725 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -175,7 +175,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .args = continue_wrapper_params, .mem = shd_get_abstraction_mem(continue_wrapper), }); - set_abstraction_body(continue_wrapper, continue_wrapper_body); + shd_set_abstraction_body(continue_wrapper, continue_wrapper_body); // replace the exit nodes by the exit wrappers LARRAY(const Node**, cached_exits, exiting_nodes_count); @@ -218,10 +218,10 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (exiting_nodes_count > 1) gen_store(exit_wrapper_bb, exit_destination_alloca, shd_int32_literal(arena, i)); - set_abstraction_body(exits[i].wrapper, finish_body_with_join(exit_wrapper_bb, join_token_exit, shd_empty(arena))); + shd_set_abstraction_body(exits[i].wrapper, finish_body_with_join(exit_wrapper_bb, join_token_exit, shd_empty(arena))); } - set_abstraction_body(inner_control_case, loop_body); + shd_set_abstraction_body(inner_control_case, loop_body); shd_destroy_dict(rewriter->map); rewriter->map = old_map; @@ -245,9 +245,9 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (is_qualified_type_uniform(nparams.nodes[j]->type)) inner_control_results = shd_change_node_at_index(arena, inner_control_results, j, prim_op_helper(arena, subgroup_assume_uniform_op, shd_empty(arena), shd_singleton(inner_control_results.nodes[j]))); } - set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); + shd_set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); Node* outer_control_case = case_(arena, shd_singleton(join_token_exit)); - set_abstraction_body(outer_control_case, jump(arena, (Jump) { + shd_set_abstraction_body(outer_control_case, jump(arena, (Jump) { .target = loop_outer, .args = nparams, .mem = shd_get_abstraction_mem(outer_control_case), @@ -272,7 +272,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { } exit_numbers[i] = shd_int32_literal(arena, i); - set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, shd_nodes(arena, exits[i].params_count, recovered_args))); + shd_set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, shd_nodes(arena, exits[i].params_count, recovered_args))); exit_jumps[i] = jump_helper(arena, bb_mem(outer_bb), exit_bb, shd_empty(arena)); } @@ -289,7 +289,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { .mem = bb_mem(outer_bb) })); } - set_abstraction_body(loop_container, outer_body); + shd_set_abstraction_body(loop_container, outer_body); shd_destroy_list(exiting_nodes); return loop_container; } @@ -433,7 +433,7 @@ static const Node* process_node(Context* ctx, const Node* node) { }), true), "jp_postdom"); Node* pre_join = basic_block(a, exit_args, shd_format_string_arena(a->arena, "merge_%s_%s", shd_get_abstraction_name_safe(ctx->current_abstraction), shd_get_abstraction_name_safe(post_dominator))); - set_abstraction_body(pre_join, join(a, (Join) { + shd_set_abstraction_body(pre_join, join(a, (Join) { .join_point = join_token, .args = exit_args, .mem = shd_get_abstraction_mem(pre_join), @@ -459,7 +459,7 @@ static const Node* process_node(Context* ctx, const Node* node) { shd_rewrite_node(r, payload.false_jump->payload.jump.target), shd_rewrite_nodes(r, payload.false_jump->payload.jump.args)), }); - set_abstraction_body(control_case, inner_terminator); + shd_set_abstraction_body(control_case, inner_terminator); shd_dict_remove(const Node*, is_declaration(post_dominator) ? r->decls_map : r->map, post_dominator); if (cached) diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index eab6fa0f0..d1cfb1bd9 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -18,9 +18,9 @@ static const Node* process(Context* ctx, const Node* node) { case Jump_TAG: { Jump payload = node->payload.jump; Node* new_block = basic_block(a, shd_empty(a), NULL); - set_abstraction_body(new_block, jump_helper(a, shd_get_abstraction_mem(new_block), - shd_rewrite_node(r, payload.target), - shd_rewrite_nodes(r, payload.args))); + shd_set_abstraction_body(new_block, jump_helper(a, shd_get_abstraction_mem(new_block), + shd_rewrite_node(r, payload.target), + shd_rewrite_nodes(r, payload.args))); return jump_helper(a, shd_rewrite_node(r, payload.mem), new_block, shd_empty(a)); } default: break; diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 486a2f8fe..5a9c9a0d9 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -107,14 +107,14 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab Controls* controls = get_or_create_controls(ctx, oabs); - set_abstraction_body(oc, shd_rewrite_node(r, obody)); + shd_set_abstraction_body(oc, shd_rewrite_node(r, obody)); size_t i = 0; AddControl add_control; while(shd_dict_iter(controls->control_destinations, &i, NULL, &add_control)) { const Node* dst = add_control.destination; Node* control_case = case_(a, shd_singleton(add_control.token)); - set_abstraction_body(control_case, jump_helper(a, shd_get_abstraction_mem(control_case), c, shd_empty(a))); + shd_set_abstraction_body(control_case, jump_helper(a, shd_get_abstraction_mem(control_case), c, shd_empty(a))); Node* c2 = case_(a, shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(c2)); @@ -130,11 +130,11 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab } c = c2; - set_abstraction_body(c2, finish_body(bb, jump_helper(a, bb_mem(bb), shd_find_processed(r, dst), results))); + shd_set_abstraction_body(c2, finish_body(bb, jump_helper(a, bb_mem(bb), shd_find_processed(r, dst), results))); } const Node* body = jump_helper(a, shd_get_abstraction_mem(nabs), c, shd_empty(a)); - set_abstraction_body(nabs, body); + shd_set_abstraction_body(nabs, body); } bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { @@ -157,7 +157,7 @@ static const Nodes* find_scope_info(const Node* abs) { if (!info || info->count > mem->payload.ext_instr.operands.count) info = &mem->payload.ext_instr.operands; } - mem = get_parent_mem(mem); + mem = shd_get_parent_mem(mem); } return info; } diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index f7a7ad79e..d249c404e 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -176,7 +176,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), shd_empty(a)); shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); - set_abstraction_body(new_fn, finish_body(bb, shd_rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); + shd_set_abstraction_body(new_fn, finish_body(bb, shd_rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); destroy_cfg(fn_ctx.cfg); free(fn_ctx.depth_per_rpo); return new_fn; @@ -190,7 +190,7 @@ static const Node* process(Context* ctx, const Node* node) { CFNode* n = cfg_lookup(ctx->cfg, node); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); - set_abstraction_body(new_bb, finish_body(bb, shd_rewrite_node(r, get_abstraction_body(node)))); + shd_set_abstraction_body(new_bb, finish_body(bb, shd_rewrite_node(r, get_abstraction_body(node)))); return new_bb; } default: break; diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 9bf12829d..b6229b3d2 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -36,7 +36,7 @@ static const Node* process(Context* ctx, const Node* node) { } shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), bb_mem(bb)); if (node->payload.fun.body) - set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body))); + shd_set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body))); else cancel_body(bb); return fun; diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index d638b0a77..ccfc674d9 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -319,7 +319,7 @@ void shd_recreate_node_body(Rewriter* rewriter, const Node* old, Node* new) { } case Function_TAG: { assert(new->payload.fun.body == NULL); - set_abstraction_body(new, rewrite_op_helper(rewriter, NcTerminator, "body", old->payload.fun.body)); + shd_set_abstraction_body(new, rewrite_op_helper(rewriter, NcTerminator, "body", old->payload.fun.body)); break; } case NominalType_TAG: { @@ -360,7 +360,7 @@ const Node* shd_recreate_node(Rewriter* rewriter, const Node* node) { Node* bb = basic_block(arena, params, node->payload.basic_block.name); shd_register_processed(rewriter, node, bb); const Node* nterminator = rewrite_op_helper(rewriter, NcTerminator, "body", node->payload.basic_block.body); - set_abstraction_body(bb, nterminator); + shd_set_abstraction_body(bb, nterminator); return bb; } } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index bd0f74030..93ad64f34 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -100,7 +100,7 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { lo = gen_conversion(bb, dst_type, lo); hi = gen_conversion(bb, dst_type, hi); // shift hi - const Node* shift_by = int_literal(bb->arena, (IntLiteral) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed, .value = get_type_bitwidth(src_type) }); + const Node* shift_by = int_literal(bb->arena, (IntLiteral) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed, .value = shd_get_type_bitwidth(src_type) }); hi = gen_primop_ce(bb, lshift_op, 2, (const Node* []) { hi, shift_by}); // Merge the two return gen_primop_ce(bb, or_op, 2, (const Node* []) { lo, hi }); diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index dc13b6d6a..2a121fcb2 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -114,7 +114,7 @@ TypeMemLayout shd_get_mem_layout(IrArena* a, const Type* type) { const Node* shd_bytes_to_words(BodyBuilder* bb, const Node* bytes) { IrArena* a = bytes->arena; const Type* word_type = int_type(a, (Int) { .width = shd_get_arena_config(a)->memory.word_size, .is_signed = false }); - size_t word_width = get_type_bitwidth(word_type); + size_t word_width = shd_get_type_bitwidth(word_type); const Node* bytes_per_word = size_t_literal(a, word_width / 8); return gen_primop_e(bb, div_op, shd_empty(a), mk_nodes(a, bytes, bytes_per_word)); } diff --git a/src/shady/type.c b/src/shady/type.c index 8f7a2f302..cded258bb 100644 --- a/src/shady/type.c +++ b/src/shady/type.c @@ -154,7 +154,7 @@ void check_subtype(const Type* supertype, const Type* type) { } } -size_t get_type_bitwidth(const Type* t) { +size_t shd_get_type_bitwidth(const Type* t) { switch (t->tag) { case Int_TAG: return int_size_in_bytes(t->payload.int_type.width) * 8; case Float_TAG: return float_size_in_bytes(t->payload.float_type.width) * 8; @@ -302,7 +302,7 @@ bool is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type) { return false; if (!(is_arithm_type(dst_type) || dst_type->tag == MaskType_TAG || is_physical_ptr_type(dst_type))) return false; - assert(get_type_bitwidth(src_type) == get_type_bitwidth(dst_type)); + assert(shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)); // either both pointers need to be in the generic address space, and we're only casting the element type, OR neither can be if ((is_physical_ptr_type(src_type) && is_physical_ptr_type(dst_type)) && (is_generic_ptr_type(src_type) != is_generic_ptr_type(dst_type))) return false; @@ -311,9 +311,9 @@ bool is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type) { bool is_conversion_legal(const Type* src_type, const Type* dst_type) { assert(is_data_type(src_type) && is_data_type(dst_type)); - if (!(is_arithm_type(src_type) || (is_physical_ptr_type(src_type) && get_type_bitwidth(src_type) == get_type_bitwidth(dst_type)))) + if (!(is_arithm_type(src_type) || (is_physical_ptr_type(src_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) return false; - if (!(is_arithm_type(dst_type) || (is_physical_ptr_type(dst_type) && get_type_bitwidth(src_type) == get_type_bitwidth(dst_type)))) + if (!(is_arithm_type(dst_type) || (is_physical_ptr_type(dst_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) return false; // we only allow ptr-ptr conversions, use reinterpret otherwise if (is_physical_ptr_type(src_type) != is_physical_ptr_type(dst_type)) diff --git a/test/test_builder.c b/test/test_builder.c index 5d2c69124..53e71ef9e 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -43,7 +43,7 @@ static void test_body_builder_fun_body(IrArena* a) { Node* true_case = case_(a, shd_empty(a)); BodyBuilder* tc_builder = begin_body_with_mem(a, shd_get_abstraction_mem(true_case)); gen_store(tc_builder, p1, shd_uint32_literal(a, 0)); - set_abstraction_body(true_case, finish_body_with_selection_merge(tc_builder, shd_empty(a))); + shd_set_abstraction_body(true_case, finish_body_with_selection_merge(tc_builder, shd_empty(a))); gen_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, shd_uint32_literal(a, 0))), true_case, NULL); const Node* p2_value = gen_load(bb, p2); @@ -53,7 +53,7 @@ static void test_body_builder_fun_body(IrArena* a) { .mem = bb_mem(bb), .args = shd_singleton(sum) }); - set_abstraction_body(fun, finish_body(bb, return_terminator)); + shd_set_abstraction_body(fun, finish_body(bb, return_terminator)); // set_abstraction_body(fun, finish_body_with_return(bb, singleton(sum))); shd_dump_module(m); @@ -62,7 +62,7 @@ static void test_body_builder_fun_body(IrArena* a) { CFG* cfg = build_fn_cfg(fun); const Node* mem = get_terminator_mem(return_terminator); do { - const Node* omem = get_original_mem(mem); + const Node* omem = shd_get_original_mem(mem); if (!omem) break; mem = omem; @@ -78,12 +78,12 @@ static void test_body_builder_fun_body(IrArena* a) { } break; } while (1); - mem = get_original_mem(mem); + mem = shd_get_original_mem(mem); CHECK(mem == shd_get_abstraction_mem(fun), exit(-1)); destroy_cfg(cfg); } -/// There is some "magic" code in body_builder and set_abstraction_body to enable inserting control-flow +/// There is some "magic" code in body_builder and shd_set_abstraction_body to enable inserting control-flow /// where there is only a mem dependency. This is useful when writing some complex polyfills. static void test_body_builder_impure_block(IrArena* a) { Module* m = shd_new_module(a, "test_module"); @@ -107,7 +107,7 @@ static void test_body_builder_impure_block(IrArena* a) { .mem = bb_mem(bb), .args = shd_singleton(sum) }); - set_abstraction_body(fun, finish_body(bb, return_terminator)); + shd_set_abstraction_body(fun, finish_body(bb, return_terminator)); shd_dump_module(m); @@ -116,13 +116,13 @@ static void test_body_builder_impure_block(IrArena* a) { while (mem) { if (mem->tag == Store_TAG) found_store = true; - mem = get_parent_mem(mem); + mem = shd_get_parent_mem(mem); } CHECK(found_store, exit(-1)); } -/// There is some "magic" code in body_builder and set_abstraction_body to enable inserting control-flow +/// There is some "magic" code in body_builder and shd_set_abstraction_body to enable inserting control-flow /// where there is only a mem dependency. This is useful when writing some complex polyfills. static void test_body_builder_impure_block_with_control_flow(IrArena* a) { Module* m = shd_new_module(a, "test_module"); @@ -139,7 +139,7 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { Node* if_true_case = case_(a, shd_empty(a)); BodyBuilder* if_true_builder = begin_body_with_mem(a, shd_get_abstraction_mem(if_true_case)); gen_store(if_true_builder, p1, shd_uint32_literal(a, 0)); - set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_true_builder, shd_empty(a))); + shd_set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_true_builder, shd_empty(a))); gen_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, shd_uint32_literal(a, 0))), if_true_case, NULL); bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, shd_empty(a))); @@ -150,7 +150,7 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { .mem = bb_mem(bb), .args = shd_singleton(sum) }); - set_abstraction_body(fun, finish_body(bb, return_terminator)); + shd_set_abstraction_body(fun, finish_body(bb, return_terminator)); shd_dump_module(m); } From fa74d55926f4b0f6cc6e7dead31ae5cd00658a7a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 8 Oct 2024 10:57:58 +0200 Subject: [PATCH 636/693] prefixed all the passes --- src/backend/c/emit_c.c | 6 +- src/backend/spirv/emit_spv.c | 14 +-- src/backend/spirv/spirv_lift_globals_ssbo.c | 2 +- src/backend/spirv/spirv_map_entrypoint_args.c | 2 +- src/frontend/slim/slim_driver.c | 4 +- src/shady/compile.c | 78 ++++++++--------- src/shady/passes/CMakeLists.txt | 2 +- src/shady/passes/cleanup.c | 22 ++--- src/shady/passes/eliminate_constants.c | 4 +- src/shady/passes/import.c | 2 +- src/shady/passes/lcssa.c | 8 +- src/shady/passes/lift_everything.c | 2 +- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_callf.c | 2 +- src/shady/passes/lower_cf_instrs.c | 2 +- src/shady/passes/lower_decay_ptrs.c | 2 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_fill.c | 2 +- src/shady/passes/lower_generic_globals.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 2 +- src/shady/passes/lower_int64.c | 2 +- src/shady/passes/lower_lea.c | 2 +- src/shady/passes/lower_logical_pointers.c | 2 +- src/shady/passes/lower_mask.c | 2 +- src/shady/passes/lower_memcpy.c | 2 +- src/shady/passes/lower_memory_layout.c | 2 +- src/shady/passes/lower_nullptr.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 2 +- src/shady/passes/lower_stack.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_subgroup_vars.c | 2 +- src/shady/passes/lower_switch_btree.c | 2 +- src/shady/passes/lower_tailcalls.c | 4 +- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/mark_leaf_functions.c | 2 +- src/shady/passes/normalize_builtins.c | 2 +- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/opt_inline.c | 6 +- src/shady/passes/opt_mem2reg.c | 4 +- src/shady/passes/passes.h | 85 +++++++++---------- src/shady/passes/reconvergence_heuristics.c | 2 +- src/shady/passes/remove_critical_edges.c | 2 +- .../{opt_restructure.c => restructure.c} | 2 +- src/shady/passes/scope2control.c | 2 +- src/shady/passes/scope_heuristic.c | 2 +- src/shady/passes/setup_stack_frames.c | 2 +- src/shady/passes/specialize_entry_point.c | 2 +- src/shady/passes/specialize_execution_model.c | 2 +- test/opt/opt_oracle.c | 2 +- 51 files changed, 156 insertions(+), 159 deletions(-) rename src/shady/passes/{opt_restructure.c => restructure.c} (99%) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 67d6bd1fb..595070d70 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -378,12 +378,12 @@ static Module* run_backend_specific_passes(const CompilerConfig* config, CEmitte Module** pmod = &initial_mod; // C lacks a nice way to express constants that can be used in type definitions afterwards, so let's just inline them all. - RUN_PASS(eliminate_constants) + RUN_PASS(shd_pass_eliminate_constants) if (econfig->dialect == CDialect_ISPC) { - RUN_PASS(lower_workgroups) + RUN_PASS(shd_pass_lower_workgroups) } if (econfig->dialect != CDialect_GLSL) { - RUN_PASS(lower_vec_arr) + RUN_PASS(shd_pass_lower_vec_arr) } return *pmod; } diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 04ce0726f..0be6b5885 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -311,18 +311,18 @@ SpvId spv_get_extended_instruction_set(Emitter* emitter, const char* name) { return new; } -RewritePass spirv_map_entrypoint_args; -RewritePass spirv_lift_globals_ssbo; +RewritePass shd_spvbe_pass_map_entrypoint_args; +RewritePass shd_spvbe_pass_lift_globals_ssbo; static Module* run_backend_specific_passes(const CompilerConfig* config, Module* initial_mod) { IrArena* initial_arena = initial_mod->arena; Module** pmod = &initial_mod; - RUN_PASS(lower_entrypoint_args) - RUN_PASS(spirv_map_entrypoint_args) - RUN_PASS(spirv_lift_globals_ssbo) - RUN_PASS(eliminate_constants) - RUN_PASS(import) + RUN_PASS(shd_pass_lower_entrypoint_args) + RUN_PASS(shd_spvbe_pass_map_entrypoint_args) + RUN_PASS(shd_spvbe_pass_lift_globals_ssbo) + RUN_PASS(shd_pass_eliminate_constants) + RUN_PASS(shd_import) return *pmod; } diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 70d82787e..1e51778d9 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -62,7 +62,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* spirv_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_spvbe_pass_lift_globals_ssbo(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index 9bb79c999..6465b08e7 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -57,7 +57,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* spirv_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_spvbe_pass_map_entrypoint_args(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/frontend/slim/slim_driver.c b/src/frontend/slim/slim_driver.c index 4bdd559a6..95450e4be 100644 --- a/src/frontend/slim/slim_driver.c +++ b/src/frontend/slim/slim_driver.c @@ -37,9 +37,9 @@ Module* shd_parse_slim_module(const CompilerConfig* config, const SlimParserConf RUN_PASS(slim_pass_bind) RUN_PASS(slim_pass_normalize) - RUN_PASS(normalize_builtins) + RUN_PASS(shd_pass_normalize_builtins) RUN_PASS(slim_pass_infer) - RUN_PASS(lower_cf_instrs) + RUN_PASS(shd_pass_lower_cf_instrs) shd_destroy_ir_arena(initial_arena); return *pmod; diff --git a/src/shady/compile.c b/src/shady/compile.c index 3dbe739b8..addf72b34 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -42,7 +42,7 @@ void shd_run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* ini shd_destroy_ir_arena(shd_module_get_arena(old_mod)); old_mod = *pmod; if (config->optimisations.cleanup.after_every_pass) - *pmod = cleanup(config, *pmod); + *pmod = shd_cleanup(config, *pmod); shd_log_module(DEBUGVV, config, *pmod); if (SHADY_RUN_VERIFY) verify_module(config, *pmod); @@ -66,77 +66,77 @@ CompilationResult shd_run_compiler_passes(CompilerConfig* config, Module** pmod) IrArena* initial_arena = (*pmod)->arena; // we don't want to mess with the original module - *pmod = import(config, *pmod); + *pmod = shd_import(config, *pmod); shd_log_fmt(DEBUG, "After import:\n"); shd_log_module(DEBUG, config, *pmod); if (config->input_cf.has_scope_annotations) { - // RUN_PASS(scope_heuristic) - RUN_PASS(lift_everything) - RUN_PASS(scope2control) + // RUN_PASS(shd_pass_scope_heuristic) + RUN_PASS(shd_pass_lift_everything) + RUN_PASS(shd_pass_scope2control) } else if (config->input_cf.restructure_with_heuristics) { - RUN_PASS(remove_critical_edges) - // RUN_PASS(lcssa) - RUN_PASS(lift_everything) - RUN_PASS(reconvergence_heuristics) + RUN_PASS(shd_pass_remove_critical_edges) + // RUN_PASS(shd_pass_lcssa) + RUN_PASS(shd_pass_lift_everything) + RUN_PASS(shd_pass_reconvergence_heuristics) } if (config->dynamic_scheduling) { add_scheduler_source(config, *pmod); } - RUN_PASS(eliminate_inlineable_constants) + RUN_PASS(shd_pass_eliminate_inlineable_constants) - RUN_PASS(setup_stack_frames) + RUN_PASS(shd_pass_setup_stack_frames) if (!config->hacks.force_join_point_lifting) - RUN_PASS(mark_leaf_functions) + RUN_PASS(shd_pass_mark_leaf_functions) - RUN_PASS(lower_callf) - RUN_PASS(opt_inline) + RUN_PASS(shd_pass_lower_callf) + RUN_PASS(shd_pass_inline) - RUN_PASS(lift_indirect_targets) + RUN_PASS(shd_pass_lift_indirect_targets) - RUN_PASS(specialize_execution_model) + RUN_PASS(shd_pass_specialize_execution_model) - //RUN_PASS(opt_stack) + //RUN_PASS(shd_pass_opt_stack) - RUN_PASS(lower_tailcalls) - //RUN_PASS(lower_switch_btree) - //RUN_PASS(opt_mem2reg) + RUN_PASS(shd_pass_lower_tailcalls) + //RUN_PASS(shd_pass_lower_switch_btree) + //RUN_PASS(shd_pass_opt_mem2reg) if (config->specialization.entry_point) - RUN_PASS(specialize_entry_point) + RUN_PASS(shd_pass_specialize_entry_point) - RUN_PASS(lower_logical_pointers) + RUN_PASS(shd_pass_lower_logical_pointers) - RUN_PASS(lower_mask) - RUN_PASS(lower_subgroup_ops) + RUN_PASS(shd_pass_lower_mask) + RUN_PASS(shd_pass_lower_subgroup_ops) if (config->lower.emulate_physical_memory) { - RUN_PASS(lower_alloca) + RUN_PASS(shd_pass_lower_alloca) } - RUN_PASS(lower_stack) - RUN_PASS(lower_memcpy) - RUN_PASS(lower_lea) - RUN_PASS(lower_generic_globals) + RUN_PASS(shd_pass_lower_stack) + RUN_PASS(shd_pass_lower_memcpy) + RUN_PASS(shd_pass_lower_lea) + RUN_PASS(shd_pass_lower_generic_globals) if (config->lower.emulate_generic_ptrs) { - RUN_PASS(lower_generic_ptrs) + RUN_PASS(shd_pass_lower_generic_ptrs) } if (config->lower.emulate_physical_memory) { - RUN_PASS(lower_physical_ptrs) + RUN_PASS(shd_pass_lower_physical_ptrs) } - RUN_PASS(lower_subgroup_vars) - RUN_PASS(lower_memory_layout) + RUN_PASS(shd_pass_lower_subgroup_vars) + RUN_PASS(shd_pass_lower_memory_layout) if (config->lower.decay_ptrs) - RUN_PASS(lower_decay_ptrs) + RUN_PASS(shd_pass_lower_decay_ptrs) - RUN_PASS(lower_int) + RUN_PASS(shd_pass_lower_int) - RUN_PASS(lower_fill) - RUN_PASS(lower_nullptr) - RUN_PASS(normalize_builtins) + RUN_PASS(shd_pass_lower_fill) + RUN_PASS(shd_pass_lower_nullptr) + RUN_PASS(shd_pass_normalize_builtins) - RUN_PASS(opt_restructurize) + RUN_PASS(shd_pass_restructurize) return CompilationNoError; } diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index 227396f77..7b329ad78 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -28,7 +28,7 @@ target_sources(shady PRIVATE lower_generic_globals.c mark_leaf_functions.c opt_inline.c - opt_restructure.c + restructure.c opt_demote_alloca.c opt_mem2reg.c specialize_entry_point.c diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 32b1ba4b7..22c9292b5 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -42,7 +42,7 @@ static bool is_used_as_value(const UsesMap* map, const Node* instr) { return false; } -const Node* process(Context* ctx, const Node* old) { +static const Node* process(Context* ctx, const Node* old) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; if (old->tag == Function_TAG || old->tag == Constant_TAG) { @@ -117,9 +117,9 @@ const Node* process(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -OptPass simplify; +OptPass shd_opt_simplify; -bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { +bool shd_opt_simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { Module* src = *m; IrArena* a = shd_module_get_arena(src); @@ -132,11 +132,11 @@ bool simplify(SHADY_UNUSED const CompilerConfig* config, Module** m) { return todo; } -OptPass opt_demote_alloca; -OptPass opt_mem2reg; -RewritePass import; +OptPass shd_opt_demote_alloca; +OptPass shd_opt_mem2reg; +RewritePass shd_import; -Module* cleanup(const CompilerConfig* config, Module* const src) { +Module* shd_cleanup(const CompilerConfig* config, Module* const src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); if (!aconfig.check_types) return src; @@ -148,9 +148,9 @@ Module* cleanup(const CompilerConfig* config, Module* const src) { todo = false; shd_debugv_print("Cleanup round %d\n", r); - APPLY_OPT(opt_demote_alloca); - APPLY_OPT(opt_mem2reg); - APPLY_OPT(simplify); + APPLY_OPT(shd_opt_demote_alloca); + APPLY_OPT(shd_opt_mem2reg); + APPLY_OPT(shd_opt_simplify); changed_at_all |= todo; @@ -158,5 +158,5 @@ Module* cleanup(const CompilerConfig* config, Module* const src) { } while (todo); if (changed_at_all) shd_debugv_print("After %d rounds of cleanup:\n", r); - return import(config, m); + return shd_import(config, m); } diff --git a/src/shady/passes/eliminate_constants.c b/src/shady/passes/eliminate_constants.c index 51e364a18..a3b6301ff 100644 --- a/src/shady/passes/eliminate_constants.c +++ b/src/shady/passes/eliminate_constants.c @@ -47,10 +47,10 @@ static Module* eliminate_constants_(SHADY_UNUSED const CompilerConfig* config, M return dst; } -Module* eliminate_constants(const CompilerConfig* config, Module* src) { +Module* shd_pass_eliminate_constants(const CompilerConfig* config, Module* src) { return eliminate_constants_(config, src, true); } -Module* eliminate_inlineable_constants(const CompilerConfig* config, Module* src) { +Module* shd_pass_eliminate_inlineable_constants(const CompilerConfig* config, Module* src) { return eliminate_constants_(config, src, false); } diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 0acf19f38..588cfb66b 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -60,7 +60,7 @@ const Node* import_node(Rewriter* r, const Node* node) { return shd_recreate_node(r, node); } -Module* import(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_import(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index c75c5d512..a718193a4 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -48,7 +48,7 @@ static String loop_name(const LTNode* n) { return ""; } -void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, Nodes* lparams, Nodes* nargs) { +static void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, Nodes* lparams, Nodes* nargs) { IrArena* a = ctx->rewriter.dst_arena; assert(old->tag == BasicBlock_TAG); @@ -82,7 +82,7 @@ void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* nparams, No shd_dict_insert(const Node*, Nodes, ctx->lifted_arguments, old, *nparams); } -const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* body) { +static const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* body) { IrArena* a = ctx->rewriter.dst_arena; Context ctx2 = *ctx; ctx = &ctx2; @@ -133,7 +133,7 @@ const Node* process_abstraction_body(Context* ctx, const Node* old, const Node* return new; } -const Node* process_node(Context* ctx, const Node* old) { +static const Node* process_node(Context* ctx, const Node* old) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; @@ -188,7 +188,7 @@ const Node* process_node(Context* ctx, const Node* old) { KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); -Module* lcssa(const CompilerConfig* config, Module* src) { +Module* shd_pass_lcssa(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index c8c7d16cc..b0d74044c 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -99,7 +99,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lift_everything(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); bool todo = true; diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 4deac2290..9e9b45436 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -221,7 +221,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lift_indirect_targets(const CompilerConfig* config, Module* src) { +Module* shd_pass_lift_indirect_targets(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = NULL; Module* dst; diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 23f7ea224..2373b9da0 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -163,7 +163,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_alloca(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 8373ce59b..2f8de9ea8 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -146,7 +146,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -Module* lower_callf(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_callf(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 8871309f9..92a513845 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -234,7 +234,7 @@ static const Node* process_node(Context* ctx, const Node* node) { KeyHash shd_hash_node(const Node**); bool shd_compare_node(const Node**, const Node**); -Module* lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_cf_instrs(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index d4f18cd81..fc7eec784 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -33,7 +33,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_decay_ptrs(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_decay_ptrs(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 33b5d992d..f52425a6e 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -90,7 +90,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_entrypoint_args(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_entrypoint_args(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index c6bc4c2a4..632e3ccaa 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -31,7 +31,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(r, node); } -Module* lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_fill(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index dfdf70375..3d50e1546 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -42,7 +42,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_generic_globals(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_generic_globals(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 8ca62c868..a7af00c27 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -273,7 +273,7 @@ static const Node* process(Context* ctx, const Node* old) { KeyHash shd_hash_string(const char** string); bool shd_compare_string(const char** a, const char** b); -Module* lower_generic_ptrs(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_generic_ptrs(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index b99a91285..f3f2b4574 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -79,7 +79,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_int(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_int(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index f6ef84203..438b59f73 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -165,7 +165,7 @@ static const Node* process(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -Module* lower_lea(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_lea(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index c68093f4c..4d8eb4262 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -137,7 +137,7 @@ static const Node* process(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -Module* lower_logical_pointers(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_logical_pointers(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.address_spaces[AsInput].physical = false; aconfig.address_spaces[AsOutput].physical = false; diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 658be4c25..5a2a78564 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -48,7 +48,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.specializations.subgroup_mask_representation = SubgroupMaskInt64; IrArena* a = shd_new_ir_arena(&aconfig); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 93fc46fee..351d57bc1 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -125,7 +125,7 @@ static const Node* process(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -Module* lower_memcpy(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_memcpy(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 9eb77623b..b3b69bda9 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -48,7 +48,7 @@ static const Node* process(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -Module* lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_memory_layout(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 62cad432d..0f2499e50 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -48,7 +48,7 @@ static const Node* process(Context* ctx, const Node* node) { KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); -Module* lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_nullptr(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 19c6d7155..dab51b395 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -480,7 +480,7 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { *get_emulated_as_word_array(ctx, as) = ref_decl_helper(a, words_array); } -Module* lower_physical_ptrs(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_physical_ptrs(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.address_spaces[AsPrivate].physical = false; aconfig.address_spaces[AsShared].physical = false; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 7dcb8bf73..1984d969e 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -174,7 +174,7 @@ static const Node* process_node(Context* ctx, const Node* old) { KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); -Module* lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_stack(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 604dd196f..78410e8d2 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -148,7 +148,7 @@ static const Node* process(Context* ctx, const Node* node) { KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); -Module* lower_subgroup_ops(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_subgroup_ops(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 2094ed8e9..b6f8630c5 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -87,7 +87,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_subgroup_vars(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_subgroup_vars(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 11c5d5346..2e609df53 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -180,7 +180,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_switch_btree(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_switch_btree(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 1d64a538b..ecf7bc6df 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -278,7 +278,7 @@ static const Node* process(Context* ctx, const Node* old) { return shd_recreate_node(&ctx->rewriter, old); } -void generate_top_level_dispatch_fn(Context* ctx) { +static void generate_top_level_dispatch_fn(Context* ctx) { assert(ctx->config->dynamic_scheduling); assert(*ctx->top_dispatcher_fn); assert((*ctx->top_dispatcher_fn)->tag == Function_TAG); @@ -437,7 +437,7 @@ void generate_top_level_dispatch_fn(Context* ctx) { KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); -Module* lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_tailcalls(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 45eaf5684..e7fa4cb94 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -53,7 +53,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_vec_arr(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_vec_arr(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.validate_builtin_types = false; // TODO: hacky IrArena* a = shd_new_ir_arena(&aconfig); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index d194b6529..75a186095 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -188,7 +188,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* lower_workgroups(const CompilerConfig* config, Module* src) { +Module* shd_pass_lower_workgroups(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index 90598c5f6..f348d6230 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -151,7 +151,7 @@ static const Node* process(Context* ctx, const Node* node) { KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); -Module* mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index d92acc26f..6acbb2c00 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -92,7 +92,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_normalize_builtins(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.validate_builtin_types = true; IrArena* a = shd_new_ir_arena(&aconfig); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 02eb71da1..3effcac4d 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -234,7 +234,7 @@ static const Node* process(Context* ctx, const Node* old) { KeyHash shd_hash_node(const Node**); bool shd_compare_node(const Node**, const Node**); -bool opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { +bool shd_opt_demote_alloca(SHADY_UNUSED const CompilerConfig* config, Module** m) { bool todo = false; Module* src = *m; IrArena* a = shd_module_get_arena(src); diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index edf255d8b..15c456cf9 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -226,7 +226,7 @@ static const Node* process(Context* ctx, const Node* node) { KeyHash shd_hash_node(const Node**); bool shd_compare_node(const Node**, const Node**); -void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { +static void simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .config = config, @@ -243,10 +243,10 @@ void opt_simplify_cf(const CompilerConfig* config, Module* src, Module* dst) { shd_destroy_rewriter(&ctx.rewriter); } -Module* opt_inline(const CompilerConfig* config, Module* src) { +Module* shd_pass_inline(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); - opt_simplify_cf(config, src, dst); + simplify_cf(config, src, dst); return dst; } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index d71def1b6..d89317902 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -119,9 +119,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(r, node); } -OptPass opt_mem2reg; - -bool opt_mem2reg(SHADY_UNUSED const CompilerConfig* config, Module** m) { +bool shd_opt_mem2reg(SHADY_UNUSED const CompilerConfig* config, Module** m) { Module* src = *m; IrArena* a = shd_module_get_arena(src); diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index 064249337..a718d6a43 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -6,8 +6,8 @@ /// @name Boring, regular compiler stuff /// @{ -RewritePass import; -RewritePass cleanup; +RewritePass shd_import; +RewritePass shd_cleanup; /// @} @@ -15,15 +15,15 @@ RewritePass cleanup; /// @{ /// Gets rid of structured control flow constructs, and turns them into branches, joins and tailcalls -RewritePass lower_cf_instrs; +RewritePass shd_pass_lower_cf_instrs; /// Uses shady.scope annotations to insert control blocks -RewritePass scope2control; -RewritePass lift_everything; -RewritePass remove_critical_edges; -RewritePass lcssa; -RewritePass scope_heuristic; +RewritePass shd_pass_scope2control; +RewritePass shd_pass_lift_everything; +RewritePass shd_pass_remove_critical_edges; +RewritePass shd_pass_lcssa; +RewritePass shd_pass_scope_heuristic; /// Try to identify reconvergence points throughout the program for unstructured control flow programs -RewritePass reconvergence_heuristics; +RewritePass shd_pass_reconvergence_heuristics; /// @} @@ -31,8 +31,8 @@ RewritePass reconvergence_heuristics; /// @{ /// Extracts unstructured basic blocks into separate functions (including spilling) -RewritePass lift_indirect_targets; -RewritePass normalize_builtins; +RewritePass shd_pass_lift_indirect_targets; +RewritePass shd_pass_normalize_builtins; /// @} @@ -40,9 +40,9 @@ RewritePass normalize_builtins; /// @{ /// Lowers calls to stack saves and forks, lowers returns to stack pops and joins -RewritePass lower_callf; +RewritePass shd_pass_lower_callf; /// Emulates tailcalls, forks and joins using a god function -RewritePass lower_tailcalls; +RewritePass shd_pass_lower_tailcalls; /// @} @@ -50,24 +50,24 @@ RewritePass lower_tailcalls; /// @{ /// Implements stack frames: saves the stack size on function entry and restores it upon exit -RewritePass setup_stack_frames; +RewritePass shd_pass_setup_stack_frames; /// Implements stack frames: collects allocas into a struct placed on the stack upon function entry -RewritePass lower_alloca; +RewritePass shd_pass_lower_alloca; /// Turns stack pushes and pops into accesses into pointer load and stores -RewritePass lower_stack; +RewritePass shd_pass_lower_stack; /// Eliminates lea_op on all physical address spaces -RewritePass lower_lea; +RewritePass shd_pass_lower_lea; /// Emulates generic pointers by replacing them with tagged integers and special load/store routines that look at those tags -RewritePass lower_generic_ptrs; +RewritePass shd_pass_lower_generic_ptrs; /// Emulates physical pointers to certain address spaces by using integer indices into global arrays -RewritePass lower_physical_ptrs; +RewritePass shd_pass_lower_physical_ptrs; /// Replaces size_of, offset_of etc with their exact values -RewritePass lower_memory_layout; -RewritePass lower_memcpy; +RewritePass shd_pass_lower_memory_layout; +RewritePass shd_pass_lower_memcpy; /// Eliminates pointers to unsized arrays from the IR. Needs lower_lea to have ran shd_first! -RewritePass lower_decay_ptrs; -RewritePass lower_generic_globals; -RewritePass lower_logical_pointers; +RewritePass shd_pass_lower_decay_ptrs; +RewritePass shd_pass_lower_generic_globals; +RewritePass shd_pass_lower_logical_pointers; /// @} @@ -75,11 +75,11 @@ RewritePass lower_logical_pointers; /// @{ /// Emulates unsupported subgroup operations using subgroup memory -RewritePass lower_subgroup_ops; +RewritePass shd_pass_lower_subgroup_ops; /// Lowers subgroup logical variables into something that actually exists (likely a carved out portion of shared memory) -RewritePass lower_subgroup_vars; +RewritePass shd_pass_lower_subgroup_vars; /// Lowers the abstract mask type to whatever the configured target mask representation is -RewritePass lower_mask; +RewritePass shd_pass_lower_mask; /// @} @@ -87,11 +87,11 @@ RewritePass lower_mask; /// @{ /// Emulates unsupported integer datatypes and operations -RewritePass lower_int; -RewritePass lower_vec_arr; -RewritePass lower_workgroups; -RewritePass lower_fill; -RewritePass lower_nullptr; +RewritePass shd_pass_lower_int; +RewritePass shd_pass_lower_vec_arr; +RewritePass shd_pass_lower_workgroups; +RewritePass shd_pass_lower_fill; +RewritePass shd_pass_lower_nullptr; /// @} @@ -99,23 +99,22 @@ RewritePass lower_nullptr; /// @{ /// Eliminates all Constant decls -RewritePass eliminate_constants; +RewritePass shd_pass_eliminate_constants; /// Ditto but for @Inline ones only -RewritePass eliminate_inlineable_constants; +RewritePass shd_pass_eliminate_inlineable_constants; /// Tags all functions that don't need special handling -RewritePass mark_leaf_functions; +RewritePass shd_pass_mark_leaf_functions; /// In addition, also inlines function calls according to heuristics -RewritePass opt_inline; -OptPass opt_mem2reg; +RewritePass shd_pass_inline; +OptPass shd_opt_mem2reg; -RewritePass opt_stack; -RewritePass opt_restructurize; -RewritePass lower_switch_btree; +RewritePass shd_pass_restructurize; +RewritePass shd_pass_lower_switch_btree; -RewritePass lower_entrypoint_args; +RewritePass shd_pass_lower_entrypoint_args; -RewritePass specialize_entry_point; -RewritePass specialize_execution_model; +RewritePass shd_pass_specialize_entry_point; +RewritePass shd_pass_specialize_execution_model; /// @} diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 0a1b2e725..858c6458b 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -481,7 +481,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return shd_recreate_node(r, node); } -Module* reconvergence_heuristics(const CompilerConfig* config, Module* src) { +Module* shd_pass_reconvergence_heuristics(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.optimisations.inline_single_use_bbs = true; IrArena* a = shd_new_ir_arena(&aconfig); diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index d1cfb1bd9..51fd378e4 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -29,7 +29,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(r, node); } -Module* remove_critical_edges(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_remove_critical_edges(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/opt_restructure.c b/src/shady/passes/restructure.c similarity index 99% rename from src/shady/passes/opt_restructure.c rename to src/shady/passes/restructure.c index 70b92bd54..58a02dc58 100644 --- a/src/shady/passes/opt_restructure.c +++ b/src/shady/passes/restructure.c @@ -415,7 +415,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* opt_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_restructurize(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 5a9c9a0d9..82cafe07d 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -300,7 +300,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* scope2control(const CompilerConfig* config, Module* src) { +Module* shd_pass_scope2control(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); aconfig.optimisations.inline_single_use_bbs = true; IrArena* a = shd_new_ir_arena(&aconfig); diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index d249c404e..f2262bcbb 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -199,7 +199,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -Module* scope_heuristic(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_scope_heuristic(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index b6229b3d2..7a5f54c3e 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -59,7 +59,7 @@ static const Node* process(Context* ctx, const Node* node) { return shd_recreate_node(r, node); } -Module* setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* src) { +Module* shd_pass_setup_stack_frames(SHADY_UNUSED const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 171393b26..37f325a31 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -104,7 +104,7 @@ static void specialize_arena_config(const CompilerConfig* config, Module* src, A } } -Module* specialize_entry_point(const CompilerConfig* config, Module* src) { +Module* shd_pass_specialize_entry_point(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); specialize_arena_config(config, src, &aconfig); IrArena* a = shd_new_ir_arena(&aconfig); diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 51ddb7005..40ad3f5c0 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -40,7 +40,7 @@ static void specialize_arena_config(const CompilerConfig* config, Module* m, Are } } -Module* specialize_execution_model(const CompilerConfig* config, Module* src) { +Module* shd_pass_specialize_execution_model(const CompilerConfig* config, Module* src) { ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); specialize_arena_config(config, src, &aconfig); IrArena* a = shd_new_ir_arena(&aconfig); diff --git a/test/opt/opt_oracle.c b/test/opt/opt_oracle.c index 0554f8b33..425162dd4 100644 --- a/test/opt/opt_oracle.c +++ b/test/opt/opt_oracle.c @@ -67,7 +67,7 @@ static Module* oracle_passes(const CompilerConfig* config, Module* initial_mod) IrArena* initial_arena = shd_module_get_arena(initial_mod); Module** pmod = &initial_mod; - RUN_PASS(cleanup) + RUN_PASS(shd_cleanup) check_module(*pmod); return *pmod; From da7406f2dbc2c5bb420e0cf7f1723aeab71cbff4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 21:30:47 +0200 Subject: [PATCH 637/693] move code to match new shady/ir structure --- include/shady/ir/composite.h | 2 - include/shady/ir/decl.h | 1 + include/shady/ir/function.h | 1 + include/shady/ir/type.h | 2 + src/backend/c/emit_c.c | 1 - src/backend/c/emit_c_control_flow.c | 1 - src/backend/c/emit_c_type.c | 1 - src/backend/c/emit_c_value.c | 1 - src/backend/spirv/emit_spv.c | 4 +- src/backend/spirv/emit_spv_control_flow.c | 1 - src/backend/spirv/emit_spv_type.c | 1 - src/backend/spirv/emit_spv_value.c | 1 - src/backend/spirv/spirv_lift_globals_ssbo.c | 1 - src/backend/spirv/spirv_map_entrypoint_args.c | 1 - src/frontend/llvm/l2s.c | 3 - src/frontend/llvm/l2s_instr.c | 5 +- src/frontend/llvm/l2s_postprocess.c | 5 +- src/frontend/llvm/l2s_type.c | 1 - src/frontend/llvm/l2s_value.c | 4 +- src/frontend/slim/infer.c | 2 +- src/frontend/slim/normalize.c | 2 - src/frontend/slim/parser.c | 1 - src/frontend/spirv/s2s.c | 27 +- src/runtime/vulkan/vk_runtime_program.c | 3 - src/shady/CMakeLists.txt | 9 +- src/shady/analysis/verify.c | 9 +- src/shady/body_builder.c | 6 +- src/shady/constructors.c | 291 ---- src/shady/fold.c | 7 +- src/shady/ir/CMakeLists.txt | 13 + src/shady/{ => ir}/annotation.c | 0 src/shady/{builtins.c => ir/builtin.c} | 10 +- src/shady/ir/composite.c | 85 ++ src/shady/ir/decl.c | 58 + src/shady/ir/float.c | 59 + src/shady/ir/function.c | 82 ++ src/shady/ir/grammar.c | 60 + src/shady/ir/int.c | 56 + src/shady/{node_helpers.c => ir/mem.c} | 2 +- src/shady/{ => ir}/module.c | 6 +- src/shady/{type_helpers.c => ir/type.c} | 82 +- src/shady/node.c | 65 +- src/shady/passes/cleanup.c | 1 - src/shady/passes/lift_everything.c | 2 - src/shady/passes/lift_indirect_targets.c | 1 - src/shady/passes/lower_alloca.c | 3 +- src/shady/passes/lower_callf.c | 1 - src/shady/passes/lower_cf_instrs.c | 1 - src/shady/passes/lower_decay_ptrs.c | 5 - src/shady/passes/lower_entrypoint_args.c | 1 - src/shady/passes/lower_fill.c | 1 - src/shady/passes/lower_generic_globals.c | 1 - src/shady/passes/lower_generic_ptrs.c | 1 - src/shady/passes/lower_int64.c | 1 - src/shady/passes/lower_lea.c | 1 - src/shady/passes/lower_logical_pointers.c | 1 - src/shady/passes/lower_mask.c | 2 +- src/shady/passes/lower_memcpy.c | 1 - src/shady/passes/lower_memory_layout.c | 3 +- src/shady/passes/lower_nullptr.c | 1 - src/shady/passes/lower_physical_ptrs.c | 1 - src/shady/passes/lower_stack.c | 2 - src/shady/passes/lower_subgroup_ops.c | 1 - src/shady/passes/lower_subgroup_vars.c | 1 - src/shady/passes/lower_switch_btree.c | 1 - src/shady/passes/lower_tailcalls.c | 1 - src/shady/passes/lower_vec_arr.c | 1 - src/shady/passes/lower_workgroups.c | 1 - src/shady/passes/normalize_builtins.c | 1 - src/shady/passes/opt_demote_alloca.c | 4 +- src/shady/passes/opt_inline.c | 3 - src/shady/passes/opt_mem2reg.c | 5 +- src/shady/passes/reconvergence_heuristics.c | 2 - src/shady/passes/remove_critical_edges.c | 1 - src/shady/passes/restructure.c | 1 - src/shady/passes/scope2control.c | 15 +- src/shady/passes/scope_heuristic.c | 1 - src/shady/passes/setup_stack_frames.c | 2 +- src/shady/passes/specialize_execution_model.c | 3 - src/shady/print.c | 5 +- src/shady/rewrite.c | 5 +- src/shady/transform/ir_gen_helpers.c | 15 +- src/shady/transform/memory_layout.c | 3 +- src/shady/type.c | 1280 ----------------- src/shady/type.h | 24 - test/test_builder.c | 1 - 86 files changed, 518 insertions(+), 1862 deletions(-) delete mode 100644 src/shady/constructors.c create mode 100644 src/shady/ir/CMakeLists.txt rename src/shady/{ => ir}/annotation.c (100%) rename src/shady/{builtins.c => ir/builtin.c} (89%) create mode 100644 src/shady/ir/composite.c create mode 100644 src/shady/ir/decl.c create mode 100644 src/shady/ir/float.c create mode 100644 src/shady/ir/function.c create mode 100644 src/shady/ir/grammar.c create mode 100644 src/shady/ir/int.c rename src/shady/{node_helpers.c => ir/mem.c} (98%) rename src/shady/{ => ir}/module.c (93%) rename src/shady/{type_helpers.c => ir/type.c} (75%) delete mode 100644 src/shady/type.c delete mode 100644 src/shady/type.h diff --git a/include/shady/ir/composite.h b/include/shady/ir/composite.h index 4912fc0b4..19cf7e756 100644 --- a/include/shady/ir/composite.h +++ b/include/shady/ir/composite.h @@ -6,8 +6,6 @@ const Node* maybe_tuple_helper(IrArena* a, Nodes values); const Node* extract_helper(const Node* composite, const Node* index); -const Node* maybe_tuple_helper(IrArena* a, Nodes values); - const Node* tuple_helper(IrArena*, Nodes contents); void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); diff --git a/include/shady/ir/decl.h b/include/shady/ir/decl.h index 2d1a5205c..4f31934bd 100644 --- a/include/shady/ir/decl.h +++ b/include/shady/ir/decl.h @@ -2,6 +2,7 @@ #define SHADY_IR_DECL_H #include "shady/ir/base.h" +#include "shady/ir/grammar.h" Node* constant(Module*, Nodes annotations, const Type*, const char* name); Node* global_var(Module*, Nodes annotations, const Type*, String, AddressSpace); diff --git a/include/shady/ir/function.h b/include/shady/ir/function.h index d301ef651..00da58d1b 100644 --- a/include/shady/ir/function.h +++ b/include/shady/ir/function.h @@ -2,6 +2,7 @@ #define SHADY_IR_FUNCTION_H #include "shady/ir/grammar.h" +#include "shady/ir/type.h" Node* param(IrArena*, const Type* type, const char* name); diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index 5a309d661..6f601ca0c 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -13,6 +13,8 @@ static inline const Node* unit_type(IrArena* arena) { Type* nominal_type(Module*, Nodes annotations, String name); +const Type* get_actual_mask_type(IrArena* arena); + String get_address_space_name(AddressSpace); /// Returns false iff pointers in that address space can contain different data at the same address /// (amongst threads in the same subgroup) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 595070d70..0009d72d3 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -1,6 +1,5 @@ #include "emit_c.h" -#include "../shady/type.h" #include "../shady/ir_private.h" #include "../shady/transform/ir_gen_helpers.h" #include "../shady/passes/passes.h" diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index df541c55f..fef859080 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -1,6 +1,5 @@ #include "emit_c.h" -#include "../shady/type.h" #include "../shady/analysis/cfg.h" #include "log.h" diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index b7334d233..6b86ae3f4 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -4,7 +4,6 @@ #include "log.h" #include "util.h" -#include "../shady/type.h" #include "../shady/ir_private.h" #include diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 8a9119527..470ce5e5e 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -5,7 +5,6 @@ #include "dict.h" #include "util.h" -#include "../shady/type.h" #include "../shady/ir_private.h" #include "../shady/transform/ir_gen_helpers.h" #include "../shady/analysis/scheduler.h" diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 0be6b5885..6d0a0ea0f 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -5,19 +5,17 @@ #include "../shady/ir_private.h" #include "../shady/analysis/cfg.h" #include "../shady/passes/passes.h" -#include "../shady/type.h" +#include "../shady/analysis/scheduler.h" #include "list.h" #include "dict.h" #include "log.h" #include "portability.h" #include "growy.h" -#include "util.h" #include #include #include -#include KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index f20f9eca6..e5e28c61d 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -1,6 +1,5 @@ #include "emit_spv.h" -#include "../shady/type.h" #include "../shady/analysis/cfg.h" #include "list.h" diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index cdfe8472c..91a4257e0 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -2,7 +2,6 @@ #include "shady/ir/memory_layout.h" -#include "../shady/type.h" #include "shady/rewrite.h" #include "portability.h" diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 92e87d6b6..d39e1bb5c 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -2,7 +2,6 @@ #include "shady/ir/memory_layout.h" -#include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" #include "../shady/analysis/cfg.h" #include "../shady/analysis/scheduler.h" diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 1e51778d9..5fc6ad186 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" -#include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" #include "dict.h" diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index 6465b08e7..ee77fa133 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" -#include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" #include "portability.h" diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 579682582..93ac240e4 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -1,14 +1,11 @@ #include "l2s_private.h" #include "ir_private.h" -#include "type.h" #include "analysis/verify.h" #include "log.h" #include "dict.h" #include "list.h" -#include "util.h" -#include "portability.h" #include "llvm-c/IRReader.h" diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index a7e94ef3b..aee2a963f 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -1,13 +1,12 @@ #include "l2s_private.h" +#include "../shady/transform/ir_gen_helpers.h" + #include "portability.h" #include "log.h" #include "dict.h" #include "list.h" -#include "../shady/type.h" -#include "../shady/transform/ir_gen_helpers.h" - #include "llvm-c/DebugInfo.h" static Nodes convert_operands(Parser* p, size_t num_ops, LLVMValueRef v) { diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index d01c456e1..4f2aa2833 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -1,14 +1,13 @@ #include "l2s_private.h" +#include "shady/rewrite.h" + #include "portability.h" #include "dict.h" #include "list.h" #include "log.h" #include "arena.h" -#include "shady/rewrite.h" -#include "../shady/type.h" - KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index c968b78be..5d9fa1fd6 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -1,5 +1,4 @@ #include "l2s_private.h" -#include "type.h" #include "portability.h" #include "log.h" diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index 64dfc1908..5d1259b61 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -1,10 +1,10 @@ #include "l2s_private.h" +#include "../../shady/transform/ir_gen_helpers.h" + #include "portability.h" #include "log.h" #include "dict.h" -#include "../../shady/transform/ir_gen_helpers.h" -#include "../../shady/type.h" static const Node* data_composite(const Type* t, size_t size, LLVMValueRef v) { IrArena* a = t->arena; diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 951de283a..f8b7f70b4 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -1,7 +1,7 @@ #include "shady/pass.h" -#include "../shady/type.h" #include "../shady/transform/ir_gen_helpers.h" +#include "../shady/check.h" #include "log.h" #include "portability.h" diff --git a/src/frontend/slim/normalize.c b/src/frontend/slim/normalize.c index 1d8b8b76d..95205462f 100644 --- a/src/frontend/slim/normalize.c +++ b/src/frontend/slim/normalize.c @@ -1,7 +1,5 @@ #include "shady/pass.h" -#include "../shady/type.h" - #include "log.h" #include "portability.h" #include "dict.h" diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 18f2b8053..36ca41c7f 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -6,7 +6,6 @@ #include "log.h" #include "util.h" -#include "type.h" #include "ir_private.h" #include "transform/ir_gen_helpers.h" diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 21833f6ea..e832caa1c 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -3,6 +3,15 @@ #include "shady/ir/builtin.h" #include "shady/ir/memory_layout.h" +#include "../shady/ir_private.h" +#include "../shady/transform/ir_gen_helpers.h" + +#include "log.h" +#include "arena.h" +#include "portability.h" +#include "dict.h" +#include "util.h" + // this avoids polluting the namespace #define SpvHasResultAndType ShadySpvHasResultAndType @@ -15,6 +24,10 @@ static void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy #include "spirv/unified1/OpenCL.std.h" #include "spirv/unified1/GLSL.std.450.h" +#include +#include +#include + // TODO: reserve real decoration IDs typedef enum { ShdDecorationName = 999999, @@ -23,20 +36,6 @@ typedef enum { ShdDecorationEntryPointName = 999996, } ShdDecoration; -#include "log.h" -#include "arena.h" -#include "portability.h" -#include "dict.h" -#include "util.h" - -#include "../shady/type.h" -#include "../shady/ir_private.h" -#include "../shady/transform/ir_gen_helpers.h" - -#include -#include -#include - typedef struct { struct { uint8_t major, minor; diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 5f3320a5b..5ace9900b 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -3,12 +3,9 @@ #include "shady/driver.h" #include "shady/ir/memory_layout.h" -#include "type.h" - #include "log.h" #include "portability.h" #include "dict.h" -#include "list.h" #include "growy.h" #include "arena.h" #include "util.h" diff --git a/src/shady/CMakeLists.txt b/src/shady/CMakeLists.txt index 164f4d2bb..26a959700 100644 --- a/src/shady/CMakeLists.txt +++ b/src/shady/CMakeLists.txt @@ -26,26 +26,21 @@ add_library(shady STATIC) target_sources(shady PRIVATE ir.c node.c - node_helpers.c - constructors.c - type.c - type_helpers.c + check.c primops.c - builtins.c rewrite.c visit.c print.c fold.c body_builder.c compile.c - annotation.c - module.c config.c ) add_subdirectory(analysis) add_subdirectory(transform) add_subdirectory(passes) +add_subdirectory(ir) target_include_directories(shady PUBLIC $) diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 1db4cd349..b574f3ed1 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -1,15 +1,16 @@ #include "verify.h" + +#include "shady/visit.h" + #include "free_frontier.h" #include "cfg.h" +#include "../ir_private.h" +#include "../check.h" #include "log.h" #include "dict.h" #include "list.h" -#include "shady/visit.h" -#include "../ir_private.h" -#include "../type.h" - #include typedef struct { diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 92cfa4f9c..4fd5cdc87 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -1,11 +1,11 @@ #include "ir_private.h" -#include "log.h" -#include "portability.h" -#include "type.h" + #include "transform/ir_gen_helpers.h" #include "list.h" #include "dict.h" +#include "log.h" +#include "portability.h" #include #include diff --git a/src/shady/constructors.c b/src/shady/constructors.c deleted file mode 100644 index 86366b1d6..000000000 --- a/src/shady/constructors.c +++ /dev/null @@ -1,291 +0,0 @@ -#include "ir_private.h" -#include "type.h" -#include "log.h" -#include "fold.h" -#include "portability.h" - -#include "dict.h" -#include "shady/visit.h" - -#include -#include - -Strings _shd_import_strings(IrArena* dst_arena, Strings old_strings); -bool shd_compare_nodes(Nodes* a, Nodes* b); - -static void pre_construction_validation(IrArena* arena, Node* node); - -const Node* _shd_fold_node_operand(NodeTag tag, NodeClass nc, String opname, const Node* op); - -const Type* _shd_check_type_generated(IrArena* a, const Node* node); - -Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh) { - pre_construction_validation(arena, &node); - if (arena->config.check_types) - node.type = _shd_check_type_generated(arena, &node); - - if (pfresh) - *pfresh = false; - - Node* ptr = &node; - Node** found = shd_dict_find_key(Node*, arena->node_set, ptr); - // sanity check nominal nodes to be unique, check for duplicates in structural nodes - if (shd_is_node_nominal(&node)) - assert(!found); - else if (found) - return *found; - - if (pfresh) - *pfresh = true; - - if (arena->config.allow_fold) { - Node* folded = (Node*) _shd_fold_node(arena, ptr); - if (folded != ptr) { - // The folding process simplified the node, we store a mapping to that simplified node and bail out ! - shd_set_insert_get_result(Node*, arena->node_set, folded); - return folded; - } - } - - if (arena->config.check_types && node.type) - assert(is_type(node.type)); - - // place the node in the arena and return it - Node* alloc = (Node*) shd_arena_alloc(arena->arena, sizeof(Node)); - *alloc = node; - alloc->id = _shd_allocate_node_id(arena, alloc); - shd_set_insert_get_result(const Node*, arena->node_set, alloc); - - return alloc; -} - -#include "constructors_generated.c" - -Node* param(IrArena* arena, const Type* type, const char* name) { - Param param = { - .type = type, - .name = string(arena, name), - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .tag = Param_TAG, - .payload.param = param - }; - return _shd_create_node_helper(arena, node, NULL); -} - -const Node* tuple_helper(IrArena* a, Nodes contents) { - const Type* t = NULL; - if (a->config.check_types) { - // infer the type of the tuple - Nodes member_types = get_values_types(a, contents); - t = record_type(a, (RecordType) {.members = strip_qualifiers(a, member_types)}); - } - - return composite_helper(a, t, contents); -} - -Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, Nodes return_types) { - assert(!mod->sealed); - IrArena* arena = mod->arena; - Function payload = { - .module = mod, - .params = params, - .body = NULL, - .name = name, - .annotations = annotations, - .return_types = return_types, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .tag = Function_TAG, - .payload.fun = payload - }; - Node* fn = _shd_create_node_helper(arena, node, NULL); - _shd_module_add_decl(mod, fn); - - for (size_t i = 0; i < params.count; i++) { - Node* param = (Node*) params.nodes[i]; - assert(param->tag == Param_TAG); - assert(!param->payload.param.abs); - param->payload.param.abs = fn; - param->payload.param.pindex = i; - } - - return fn; -} - -Node* basic_block(IrArena* arena, Nodes params, const char* name) { - BasicBlock payload = { - .params = params, - .body = NULL, - .name = name, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .tag = BasicBlock_TAG, - .payload.basic_block = payload - }; - - Node* bb = _shd_create_node_helper(arena, node, NULL); - - for (size_t i = 0; i < params.count; i++) { - Node* param = (Node*) params.nodes[i]; - assert(param->tag == Param_TAG); - assert(!param->payload.param.abs); - param->payload.param.abs = bb; - param->payload.param.pindex = i; - } - - return bb; -} - -Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { - IrArena* arena = mod->arena; - Constant cnst = { - .annotations = annotations, - .name = string(arena, name), - .type_hint = hint, - .value = NULL, - }; - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .tag = Constant_TAG, - .payload.constant = cnst - }; - Node* decl = _shd_create_node_helper(arena, node, NULL); - _shd_module_add_decl(mod, decl); - return decl; -} - -Node* global_var(Module* mod, Nodes annotations, const Type* type, const char* name, AddressSpace as) { - const Node* existing = shd_module_get_declaration(mod, name); - if (existing) { - assert(existing->tag == GlobalVariable_TAG); - assert(existing->payload.global_variable.type == type); - assert(existing->payload.global_variable.address_space == as); - assert(!mod->arena->config.check_types || shd_compare_nodes((Nodes*) &existing->payload.global_variable.annotations, &annotations)); - return (Node*) existing; - } - - IrArena* arena = mod->arena; - GlobalVariable gvar = { - .annotations = annotations, - .name = string(arena, name), - .type = type, - .address_space = as, - .init = NULL, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .tag = GlobalVariable_TAG, - .payload.global_variable = gvar - }; - Node* decl = _shd_create_node_helper(arena, node, NULL); - _shd_module_add_decl(mod, decl); - return decl; -} - -Type* nominal_type(Module* mod, Nodes annotations, String name) { - IrArena* arena = mod->arena; - NominalType payload = { - .name = string(arena, name), - .module = mod, - .annotations = annotations, - .body = NULL, - }; - - Node node; - memset((void*) &node, 0, sizeof(Node)); - node = (Node) { - .arena = arena, - .type = NULL, - .tag = NominalType_TAG, - .payload.nom_type = payload - }; - Node* decl = _shd_create_node_helper(arena, node, NULL); - _shd_module_add_decl(mod, decl); - return decl; -} - -const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes indices) { - const Node* lea = ptr_array_element_offset(a, (PtrArrayElementOffset) { - .ptr = ptr, - .offset = offset, - }); - for (size_t i = 0; i < indices.count; i++) { - lea = ptr_composite_element(a, (PtrCompositeElement) { - .ptr = lea, - .index = indices.nodes[i], - }); - } - return lea; -} - -const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w) { return int_type(a, (Int) { .width = w, .is_signed = s }); } - -const Type* shd_int8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = true }); } -const Type* shd_int16_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy16, .is_signed = true }); } -const Type* shd_int32_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy32, .is_signed = true }); } -const Type* shd_int64_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy64, .is_signed = true }); } - -const Type* shd_uint8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = false }); } -const Type* shd_uint16_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy16, .is_signed = false }); } -const Type* shd_uint32_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy32, .is_signed = false }); } -const Type* shd_uint64_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy64, .is_signed = false }); } - -const Node* shd_int8_literal (IrArena* arena, int8_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy8, .value = (uint64_t) (uint8_t) i, .is_signed = true }); } -const Node* shd_int16_literal(IrArena* arena, int16_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy16, .value = (uint64_t) (uint16_t) i, .is_signed = true }); } -const Node* shd_int32_literal(IrArena* arena, int32_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy32, .value = (uint64_t) (uint32_t) i, .is_signed = true }); } -const Node* shd_int64_literal(IrArena* arena, int64_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy64, .value = (uint64_t) i, .is_signed = true }); } - -const Node* shd_uint8_literal (IrArena* arena, uint8_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy8, .value = (int64_t) i }); } -const Node* shd_uint16_literal(IrArena* arena, uint16_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy16, .value = (int64_t) i }); } -const Node* shd_uint32_literal(IrArena* arena, uint32_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy32, .value = (int64_t) i }); } -const Node* shd_uint64_literal(IrArena* arena, uint64_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy64, .value = i }); } - -const Type* shd_fp16_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy16 }); } -const Type* shd_fp32_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy32 }); } -const Type* shd_fp64_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy64 }); } - -const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value) { - switch (size) { - case FloatTy16: assert(false); break; - case FloatTy32: { - float f = value; - uint64_t bits = 0; - memcpy(&bits, &f, sizeof(f)); - return float_literal(a, (FloatLiteral) { .width = size, .value = bits }); - } - case FloatTy64: { - uint64_t bits = 0; - memcpy(&bits, &value, sizeof(value)); - return float_literal(a, (FloatLiteral) { .width = size, .value = bits }); - } - } -} - -const Node* extract_helper(const Node* composite, const Node* index) { - IrArena* a = composite->arena; - return prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, composite, index)); -} - -const Node* maybe_tuple_helper(IrArena* a, Nodes values) { - if (values.count == 1) - return shd_first(values); - return tuple_helper(a, values); -} diff --git a/src/shady/fold.c b/src/shady/fold.c index 2f86ae75d..4ae9a9c5c 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -1,15 +1,12 @@ #include "fold.h" #include "shady/ir/memory_layout.h" -#include "shady/rewrite.h" -#include "log.h" +#include "transform/ir_gen_helpers.h" +#include "check.h" -#include "type.h" #include "portability.h" -#include "transform/ir_gen_helpers.h" - #include #include diff --git a/src/shady/ir/CMakeLists.txt b/src/shady/ir/CMakeLists.txt new file mode 100644 index 000000000..7a872d210 --- /dev/null +++ b/src/shady/ir/CMakeLists.txt @@ -0,0 +1,13 @@ +target_sources(shady PRIVATE + annotation.c + mem.c + module.c + int.c + float.c + composite.c + function.c + decl.c + builtin.c + type.c + grammar.c +) \ No newline at end of file diff --git a/src/shady/annotation.c b/src/shady/ir/annotation.c similarity index 100% rename from src/shady/annotation.c rename to src/shady/ir/annotation.c diff --git a/src/shady/builtins.c b/src/shady/ir/builtin.c similarity index 89% rename from src/shady/builtins.c rename to src/shady/ir/builtin.c index 34dc75ae5..6fb075774 100644 --- a/src/shady/builtins.c +++ b/src/shady/ir/builtin.c @@ -1,10 +1,10 @@ -#include "shady/ir/builtin.h" -#include "shady/ir/annotation.h" +#include "../../../include/shady/ir/builtin.h" +#include "../../../include/shady/ir/annotation.h" -#include "spirv/unified1/spirv.h" +#include "../../../SPIRV-Headers/include/spirv/unified1/spirv.h" -#include "log.h" -#include "portability.h" +#include "../../common/log.h" +#include "../../common/portability.h" #include static AddressSpace builtin_as[] = { diff --git a/src/shady/ir/composite.c b/src/shady/ir/composite.c new file mode 100644 index 000000000..9b4598abb --- /dev/null +++ b/src/shady/ir/composite.c @@ -0,0 +1,85 @@ +#include "shady/ir/composite.h" + +#include "ir_private.h" + +#include "log.h" + +#include + +const Node* extract_helper(const Node* composite, const Node* index) { + IrArena* a = composite->arena; + return prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, composite, index)); +} + +const Node* maybe_tuple_helper(IrArena* a, Nodes values) { + if (values.count == 1) + return shd_first(values); + return tuple_helper(a, values); +} + +const Node* tuple_helper(IrArena* a, Nodes contents) { + const Type* t = NULL; + if (a->config.check_types) { + // infer the type of the tuple + Nodes member_types = get_values_types(a, contents); + t = record_type(a, (RecordType) {.members = strip_qualifiers(a, member_types)}); + } + + return composite_helper(a, t, contents); +} + +void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack) { + const Type* current_type = *datatype; + + if (selector->arena->config.check_types) { + const Type* selector_type = selector->type; + bool selector_uniform = deconstruct_qualified_type(&selector_type); + assert(selector_type->tag == Int_TAG && "selectors must be integers"); + *uniform &= selector_uniform; + } + + try_again: + switch (current_type->tag) { + case RecordType_TAG: { + size_t selector_value = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); + assert(selector_value < current_type->payload.record_type.members.count); + current_type = current_type->payload.record_type.members.nodes[selector_value]; + break; + } + case ArrType_TAG: { + current_type = current_type->payload.arr_type.element_type; + break; + } + case TypeDeclRef_TAG: { + const Node* nom_decl = current_type->payload.type_decl_ref.decl; + assert(nom_decl->tag == NominalType_TAG); + current_type = nom_decl->payload.nom_type.body; + goto try_again; + } + case PackType_TAG: { + assert(allow_entering_pack); + assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a pack type need to be constant"); + size_t selector_value = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); + assert(selector_value < current_type->payload.pack_type.width); + current_type = current_type->payload.pack_type.element_type; + break; + } + // also remember to assert literals for the selectors ! + default: { + shd_log_fmt(ERROR, "Trying to enter non-composite type '"); + shd_log_node(ERROR, current_type); + shd_log_fmt(ERROR, "' with selector '"); + shd_log_node(ERROR, selector); + shd_log_fmt(ERROR, "'."); + shd_error(""); + } + } + *datatype = current_type; +} + +void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack) { + for(size_t i = 0; i < indices.count; i++) { + const Node* selector = indices.nodes[i]; + enter_composite(datatype, uniform, selector, allow_entering_pack); + } +} diff --git a/src/shady/ir/decl.c b/src/shady/ir/decl.c new file mode 100644 index 000000000..f1a9f9b48 --- /dev/null +++ b/src/shady/ir/decl.c @@ -0,0 +1,58 @@ +#include "shady/ir/decl.h" + +#include "../ir_private.h" + +#include + +bool shd_compare_nodes(Nodes* a, Nodes* b); + +Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { + IrArena* arena = mod->arena; + Constant cnst = { + .annotations = annotations, + .name = string(arena, name), + .type_hint = hint, + .value = NULL, + }; + Node node; + memset((void*) &node, 0, sizeof(Node)); + node = (Node) { + .arena = arena, + .tag = Constant_TAG, + .payload.constant = cnst + }; + Node* decl = _shd_create_node_helper(arena, node, NULL); + _shd_module_add_decl(mod, decl); + return decl; +} + +Node* global_var(Module* mod, Nodes annotations, const Type* type, const char* name, AddressSpace as) { + const Node* existing = shd_module_get_declaration(mod, name); + if (existing) { + assert(existing->tag == GlobalVariable_TAG); + assert(existing->payload.global_variable.type == type); + assert(existing->payload.global_variable.address_space == as); + assert(!mod->arena->config.check_types || shd_compare_nodes((Nodes*) &existing->payload.global_variable.annotations, &annotations)); + return (Node*) existing; + } + + IrArena* arena = mod->arena; + GlobalVariable gvar = { + .annotations = annotations, + .name = string(arena, name), + .type = type, + .address_space = as, + .init = NULL, + }; + + Node node; + memset((void*) &node, 0, sizeof(Node)); + node = (Node) { + .arena = arena, + .tag = GlobalVariable_TAG, + .payload.global_variable = gvar + }; + Node* decl = _shd_create_node_helper(arena, node, NULL); + _shd_module_add_decl(mod, decl); + return decl; +} \ No newline at end of file diff --git a/src/shady/ir/float.c b/src/shady/ir/float.c new file mode 100644 index 000000000..87361d3ba --- /dev/null +++ b/src/shady/ir/float.c @@ -0,0 +1,59 @@ +#include "shady/ir/float.h" + +#include "shady/analysis/literal.h" + +#include "log.h" + +#include + +const Type* shd_fp16_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy16 }); } +const Type* shd_fp32_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy32 }); } +const Type* shd_fp64_type(IrArena* arena) { return float_type(arena, (Float) { .width = FloatTy64 }); } + +const Node* shd_fp_literal_helper(IrArena* a, FloatSizes size, double value) { + switch (size) { + case FloatTy16: assert(false); break; + case FloatTy32: { + float f = value; + uint64_t bits = 0; + memcpy(&bits, &f, sizeof(f)); + return float_literal(a, (FloatLiteral) { .width = size, .value = bits }); + } + case FloatTy64: { + uint64_t bits = 0; + memcpy(&bits, &value, sizeof(value)); + return float_literal(a, (FloatLiteral) { .width = size, .value = bits }); + } + } +} + +const FloatLiteral* shd_resolve_to_float_literal(const Node* node) { + node = shd_resolve_node_to_definition(node, shd_default_node_resolve_config()); + if (!node) + return NULL; + if (node->tag == FloatLiteral_TAG) + return &node->payload.float_literal; + return NULL; +} + +static_assert(sizeof(float) == sizeof(uint64_t) / 2, "floats aren't the size we expect"); +double shd_get_float_literal_value(FloatLiteral literal) { + double r; + switch (literal.width) { + case FloatTy16: + shd_error_print("TODO: fp16 literals"); + shd_error_die(); + SHADY_UNREACHABLE; + break; + case FloatTy32: { + float f; + memcpy(&f, &literal.value, sizeof(float)); + r = (double) f; + break; + } + case FloatTy64: + memcpy(&r, &literal.value, sizeof(double)); + break; + } + return r; +} diff --git a/src/shady/ir/function.c b/src/shady/ir/function.c new file mode 100644 index 000000000..4e708859c --- /dev/null +++ b/src/shady/ir/function.c @@ -0,0 +1,82 @@ +#include "shady/ir/function.h" + +#include "../ir_private.h" + +#include + +Node* param(IrArena* arena, const Type* type, const char* name) { + Param param = { + .type = type, + .name = string(arena, name), + }; + + Node node; + memset((void*) &node, 0, sizeof(Node)); + node = (Node) { + .arena = arena, + .tag = Param_TAG, + .payload.param = param + }; + return _shd_create_node_helper(arena, node, NULL); +} + +Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, Nodes return_types) { + assert(!mod->sealed); + IrArena* arena = mod->arena; + Function payload = { + .module = mod, + .params = params, + .body = NULL, + .name = name, + .annotations = annotations, + .return_types = return_types, + }; + + Node node; + memset((void*) &node, 0, sizeof(Node)); + node = (Node) { + .arena = arena, + .tag = Function_TAG, + .payload.fun = payload + }; + Node* fn = _shd_create_node_helper(arena, node, NULL); + _shd_module_add_decl(mod, fn); + + for (size_t i = 0; i < params.count; i++) { + Node* param = (Node*) params.nodes[i]; + assert(param->tag == Param_TAG); + assert(!param->payload.param.abs); + param->payload.param.abs = fn; + param->payload.param.pindex = i; + } + + return fn; +} + +Node* basic_block(IrArena* arena, Nodes params, const char* name) { + BasicBlock payload = { + .params = params, + .body = NULL, + .name = name, + }; + + Node node; + memset((void*) &node, 0, sizeof(Node)); + node = (Node) { + .arena = arena, + .tag = BasicBlock_TAG, + .payload.basic_block = payload + }; + + Node* bb = _shd_create_node_helper(arena, node, NULL); + + for (size_t i = 0; i < params.count; i++) { + Node* param = (Node*) params.nodes[i]; + assert(param->tag == Param_TAG); + assert(!param->payload.param.abs); + param->payload.param.abs = bb; + param->payload.param.pindex = i; + } + + return bb; +} \ No newline at end of file diff --git a/src/shady/ir/grammar.c b/src/shady/ir/grammar.c new file mode 100644 index 000000000..2eb0b9d4a --- /dev/null +++ b/src/shady/ir/grammar.c @@ -0,0 +1,60 @@ +#include "../../../include/shady/ir/grammar.h" + +#include "../fold.h" + +#include "../../common/log.h" +#include "../../common/portability.h" +#include "../../common/dict.h" + +#include +#include + +Strings _shd_import_strings(IrArena* dst_arena, Strings old_strings); + +static void pre_construction_validation(IrArena* arena, Node* node); + +const Node* _shd_fold_node_operand(NodeTag tag, NodeClass nc, String opname, const Node* op); + +const Type* _shd_check_type_generated(IrArena* a, const Node* node); + +Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh) { + pre_construction_validation(arena, &node); + if (arena->config.check_types) + node.type = _shd_check_type_generated(arena, &node); + + if (pfresh) + *pfresh = false; + + Node* ptr = &node; + Node** found = shd_dict_find_key(Node*, arena->node_set, ptr); + // sanity check nominal nodes to be unique, check for duplicates in structural nodes + if (shd_is_node_nominal(&node)) + assert(!found); + else if (found) + return *found; + + if (pfresh) + *pfresh = true; + + if (arena->config.allow_fold) { + Node* folded = (Node*) _shd_fold_node(arena, ptr); + if (folded != ptr) { + // The folding process simplified the node, we store a mapping to that simplified node and bail out ! + shd_set_insert_get_result(Node*, arena->node_set, folded); + return folded; + } + } + + if (arena->config.check_types && node.type) + assert(is_type(node.type)); + + // place the node in the arena and return it + Node* alloc = (Node*) shd_arena_alloc(arena->arena, sizeof(Node)); + *alloc = node; + alloc->id = _shd_allocate_node_id(arena, alloc); + shd_set_insert_get_result(const Node*, arena->node_set, alloc); + + return alloc; +} + +#include "../../../cmake-build-debug/src/shady/constructors_generated.c" diff --git a/src/shady/ir/int.c b/src/shady/ir/int.c new file mode 100644 index 000000000..5cdd8a032 --- /dev/null +++ b/src/shady/ir/int.c @@ -0,0 +1,56 @@ +#include "shady/ir/int.h" + +#include "shady/analysis/literal.h" + +#include + +const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w) { return int_type(a, (Int) { .width = w, .is_signed = s }); } + +const Type* shd_int8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = true }); } +const Type* shd_int16_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy16, .is_signed = true }); } +const Type* shd_int32_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy32, .is_signed = true }); } +const Type* shd_int64_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy64, .is_signed = true }); } + +const Type* shd_uint8_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy8 , .is_signed = false }); } +const Type* shd_uint16_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy16, .is_signed = false }); } +const Type* shd_uint32_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy32, .is_signed = false }); } +const Type* shd_uint64_type(IrArena* arena) { return int_type(arena, (Int) { .width = IntTy64, .is_signed = false }); } + +const Node* shd_int8_literal (IrArena* arena, int8_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy8, .value = (uint64_t) (uint8_t) i, .is_signed = true }); } +const Node* shd_int16_literal(IrArena* arena, int16_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy16, .value = (uint64_t) (uint16_t) i, .is_signed = true }); } +const Node* shd_int32_literal(IrArena* arena, int32_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy32, .value = (uint64_t) (uint32_t) i, .is_signed = true }); } +const Node* shd_int64_literal(IrArena* arena, int64_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy64, .value = (uint64_t) i, .is_signed = true }); } + +const Node* shd_uint8_literal (IrArena* arena, uint8_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy8, .value = (int64_t) i }); } +const Node* shd_uint16_literal(IrArena* arena, uint16_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy16, .value = (int64_t) i }); } +const Node* shd_uint32_literal(IrArena* arena, uint32_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy32, .value = (int64_t) i }); } +const Node* shd_uint64_literal(IrArena* arena, uint64_t i) { return int_literal(arena, (IntLiteral) { .width = IntTy64, .value = i }); } + +const IntLiteral* shd_resolve_to_int_literal(const Node* node) { + node = shd_resolve_node_to_definition(node, shd_default_node_resolve_config()); + if (!node) + return NULL; + if (node->tag == IntLiteral_TAG) + return &node->payload.int_literal; + return NULL; +} + +int64_t shd_get_int_literal_value(IntLiteral literal, bool sign_extend) { + if (sign_extend) { + switch (literal.width) { + case IntTy8: return (int64_t) (int8_t) (literal.value & 0xFF); + case IntTy16: return (int64_t) (int16_t) (literal.value & 0xFFFF); + case IntTy32: return (int64_t) (int32_t) (literal.value & 0xFFFFFFFF); + case IntTy64: return (int64_t) literal.value; + default: assert(false); + } + } else { + switch (literal.width) { + case IntTy8: return literal.value & 0xFF; + case IntTy16: return literal.value & 0xFFFF; + case IntTy32: return literal.value & 0xFFFFFFFF; + case IntTy64: return literal.value; + default: assert(false); + } + } +} \ No newline at end of file diff --git a/src/shady/node_helpers.c b/src/shady/ir/mem.c similarity index 98% rename from src/shady/node_helpers.c rename to src/shady/ir/mem.c index f8bd9f04f..1375aba62 100644 --- a/src/shady/node_helpers.c +++ b/src/shady/ir/mem.c @@ -1,4 +1,4 @@ -#include "shady/ir.h" +#include "../../../include/shady/ir.h" #include diff --git a/src/shady/module.c b/src/shady/ir/module.c similarity index 93% rename from src/shady/module.c rename to src/shady/ir/module.c index b762ff1cd..785f56f8b 100644 --- a/src/shady/module.c +++ b/src/shady/ir/module.c @@ -1,7 +1,7 @@ -#include "ir_private.h" +#include "../ir_private.h" -#include "list.h" -#include "portability.h" +#include "../../common/list.h" +#include "../../common/portability.h" #include diff --git a/src/shady/type_helpers.c b/src/shady/ir/type.c similarity index 75% rename from src/shady/type_helpers.c rename to src/shady/ir/type.c index e2dc0e801..c934070ab 100644 --- a/src/shady/type_helpers.c +++ b/src/shady/ir/type.c @@ -1,5 +1,5 @@ -#include "ir_private.h" -#include "type.h" +#include "../ir_private.h" + #include "log.h" #include "portability.h" @@ -49,62 +49,6 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { return type; } -void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack) { - const Type* current_type = *datatype; - - if (selector->arena->config.check_types) { - const Type* selector_type = selector->type; - bool selector_uniform = deconstruct_qualified_type(&selector_type); - assert(selector_type->tag == Int_TAG && "selectors must be integers"); - *uniform &= selector_uniform; - } - - try_again: - switch (current_type->tag) { - case RecordType_TAG: { - size_t selector_value = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); - assert(selector_value < current_type->payload.record_type.members.count); - current_type = current_type->payload.record_type.members.nodes[selector_value]; - break; - } - case ArrType_TAG: { - current_type = current_type->payload.arr_type.element_type; - break; - } - case TypeDeclRef_TAG: { - const Node* nom_decl = current_type->payload.type_decl_ref.decl; - assert(nom_decl->tag == NominalType_TAG); - current_type = nom_decl->payload.nom_type.body; - goto try_again; - } - case PackType_TAG: { - assert(allow_entering_pack); - assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a pack type need to be constant"); - size_t selector_value = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); - assert(selector_value < current_type->payload.pack_type.width); - current_type = current_type->payload.pack_type.element_type; - break; - } - // also remember to assert literals for the selectors ! - default: { - shd_log_fmt(ERROR, "Trying to enter non-composite type '"); - shd_log_node(ERROR, current_type); - shd_log_fmt(ERROR, "' with selector '"); - shd_log_node(ERROR, selector); - shd_log_fmt(ERROR, "'."); - shd_error(""); - } - } - *datatype = current_type; -} - -void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack) { - for(size_t i = 0; i < indices.count; i++) { - const Node* selector = indices.nodes[i]; - enter_composite(datatype, uniform, selector, allow_entering_pack); - } -} - Nodes get_param_types(IrArena* arena, Nodes variables) { LARRAY(const Type*, arr, variables.count); for (size_t i = 0; i < variables.count; i++) { @@ -290,3 +234,25 @@ const Node* get_fill_type_size(const Type* composite_t) { default: shd_error("fill values need to be either array or pack types") } } + +Type* nominal_type(Module* mod, Nodes annotations, String name) { + IrArena* arena = mod->arena; + NominalType payload = { + .name = string(arena, name), + .module = mod, + .annotations = annotations, + .body = NULL, + }; + + Node node; + memset((void*) &node, 0, sizeof(Node)); + node = (Node) { + .arena = arena, + .type = NULL, + .tag = NominalType_TAG, + .payload.nom_type = payload + }; + Node* decl = _shd_create_node_helper(arena, node, NULL); + _shd_module_add_decl(mod, decl); + return decl; +} diff --git a/src/shady/node.c b/src/shady/node.c index 4ae44de24..8bb86d87b 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -1,8 +1,7 @@ -#include "type.h" -#include "log.h" #include "ir_private.h" -#include "portability.h" +#include "log.h" +#include "portability.h" #include "dict.h" #include @@ -30,48 +29,6 @@ void shd_set_value_name(const Node* var, String name) { // var->payload.varz.name = string(var->arena, name); } -int64_t shd_get_int_literal_value(IntLiteral literal, bool sign_extend) { - if (sign_extend) { - switch (literal.width) { - case IntTy8: return (int64_t) (int8_t) (literal.value & 0xFF); - case IntTy16: return (int64_t) (int16_t) (literal.value & 0xFFFF); - case IntTy32: return (int64_t) (int32_t) (literal.value & 0xFFFFFFFF); - case IntTy64: return (int64_t) literal.value; - default: assert(false); - } - } else { - switch (literal.width) { - case IntTy8: return literal.value & 0xFF; - case IntTy16: return literal.value & 0xFFFF; - case IntTy32: return literal.value & 0xFFFFFFFF; - case IntTy64: return literal.value; - default: assert(false); - } - } -} - -static_assert(sizeof(float) == sizeof(uint64_t) / 2, "floats aren't the size we expect"); -double shd_get_float_literal_value(FloatLiteral literal) { - double r; - switch (literal.width) { - case FloatTy16: - shd_error_print("TODO: fp16 literals"); - shd_error_die(); - SHADY_UNREACHABLE; - break; - case FloatTy32: { - float f; - memcpy(&f, &literal.value, sizeof(float)); - r = (double) f; - break; - } - case FloatTy64: - memcpy(&r, &literal.value, sizeof(double)); - break; - } - return r; -} - static bool is_zero(const Node* node) { const IntLiteral* lit = shd_resolve_to_int_literal(node); if (lit && shd_get_int_literal_value(*lit, false) == 0) @@ -192,24 +149,6 @@ const Node* shd_resolve_node_to_definition(const Node* node, NodeResolveConfig c return node; } -const IntLiteral* shd_resolve_to_int_literal(const Node* node) { - node = shd_resolve_node_to_definition(node, shd_default_node_resolve_config()); - if (!node) - return NULL; - if (node->tag == IntLiteral_TAG) - return &node->payload.int_literal; - return NULL; -} - -const FloatLiteral* shd_resolve_to_float_literal(const Node* node) { - node = shd_resolve_node_to_definition(node, shd_default_node_resolve_config()); - if (!node) - return NULL; - if (node->tag == FloatLiteral_TAG) - return &node->payload.float_literal; - return NULL; -} - const char* shd_get_string_literal(IrArena* arena, const Node* node) { if (!node) return NULL; diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 22c9292b5..4ffc6fe63 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -3,7 +3,6 @@ #include "../analysis/uses.h" #include "../analysis/leak.h" #include "../ir_private.h" -#include "../type.h" #include "portability.h" #include "log.h" diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index b0d74044c..8a9b026de 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -1,13 +1,11 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" #include "../analysis/scheduler.h" #include "../analysis/free_frontier.h" -#include "log.h" #include "dict.h" #include "portability.h" diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 9e9b45436..768ecc6a0 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "join_point_ops.h" -#include "../type.h" #include "../ir_private.h" #include "shady/visit.h" diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 2373b9da0..e80290321 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -1,7 +1,6 @@ #include "shady/pass.h" - #include "shady/visit.h" -#include "../type.h" + #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 2f8de9ea8..b7d41e3d8 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "join_point_ops.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 92a513845..14233f7a1 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -1,6 +1,5 @@ #include "shady/pass.h" -#include "../type.h" #include "../analysis/cfg.h" #include "log.h" diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index fc7eec784..97496540a 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -1,12 +1,7 @@ #include "shady/pass.h" -#include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" -#include "log.h" -#include "portability.h" - typedef struct { Rewriter rewriter; const CompilerConfig* config; diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index f52425a6e..f3b879db4 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "portability.h" diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index 632e3ccaa..a16ab5286 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 3d50e1546..5f647794c 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index a7af00c27..3477e4322 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" -#include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index f3f2b4574..5ca3ba664 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 438b59f73..ef455c08e 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -1,6 +1,5 @@ #include "shady/pass.h" -#include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 4d8eb4262..361d537f6 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -1,6 +1,5 @@ #include "shady/pass.h" -#include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 5a2a78564..91e8167bd 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -1,7 +1,7 @@ #include "shady/pass.h" +#include "shady/ir/type.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 351d57bc1..9b09382d6 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -2,7 +2,6 @@ #include "shady/ir/memory_layout.h" #include "../transform/ir_gen_helpers.h" -#include "../type.h" #include "../ir_private.h" #include "log.h" diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index b3b69bda9..09b219d32 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" - -#include "../type.h" +#include "shady/ir/type.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 0f2499e50..65e186cb1 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index dab51b395..3e7b0fd7e 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -2,7 +2,6 @@ #include "shady/ir/memory_layout.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 1984d969e..d1d034a9b 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -1,8 +1,6 @@ #include "shady/pass.h" -#include "../type.h" #include "../ir_private.h" - #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 78410e8d2..05cf8fcfb 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "portability.h" diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index b6f8630c5..f94c9cba1 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -1,6 +1,5 @@ #include "shady/pass.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "dict.h" diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 2e609df53..a00a6974a 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index ecf7bc6df..13bf1ae6e 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "join_point_ops.h" -#include "../type.h" #include "../ir_private.h" #include "../analysis/cfg.h" diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index e7fa4cb94..6c9986bf6 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -1,6 +1,5 @@ #include "shady/pass.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "portability.h" diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 75a186095..75e8575a0 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "util.h" diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 6acbb2c00..62580e610 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 3effcac4d..9746d884f 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -1,15 +1,15 @@ #include "shady/pass.h" #include "shady/visit.h" -#include "../type.h" + #include "../ir_private.h" +#include "../check.h" #include "../transform/ir_gen_helpers.h" #include "../analysis/uses.h" #include "../analysis/leak.h" #include "log.h" #include "portability.h" -#include "list.h" #include "dict.h" #include "util.h" diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 15c456cf9..7ec962762 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -1,12 +1,9 @@ #include "shady/pass.h" -#include "../type.h" #include "../ir_private.h" - #include "../analysis/callgraph.h" #include "dict.h" -#include "list.h" #include "portability.h" #include "util.h" #include "log.h" diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index d89317902..d81c47ad7 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -1,13 +1,10 @@ -#include - #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" -#include "log.h" +#include "list.h" #include "portability.h" typedef struct { diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 858c6458b..c35e842d1 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -1,9 +1,7 @@ #include "shady/pass.h" -#include "../type.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" - #include "../analysis/cfg.h" #include "../analysis/looptree.h" diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index 51fd378e4..3f0d8ad52 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/restructure.c b/src/shady/passes/restructure.c index 58a02dc58..fcddff643 100644 --- a/src/shady/passes/restructure.c +++ b/src/shady/passes/restructure.c @@ -1,6 +1,5 @@ #include "shady/pass.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 82cafe07d..9d5d95ddd 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -1,5 +1,12 @@ #include "shady/pass.h" +#include "shady/rewrite.h" + +#include "../ir_private.h" +#include "../analysis/cfg.h" +#include "../analysis/scheduler.h" +#include "../transform/ir_gen_helpers.h" + #include "portability.h" #include "dict.h" #include "list.h" @@ -7,14 +14,6 @@ #include "arena.h" #include "util.h" -#include "shady/rewrite.h" -#include "../type.h" -#include "../ir_private.h" -#include "../analysis/cfg.h" -#include "../analysis/scheduler.h" -#include "../analysis/free_frontier.h" -#include "../transform/ir_gen_helpers.h" - #include KeyHash shd_hash_node(Node** pnode); diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index f2262bcbb..4e6c440fa 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../type.h" #include "../analysis/cfg.h" #include "../analysis/looptree.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 7a5f54c3e..0af6182be 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -1,7 +1,7 @@ #include "shady/pass.h" #include "shady/visit.h" -#include "../type.h" + #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 40ad3f5c0..08756b063 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -1,11 +1,8 @@ #include "shady/pass.h" -#include "../ir_private.h" -#include "../type.h" #include "../transform/ir_gen_helpers.h" #include "portability.h" -#include "log.h" #include diff --git a/src/shady/print.c b/src/shady/print.c index bc5e0adb6..3508717c6 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -1,5 +1,7 @@ #include "shady/print.h" +#include "shady/visit.h" + #include "ir_private.h" #include "analysis/cfg.h" #include "analysis/scheduler.h" @@ -12,9 +14,6 @@ #include "growy.h" #include "printer.h" -#include "type.h" -#include "shady/visit.h" - #include #include #include diff --git a/src/shady/rewrite.c b/src/shady/rewrite.c index ccfc674d9..e61c03657 100644 --- a/src/shady/rewrite.c +++ b/src/shady/rewrite.c @@ -1,10 +1,9 @@ #include "shady/rewrite.h" -#include "log.h" #include "ir_private.h" -#include "portability.h" -#include "type.h" +#include "log.h" +#include "portability.h" #include "dict.h" #include diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 93ad64f34..1a3838493 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -4,7 +4,6 @@ #include "shady/ir/memory_layout.h" #include "../ir_private.h" -#include "../type.h" #include "list.h" #include "portability.h" @@ -14,6 +13,20 @@ #include #include +const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes indices) { + const Node* lea = ptr_array_element_offset(a, (PtrArrayElementOffset) { + .ptr = ptr, + .offset = offset, + }); + for (size_t i = 0; i < indices.count; i++) { + lea = ptr_composite_element(a, (PtrCompositeElement) { + .ptr = lea, + .index = indices.nodes[i], + }); + } + return lea; +} + Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { assert(bb->arena->config.check_types); const Node* instruction = call(bb->arena, (Call) { .callee = callee, .args = args, .mem = bb_mem(bb) }); diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 2a121fcb2..08955484b 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -1,11 +1,10 @@ #include "shady/ir/memory_layout.h" + #include "ir_gen_helpers.h" #include "log.h" #include "portability.h" -#include "../type.h" - #include inline static size_t round_up(size_t a, size_t b) { diff --git a/src/shady/type.c b/src/shady/type.c deleted file mode 100644 index cded258bb..000000000 --- a/src/shady/type.c +++ /dev/null @@ -1,1280 +0,0 @@ -#include "type.h" - -#include "log.h" -#include "ir_private.h" -#include "portability.h" -#include "dict.h" -#include "util.h" - -#include "shady/ir/builtin.h" - -#include -#include - -#pragma GCC diagnostic error "-Wswitch" - -static bool are_types_identical(size_t num_types, const Type* types[]) { - for (size_t i = 0; i < num_types; i++) { - assert(types[i]); - if (types[0] != types[i]) - return false; - } - return true; -} - -bool is_subtype(const Type* supertype, const Type* type) { - assert(supertype && type); - if (supertype->tag != type->tag) - return false; - if (type == supertype) - return true; - switch (is_type(supertype)) { - case NotAType: shd_error("supplied not a type to is_subtype"); - case QualifiedType_TAG: { - // uniform T <: varying T - if (supertype->payload.qualified_type.is_uniform && !type->payload.qualified_type.is_uniform) - return false; - return is_subtype(supertype->payload.qualified_type.type, type->payload.qualified_type.type); - } - case RecordType_TAG: { - const Nodes* supermembers = &supertype->payload.record_type.members; - const Nodes* members = &type->payload.record_type.members; - if (supermembers->count != members->count) - return false; - for (size_t i = 0; i < members->count; i++) { - if (!is_subtype(supermembers->nodes[i], members->nodes[i])) - return false; - } - return supertype->payload.record_type.special == type->payload.record_type.special; - } - case JoinPointType_TAG: { - const Nodes* superparams = &supertype->payload.join_point_type.yield_types; - const Nodes* params = &type->payload.join_point_type.yield_types; - if (params->count != superparams->count) return false; - for (size_t i = 0; i < params->count; i++) { - if (!is_subtype(params->nodes[i], superparams->nodes[i])) - return false; - } - return true; - } - case FnType_TAG: { - // check returns - if (supertype->payload.fn_type.return_types.count != type->payload.fn_type.return_types.count) - return false; - for (size_t i = 0; i < type->payload.fn_type.return_types.count; i++) - if (!is_subtype(supertype->payload.fn_type.return_types.nodes[i], type->payload.fn_type.return_types.nodes[i])) - return false; - // check params - const Nodes* superparams = &supertype->payload.fn_type.param_types; - const Nodes* params = &type->payload.fn_type.param_types; - if (params->count != superparams->count) return false; - for (size_t i = 0; i < params->count; i++) { - if (!is_subtype(params->nodes[i], superparams->nodes[i])) - return false; - } - return true; - } case BBType_TAG: { - // check params - const Nodes* superparams = &supertype->payload.bb_type.param_types; - const Nodes* params = &type->payload.bb_type.param_types; - if (params->count != superparams->count) return false; - for (size_t i = 0; i < params->count; i++) { - if (!is_subtype(params->nodes[i], superparams->nodes[i])) - return false; - } - return true; - } case LamType_TAG: { - // check params - const Nodes* superparams = &supertype->payload.lam_type.param_types; - const Nodes* params = &type->payload.lam_type.param_types; - if (params->count != superparams->count) return false; - for (size_t i = 0; i < params->count; i++) { - if (!is_subtype(params->nodes[i], superparams->nodes[i])) - return false; - } - return true; - } case PtrType_TAG: { - if (supertype->payload.ptr_type.address_space != type->payload.ptr_type.address_space) - return false; - if (!supertype->payload.ptr_type.is_reference && type->payload.ptr_type.is_reference) - return false; - return is_subtype(supertype->payload.ptr_type.pointed_type, type->payload.ptr_type.pointed_type); - } - case Int_TAG: return supertype->payload.int_type.width == type->payload.int_type.width && supertype->payload.int_type.is_signed == type->payload.int_type.is_signed; - case ArrType_TAG: { - if (!is_subtype(supertype->payload.arr_type.element_type, type->payload.arr_type.element_type)) - return false; - // unsized arrays are supertypes of sized arrays (even though they're not datatypes...) - // TODO: maybe change this so it's only valid when talking about to pointer-to-arrays - const IntLiteral* size_literal = shd_resolve_to_int_literal(supertype->payload.arr_type.size); - if (size_literal && size_literal->value == 0) - return true; - return supertype->payload.arr_type.size == type->payload.arr_type.size || !supertype->payload.arr_type.size; - } - case PackType_TAG: { - if (!is_subtype(supertype->payload.pack_type.element_type, type->payload.pack_type.element_type)) - return false; - return supertype->payload.pack_type.width == type->payload.pack_type.width; - } - case Type_TypeDeclRef_TAG: { - return supertype->payload.type_decl_ref.decl == type->payload.type_decl_ref.decl; - } - case Type_ImageType_TAG: { - if (!is_subtype(supertype->payload.image_type.sampled_type, type->payload.image_type.sampled_type)) - return false; - if (supertype->payload.image_type.depth != type->payload.image_type.depth) - return false; - if (supertype->payload.image_type.dim != type->payload.image_type.dim) - return false; - if (supertype->payload.image_type.arrayed != type->payload.image_type.arrayed) - return false; - if (supertype->payload.image_type.ms != type->payload.image_type.ms) - return false; - if (supertype->payload.image_type.sampled != type->payload.image_type.sampled) - return false; - if (supertype->payload.image_type.imageformat != type->payload.image_type.imageformat) - return false; - return true; - } - case Type_SampledImageType_TAG: - return is_subtype(supertype->payload.sampled_image_type.image_type, type->payload.sampled_image_type.image_type); - default: break; - } - // Two types are always equal (and therefore subtypes of each other) if their payload matches - return memcmp(&supertype->payload, &type->payload, sizeof(type->payload)) == 0; -} - -void check_subtype(const Type* supertype, const Type* type) { - if (!is_subtype(supertype, type)) { - shd_log_node(ERROR, type); - shd_error_print(" isn't a subtype of "); - shd_log_node(ERROR, supertype); - shd_error_print("\n"); - shd_error("failed check_subtype") - } -} - -size_t shd_get_type_bitwidth(const Type* t) { - switch (t->tag) { - case Int_TAG: return int_size_in_bytes(t->payload.int_type.width) * 8; - case Float_TAG: return float_size_in_bytes(t->payload.float_type.width) * 8; - case PtrType_TAG: { - if (t->arena->config.address_spaces[t->payload.ptr_type.address_space].physical) - return int_size_in_bytes(t->arena->config.memory.ptr_size) * 8; - break; - } - default: break; - } - return SIZE_MAX; -} - -bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { - switch (as) { - case AsGeneric: - case AsInput: - case AsOutput: - case AsFunction: - case AsPrivate: return !arena->config.is_simt; - default: return true; - } -} - -const Type* get_actual_mask_type(IrArena* arena) { - switch (arena->config.specializations.subgroup_mask_representation) { - case SubgroupMaskAbstract: return mask_type(arena); - case SubgroupMaskInt64: return shd_uint64_type(arena); - default: assert(false); - } -} - -String name_type_safe(IrArena* arena, const Type* t) { - switch (is_type(t)) { - case NotAType: assert(false); - case Type_MaskType_TAG: return "mask_t"; - case Type_JoinPointType_TAG: return "join_type_t"; - case Type_NoRet_TAG: return "no_ret"; - case Type_Int_TAG: { - if (t->payload.int_type.is_signed) - return shd_format_string_arena(arena->arena, "i%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); - else - return shd_format_string_arena(arena->arena, "u%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); - } - case Type_Float_TAG: return shd_format_string_arena(arena->arena, "f%s", ((String[]) { "16", "32", "64" })[t->payload.float_type.width]); - case Type_Bool_TAG: return "bool"; - case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; - default: break; - } - return unique_name(arena, shd_get_node_tag_string(t->tag)); -} - -/// Is this a type that a value in the language can have ? -bool is_value_type(const Type* type) { - if (type->tag != QualifiedType_TAG) - return false; - return is_data_type(get_unqualified_type(type)); -} - -/// Is this a valid data type (for usage in other types and as type arguments) ? -bool is_data_type(const Type* type) { - switch (is_type(type)) { - case Type_MaskType_TAG: - case Type_JoinPointType_TAG: - case Type_Int_TAG: - case Type_Float_TAG: - case Type_Bool_TAG: - return true; - case Type_PtrType_TAG: - return true; - case Type_ArrType_TAG: - // array types _must_ be sized to be real data types - return type->payload.arr_type.size != NULL; - case Type_PackType_TAG: - return is_data_type(type->payload.pack_type.element_type); - case Type_RecordType_TAG: { - for (size_t i = 0; i < type->payload.record_type.members.count; i++) - if (!is_data_type(type->payload.record_type.members.nodes[i])) - return false; - // multi-return record types are the results of instructions, but are not values themselves - return type->payload.record_type.special == NotSpecial; - } - case Type_TypeDeclRef_TAG: - return !get_nominal_type_body(type) || is_data_type(get_nominal_type_body(type)); - // qualified types are not data types because that information is only meant for values - case Type_QualifiedType_TAG: return false; - // values cannot contain abstractions - case Type_FnType_TAG: - case Type_BBType_TAG: - case Type_LamType_TAG: - return false; - // this type has no values to begin with - case Type_NoRet_TAG: - return false; - case NotAType: - return false; - // Image stuff is data (albeit opaque) - case Type_SampledImageType_TAG: - case Type_SamplerType_TAG: - case Type_ImageType_TAG: - return true; - } -} - -bool is_arithm_type(const Type* t) { - return t->tag == Int_TAG || t->tag == Float_TAG; -} - -bool is_shiftable_type(const Type* t) { - return t->tag == Int_TAG || t->tag == MaskType_TAG; -} - -bool has_boolean_ops(const Type* t) { - return t->tag == Int_TAG || t->tag == Bool_TAG || t->tag == MaskType_TAG; -} - -bool is_comparable_type(const Type* t) { - return true; // TODO this is fine to allow, but we'll need to lower it for composite and native ptr types ! -} - -bool is_ordered_type(const Type* t) { - return is_arithm_type(t); -} - -bool is_physical_ptr_type(const Type* t) { - if (t->tag != PtrType_TAG) - return false; - return !t->payload.ptr_type.is_reference; - // AddressSpace as = t->payload.ptr_type.address_space; - // return t->arena->config.address_spaces[as].physical; -} - -bool is_generic_ptr_type(const Type* t) { - if (t->tag != PtrType_TAG) - return false; - AddressSpace as = t->payload.ptr_type.address_space; - return as == AsGeneric; -} - -bool is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type) { - assert(is_data_type(src_type) && is_data_type(dst_type)); - if (src_type == dst_type) - return true; // folding will eliminate those, but we need to pass type-checking first :) - if (!(is_arithm_type(src_type) || src_type->tag == MaskType_TAG || is_physical_ptr_type(src_type))) - return false; - if (!(is_arithm_type(dst_type) || dst_type->tag == MaskType_TAG || is_physical_ptr_type(dst_type))) - return false; - assert(shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)); - // either both pointers need to be in the generic address space, and we're only casting the element type, OR neither can be - if ((is_physical_ptr_type(src_type) && is_physical_ptr_type(dst_type)) && (is_generic_ptr_type(src_type) != is_generic_ptr_type(dst_type))) - return false; - return true; -} - -bool is_conversion_legal(const Type* src_type, const Type* dst_type) { - assert(is_data_type(src_type) && is_data_type(dst_type)); - if (!(is_arithm_type(src_type) || (is_physical_ptr_type(src_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) - return false; - if (!(is_arithm_type(dst_type) || (is_physical_ptr_type(dst_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) - return false; - // we only allow ptr-ptr conversions, use reinterpret otherwise - if (is_physical_ptr_type(src_type) != is_physical_ptr_type(dst_type)) - return false; - // exactly one of the pointers needs to be in the generic address space - if (is_generic_ptr_type(src_type) && is_generic_ptr_type(dst_type)) - return false; - if (src_type->tag == Int_TAG && dst_type->tag == Int_TAG) { - bool changes_sign = src_type->payload.int_type.is_signed != dst_type->payload.int_type.is_signed; - bool changes_width = src_type->payload.int_type.width != dst_type->payload.int_type.width; - if (changes_sign && changes_width) - return false; - } - // element types have to match (use reinterpret_cast for changing it) - if (is_physical_ptr_type(src_type) && is_physical_ptr_type(dst_type)) { - AddressSpace src_as = src_type->payload.ptr_type.address_space; - AddressSpace dst_as = dst_type->payload.ptr_type.address_space; - if (src_type->payload.ptr_type.pointed_type != dst_type->payload.ptr_type.pointed_type) - return false; - } - return true; -} - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" - -const Type* check_type_join_point_type(IrArena* arena, JoinPointType type) { - for (size_t i = 0; i < type.yield_types.count; i++) { - assert(is_data_type(type.yield_types.nodes[i])); - } - return NULL; -} - -const Type* check_type_record_type(IrArena* arena, RecordType type) { - assert(type.names.count == 0 || type.names.count == type.members.count); - for (size_t i = 0; i < type.members.count; i++) { - // member types are value types iff this is a return tuple - if (type.special == MultipleReturn) - assert(is_value_type(type.members.nodes[i])); - else - assert(is_data_type(type.members.nodes[i])); - } - return NULL; -} - -const Type* check_type_qualified_type(IrArena* arena, QualifiedType qualified_type) { - assert(is_data_type(qualified_type.type)); - assert(arena->config.is_simt || qualified_type.is_uniform); - return NULL; -} - -const Type* check_type_arr_type(IrArena* arena, ArrType type) { - assert(is_data_type(type.element_type)); - return NULL; -} - -const Type* check_type_pack_type(IrArena* arena, PackType pack_type) { - assert(is_data_type(pack_type.element_type)); - return NULL; -} - -const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { - if (!arena->config.address_spaces[ptr_type.address_space].allowed) { - shd_error_print("Address space %s is not allowed in this arena\n", get_address_space_name(ptr_type.address_space)); - shd_error_die(); - } - assert(ptr_type.pointed_type && "Shady does not support untyped pointers, but can infer them, see infer.c"); - if (ptr_type.pointed_type) { - if (ptr_type.pointed_type->tag == ArrType_TAG) { - assert(is_data_type(ptr_type.pointed_type->payload.arr_type.element_type)); - return NULL; - } - if (ptr_type.pointed_type->tag == FnType_TAG || ptr_type.pointed_type == unit_type(arena)) { - // no diagnostic required, we just allow these - return NULL; - } - const Node* maybe_record_type = ptr_type.pointed_type; - if (maybe_record_type->tag == TypeDeclRef_TAG) - maybe_record_type = get_nominal_type_body(maybe_record_type); - if (maybe_record_type && maybe_record_type->tag == RecordType_TAG && maybe_record_type->payload.record_type.special == DecorateBlock) { - return NULL; - } - assert(is_data_type(ptr_type.pointed_type)); - } - return NULL; -} - -const Type* check_type_param(IrArena* arena, Param variable) { - assert(is_value_type(variable.type)); - return variable.type; -} - -const Type* check_type_untyped_number(IrArena* arena, UntypedNumber untyped) { - shd_error("should never happen"); -} - -const Type* check_type_int_literal(IrArena* arena, IntLiteral lit) { - return qualified_type(arena, (QualifiedType) { - .is_uniform = true, - .type = int_type(arena, (Int) { .width = lit.width, .is_signed = lit.is_signed }) - }); -} - -const Type* check_type_float_literal(IrArena* arena, FloatLiteral lit) { - return qualified_type(arena, (QualifiedType) { - .is_uniform = true, - .type = float_type(arena, (Float) { .width = lit.width }) - }); -} - -const Type* check_type_true_lit(IrArena* arena) { return qualified_type(arena, (QualifiedType) { .type = bool_type(arena), .is_uniform = true }); } -const Type* check_type_false_lit(IrArena* arena) { return qualified_type(arena, (QualifiedType) { .type = bool_type(arena), .is_uniform = true }); } - -const Type* check_type_string_lit(IrArena* arena, StringLiteral str_lit) { - const Type* t = arr_type(arena, (ArrType) { - .element_type = shd_int8_type(arena), - .size = shd_int32_literal(arena, strlen(str_lit.string)) - }); - return qualified_type(arena, (QualifiedType) { - .type = t, - .is_uniform = true, - }); -} - -const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { - assert(is_data_type(payload.ptr_type) && payload.ptr_type->tag == PtrType_TAG); - return shd_as_qualified_type(payload.ptr_type, true); -} - -const Type* check_type_composite(IrArena* arena, Composite composite) { - if (composite.type) { - assert(is_data_type(composite.type)); - Nodes expected_member_types = get_composite_type_element_types(composite.type); - bool is_uniform = true; - assert(composite.contents.count == expected_member_types.count); - for (size_t i = 0; i < composite.contents.count; i++) { - const Type* element_type = composite.contents.nodes[i]->type; - is_uniform &= deconstruct_qualified_type(&element_type); - assert(is_subtype(expected_member_types.nodes[i], element_type)); - } - return qualified_type(arena, (QualifiedType) { - .is_uniform = is_uniform, - .type = composite.type - }); - } - bool is_uniform = true; - LARRAY(const Type*, member_ts, composite.contents.count); - for (size_t i = 0; i < composite.contents.count; i++) { - const Type* element_type = composite.contents.nodes[i]->type; - is_uniform &= deconstruct_qualified_type(&element_type); - member_ts[i] = element_type; - } - return qualified_type(arena, (QualifiedType) { - .is_uniform = is_uniform, - .type = record_type(arena, (RecordType) { - .members = shd_nodes(arena, composite.contents.count, member_ts) - }) - }); -} - -const Type* check_type_fill(IrArena* arena, Fill payload) { - assert(is_data_type(payload.type)); - const Node* element_t = get_fill_type_element_type(payload.type); - const Node* value_t = payload.value->type; - bool u = deconstruct_qualified_type(&value_t); - assert(is_subtype(element_t, value_t)); - return qualified_type(arena, (QualifiedType) { - .is_uniform = u, - .type = payload.type - }); -} - -const Type* check_type_undef(IrArena* arena, Undef payload) { - assert(is_data_type(payload.type)); - return qualified_type(arena, (QualifiedType) { - .is_uniform = true, - .type = payload.type - }); -} - -const Type* check_type_mem_and_value(IrArena* arena, MemAndValue mav) { - return mav.value->type; -} - -const Type* check_type_fn_addr(IrArena* arena, FnAddr fn_addr) { - assert(fn_addr.fn->type->tag == FnType_TAG); - assert(fn_addr.fn->tag == Function_TAG); - return qualified_type(arena, (QualifiedType) { - .is_uniform = true, - .type = ptr_type(arena, (PtrType) { - .pointed_type = fn_addr.fn->type, - .address_space = AsGeneric /* the actual AS does not matter because these are opaque anyways */, - }) - }); -} - -const Type* check_type_ref_decl(IrArena* arena, RefDecl ref_decl) { - const Type* t = ref_decl.decl->type; - assert(t && "RefDecl needs to be applied on a decl with a non-null type. Did you forget to set 'type' on a constant ?"); - switch (ref_decl.decl->tag) { - case GlobalVariable_TAG: - case Constant_TAG: break; - default: shd_error("You can only use RefDecl on a global or a constant. See FnAddr for taking addresses of functions.") - } - assert(t->tag != QualifiedType_TAG && "decl types may not be qualified"); - return qualified_type(arena, (QualifiedType) { - .type = t, - .is_uniform = true, - }); -} - -const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { - for (size_t i = 0; i < prim_op.type_arguments.count; i++) { - const Node* ta = prim_op.type_arguments.nodes[i]; - assert(ta && is_type(ta)); - } - for (size_t i = 0; i < prim_op.operands.count; i++) { - const Node* operand = prim_op.operands.nodes[i]; - assert(operand && is_value(operand)); - } - - bool extended = false; - bool ordered = false; - AddressSpace as; - switch (prim_op.op) { - case neg_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 1); - - const Type* type = shd_first(prim_op.operands)->type; - assert(is_arithm_type(get_maybe_packed_type_element(get_unqualified_type(type)))); - return type; - } - case rshift_arithm_op: - case rshift_logical_op: - case lshift_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 2); - const Type* first_operand_type = shd_first(prim_op.operands)->type; - const Type* second_operand_type = prim_op.operands.nodes[1]->type; - - bool uniform_result = deconstruct_qualified_type(&first_operand_type); - uniform_result &= deconstruct_qualified_type(&second_operand_type); - - size_t value_simd_width = deconstruct_maybe_packed_type(&first_operand_type); - size_t shift_simd_width = deconstruct_maybe_packed_type(&second_operand_type); - assert(value_simd_width == shift_simd_width); - - assert(first_operand_type->tag == Int_TAG); - assert(second_operand_type->tag == Int_TAG); - - return shd_as_qualified_type(maybe_packed_type_helper(first_operand_type, value_simd_width), uniform_result); - } - case add_carry_op: - case sub_borrow_op: - case mul_extended_op: extended = true; SHADY_FALLTHROUGH; - case min_op: - case max_op: - case add_op: - case sub_op: - case mul_op: - case div_op: - case mod_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); - - bool result_uniform = true; - for (size_t i = 0; i < prim_op.operands.count; i++) { - const Node* arg = prim_op.operands.nodes[i]; - const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); - - assert(is_arithm_type(get_maybe_packed_type_element(operand_type))); - assert(first_operand_type == operand_type && "operand type mismatch"); - - result_uniform &= operand_uniform; - } - - const Type* result_t = first_operand_type; - if (extended) { - // TODO: assert unsigned - result_t = record_type(arena, (RecordType) {.members = mk_nodes(arena, result_t, result_t)}); - } - return shd_as_qualified_type(result_t, result_uniform); - } - - case not_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 1); - - const Type* type = shd_first(prim_op.operands)->type; - assert(has_boolean_ops(get_maybe_packed_type_element(get_unqualified_type(type)))); - return type; - } - case or_op: - case xor_op: - case and_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); - - bool result_uniform = true; - for (size_t i = 0; i < prim_op.operands.count; i++) { - const Node* arg = prim_op.operands.nodes[i]; - const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); - - assert(has_boolean_ops(get_maybe_packed_type_element(operand_type))); - assert(first_operand_type == operand_type && "operand type mismatch"); - - result_uniform &= operand_uniform; - } - - return shd_as_qualified_type(first_operand_type, result_uniform); - } - case lt_op: - case lte_op: - case gt_op: - case gte_op: ordered = true; SHADY_FALLTHROUGH - case eq_op: - case neq_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); - size_t first_operand_width = get_maybe_packed_type_width(first_operand_type); - - bool result_uniform = true; - for (size_t i = 0; i < prim_op.operands.count; i++) { - const Node* arg = prim_op.operands.nodes[i]; - const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); - - assert((ordered ? is_ordered_type : is_comparable_type)(get_maybe_packed_type_element(operand_type))); - assert(first_operand_type == operand_type && "operand type mismatch"); - - result_uniform &= operand_uniform; - } - - return shd_as_qualified_type(maybe_packed_type_helper(bool_type(arena), first_operand_width), - result_uniform); - } - case sqrt_op: - case inv_sqrt_op: - case floor_op: - case ceil_op: - case round_op: - case fract_op: - case sin_op: - case cos_op: - case exp_op: - { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 1); - const Node* src_type = shd_first(prim_op.operands)->type; - bool uniform = deconstruct_qualified_type(&src_type); - size_t width = deconstruct_maybe_packed_type(&src_type); - assert(src_type->tag == Float_TAG); - return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); - } - case pow_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); - - bool result_uniform = true; - for (size_t i = 0; i < prim_op.operands.count; i++) { - const Node* arg = prim_op.operands.nodes[i]; - const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); - - assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); - assert(first_operand_type == operand_type && "operand type mismatch"); - - result_uniform &= operand_uniform; - } - - return shd_as_qualified_type(first_operand_type, result_uniform); - } - case fma_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 3); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); - - bool result_uniform = true; - for (size_t i = 0; i < prim_op.operands.count; i++) { - const Node* arg = prim_op.operands.nodes[i]; - const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); - - assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); - assert(first_operand_type == operand_type && "operand type mismatch"); - - result_uniform &= operand_uniform; - } - - return shd_as_qualified_type(first_operand_type, result_uniform); - } - case abs_op: - case sign_op: - { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 1); - const Node* src_type = shd_first(prim_op.operands)->type; - bool uniform = deconstruct_qualified_type(&src_type); - size_t width = deconstruct_maybe_packed_type(&src_type); - assert(src_type->tag == Float_TAG || src_type->tag == Int_TAG && src_type->payload.int_type.is_signed); - return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); - } - case align_of_op: - case size_of_op: { - assert(prim_op.type_arguments.count == 1); - assert(prim_op.operands.count == 0); - return qualified_type(arena, (QualifiedType) { - .is_uniform = true, - .type = int_type(arena, (Int) { .width = arena->config.memory.ptr_size, .is_signed = false }) - }); - } - case offset_of_op: { - assert(prim_op.type_arguments.count == 1); - assert(prim_op.operands.count == 1); - const Type* optype = shd_first(prim_op.operands)->type; - bool uniform = deconstruct_qualified_type(&optype); - assert(uniform && optype->tag == Int_TAG); - return qualified_type(arena, (QualifiedType) { - .is_uniform = true, - .type = int_type(arena, (Int) { .width = arena->config.memory.ptr_size, .is_signed = false }) - }); - } - case select_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 3); - const Type* condition_type = prim_op.operands.nodes[0]->type; - bool condition_uniform = deconstruct_qualified_type(&condition_type); - size_t width = deconstruct_maybe_packed_type(&condition_type); - - const Type* alternatives_types[2]; - bool alternatives_all_uniform = true; - for (size_t i = 0; i < 2; i++) { - alternatives_types[i] = prim_op.operands.nodes[1 + i]->type; - alternatives_all_uniform &= deconstruct_qualified_type(&alternatives_types[i]); - size_t alternative_width = deconstruct_maybe_packed_type(&alternatives_types[i]); - assert(alternative_width == width); - } - - assert(is_subtype(bool_type(arena), condition_type)); - // todo find true supertype - assert(are_types_identical(2, alternatives_types)); - - return shd_as_qualified_type(maybe_packed_type_helper(alternatives_types[0], width), - alternatives_all_uniform && condition_uniform); - } - case insert_op: - case extract_dynamic_op: - case extract_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count >= 2); - const Node* source = shd_first(prim_op.operands); - - size_t indices_start = prim_op.op == insert_op ? 2 : 1; - Nodes indices = shd_nodes(arena, prim_op.operands.count - indices_start, &prim_op.operands.nodes[indices_start]); - - const Type* t = source->type; - bool uniform = deconstruct_qualified_type(&t); - enter_composite_indices(&t, &uniform, indices, true); - - if (prim_op.op == insert_op) { - const Node* inserted_data = prim_op.operands.nodes[1]; - const Type* inserted_data_type = inserted_data->type; - bool is_uniform = uniform & deconstruct_qualified_type(&inserted_data_type); - assert(is_subtype(t, inserted_data_type) && "inserting data into a composite, but it doesn't match the target and indices"); - return qualified_type(arena, (QualifiedType) { - .is_uniform = is_uniform, - .type = get_unqualified_type(source->type), - }); - } - - return shd_as_qualified_type(t, uniform); - } - case shuffle_op: { - assert(prim_op.operands.count >= 2); - assert(prim_op.type_arguments.count == 0); - const Node* lhs = prim_op.operands.nodes[0]; - const Node* rhs = prim_op.operands.nodes[1]; - const Type* lhs_t = lhs->type; - const Type* rhs_t = rhs->type; - bool lhs_u = deconstruct_qualified_type(&lhs_t); - bool rhs_u = deconstruct_qualified_type(&rhs_t); - assert(lhs_t->tag == PackType_TAG && rhs_t->tag == PackType_TAG); - size_t total_size = lhs_t->payload.pack_type.width + rhs_t->payload.pack_type.width; - const Type* element_t = lhs_t->payload.pack_type.element_type; - assert(element_t == rhs_t->payload.pack_type.element_type); - - size_t indices_count = prim_op.operands.count - 2; - const Node** indices = &prim_op.operands.nodes[2]; - bool u = lhs_u & rhs_u; - for (size_t i = 0; i < indices_count; i++) { - u &= is_qualified_type_uniform(indices[i]->type); - int64_t index = shd_get_int_literal_value(*shd_resolve_to_int_literal(indices[i]), true); - assert(index < 0 /* poison */ || (index >= 0 && index < total_size && "shuffle element out of range")); - } - return shd_as_qualified_type( - pack_type(arena, (PackType) {.element_type = element_t, .width = indices_count}), u); - } - case reinterpret_op: { - assert(prim_op.type_arguments.count == 1); - assert(prim_op.operands.count == 1); - const Node* source = shd_first(prim_op.operands); - const Type* src_type = source->type; - bool src_uniform = deconstruct_qualified_type(&src_type); - - const Type* dst_type = shd_first(prim_op.type_arguments); - assert(is_data_type(dst_type)); - assert(is_reinterpret_cast_legal(src_type, dst_type)); - - return qualified_type(arena, (QualifiedType) { - .is_uniform = src_uniform, - .type = dst_type - }); - } - case convert_op: { - assert(prim_op.type_arguments.count == 1); - assert(prim_op.operands.count == 1); - const Node* source = shd_first(prim_op.operands); - const Type* src_type = source->type; - bool src_uniform = deconstruct_qualified_type(&src_type); - - const Type* dst_type = shd_first(prim_op.type_arguments); - assert(is_data_type(dst_type)); - assert(is_conversion_legal(src_type, dst_type)); - - // TODO check the conversion is legal - return qualified_type(arena, (QualifiedType) { - .is_uniform = src_uniform, - .type = dst_type - }); - } - // Mask management - case empty_mask_op: { - assert(prim_op.type_arguments.count == 0 && prim_op.operands.count == 0); - return shd_as_qualified_type(get_actual_mask_type(arena), true); - } - case mask_is_thread_active_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 2); - return qualified_type(arena, (QualifiedType) { - .is_uniform = is_qualified_type_uniform(prim_op.operands.nodes[0]->type) && is_qualified_type_uniform(prim_op.operands.nodes[1]->type), - .type = bool_type(arena) - }); - } - // Subgroup ops - case subgroup_assume_uniform_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 1); - const Type* operand_type = get_unqualified_type(prim_op.operands.nodes[0]->type); - return qualified_type(arena, (QualifiedType) { - .is_uniform = true, - .type = operand_type - }); - } - // Intermediary ops - case sample_texture_op: { - assert(prim_op.type_arguments.count == 0); - assert(prim_op.operands.count == 2); - const Type* sampled_image_t = shd_first(prim_op.operands)->type; - bool uniform_src = deconstruct_qualified_type(&sampled_image_t); - const Type* coords_t = prim_op.operands.nodes[1]->type; - deconstruct_qualified_type(&coords_t); - assert(sampled_image_t->tag == SampledImageType_TAG); - const Type* image_t = sampled_image_t->payload.sampled_image_type.image_type; - assert(image_t->tag == ImageType_TAG); - size_t coords_dim = deconstruct_packed_type(&coords_t); - return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = maybe_packed_type_helper(image_t->payload.image_type.sampled_type, 4) }); - } - case PRIMOPS_COUNT: assert(false); - } -} - -const Type* check_type_ext_instr(IrArena* arena, ExtInstr payload) { - return payload.result_t; -} - -static void check_arguments_types_against_parameters_helper(Nodes param_types, Nodes arg_types) { - if (param_types.count != arg_types.count) - shd_error("Mismatched number of arguments/parameters"); - for (size_t i = 0; i < param_types.count; i++) - check_subtype(param_types.nodes[i], arg_types.nodes[i]); -} - -/// Shared logic between indirect calls and tailcalls -static Nodes check_value_call(const Node* callee, Nodes argument_types) { - assert(is_value(callee)); - - const Type* callee_type = callee->type; - SHADY_UNUSED bool callee_uniform = deconstruct_qualified_type(&callee_type); - AddressSpace as = deconstruct_pointer_type(&callee_type); - assert(as == AsGeneric); - - assert(callee_type->tag == FnType_TAG); - - const FnType* fn_type = &callee_type->payload.fn_type; - check_arguments_types_against_parameters_helper(fn_type->param_types, argument_types); - // TODO force the return types to be varying if the callee is not uniform - return fn_type->return_types; -} - -const Type* check_type_call(IrArena* arena, Call call) { - Nodes args = call.args; - for (size_t i = 0; i < args.count; i++) { - const Node* argument = args.nodes[i]; - assert(is_value(argument)); - } - Nodes argument_types = get_values_types(arena, args); - return maybe_multiple_return(arena, check_value_call(call.callee, argument_types)); -} - -static void ensure_types_are_data_types(const Nodes* yield_types) { - for (size_t i = 0; i < yield_types->count; i++) { - assert(is_data_type(yield_types->nodes[i])); - } -} - -static void ensure_types_are_value_types(const Nodes* yield_types) { - for (size_t i = 0; i < yield_types->count; i++) { - assert(is_value_type(yield_types->nodes[i])); - } -} - -const Type* check_type_if_instr(IrArena* arena, If if_instr) { - assert(if_instr.tail && is_abstraction(if_instr.tail)); - ensure_types_are_data_types(&if_instr.yield_types); - if (get_unqualified_type(if_instr.condition->type) != bool_type(arena)) - shd_error("condition of an if should be bool"); - // TODO check the contained Merge instrs - if (if_instr.yield_types.count > 0) - assert(if_instr.if_false); - - check_arguments_types_against_parameters_helper(get_param_types(arena, get_abstraction_params(if_instr.tail)), add_qualifiers(arena, if_instr.yield_types, false)); - return noret_type(arena); -} - -const Type* check_type_match_instr(IrArena* arena, Match match_instr) { - ensure_types_are_data_types(&match_instr.yield_types); - // TODO check param against initial_args - // TODO check the contained Merge instrs - return noret_type(arena); -} - -const Type* check_type_loop_instr(IrArena* arena, Loop loop_instr) { - ensure_types_are_data_types(&loop_instr.yield_types); - // TODO check param against initial_args - // TODO check the contained Merge instrs - return noret_type(arena); -} - -const Type* check_type_control(IrArena* arena, Control control) { - ensure_types_are_data_types(&control.yield_types); - // TODO check it then ! - const Node* join_point = shd_first(get_abstraction_params(control.inside)); - - const Type* join_point_type = join_point->type; - deconstruct_qualified_type(&join_point_type); - assert(join_point_type->tag == JoinPointType_TAG); - - Nodes join_point_yield_types = join_point_type->payload.join_point_type.yield_types; - assert(join_point_yield_types.count == control.yield_types.count); - for (size_t i = 0; i < control.yield_types.count; i++) { - assert(is_subtype(control.yield_types.nodes[i], join_point_yield_types.nodes[i])); - } - - assert(get_abstraction_params(control.tail).count == control.yield_types.count); - - return noret_type(arena); -} - -const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { - return empty_multiple_return_type(arena); -} - -const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { - assert(is_type(alloc.type)); - return qualified_type(a, (QualifiedType) { - .is_uniform = is_addr_space_uniform(a, AsPrivate), - .type = ptr_type(a, (PtrType) { - .pointed_type = alloc.type, - .address_space = AsPrivate, - .is_reference = false - }) - }); -} - -const Type* check_type_local_alloc(IrArena* a, LocalAlloc alloc) { - assert(is_type(alloc.type)); - return qualified_type(a, (QualifiedType) { - .is_uniform = is_addr_space_uniform(a, AsFunction), - .type = ptr_type(a, (PtrType) { - .pointed_type = alloc.type, - .address_space = AsFunction, - .is_reference = true - }) - }); -} - -const Type* check_type_load(IrArena* a, Load load) { - const Node* ptr_type = load.ptr->type; - bool ptr_uniform = deconstruct_qualified_type(&ptr_type); - size_t width = deconstruct_maybe_packed_type(&ptr_type); - - assert(ptr_type->tag == PtrType_TAG); - const PtrType* node_ptr_type_ = &ptr_type->payload.ptr_type; - const Type* elem_type = node_ptr_type_->pointed_type; - elem_type = maybe_packed_type_helper(elem_type, width); - return shd_as_qualified_type(elem_type, - ptr_uniform && is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); -} - -const Type* check_type_store(IrArena* a, Store store) { - const Node* ptr_type = store.ptr->type; - bool ptr_uniform = deconstruct_qualified_type(&ptr_type); - size_t width = deconstruct_maybe_packed_type(&ptr_type); - assert(ptr_type->tag == PtrType_TAG); - const PtrType* ptr_type_payload = &ptr_type->payload.ptr_type; - const Type* elem_type = ptr_type_payload->pointed_type; - assert(elem_type); - elem_type = maybe_packed_type_helper(elem_type, width); - // we don't enforce uniform stores - but we care about storing the right thing :) - const Type* val_expected_type = qualified_type(a, (QualifiedType) { - .is_uniform = !a->config.is_simt, - .type = elem_type - }); - - assert(is_subtype(val_expected_type, store.value->type)); - return empty_multiple_return_type(a); -} - -const Type* check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffset lea) { - const Type* base_ptr_type = lea.ptr->type; - bool uniform = deconstruct_qualified_type(&base_ptr_type); - assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); - const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; - - assert(lea.offset); - const Type* offset_type = lea.offset->type; - bool offset_uniform = deconstruct_qualified_type(&offset_type); - assert(offset_type->tag == Int_TAG && "lea expects an integer offset"); - - const IntLiteral* lit = shd_resolve_to_int_literal(lea.offset); - bool offset_is_zero = lit && lit->value == 0; - assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); - assert(offset_is_zero || is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); - uniform &= offset_uniform; - - return qualified_type(a, (QualifiedType) { - .is_uniform = uniform, - .type = ptr_type(a, (PtrType) { - .pointed_type = pointee_type, - .address_space = base_ptr_type->payload.ptr_type.address_space, - .is_reference = base_ptr_type->payload.ptr_type.is_reference - }) - }); -} - -const Type* check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea) { - const Type* base_ptr_type = lea.ptr->type; - bool uniform = deconstruct_qualified_type(&base_ptr_type); - assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); - const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; - - enter_composite(&pointee_type, &uniform, lea.index, true); - - return qualified_type(a, (QualifiedType) { - .is_uniform = uniform, - .type = ptr_type(a, (PtrType) { - .pointed_type = pointee_type, - .address_space = base_ptr_type->payload.ptr_type.address_space, - .is_reference = base_ptr_type->payload.ptr_type.is_reference - }) - }); -} - -const Type* check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { - const Type* dst_t = copy_bytes.dst->type; - deconstruct_qualified_type(&dst_t); - assert(dst_t->tag == PtrType_TAG); - const Type* src_t = copy_bytes.src->type; - deconstruct_qualified_type(&src_t); - assert(src_t); - const Type* cnt_t = copy_bytes.count->type; - deconstruct_qualified_type(&cnt_t); - assert(cnt_t->tag == Int_TAG); - return empty_multiple_return_type(a); -} - -const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { - const Type* dst_t = fill_bytes.dst->type; - deconstruct_qualified_type(&dst_t); - assert(dst_t->tag == PtrType_TAG); - const Type* src_t = fill_bytes.src->type; - deconstruct_qualified_type(&src_t); - assert(src_t); - const Type* cnt_t = fill_bytes.count->type; - deconstruct_qualified_type(&cnt_t); - assert(cnt_t->tag == Int_TAG); - return empty_multiple_return_type(a); -} - -const Type* check_type_push_stack(IrArena* a, PushStack payload) { - assert(payload.value); - return empty_multiple_return_type(a); -} - -const Type* check_type_pop_stack(IrArena* a, PopStack payload) { - return shd_as_qualified_type(payload.type, false); -} - -const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { - assert(get_unqualified_type(payload.value->type) == shd_uint32_type(a)); - return shd_as_qualified_type(unit_type(a), true); -} - -const Type* check_type_get_stack_size(IrArena* a, SHADY_UNUSED GetStackSize ss) { - return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = shd_uint32_type(a) }); -} - -const Type* check_type_get_stack_base_addr(IrArena* a, SHADY_UNUSED GetStackBaseAddr gsba) { - const Node* ptr = ptr_type(a, (PtrType) { .pointed_type = shd_uint8_type(a), .address_space = AsPrivate}); - return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = ptr }); -} - -const Type* check_type_debug_printf(IrArena* a, DebugPrintf payload) { - return empty_multiple_return_type(a); -} - -const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { - Nodes args = tail_call.args; - for (size_t i = 0; i < args.count; i++) { - const Node* argument = args.nodes[i]; - assert(is_value(argument)); - } - assert(check_value_call(tail_call.callee, get_values_types(arena, tail_call.args)).count == 0); - return noret_type(arena); -} - -static void check_basic_block_call(const Node* block, Nodes argument_types) { - assert(is_basic_block(block)); - assert(block->type->tag == BBType_TAG); - BBType bb_type = block->type->payload.bb_type; - check_arguments_types_against_parameters_helper(bb_type.param_types, argument_types); -} - -const Type* check_type_jump(IrArena* arena, Jump jump) { - for (size_t i = 0; i < jump.args.count; i++) { - const Node* argument = jump.args.nodes[i]; - assert(is_value(argument)); - } - - check_basic_block_call(jump.target, get_values_types(arena, jump.args)); - return noret_type(arena); -} - -const Type* check_type_branch(IrArena* arena, Branch payload) { - assert(payload.true_jump->tag == Jump_TAG); - assert(payload.false_jump->tag == Jump_TAG); - return noret_type(arena); -} - -const Type* check_type_br_switch(IrArena* arena, Switch payload) { - for (size_t i = 0; i < payload.case_jumps.count; i++) - assert(payload.case_jumps.nodes[i]->tag == Jump_TAG); - assert(payload.case_values.count == payload.case_jumps.count); - assert(payload.default_jump->tag == Jump_TAG); - return noret_type(arena); -} - -const Type* check_type_join(IrArena* arena, Join join) { - for (size_t i = 0; i < join.args.count; i++) { - const Node* argument = join.args.nodes[i]; - assert(is_value(argument)); - } - - const Type* join_target_type = join.join_point->type; - - deconstruct_qualified_type(&join_target_type); - assert(join_target_type->tag == JoinPointType_TAG); - - Nodes join_point_param_types = join_target_type->payload.join_point_type.yield_types; - join_point_param_types = add_qualifiers(arena, join_point_param_types, !arena->config.is_simt); - - check_arguments_types_against_parameters_helper(join_point_param_types, get_values_types(arena, join.args)); - - return noret_type(arena); -} - -const Type* check_type_unreachable(IrArena* arena, SHADY_UNUSED Unreachable u) { - return noret_type(arena); -} - -const Type* check_type_merge_continue(IrArena* arena, MergeContinue mc) { - // TODO check it - return noret_type(arena); -} - -const Type* check_type_merge_break(IrArena* arena, MergeBreak mc) { - // TODO check it - return noret_type(arena); -} - -const Type* check_type_merge_selection(IrArena* arena, SHADY_UNUSED MergeSelection payload) { - // TODO check it - return noret_type(arena); -} - -const Type* check_type_fn_ret(IrArena* arena, Return ret) { - // assert(ret.fn); - // TODO check it then ! - return noret_type(arena); -} - -const Type* check_type_fun(IrArena* arena, Function fn) { - for (size_t i = 0; i < fn.return_types.count; i++) { - assert(is_value_type(fn.return_types.nodes[i])); - } - return fn_type(arena, (FnType) { .param_types = get_param_types(arena, (&fn)->params), .return_types = (&fn)->return_types }); -} - -const Type* check_type_basic_block(IrArena* arena, BasicBlock bb) { - return bb_type(arena, (BBType) { .param_types = get_param_types(arena, (&bb)->params) }); -} - -const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_variable) { - assert(is_type(global_variable.type)); - - const Node* ba = shd_lookup_annotation_list(global_variable.annotations, "Builtin"); - if (ba && arena->config.validate_builtin_types) { - Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); - assert(b != BuiltinsCount); - const Type* t = shd_get_builtin_type(arena, b); - if (t != global_variable.type) { - shd_error_print("Creating a @Builtin global variable '%s' with the incorrect type: ", global_variable.name); - shd_log_node(ERROR, global_variable.type); - shd_error_print(" instead of the expected "); - shd_log_node(ERROR, t); - shd_error_print(".\n"); - shd_error_die(); - } - } - - assert(global_variable.address_space < NumAddressSpaces); - - return ptr_type(arena, (PtrType) { - .pointed_type = global_variable.type, - .address_space = global_variable.address_space, - .is_reference = shd_lookup_annotation_list(global_variable.annotations, "Logical"), - }); -} - -const Type* check_type_constant(IrArena* arena, Constant cnst) { - assert(is_data_type(cnst.type_hint)); - return cnst.type_hint; -} - -#include "type_generated.c" - -#pragma GCC diagnostic pop diff --git a/src/shady/type.h b/src/shady/type.h deleted file mode 100644 index 31303b734..000000000 --- a/src/shady/type.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SHADY_TYPE_H -#define SHADY_TYPE_H - -#include "shady/ir.h" - -bool is_subtype(const Type* supertype, const Type* type); -void check_subtype(const Type* supertype, const Type* type); - -bool is_arithm_type(const Type*); -bool is_shiftable_type(const Type*); -bool has_boolean_ops(const Type*); -bool is_comparable_type(const Type*); -bool is_ordered_type(const Type*); -bool is_physical_ptr_type(const Type* t); -bool is_generic_ptr_type(const Type* t); - -bool is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type); -bool is_conversion_legal(const Type* src_type, const Type* dst_type); - -#include "type_generated.h" - -const Type* get_actual_mask_type(IrArena* arena); - -#endif diff --git a/test/test_builder.c b/test/test_builder.c index 53e71ef9e..c25dabef0 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -6,7 +6,6 @@ #include "../shady/analysis/cfg.h" #include "log.h" -#include "type.h" #include #include From 472d2cbe19e1bbcfa62d082b0e96da0e711bb201 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 21:52:23 +0200 Subject: [PATCH 638/693] body_builder: move struct layout away from ir_private.h --- src/frontend/slim/parser.c | 4 +- src/shady/body_builder.c | 31 +++++++++++--- src/shady/ir/function.c | 62 +++++++++++++++++++++++++++ src/shady/ir_private.h | 18 +++----- src/shady/node.c | 64 ---------------------------- src/shady/passes/lower_int64.c | 16 +++---- src/shady/passes/lower_workgroups.c | 5 +-- src/shady/transform/ir_gen_helpers.c | 58 ++++++++++++------------- 8 files changed, 136 insertions(+), 122 deletions(-) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 36ca41c7f..abcb00d78 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -858,13 +858,13 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); - gen_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(bb->arena), shd_nodes_prepend(bb->arena, strings2nodes(bb->arena, ids), instruction)); + gen_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(arena), shd_nodes_prepend(arena, strings2nodes(arena, ids), instruction)); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); - gen_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(bb->arena), shd_nodes_prepend(bb->arena, shd_concat_nodes(bb->arena, strings2nodes(bb->arena, ids), types), instruction)); + gen_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(arena), shd_nodes_prepend(arena, shd_concat_nodes(arena, strings2nodes(arena, ids), types), instruction)); } else { const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 4fd5cdc87..67bfcc920 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -1,4 +1,4 @@ -#include "ir_private.h" +#include "shady/body_builder.h" #include "transform/ir_gen_helpers.h" @@ -12,6 +12,15 @@ #pragma GCC diagnostic error "-Wswitch" +struct BodyBuilder_ { + IrArena* arena; + struct List* stack; + const Node* block_entry_block; + const Node* block_entry_mem; + const Node* mem; + Node* tail_block; +}; + typedef struct { Structured_constructTag tag; union NodesUnion payload; @@ -46,6 +55,18 @@ BodyBuilder* begin_block_pure(IrArena* a) { return builder; } +IrArena* _shd_get_bb_arena(BodyBuilder* bb) { + return bb->arena; +} + +const Node* _shd_bb_insert_mem(BodyBuilder* bb) { + return bb->block_entry_mem; +} + +const Node* _shd_bb_insert_block(BodyBuilder* bb) { + return bb->block_entry_block; +} + const Node* bb_mem(BodyBuilder* bb) { return bb->mem; } @@ -63,7 +84,7 @@ Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size } static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { - if (bb->arena->config.check_types) { + if (shd_get_arena_config(bb->arena)->check_types) { assert(is_mem(instruction)); } if (is_mem(instruction) && /* avoid things like ExtInstr with null mem input! */ shd_get_parent_mem(instruction)) @@ -72,7 +93,7 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp } Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { - assert(bb->arena->config.check_types); + assert(shd_get_arena_config(bb->arena)->check_types); return bind_internal(bb, instruction, shd_singleton(instruction->type).count); } @@ -81,7 +102,7 @@ const Node* bind_instruction_single(BodyBuilder* bb, const Node* instr) { } Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String const output_names[]) { - assert(bb->arena->config.check_types); + assert(shd_get_arena_config(bb->arena)->check_types); assert(output_names); return bind_internal(bb, instruction, shd_singleton(instruction->type).count); } @@ -203,7 +224,7 @@ const Node* yield_values_and_wrap_in_block(BodyBuilder* bb, Nodes values) { return yield_value_and_wrap_in_block(bb, maybe_tuple_helper(bb->arena, values)); } -const Node* finish_block_body(BodyBuilder* bb, const Node* terminator) { +const Node* _shd_finish_block_body(BodyBuilder* bb, const Node* terminator) { assert(bb->block_entry_mem); terminator = build_body(bb, terminator); shd_destroy_list(bb->stack); diff --git a/src/shady/ir/function.c b/src/shady/ir/function.c index 4e708859c..4bd540a5b 100644 --- a/src/shady/ir/function.c +++ b/src/shady/ir/function.c @@ -79,4 +79,66 @@ Node* basic_block(IrArena* arena, Nodes params, const char* name) { } return bb; +} + +const Node* shd_get_abstraction_mem(const Node* abs) { + return abs_mem(abs->arena, (AbsMem) { .abs = abs }); +} + +String shd_get_abstraction_name(const Node* abs) { + assert(is_abstraction(abs)); + switch (abs->tag) { + case Function_TAG: return abs->payload.fun.name; + case BasicBlock_TAG: return abs->payload.basic_block.name; + default: assert(false); + } +} + +String shd_get_abstraction_name_unsafe(const Node* abs) { + assert(is_abstraction(abs)); + switch (abs->tag) { + case Function_TAG: return abs->payload.fun.name; + case BasicBlock_TAG: return abs->payload.basic_block.name; + default: assert(false); + } +} + +String shd_get_abstraction_name_safe(const Node* abs) { + String name = shd_get_abstraction_name_unsafe(abs); + if (name) + return name; + return shd_fmt_string_irarena(abs->arena, "%%%d", abs->id); +} + +void shd_set_abstraction_body(Node* abs, const Node* body) { + assert(is_abstraction(abs)); + assert(!body || is_terminator(body)); + IrArena* a = abs->arena; + + if (body) { + while (true) { + const Node* mem0 = shd_get_original_mem(get_terminator_mem(body)); + assert(mem0->tag == AbsMem_TAG); + Node* mem_abs = mem0->payload.abs_mem.abs; + if (is_basic_block(mem_abs)) { + BodyBuilder* insert = mem_abs->payload.basic_block.insert; + if (insert && mem_abs != abs) { + const Node* mem = _shd_bb_insert_mem(insert); + const Node* block = _shd_bb_insert_block(insert); + shd_set_abstraction_body((Node*) block, _shd_finish_block_body(insert, body)); + body = jump_helper(a, mem, block, shd_empty(a)); + // mem_abs->payload.basic_block.insert = NULL; + continue; + } + } + assert(mem_abs == abs); + break; + } + } + + switch (abs->tag) { + case Function_TAG: abs->payload.fun.body = body; break; + case BasicBlock_TAG: abs->payload.basic_block.body = body; break; + default: assert(false); + } } \ No newline at end of file diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index 3e4776b99..a9fc73ac9 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -10,7 +10,7 @@ #include "stdlib.h" #include "stdio.h" -typedef struct IrArena_ { +struct IrArena_ { Arena* arena; ArenaConfig config; @@ -22,7 +22,7 @@ typedef struct IrArena_ { struct Dict* nodes_set; struct Dict* strings_set; -} IrArena_; +}; struct Module_ { IrArena* arena; @@ -34,17 +34,13 @@ struct Module_ { void _shd_module_add_decl(Module* m, Node* node); void shd_destroy_module(Module* m); -struct BodyBuilder_ { - IrArena* arena; - struct List* stack; - const Node* block_entry_block; - const Node* block_entry_mem; - const Node* mem; - Node* tail_block; -}; - NodeId _shd_allocate_node_id(IrArena* arena, const Node* n); +IrArena* _shd_get_bb_arena(BodyBuilder* bb); +const Node* _shd_bb_insert_mem(BodyBuilder* bb); +const Node* _shd_bb_insert_block(BodyBuilder* bb); +const Node* _shd_finish_block_body(BodyBuilder* bb, const Node* terminator); + struct List; Nodes shd_list_to_nodes(IrArena* arena, struct List* list); diff --git a/src/shady/node.c b/src/shady/node.c index 8bb86d87b..fb4840c61 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -204,70 +204,6 @@ const char* shd_get_string_literal(IrArena* arena, const Node* node) { return NULL; } -const Node* shd_get_abstraction_mem(const Node* abs) { - return abs_mem(abs->arena, (AbsMem) { .abs = abs }); -} - -String shd_get_abstraction_name(const Node* abs) { - assert(is_abstraction(abs)); - switch (abs->tag) { - case Function_TAG: return abs->payload.fun.name; - case BasicBlock_TAG: return abs->payload.basic_block.name; - default: assert(false); - } -} - -String shd_get_abstraction_name_unsafe(const Node* abs) { - assert(is_abstraction(abs)); - switch (abs->tag) { - case Function_TAG: return abs->payload.fun.name; - case BasicBlock_TAG: return abs->payload.basic_block.name; - default: assert(false); - } -} - -String shd_get_abstraction_name_safe(const Node* abs) { - String name = shd_get_abstraction_name_unsafe(abs); - if (name) - return name; - return shd_fmt_string_irarena(abs->arena, "%%%d", abs->id); -} - -const Node* finish_block_body(BodyBuilder* bb, const Node* terminator); - -void shd_set_abstraction_body(Node* abs, const Node* body) { - assert(is_abstraction(abs)); - assert(!body || is_terminator(body)); - IrArena* a = abs->arena; - - if (body) { - while (true) { - const Node* mem0 = shd_get_original_mem(get_terminator_mem(body)); - assert(mem0->tag == AbsMem_TAG); - Node* mem_abs = mem0->payload.abs_mem.abs; - if (is_basic_block(mem_abs)) { - BodyBuilder* insert = mem_abs->payload.basic_block.insert; - if (insert && mem_abs != abs) { - const Node* mem = insert->block_entry_mem; - const Node* block = insert->block_entry_block; - shd_set_abstraction_body((Node*) block, finish_block_body(insert, body)); - body = jump_helper(a, mem, block, shd_empty(a)); - // mem_abs->payload.basic_block.insert = NULL; - continue; - } - } - assert(mem_abs == abs); - break; - } - } - - switch (abs->tag) { - case Function_TAG: abs->payload.fun.body = body; break; - case BasicBlock_TAG: abs->payload.basic_block.body = body; break; - default: assert(false); - } -} - const char* node_tags[]; const char* shd_get_node_tag_string(NodeTag tag) { diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 5ca3ba664..decae7bfc 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -16,16 +16,16 @@ static bool should_convert(Context* ctx, const Type* t) { return t->tag == Int_TAG && t->payload.int_type.width == IntTy64 && ctx->config->lower.int64; } -static void extract_low_hi_halves(BodyBuilder* bb, const Node* src, const Node** lo, const Node** hi) { - *lo = shd_first(bind_instruction(bb, prim_op(bb->arena, - (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, shd_int32_literal(bb->arena, 0)) }))); - *hi = shd_first(bind_instruction(bb, prim_op(bb->arena, - (PrimOp) { .op = extract_op, .operands = mk_nodes(bb->arena, src, shd_int32_literal(bb->arena, 1)) }))); +static void extract_low_hi_halves(IrArena* a, BodyBuilder* bb, const Node* src, const Node** lo, const Node** hi) { + *lo = shd_first(bind_instruction(bb, prim_op(a, + (PrimOp) { .op = extract_op, .operands = mk_nodes(a, src, shd_int32_literal(a, 0)) }))); + *hi = shd_first(bind_instruction(bb, prim_op(a, + (PrimOp) { .op = extract_op, .operands = mk_nodes(a, src, shd_int32_literal(a, 1)) }))); } -static void extract_low_hi_halves_list(BodyBuilder* bb, Nodes src, const Node** lows, const Node** his) { +static void extract_low_hi_halves_list(IrArena* a, BodyBuilder* bb, Nodes src, const Node** lows, const Node** his) { for (size_t i = 0; i < src.count; i++) { - extract_low_hi_halves(bb, src.nodes[i], lows, his); + extract_low_hi_halves(a, bb, src.nodes[i], lows, his); lows++; his++; } @@ -59,7 +59,7 @@ static const Node* process(Context* ctx, const Node* node) { Nodes new_nodes = shd_rewrite_nodes(&ctx->rewriter, old_nodes); // TODO: convert into and then out of unsigned BodyBuilder* bb = begin_block_pure(a); - extract_low_hi_halves_list(bb, new_nodes, lows, his); + extract_low_hi_halves_list(a, bb, new_nodes, lows, his); Nodes low_and_carry = bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_carry_op, .operands = shd_nodes(a, 2, lows)})); const Node* lo = shd_first(low_and_carry); // compute the high side, without forgetting the carry bit diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 75e8575a0..a5ad2dede 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -16,8 +16,7 @@ typedef struct { bool is_entry_point; } Context; -static void add_bounds_check(BodyBuilder* bb, const Node* i, const Node* max) { - IrArena* a = bb->arena; +static void add_bounds_check(IrArena* a, BodyBuilder* bb, const Node* i, const Node* max) { Node* out_of_bounds_case = case_(a, shd_empty(a)); shd_set_abstraction_body(out_of_bounds_case, merge_break(a, (MergeBreak) { .args = shd_empty(a), @@ -119,7 +118,7 @@ static const Node* process(Context* ctx, const Node* node) { cases[scope * 3 + dim] = loop_body; BodyBuilder* loop_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_body)); builders[scope * 3 + dim] = loop_bb; - add_bounds_check(loop_bb, params[dim], maxes[dim]); + add_bounds_check(a, loop_bb, params[dim], maxes[dim]); } } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 1a3838493..9014368bf 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -28,19 +28,19 @@ const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes in } Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { - assert(bb->arena->config.check_types); - const Node* instruction = call(bb->arena, (Call) { .callee = callee, .args = args, .mem = bb_mem(bb) }); + assert(shd_get_arena_config(_shd_get_bb_arena(bb))->check_types); + const Node* instruction = call(_shd_get_bb_arena(bb), (Call) { .callee = callee, .args = args, .mem = bb_mem(bb) }); return bind_instruction(bb, instruction); } Nodes gen_primop(BodyBuilder* bb, Op op, Nodes type_args, Nodes operands) { - assert(bb->arena->config.check_types); - const Node* instruction = prim_op(bb->arena, (PrimOp) { .op = op, .type_arguments = type_args, .operands = operands }); + assert(shd_get_arena_config(_shd_get_bb_arena(bb))->check_types); + const Node* instruction = prim_op(_shd_get_bb_arena(bb), (PrimOp) { .op = op, .type_arguments = type_args, .operands = operands }); return shd_singleton(instruction); } Nodes gen_primop_c(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { - return gen_primop(bb, op, shd_empty(bb->arena), shd_nodes(bb->arena, operands_count, operands)); + return gen_primop(bb, op, shd_empty(_shd_get_bb_arena(bb)), shd_nodes(_shd_get_bb_arena(bb), operands_count, operands)); } const Node* gen_primop_ce(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { @@ -55,7 +55,7 @@ const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { } const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { - return bind_instruction_single(bb, ext_instr(bb->arena, (ExtInstr) { + return bind_instruction_single(bb, ext_instr(_shd_get_bb_arena(bb), (ExtInstr) { .mem = bb_mem(bb), .set = set, .opcode = opcode, @@ -65,7 +65,7 @@ const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const T } void gen_push_value_stack(BodyBuilder* bb, const Node* value) { - bind_instruction(bb, push_stack(bb->arena, (PushStack) { .value = value, .mem = bb_mem(bb) })); + bind_instruction(bb, push_stack(_shd_get_bb_arena(bb), (PushStack) { .value = value, .mem = bb_mem(bb) })); } void gen_push_values_stack(BodyBuilder* bb, Nodes values) { @@ -76,30 +76,30 @@ void gen_push_values_stack(BodyBuilder* bb, Nodes values) { } const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { - const Node* instruction = pop_stack(bb->arena, (PopStack) { .type = type, .mem = bb_mem(bb) }); + const Node* instruction = pop_stack(_shd_get_bb_arena(bb), (PopStack) { .type = type, .mem = bb_mem(bb) }); return shd_first(bind_instruction(bb, instruction)); } const Node* gen_get_stack_base_addr(BodyBuilder* bb) { - return get_stack_base_addr(bb->arena, (GetStackBaseAddr) { .mem = bb_mem(bb) }); + return get_stack_base_addr(_shd_get_bb_arena(bb), (GetStackBaseAddr) { .mem = bb_mem(bb) }); } const Node* gen_get_stack_size(BodyBuilder* bb) { - return shd_first(bind_instruction(bb, get_stack_size(bb->arena, (GetStackSize) { .mem = bb_mem(bb) }))); + return shd_first(bind_instruction(bb, get_stack_size(_shd_get_bb_arena(bb), (GetStackSize) { .mem = bb_mem(bb) }))); } void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { - bind_instruction(bb, set_stack_size(bb->arena, (SetStackSize) { .value = new_size, .mem = bb_mem(bb) })); + bind_instruction(bb, set_stack_size(_shd_get_bb_arena(bb), (SetStackSize) { .value = new_size, .mem = bb_mem(bb) })); } const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); - return prim_op(bb->arena, (PrimOp) { .op = reinterpret_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); + return prim_op(_shd_get_bb_arena(bb), (PrimOp) { .op = reinterpret_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); } const Node* gen_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); - return prim_op(bb->arena, (PrimOp) { .op = convert_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); + return prim_op(_shd_get_bb_arena(bb), (PrimOp) { .op = convert_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); } const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { @@ -108,23 +108,23 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { assert(src_type->tag == Int_TAG); IntSizes size = src_type->payload.int_type.width; assert(size != IntSizeMax); - const Type* dst_type = int_type(bb->arena, (Int) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed }); + const Type* dst_type = int_type(_shd_get_bb_arena(bb), (Int) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed }); // widen them lo = gen_conversion(bb, dst_type, lo); hi = gen_conversion(bb, dst_type, hi); // shift hi - const Node* shift_by = int_literal(bb->arena, (IntLiteral) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed, .value = shd_get_type_bitwidth(src_type) }); + const Node* shift_by = int_literal(_shd_get_bb_arena(bb), (IntLiteral) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed, .value = shd_get_type_bitwidth(src_type) }); hi = gen_primop_ce(bb, lshift_op, 2, (const Node* []) { hi, shift_by}); // Merge the two return gen_primop_ce(bb, or_op, 2, (const Node* []) { lo, hi }); } const Node* gen_stack_alloc(BodyBuilder* bb, const Type* type) { - return shd_first(bind_instruction(bb, stack_alloc(bb->arena, (StackAlloc) { .type = type, .mem = bb_mem(bb) }))); + return shd_first(bind_instruction(bb, stack_alloc(_shd_get_bb_arena(bb), (StackAlloc) { .type = type, .mem = bb_mem(bb) }))); } const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { - return shd_first(bind_instruction(bb, local_alloc(bb->arena, (LocalAlloc) { .type = type, .mem = bb_mem(bb) }))); + return shd_first(bind_instruction(bb, local_alloc(_shd_get_bb_arena(bb), (LocalAlloc) { .type = type, .mem = bb_mem(bb) }))); } const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Node* index) { @@ -132,15 +132,15 @@ const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Nod } const Node* gen_load(BodyBuilder* bb, const Node* ptr) { - return shd_first(bind_instruction(bb, load(bb->arena, (Load) { .ptr = ptr, .mem = bb_mem(bb) }))); + return shd_first(bind_instruction(bb, load(_shd_get_bb_arena(bb), (Load) { .ptr = ptr, .mem = bb_mem(bb) }))); } void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { - bind_instruction(bb, store(bb->arena, (Store) { .ptr = ptr, .value = value, .mem = bb_mem(bb) })); + bind_instruction(bb, store(_shd_get_bb_arena(bb), (Store) { .ptr = ptr, .value = value, .mem = bb_mem(bb) })); } const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { - return lea_helper(bb->arena, base, offset, selectors); + return lea_helper(_shd_get_bb_arena(bb), base, offset, selectors); } const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { @@ -152,11 +152,11 @@ const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { } void gen_comment(BodyBuilder* bb, String str) { - bind_instruction(bb, comment(bb->arena, (Comment) { .string = str, .mem = bb_mem(bb) })); + bind_instruction(bb, comment(_shd_get_bb_arena(bb), (Comment) { .string = str, .mem = bb_mem(bb) })); } void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { - bind_instruction_single(bb, debug_printf(bb->arena, (DebugPrintf) { .string = pattern, .args = args, .mem = bb_mem(bb) })); + bind_instruction_single(bb, debug_printf(_shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = bb_mem(bb) })); } const Node* get_builtin(Module* m, Builtin b) { @@ -193,7 +193,7 @@ const Node* get_or_create_builtin(Module* m, Builtin b, String n) { } const Node* gen_builtin_load(Module* m, BodyBuilder* bb, Builtin b) { - return gen_load(bb, ref_decl_helper(bb->arena, get_or_create_builtin(m, b, NULL))); + return gen_load(bb, ref_decl_helper(_shd_get_bb_arena(bb), get_or_create_builtin(m, b, NULL))); } bool is_builtin_load_op(const Node* n, Builtin* out) { @@ -243,7 +243,7 @@ const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* d assert(dst_type->tag == Int_TAG); // first convert to final bitsize then bitcast - const Type* extended_src_t = int_type(bb->arena, (Int) { .width = dst_type->payload.int_type.width, .is_signed = src_type->payload.int_type.is_signed }); + const Type* extended_src_t = int_type(_shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = src_type->payload.int_type.is_signed }); const Node* val = src; val = gen_primop_e(bb, convert_op, shd_singleton(extended_src_t), shd_singleton(val)); val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); @@ -256,7 +256,7 @@ const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* d assert(dst_type->tag == Int_TAG); // first bitcast then convert to final bitsize - const Type* reinterpreted_src_t = int_type(bb->arena, (Int) { .width = src_type->payload.int_type.width, .is_signed = dst_type->payload.int_type.is_signed }); + const Type* reinterpreted_src_t = int_type(_shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = dst_type->payload.int_type.is_signed }); const Node* val = src; val = gen_primop_e(bb, reinterpret_op, shd_singleton(reinterpreted_src_t), shd_singleton(val)); val = gen_primop_e(bb, convert_op, shd_singleton(dst_type), shd_singleton(val)); @@ -270,9 +270,9 @@ const Node* convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const const Node* val = src; val = gen_primop_e(bb, reinterpret_op, shd_singleton( - int_type(bb->arena, (Int) { .width = src_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); + int_type(_shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); val = gen_primop_e(bb, convert_op, shd_singleton( - int_type(bb->arena, (Int) { .width = dst_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); + int_type(_shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } @@ -284,9 +284,9 @@ const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, cons const Node* val = src; val = gen_primop_e(bb, reinterpret_op, shd_singleton( - int_type(bb->arena, (Int) { .width = src_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); + int_type(_shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); val = gen_primop_e(bb, convert_op, shd_singleton( - int_type(bb->arena, (Int) { .width = dst_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); + int_type(_shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } From f50c332b53cc08bbc0545eb21c511a0665804d4a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 7 Oct 2024 21:56:56 +0200 Subject: [PATCH 639/693] added literal.c and debug.c --- include/shady/analysis/literal.h | 2 +- include/shady/ir/debug.h | 2 +- src/shady/analysis/CMakeLists.txt | 1 + src/shady/analysis/literal.c | 183 +++++++++++++++++++++++++++ src/shady/ir/CMakeLists.txt | 1 + src/shady/ir/debug.c | 26 ++++ src/shady/node.c | 200 ------------------------------ 7 files changed, 213 insertions(+), 202 deletions(-) create mode 100644 src/shady/analysis/literal.c create mode 100644 src/shady/ir/debug.c diff --git a/include/shady/analysis/literal.h b/include/shady/analysis/literal.h index 31a1494fe..9125d4504 100644 --- a/include/shady/analysis/literal.h +++ b/include/shady/analysis/literal.h @@ -1,7 +1,7 @@ #ifndef SHADY_ANALYSIS_LITERAL_H #define SHADY_ANALYSIS_LITERAL_H -#include "shady/ir/base.h" +#include "shady/ir/grammar.h" const char* shd_get_string_literal(IrArena* arena, const Node* node); diff --git a/include/shady/ir/debug.h b/include/shady/ir/debug.h index ee3659249..631619e5f 100644 --- a/include/shady/ir/debug.h +++ b/include/shady/ir/debug.h @@ -1,7 +1,7 @@ #ifndef SHADY_IR_DEBUG_H #define SHADY_IR_DEBUG_H -#include "shady/ir/base.h" +#include "shady/ir/grammar.h" /// Get the name out of a global variable, function or constant String shd_get_value_name_safe(const Node* v); diff --git a/src/shady/analysis/CMakeLists.txt b/src/shady/analysis/CMakeLists.txt index a92e52075..778f0f643 100644 --- a/src/shady/analysis/CMakeLists.txt +++ b/src/shady/analysis/CMakeLists.txt @@ -8,4 +8,5 @@ target_sources(shady PRIVATE looptree.c leak.c scheduler.c + literal.c ) diff --git a/src/shady/analysis/literal.c b/src/shady/analysis/literal.c new file mode 100644 index 000000000..721cba876 --- /dev/null +++ b/src/shady/analysis/literal.c @@ -0,0 +1,183 @@ +#include "shady/analysis/literal.h" + +#include "shady/ir/int.h" +#include "shady/ir/type.h" + +#include "portability.h" + +#include + +static bool is_zero(const Node* node) { + const IntLiteral* lit = shd_resolve_to_int_literal(node); + if (lit && shd_get_int_literal_value(*lit, false) == 0) + return true; + return false; +} + +const Node* shd_chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { + while (true) { + ptr = shd_resolve_node_to_definition(ptr, config); + switch (ptr->tag) { + case PtrArrayElementOffset_TAG: break; + case PtrCompositeElement_TAG: { + PtrCompositeElement payload = ptr->payload.ptr_composite_element; + if (!is_zero(payload.index)) + break; + ptr = payload.ptr; + continue; + } + case PrimOp_TAG: { + switch (ptr->payload.prim_op.op) { + case convert_op: { + // chase generic pointers to their source + if (shd_first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { + ptr = shd_first(ptr->payload.prim_op.operands); + continue; + } + break; + } + case reinterpret_op: { + // chase ptr casts to their source + // TODO: figure out round-trips through integer casts? + if (shd_first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { + ptr = shd_first(ptr->payload.prim_op.operands); + continue; + } + break; + } + default: break; + } + break; + } + default: break; + } + break; + } + return ptr; +} + +const Node* shd_resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config) { + while (ptr) { + ptr = shd_resolve_node_to_definition(ptr, config); + switch (ptr->tag) { + case PrimOp_TAG: { + switch (ptr->payload.prim_op.op) { + case convert_op: { // allow address space conversions + ptr = shd_first(ptr->payload.prim_op.operands); + continue; + } + default: break; + } + } + case GlobalVariable_TAG: + if (config.assume_globals_immutability) + return ptr->payload.global_variable.init; + break; + default: break; + } + ptr = NULL; + } + return NULL; +} + +NodeResolveConfig shd_default_node_resolve_config(void) { + return (NodeResolveConfig) { + .enter_loads = true, + .allow_incompatible_types = false, + .assume_globals_immutability = false, + }; +} + +const Node* shd_resolve_node_to_definition(const Node* node, NodeResolveConfig config) { + while (node) { + switch (node->tag) { + case Constant_TAG: + node = node->payload.constant.value; + continue; + case RefDecl_TAG: + node = node->payload.ref_decl.decl; + continue; + case Load_TAG: { + if (config.enter_loads) { + const Node* source = node->payload.load.ptr; + const Node* result = shd_resolve_ptr_to_value(source, config); + if (!result) + break; + node = result; + continue; + } + } + case PrimOp_TAG: { + switch (node->payload.prim_op.op) { + case convert_op: + case reinterpret_op: { + if (config.allow_incompatible_types) { + node = shd_first(node->payload.prim_op.operands); + continue; + } + } + default: break; + } + break; + } + default: break; + } + break; + } + return node; +} + +const char* shd_get_string_literal(IrArena* arena, const Node* node) { + if (!node) + return NULL; + if (node->type && get_unqualified_type(node->type)->tag == PtrType_TAG) { + NodeResolveConfig nrc = shd_default_node_resolve_config(); + const Node* ptr = shd_chase_ptr_to_source(node, nrc); + const Node* value = shd_resolve_ptr_to_value(ptr, nrc); + if (value) + return shd_get_string_literal(arena, value); + } + switch (node->tag) { + case Declaration_GlobalVariable_TAG: { + const Node* init = node->payload.global_variable.init; + if (init) { + return shd_get_string_literal(arena, init); + } + break; + } + case Declaration_Constant_TAG: { + return shd_get_string_literal(arena, node->payload.constant.value); + } + case RefDecl_TAG: { + const Node* decl = node->payload.ref_decl.decl; + return shd_get_string_literal(arena, decl); + } + /*case Lea_TAG: { + Lea lea = node->payload.lea; + if (lea.indices.count == 3 && is_zero(lea.offset) && is_zero(first(lea.indices))) { + const Node* ref = lea.ptr; + if (ref->tag != RefDecl_TAG) + return NULL; + const Node* decl = ref->payload.ref_decl.decl; + if (decl->tag != GlobalVariable_TAG || !decl->payload.global_variable.init) + return NULL; + return get_string_literal(arena, decl->payload.global_variable.init); + } + break; + }*/ + case StringLiteral_TAG: return node->payload.string_lit.string; + case Composite_TAG: { + Nodes contents = node->payload.composite.contents; + LARRAY(char, chars, contents.count); + for (size_t i = 0; i < contents.count; i++) { + const Node* value = contents.nodes[i]; + assert(value->tag == IntLiteral_TAG && value->payload.int_literal.width == IntTy8); + chars[i] = (unsigned char) shd_get_int_literal_value(*shd_resolve_to_int_literal(value), false); + } + assert(chars[contents.count - 1] == 0); + return string(arena, chars); + } + default: break; + } + return NULL; +} diff --git a/src/shady/ir/CMakeLists.txt b/src/shady/ir/CMakeLists.txt index 7a872d210..9afdaf292 100644 --- a/src/shady/ir/CMakeLists.txt +++ b/src/shady/ir/CMakeLists.txt @@ -10,4 +10,5 @@ target_sources(shady PRIVATE builtin.c type.c grammar.c + debug.c ) \ No newline at end of file diff --git a/src/shady/ir/debug.c b/src/shady/ir/debug.c new file mode 100644 index 000000000..b92747a27 --- /dev/null +++ b/src/shady/ir/debug.c @@ -0,0 +1,26 @@ +#include "shady/ir/debug.h" + +#include +#include + +String shd_get_value_name_unsafe(const Node* v) { + assert(v && is_value(v)); + if (v->tag == Param_TAG) + return v->payload.param.name; + return NULL; +} + +String shd_get_value_name_safe(const Node* v) { + String name = shd_get_value_name_unsafe(v); + if (name && strlen(name) > 0) + return name; + //if (v->tag == Variable_TAG) + return shd_fmt_string_irarena(v->arena, "%%%d", v->id); + //return node_tags[v->tag]; +} + +void shd_set_value_name(const Node* var, String name) { + // TODO: annotations + // if (var->tag == Variablez_TAG) + // var->payload.varz.name = string(var->arena, name); +} diff --git a/src/shady/node.c b/src/shady/node.c index fb4840c61..92b276743 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -4,206 +4,6 @@ #include "portability.h" #include "dict.h" -#include -#include - -String shd_get_value_name_unsafe(const Node* v) { - assert(v && is_value(v)); - if (v->tag == Param_TAG) - return v->payload.param.name; - return NULL; -} - -String shd_get_value_name_safe(const Node* v) { - String name = shd_get_value_name_unsafe(v); - if (name && strlen(name) > 0) - return name; - //if (v->tag == Variable_TAG) - return shd_fmt_string_irarena(v->arena, "%%%d", v->id); - //return node_tags[v->tag]; -} - -void shd_set_value_name(const Node* var, String name) { - // TODO: annotations - // if (var->tag == Variablez_TAG) - // var->payload.varz.name = string(var->arena, name); -} - -static bool is_zero(const Node* node) { - const IntLiteral* lit = shd_resolve_to_int_literal(node); - if (lit && shd_get_int_literal_value(*lit, false) == 0) - return true; - return false; -} - -const Node* shd_chase_ptr_to_source(const Node* ptr, NodeResolveConfig config) { - while (true) { - ptr = shd_resolve_node_to_definition(ptr, config); - switch (ptr->tag) { - case PtrArrayElementOffset_TAG: break; - case PtrCompositeElement_TAG: { - PtrCompositeElement payload = ptr->payload.ptr_composite_element; - if (!is_zero(payload.index)) - break; - ptr = payload.ptr; - continue; - } - case PrimOp_TAG: { - switch (ptr->payload.prim_op.op) { - case convert_op: { - // chase generic pointers to their source - if (shd_first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { - ptr = shd_first(ptr->payload.prim_op.operands); - continue; - } - break; - } - case reinterpret_op: { - // chase ptr casts to their source - // TODO: figure out round-trips through integer casts? - if (shd_first(ptr->payload.prim_op.type_arguments)->tag == PtrType_TAG) { - ptr = shd_first(ptr->payload.prim_op.operands); - continue; - } - break; - } - default: break; - } - break; - } - default: break; - } - break; - } - return ptr; -} - -const Node* shd_resolve_ptr_to_value(const Node* ptr, NodeResolveConfig config) { - while (ptr) { - ptr = shd_resolve_node_to_definition(ptr, config); - switch (ptr->tag) { - case PrimOp_TAG: { - switch (ptr->payload.prim_op.op) { - case convert_op: { // allow address space conversions - ptr = shd_first(ptr->payload.prim_op.operands); - continue; - } - default: break; - } - } - case GlobalVariable_TAG: - if (config.assume_globals_immutability) - return ptr->payload.global_variable.init; - break; - default: break; - } - ptr = NULL; - } - return NULL; -} - -NodeResolveConfig shd_default_node_resolve_config(void) { - return (NodeResolveConfig) { - .enter_loads = true, - .allow_incompatible_types = false, - .assume_globals_immutability = false, - }; -} - -const Node* shd_resolve_node_to_definition(const Node* node, NodeResolveConfig config) { - while (node) { - switch (node->tag) { - case Constant_TAG: - node = node->payload.constant.value; - continue; - case RefDecl_TAG: - node = node->payload.ref_decl.decl; - continue; - case Load_TAG: { - if (config.enter_loads) { - const Node* source = node->payload.load.ptr; - const Node* result = shd_resolve_ptr_to_value(source, config); - if (!result) - break; - node = result; - continue; - } - } - case PrimOp_TAG: { - switch (node->payload.prim_op.op) { - case convert_op: - case reinterpret_op: { - if (config.allow_incompatible_types) { - node = shd_first(node->payload.prim_op.operands); - continue; - } - } - default: break; - } - break; - } - default: break; - } - break; - } - return node; -} - -const char* shd_get_string_literal(IrArena* arena, const Node* node) { - if (!node) - return NULL; - if (node->type && get_unqualified_type(node->type)->tag == PtrType_TAG) { - NodeResolveConfig nrc = shd_default_node_resolve_config(); - const Node* ptr = shd_chase_ptr_to_source(node, nrc); - const Node* value = shd_resolve_ptr_to_value(ptr, nrc); - if (value) - return shd_get_string_literal(arena, value); - } - switch (node->tag) { - case Declaration_GlobalVariable_TAG: { - const Node* init = node->payload.global_variable.init; - if (init) { - return shd_get_string_literal(arena, init); - } - break; - } - case Declaration_Constant_TAG: { - return shd_get_string_literal(arena, node->payload.constant.value); - } - case RefDecl_TAG: { - const Node* decl = node->payload.ref_decl.decl; - return shd_get_string_literal(arena, decl); - } - /*case Lea_TAG: { - Lea lea = node->payload.lea; - if (lea.indices.count == 3 && is_zero(lea.offset) && is_zero(first(lea.indices))) { - const Node* ref = lea.ptr; - if (ref->tag != RefDecl_TAG) - return NULL; - const Node* decl = ref->payload.ref_decl.decl; - if (decl->tag != GlobalVariable_TAG || !decl->payload.global_variable.init) - return NULL; - return get_string_literal(arena, decl->payload.global_variable.init); - } - break; - }*/ - case StringLiteral_TAG: return node->payload.string_lit.string; - case Composite_TAG: { - Nodes contents = node->payload.composite.contents; - LARRAY(char, chars, contents.count); - for (size_t i = 0; i < contents.count; i++) { - const Node* value = contents.nodes[i]; - assert(value->tag == IntLiteral_TAG && value->payload.int_literal.width == IntTy8); - chars[i] = (unsigned char) shd_get_int_literal_value(*shd_resolve_to_int_literal(value), false); - } - assert(chars[contents.count - 1] == 0); - return string(arena, chars); - } - default: break; - } - return NULL; -} - const char* node_tags[]; const char* shd_get_node_tag_string(NodeTag tag) { From f7e785049bee37d237e4c4d4a0bf20e7bfcb1fe3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 9 Oct 2024 15:13:24 +0200 Subject: [PATCH 640/693] add missing check.[c, h] files --- src/shady/check.c | 1280 +++++++++++++++++++++++++++++++++++++++++++++ src/shady/check.h | 22 + 2 files changed, 1302 insertions(+) create mode 100644 src/shady/check.c create mode 100644 src/shady/check.h diff --git a/src/shady/check.c b/src/shady/check.c new file mode 100644 index 000000000..83088dfb1 --- /dev/null +++ b/src/shady/check.c @@ -0,0 +1,1280 @@ +#include "check.h" + +#include "log.h" +#include "ir_private.h" +#include "portability.h" +#include "dict.h" +#include "util.h" + +#include "shady/ir/builtin.h" + +#include +#include + +#pragma GCC diagnostic error "-Wswitch" + +static bool are_types_identical(size_t num_types, const Type* types[]) { + for (size_t i = 0; i < num_types; i++) { + assert(types[i]); + if (types[0] != types[i]) + return false; + } + return true; +} + +bool is_subtype(const Type* supertype, const Type* type) { + assert(supertype && type); + if (supertype->tag != type->tag) + return false; + if (type == supertype) + return true; + switch (is_type(supertype)) { + case NotAType: shd_error("supplied not a type to is_subtype"); + case QualifiedType_TAG: { + // uniform T <: varying T + if (supertype->payload.qualified_type.is_uniform && !type->payload.qualified_type.is_uniform) + return false; + return is_subtype(supertype->payload.qualified_type.type, type->payload.qualified_type.type); + } + case RecordType_TAG: { + const Nodes* supermembers = &supertype->payload.record_type.members; + const Nodes* members = &type->payload.record_type.members; + if (supermembers->count != members->count) + return false; + for (size_t i = 0; i < members->count; i++) { + if (!is_subtype(supermembers->nodes[i], members->nodes[i])) + return false; + } + return supertype->payload.record_type.special == type->payload.record_type.special; + } + case JoinPointType_TAG: { + const Nodes* superparams = &supertype->payload.join_point_type.yield_types; + const Nodes* params = &type->payload.join_point_type.yield_types; + if (params->count != superparams->count) return false; + for (size_t i = 0; i < params->count; i++) { + if (!is_subtype(params->nodes[i], superparams->nodes[i])) + return false; + } + return true; + } + case FnType_TAG: { + // check returns + if (supertype->payload.fn_type.return_types.count != type->payload.fn_type.return_types.count) + return false; + for (size_t i = 0; i < type->payload.fn_type.return_types.count; i++) + if (!is_subtype(supertype->payload.fn_type.return_types.nodes[i], type->payload.fn_type.return_types.nodes[i])) + return false; + // check params + const Nodes* superparams = &supertype->payload.fn_type.param_types; + const Nodes* params = &type->payload.fn_type.param_types; + if (params->count != superparams->count) return false; + for (size_t i = 0; i < params->count; i++) { + if (!is_subtype(params->nodes[i], superparams->nodes[i])) + return false; + } + return true; + } case BBType_TAG: { + // check params + const Nodes* superparams = &supertype->payload.bb_type.param_types; + const Nodes* params = &type->payload.bb_type.param_types; + if (params->count != superparams->count) return false; + for (size_t i = 0; i < params->count; i++) { + if (!is_subtype(params->nodes[i], superparams->nodes[i])) + return false; + } + return true; + } case LamType_TAG: { + // check params + const Nodes* superparams = &supertype->payload.lam_type.param_types; + const Nodes* params = &type->payload.lam_type.param_types; + if (params->count != superparams->count) return false; + for (size_t i = 0; i < params->count; i++) { + if (!is_subtype(params->nodes[i], superparams->nodes[i])) + return false; + } + return true; + } case PtrType_TAG: { + if (supertype->payload.ptr_type.address_space != type->payload.ptr_type.address_space) + return false; + if (!supertype->payload.ptr_type.is_reference && type->payload.ptr_type.is_reference) + return false; + return is_subtype(supertype->payload.ptr_type.pointed_type, type->payload.ptr_type.pointed_type); + } + case Int_TAG: return supertype->payload.int_type.width == type->payload.int_type.width && supertype->payload.int_type.is_signed == type->payload.int_type.is_signed; + case ArrType_TAG: { + if (!is_subtype(supertype->payload.arr_type.element_type, type->payload.arr_type.element_type)) + return false; + // unsized arrays are supertypes of sized arrays (even though they're not datatypes...) + // TODO: maybe change this so it's only valid when talking about to pointer-to-arrays + const IntLiteral* size_literal = shd_resolve_to_int_literal(supertype->payload.arr_type.size); + if (size_literal && size_literal->value == 0) + return true; + return supertype->payload.arr_type.size == type->payload.arr_type.size || !supertype->payload.arr_type.size; + } + case PackType_TAG: { + if (!is_subtype(supertype->payload.pack_type.element_type, type->payload.pack_type.element_type)) + return false; + return supertype->payload.pack_type.width == type->payload.pack_type.width; + } + case Type_TypeDeclRef_TAG: { + return supertype->payload.type_decl_ref.decl == type->payload.type_decl_ref.decl; + } + case Type_ImageType_TAG: { + if (!is_subtype(supertype->payload.image_type.sampled_type, type->payload.image_type.sampled_type)) + return false; + if (supertype->payload.image_type.depth != type->payload.image_type.depth) + return false; + if (supertype->payload.image_type.dim != type->payload.image_type.dim) + return false; + if (supertype->payload.image_type.arrayed != type->payload.image_type.arrayed) + return false; + if (supertype->payload.image_type.ms != type->payload.image_type.ms) + return false; + if (supertype->payload.image_type.sampled != type->payload.image_type.sampled) + return false; + if (supertype->payload.image_type.imageformat != type->payload.image_type.imageformat) + return false; + return true; + } + case Type_SampledImageType_TAG: + return is_subtype(supertype->payload.sampled_image_type.image_type, type->payload.sampled_image_type.image_type); + default: break; + } + // Two types are always equal (and therefore subtypes of each other) if their payload matches + return memcmp(&supertype->payload, &type->payload, sizeof(type->payload)) == 0; +} + +void check_subtype(const Type* supertype, const Type* type) { + if (!is_subtype(supertype, type)) { + shd_log_node(ERROR, type); + shd_error_print(" isn't a subtype of "); + shd_log_node(ERROR, supertype); + shd_error_print("\n"); + shd_error("failed check_subtype") + } +} + +size_t shd_get_type_bitwidth(const Type* t) { + switch (t->tag) { + case Int_TAG: return int_size_in_bytes(t->payload.int_type.width) * 8; + case Float_TAG: return float_size_in_bytes(t->payload.float_type.width) * 8; + case PtrType_TAG: { + if (t->arena->config.address_spaces[t->payload.ptr_type.address_space].physical) + return int_size_in_bytes(t->arena->config.memory.ptr_size) * 8; + break; + } + default: break; + } + return SIZE_MAX; +} + +bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { + switch (as) { + case AsGeneric: + case AsInput: + case AsOutput: + case AsFunction: + case AsPrivate: return !arena->config.is_simt; + default: return true; + } +} + +const Type* get_actual_mask_type(IrArena* arena) { + switch (arena->config.specializations.subgroup_mask_representation) { + case SubgroupMaskAbstract: return mask_type(arena); + case SubgroupMaskInt64: return shd_uint64_type(arena); + default: assert(false); + } +} + +String name_type_safe(IrArena* arena, const Type* t) { + switch (is_type(t)) { + case NotAType: assert(false); + case Type_MaskType_TAG: return "mask_t"; + case Type_JoinPointType_TAG: return "join_type_t"; + case Type_NoRet_TAG: return "no_ret"; + case Type_Int_TAG: { + if (t->payload.int_type.is_signed) + return shd_format_string_arena(arena->arena, "i%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); + else + return shd_format_string_arena(arena->arena, "u%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); + } + case Type_Float_TAG: return shd_format_string_arena(arena->arena, "f%s", ((String[]) { "16", "32", "64" })[t->payload.float_type.width]); + case Type_Bool_TAG: return "bool"; + case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; + default: break; + } + return unique_name(arena, shd_get_node_tag_string(t->tag)); +} + +/// Is this a type that a value in the language can have ? +bool is_value_type(const Type* type) { + if (type->tag != QualifiedType_TAG) + return false; + return is_data_type(get_unqualified_type(type)); +} + +/// Is this a valid data type (for usage in other types and as type arguments) ? +bool is_data_type(const Type* type) { + switch (is_type(type)) { + case Type_MaskType_TAG: + case Type_JoinPointType_TAG: + case Type_Int_TAG: + case Type_Float_TAG: + case Type_Bool_TAG: + return true; + case Type_PtrType_TAG: + return true; + case Type_ArrType_TAG: + // array types _must_ be sized to be real data types + return type->payload.arr_type.size != NULL; + case Type_PackType_TAG: + return is_data_type(type->payload.pack_type.element_type); + case Type_RecordType_TAG: { + for (size_t i = 0; i < type->payload.record_type.members.count; i++) + if (!is_data_type(type->payload.record_type.members.nodes[i])) + return false; + // multi-return record types are the results of instructions, but are not values themselves + return type->payload.record_type.special == NotSpecial; + } + case Type_TypeDeclRef_TAG: + return !get_nominal_type_body(type) || is_data_type(get_nominal_type_body(type)); + // qualified types are not data types because that information is only meant for values + case Type_QualifiedType_TAG: return false; + // values cannot contain abstractions + case Type_FnType_TAG: + case Type_BBType_TAG: + case Type_LamType_TAG: + return false; + // this type has no values to begin with + case Type_NoRet_TAG: + return false; + case NotAType: + return false; + // Image stuff is data (albeit opaque) + case Type_SampledImageType_TAG: + case Type_SamplerType_TAG: + case Type_ImageType_TAG: + return true; + } +} + +bool is_arithm_type(const Type* t) { + return t->tag == Int_TAG || t->tag == Float_TAG; +} + +bool is_shiftable_type(const Type* t) { + return t->tag == Int_TAG || t->tag == MaskType_TAG; +} + +bool has_boolean_ops(const Type* t) { + return t->tag == Int_TAG || t->tag == Bool_TAG || t->tag == MaskType_TAG; +} + +bool is_comparable_type(const Type* t) { + return true; // TODO this is fine to allow, but we'll need to lower it for composite and native ptr types ! +} + +bool is_ordered_type(const Type* t) { + return is_arithm_type(t); +} + +bool is_physical_ptr_type(const Type* t) { + if (t->tag != PtrType_TAG) + return false; + return !t->payload.ptr_type.is_reference; + // AddressSpace as = t->payload.ptr_type.address_space; + // return t->arena->config.address_spaces[as].physical; +} + +bool is_generic_ptr_type(const Type* t) { + if (t->tag != PtrType_TAG) + return false; + AddressSpace as = t->payload.ptr_type.address_space; + return as == AsGeneric; +} + +bool is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type) { + assert(is_data_type(src_type) && is_data_type(dst_type)); + if (src_type == dst_type) + return true; // folding will eliminate those, but we need to pass type-checking first :) + if (!(is_arithm_type(src_type) || src_type->tag == MaskType_TAG || is_physical_ptr_type(src_type))) + return false; + if (!(is_arithm_type(dst_type) || dst_type->tag == MaskType_TAG || is_physical_ptr_type(dst_type))) + return false; + assert(shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)); + // either both pointers need to be in the generic address space, and we're only casting the element type, OR neither can be + if ((is_physical_ptr_type(src_type) && is_physical_ptr_type(dst_type)) && (is_generic_ptr_type(src_type) != is_generic_ptr_type(dst_type))) + return false; + return true; +} + +bool is_conversion_legal(const Type* src_type, const Type* dst_type) { + assert(is_data_type(src_type) && is_data_type(dst_type)); + if (!(is_arithm_type(src_type) || (is_physical_ptr_type(src_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) + return false; + if (!(is_arithm_type(dst_type) || (is_physical_ptr_type(dst_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) + return false; + // we only allow ptr-ptr conversions, use reinterpret otherwise + if (is_physical_ptr_type(src_type) != is_physical_ptr_type(dst_type)) + return false; + // exactly one of the pointers needs to be in the generic address space + if (is_generic_ptr_type(src_type) && is_generic_ptr_type(dst_type)) + return false; + if (src_type->tag == Int_TAG && dst_type->tag == Int_TAG) { + bool changes_sign = src_type->payload.int_type.is_signed != dst_type->payload.int_type.is_signed; + bool changes_width = src_type->payload.int_type.width != dst_type->payload.int_type.width; + if (changes_sign && changes_width) + return false; + } + // element types have to match (use reinterpret_cast for changing it) + if (is_physical_ptr_type(src_type) && is_physical_ptr_type(dst_type)) { + AddressSpace src_as = src_type->payload.ptr_type.address_space; + AddressSpace dst_as = dst_type->payload.ptr_type.address_space; + if (src_type->payload.ptr_type.pointed_type != dst_type->payload.ptr_type.pointed_type) + return false; + } + return true; +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" + +const Type* check_type_join_point_type(IrArena* arena, JoinPointType type) { + for (size_t i = 0; i < type.yield_types.count; i++) { + assert(is_data_type(type.yield_types.nodes[i])); + } + return NULL; +} + +const Type* check_type_record_type(IrArena* arena, RecordType type) { + assert(type.names.count == 0 || type.names.count == type.members.count); + for (size_t i = 0; i < type.members.count; i++) { + // member types are value types iff this is a return tuple + if (type.special == MultipleReturn) + assert(is_value_type(type.members.nodes[i])); + else + assert(is_data_type(type.members.nodes[i])); + } + return NULL; +} + +const Type* check_type_qualified_type(IrArena* arena, QualifiedType qualified_type) { + assert(is_data_type(qualified_type.type)); + assert(arena->config.is_simt || qualified_type.is_uniform); + return NULL; +} + +const Type* check_type_arr_type(IrArena* arena, ArrType type) { + assert(is_data_type(type.element_type)); + return NULL; +} + +const Type* check_type_pack_type(IrArena* arena, PackType pack_type) { + assert(is_data_type(pack_type.element_type)); + return NULL; +} + +const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { + if (!arena->config.address_spaces[ptr_type.address_space].allowed) { + shd_error_print("Address space %s is not allowed in this arena\n", get_address_space_name(ptr_type.address_space)); + shd_error_die(); + } + assert(ptr_type.pointed_type && "Shady does not support untyped pointers, but can infer them, see infer.c"); + if (ptr_type.pointed_type) { + if (ptr_type.pointed_type->tag == ArrType_TAG) { + assert(is_data_type(ptr_type.pointed_type->payload.arr_type.element_type)); + return NULL; + } + if (ptr_type.pointed_type->tag == FnType_TAG || ptr_type.pointed_type == unit_type(arena)) { + // no diagnostic required, we just allow these + return NULL; + } + const Node* maybe_record_type = ptr_type.pointed_type; + if (maybe_record_type->tag == TypeDeclRef_TAG) + maybe_record_type = get_nominal_type_body(maybe_record_type); + if (maybe_record_type && maybe_record_type->tag == RecordType_TAG && maybe_record_type->payload.record_type.special == DecorateBlock) { + return NULL; + } + assert(is_data_type(ptr_type.pointed_type)); + } + return NULL; +} + +const Type* check_type_param(IrArena* arena, Param variable) { + assert(is_value_type(variable.type)); + return variable.type; +} + +const Type* check_type_untyped_number(IrArena* arena, UntypedNumber untyped) { + shd_error("should never happen"); +} + +const Type* check_type_int_literal(IrArena* arena, IntLiteral lit) { + return qualified_type(arena, (QualifiedType) { + .is_uniform = true, + .type = int_type(arena, (Int) { .width = lit.width, .is_signed = lit.is_signed }) + }); +} + +const Type* check_type_float_literal(IrArena* arena, FloatLiteral lit) { + return qualified_type(arena, (QualifiedType) { + .is_uniform = true, + .type = float_type(arena, (Float) { .width = lit.width }) + }); +} + +const Type* check_type_true_lit(IrArena* arena) { return qualified_type(arena, (QualifiedType) { .type = bool_type(arena), .is_uniform = true }); } +const Type* check_type_false_lit(IrArena* arena) { return qualified_type(arena, (QualifiedType) { .type = bool_type(arena), .is_uniform = true }); } + +const Type* check_type_string_lit(IrArena* arena, StringLiteral str_lit) { + const Type* t = arr_type(arena, (ArrType) { + .element_type = shd_int8_type(arena), + .size = shd_int32_literal(arena, strlen(str_lit.string)) + }); + return qualified_type(arena, (QualifiedType) { + .type = t, + .is_uniform = true, + }); +} + +const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { + assert(is_data_type(payload.ptr_type) && payload.ptr_type->tag == PtrType_TAG); + return shd_as_qualified_type(payload.ptr_type, true); +} + +const Type* check_type_composite(IrArena* arena, Composite composite) { + if (composite.type) { + assert(is_data_type(composite.type)); + Nodes expected_member_types = get_composite_type_element_types(composite.type); + bool is_uniform = true; + assert(composite.contents.count == expected_member_types.count); + for (size_t i = 0; i < composite.contents.count; i++) { + const Type* element_type = composite.contents.nodes[i]->type; + is_uniform &= deconstruct_qualified_type(&element_type); + assert(is_subtype(expected_member_types.nodes[i], element_type)); + } + return qualified_type(arena, (QualifiedType) { + .is_uniform = is_uniform, + .type = composite.type + }); + } + bool is_uniform = true; + LARRAY(const Type*, member_ts, composite.contents.count); + for (size_t i = 0; i < composite.contents.count; i++) { + const Type* element_type = composite.contents.nodes[i]->type; + is_uniform &= deconstruct_qualified_type(&element_type); + member_ts[i] = element_type; + } + return qualified_type(arena, (QualifiedType) { + .is_uniform = is_uniform, + .type = record_type(arena, (RecordType) { + .members = shd_nodes(arena, composite.contents.count, member_ts) + }) + }); +} + +const Type* check_type_fill(IrArena* arena, Fill payload) { + assert(is_data_type(payload.type)); + const Node* element_t = get_fill_type_element_type(payload.type); + const Node* value_t = payload.value->type; + bool u = deconstruct_qualified_type(&value_t); + assert(is_subtype(element_t, value_t)); + return qualified_type(arena, (QualifiedType) { + .is_uniform = u, + .type = payload.type + }); +} + +const Type* check_type_undef(IrArena* arena, Undef payload) { + assert(is_data_type(payload.type)); + return qualified_type(arena, (QualifiedType) { + .is_uniform = true, + .type = payload.type + }); +} + +const Type* check_type_mem_and_value(IrArena* arena, MemAndValue mav) { + return mav.value->type; +} + +const Type* check_type_fn_addr(IrArena* arena, FnAddr fn_addr) { + assert(fn_addr.fn->type->tag == FnType_TAG); + assert(fn_addr.fn->tag == Function_TAG); + return qualified_type(arena, (QualifiedType) { + .is_uniform = true, + .type = ptr_type(arena, (PtrType) { + .pointed_type = fn_addr.fn->type, + .address_space = AsGeneric /* the actual AS does not matter because these are opaque anyways */, + }) + }); +} + +const Type* check_type_ref_decl(IrArena* arena, RefDecl ref_decl) { + const Type* t = ref_decl.decl->type; + assert(t && "RefDecl needs to be applied on a decl with a non-null type. Did you forget to set 'type' on a constant ?"); + switch (ref_decl.decl->tag) { + case GlobalVariable_TAG: + case Constant_TAG: break; + default: shd_error("You can only use RefDecl on a global or a constant. See FnAddr for taking addresses of functions.") + } + assert(t->tag != QualifiedType_TAG && "decl types may not be qualified"); + return qualified_type(arena, (QualifiedType) { + .type = t, + .is_uniform = true, + }); +} + +const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { + for (size_t i = 0; i < prim_op.type_arguments.count; i++) { + const Node* ta = prim_op.type_arguments.nodes[i]; + assert(ta && is_type(ta)); + } + for (size_t i = 0; i < prim_op.operands.count; i++) { + const Node* operand = prim_op.operands.nodes[i]; + assert(operand && is_value(operand)); + } + + bool extended = false; + bool ordered = false; + AddressSpace as; + switch (prim_op.op) { + case neg_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 1); + + const Type* type = shd_first(prim_op.operands)->type; + assert(is_arithm_type(get_maybe_packed_type_element(get_unqualified_type(type)))); + return type; + } + case rshift_arithm_op: + case rshift_logical_op: + case lshift_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 2); + const Type* first_operand_type = shd_first(prim_op.operands)->type; + const Type* second_operand_type = prim_op.operands.nodes[1]->type; + + bool uniform_result = deconstruct_qualified_type(&first_operand_type); + uniform_result &= deconstruct_qualified_type(&second_operand_type); + + size_t value_simd_width = deconstruct_maybe_packed_type(&first_operand_type); + size_t shift_simd_width = deconstruct_maybe_packed_type(&second_operand_type); + assert(value_simd_width == shift_simd_width); + + assert(first_operand_type->tag == Int_TAG); + assert(second_operand_type->tag == Int_TAG); + + return shd_as_qualified_type(maybe_packed_type_helper(first_operand_type, value_simd_width), uniform_result); + } + case add_carry_op: + case sub_borrow_op: + case mul_extended_op: extended = true; SHADY_FALLTHROUGH; + case min_op: + case max_op: + case add_op: + case sub_op: + case mul_op: + case div_op: + case mod_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 2); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + + bool result_uniform = true; + for (size_t i = 0; i < prim_op.operands.count; i++) { + const Node* arg = prim_op.operands.nodes[i]; + const Type* operand_type = arg->type; + bool operand_uniform = deconstruct_qualified_type(&operand_type); + + assert(is_arithm_type(get_maybe_packed_type_element(operand_type))); + assert(first_operand_type == operand_type && "operand type mismatch"); + + result_uniform &= operand_uniform; + } + + const Type* result_t = first_operand_type; + if (extended) { + // TODO: assert unsigned + result_t = record_type(arena, (RecordType) {.members = mk_nodes(arena, result_t, result_t)}); + } + return shd_as_qualified_type(result_t, result_uniform); + } + + case not_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 1); + + const Type* type = shd_first(prim_op.operands)->type; + assert(has_boolean_ops(get_maybe_packed_type_element(get_unqualified_type(type)))); + return type; + } + case or_op: + case xor_op: + case and_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 2); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + + bool result_uniform = true; + for (size_t i = 0; i < prim_op.operands.count; i++) { + const Node* arg = prim_op.operands.nodes[i]; + const Type* operand_type = arg->type; + bool operand_uniform = deconstruct_qualified_type(&operand_type); + + assert(has_boolean_ops(get_maybe_packed_type_element(operand_type))); + assert(first_operand_type == operand_type && "operand type mismatch"); + + result_uniform &= operand_uniform; + } + + return shd_as_qualified_type(first_operand_type, result_uniform); + } + case lt_op: + case lte_op: + case gt_op: + case gte_op: ordered = true; SHADY_FALLTHROUGH + case eq_op: + case neq_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 2); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + size_t first_operand_width = get_maybe_packed_type_width(first_operand_type); + + bool result_uniform = true; + for (size_t i = 0; i < prim_op.operands.count; i++) { + const Node* arg = prim_op.operands.nodes[i]; + const Type* operand_type = arg->type; + bool operand_uniform = deconstruct_qualified_type(&operand_type); + + assert((ordered ? is_ordered_type : is_comparable_type)(get_maybe_packed_type_element(operand_type))); + assert(first_operand_type == operand_type && "operand type mismatch"); + + result_uniform &= operand_uniform; + } + + return shd_as_qualified_type(maybe_packed_type_helper(bool_type(arena), first_operand_width), + result_uniform); + } + case sqrt_op: + case inv_sqrt_op: + case floor_op: + case ceil_op: + case round_op: + case fract_op: + case sin_op: + case cos_op: + case exp_op: + { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 1); + const Node* src_type = shd_first(prim_op.operands)->type; + bool uniform = deconstruct_qualified_type(&src_type); + size_t width = deconstruct_maybe_packed_type(&src_type); + assert(src_type->tag == Float_TAG); + return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); + } + case pow_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 2); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + + bool result_uniform = true; + for (size_t i = 0; i < prim_op.operands.count; i++) { + const Node* arg = prim_op.operands.nodes[i]; + const Type* operand_type = arg->type; + bool operand_uniform = deconstruct_qualified_type(&operand_type); + + assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); + assert(first_operand_type == operand_type && "operand type mismatch"); + + result_uniform &= operand_uniform; + } + + return shd_as_qualified_type(first_operand_type, result_uniform); + } + case fma_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 3); + const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + + bool result_uniform = true; + for (size_t i = 0; i < prim_op.operands.count; i++) { + const Node* arg = prim_op.operands.nodes[i]; + const Type* operand_type = arg->type; + bool operand_uniform = deconstruct_qualified_type(&operand_type); + + assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); + assert(first_operand_type == operand_type && "operand type mismatch"); + + result_uniform &= operand_uniform; + } + + return shd_as_qualified_type(first_operand_type, result_uniform); + } + case abs_op: + case sign_op: + { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 1); + const Node* src_type = shd_first(prim_op.operands)->type; + bool uniform = deconstruct_qualified_type(&src_type); + size_t width = deconstruct_maybe_packed_type(&src_type); + assert(src_type->tag == Float_TAG || src_type->tag == Int_TAG && src_type->payload.int_type.is_signed); + return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); + } + case align_of_op: + case size_of_op: { + assert(prim_op.type_arguments.count == 1); + assert(prim_op.operands.count == 0); + return qualified_type(arena, (QualifiedType) { + .is_uniform = true, + .type = int_type(arena, (Int) { .width = arena->config.memory.ptr_size, .is_signed = false }) + }); + } + case offset_of_op: { + assert(prim_op.type_arguments.count == 1); + assert(prim_op.operands.count == 1); + const Type* optype = shd_first(prim_op.operands)->type; + bool uniform = deconstruct_qualified_type(&optype); + assert(uniform && optype->tag == Int_TAG); + return qualified_type(arena, (QualifiedType) { + .is_uniform = true, + .type = int_type(arena, (Int) { .width = arena->config.memory.ptr_size, .is_signed = false }) + }); + } + case select_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 3); + const Type* condition_type = prim_op.operands.nodes[0]->type; + bool condition_uniform = deconstruct_qualified_type(&condition_type); + size_t width = deconstruct_maybe_packed_type(&condition_type); + + const Type* alternatives_types[2]; + bool alternatives_all_uniform = true; + for (size_t i = 0; i < 2; i++) { + alternatives_types[i] = prim_op.operands.nodes[1 + i]->type; + alternatives_all_uniform &= deconstruct_qualified_type(&alternatives_types[i]); + size_t alternative_width = deconstruct_maybe_packed_type(&alternatives_types[i]); + assert(alternative_width == width); + } + + assert(is_subtype(bool_type(arena), condition_type)); + // todo find true supertype + assert(are_types_identical(2, alternatives_types)); + + return shd_as_qualified_type(maybe_packed_type_helper(alternatives_types[0], width), + alternatives_all_uniform && condition_uniform); + } + case insert_op: + case extract_dynamic_op: + case extract_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count >= 2); + const Node* source = shd_first(prim_op.operands); + + size_t indices_start = prim_op.op == insert_op ? 2 : 1; + Nodes indices = shd_nodes(arena, prim_op.operands.count - indices_start, &prim_op.operands.nodes[indices_start]); + + const Type* t = source->type; + bool uniform = deconstruct_qualified_type(&t); + enter_composite_indices(&t, &uniform, indices, true); + + if (prim_op.op == insert_op) { + const Node* inserted_data = prim_op.operands.nodes[1]; + const Type* inserted_data_type = inserted_data->type; + bool is_uniform = uniform & deconstruct_qualified_type(&inserted_data_type); + assert(is_subtype(t, inserted_data_type) && "inserting data into a composite, but it doesn't match the target and indices"); + return qualified_type(arena, (QualifiedType) { + .is_uniform = is_uniform, + .type = get_unqualified_type(source->type), + }); + } + + return shd_as_qualified_type(t, uniform); + } + case shuffle_op: { + assert(prim_op.operands.count >= 2); + assert(prim_op.type_arguments.count == 0); + const Node* lhs = prim_op.operands.nodes[0]; + const Node* rhs = prim_op.operands.nodes[1]; + const Type* lhs_t = lhs->type; + const Type* rhs_t = rhs->type; + bool lhs_u = deconstruct_qualified_type(&lhs_t); + bool rhs_u = deconstruct_qualified_type(&rhs_t); + assert(lhs_t->tag == PackType_TAG && rhs_t->tag == PackType_TAG); + size_t total_size = lhs_t->payload.pack_type.width + rhs_t->payload.pack_type.width; + const Type* element_t = lhs_t->payload.pack_type.element_type; + assert(element_t == rhs_t->payload.pack_type.element_type); + + size_t indices_count = prim_op.operands.count - 2; + const Node** indices = &prim_op.operands.nodes[2]; + bool u = lhs_u & rhs_u; + for (size_t i = 0; i < indices_count; i++) { + u &= is_qualified_type_uniform(indices[i]->type); + int64_t index = shd_get_int_literal_value(*shd_resolve_to_int_literal(indices[i]), true); + assert(index < 0 /* poison */ || (index >= 0 && index < total_size && "shuffle element out of range")); + } + return shd_as_qualified_type( + pack_type(arena, (PackType) {.element_type = element_t, .width = indices_count}), u); + } + case reinterpret_op: { + assert(prim_op.type_arguments.count == 1); + assert(prim_op.operands.count == 1); + const Node* source = shd_first(prim_op.operands); + const Type* src_type = source->type; + bool src_uniform = deconstruct_qualified_type(&src_type); + + const Type* dst_type = shd_first(prim_op.type_arguments); + assert(is_data_type(dst_type)); + assert(is_reinterpret_cast_legal(src_type, dst_type)); + + return qualified_type(arena, (QualifiedType) { + .is_uniform = src_uniform, + .type = dst_type + }); + } + case convert_op: { + assert(prim_op.type_arguments.count == 1); + assert(prim_op.operands.count == 1); + const Node* source = shd_first(prim_op.operands); + const Type* src_type = source->type; + bool src_uniform = deconstruct_qualified_type(&src_type); + + const Type* dst_type = shd_first(prim_op.type_arguments); + assert(is_data_type(dst_type)); + assert(is_conversion_legal(src_type, dst_type)); + + // TODO check the conversion is legal + return qualified_type(arena, (QualifiedType) { + .is_uniform = src_uniform, + .type = dst_type + }); + } + // Mask management + case empty_mask_op: { + assert(prim_op.type_arguments.count == 0 && prim_op.operands.count == 0); + return shd_as_qualified_type(get_actual_mask_type(arena), true); + } + case mask_is_thread_active_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 2); + return qualified_type(arena, (QualifiedType) { + .is_uniform = is_qualified_type_uniform(prim_op.operands.nodes[0]->type) && is_qualified_type_uniform(prim_op.operands.nodes[1]->type), + .type = bool_type(arena) + }); + } + // Subgroup ops + case subgroup_assume_uniform_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 1); + const Type* operand_type = get_unqualified_type(prim_op.operands.nodes[0]->type); + return qualified_type(arena, (QualifiedType) { + .is_uniform = true, + .type = operand_type + }); + } + // Intermediary ops + case sample_texture_op: { + assert(prim_op.type_arguments.count == 0); + assert(prim_op.operands.count == 2); + const Type* sampled_image_t = shd_first(prim_op.operands)->type; + bool uniform_src = deconstruct_qualified_type(&sampled_image_t); + const Type* coords_t = prim_op.operands.nodes[1]->type; + deconstruct_qualified_type(&coords_t); + assert(sampled_image_t->tag == SampledImageType_TAG); + const Type* image_t = sampled_image_t->payload.sampled_image_type.image_type; + assert(image_t->tag == ImageType_TAG); + size_t coords_dim = deconstruct_packed_type(&coords_t); + return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = maybe_packed_type_helper(image_t->payload.image_type.sampled_type, 4) }); + } + case PRIMOPS_COUNT: assert(false); + } +} + +const Type* check_type_ext_instr(IrArena* arena, ExtInstr payload) { + return payload.result_t; +} + +static void check_arguments_types_against_parameters_helper(Nodes param_types, Nodes arg_types) { + if (param_types.count != arg_types.count) + shd_error("Mismatched number of arguments/parameters"); + for (size_t i = 0; i < param_types.count; i++) + check_subtype(param_types.nodes[i], arg_types.nodes[i]); +} + +/// Shared logic between indirect calls and tailcalls +static Nodes check_value_call(const Node* callee, Nodes argument_types) { + assert(is_value(callee)); + + const Type* callee_type = callee->type; + SHADY_UNUSED bool callee_uniform = deconstruct_qualified_type(&callee_type); + AddressSpace as = deconstruct_pointer_type(&callee_type); + assert(as == AsGeneric); + + assert(callee_type->tag == FnType_TAG); + + const FnType* fn_type = &callee_type->payload.fn_type; + check_arguments_types_against_parameters_helper(fn_type->param_types, argument_types); + // TODO force the return types to be varying if the callee is not uniform + return fn_type->return_types; +} + +const Type* check_type_call(IrArena* arena, Call call) { + Nodes args = call.args; + for (size_t i = 0; i < args.count; i++) { + const Node* argument = args.nodes[i]; + assert(is_value(argument)); + } + Nodes argument_types = get_values_types(arena, args); + return maybe_multiple_return(arena, check_value_call(call.callee, argument_types)); +} + +static void ensure_types_are_data_types(const Nodes* yield_types) { + for (size_t i = 0; i < yield_types->count; i++) { + assert(is_data_type(yield_types->nodes[i])); + } +} + +static void ensure_types_are_value_types(const Nodes* yield_types) { + for (size_t i = 0; i < yield_types->count; i++) { + assert(is_value_type(yield_types->nodes[i])); + } +} + +const Type* check_type_if_instr(IrArena* arena, If if_instr) { + assert(if_instr.tail && is_abstraction(if_instr.tail)); + ensure_types_are_data_types(&if_instr.yield_types); + if (get_unqualified_type(if_instr.condition->type) != bool_type(arena)) + shd_error("condition of an if should be bool"); + // TODO check the contained Merge instrs + if (if_instr.yield_types.count > 0) + assert(if_instr.if_false); + + check_arguments_types_against_parameters_helper(get_param_types(arena, get_abstraction_params(if_instr.tail)), add_qualifiers(arena, if_instr.yield_types, false)); + return noret_type(arena); +} + +const Type* check_type_match_instr(IrArena* arena, Match match_instr) { + ensure_types_are_data_types(&match_instr.yield_types); + // TODO check param against initial_args + // TODO check the contained Merge instrs + return noret_type(arena); +} + +const Type* check_type_loop_instr(IrArena* arena, Loop loop_instr) { + ensure_types_are_data_types(&loop_instr.yield_types); + // TODO check param against initial_args + // TODO check the contained Merge instrs + return noret_type(arena); +} + +const Type* check_type_control(IrArena* arena, Control control) { + ensure_types_are_data_types(&control.yield_types); + // TODO check it then ! + const Node* join_point = shd_first(get_abstraction_params(control.inside)); + + const Type* join_point_type = join_point->type; + deconstruct_qualified_type(&join_point_type); + assert(join_point_type->tag == JoinPointType_TAG); + + Nodes join_point_yield_types = join_point_type->payload.join_point_type.yield_types; + assert(join_point_yield_types.count == control.yield_types.count); + for (size_t i = 0; i < control.yield_types.count; i++) { + assert(is_subtype(control.yield_types.nodes[i], join_point_yield_types.nodes[i])); + } + + assert(get_abstraction_params(control.tail).count == control.yield_types.count); + + return noret_type(arena); +} + +const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { + return empty_multiple_return_type(arena); +} + +const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { + assert(is_type(alloc.type)); + return qualified_type(a, (QualifiedType) { + .is_uniform = is_addr_space_uniform(a, AsPrivate), + .type = ptr_type(a, (PtrType) { + .pointed_type = alloc.type, + .address_space = AsPrivate, + .is_reference = false + }) + }); +} + +const Type* check_type_local_alloc(IrArena* a, LocalAlloc alloc) { + assert(is_type(alloc.type)); + return qualified_type(a, (QualifiedType) { + .is_uniform = is_addr_space_uniform(a, AsFunction), + .type = ptr_type(a, (PtrType) { + .pointed_type = alloc.type, + .address_space = AsFunction, + .is_reference = true + }) + }); +} + +const Type* check_type_load(IrArena* a, Load load) { + const Node* ptr_type = load.ptr->type; + bool ptr_uniform = deconstruct_qualified_type(&ptr_type); + size_t width = deconstruct_maybe_packed_type(&ptr_type); + + assert(ptr_type->tag == PtrType_TAG); + const PtrType* node_ptr_type_ = &ptr_type->payload.ptr_type; + const Type* elem_type = node_ptr_type_->pointed_type; + elem_type = maybe_packed_type_helper(elem_type, width); + return shd_as_qualified_type(elem_type, + ptr_uniform && is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); +} + +const Type* check_type_store(IrArena* a, Store store) { + const Node* ptr_type = store.ptr->type; + bool ptr_uniform = deconstruct_qualified_type(&ptr_type); + size_t width = deconstruct_maybe_packed_type(&ptr_type); + assert(ptr_type->tag == PtrType_TAG); + const PtrType* ptr_type_payload = &ptr_type->payload.ptr_type; + const Type* elem_type = ptr_type_payload->pointed_type; + assert(elem_type); + elem_type = maybe_packed_type_helper(elem_type, width); + // we don't enforce uniform stores - but we care about storing the right thing :) + const Type* val_expected_type = qualified_type(a, (QualifiedType) { + .is_uniform = !a->config.is_simt, + .type = elem_type + }); + + assert(is_subtype(val_expected_type, store.value->type)); + return empty_multiple_return_type(a); +} + +const Type* check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffset lea) { + const Type* base_ptr_type = lea.ptr->type; + bool uniform = deconstruct_qualified_type(&base_ptr_type); + assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); + const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; + + assert(lea.offset); + const Type* offset_type = lea.offset->type; + bool offset_uniform = deconstruct_qualified_type(&offset_type); + assert(offset_type->tag == Int_TAG && "lea expects an integer offset"); + + const IntLiteral* lit = shd_resolve_to_int_literal(lea.offset); + bool offset_is_zero = lit && lit->value == 0; + assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); + assert(offset_is_zero || is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); + uniform &= offset_uniform; + + return qualified_type(a, (QualifiedType) { + .is_uniform = uniform, + .type = ptr_type(a, (PtrType) { + .pointed_type = pointee_type, + .address_space = base_ptr_type->payload.ptr_type.address_space, + .is_reference = base_ptr_type->payload.ptr_type.is_reference + }) + }); +} + +const Type* check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea) { + const Type* base_ptr_type = lea.ptr->type; + bool uniform = deconstruct_qualified_type(&base_ptr_type); + assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); + const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; + + enter_composite(&pointee_type, &uniform, lea.index, true); + + return qualified_type(a, (QualifiedType) { + .is_uniform = uniform, + .type = ptr_type(a, (PtrType) { + .pointed_type = pointee_type, + .address_space = base_ptr_type->payload.ptr_type.address_space, + .is_reference = base_ptr_type->payload.ptr_type.is_reference + }) + }); +} + +const Type* check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { + const Type* dst_t = copy_bytes.dst->type; + deconstruct_qualified_type(&dst_t); + assert(dst_t->tag == PtrType_TAG); + const Type* src_t = copy_bytes.src->type; + deconstruct_qualified_type(&src_t); + assert(src_t); + const Type* cnt_t = copy_bytes.count->type; + deconstruct_qualified_type(&cnt_t); + assert(cnt_t->tag == Int_TAG); + return empty_multiple_return_type(a); +} + +const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { + const Type* dst_t = fill_bytes.dst->type; + deconstruct_qualified_type(&dst_t); + assert(dst_t->tag == PtrType_TAG); + const Type* src_t = fill_bytes.src->type; + deconstruct_qualified_type(&src_t); + assert(src_t); + const Type* cnt_t = fill_bytes.count->type; + deconstruct_qualified_type(&cnt_t); + assert(cnt_t->tag == Int_TAG); + return empty_multiple_return_type(a); +} + +const Type* check_type_push_stack(IrArena* a, PushStack payload) { + assert(payload.value); + return empty_multiple_return_type(a); +} + +const Type* check_type_pop_stack(IrArena* a, PopStack payload) { + return shd_as_qualified_type(payload.type, false); +} + +const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { + assert(get_unqualified_type(payload.value->type) == shd_uint32_type(a)); + return shd_as_qualified_type(unit_type(a), true); +} + +const Type* check_type_get_stack_size(IrArena* a, SHADY_UNUSED GetStackSize ss) { + return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = shd_uint32_type(a) }); +} + +const Type* check_type_get_stack_base_addr(IrArena* a, SHADY_UNUSED GetStackBaseAddr gsba) { + const Node* ptr = ptr_type(a, (PtrType) { .pointed_type = shd_uint8_type(a), .address_space = AsPrivate}); + return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = ptr }); +} + +const Type* check_type_debug_printf(IrArena* a, DebugPrintf payload) { + return empty_multiple_return_type(a); +} + +const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { + Nodes args = tail_call.args; + for (size_t i = 0; i < args.count; i++) { + const Node* argument = args.nodes[i]; + assert(is_value(argument)); + } + assert(check_value_call(tail_call.callee, get_values_types(arena, tail_call.args)).count == 0); + return noret_type(arena); +} + +static void check_basic_block_call(const Node* block, Nodes argument_types) { + assert(is_basic_block(block)); + assert(block->type->tag == BBType_TAG); + BBType bb_type = block->type->payload.bb_type; + check_arguments_types_against_parameters_helper(bb_type.param_types, argument_types); +} + +const Type* check_type_jump(IrArena* arena, Jump jump) { + for (size_t i = 0; i < jump.args.count; i++) { + const Node* argument = jump.args.nodes[i]; + assert(is_value(argument)); + } + + check_basic_block_call(jump.target, get_values_types(arena, jump.args)); + return noret_type(arena); +} + +const Type* check_type_branch(IrArena* arena, Branch payload) { + assert(payload.true_jump->tag == Jump_TAG); + assert(payload.false_jump->tag == Jump_TAG); + return noret_type(arena); +} + +const Type* check_type_br_switch(IrArena* arena, Switch payload) { + for (size_t i = 0; i < payload.case_jumps.count; i++) + assert(payload.case_jumps.nodes[i]->tag == Jump_TAG); + assert(payload.case_values.count == payload.case_jumps.count); + assert(payload.default_jump->tag == Jump_TAG); + return noret_type(arena); +} + +const Type* check_type_join(IrArena* arena, Join join) { + for (size_t i = 0; i < join.args.count; i++) { + const Node* argument = join.args.nodes[i]; + assert(is_value(argument)); + } + + const Type* join_target_type = join.join_point->type; + + deconstruct_qualified_type(&join_target_type); + assert(join_target_type->tag == JoinPointType_TAG); + + Nodes join_point_param_types = join_target_type->payload.join_point_type.yield_types; + join_point_param_types = add_qualifiers(arena, join_point_param_types, !arena->config.is_simt); + + check_arguments_types_against_parameters_helper(join_point_param_types, get_values_types(arena, join.args)); + + return noret_type(arena); +} + +const Type* check_type_unreachable(IrArena* arena, SHADY_UNUSED Unreachable u) { + return noret_type(arena); +} + +const Type* check_type_merge_continue(IrArena* arena, MergeContinue mc) { + // TODO check it + return noret_type(arena); +} + +const Type* check_type_merge_break(IrArena* arena, MergeBreak mc) { + // TODO check it + return noret_type(arena); +} + +const Type* check_type_merge_selection(IrArena* arena, SHADY_UNUSED MergeSelection payload) { + // TODO check it + return noret_type(arena); +} + +const Type* check_type_fn_ret(IrArena* arena, Return ret) { + // assert(ret.fn); + // TODO check it then ! + return noret_type(arena); +} + +const Type* check_type_fun(IrArena* arena, Function fn) { + for (size_t i = 0; i < fn.return_types.count; i++) { + assert(is_value_type(fn.return_types.nodes[i])); + } + return fn_type(arena, (FnType) { .param_types = get_param_types(arena, (&fn)->params), .return_types = (&fn)->return_types }); +} + +const Type* check_type_basic_block(IrArena* arena, BasicBlock bb) { + return bb_type(arena, (BBType) { .param_types = get_param_types(arena, (&bb)->params) }); +} + +const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_variable) { + assert(is_type(global_variable.type)); + + const Node* ba = shd_lookup_annotation_list(global_variable.annotations, "Builtin"); + if (ba && arena->config.validate_builtin_types) { + Builtin b = shd_get_builtin_by_name(shd_get_annotation_string_payload(ba)); + assert(b != BuiltinsCount); + const Type* t = shd_get_builtin_type(arena, b); + if (t != global_variable.type) { + shd_error_print("Creating a @Builtin global variable '%s' with the incorrect type: ", global_variable.name); + shd_log_node(ERROR, global_variable.type); + shd_error_print(" instead of the expected "); + shd_log_node(ERROR, t); + shd_error_print(".\n"); + shd_error_die(); + } + } + + assert(global_variable.address_space < NumAddressSpaces); + + return ptr_type(arena, (PtrType) { + .pointed_type = global_variable.type, + .address_space = global_variable.address_space, + .is_reference = shd_lookup_annotation_list(global_variable.annotations, "Logical"), + }); +} + +const Type* check_type_constant(IrArena* arena, Constant cnst) { + assert(is_data_type(cnst.type_hint)); + return cnst.type_hint; +} + +#include "type_generated.c" + +#pragma GCC diagnostic pop diff --git a/src/shady/check.h b/src/shady/check.h new file mode 100644 index 000000000..1925e35f0 --- /dev/null +++ b/src/shady/check.h @@ -0,0 +1,22 @@ +#ifndef SHADY_TYPE_H +#define SHADY_TYPE_H + +#include "shady/ir.h" + +bool is_subtype(const Type* supertype, const Type* type); +void check_subtype(const Type* supertype, const Type* type); + +bool is_arithm_type(const Type*); +bool is_shiftable_type(const Type*); +bool has_boolean_ops(const Type*); +bool is_comparable_type(const Type*); +bool is_ordered_type(const Type*); +bool is_physical_ptr_type(const Type* t); +bool is_generic_ptr_type(const Type* t); + +bool is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type); +bool is_conversion_legal(const Type* src_type, const Type* dst_type); + +#include "type_generated.h" + +#endif From b1f59cdb1626585934444c5d6455cc180ac4a172 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 9 Oct 2024 15:59:24 +0200 Subject: [PATCH 641/693] prefix some things in check.c --- include/shady/ir/base.h | 1 - include/shady/ir/type.h | 6 ++- src/backend/c/emit_c.c | 2 +- src/backend/c/emit_c_value.c | 6 +-- src/backend/spirv/emit_spv_value.c | 2 +- src/frontend/slim/infer.c | 8 ++-- src/shady/analysis/verify.c | 6 +-- src/shady/check.c | 58 +++++++++++++------------- src/shady/check.h | 4 +- src/shady/fold.c | 4 +- src/shady/ir/type.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 6 +-- src/shady/passes/lower_mask.c | 6 +-- src/shady/passes/lower_nullptr.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 6 +-- src/shady/passes/lower_stack.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 2 +- 17 files changed, 62 insertions(+), 61 deletions(-) diff --git a/include/shady/ir/base.h b/include/shady/ir/base.h index 156604327..b44a72243 100644 --- a/include/shady/ir/base.h +++ b/include/shady/ir/base.h @@ -50,6 +50,5 @@ String string(IrArena*, const char*); // see also: format_string in util.h String shd_fmt_string_irarena(IrArena* arena, const char* str, ...); String unique_name(IrArena*, const char* base_name); -String name_type_safe(IrArena*, const Type*); #endif diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index 6f601ca0c..7f110806c 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -13,12 +13,14 @@ static inline const Node* unit_type(IrArena* arena) { Type* nominal_type(Module*, Nodes annotations, String name); -const Type* get_actual_mask_type(IrArena* arena); +const Type* shd_get_actual_mask_type(IrArena* arena); String get_address_space_name(AddressSpace); /// Returns false iff pointers in that address space can contain different data at the same address /// (amongst threads in the same subgroup) -bool is_addr_space_uniform(IrArena*, AddressSpace); +bool shd_is_addr_space_uniform(IrArena*, AddressSpace); + +String shd_get_type_name(IrArena* arena, const Type* t); /// Is this a type that a value in the language can have ? bool is_value_type(const Type*); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 0009d72d3..1fff77986 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -221,7 +221,7 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String // ISPC wants uniform/varying annotations if (emitter->config.dialect == CDialect_ISPC) { - bool uniform = is_addr_space_uniform(emitter->arena, as); + bool uniform = shd_is_addr_space_uniform(emitter->arena, as); if (uniform) name = shd_format_string_arena(emitter->arena->arena, "uniform %s", name); else diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 470ce5e5e..52d46ee75 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -217,7 +217,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No c_emit_decl(emitter, decl); if (emitter->config.dialect == CDialect_ISPC && decl->tag == GlobalVariable_TAG) { - if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !shd_is_decl_builtin( + if (!shd_is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !shd_is_decl_builtin( decl)) { assert(fn && "ISPC backend cannot statically refer to a varying variable"); return ispc_varying_ptr_helper(emitter, fn->instruction_printers[0], decl->type, *lookup_existing_term(emitter, NULL, decl)); @@ -933,7 +933,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, fn, payload.ptr)); CValue cvalue = to_cvalue(emitter, c_emit_value(emitter, fn, payload.value)); // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this - if (emitter->config.dialect == CDialect_ISPC && addr_uniform && is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) + if (emitter->config.dialect == CDialect_ISPC && addr_uniform && shd_is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) cvalue = shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); shd_print(p, "\n%s = %s;", dereferenced, cvalue); @@ -987,7 +987,7 @@ static bool can_appear_at_top_level(Emitter* emitter, const Node* node) { if (node->tag == RefDecl_TAG) { const Node* decl = node->payload.ref_decl.decl; if (decl->tag == GlobalVariable_TAG) - if (!is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !shd_is_decl_builtin( + if (!shd_is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !shd_is_decl_builtin( decl)) //if (is_value(node) && !is_qualified_type_uniform(node->type)) return false; diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index d39e1bb5c..3a7a803f0 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -295,7 +295,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b assert(instr.operands.count == 2); // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); // ad-hoc extension for my sanity - if (get_unqualified_type(instr.result_t) == get_actual_mask_type(emitter->arena)) { + if (get_unqualified_type(instr.result_t) == shd_get_actual_mask_type(emitter->arena)) { const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = shd_uint32_type(emitter->arena) }); SpvId raw_result = spvb_group_ballot(bb_builder, spv_emit_type(emitter, i32x4), spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), spv_emit_value(emitter, fn_builder, shd_first(instr.operands))); // TODO: why are we doing this in SPIR-V and not the IR ? diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index f8b7f70b4..971265a33 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -170,7 +170,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec bool expect_uniform = false; if (expected_type) { expect_uniform = deconstruct_qualified_type(&expected_type); - assert(is_subtype(expected_type, type)); + assert(shd_is_subtype(expected_type, type)); } return infer(ctx, node->payload.constrained.value, shd_as_qualified_type(type, expect_uniform)); } @@ -237,7 +237,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec const Node* elem_type = infer(ctx, node->payload.composite.type, NULL); bool uniform = false; if (elem_type && expected_type) { - assert(is_subtype(get_unqualified_type(expected_type), elem_type)); + assert(shd_is_subtype(get_unqualified_type(expected_type), elem_type)); } else if (expected_type) { uniform = deconstruct_qualified_type(&elem_type); elem_type = expected_type; @@ -266,7 +266,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec assert(composite_t); bool uniform = false; if (composite_t && expected_type) { - assert(is_subtype(get_unqualified_type(expected_type), composite_t)); + assert(shd_is_subtype(get_unqualified_type(expected_type), composite_t)); } else if (expected_type) { uniform = deconstruct_qualified_type(&composite_t); composite_t = expected_type; @@ -300,7 +300,7 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg // and do not use the provided param type if it is an untyped ptr if (!param_type || param_type->tag != PtrType_TAG || param_type->payload.ptr_type.pointed_type) param_type = inferred_arg_type.nodes[i]; - assert(is_subtype(param_type, inferred_arg_type.nodes[i])); + assert(shd_is_subtype(param_type, inferred_arg_type.nodes[i])); nparams[i] = param(a, param_type, old_param->name); shd_register_processed(&body_context.rewriter, node->payload.basic_block.params.nodes[i], nparams[i]); } diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index b574f3ed1..3a4720dbf 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -79,7 +79,7 @@ static void verify_nominal_node(const Node* fn, const Node* n) { break; } case BasicBlock_TAG: { - assert(is_subtype(noret_type(n->arena), n->payload.basic_block.body->type)); + assert(shd_is_subtype(noret_type(n->arena), n->payload.basic_block.body->type)); break; } case NominalType_TAG: { @@ -91,7 +91,7 @@ static void verify_nominal_node(const Node* fn, const Node* n) { const Type* t = n->payload.constant.value->type; bool u = deconstruct_qualified_type(&t); assert(u); - assert(is_subtype(n->payload.constant.type_hint, t)); + assert(shd_is_subtype(n->payload.constant.type_hint, t)); } break; } @@ -100,7 +100,7 @@ static void verify_nominal_node(const Node* fn, const Node* n) { const Type* t = n->payload.global_variable.init->type; bool u = deconstruct_qualified_type(&t); assert(u); - assert(is_subtype(n->payload.global_variable.type, t)); + assert(shd_is_subtype(n->payload.global_variable.type, t)); } break; } diff --git a/src/shady/check.c b/src/shady/check.c index 83088dfb1..40b952fca 100644 --- a/src/shady/check.c +++ b/src/shady/check.c @@ -22,7 +22,7 @@ static bool are_types_identical(size_t num_types, const Type* types[]) { return true; } -bool is_subtype(const Type* supertype, const Type* type) { +bool shd_is_subtype(const Type* supertype, const Type* type) { assert(supertype && type); if (supertype->tag != type->tag) return false; @@ -34,7 +34,7 @@ bool is_subtype(const Type* supertype, const Type* type) { // uniform T <: varying T if (supertype->payload.qualified_type.is_uniform && !type->payload.qualified_type.is_uniform) return false; - return is_subtype(supertype->payload.qualified_type.type, type->payload.qualified_type.type); + return shd_is_subtype(supertype->payload.qualified_type.type, type->payload.qualified_type.type); } case RecordType_TAG: { const Nodes* supermembers = &supertype->payload.record_type.members; @@ -42,7 +42,7 @@ bool is_subtype(const Type* supertype, const Type* type) { if (supermembers->count != members->count) return false; for (size_t i = 0; i < members->count; i++) { - if (!is_subtype(supermembers->nodes[i], members->nodes[i])) + if (!shd_is_subtype(supermembers->nodes[i], members->nodes[i])) return false; } return supertype->payload.record_type.special == type->payload.record_type.special; @@ -52,7 +52,7 @@ bool is_subtype(const Type* supertype, const Type* type) { const Nodes* params = &type->payload.join_point_type.yield_types; if (params->count != superparams->count) return false; for (size_t i = 0; i < params->count; i++) { - if (!is_subtype(params->nodes[i], superparams->nodes[i])) + if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) return false; } return true; @@ -62,14 +62,14 @@ bool is_subtype(const Type* supertype, const Type* type) { if (supertype->payload.fn_type.return_types.count != type->payload.fn_type.return_types.count) return false; for (size_t i = 0; i < type->payload.fn_type.return_types.count; i++) - if (!is_subtype(supertype->payload.fn_type.return_types.nodes[i], type->payload.fn_type.return_types.nodes[i])) + if (!shd_is_subtype(supertype->payload.fn_type.return_types.nodes[i], type->payload.fn_type.return_types.nodes[i])) return false; // check params const Nodes* superparams = &supertype->payload.fn_type.param_types; const Nodes* params = &type->payload.fn_type.param_types; if (params->count != superparams->count) return false; for (size_t i = 0; i < params->count; i++) { - if (!is_subtype(params->nodes[i], superparams->nodes[i])) + if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) return false; } return true; @@ -79,7 +79,7 @@ bool is_subtype(const Type* supertype, const Type* type) { const Nodes* params = &type->payload.bb_type.param_types; if (params->count != superparams->count) return false; for (size_t i = 0; i < params->count; i++) { - if (!is_subtype(params->nodes[i], superparams->nodes[i])) + if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) return false; } return true; @@ -89,7 +89,7 @@ bool is_subtype(const Type* supertype, const Type* type) { const Nodes* params = &type->payload.lam_type.param_types; if (params->count != superparams->count) return false; for (size_t i = 0; i < params->count; i++) { - if (!is_subtype(params->nodes[i], superparams->nodes[i])) + if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) return false; } return true; @@ -98,11 +98,11 @@ bool is_subtype(const Type* supertype, const Type* type) { return false; if (!supertype->payload.ptr_type.is_reference && type->payload.ptr_type.is_reference) return false; - return is_subtype(supertype->payload.ptr_type.pointed_type, type->payload.ptr_type.pointed_type); + return shd_is_subtype(supertype->payload.ptr_type.pointed_type, type->payload.ptr_type.pointed_type); } case Int_TAG: return supertype->payload.int_type.width == type->payload.int_type.width && supertype->payload.int_type.is_signed == type->payload.int_type.is_signed; case ArrType_TAG: { - if (!is_subtype(supertype->payload.arr_type.element_type, type->payload.arr_type.element_type)) + if (!shd_is_subtype(supertype->payload.arr_type.element_type, type->payload.arr_type.element_type)) return false; // unsized arrays are supertypes of sized arrays (even though they're not datatypes...) // TODO: maybe change this so it's only valid when talking about to pointer-to-arrays @@ -112,7 +112,7 @@ bool is_subtype(const Type* supertype, const Type* type) { return supertype->payload.arr_type.size == type->payload.arr_type.size || !supertype->payload.arr_type.size; } case PackType_TAG: { - if (!is_subtype(supertype->payload.pack_type.element_type, type->payload.pack_type.element_type)) + if (!shd_is_subtype(supertype->payload.pack_type.element_type, type->payload.pack_type.element_type)) return false; return supertype->payload.pack_type.width == type->payload.pack_type.width; } @@ -120,7 +120,7 @@ bool is_subtype(const Type* supertype, const Type* type) { return supertype->payload.type_decl_ref.decl == type->payload.type_decl_ref.decl; } case Type_ImageType_TAG: { - if (!is_subtype(supertype->payload.image_type.sampled_type, type->payload.image_type.sampled_type)) + if (!shd_is_subtype(supertype->payload.image_type.sampled_type, type->payload.image_type.sampled_type)) return false; if (supertype->payload.image_type.depth != type->payload.image_type.depth) return false; @@ -137,15 +137,15 @@ bool is_subtype(const Type* supertype, const Type* type) { return true; } case Type_SampledImageType_TAG: - return is_subtype(supertype->payload.sampled_image_type.image_type, type->payload.sampled_image_type.image_type); + return shd_is_subtype(supertype->payload.sampled_image_type.image_type, type->payload.sampled_image_type.image_type); default: break; } // Two types are always equal (and therefore subtypes of each other) if their payload matches return memcmp(&supertype->payload, &type->payload, sizeof(type->payload)) == 0; } -void check_subtype(const Type* supertype, const Type* type) { - if (!is_subtype(supertype, type)) { +void shd_check_subtype(const Type* supertype, const Type* type) { + if (!shd_is_subtype(supertype, type)) { shd_log_node(ERROR, type); shd_error_print(" isn't a subtype of "); shd_log_node(ERROR, supertype); @@ -168,7 +168,7 @@ size_t shd_get_type_bitwidth(const Type* t) { return SIZE_MAX; } -bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { +bool shd_is_addr_space_uniform(IrArena* arena, AddressSpace as) { switch (as) { case AsGeneric: case AsInput: @@ -179,7 +179,7 @@ bool is_addr_space_uniform(IrArena* arena, AddressSpace as) { } } -const Type* get_actual_mask_type(IrArena* arena) { +const Type* shd_get_actual_mask_type(IrArena* arena) { switch (arena->config.specializations.subgroup_mask_representation) { case SubgroupMaskAbstract: return mask_type(arena); case SubgroupMaskInt64: return shd_uint64_type(arena); @@ -187,7 +187,7 @@ const Type* get_actual_mask_type(IrArena* arena) { } } -String name_type_safe(IrArena* arena, const Type* t) { +String shd_get_type_name(IrArena* arena, const Type* t) { switch (is_type(t)) { case NotAType: assert(false); case Type_MaskType_TAG: return "mask_t"; @@ -452,7 +452,7 @@ const Type* check_type_composite(IrArena* arena, Composite composite) { for (size_t i = 0; i < composite.contents.count; i++) { const Type* element_type = composite.contents.nodes[i]->type; is_uniform &= deconstruct_qualified_type(&element_type); - assert(is_subtype(expected_member_types.nodes[i], element_type)); + assert(shd_is_subtype(expected_member_types.nodes[i], element_type)); } return qualified_type(arena, (QualifiedType) { .is_uniform = is_uniform, @@ -479,7 +479,7 @@ const Type* check_type_fill(IrArena* arena, Fill payload) { const Node* element_t = get_fill_type_element_type(payload.type); const Node* value_t = payload.value->type; bool u = deconstruct_qualified_type(&value_t); - assert(is_subtype(element_t, value_t)); + assert(shd_is_subtype(element_t, value_t)); return qualified_type(arena, (QualifiedType) { .is_uniform = u, .type = payload.type @@ -759,7 +759,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(alternative_width == width); } - assert(is_subtype(bool_type(arena), condition_type)); + assert(shd_is_subtype(bool_type(arena), condition_type)); // todo find true supertype assert(are_types_identical(2, alternatives_types)); @@ -784,7 +784,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Node* inserted_data = prim_op.operands.nodes[1]; const Type* inserted_data_type = inserted_data->type; bool is_uniform = uniform & deconstruct_qualified_type(&inserted_data_type); - assert(is_subtype(t, inserted_data_type) && "inserting data into a composite, but it doesn't match the target and indices"); + assert(shd_is_subtype(t, inserted_data_type) && "inserting data into a composite, but it doesn't match the target and indices"); return qualified_type(arena, (QualifiedType) { .is_uniform = is_uniform, .type = get_unqualified_type(source->type), @@ -854,7 +854,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { // Mask management case empty_mask_op: { assert(prim_op.type_arguments.count == 0 && prim_op.operands.count == 0); - return shd_as_qualified_type(get_actual_mask_type(arena), true); + return shd_as_qualified_type(shd_get_actual_mask_type(arena), true); } case mask_is_thread_active_op: { assert(prim_op.type_arguments.count == 0); @@ -900,7 +900,7 @@ static void check_arguments_types_against_parameters_helper(Nodes param_types, N if (param_types.count != arg_types.count) shd_error("Mismatched number of arguments/parameters"); for (size_t i = 0; i < param_types.count; i++) - check_subtype(param_types.nodes[i], arg_types.nodes[i]); + shd_check_subtype(param_types.nodes[i], arg_types.nodes[i]); } /// Shared logic between indirect calls and tailcalls @@ -981,7 +981,7 @@ const Type* check_type_control(IrArena* arena, Control control) { Nodes join_point_yield_types = join_point_type->payload.join_point_type.yield_types; assert(join_point_yield_types.count == control.yield_types.count); for (size_t i = 0; i < control.yield_types.count; i++) { - assert(is_subtype(control.yield_types.nodes[i], join_point_yield_types.nodes[i])); + assert(shd_is_subtype(control.yield_types.nodes[i], join_point_yield_types.nodes[i])); } assert(get_abstraction_params(control.tail).count == control.yield_types.count); @@ -996,7 +996,7 @@ const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { assert(is_type(alloc.type)); return qualified_type(a, (QualifiedType) { - .is_uniform = is_addr_space_uniform(a, AsPrivate), + .is_uniform = shd_is_addr_space_uniform(a, AsPrivate), .type = ptr_type(a, (PtrType) { .pointed_type = alloc.type, .address_space = AsPrivate, @@ -1008,7 +1008,7 @@ const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { const Type* check_type_local_alloc(IrArena* a, LocalAlloc alloc) { assert(is_type(alloc.type)); return qualified_type(a, (QualifiedType) { - .is_uniform = is_addr_space_uniform(a, AsFunction), + .is_uniform = shd_is_addr_space_uniform(a, AsFunction), .type = ptr_type(a, (PtrType) { .pointed_type = alloc.type, .address_space = AsFunction, @@ -1027,7 +1027,7 @@ const Type* check_type_load(IrArena* a, Load load) { const Type* elem_type = node_ptr_type_->pointed_type; elem_type = maybe_packed_type_helper(elem_type, width); return shd_as_qualified_type(elem_type, - ptr_uniform && is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); + ptr_uniform && shd_is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); } const Type* check_type_store(IrArena* a, Store store) { @@ -1045,7 +1045,7 @@ const Type* check_type_store(IrArena* a, Store store) { .type = elem_type }); - assert(is_subtype(val_expected_type, store.value->type)); + assert(shd_is_subtype(val_expected_type, store.value->type)); return empty_multiple_return_type(a); } diff --git a/src/shady/check.h b/src/shady/check.h index 1925e35f0..4395223eb 100644 --- a/src/shady/check.h +++ b/src/shady/check.h @@ -3,8 +3,8 @@ #include "shady/ir.h" -bool is_subtype(const Type* supertype, const Type* type); -void check_subtype(const Type* supertype, const Type* type); +bool shd_is_subtype(const Type* supertype, const Type* type); +void shd_check_subtype(const Type* supertype, const Type* type); bool is_arithm_type(const Type*); bool is_shiftable_type(const Type*); diff --git a/src/shady/fold.c b/src/shady/fold.c index 4ae9a9c5c..f1d815d24 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -308,7 +308,7 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { if (!r) return node; - if (!is_subtype(node->type, r->type)) + if (!shd_is_subtype(node->type, r->type)) r = prim_op_helper(arena, convert_op, shd_singleton(get_unqualified_type(node->type)), shd_singleton(r)); return r; } @@ -464,7 +464,7 @@ const Node* _shd_fold_node(IrArena* arena, const Node* node) { if (is_terminator(original_node)) assert(is_terminator(node)); if (node->type) - assert(is_subtype(original_node->type, node->type)); + assert(shd_is_subtype(original_node->type, node->type)); return node; } diff --git a/src/shady/ir/type.c b/src/shady/ir/type.c index c934070ab..700ebd10e 100644 --- a/src/shady/ir/type.c +++ b/src/shady/ir/type.c @@ -38,7 +38,7 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { type = get_unqualified_type(type); } assert(type->tag == PtrType_TAG); - uniform &= is_addr_space_uniform(arena, type->payload.ptr_type.address_space); + uniform &= shd_is_addr_space_uniform(arena, type->payload.ptr_type.address_space); type = type->payload.ptr_type.pointed_type; if (qualified) diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 3477e4322..1520a778a 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -80,8 +80,8 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo IrArena* a = ctx->rewriter.dst_arena; String name; switch (which) { - case LoadFn: name = shd_fmt_string_irarena(a, "generated_load_Generic_%s%s", name_type_safe(a, t), uniform_ptr ? "_uniform" : ""); break; - case StoreFn: name = shd_fmt_string_irarena(a, "generated_store_Generic_%s", name_type_safe(a, t)); break; + case LoadFn: name = shd_fmt_string_irarena(a, "generated_load_Generic_%s%s", shd_get_type_name(a, t), uniform_ptr ? "_uniform" : ""); break; + case StoreFn: name = shd_fmt_string_irarena(a, "generated_store_Generic_%s", shd_get_type_name(a, t)); break; } const Node** found = shd_dict_find_value(String, const Node*, ctx->fns, name); @@ -207,7 +207,7 @@ static const Node* process(Context* ctx, const Node* old) { Load payload = old->payload.load; const Type* old_ptr_t = payload.ptr->type; bool u = deconstruct_qualified_type(&old_ptr_t); - u &= is_addr_space_uniform(a, old_ptr_t->payload.ptr_type.address_space); + u &= shd_is_addr_space_uniform(a, old_ptr_t->payload.ptr_type.address_space); if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { return call(a, (Call) { .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, LoadFn, u, shd_rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 91e8167bd..b7ed855c6 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -17,7 +17,7 @@ static const Node* process(Context* ctx, const Node* node) { IrArena* a = ctx->rewriter.dst_arena; switch (node->tag) { - case MaskType_TAG: return get_actual_mask_type(ctx->rewriter.dst_arena); + case MaskType_TAG: return shd_get_actual_mask_type(ctx->rewriter.dst_arena); case PrimOp_TAG: { Op op = node->payload.prim_op.op; Nodes old_nodes = node->payload.prim_op.operands; @@ -28,7 +28,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = begin_block_pure(a); const Node* mask = shd_rewrite_node(&ctx->rewriter, old_nodes.nodes[0]); const Node* index = shd_rewrite_node(&ctx->rewriter, old_nodes.nodes[1]); - index = gen_conversion(bb, get_actual_mask_type(ctx->rewriter.dst_arena), index); + index = gen_conversion(bb, shd_get_actual_mask_type(ctx->rewriter.dst_arena), index); const Node* acc = mask; // acc >>= index acc = gen_primop_ce(bb, rshift_logical_op, 2, (const Node* []) { acc, index }); @@ -54,7 +54,7 @@ Module* shd_pass_lower_mask(SHADY_UNUSED const CompilerConfig* config, Module* s IrArena* a = shd_new_ir_arena(&aconfig); Module* dst = shd_new_module(a, shd_module_get_name(src)); - const Type* mask_type = get_actual_mask_type(a); + const Type* mask_type = shd_get_actual_mask_type(a); assert(mask_type->tag == Int_TAG); Context ctx = { diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 65e186cb1..08799e6b5 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -22,7 +22,7 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { const Node* nul = gen_reinterpret_cast(bb, t, shd_uint64_literal(a, 0)); Node* decl = constant(ctx->rewriter.dst_module, shd_singleton(annotation(a, (Annotation) { .name = "Generated", - })), t, shd_fmt_string_irarena(a, "nullptr_%s", name_type_safe(a, t))); + })), t, shd_fmt_string_irarena(a, "nullptr_%s", shd_get_type_name(a, t))); decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(nul)); const Node* ref = ref_decl_helper(a, decl); shd_dict_insert(const Type*, const Node*, ctx->map, t, ref); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 3e7b0fd7e..eedf69531 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -261,14 +261,14 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Type* emulated_ptr_type = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); const Node* address_param = param(a, qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || uniform_address, .type = emulated_ptr_type }), "ptr"); - const Type* input_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && is_addr_space_uniform(a, as) && false), .type = element_type }); + const Type* input_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && shd_is_addr_space_uniform(a, as) && false), .type = element_type }); const Node* value_param = ser ? param(a, input_value_t, "value") : NULL; Nodes params = ser ? mk_nodes(a, address_param, value_param) : shd_singleton(address_param); - const Type* return_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && is_addr_space_uniform(a, as)), .type = element_type }); + const Type* return_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && shd_is_addr_space_uniform(a, as)), .type = element_type }); Nodes return_ts = ser ? shd_empty(a) : shd_singleton(return_value_t); - String name = shd_format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", get_address_space_name(as), uniform_address ? "uniform" : "varying", name_type_safe(a, element_type)); + String name = shd_format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", get_address_space_name(as), uniform_address ? "uniform" : "varying", shd_get_type_name(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index d1d034a9b..e25c65d55 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -38,7 +38,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { const Node* value_param = push ? param(a, qualified_t, "value") : NULL; Nodes params = push ? shd_singleton(value_param) : shd_empty(a); Nodes return_ts = push ? shd_empty(a) : shd_singleton(qualified_t); - String name = shd_format_string_arena(a->arena, "generated_%s_%s", push ? "push" : "pop", name_type_safe(a, element_type)); + String name = shd_format_string_arena(a->arena, "generated_%s_%s", push ? "push" : "pop", shd_get_type_name(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 05cf8fcfb..389c6c1f6 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -117,7 +117,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod fn = *found; else { const Node* src_param = param(a, shd_as_qualified_type(t, false), "src"); - fn = function(m, shd_singleton(src_param), shd_fmt_string_irarena(a, "subgroup_first_%s", name_type_safe(a, t)), + fn = function(m, shd_singleton(src_param), shd_fmt_string_irarena(a, "subgroup_first_%s", shd_get_type_name(a, t)), mk_nodes(a, annotation(a, (Annotation) { .name = "Generated"}), annotation(a, (Annotation) { .name = "Leaf" })), shd_singleton( shd_as_qualified_type(t, true))); shd_dict_insert(const Node*, Node*, ctx->fns, t, fn); From 356af2d204014cdb13dd7b7f2eb10153095edc6d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 9 Oct 2024 17:34:51 +0200 Subject: [PATCH 642/693] prefix more type-related stuff, move it to type.h --- include/shady/ir/type.h | 46 +- src/backend/c/emit_c.c | 8 +- src/backend/c/emit_c_control_flow.c | 2 +- src/backend/c/emit_c_value.c | 36 +- src/backend/spirv/emit_spv.c | 2 +- src/backend/spirv/emit_spv_control_flow.c | 6 +- src/backend/spirv/emit_spv_type.c | 4 +- src/backend/spirv/emit_spv_value.c | 18 +- src/frontend/llvm/l2s_postprocess.c | 2 +- src/frontend/slim/infer.c | 40 +- src/frontend/slim/parser.c | 2 +- src/frontend/spirv/s2s.c | 4 +- src/runtime/vulkan/vk_runtime_program.c | 4 +- src/shady/analysis/literal.c | 2 +- src/shady/analysis/verify.c | 4 +- src/shady/body_builder.c | 2 +- src/shady/check.c | 486 ++++---------------- src/shady/check.h | 14 - src/shady/fold.c | 22 +- src/shady/generator_node.c | 2 +- src/shady/ir/composite.c | 6 +- src/shady/ir/type.c | 356 +++++++++++++- src/shady/passes/lift_indirect_targets.c | 6 +- src/shady/passes/lower_alloca.c | 2 +- src/shady/passes/lower_callf.c | 12 +- src/shady/passes/lower_cf_instrs.c | 4 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 8 +- src/shady/passes/lower_int64.c | 2 +- src/shady/passes/lower_lea.c | 8 +- src/shady/passes/lower_logical_pointers.c | 16 +- src/shady/passes/lower_memcpy.c | 8 +- src/shady/passes/lower_physical_ptrs.c | 20 +- src/shady/passes/lower_stack.c | 6 +- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_tailcalls.c | 8 +- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/normalize_builtins.c | 4 +- src/shady/passes/opt_demote_alloca.c | 12 +- src/shady/passes/opt_inline.c | 2 +- src/shady/passes/opt_mem2reg.c | 6 +- src/shady/passes/reconvergence_heuristics.c | 14 +- src/shady/passes/restructure.c | 2 +- src/shady/passes/scope2control.c | 6 +- src/shady/print.c | 6 +- src/shady/transform/ir_gen_helpers.c | 12 +- src/shady/transform/memory_layout.c | 17 +- 47 files changed, 636 insertions(+), 619 deletions(-) diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index 7f110806c..33d1fceee 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -15,21 +15,35 @@ Type* nominal_type(Module*, Nodes annotations, String name); const Type* shd_get_actual_mask_type(IrArena* arena); -String get_address_space_name(AddressSpace); -/// Returns false iff pointers in that address space can contain different data at the same address -/// (amongst threads in the same subgroup) -bool shd_is_addr_space_uniform(IrArena*, AddressSpace); - -String shd_get_type_name(IrArena* arena, const Type* t); +bool shd_is_subtype(const Type* supertype, const Type* type); +void shd_check_subtype(const Type* supertype, const Type* type); /// Is this a type that a value in the language can have ? -bool is_value_type(const Type*); +bool shd_is_value_type(const Type*); /// Is this a valid data type (for usage in other types and as type arguments) ? -bool is_data_type(const Type*); +bool shd_is_data_type(const Type*); + +bool shd_is_arithm_type(const Type*); +bool shd_is_shiftable_type(const Type*); +bool shd_has_boolean_ops(const Type*); +bool shd_is_comparable_type(const Type*); +bool shd_is_ordered_type(const Type*); +bool shd_is_physical_ptr_type(const Type* t); +bool shd_is_generic_ptr_type(const Type* t); + +bool shd_is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type); +bool shd_is_conversion_legal(const Type* src_type, const Type* dst_type); /// Returns the (possibly qualified) pointee type from a (possibly qualified) ptr type -const Type* get_pointee_type(IrArena*, const Type*); +const Type* shd_get_pointee_type(IrArena*, const Type*); + +String shd_get_address_space_name(AddressSpace); +/// Returns false iff pointers in that address space can contain different data at the same address +/// (amongst threads in the same subgroup) +bool shd_is_addr_space_uniform(IrArena*, AddressSpace); + +String shd_get_type_name(IrArena* arena, const Type* t); const Type* maybe_multiple_return(IrArena* arena, Nodes types); Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); @@ -37,20 +51,20 @@ Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); /// Collects the annotated types in the list of variables /// NB: this is different from get_values_types, that function uses node.type, whereas this one uses node.payload.var.type /// This means this function works in untyped modules where node.type is NULL. -Nodes get_param_types(IrArena* arena, Nodes variables); +Nodes shd_get_param_types(IrArena* arena, Nodes variables); -Nodes get_values_types(IrArena*, Nodes); +Nodes shd_get_values_types(IrArena*, Nodes); // Qualified type helpers /// Ensures an operand has divergence-annotated type and extracts it -const Type* get_unqualified_type(const Type*); -bool is_qualified_type_uniform(const Type*); -bool deconstruct_qualified_type(const Type**); +const Type* shd_get_unqualified_type(const Type*); +bool shd_is_qualified_type_uniform(const Type*); +bool shd_deconstruct_qualified_type(const Type**); const Type* shd_as_qualified_type(const Type* type, bool uniform); -Nodes strip_qualifiers(IrArena*, Nodes); -Nodes add_qualifiers(IrArena*, Nodes, bool); +Nodes shd_strip_qualifiers(IrArena*, Nodes); +Nodes shd_add_qualifiers(IrArena*, Nodes, bool); // Pack (vector) type helpers const Type* get_packed_type_element(const Type*); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 1fff77986..012357700 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -189,8 +189,8 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String break; } default: { - prefix = shd_format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); - shd_warn_print("warning: address space %s not supported in CUDA for global variables\n", get_address_space_name(as)); + prefix = shd_format_string_arena(emitter->arena->arena, "/* %s */", shd_get_address_space_name(as)); + shd_warn_print("warning: address space %s not supported in CUDA for global variables\n", shd_get_address_space_name(as)); break; } } @@ -209,8 +209,8 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String break; } default: { - prefix = shd_format_string_arena(emitter->arena->arena, "/* %s */", get_address_space_name(as)); - shd_warn_print("warning: address space %s not supported in GLSL for global variables\n", get_address_space_name(as)); + prefix = shd_format_string_arena(emitter->arena->arena, "/* %s */", shd_get_address_space_name(as)); + shd_warn_print("warning: address space %s not supported in GLSL for global variables\n", shd_get_address_space_name(as)); break; } } diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index fef859080..675795a06 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -148,7 +148,7 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { arr[i] = unique_name(emitter->arena, "phi"); } Strings param_names = shd_strings(emitter->arena, variables.count, arr); - Strings eparams = emit_variable_declarations(emitter, fn, p, NULL, ¶m_names, get_param_types(emitter->arena, params), true, &loop.initial_args); + Strings eparams = emit_variable_declarations(emitter, fn, p, NULL, ¶m_names, shd_get_param_types(emitter->arena, params), true, &loop.initial_args); for (size_t i = 0; i < params.count; i++) register_emitted(&sub_emiter, fn, params.nodes[i], term_from_cvalue(eparams.strings[i])); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 52d46ee75..b5e74b49d 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -246,7 +246,7 @@ CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CT static const Type* get_first_op_scalar_type(Nodes ops) { const Type* t = shd_first(ops)->type; - deconstruct_qualified_type(&t); + shd_deconstruct_qualified_type(&t); deconstruct_maybe_packed_type(&t); return t; } @@ -495,7 +495,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node const Node* offset = prim_op->operands.nodes[1]; CValue c_offset = to_cvalue(emitter, c_emit_value(emitter, fn, offset)); if (emitter->config.dialect == CDialect_GLSL) { - if (get_unqualified_type(offset->type)->payload.int_type.width == IntTy64) + if (shd_get_unqualified_type(offset->type)->payload.int_type.width == IntTy64) c_offset = shd_format_string_arena(arena->arena, "int(%s)", c_offset); } term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s %s %s)", src, prim_op->op == lshift_op ? "<<" : ">>", c_offset)); @@ -527,7 +527,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } case convert_op: { CTerm src = c_emit_value(emitter, fn, shd_first(prim_op->operands)); - const Type* src_type = get_unqualified_type(shd_first(prim_op->operands)->type); + const Type* src_type = shd_get_unqualified_type(shd_first(prim_op->operands)->type); const Type* dst_type = shd_first(prim_op->type_arguments); if (emitter->config.dialect == CDialect_GLSL) { if (is_glsl_scalar_type(src_type) && is_glsl_scalar_type(dst_type)) { @@ -543,7 +543,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } case reinterpret_op: { CTerm src_value = c_emit_value(emitter, fn, shd_first(prim_op->operands)); - const Type* src_type = get_unqualified_type(shd_first(prim_op->operands)->type); + const Type* src_type = shd_get_unqualified_type(shd_first(prim_op->operands)->type); const Type* dst_type = shd_first(prim_op->type_arguments); switch (emitter->config.dialect) { case CDialect_CUDA: @@ -625,7 +625,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node term = term_from_cvalue(dst); } - const Type* t = get_unqualified_type(shd_first(prim_op->operands)->type); + const Type* t = shd_get_unqualified_type(shd_first(prim_op->operands)->type); for (size_t i = (insert ? 2 : 1); i < prim_op->operands.count; i++) { const Node* index = prim_op->operands.nodes[i]; const IntLiteral* static_index = shd_resolve_to_int_literal(index); @@ -678,8 +678,8 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node String rhs_e = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); const Type* lhs_t = lhs->type; const Type* rhs_t = rhs->type; - bool lhs_u = deconstruct_qualified_type(&lhs_t); - bool rhs_u = deconstruct_qualified_type(&rhs_t); + bool lhs_u = shd_deconstruct_qualified_type(&lhs_t); + bool rhs_u = shd_deconstruct_qualified_type(&rhs_t); size_t left_size = lhs_t->payload.pack_type.width; // size_t total_size = lhs_t->payload.pack_type.width + rhs_t->payload.pack_type.width; String suffixes = "xyzw"; @@ -793,13 +793,13 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer CTerm acc = c_emit_value(emitter, fn, lea.ptr); const Type* src_qtype = lea.ptr->type; - bool uniform = is_qualified_type_uniform(src_qtype); - const Type* curr_ptr_type = get_unqualified_type(src_qtype); + bool uniform = shd_is_qualified_type_uniform(src_qtype); + const Type* curr_ptr_type = shd_get_unqualified_type(src_qtype); assert(curr_ptr_type->tag == PtrType_TAG); - const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); + const Type* pointee_type = shd_get_pointee_type(arena, curr_ptr_type); const Node* selector = lea.index; - uniform &= is_qualified_type_uniform(selector->type); + uniform &= shd_is_qualified_type_uniform(selector->type); switch (is_type(pointee_type)) { case ArrType_TAG: { CTerm index = c_emit_value(emitter, fn, selector); @@ -859,8 +859,8 @@ static CTerm emit_ptr_array_element_offset(Emitter* emitter, FnEmitter* fn, Prin CTerm acc = c_emit_value(emitter, fn, lea.ptr); const Type* src_qtype = lea.ptr->type; - bool uniform = is_qualified_type_uniform(src_qtype); - const Type* curr_ptr_type = get_unqualified_type(src_qtype); + bool uniform = shd_is_qualified_type_uniform(src_qtype); + const Type* curr_ptr_type = shd_get_unqualified_type(src_qtype); assert(curr_ptr_type->tag == PtrType_TAG); const IntLiteral* offset_static_value = shd_resolve_to_int_literal(lea.offset); @@ -869,9 +869,9 @@ static CTerm emit_ptr_array_element_offset(Emitter* emitter, FnEmitter* fn, Prin // we sadly need to drop to the value level (aka explicit pointer arithmetic) to do this // this means such code is never going to be legal in GLSL // also the cast is to account for our arrays-in-structs hack - const Type* pointee_type = get_pointee_type(arena, curr_ptr_type); + const Type* pointee_type = shd_get_pointee_type(arena, curr_ptr_type); acc = term_from_cvalue(shd_format_string_arena(arena->arena, "((%s) &(%s)[%s])", c_emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); - uniform &= is_qualified_type_uniform(lea.offset->type); + uniform &= shd_is_qualified_type_uniform(lea.offset->type); } if (emitter->config.dialect == CDialect_ISPC) @@ -893,7 +893,7 @@ static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* instr) { CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; c_emit_variable_declaration(emitter, p, get_allocated_type(instr), variable_name, true, NULL); if (emitter->config.dialect == CDialect_ISPC) { - variable = ispc_varying_ptr_helper(emitter, p, get_unqualified_type(instr->type), variable); + variable = ispc_varying_ptr_helper(emitter, p, shd_get_unqualified_type(instr->type), variable); } return variable; } @@ -927,8 +927,8 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const Store payload = instruction->payload.store; c_emit_mem(emitter, fn, payload.mem); const Type* addr_type = payload.ptr->type; - bool addr_uniform = deconstruct_qualified_type(&addr_type); - bool value_uniform = is_qualified_type_uniform(payload.value->type); + bool addr_uniform = shd_deconstruct_qualified_type(&addr_type); + bool value_uniform = shd_is_qualified_type_uniform(payload.value->type); assert(addr_type->tag == PtrType_TAG); CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, fn, payload.ptr)); CValue cvalue = to_cvalue(emitter, c_emit_value(emitter, fn, payload.value)); diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 6d0a0ea0f..e851dcbcc 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -94,7 +94,7 @@ static void emit_function(Emitter* emitter, const Node* node) { const Type* param_type = param->payload.param.type; SpvId param_id = spvb_parameter(fn_builder.base, spv_emit_type(emitter, param_type)); spv_register_emitted(emitter, false, param, param_id); - deconstruct_qualified_type(¶m_type); + shd_deconstruct_qualified_type(¶m_type); if (param_type->tag == PtrType_TAG && param_type->payload.ptr_type.address_space == AsGlobal) { spvb_decorate(emitter->file_builder, param_id, SpvDecorationAliased, 0, NULL); } diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index e5e28c61d..1a0a3999b 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -52,13 +52,13 @@ static void emit_match(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_bui spv_emit_mem(emitter, fn_builder, match.mem); SpvId join_bb_id = spv_find_emitted(emitter, fn_builder, match.tail); - assert(get_unqualified_type(match.inspect->type)->tag == Int_TAG); + assert(shd_get_unqualified_type(match.inspect->type)->tag == Int_TAG); SpvId inspectee = spv_emit_value(emitter, fn_builder, match.inspect); SpvId default_id = spv_find_emitted(emitter, fn_builder, match.default_case); const Type* inspectee_t = match.inspect->type; - deconstruct_qualified_type(&inspectee_t); + shd_deconstruct_qualified_type(&inspectee_t); assert(inspectee_t->tag == Int_TAG); size_t literal_width = inspectee_t->payload.int_type.width == IntTy64 ? 2 : 1; size_t literal_case_entry_size = literal_width + 1; @@ -93,7 +93,7 @@ static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_buil Nodes body_params = get_abstraction_params(loop_instr.body); LARRAY(SpvbPhi*, loop_continue_phis, body_params.count); for (size_t i = 0; i < body_params.count; i++) { - SpvId loop_param_type = spv_emit_type(emitter, get_unqualified_type(body_params.nodes[i]->type)); + SpvId loop_param_type = spv_emit_type(emitter, shd_get_unqualified_type(body_params.nodes[i]->type)); SpvId continue_phi_id = spvb_fresh_id(emitter->file_builder); SpvbPhi* continue_phi = spvb_add_phi(continue_builder, loop_param_type, continue_phi_id); diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index 91a4257e0..f2f734671 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -32,7 +32,7 @@ SpvStorageClass spv_emit_addr_space(Emitter* emitter, AddressSpace address_space case AsUniformConstant: return SpvStorageClassUniformConstant; default: { - shd_error_print("Cannot emit address space %s.\n", get_address_space_name(address_space)); + shd_error_print("Cannot emit address space %s.\n", shd_get_address_space_name(address_space)); shd_error_die(); SHADY_UNREACHABLE; } @@ -215,7 +215,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { case Type_JoinPointType_TAG: shd_error("These must be lowered beforehand") } - if (is_data_type(type)) { + if (shd_is_data_type(type)) { if (type->tag == PtrType_TAG && type->payload.ptr_type.address_space == AsGlobal) { //TypeMemLayout elem_mem_layout = get_mem_layout(emitter->arena, type->payload.ptr_type.pointed_type); //spvb_decorate(emitter->file_builder, new, SpvDecorationArrayStride, 1, (uint32_t[]) {elem_mem_layout.size_in_bytes}); diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 3a7a803f0..78ca71cd6 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -34,7 +34,7 @@ typedef enum { } OperandClass; static OperandClass classify_operand_type(const Type* type) { - assert(is_type(type) && is_data_type(type)); + assert(is_type(type) && shd_is_data_type(type)); if (type->tag == PackType_TAG) return classify_operand_type(type->payload.pack_type.element_type); @@ -146,8 +146,8 @@ static const IselTableEntry isel_table[] = { static const Type* get_result_t(Emitter* emitter, IselTableEntry entry, Nodes args, Nodes type_arguments) { switch (entry.result_kind) { - case Same: return get_unqualified_type(shd_first(args)->type); - case SameTuple: return record_type(emitter->arena, (RecordType) { .members = mk_nodes(emitter->arena, get_unqualified_type(shd_first(args)->type), get_unqualified_type(shd_first(args)->type)) }); + case Same: return shd_get_unqualified_type(shd_first(args)->type); + case SameTuple: return record_type(emitter->arena, (RecordType) { .members = mk_nodes(emitter->arena, shd_get_unqualified_type(shd_first(args)->type), shd_get_unqualified_type(shd_first(args)->type)) }); case Bool: return bool_type(emitter->arena); case TyOperand: return shd_first(type_arguments); case Void: return unit_type(emitter->arena); @@ -160,13 +160,13 @@ static SpvOp get_opcode(SHADY_UNUSED Emitter* emitter, IselTableEntry entry, Nod case Monomorphic: return entry.op; case FirstOp: { assert(args.count >= 1); - OperandClass op_class = classify_operand_type(get_unqualified_type(shd_first(args)->type)); + OperandClass op_class = classify_operand_type(shd_get_unqualified_type(shd_first(args)->type)); return entry.fo[op_class]; } case FirstAndResult: { assert(args.count >= 1); assert(type_arguments.count == 1); - OperandClass op_class = classify_operand_type(get_unqualified_type(shd_first(args)->type)); + OperandClass op_class = classify_operand_type(shd_get_unqualified_type(shd_first(args)->type)); OperandClass return_t_class = classify_operand_type(shd_first(type_arguments)); return entry.foar[op_class][return_t_class]; } @@ -212,7 +212,7 @@ static SpvId emit_primop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_b switch (the_op.op) { case reinterpret_op: { const Type* dst = shd_first(the_op.type_arguments); - const Type* src = get_unqualified_type(shd_first(the_op.operands)->type); + const Type* src = shd_get_unqualified_type(shd_first(the_op.operands)->type); assert(dst->tag == PtrType_TAG && src->tag == PtrType_TAG); assert(src != dst); return spvb_op(bb_builder, SpvOpBitcast, spv_emit_type(emitter, dst), 1, (SpvId[]) {spv_emit_value(emitter, fn_builder, shd_first(the_op.operands)) }); @@ -295,7 +295,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b assert(instr.operands.count == 2); // SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, int32_literal(emitter->arena, SpvScopeSubgroup)); // ad-hoc extension for my sanity - if (get_unqualified_type(instr.result_t) == shd_get_actual_mask_type(emitter->arena)) { + if (shd_get_unqualified_type(instr.result_t) == shd_get_actual_mask_type(emitter->arena)) { const Type* i32x4 = pack_type(emitter->arena, (PackType) { .width = 4, .element_type = shd_uint32_type(emitter->arena) }); SpvId raw_result = spvb_group_ballot(bb_builder, spv_emit_type(emitter, i32x4), spv_emit_value(emitter, fn_builder, instr.operands.nodes[1]), spv_emit_value(emitter, fn_builder, shd_first(instr.operands))); // TODO: why are we doing this in SPIR-V and not the IR ? @@ -387,7 +387,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui Load payload = instruction->payload.load; spv_emit_mem(emitter, fn_builder, payload.mem); const Type* ptr_type = payload.ptr->type; - deconstruct_qualified_type(&ptr_type); + shd_deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); const Type* elem_type = ptr_type->payload.ptr_type.pointed_type; @@ -408,7 +408,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui Store payload = instruction->payload.store; spv_emit_mem(emitter, fn_builder, payload.mem); const Type* ptr_type = payload.ptr->type; - deconstruct_qualified_type(&ptr_type); + shd_deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); const Type* elem_type = ptr_type->payload.ptr_type.pointed_type; diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 4f2aa2833..c263051b9 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -73,7 +73,7 @@ static const Node* process_node(Context* ctx, const Node* node) { } else if (strcmp(get_annotation_name(an->payload), "EntryPoint") == 0) { for (size_t i = 0; i < new_params.count; i++) new_params = shd_change_node_at_index(a, new_params, i, param(a, shd_as_qualified_type( - get_unqualified_type(new_params.nodes[i]->payload.param.type), true), new_params.nodes[i]->payload.param.name)); + shd_get_unqualified_type(new_params.nodes[i]->payload.param.type), true), new_params.nodes[i]->payload.param.name)); } old_annotations = shd_nodes_append(a, old_annotations, an->payload); an = an->next; diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 971265a33..0ba5b2a24 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -14,7 +14,7 @@ static Nodes annotate_all_types(IrArena* a, Nodes types, bool uniform_by_default) { LARRAY(const Type*, ntypes, types.count); for (size_t i = 0; i < types.count; i++) { - if (is_data_type(types.nodes[i])) + if (shd_is_data_type(types.nodes[i])) ntypes[i] = qualified_type(a, (QualifiedType) { .type = types.nodes[i], .is_uniform = uniform_by_default, @@ -113,7 +113,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { const Type* imported_hint = infer(ctx, oconstant->type_hint, NULL); const Node* instruction = NULL; if (imported_hint) { - assert(is_data_type(imported_hint)); + assert(shd_is_data_type(imported_hint)); const Node* s = shd_as_qualified_type(imported_hint, true); if (oconstant->value) instruction = infer(ctx, oconstant->value, s); @@ -121,7 +121,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { instruction = infer(ctx, oconstant->value, NULL); } if (instruction) - imported_hint = get_unqualified_type(instruction->type); + imported_hint = shd_get_unqualified_type(instruction->type); assert(imported_hint); Node* nconstant = constant(ctx->rewriter.dst_module, infer_nodes(ctx, oconstant->annotations), imported_hint, oconstant->name); @@ -152,8 +152,8 @@ static const Node* infer_decl(Context* ctx, const Node* node) { /// Like get_unqualified_type but won't error out if type wasn't qualified to begin with static const Type* remove_uniformity_qualifier(const Node* type) { - if (is_value_type(type)) - return get_unqualified_type(type); + if (shd_is_value_type(type)) + return shd_get_unqualified_type(type); return type; } @@ -169,7 +169,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec const Type* type = infer(ctx, node->payload.constrained.type, NULL); bool expect_uniform = false; if (expected_type) { - expect_uniform = deconstruct_qualified_type(&expected_type); + expect_uniform = shd_deconstruct_qualified_type(&expected_type); assert(shd_is_subtype(expected_type, type)); } return infer(ctx, node->payload.constrained.value, shd_as_qualified_type(type, expect_uniform)); @@ -237,9 +237,9 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec const Node* elem_type = infer(ctx, node->payload.composite.type, NULL); bool uniform = false; if (elem_type && expected_type) { - assert(shd_is_subtype(get_unqualified_type(expected_type), elem_type)); + assert(shd_is_subtype(shd_get_unqualified_type(expected_type), elem_type)); } else if (expected_type) { - uniform = deconstruct_qualified_type(&elem_type); + uniform = shd_deconstruct_qualified_type(&elem_type); elem_type = expected_type; } @@ -257,7 +257,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec // Composites are tuples by default if (!elem_type) - elem_type = record_type(a, (RecordType) { .members = strip_qualifiers(a, get_values_types(a, nmembers)) }); + elem_type = record_type(a, (RecordType) { .members = shd_strip_qualifiers(a, shd_get_values_types(a, nmembers)) }); return composite_helper(a, elem_type, nmembers); } @@ -266,9 +266,9 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec assert(composite_t); bool uniform = false; if (composite_t && expected_type) { - assert(shd_is_subtype(get_unqualified_type(expected_type), composite_t)); + assert(shd_is_subtype(shd_get_unqualified_type(expected_type), composite_t)); } else if (expected_type) { - uniform = deconstruct_qualified_type(&composite_t); + uniform = shd_deconstruct_qualified_type(&composite_t); composite_t = expected_type; } assert(composite_t); @@ -357,11 +357,11 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe case reinterpret_op: case convert_op: { new_operands[0] = infer(ctx, old_operands.nodes[0], NULL); - const Type* src_pointer_type = get_unqualified_type(new_operands[0]->type); + const Type* src_pointer_type = shd_get_unqualified_type(new_operands[0]->type); const Type* old_dst_pointer_type = shd_first(old_type_args); const Type* dst_pointer_type = shd_first(type_args); - if (is_generic_ptr_type(src_pointer_type) != is_generic_ptr_type(dst_pointer_type)) + if (shd_is_generic_ptr_type(src_pointer_type) != shd_is_generic_ptr_type(dst_pointer_type)) op = convert_op; goto rebuild; @@ -402,7 +402,7 @@ static const Node* infer_indirect_call(Context* ctx, const Node* node, const Nod assert(is_value(new_callee)); LARRAY(const Node*, new_args, node->payload.call.args.count); - const Type* callee_type = get_unqualified_type(new_callee->type); + const Type* callee_type = shd_get_unqualified_type(new_callee->type); if (callee_type->tag != PtrType_TAG) shd_error("functions are called through function pointers"); callee_type = callee_type->payload.ptr_type.pointed_type; @@ -433,7 +433,7 @@ static const Node* infer_if(Context* ctx, const Node* node) { Nodes join_types = infer_nodes(ctx, node->payload.if_instr.yield_types); Context infer_if_body_ctx = *ctx; // When we infer the types of the arguments to a call to merge(), they are expected to be varying - Nodes expected_join_types = add_qualifiers(a, join_types, false); + Nodes expected_join_types = shd_add_qualifiers(a, join_types, false); const Node* true_body = infer_case(&infer_if_body_ctx, node->payload.if_instr.if_true, shd_nodes(a, 0, NULL)); // don't allow seeing the variables made available in the true branch @@ -458,7 +458,7 @@ static const Node* infer_loop(Context* ctx, const Node* node) { const Node* old_body = node->payload.loop_instr.body; Nodes old_params = get_abstraction_params(old_body); - Nodes old_params_types = get_param_types(a, old_params); + Nodes old_params_types = shd_get_param_types(a, old_params); Nodes new_params_types = infer_nodes(ctx, old_params_types); new_params_types = annotate_all_types(a, new_params_types, false); @@ -468,7 +468,7 @@ static const Node* infer_loop(Context* ctx, const Node* node) { new_initial_args[i] = infer(ctx, old_initial_args.nodes[i], new_params_types.nodes[i]); Nodes loop_yield_types = infer_nodes(ctx, node->payload.loop_instr.yield_types); - Nodes qual_yield_types = add_qualifiers(a, loop_yield_types, false); + Nodes qual_yield_types = shd_add_qualifiers(a, loop_yield_types, false); const Node* nbody = infer_case(&loop_body_ctx, old_body, new_params_types); // TODO check new body params match continue types @@ -524,7 +524,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* case Instruction_Store_TAG: { Store payload = node->payload.store; const Node* ptr = infer(ctx, payload.ptr, NULL); - const Type* ptr_type = get_unqualified_type(ptr->type); + const Type* ptr_type = shd_get_unqualified_type(ptr->type); assert(ptr_type->tag == PtrType_TAG); const Type* element_t = ptr_type->payload.ptr_type.pointed_type; assert(element_t); @@ -534,7 +534,7 @@ static const Node* infer_instruction(Context* ctx, const Node* node, const Type* case Instruction_StackAlloc_TAG: { const Type* element_type = node->payload.stack_alloc.type; assert(is_type(element_type)); - assert(is_data_type(element_type)); + assert(shd_is_data_type(element_type)); return stack_alloc(a, (StackAlloc) { .type = infer_type(ctx, element_type), .mem = infer(ctx, node->payload.stack_alloc.mem, NULL) }); } default: break; @@ -586,7 +586,7 @@ static const Node* process(Context* src_ctx, const Node* node) { return infer_instruction(&ctx, node, NULL); } else if (is_value(node)) { const Node* value = infer_value(&ctx, node, expected_type); - assert(is_value_type(value->type)); + assert(shd_is_value_type(value->type)); return value; } else if (is_terminator(node)) { assert(expected_type == NULL); diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index abcb00d78..8491d01f1 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -1171,7 +1171,7 @@ static const Node* accept_global_var_decl(ctxparams, Nodes annotations) { AddressSpace nas = accept_address_space(ctx); if (nas != NumAddressSpaces) { if (as != NumAddressSpaces && as != nas) { - syntax_error_fmt("Conflicting address spaces for definition: %s and %s", get_address_space_name(as), get_address_space_name(nas)); + syntax_error_fmt("Conflicting address spaces for definition: %s and %s", shd_get_address_space_name(as), shd_get_address_space_name(nas)); } as = nas; continue; diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index e832caa1c..bbde9ea4e 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -738,7 +738,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { const Type* contents_t = get_def_type(parser, result_t); AddressSpace as2 = deconstruct_pointer_type(&contents_t); assert(as == as2); - assert(is_data_type(contents_t)); + assert(shd_is_data_type(contents_t)); if (parser->fun) { const Node* ptr = shd_first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { .type = contents_t, .mem = bb_mem(parser->current_block.builder) }), 1)); @@ -1086,7 +1086,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { const Node* cnt; if (op == SpvOpCopyMemory) { const Type* elem_t = src->type; - deconstruct_qualified_type(&elem_t); + shd_deconstruct_qualified_type(&elem_t); deconstruct_pointer_type(&elem_t); cnt = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = size_of_op, diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 5ace9900b..75f1b2e41 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -67,7 +67,7 @@ static void write_value(unsigned char* tgt, const Node* value) { } } else if (struct_t->tag == ArrType_TAG) { for (size_t i = 0; i < values.count; i++) { - TypeMemLayout layout = shd_get_mem_layout(value->arena, get_unqualified_type(values.nodes[i]->type)); + TypeMemLayout layout = shd_get_mem_layout(value->arena, shd_get_unqualified_type(values.nodes[i]->type)); write_value(tgt, values.nodes[i]); tgt += layout.size_in_bytes; } @@ -118,7 +118,7 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay for (size_t j = 0; j < struct_t->payload.record_type.members.count; j++) { const Type* member_t = struct_t->payload.record_type.members.nodes[j]; assert(member_t->tag == PtrType_TAG); - member_t = get_pointee_type(member_t->arena, member_t); + member_t = shd_get_pointee_type(member_t->arena, member_t); TypeMemLayout layout = shd_get_mem_layout(shd_module_get_arena(program->specialized_module), member_t); ProgramResourceInfo* constant_res_info = shd_arena_alloc(program->arena, sizeof(ProgramResourceInfo)); diff --git a/src/shady/analysis/literal.c b/src/shady/analysis/literal.c index 721cba876..2be2a6e85 100644 --- a/src/shady/analysis/literal.c +++ b/src/shady/analysis/literal.c @@ -130,7 +130,7 @@ const Node* shd_resolve_node_to_definition(const Node* node, NodeResolveConfig c const char* shd_get_string_literal(IrArena* arena, const Node* node) { if (!node) return NULL; - if (node->type && get_unqualified_type(node->type)->tag == PtrType_TAG) { + if (node->type && shd_get_unqualified_type(node->type)->tag == PtrType_TAG) { NodeResolveConfig nrc = shd_default_node_resolve_config(); const Node* ptr = shd_chase_ptr_to_source(node, nrc); const Node* value = shd_resolve_ptr_to_value(ptr, nrc); diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 3a4720dbf..19f790d88 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -89,7 +89,7 @@ static void verify_nominal_node(const Node* fn, const Node* n) { case Constant_TAG: { if (n->payload.constant.value) { const Type* t = n->payload.constant.value->type; - bool u = deconstruct_qualified_type(&t); + bool u = shd_deconstruct_qualified_type(&t); assert(u); assert(shd_is_subtype(n->payload.constant.type_hint, t)); } @@ -98,7 +98,7 @@ static void verify_nominal_node(const Node* fn, const Node* n) { case GlobalVariable_TAG: { if (n->payload.global_variable.init) { const Type* t = n->payload.global_variable.init->type; - bool u = deconstruct_qualified_type(&t); + bool u = shd_deconstruct_qualified_type(&t); assert(u); assert(shd_is_subtype(n->payload.global_variable.type, t)); } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 67bfcc920..a14acb6ce 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -252,7 +252,7 @@ const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { IrArena* a = bb->arena; - Nodes qyield_types = add_qualifiers(a, yield_types, false); + Nodes qyield_types = shd_add_qualifiers(a, yield_types, false); LARRAY(const Node*, tail_params, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) tail_params[i] = param(a, qyield_types.nodes[i], NULL); diff --git a/src/shady/check.c b/src/shady/check.c index 40b952fca..647702d27 100644 --- a/src/shady/check.c +++ b/src/shady/check.c @@ -1,4 +1,5 @@ #include "check.h" +#include "shady/ir/memory_layout.h" #include "log.h" #include "ir_private.h" @@ -11,8 +12,6 @@ #include #include -#pragma GCC diagnostic error "-Wswitch" - static bool are_types_identical(size_t num_types, const Type* types[]) { for (size_t i = 0; i < num_types; i++) { assert(types[i]); @@ -22,327 +21,12 @@ static bool are_types_identical(size_t num_types, const Type* types[]) { return true; } -bool shd_is_subtype(const Type* supertype, const Type* type) { - assert(supertype && type); - if (supertype->tag != type->tag) - return false; - if (type == supertype) - return true; - switch (is_type(supertype)) { - case NotAType: shd_error("supplied not a type to is_subtype"); - case QualifiedType_TAG: { - // uniform T <: varying T - if (supertype->payload.qualified_type.is_uniform && !type->payload.qualified_type.is_uniform) - return false; - return shd_is_subtype(supertype->payload.qualified_type.type, type->payload.qualified_type.type); - } - case RecordType_TAG: { - const Nodes* supermembers = &supertype->payload.record_type.members; - const Nodes* members = &type->payload.record_type.members; - if (supermembers->count != members->count) - return false; - for (size_t i = 0; i < members->count; i++) { - if (!shd_is_subtype(supermembers->nodes[i], members->nodes[i])) - return false; - } - return supertype->payload.record_type.special == type->payload.record_type.special; - } - case JoinPointType_TAG: { - const Nodes* superparams = &supertype->payload.join_point_type.yield_types; - const Nodes* params = &type->payload.join_point_type.yield_types; - if (params->count != superparams->count) return false; - for (size_t i = 0; i < params->count; i++) { - if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) - return false; - } - return true; - } - case FnType_TAG: { - // check returns - if (supertype->payload.fn_type.return_types.count != type->payload.fn_type.return_types.count) - return false; - for (size_t i = 0; i < type->payload.fn_type.return_types.count; i++) - if (!shd_is_subtype(supertype->payload.fn_type.return_types.nodes[i], type->payload.fn_type.return_types.nodes[i])) - return false; - // check params - const Nodes* superparams = &supertype->payload.fn_type.param_types; - const Nodes* params = &type->payload.fn_type.param_types; - if (params->count != superparams->count) return false; - for (size_t i = 0; i < params->count; i++) { - if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) - return false; - } - return true; - } case BBType_TAG: { - // check params - const Nodes* superparams = &supertype->payload.bb_type.param_types; - const Nodes* params = &type->payload.bb_type.param_types; - if (params->count != superparams->count) return false; - for (size_t i = 0; i < params->count; i++) { - if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) - return false; - } - return true; - } case LamType_TAG: { - // check params - const Nodes* superparams = &supertype->payload.lam_type.param_types; - const Nodes* params = &type->payload.lam_type.param_types; - if (params->count != superparams->count) return false; - for (size_t i = 0; i < params->count; i++) { - if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) - return false; - } - return true; - } case PtrType_TAG: { - if (supertype->payload.ptr_type.address_space != type->payload.ptr_type.address_space) - return false; - if (!supertype->payload.ptr_type.is_reference && type->payload.ptr_type.is_reference) - return false; - return shd_is_subtype(supertype->payload.ptr_type.pointed_type, type->payload.ptr_type.pointed_type); - } - case Int_TAG: return supertype->payload.int_type.width == type->payload.int_type.width && supertype->payload.int_type.is_signed == type->payload.int_type.is_signed; - case ArrType_TAG: { - if (!shd_is_subtype(supertype->payload.arr_type.element_type, type->payload.arr_type.element_type)) - return false; - // unsized arrays are supertypes of sized arrays (even though they're not datatypes...) - // TODO: maybe change this so it's only valid when talking about to pointer-to-arrays - const IntLiteral* size_literal = shd_resolve_to_int_literal(supertype->payload.arr_type.size); - if (size_literal && size_literal->value == 0) - return true; - return supertype->payload.arr_type.size == type->payload.arr_type.size || !supertype->payload.arr_type.size; - } - case PackType_TAG: { - if (!shd_is_subtype(supertype->payload.pack_type.element_type, type->payload.pack_type.element_type)) - return false; - return supertype->payload.pack_type.width == type->payload.pack_type.width; - } - case Type_TypeDeclRef_TAG: { - return supertype->payload.type_decl_ref.decl == type->payload.type_decl_ref.decl; - } - case Type_ImageType_TAG: { - if (!shd_is_subtype(supertype->payload.image_type.sampled_type, type->payload.image_type.sampled_type)) - return false; - if (supertype->payload.image_type.depth != type->payload.image_type.depth) - return false; - if (supertype->payload.image_type.dim != type->payload.image_type.dim) - return false; - if (supertype->payload.image_type.arrayed != type->payload.image_type.arrayed) - return false; - if (supertype->payload.image_type.ms != type->payload.image_type.ms) - return false; - if (supertype->payload.image_type.sampled != type->payload.image_type.sampled) - return false; - if (supertype->payload.image_type.imageformat != type->payload.image_type.imageformat) - return false; - return true; - } - case Type_SampledImageType_TAG: - return shd_is_subtype(supertype->payload.sampled_image_type.image_type, type->payload.sampled_image_type.image_type); - default: break; - } - // Two types are always equal (and therefore subtypes of each other) if their payload matches - return memcmp(&supertype->payload, &type->payload, sizeof(type->payload)) == 0; -} - -void shd_check_subtype(const Type* supertype, const Type* type) { - if (!shd_is_subtype(supertype, type)) { - shd_log_node(ERROR, type); - shd_error_print(" isn't a subtype of "); - shd_log_node(ERROR, supertype); - shd_error_print("\n"); - shd_error("failed check_subtype") - } -} - -size_t shd_get_type_bitwidth(const Type* t) { - switch (t->tag) { - case Int_TAG: return int_size_in_bytes(t->payload.int_type.width) * 8; - case Float_TAG: return float_size_in_bytes(t->payload.float_type.width) * 8; - case PtrType_TAG: { - if (t->arena->config.address_spaces[t->payload.ptr_type.address_space].physical) - return int_size_in_bytes(t->arena->config.memory.ptr_size) * 8; - break; - } - default: break; - } - return SIZE_MAX; -} - -bool shd_is_addr_space_uniform(IrArena* arena, AddressSpace as) { - switch (as) { - case AsGeneric: - case AsInput: - case AsOutput: - case AsFunction: - case AsPrivate: return !arena->config.is_simt; - default: return true; - } -} - -const Type* shd_get_actual_mask_type(IrArena* arena) { - switch (arena->config.specializations.subgroup_mask_representation) { - case SubgroupMaskAbstract: return mask_type(arena); - case SubgroupMaskInt64: return shd_uint64_type(arena); - default: assert(false); - } -} - -String shd_get_type_name(IrArena* arena, const Type* t) { - switch (is_type(t)) { - case NotAType: assert(false); - case Type_MaskType_TAG: return "mask_t"; - case Type_JoinPointType_TAG: return "join_type_t"; - case Type_NoRet_TAG: return "no_ret"; - case Type_Int_TAG: { - if (t->payload.int_type.is_signed) - return shd_format_string_arena(arena->arena, "i%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); - else - return shd_format_string_arena(arena->arena, "u%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); - } - case Type_Float_TAG: return shd_format_string_arena(arena->arena, "f%s", ((String[]) { "16", "32", "64" })[t->payload.float_type.width]); - case Type_Bool_TAG: return "bool"; - case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; - default: break; - } - return unique_name(arena, shd_get_node_tag_string(t->tag)); -} - -/// Is this a type that a value in the language can have ? -bool is_value_type(const Type* type) { - if (type->tag != QualifiedType_TAG) - return false; - return is_data_type(get_unqualified_type(type)); -} - -/// Is this a valid data type (for usage in other types and as type arguments) ? -bool is_data_type(const Type* type) { - switch (is_type(type)) { - case Type_MaskType_TAG: - case Type_JoinPointType_TAG: - case Type_Int_TAG: - case Type_Float_TAG: - case Type_Bool_TAG: - return true; - case Type_PtrType_TAG: - return true; - case Type_ArrType_TAG: - // array types _must_ be sized to be real data types - return type->payload.arr_type.size != NULL; - case Type_PackType_TAG: - return is_data_type(type->payload.pack_type.element_type); - case Type_RecordType_TAG: { - for (size_t i = 0; i < type->payload.record_type.members.count; i++) - if (!is_data_type(type->payload.record_type.members.nodes[i])) - return false; - // multi-return record types are the results of instructions, but are not values themselves - return type->payload.record_type.special == NotSpecial; - } - case Type_TypeDeclRef_TAG: - return !get_nominal_type_body(type) || is_data_type(get_nominal_type_body(type)); - // qualified types are not data types because that information is only meant for values - case Type_QualifiedType_TAG: return false; - // values cannot contain abstractions - case Type_FnType_TAG: - case Type_BBType_TAG: - case Type_LamType_TAG: - return false; - // this type has no values to begin with - case Type_NoRet_TAG: - return false; - case NotAType: - return false; - // Image stuff is data (albeit opaque) - case Type_SampledImageType_TAG: - case Type_SamplerType_TAG: - case Type_ImageType_TAG: - return true; - } -} - -bool is_arithm_type(const Type* t) { - return t->tag == Int_TAG || t->tag == Float_TAG; -} - -bool is_shiftable_type(const Type* t) { - return t->tag == Int_TAG || t->tag == MaskType_TAG; -} - -bool has_boolean_ops(const Type* t) { - return t->tag == Int_TAG || t->tag == Bool_TAG || t->tag == MaskType_TAG; -} - -bool is_comparable_type(const Type* t) { - return true; // TODO this is fine to allow, but we'll need to lower it for composite and native ptr types ! -} - -bool is_ordered_type(const Type* t) { - return is_arithm_type(t); -} - -bool is_physical_ptr_type(const Type* t) { - if (t->tag != PtrType_TAG) - return false; - return !t->payload.ptr_type.is_reference; - // AddressSpace as = t->payload.ptr_type.address_space; - // return t->arena->config.address_spaces[as].physical; -} - -bool is_generic_ptr_type(const Type* t) { - if (t->tag != PtrType_TAG) - return false; - AddressSpace as = t->payload.ptr_type.address_space; - return as == AsGeneric; -} - -bool is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type) { - assert(is_data_type(src_type) && is_data_type(dst_type)); - if (src_type == dst_type) - return true; // folding will eliminate those, but we need to pass type-checking first :) - if (!(is_arithm_type(src_type) || src_type->tag == MaskType_TAG || is_physical_ptr_type(src_type))) - return false; - if (!(is_arithm_type(dst_type) || dst_type->tag == MaskType_TAG || is_physical_ptr_type(dst_type))) - return false; - assert(shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)); - // either both pointers need to be in the generic address space, and we're only casting the element type, OR neither can be - if ((is_physical_ptr_type(src_type) && is_physical_ptr_type(dst_type)) && (is_generic_ptr_type(src_type) != is_generic_ptr_type(dst_type))) - return false; - return true; -} - -bool is_conversion_legal(const Type* src_type, const Type* dst_type) { - assert(is_data_type(src_type) && is_data_type(dst_type)); - if (!(is_arithm_type(src_type) || (is_physical_ptr_type(src_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) - return false; - if (!(is_arithm_type(dst_type) || (is_physical_ptr_type(dst_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) - return false; - // we only allow ptr-ptr conversions, use reinterpret otherwise - if (is_physical_ptr_type(src_type) != is_physical_ptr_type(dst_type)) - return false; - // exactly one of the pointers needs to be in the generic address space - if (is_generic_ptr_type(src_type) && is_generic_ptr_type(dst_type)) - return false; - if (src_type->tag == Int_TAG && dst_type->tag == Int_TAG) { - bool changes_sign = src_type->payload.int_type.is_signed != dst_type->payload.int_type.is_signed; - bool changes_width = src_type->payload.int_type.width != dst_type->payload.int_type.width; - if (changes_sign && changes_width) - return false; - } - // element types have to match (use reinterpret_cast for changing it) - if (is_physical_ptr_type(src_type) && is_physical_ptr_type(dst_type)) { - AddressSpace src_as = src_type->payload.ptr_type.address_space; - AddressSpace dst_as = dst_type->payload.ptr_type.address_space; - if (src_type->payload.ptr_type.pointed_type != dst_type->payload.ptr_type.pointed_type) - return false; - } - return true; -} - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" const Type* check_type_join_point_type(IrArena* arena, JoinPointType type) { for (size_t i = 0; i < type.yield_types.count; i++) { - assert(is_data_type(type.yield_types.nodes[i])); + assert(shd_is_data_type(type.yield_types.nodes[i])); } return NULL; } @@ -352,38 +36,38 @@ const Type* check_type_record_type(IrArena* arena, RecordType type) { for (size_t i = 0; i < type.members.count; i++) { // member types are value types iff this is a return tuple if (type.special == MultipleReturn) - assert(is_value_type(type.members.nodes[i])); + assert(shd_is_value_type(type.members.nodes[i])); else - assert(is_data_type(type.members.nodes[i])); + assert(shd_is_data_type(type.members.nodes[i])); } return NULL; } const Type* check_type_qualified_type(IrArena* arena, QualifiedType qualified_type) { - assert(is_data_type(qualified_type.type)); + assert(shd_is_data_type(qualified_type.type)); assert(arena->config.is_simt || qualified_type.is_uniform); return NULL; } const Type* check_type_arr_type(IrArena* arena, ArrType type) { - assert(is_data_type(type.element_type)); + assert(shd_is_data_type(type.element_type)); return NULL; } const Type* check_type_pack_type(IrArena* arena, PackType pack_type) { - assert(is_data_type(pack_type.element_type)); + assert(shd_is_data_type(pack_type.element_type)); return NULL; } const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { if (!arena->config.address_spaces[ptr_type.address_space].allowed) { - shd_error_print("Address space %s is not allowed in this arena\n", get_address_space_name(ptr_type.address_space)); + shd_error_print("Address space %s is not allowed in this arena\n", shd_get_address_space_name(ptr_type.address_space)); shd_error_die(); } assert(ptr_type.pointed_type && "Shady does not support untyped pointers, but can infer them, see infer.c"); if (ptr_type.pointed_type) { if (ptr_type.pointed_type->tag == ArrType_TAG) { - assert(is_data_type(ptr_type.pointed_type->payload.arr_type.element_type)); + assert(shd_is_data_type(ptr_type.pointed_type->payload.arr_type.element_type)); return NULL; } if (ptr_type.pointed_type->tag == FnType_TAG || ptr_type.pointed_type == unit_type(arena)) { @@ -396,13 +80,13 @@ const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { if (maybe_record_type && maybe_record_type->tag == RecordType_TAG && maybe_record_type->payload.record_type.special == DecorateBlock) { return NULL; } - assert(is_data_type(ptr_type.pointed_type)); + assert(shd_is_data_type(ptr_type.pointed_type)); } return NULL; } const Type* check_type_param(IrArena* arena, Param variable) { - assert(is_value_type(variable.type)); + assert(shd_is_value_type(variable.type)); return variable.type; } @@ -439,19 +123,19 @@ const Type* check_type_string_lit(IrArena* arena, StringLiteral str_lit) { } const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { - assert(is_data_type(payload.ptr_type) && payload.ptr_type->tag == PtrType_TAG); + assert(shd_is_data_type(payload.ptr_type) && payload.ptr_type->tag == PtrType_TAG); return shd_as_qualified_type(payload.ptr_type, true); } const Type* check_type_composite(IrArena* arena, Composite composite) { if (composite.type) { - assert(is_data_type(composite.type)); + assert(shd_is_data_type(composite.type)); Nodes expected_member_types = get_composite_type_element_types(composite.type); bool is_uniform = true; assert(composite.contents.count == expected_member_types.count); for (size_t i = 0; i < composite.contents.count; i++) { const Type* element_type = composite.contents.nodes[i]->type; - is_uniform &= deconstruct_qualified_type(&element_type); + is_uniform &= shd_deconstruct_qualified_type(&element_type); assert(shd_is_subtype(expected_member_types.nodes[i], element_type)); } return qualified_type(arena, (QualifiedType) { @@ -463,7 +147,7 @@ const Type* check_type_composite(IrArena* arena, Composite composite) { LARRAY(const Type*, member_ts, composite.contents.count); for (size_t i = 0; i < composite.contents.count; i++) { const Type* element_type = composite.contents.nodes[i]->type; - is_uniform &= deconstruct_qualified_type(&element_type); + is_uniform &= shd_deconstruct_qualified_type(&element_type); member_ts[i] = element_type; } return qualified_type(arena, (QualifiedType) { @@ -475,10 +159,10 @@ const Type* check_type_composite(IrArena* arena, Composite composite) { } const Type* check_type_fill(IrArena* arena, Fill payload) { - assert(is_data_type(payload.type)); + assert(shd_is_data_type(payload.type)); const Node* element_t = get_fill_type_element_type(payload.type); const Node* value_t = payload.value->type; - bool u = deconstruct_qualified_type(&value_t); + bool u = shd_deconstruct_qualified_type(&value_t); assert(shd_is_subtype(element_t, value_t)); return qualified_type(arena, (QualifiedType) { .is_uniform = u, @@ -487,7 +171,7 @@ const Type* check_type_fill(IrArena* arena, Fill payload) { } const Type* check_type_undef(IrArena* arena, Undef payload) { - assert(is_data_type(payload.type)); + assert(shd_is_data_type(payload.type)); return qualified_type(arena, (QualifiedType) { .is_uniform = true, .type = payload.type @@ -544,7 +228,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 1); const Type* type = shd_first(prim_op.operands)->type; - assert(is_arithm_type(get_maybe_packed_type_element(get_unqualified_type(type)))); + assert(shd_is_arithm_type(get_maybe_packed_type_element(shd_get_unqualified_type(type)))); return type; } case rshift_arithm_op: @@ -555,8 +239,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* first_operand_type = shd_first(prim_op.operands)->type; const Type* second_operand_type = prim_op.operands.nodes[1]->type; - bool uniform_result = deconstruct_qualified_type(&first_operand_type); - uniform_result &= deconstruct_qualified_type(&second_operand_type); + bool uniform_result = shd_deconstruct_qualified_type(&first_operand_type); + uniform_result &= shd_deconstruct_qualified_type(&second_operand_type); size_t value_simd_width = deconstruct_maybe_packed_type(&first_operand_type); size_t shift_simd_width = deconstruct_maybe_packed_type(&second_operand_type); @@ -579,15 +263,15 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case mod_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + const Type* first_operand_type = shd_get_unqualified_type(shd_first(prim_op.operands)->type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { const Node* arg = prim_op.operands.nodes[i]; const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); + bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); - assert(is_arithm_type(get_maybe_packed_type_element(operand_type))); + assert(shd_is_arithm_type(get_maybe_packed_type_element(operand_type))); assert(first_operand_type == operand_type && "operand type mismatch"); result_uniform &= operand_uniform; @@ -606,7 +290,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 1); const Type* type = shd_first(prim_op.operands)->type; - assert(has_boolean_ops(get_maybe_packed_type_element(get_unqualified_type(type)))); + assert(shd_has_boolean_ops(get_maybe_packed_type_element(shd_get_unqualified_type(type)))); return type; } case or_op: @@ -614,15 +298,15 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case and_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + const Type* first_operand_type = shd_get_unqualified_type(shd_first(prim_op.operands)->type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { const Node* arg = prim_op.operands.nodes[i]; const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); + bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); - assert(has_boolean_ops(get_maybe_packed_type_element(operand_type))); + assert(shd_has_boolean_ops(get_maybe_packed_type_element(operand_type))); assert(first_operand_type == operand_type && "operand type mismatch"); result_uniform &= operand_uniform; @@ -638,16 +322,16 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case neq_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + const Type* first_operand_type = shd_get_unqualified_type(shd_first(prim_op.operands)->type); size_t first_operand_width = get_maybe_packed_type_width(first_operand_type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { const Node* arg = prim_op.operands.nodes[i]; const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); + bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); - assert((ordered ? is_ordered_type : is_comparable_type)(get_maybe_packed_type_element(operand_type))); + assert((ordered ? shd_is_ordered_type : shd_is_comparable_type)(get_maybe_packed_type_element(operand_type))); assert(first_operand_type == operand_type && "operand type mismatch"); result_uniform &= operand_uniform; @@ -669,7 +353,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); const Node* src_type = shd_first(prim_op.operands)->type; - bool uniform = deconstruct_qualified_type(&src_type); + bool uniform = shd_deconstruct_qualified_type(&src_type); size_t width = deconstruct_maybe_packed_type(&src_type); assert(src_type->tag == Float_TAG); return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); @@ -677,13 +361,13 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case pow_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + const Type* first_operand_type = shd_get_unqualified_type(shd_first(prim_op.operands)->type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { const Node* arg = prim_op.operands.nodes[i]; const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); + bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); assert(first_operand_type == operand_type && "operand type mismatch"); @@ -696,13 +380,13 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case fma_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 3); - const Type* first_operand_type = get_unqualified_type(shd_first(prim_op.operands)->type); + const Type* first_operand_type = shd_get_unqualified_type(shd_first(prim_op.operands)->type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { const Node* arg = prim_op.operands.nodes[i]; const Type* operand_type = arg->type; - bool operand_uniform = deconstruct_qualified_type(&operand_type); + bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); assert(first_operand_type == operand_type && "operand type mismatch"); @@ -718,7 +402,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); const Node* src_type = shd_first(prim_op.operands)->type; - bool uniform = deconstruct_qualified_type(&src_type); + bool uniform = shd_deconstruct_qualified_type(&src_type); size_t width = deconstruct_maybe_packed_type(&src_type); assert(src_type->tag == Float_TAG || src_type->tag == Int_TAG && src_type->payload.int_type.is_signed); return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); @@ -736,7 +420,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 1); assert(prim_op.operands.count == 1); const Type* optype = shd_first(prim_op.operands)->type; - bool uniform = deconstruct_qualified_type(&optype); + bool uniform = shd_deconstruct_qualified_type(&optype); assert(uniform && optype->tag == Int_TAG); return qualified_type(arena, (QualifiedType) { .is_uniform = true, @@ -747,14 +431,14 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 3); const Type* condition_type = prim_op.operands.nodes[0]->type; - bool condition_uniform = deconstruct_qualified_type(&condition_type); + bool condition_uniform = shd_deconstruct_qualified_type(&condition_type); size_t width = deconstruct_maybe_packed_type(&condition_type); const Type* alternatives_types[2]; bool alternatives_all_uniform = true; for (size_t i = 0; i < 2; i++) { alternatives_types[i] = prim_op.operands.nodes[1 + i]->type; - alternatives_all_uniform &= deconstruct_qualified_type(&alternatives_types[i]); + alternatives_all_uniform &= shd_deconstruct_qualified_type(&alternatives_types[i]); size_t alternative_width = deconstruct_maybe_packed_type(&alternatives_types[i]); assert(alternative_width == width); } @@ -777,17 +461,17 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { Nodes indices = shd_nodes(arena, prim_op.operands.count - indices_start, &prim_op.operands.nodes[indices_start]); const Type* t = source->type; - bool uniform = deconstruct_qualified_type(&t); + bool uniform = shd_deconstruct_qualified_type(&t); enter_composite_indices(&t, &uniform, indices, true); if (prim_op.op == insert_op) { const Node* inserted_data = prim_op.operands.nodes[1]; const Type* inserted_data_type = inserted_data->type; - bool is_uniform = uniform & deconstruct_qualified_type(&inserted_data_type); + bool is_uniform = uniform & shd_deconstruct_qualified_type(&inserted_data_type); assert(shd_is_subtype(t, inserted_data_type) && "inserting data into a composite, but it doesn't match the target and indices"); return qualified_type(arena, (QualifiedType) { .is_uniform = is_uniform, - .type = get_unqualified_type(source->type), + .type = shd_get_unqualified_type(source->type), }); } @@ -800,8 +484,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Node* rhs = prim_op.operands.nodes[1]; const Type* lhs_t = lhs->type; const Type* rhs_t = rhs->type; - bool lhs_u = deconstruct_qualified_type(&lhs_t); - bool rhs_u = deconstruct_qualified_type(&rhs_t); + bool lhs_u = shd_deconstruct_qualified_type(&lhs_t); + bool rhs_u = shd_deconstruct_qualified_type(&rhs_t); assert(lhs_t->tag == PackType_TAG && rhs_t->tag == PackType_TAG); size_t total_size = lhs_t->payload.pack_type.width + rhs_t->payload.pack_type.width; const Type* element_t = lhs_t->payload.pack_type.element_type; @@ -811,7 +495,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Node** indices = &prim_op.operands.nodes[2]; bool u = lhs_u & rhs_u; for (size_t i = 0; i < indices_count; i++) { - u &= is_qualified_type_uniform(indices[i]->type); + u &= shd_is_qualified_type_uniform(indices[i]->type); int64_t index = shd_get_int_literal_value(*shd_resolve_to_int_literal(indices[i]), true); assert(index < 0 /* poison */ || (index >= 0 && index < total_size && "shuffle element out of range")); } @@ -823,11 +507,11 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 1); const Node* source = shd_first(prim_op.operands); const Type* src_type = source->type; - bool src_uniform = deconstruct_qualified_type(&src_type); + bool src_uniform = shd_deconstruct_qualified_type(&src_type); const Type* dst_type = shd_first(prim_op.type_arguments); - assert(is_data_type(dst_type)); - assert(is_reinterpret_cast_legal(src_type, dst_type)); + assert(shd_is_data_type(dst_type)); + assert(shd_is_reinterpret_cast_legal(src_type, dst_type)); return qualified_type(arena, (QualifiedType) { .is_uniform = src_uniform, @@ -839,11 +523,11 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 1); const Node* source = shd_first(prim_op.operands); const Type* src_type = source->type; - bool src_uniform = deconstruct_qualified_type(&src_type); + bool src_uniform = shd_deconstruct_qualified_type(&src_type); const Type* dst_type = shd_first(prim_op.type_arguments); - assert(is_data_type(dst_type)); - assert(is_conversion_legal(src_type, dst_type)); + assert(shd_is_data_type(dst_type)); + assert(shd_is_conversion_legal(src_type, dst_type)); // TODO check the conversion is legal return qualified_type(arena, (QualifiedType) { @@ -860,7 +544,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); return qualified_type(arena, (QualifiedType) { - .is_uniform = is_qualified_type_uniform(prim_op.operands.nodes[0]->type) && is_qualified_type_uniform(prim_op.operands.nodes[1]->type), + .is_uniform = shd_is_qualified_type_uniform(prim_op.operands.nodes[0]->type) && shd_is_qualified_type_uniform(prim_op.operands.nodes[1]->type), .type = bool_type(arena) }); } @@ -868,7 +552,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { case subgroup_assume_uniform_op: { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 1); - const Type* operand_type = get_unqualified_type(prim_op.operands.nodes[0]->type); + const Type* operand_type = shd_get_unqualified_type(prim_op.operands.nodes[0]->type); return qualified_type(arena, (QualifiedType) { .is_uniform = true, .type = operand_type @@ -879,9 +563,9 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); const Type* sampled_image_t = shd_first(prim_op.operands)->type; - bool uniform_src = deconstruct_qualified_type(&sampled_image_t); + bool uniform_src = shd_deconstruct_qualified_type(&sampled_image_t); const Type* coords_t = prim_op.operands.nodes[1]->type; - deconstruct_qualified_type(&coords_t); + shd_deconstruct_qualified_type(&coords_t); assert(sampled_image_t->tag == SampledImageType_TAG); const Type* image_t = sampled_image_t->payload.sampled_image_type.image_type; assert(image_t->tag == ImageType_TAG); @@ -908,7 +592,7 @@ static Nodes check_value_call(const Node* callee, Nodes argument_types) { assert(is_value(callee)); const Type* callee_type = callee->type; - SHADY_UNUSED bool callee_uniform = deconstruct_qualified_type(&callee_type); + SHADY_UNUSED bool callee_uniform = shd_deconstruct_qualified_type(&callee_type); AddressSpace as = deconstruct_pointer_type(&callee_type); assert(as == AsGeneric); @@ -926,32 +610,32 @@ const Type* check_type_call(IrArena* arena, Call call) { const Node* argument = args.nodes[i]; assert(is_value(argument)); } - Nodes argument_types = get_values_types(arena, args); + Nodes argument_types = shd_get_values_types(arena, args); return maybe_multiple_return(arena, check_value_call(call.callee, argument_types)); } static void ensure_types_are_data_types(const Nodes* yield_types) { for (size_t i = 0; i < yield_types->count; i++) { - assert(is_data_type(yield_types->nodes[i])); + assert(shd_is_data_type(yield_types->nodes[i])); } } static void ensure_types_are_value_types(const Nodes* yield_types) { for (size_t i = 0; i < yield_types->count; i++) { - assert(is_value_type(yield_types->nodes[i])); + assert(shd_is_value_type(yield_types->nodes[i])); } } const Type* check_type_if_instr(IrArena* arena, If if_instr) { assert(if_instr.tail && is_abstraction(if_instr.tail)); ensure_types_are_data_types(&if_instr.yield_types); - if (get_unqualified_type(if_instr.condition->type) != bool_type(arena)) + if (shd_get_unqualified_type(if_instr.condition->type) != bool_type(arena)) shd_error("condition of an if should be bool"); // TODO check the contained Merge instrs if (if_instr.yield_types.count > 0) assert(if_instr.if_false); - check_arguments_types_against_parameters_helper(get_param_types(arena, get_abstraction_params(if_instr.tail)), add_qualifiers(arena, if_instr.yield_types, false)); + check_arguments_types_against_parameters_helper(shd_get_param_types(arena, get_abstraction_params(if_instr.tail)), shd_add_qualifiers(arena, if_instr.yield_types, false)); return noret_type(arena); } @@ -975,7 +659,7 @@ const Type* check_type_control(IrArena* arena, Control control) { const Node* join_point = shd_first(get_abstraction_params(control.inside)); const Type* join_point_type = join_point->type; - deconstruct_qualified_type(&join_point_type); + shd_deconstruct_qualified_type(&join_point_type); assert(join_point_type->tag == JoinPointType_TAG); Nodes join_point_yield_types = join_point_type->payload.join_point_type.yield_types; @@ -1019,7 +703,7 @@ const Type* check_type_local_alloc(IrArena* a, LocalAlloc alloc) { const Type* check_type_load(IrArena* a, Load load) { const Node* ptr_type = load.ptr->type; - bool ptr_uniform = deconstruct_qualified_type(&ptr_type); + bool ptr_uniform = shd_deconstruct_qualified_type(&ptr_type); size_t width = deconstruct_maybe_packed_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); @@ -1032,7 +716,7 @@ const Type* check_type_load(IrArena* a, Load load) { const Type* check_type_store(IrArena* a, Store store) { const Node* ptr_type = store.ptr->type; - bool ptr_uniform = deconstruct_qualified_type(&ptr_type); + bool ptr_uniform = shd_deconstruct_qualified_type(&ptr_type); size_t width = deconstruct_maybe_packed_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); const PtrType* ptr_type_payload = &ptr_type->payload.ptr_type; @@ -1051,19 +735,19 @@ const Type* check_type_store(IrArena* a, Store store) { const Type* check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffset lea) { const Type* base_ptr_type = lea.ptr->type; - bool uniform = deconstruct_qualified_type(&base_ptr_type); + bool uniform = shd_deconstruct_qualified_type(&base_ptr_type); assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; assert(lea.offset); const Type* offset_type = lea.offset->type; - bool offset_uniform = deconstruct_qualified_type(&offset_type); + bool offset_uniform = shd_deconstruct_qualified_type(&offset_type); assert(offset_type->tag == Int_TAG && "lea expects an integer offset"); const IntLiteral* lit = shd_resolve_to_int_literal(lea.offset); bool offset_is_zero = lit && lit->value == 0; assert(offset_is_zero || !base_ptr_type->payload.ptr_type.is_reference && "if an offset is used, the base cannot be a reference"); - assert(offset_is_zero || is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); + assert(offset_is_zero || shd_is_data_type(pointee_type) && "if an offset is used, the base must point to a data type"); uniform &= offset_uniform; return qualified_type(a, (QualifiedType) { @@ -1078,7 +762,7 @@ const Type* check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffse const Type* check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea) { const Type* base_ptr_type = lea.ptr->type; - bool uniform = deconstruct_qualified_type(&base_ptr_type); + bool uniform = shd_deconstruct_qualified_type(&base_ptr_type); assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; @@ -1096,26 +780,26 @@ const Type* check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea const Type* check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { const Type* dst_t = copy_bytes.dst->type; - deconstruct_qualified_type(&dst_t); + shd_deconstruct_qualified_type(&dst_t); assert(dst_t->tag == PtrType_TAG); const Type* src_t = copy_bytes.src->type; - deconstruct_qualified_type(&src_t); + shd_deconstruct_qualified_type(&src_t); assert(src_t); const Type* cnt_t = copy_bytes.count->type; - deconstruct_qualified_type(&cnt_t); + shd_deconstruct_qualified_type(&cnt_t); assert(cnt_t->tag == Int_TAG); return empty_multiple_return_type(a); } const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { const Type* dst_t = fill_bytes.dst->type; - deconstruct_qualified_type(&dst_t); + shd_deconstruct_qualified_type(&dst_t); assert(dst_t->tag == PtrType_TAG); const Type* src_t = fill_bytes.src->type; - deconstruct_qualified_type(&src_t); + shd_deconstruct_qualified_type(&src_t); assert(src_t); const Type* cnt_t = fill_bytes.count->type; - deconstruct_qualified_type(&cnt_t); + shd_deconstruct_qualified_type(&cnt_t); assert(cnt_t->tag == Int_TAG); return empty_multiple_return_type(a); } @@ -1130,7 +814,7 @@ const Type* check_type_pop_stack(IrArena* a, PopStack payload) { } const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { - assert(get_unqualified_type(payload.value->type) == shd_uint32_type(a)); + assert(shd_get_unqualified_type(payload.value->type) == shd_uint32_type(a)); return shd_as_qualified_type(unit_type(a), true); } @@ -1153,7 +837,7 @@ const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { const Node* argument = args.nodes[i]; assert(is_value(argument)); } - assert(check_value_call(tail_call.callee, get_values_types(arena, tail_call.args)).count == 0); + assert(check_value_call(tail_call.callee, shd_get_values_types(arena, tail_call.args)).count == 0); return noret_type(arena); } @@ -1170,7 +854,7 @@ const Type* check_type_jump(IrArena* arena, Jump jump) { assert(is_value(argument)); } - check_basic_block_call(jump.target, get_values_types(arena, jump.args)); + check_basic_block_call(jump.target, shd_get_values_types(arena, jump.args)); return noret_type(arena); } @@ -1196,13 +880,13 @@ const Type* check_type_join(IrArena* arena, Join join) { const Type* join_target_type = join.join_point->type; - deconstruct_qualified_type(&join_target_type); + shd_deconstruct_qualified_type(&join_target_type); assert(join_target_type->tag == JoinPointType_TAG); Nodes join_point_param_types = join_target_type->payload.join_point_type.yield_types; - join_point_param_types = add_qualifiers(arena, join_point_param_types, !arena->config.is_simt); + join_point_param_types = shd_add_qualifiers(arena, join_point_param_types, !arena->config.is_simt); - check_arguments_types_against_parameters_helper(join_point_param_types, get_values_types(arena, join.args)); + check_arguments_types_against_parameters_helper(join_point_param_types, shd_get_values_types(arena, join.args)); return noret_type(arena); } @@ -1234,13 +918,13 @@ const Type* check_type_fn_ret(IrArena* arena, Return ret) { const Type* check_type_fun(IrArena* arena, Function fn) { for (size_t i = 0; i < fn.return_types.count; i++) { - assert(is_value_type(fn.return_types.nodes[i])); + assert(shd_is_value_type(fn.return_types.nodes[i])); } - return fn_type(arena, (FnType) { .param_types = get_param_types(arena, (&fn)->params), .return_types = (&fn)->return_types }); + return fn_type(arena, (FnType) { .param_types = shd_get_param_types(arena, (&fn)->params), .return_types = (&fn)->return_types }); } const Type* check_type_basic_block(IrArena* arena, BasicBlock bb) { - return bb_type(arena, (BBType) { .param_types = get_param_types(arena, (&bb)->params) }); + return bb_type(arena, (BBType) { .param_types = shd_get_param_types(arena, (&bb)->params) }); } const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_variable) { @@ -1271,7 +955,7 @@ const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_var } const Type* check_type_constant(IrArena* arena, Constant cnst) { - assert(is_data_type(cnst.type_hint)); + assert(shd_is_data_type(cnst.type_hint)); return cnst.type_hint; } diff --git a/src/shady/check.h b/src/shady/check.h index 4395223eb..057a23cd3 100644 --- a/src/shady/check.h +++ b/src/shady/check.h @@ -3,20 +3,6 @@ #include "shady/ir.h" -bool shd_is_subtype(const Type* supertype, const Type* type); -void shd_check_subtype(const Type* supertype, const Type* type); - -bool is_arithm_type(const Type*); -bool is_shiftable_type(const Type*); -bool has_boolean_ops(const Type*); -bool is_comparable_type(const Type*); -bool is_ordered_type(const Type*); -bool is_physical_ptr_type(const Type* t); -bool is_generic_ptr_type(const Type* t); - -bool is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type); -bool is_conversion_legal(const Type* src_type, const Type* dst_type); - #include "type_generated.h" #endif diff --git a/src/shady/fold.c b/src/shady/fold.c index f1d815d24..7d55dd437 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -181,7 +181,7 @@ static inline const Node* resolve_ptr_source(const Node* ptr) { const Node* original_ptr = ptr; IrArena* a = ptr->arena; const Type* t = ptr->type; - bool u = deconstruct_qualified_type(&t); + bool u = shd_deconstruct_qualified_type(&t); assert(t->tag == PtrType_TAG); const Type* desired_pointee_type = t->payload.ptr_type.pointed_type; // const Node* last_known_good = node; @@ -207,7 +207,7 @@ static inline const Node* resolve_ptr_source(const Node* ptr) { assert(!specialize_generic && "something should not be converted to generic twice!"); specialize_generic = true; ptr = shd_first(instruction.operands); - src_as = get_unqualified_type(ptr->type)->payload.ptr_type.address_space; + src_as = shd_get_unqualified_type(ptr->type)->payload.ptr_type.address_space; continue; } default: break; @@ -231,7 +231,7 @@ static inline const Node* resolve_ptr_source(const Node* ptr) { // if there was more than one of those pointless casts... if (distance > 1 || specialize_generic) { const Type* new_src_ptr_type = ptr->type; - deconstruct_qualified_type(&new_src_ptr_type); + shd_deconstruct_qualified_type(&new_src_ptr_type); if (new_src_ptr_type->tag != PtrType_TAG || new_src_ptr_type->payload.ptr_type.pointed_type != desired_pointee_type) { PtrType payload = t->payload.ptr_type; payload.address_space = src_as; @@ -244,7 +244,7 @@ static inline const Node* resolve_ptr_source(const Node* ptr) { static inline const Node* simplify_ptr_operand(IrArena* a, const Node* old_op) { const Type* ptr_t = old_op->type; - deconstruct_qualified_type(&ptr_t); + shd_deconstruct_qualified_type(&ptr_t); if (ptr_t->payload.ptr_type.is_reference) return NULL; return resolve_ptr_source(old_op); @@ -309,7 +309,7 @@ static inline const Node* fold_simplify_ptr_operand(const Node* node) { return node; if (!shd_is_subtype(node->type, r->type)) - r = prim_op_helper(arena, convert_op, shd_singleton(get_unqualified_type(node->type)), shd_singleton(r)); + r = prim_op_helper(arena, convert_op, shd_singleton(shd_get_unqualified_type(node->type)), shd_singleton(r)); return r; } @@ -322,14 +322,14 @@ static const Node* fold_prim_op(IrArena* arena, const Node* node) { // TODO: case subgroup_broadcast_first_op: case subgroup_assume_uniform_op: { const Node* value = shd_first(payload.operands); - if (is_qualified_type_uniform(value->type)) + if (shd_is_qualified_type_uniform(value->type)) return quote_single(arena, value); break; } case convert_op: case reinterpret_op: { // get rid of identity casts - if (payload.type_arguments.nodes[0] == get_unqualified_type(payload.operands.nodes[0]->type)) + if (payload.type_arguments.nodes[0] == shd_get_unqualified_type(payload.operands.nodes[0]->type)) return quote_single(arena, payload.operands.nodes[0]); break; } @@ -342,7 +342,7 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { switch (node->tag) { case Load_TAG: { if (node->payload.load.ptr->tag == Undef_TAG) - return mem_and_value(arena, (MemAndValue) { .value = undef(arena, (Undef) { .type = get_unqualified_type(node->type) }), .mem = node->payload.load.mem }); + return mem_and_value(arena, (MemAndValue) { .value = undef(arena, (Undef) { .type = shd_get_unqualified_type(node->type) }), .mem = node->payload.load.mem }); break; } case Store_TAG: { @@ -353,13 +353,13 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { case PtrArrayElementOffset_TAG: { PtrArrayElementOffset payload = node->payload.ptr_array_element_offset; if (payload.ptr->tag == Undef_TAG) - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + return quote_single(arena, undef(arena, (Undef) { .type = shd_get_unqualified_type(node->type) })); break; } case PtrCompositeElement_TAG: { PtrCompositeElement payload = node->payload.ptr_composite_element; if (payload.ptr->tag == Undef_TAG) - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + return quote_single(arena, undef(arena, (Undef) { .type = shd_get_unqualified_type(node->type) })); break; } case PrimOp_TAG: { @@ -368,7 +368,7 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { case reinterpret_op: case convert_op: { if (shd_first(payload.operands)->tag == Undef_TAG) - return quote_single(arena, undef(arena, (Undef) { .type = get_unqualified_type(node->type) })); + return quote_single(arena, undef(arena, (Undef) { .type = shd_get_unqualified_type(node->type) })); break; } default: break; diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index d1f49ae22..147020ec4 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -189,7 +189,7 @@ static void generate_getters_for_class(Growy* g, json_object* src, json_object* } void generate_address_space_name_fn(Growy* g, json_object* address_spaces) { - shd_growy_append_formatted(g, "String get_address_space_name(AddressSpace as) {\n"); + shd_growy_append_formatted(g, "String shd_get_address_space_name(AddressSpace as) {\n"); shd_growy_append_formatted(g, "\tswitch (as) {\n"); for (size_t i = 0; i < json_object_array_length(address_spaces); i++) { json_object* as = json_object_array_get_idx(address_spaces, i); diff --git a/src/shady/ir/composite.c b/src/shady/ir/composite.c index 9b4598abb..1cf22f209 100644 --- a/src/shady/ir/composite.c +++ b/src/shady/ir/composite.c @@ -21,8 +21,8 @@ const Node* tuple_helper(IrArena* a, Nodes contents) { const Type* t = NULL; if (a->config.check_types) { // infer the type of the tuple - Nodes member_types = get_values_types(a, contents); - t = record_type(a, (RecordType) {.members = strip_qualifiers(a, member_types)}); + Nodes member_types = shd_get_values_types(a, contents); + t = record_type(a, (RecordType) {.members = shd_strip_qualifiers(a, member_types)}); } return composite_helper(a, t, contents); @@ -33,7 +33,7 @@ void enter_composite(const Type** datatype, bool* uniform, const Node* selector, if (selector->arena->config.check_types) { const Type* selector_type = selector->type; - bool selector_uniform = deconstruct_qualified_type(&selector_type); + bool selector_uniform = shd_deconstruct_qualified_type(&selector_type); assert(selector_type->tag == Int_TAG && "selectors must be integers"); *uniform &= selector_uniform; } diff --git a/src/shady/ir/type.c b/src/shady/ir/type.c index 700ebd10e..8419f4376 100644 --- a/src/shady/ir/type.c +++ b/src/shady/ir/type.c @@ -1,10 +1,328 @@ +#include "shady/ir/type.h" +#include "shady/ir/function.h" +#include "shady/ir/memory_layout.h" +#include "shady/ir/module.h" + #include "../ir_private.h" #include "log.h" #include "portability.h" +#include "util.h" #include +#pragma GCC diagnostic error "-Wswitch" + +static bool are_types_identical(size_t num_types, const Type* types[]) { + for (size_t i = 0; i < num_types; i++) { + assert(types[i]); + if (types[0] != types[i]) + return false; + } + return true; +} + +bool shd_is_subtype(const Type* supertype, const Type* type) { + assert(supertype && type); + if (supertype->tag != type->tag) + return false; + if (type == supertype) + return true; + switch (is_type(supertype)) { + case NotAType: shd_error("supplied not a type to is_subtype"); + case QualifiedType_TAG: { + // uniform T <: varying T + if (supertype->payload.qualified_type.is_uniform && !type->payload.qualified_type.is_uniform) + return false; + return shd_is_subtype(supertype->payload.qualified_type.type, type->payload.qualified_type.type); + } + case RecordType_TAG: { + const Nodes* supermembers = &supertype->payload.record_type.members; + const Nodes* members = &type->payload.record_type.members; + if (supermembers->count != members->count) + return false; + for (size_t i = 0; i < members->count; i++) { + if (!shd_is_subtype(supermembers->nodes[i], members->nodes[i])) + return false; + } + return supertype->payload.record_type.special == type->payload.record_type.special; + } + case JoinPointType_TAG: { + const Nodes* superparams = &supertype->payload.join_point_type.yield_types; + const Nodes* params = &type->payload.join_point_type.yield_types; + if (params->count != superparams->count) return false; + for (size_t i = 0; i < params->count; i++) { + if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) + return false; + } + return true; + } + case FnType_TAG: { + // check returns + if (supertype->payload.fn_type.return_types.count != type->payload.fn_type.return_types.count) + return false; + for (size_t i = 0; i < type->payload.fn_type.return_types.count; i++) + if (!shd_is_subtype(supertype->payload.fn_type.return_types.nodes[i], type->payload.fn_type.return_types.nodes[i])) + return false; + // check params + const Nodes* superparams = &supertype->payload.fn_type.param_types; + const Nodes* params = &type->payload.fn_type.param_types; + if (params->count != superparams->count) return false; + for (size_t i = 0; i < params->count; i++) { + if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) + return false; + } + return true; + } case BBType_TAG: { + // check params + const Nodes* superparams = &supertype->payload.bb_type.param_types; + const Nodes* params = &type->payload.bb_type.param_types; + if (params->count != superparams->count) return false; + for (size_t i = 0; i < params->count; i++) { + if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) + return false; + } + return true; + } case LamType_TAG: { + // check params + const Nodes* superparams = &supertype->payload.lam_type.param_types; + const Nodes* params = &type->payload.lam_type.param_types; + if (params->count != superparams->count) return false; + for (size_t i = 0; i < params->count; i++) { + if (!shd_is_subtype(params->nodes[i], superparams->nodes[i])) + return false; + } + return true; + } case PtrType_TAG: { + if (supertype->payload.ptr_type.address_space != type->payload.ptr_type.address_space) + return false; + if (!supertype->payload.ptr_type.is_reference && type->payload.ptr_type.is_reference) + return false; + return shd_is_subtype(supertype->payload.ptr_type.pointed_type, type->payload.ptr_type.pointed_type); + } + case Int_TAG: return supertype->payload.int_type.width == type->payload.int_type.width && supertype->payload.int_type.is_signed == type->payload.int_type.is_signed; + case ArrType_TAG: { + if (!shd_is_subtype(supertype->payload.arr_type.element_type, type->payload.arr_type.element_type)) + return false; + // unsized arrays are supertypes of sized arrays (even though they're not datatypes...) + // TODO: maybe change this so it's only valid when talking about to pointer-to-arrays + const IntLiteral* size_literal = shd_resolve_to_int_literal(supertype->payload.arr_type.size); + if (size_literal && size_literal->value == 0) + return true; + return supertype->payload.arr_type.size == type->payload.arr_type.size || !supertype->payload.arr_type.size; + } + case PackType_TAG: { + if (!shd_is_subtype(supertype->payload.pack_type.element_type, type->payload.pack_type.element_type)) + return false; + return supertype->payload.pack_type.width == type->payload.pack_type.width; + } + case Type_TypeDeclRef_TAG: { + return supertype->payload.type_decl_ref.decl == type->payload.type_decl_ref.decl; + } + case Type_ImageType_TAG: { + if (!shd_is_subtype(supertype->payload.image_type.sampled_type, type->payload.image_type.sampled_type)) + return false; + if (supertype->payload.image_type.depth != type->payload.image_type.depth) + return false; + if (supertype->payload.image_type.dim != type->payload.image_type.dim) + return false; + if (supertype->payload.image_type.arrayed != type->payload.image_type.arrayed) + return false; + if (supertype->payload.image_type.ms != type->payload.image_type.ms) + return false; + if (supertype->payload.image_type.sampled != type->payload.image_type.sampled) + return false; + if (supertype->payload.image_type.imageformat != type->payload.image_type.imageformat) + return false; + return true; + } + case Type_SampledImageType_TAG: + return shd_is_subtype(supertype->payload.sampled_image_type.image_type, type->payload.sampled_image_type.image_type); + default: break; + } + // Two types are always equal (and therefore subtypes of each other) if their payload matches + return memcmp(&supertype->payload, &type->payload, sizeof(type->payload)) == 0; +} + +void shd_check_subtype(const Type* supertype, const Type* type) { + if (!shd_is_subtype(supertype, type)) { + shd_log_node(ERROR, type); + shd_error_print(" isn't a subtype of "); + shd_log_node(ERROR, supertype); + shd_error_print("\n"); + shd_error("failed check_subtype") + } +} + +/// Is this a type that a value in the language can have ? +bool shd_is_value_type(const Type* type) { + if (type->tag != QualifiedType_TAG) + return false; + return shd_is_data_type(shd_get_unqualified_type(type)); +} + +/// Is this a valid data type (for usage in other types and as type arguments) ? +bool shd_is_data_type(const Type* type) { + switch (is_type(type)) { + case Type_MaskType_TAG: + case Type_JoinPointType_TAG: + case Type_Int_TAG: + case Type_Float_TAG: + case Type_Bool_TAG: + return true; + case Type_PtrType_TAG: + return true; + case Type_ArrType_TAG: + // array types _must_ be sized to be real data types + return type->payload.arr_type.size != NULL; + case Type_PackType_TAG: + return shd_is_data_type(type->payload.pack_type.element_type); + case Type_RecordType_TAG: { + for (size_t i = 0; i < type->payload.record_type.members.count; i++) + if (!shd_is_data_type(type->payload.record_type.members.nodes[i])) + return false; + // multi-return record types are the results of instructions, but are not values themselves + return type->payload.record_type.special == NotSpecial; + } + case Type_TypeDeclRef_TAG: + return !get_nominal_type_body(type) || shd_is_data_type(get_nominal_type_body(type)); + // qualified types are not data types because that information is only meant for values + case Type_QualifiedType_TAG: return false; + // values cannot contain abstractions + case Type_FnType_TAG: + case Type_BBType_TAG: + case Type_LamType_TAG: + return false; + // this type has no values to begin with + case Type_NoRet_TAG: + return false; + case NotAType: + return false; + // Image stuff is data (albeit opaque) + case Type_SampledImageType_TAG: + case Type_SamplerType_TAG: + case Type_ImageType_TAG: + return true; + } +} + +bool shd_is_arithm_type(const Type* t) { + return t->tag == Int_TAG || t->tag == Float_TAG; +} + +bool shd_is_shiftable_type(const Type* t) { + return t->tag == Int_TAG || t->tag == MaskType_TAG; +} + +bool shd_has_boolean_ops(const Type* t) { + return t->tag == Int_TAG || t->tag == Bool_TAG || t->tag == MaskType_TAG; +} + +bool shd_is_comparable_type(const Type* t) { + return true; // TODO this is fine to allow, but we'll need to lower it for composite and native ptr types ! +} + +bool shd_is_ordered_type(const Type* t) { + return shd_is_arithm_type(t); +} + +bool shd_is_physical_ptr_type(const Type* t) { + if (t->tag != PtrType_TAG) + return false; + return !t->payload.ptr_type.is_reference; + // AddressSpace as = t->payload.ptr_type.address_space; + // return t->shd_get_arena_config(arena)->address_spaces[as].physical; +} + +bool shd_is_generic_ptr_type(const Type* t) { + if (t->tag != PtrType_TAG) + return false; + AddressSpace as = t->payload.ptr_type.address_space; + return as == AsGeneric; +} + +bool shd_is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type) { + assert(shd_is_data_type(src_type) && shd_is_data_type(dst_type)); + if (src_type == dst_type) + return true; // folding will eliminate those, but we need to pass type-checking first :) + if (!(shd_is_arithm_type(src_type) || src_type->tag == MaskType_TAG || shd_is_physical_ptr_type(src_type))) + return false; + if (!(shd_is_arithm_type(dst_type) || dst_type->tag == MaskType_TAG || shd_is_physical_ptr_type(dst_type))) + return false; + assert(shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)); + // either both pointers need to be in the generic address space, and we're only casting the element type, OR neither can be + if ((shd_is_physical_ptr_type(src_type) && shd_is_physical_ptr_type(dst_type)) && (shd_is_generic_ptr_type(src_type) != shd_is_generic_ptr_type(dst_type))) + return false; + return true; +} + +bool shd_is_conversion_legal(const Type* src_type, const Type* dst_type) { + assert(shd_is_data_type(src_type) && shd_is_data_type(dst_type)); + if (!(shd_is_arithm_type(src_type) || (shd_is_physical_ptr_type(src_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) + return false; + if (!(shd_is_arithm_type(dst_type) || (shd_is_physical_ptr_type(dst_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) + return false; + // we only allow ptr-ptr conversions, use reinterpret otherwise + if (shd_is_physical_ptr_type(src_type) != shd_is_physical_ptr_type(dst_type)) + return false; + // exactly one of the pointers needs to be in the generic address space + if (shd_is_generic_ptr_type(src_type) && shd_is_generic_ptr_type(dst_type)) + return false; + if (src_type->tag == Int_TAG && dst_type->tag == Int_TAG) { + bool changes_sign = src_type->payload.int_type.is_signed != dst_type->payload.int_type.is_signed; + bool changes_width = src_type->payload.int_type.width != dst_type->payload.int_type.width; + if (changes_sign && changes_width) + return false; + } + // element types have to match (use reinterpret_cast for changing it) + if (shd_is_physical_ptr_type(src_type) && shd_is_physical_ptr_type(dst_type)) { + AddressSpace src_as = src_type->payload.ptr_type.address_space; + AddressSpace dst_as = dst_type->payload.ptr_type.address_space; + if (src_type->payload.ptr_type.pointed_type != dst_type->payload.ptr_type.pointed_type) + return false; + } + return true; +} + +bool shd_is_addr_space_uniform(IrArena* arena, AddressSpace as) { + switch (as) { + case AsGeneric: + case AsInput: + case AsOutput: + case AsFunction: + case AsPrivate: return !shd_get_arena_config(arena)->is_simt; + default: return true; + } +} + +const Type* shd_get_actual_mask_type(IrArena* arena) { + switch (shd_get_arena_config(arena)->specializations.subgroup_mask_representation) { + case SubgroupMaskAbstract: return mask_type(arena); + case SubgroupMaskInt64: return shd_uint64_type(arena); + default: assert(false); + } +} + +String shd_get_type_name(IrArena* arena, const Type* t) { + switch (is_type(t)) { + case NotAType: assert(false); + case Type_MaskType_TAG: return "mask_t"; + case Type_JoinPointType_TAG: return "join_type_t"; + case Type_NoRet_TAG: return "no_ret"; + case Type_Int_TAG: { + if (t->payload.int_type.is_signed) + return shd_fmt_string_irarena(arena, "i%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); + else + return shd_fmt_string_irarena(arena, "u%s", ((String[]) { "8", "16", "32", "64" })[t->payload.int_type.width]); + } + case Type_Float_TAG: return shd_fmt_string_irarena(arena, "f%s", ((String[]) { "16", "32", "64" })[t->payload.float_type.width]); + case Type_Bool_TAG: return "bool"; + case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; + default: break; + } + return unique_name(arena, shd_get_node_tag_string(t->tag)); +} + const Type* maybe_multiple_return(IrArena* arena, Nodes types) { switch (types.count) { case 0: return empty_multiple_return_type(arena); @@ -25,17 +343,17 @@ Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type) { return type->payload.record_type.members; // fallthrough default: - assert(is_value_type(type)); + assert(shd_is_value_type(type)); return shd_singleton(type); } } -const Type* get_pointee_type(IrArena* arena, const Type* type) { +const Type* shd_get_pointee_type(IrArena* arena, const Type* type) { bool qualified = false, uniform = false; - if (is_value_type(type)) { + if (shd_is_value_type(type)) { qualified = true; - uniform = is_qualified_type_uniform(type); - type = get_unqualified_type(type); + uniform = shd_is_qualified_type_uniform(type); + type = shd_get_unqualified_type(type); } assert(type->tag == PtrType_TAG); uniform &= shd_is_addr_space_uniform(arena, type->payload.ptr_type.address_space); @@ -49,7 +367,7 @@ const Type* get_pointee_type(IrArena* arena, const Type* type) { return type; } -Nodes get_param_types(IrArena* arena, Nodes variables) { +Nodes shd_get_param_types(IrArena* arena, Nodes variables) { LARRAY(const Type*, arr, variables.count); for (size_t i = 0; i < variables.count; i++) { assert(variables.nodes[i]->tag == Param_TAG); @@ -58,28 +376,28 @@ Nodes get_param_types(IrArena* arena, Nodes variables) { return shd_nodes(arena, variables.count, arr); } -Nodes get_values_types(IrArena* arena, Nodes values) { - assert(arena->config.check_types); +Nodes shd_get_values_types(IrArena* arena, Nodes values) { + assert(shd_get_arena_config(arena)->check_types); LARRAY(const Type*, arr, values.count); for (size_t i = 0; i < values.count; i++) arr[i] = values.nodes[i]->type; return shd_nodes(arena, values.count, arr); } -bool is_qualified_type_uniform(const Type* type) { +bool shd_is_qualified_type_uniform(const Type* type) { const Type* result_type = type; - bool is_uniform = deconstruct_qualified_type(&result_type); + bool is_uniform = shd_deconstruct_qualified_type(&result_type); return is_uniform; } -const Type* get_unqualified_type(const Type* type) { +const Type* shd_get_unqualified_type(const Type* type) { assert(is_type(type)); const Type* result_type = type; - deconstruct_qualified_type(&result_type); + shd_deconstruct_qualified_type(&result_type); return result_type; } -bool deconstruct_qualified_type(const Type** type_out) { +bool shd_deconstruct_qualified_type(const Type** type_out) { const Type* type = *type_out; if (type->tag == QualifiedType_TAG) { *type_out = type->payload.qualified_type.type; @@ -91,18 +409,18 @@ const Type* shd_as_qualified_type(const Type* type, bool uniform) { return qualified_type(type->arena, (QualifiedType) { .type = type, .is_uniform = uniform }); } -Nodes strip_qualifiers(IrArena* arena, Nodes tys) { +Nodes shd_strip_qualifiers(IrArena* arena, Nodes tys) { LARRAY(const Type*, arr, tys.count); for (size_t i = 0; i < tys.count; i++) - arr[i] = get_unqualified_type(tys.nodes[i]); + arr[i] = shd_get_unqualified_type(tys.nodes[i]); return shd_nodes(arena, tys.count, arr); } -Nodes add_qualifiers(IrArena* arena, Nodes tys, bool uniform) { +Nodes shd_add_qualifiers(IrArena* arena, Nodes tys, bool uniform) { LARRAY(const Type*, arr, tys.count); for (size_t i = 0; i < tys.count; i++) arr[i] = shd_as_qualified_type(tys.nodes[i], - uniform || !arena->config.is_simt /* SIMD arenas ban varying value types */); + uniform || !shd_get_arena_config(arena)->is_simt /* SIMD arenas ban varying value types */); return shd_nodes(arena, tys.count, arr); } @@ -135,7 +453,7 @@ size_t get_maybe_packed_type_width(const Type* type) { size_t deconstruct_maybe_packed_type(const Type** type) { const Type* t = *type; - assert(is_data_type(t)); + assert(shd_is_data_type(t)); if (t->tag == PackType_TAG) { *type = t->payload.pack_type.element_type; return t->payload.pack_type.width; @@ -236,7 +554,7 @@ const Node* get_fill_type_size(const Type* composite_t) { } Type* nominal_type(Module* mod, Nodes annotations, String name) { - IrArena* arena = mod->arena; + IrArena* arena = shd_module_get_arena(mod); NominalType payload = { .name = string(arena, name), .module = mod, diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 768ecc6a0..b4fe540ed 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -50,7 +50,7 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, Nodes sp const Node* ovar = spilled_vars.nodes[i]; const Node* nvar = shd_rewrite_node(&ctx->rewriter, ovar); const Type* t = nvar->type; - deconstruct_qualified_type(&t); + shd_deconstruct_qualified_type(&t); assert(t->tag != PtrType_TAG || !t->payload.ptr_type.is_reference && "References cannot be spilled"); gen_push_value_stack(builder, nvar); } @@ -138,11 +138,11 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { const Type* value_type = shd_rewrite_node(r, ovar->type); //String param_name = get_value_name_unsafe(ovar); - const Node* recovered_value = gen_pop_value_stack(bb, get_unqualified_type(value_type)); + const Node* recovered_value = gen_pop_value_stack(bb, shd_get_unqualified_type(value_type)); //if (param_name) // set_value_name(recovered_value, param_name); - if (is_qualified_type_uniform(ovar->type)) + if (shd_is_qualified_type_uniform(ovar->type)) recovered_value = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .operands = shd_singleton(recovered_value) }); shd_register_processed(r, ovar, recovered_value); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index e80290321..6e9583b0b 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -52,7 +52,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { break; const Type* element_type = shd_rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); - assert(is_data_type(element_type)); + assert(shd_is_data_type(element_type)); const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, shd_singleton(type_decl_ref_helper(a, vctx->nom_t)), shd_singleton(shd_int32_literal(a, shd_list_count(vctx->members)))); shd_list_append(const Type*, vctx->members, element_type); diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index b7d41e3d8..1ff2b98db 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -39,7 +39,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { // Supplement an additional parameter for the join point const Type* jp_type = join_point_type(a, (JoinPointType) { - .yield_types = strip_qualifiers(a, shd_rewrite_nodes(&ctx->rewriter, old->payload.fun.return_types)) + .yield_types = shd_strip_qualifiers(a, shd_rewrite_nodes(&ctx->rewriter, old->payload.fun.return_types)) }); if (shd_lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { @@ -74,7 +74,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { Nodes param_types = shd_rewrite_nodes(r, old->payload.fn_type.param_types); Nodes returned_types = shd_rewrite_nodes(&ctx->rewriter, old->payload.fn_type.return_types); const Type* jp_type = qualified_type(a, (QualifiedType) { - .type = join_point_type(a, (JoinPointType) { .yield_types = strip_qualifiers(a, returned_types) }), + .type = join_point_type(a, (JoinPointType) { .yield_types = shd_strip_qualifiers(a, returned_types) }), .is_uniform = false }); param_types = shd_nodes_append(a, param_types, jp_type); @@ -110,8 +110,8 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { break; const Type* ocallee_type = ocallee->type; - bool callee_uniform = deconstruct_qualified_type(&ocallee_type); - ocallee_type = get_pointee_type(a, ocallee_type); + bool callee_uniform = shd_deconstruct_qualified_type(&ocallee_type); + ocallee_type = shd_get_pointee_type(a, ocallee_type); assert(ocallee_type->tag == FnType_TAG); Nodes returned_types = shd_rewrite_nodes(&ctx->rewriter, ocallee_type->payload.fn_type.return_types); @@ -121,7 +121,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { // Create the body of the control that receives the appropriately typed join point const Type* jp_type = qualified_type(a, (QualifiedType) { - .type = join_point_type(a, (JoinPointType) { .yield_types = strip_qualifiers(a, returned_types) }), + .type = join_point_type(a, (JoinPointType) { .yield_types = shd_strip_qualifiers(a, returned_types) }), .is_uniform = false }); const Node* jp = param(a, jp_type, "fn_return_point"); @@ -138,7 +138,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { }); shd_set_abstraction_body(control_case, control_body); BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); - return yield_values_and_wrap_in_block(bb, gen_control(bb, strip_qualifiers(a, returned_types), control_case)); + return yield_values_and_wrap_in_block(bb, gen_control(bb, shd_strip_qualifiers(a, returned_types), control_case)); } default: break; } diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 14233f7a1..77f7e255d 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -84,8 +84,8 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* old_loop_block = payload.body; Nodes yield_types = shd_rewrite_nodes(&ctx->rewriter, node->payload.loop_instr.yield_types); - Nodes param_types = shd_rewrite_nodes(&ctx->rewriter, get_param_types(a, get_abstraction_params(old_loop_block))); - param_types = strip_qualifiers(a, param_types); + Nodes param_types = shd_rewrite_nodes(&ctx->rewriter, shd_get_param_types(a, get_abstraction_params(old_loop_block))); + param_types = shd_strip_qualifiers(a, param_types); const Type* break_jp_type = qualified_type(a, (QualifiedType) { .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index f3b879db4..8fd5f92e8 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -32,7 +32,7 @@ static const Node* generate_arg_struct_type(Rewriter* rewriter, Nodes params) { for (int i = 0; i < params.count; ++i) { const Type* type = shd_rewrite_node(rewriter, params.nodes[i]->type); - if (!deconstruct_qualified_type(&type)) + if (!shd_deconstruct_qualified_type(&type)) shd_error("EntryPoint parameters must be uniform"); types[i] = type; diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 1520a778a..429bfc7cd 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -40,7 +40,7 @@ static uint64_t get_tag_for_addr_space(AddressSpace as) { if (generic_ptr_tags[i] == as) return (uint64_t) i; } - shd_error("address space '%s' can't be converted to generic", get_address_space_name(as)); + shd_error("address space '%s' can't be converted to generic", shd_get_address_space_name(as)); } static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t tag, const Node* nptr, const Type* element_type) { @@ -206,7 +206,7 @@ static const Node* process(Context* ctx, const Node* old) { case Load_TAG: { Load payload = old->payload.load; const Type* old_ptr_t = payload.ptr->type; - bool u = deconstruct_qualified_type(&old_ptr_t); + bool u = shd_deconstruct_qualified_type(&old_ptr_t); u &= shd_is_addr_space_uniform(a, old_ptr_t->payload.ptr_type.address_space); if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { return call(a, (Call) { @@ -220,7 +220,7 @@ static const Node* process(Context* ctx, const Node* old) { case Store_TAG: { Store payload = old->payload.store; const Type* old_ptr_t = payload.ptr->type; - deconstruct_qualified_type(&old_ptr_t); + shd_deconstruct_qualified_type(&old_ptr_t); if (old_ptr_t->payload.ptr_type.address_space == AsGeneric) { return call(a, (Call) { .callee = fn_addr_helper(a, get_or_make_access_fn(ctx, StoreFn, false, shd_rewrite_node(r, old_ptr_t->payload.ptr_type.pointed_type))), @@ -235,7 +235,7 @@ static const Node* process(Context* ctx, const Node* old) { case convert_op: { const Node* old_src = shd_first(old->payload.prim_op.operands); const Type* old_src_t = old_src->type; - deconstruct_qualified_type(&old_src_t); + shd_deconstruct_qualified_type(&old_src_t); const Type* old_dst_t = shd_first(old->payload.prim_op.type_arguments); if (old_dst_t->tag == PtrType_TAG && old_dst_t->payload.ptr_type.address_space == AsGeneric) { // cast _into_ generic diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index decae7bfc..0dd633fc4 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -12,7 +12,7 @@ typedef struct { } Context; static bool should_convert(Context* ctx, const Type* t) { - t = get_unqualified_type(t); + t = shd_get_unqualified_type(t); return t->tag == Int_TAG && t->payload.int_type.width == IntTy64 && ctx->config->lower.int64; } diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index ef455c08e..c407c9b36 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -116,10 +116,10 @@ static const Node* process(Context* ctx, const Node* old) { PtrArrayElementOffset lea = old->payload.ptr_array_element_offset; const Node* old_base = lea.ptr; const Type* old_base_ptr_t = old_base->type; - deconstruct_qualified_type(&old_base_ptr_t); + shd_deconstruct_qualified_type(&old_base_ptr_t); assert(old_base_ptr_t->tag == PtrType_TAG); const Node* old_result_t = old->type; - deconstruct_qualified_type(&old_result_t); + shd_deconstruct_qualified_type(&old_result_t); bool must_lower = false; // we have to lower generic pointers if we emulate them using ints must_lower |= ctx->config->lower.emulate_generic_ptrs && old_base_ptr_t->payload.ptr_type.address_space == AsGeneric; @@ -139,10 +139,10 @@ static const Node* process(Context* ctx, const Node* old) { PtrCompositeElement lea = old->payload.ptr_composite_element; const Node* old_base = lea.ptr; const Type* old_base_ptr_t = old_base->type; - deconstruct_qualified_type(&old_base_ptr_t); + shd_deconstruct_qualified_type(&old_base_ptr_t); assert(old_base_ptr_t->tag == PtrType_TAG); const Node* old_result_t = old->type; - deconstruct_qualified_type(&old_result_t); + shd_deconstruct_qualified_type(&old_result_t); bool must_lower = false; // we have to lower generic pointers if we emulate them using ints must_lower |= ctx->config->lower.emulate_generic_ptrs && old_base_ptr_t->payload.ptr_type.address_space == AsGeneric; diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 361d537f6..dcbc3fe88 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -17,7 +17,7 @@ typedef struct { static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node* ptr, const Type* expected_type) { IrArena* a = ctx->rewriter.dst_arena; while (true) { - const Type* actual_type = get_unqualified_type(ptr->type); + const Type* actual_type = shd_get_unqualified_type(ptr->type); assert(actual_type->tag == PtrType_TAG); actual_type = get_pointer_type_element(actual_type); if (expected_type == actual_type) @@ -69,11 +69,11 @@ static const Node* process(Context* ctx, const Node* old) { case PtrCompositeElement_TAG: { PtrCompositeElement payload = old->payload.ptr_composite_element; const Type* optr_t = payload.ptr->type; - deconstruct_qualified_type(&optr_t); + shd_deconstruct_qualified_type(&optr_t); assert(optr_t->tag == PtrType_TAG); const Type* expected_type = shd_rewrite_node(r, optr_t); const Node* ptr = shd_rewrite_node(r, payload.ptr); - const Type* actual_type = get_unqualified_type(ptr->type); + const Type* actual_type = shd_get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); @@ -85,7 +85,7 @@ static const Node* process(Context* ctx, const Node* old) { case reinterpret_op: { const Node* osrc = shd_first(payload.operands); const Type* osrc_t = osrc->type; - deconstruct_qualified_type(&osrc_t); + shd_deconstruct_qualified_type(&osrc_t); if (osrc_t->tag == PtrType_TAG && !shd_get_arena_config(a)->address_spaces[osrc_t->payload.ptr_type.address_space].physical) return shd_rewrite_node(r, osrc); break; @@ -97,11 +97,11 @@ static const Node* process(Context* ctx, const Node* old) { case Load_TAG: { Load payload = old->payload.load; const Type* optr_t = payload.ptr->type; - deconstruct_qualified_type(&optr_t); + shd_deconstruct_qualified_type(&optr_t); assert(optr_t->tag == PtrType_TAG); const Type* expected_type = shd_rewrite_node(r, optr_t); const Node* ptr = shd_rewrite_node(r, payload.ptr); - const Type* actual_type = get_unqualified_type(ptr->type); + const Type* actual_type = shd_get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); @@ -110,11 +110,11 @@ static const Node* process(Context* ctx, const Node* old) { case Store_TAG: { Store payload = old->payload.store; const Type* optr_t = payload.ptr->type; - deconstruct_qualified_type(&optr_t); + shd_deconstruct_qualified_type(&optr_t); assert(optr_t->tag == PtrType_TAG); const Type* expected_type = shd_rewrite_node(r, optr_t); const Node* ptr = shd_rewrite_node(r, payload.ptr); - const Type* actual_type = get_unqualified_type(ptr->type); + const Type* actual_type = shd_get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 9b09382d6..f0851b992 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -28,7 +28,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* dst_addr = shd_rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; - deconstruct_qualified_type(&dst_addr_type); + shd_deconstruct_qualified_type(&dst_addr_type); assert(dst_addr_type->tag == PtrType_TAG); dst_addr_type = ptr_type(a, (PtrType) { .address_space = dst_addr_type->payload.ptr_type.address_space, @@ -38,7 +38,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* src_addr = shd_rewrite_node(&ctx->rewriter, payload.src); const Type* src_addr_type = src_addr->type; - deconstruct_qualified_type(&src_addr_type); + shd_deconstruct_qualified_type(&src_addr_type); assert(src_addr_type->tag == PtrType_TAG); src_addr_type = ptr_type(a, (PtrType) { .address_space = src_addr_type->payload.ptr_type.address_space, @@ -77,7 +77,7 @@ static const Node* process(Context* ctx, const Node* old) { FillBytes payload = old->payload.fill_bytes; const Node* src_value = shd_rewrite_node(&ctx->rewriter, payload.src); const Type* src_type = src_value->type; - deconstruct_qualified_type(&src_type); + shd_deconstruct_qualified_type(&src_type); assert(src_type->tag == Int_TAG); const Type* word_type = src_type;// int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); @@ -85,7 +85,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* dst_addr = shd_rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; - deconstruct_qualified_type(&dst_addr_type); + shd_deconstruct_qualified_type(&dst_addr_type); assert(dst_addr_type->tag == PtrType_TAG); dst_addr_type = ptr_type(a, (PtrType) { .address_space = dst_addr_type->payload.ptr_type.address_space, diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index eedf69531..778c71bce 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -89,8 +89,8 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type shift = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); } if (config->printf_trace.memory_accesses) { - AddressSpace as = get_unqualified_type(arr->type)->payload.ptr_type.address_space; - String template = shd_fmt_string_irarena(a, "loaded %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); + AddressSpace as = shd_get_unqualified_type(arr->type)->payload.ptr_type.address_space; + String template = shd_fmt_string_irarena(a, "loaded %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", shd_get_address_space_name(as), "%lx"); const Node* widened = acc; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, shd_uint32_type(a), acc); @@ -192,8 +192,8 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element shift = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); } if (config->printf_trace.memory_accesses) { - AddressSpace as = get_unqualified_type(arr->type)->payload.ptr_type.address_space; - String template = shd_fmt_string_irarena(a, "stored %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", get_address_space_name(as), "%lx"); + AddressSpace as = shd_get_unqualified_type(arr->type)->payload.ptr_type.address_space; + String template = shd_fmt_string_irarena(a, "stored %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", shd_get_address_space_name(as), "%lx"); const Node* widened = value; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, shd_uint32_type(a), value); @@ -268,7 +268,7 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un const Type* return_value_t = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt || (uniform_address && shd_is_addr_space_uniform(a, as)), .type = element_type }); Nodes return_ts = ser ? shd_empty(a) : shd_singleton(return_value_t); - String name = shd_format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", get_address_space_name(as), uniform_address ? "uniform" : "varying", shd_get_type_name(a, element_type)); + String name = shd_format_string_arena(a->arena, "generated_%s_%s_%s_%s", ser ? "store" : "load", shd_get_address_space_name(as), uniform_address ? "uniform" : "varying", shd_get_type_name(a, element_type)); Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); @@ -293,7 +293,7 @@ static const Node* process_node(Context* ctx, const Node* old) { case Load_TAG: { Load payload = old->payload.load; const Type* ptr_type = payload.ptr->type; - bool uniform_ptr = deconstruct_qualified_type(&ptr_type); + bool uniform_ptr = shd_deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; @@ -307,7 +307,7 @@ static const Node* process_node(Context* ctx, const Node* old) { case Store_TAG: { Store payload = old->payload.store; const Type* ptr_type = payload.ptr->type; - bool uniform_ptr = deconstruct_qualified_type(&ptr_type); + bool uniform_ptr = shd_deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; @@ -386,7 +386,7 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect IrArena* a = ctx->rewriter.dst_arena; Module* m = ctx->rewriter.dst_module; - String as_name = get_address_space_name(as); + String as_name = shd_get_address_space_name(as); Node* global_struct_t = nominal_type(m, shd_singleton(annotation(a, (Annotation) { .name = "Generated" })), shd_format_string_arena(a->arena, "globals_physical_%s_t", as_name)); LARRAY(String, member_names, collected.count); @@ -433,7 +433,7 @@ static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, Body const Node* old_init = old_decl->payload.global_variable.init; if (old_init) { const Node* value = shd_rewrite_node(r, old_init); - const Node* fn = gen_serdes_fn(ctx, get_unqualified_type(value->type), false, true, old_decl->payload.global_variable.address_space); + const Node* fn = gen_serdes_fn(ctx, shd_get_unqualified_type(value->type), false, true, old_decl->payload.global_variable.address_space); gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, shd_rewrite_node(r, ref_decl_helper(oa, old_decl)), value)); } } @@ -442,7 +442,7 @@ static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, Body static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { IrArena* a = ctx->rewriter.dst_arena; Module* m = ctx->rewriter.dst_module; - String as_name = get_address_space_name(as); + String as_name = shd_get_address_space_name(as); const Type* word_type = int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }); const Type* ptr_size_type = int_type(a, (Int) { .width = a->config.memory.ptr_size, .is_signed = false }); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index e25c65d55..363117692 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -57,8 +57,8 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { stack_size = gen_primop_ce(bb, sub_op, 2, (const Node* []) { stack_size, element_size}); const Node* addr = gen_lea(bb, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); - assert(get_unqualified_type(addr->type)->tag == PtrType_TAG); - AddressSpace addr_space = get_unqualified_type(addr->type)->payload.ptr_type.address_space; + assert(shd_get_unqualified_type(addr->type)->tag == PtrType_TAG); + AddressSpace addr_space = shd_get_unqualified_type(addr->type)->payload.ptr_type.address_space; addr = gen_reinterpret_cast(bb, ptr_type(a, (PtrType) {.address_space = addr_space, .pointed_type = element_type}), addr); @@ -139,7 +139,7 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ctx->stack); PushStack payload = old->payload.push_stack; BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); - const Type* element_type = shd_rewrite_node(&ctx->rewriter, get_unqualified_type(old->payload.push_stack.value->type)); + const Type* element_type = shd_rewrite_node(&ctx->rewriter, shd_get_unqualified_type(old->payload.push_stack.value->type)); bool push = true; diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 389c6c1f6..50f6509e2 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -104,7 +104,7 @@ static void build_fn_body(Context* ctx, Node* fn, const Node* scope, const Node* static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Node* scope, const Node* src) { IrArena* a = ctx->rewriter.dst_arena; Module* m = ctx->rewriter.dst_module; - const Node* t = get_unqualified_type(src->type); + const Node* t = shd_get_unqualified_type(src->type); if (is_supported_natively(ctx, t)) return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, shd_as_qualified_type(t, true), mk_nodes(a, scope, src)); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 13bf1ae6e..73bb334a2 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -151,10 +151,10 @@ static const Node* process(Context* ctx, const Node* old) { // Params become stack pops ! for (size_t i = 0; i < old->payload.fun.params.count; i++) { const Node* old_param = old->payload.fun.params.nodes[i]; - const Type* new_param_type = shd_rewrite_node(&ctx->rewriter, get_unqualified_type(old_param->type)); + const Type* new_param_type = shd_rewrite_node(&ctx->rewriter, shd_get_unqualified_type(old_param->type)); const Node* popped = gen_pop_value_stack(bb, new_param_type); // TODO use the uniform stack instead ? or no ? - if (is_qualified_type_uniform(old_param->type)) + if (shd_is_qualified_type_uniform(old_param->type)) popped = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = shd_empty(a), .operands = shd_singleton(popped) }); if (old_param->payload.param.name) shd_set_value_name((Node*) popped, old_param->payload.param.name); @@ -220,7 +220,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* jp = shd_rewrite_node(&ctx->rewriter, old->payload.join.join_point); const Node* jp_type = jp->type; - deconstruct_qualified_type(&jp_type); + shd_deconstruct_qualified_type(&jp_type); if (jp_type->tag == JoinPointType_TAG) break; @@ -249,7 +249,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* old_jp = shd_first(get_abstraction_params(payload.inside)); assert(old_jp->tag == Param_TAG); const Node* old_jp_type = old_jp->type; - deconstruct_qualified_type(&old_jp_type); + shd_deconstruct_qualified_type(&old_jp_type); assert(old_jp_type->tag == JoinPointType_TAG); const Node* new_jp_type = join_point_type(a, (JoinPointType) { .yield_types = shd_rewrite_nodes(&ctx->rewriter, old_jp_type->payload.join_point_type.yield_types), diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 6c9986bf6..89a97cbd1 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -12,7 +12,7 @@ typedef struct { static const Node* scalarify_primop(Context* ctx, const Node* old) { IrArena* a = ctx->rewriter.dst_arena; const Type* dst_type = old->type; - deconstruct_qualified_type(&dst_type); + shd_deconstruct_qualified_type(&dst_type); size_t width = deconstruct_maybe_packed_type(&dst_type); if (width == 1) return shd_recreate_node(&ctx->rewriter, old); diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 62580e610..71f143a2d 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -38,7 +38,7 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { case PtrCompositeElement_TAG: { const Type* src_req_cast = get_req_cast(ctx, src->payload.ptr_composite_element.ptr); if (src_req_cast) { - bool u = deconstruct_qualified_type(&src_req_cast); + bool u = shd_deconstruct_qualified_type(&src_req_cast); enter_composite(&src_req_cast, &u, src->payload.ptr_composite_element.index, false); return src_req_cast; } @@ -77,7 +77,7 @@ static const Node* process(Context* ctx, const Node* node) { case Load_TAG: { const Type* req_cast = get_req_cast(ctx, node->payload.load.ptr); if (req_cast) { - assert(is_data_type(req_cast)); + assert(shd_is_data_type(req_cast)); BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, node->payload.load.mem)); const Node* r1 = shd_first(bind_instruction(bb, shd_recreate_node(r, node))); const Node* r2 = shd_first(gen_primop(bb, reinterpret_op, shd_singleton(req_cast), shd_singleton(r1))); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 9746d884f..b46c9ab69 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -44,7 +44,7 @@ typedef struct { static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, AllocaInfo* k, const UsesMap* map) { const Type* ptr_type = ptr_value->type; - bool ptr_u = deconstruct_qualified_type(&ptr_type); + bool ptr_u = shd_deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); const Use* use = get_first_use(map, ptr_value); @@ -151,7 +151,7 @@ static const Node* handle_alloc(Context* ctx, const Node* old, const Type* old_t if (!k->leaks) { if (!k->read_from/* this should include killing dead stores! */) { *ctx->todo |= true; - const Node* new = undef(a, (Undef) { .type = get_unqualified_type(shd_rewrite_node(r, old->type)) }); + const Node* new = undef(a, (Undef) { .type = shd_get_unqualified_type(shd_rewrite_node(r, old->type)) }); new = mem_and_value(a, (MemAndValue) { .value = new, .mem = nmem }); k->new = new; return new; @@ -193,8 +193,8 @@ static const Node* process(Context* ctx, const Node* old) { shd_rewrite_node(r, payload.mem); PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { - const Type* access_type = get_pointer_type_element(get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); - if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { + const Type* access_type = get_pointer_type_element(shd_get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); + if (shd_is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { if (k.src_alloca->new == shd_rewrite_node(r, payload.ptr)) break; *ctx->todo |= true; @@ -211,8 +211,8 @@ static const Node* process(Context* ctx, const Node* old) { shd_rewrite_node(r, payload.mem); PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { - const Type* access_type = get_pointer_type_element(get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); - if (is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { + const Type* access_type = get_pointer_type_element(shd_get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); + if (shd_is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { if (k.src_alloca->new == shd_rewrite_node(r, payload.ptr)) break; *ctx->todo |= true; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 7ec962762..39d174783 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -171,7 +171,7 @@ static const Node* process(Context* ctx, const Node* node) { Nodes nargs = shd_rewrite_nodes(&ctx->rewriter, payload.args); // Prepare a join point to replace the old function return - Nodes nyield_types = strip_qualifiers(a, shd_rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); + Nodes nyield_types = shd_strip_qualifiers(a, shd_rewrite_nodes(&ctx->rewriter, ocallee->payload.fun.return_types)); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = nyield_types }); const Node* join_point = param(a, shd_as_qualified_type(jp_type, true), shd_format_string_arena(a->arena, "inlined_return_%s", shd_get_abstraction_name(ocallee))); diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index d81c47ad7..be115b58d 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -38,7 +38,7 @@ static const Node* get_ptr_source(const Node* ptr) { case reinterpret_op: case convert_op: { const Node* src = shd_first(payload.operands); - if (get_unqualified_type(src->type)->tag == PtrType_TAG) { + if (shd_get_unqualified_type(src->type)->tag == PtrType_TAG) { ptr = src; continue; } @@ -101,11 +101,11 @@ static const Node* process(Context* ctx, const Node* node) { if (src->tag != LocalAlloc_TAG) break; // for now, only simplify loads from non-leaking allocas - const Node* ovalue = get_last_stored_value(ctx, payload.ptr, payload.mem, get_unqualified_type(node->type)); + const Node* ovalue = get_last_stored_value(ctx, payload.ptr, payload.mem, shd_get_unqualified_type(node->type)); if (ovalue) { *ctx->todo = true; const Node* value = shd_rewrite_node(r, ovalue); - if (is_qualified_type_uniform(node->type)) + if (shd_is_qualified_type_uniform(node->type)) value = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(value)); return mem_and_value(a, (MemAndValue) { .mem = shd_rewrite_node(r, payload.mem), .value = value }); } diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index c35e842d1..d9de85228 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -126,17 +126,17 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Nodes nparams = shd_recreate_params(rewriter, get_abstraction_params(node)); Node* loop_container = basic_block(arena, nparams, node->payload.basic_block.name); BodyBuilder* outer_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(loop_container)); - Nodes inner_yield_types = strip_qualifiers(arena, get_param_types(arena, nparams)); + Nodes inner_yield_types = shd_strip_qualifiers(arena, shd_get_param_types(arena, nparams)); LARRAY(Exit, exits, exiting_nodes_count); for (size_t i = 0; i < exiting_nodes_count; i++) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; - Nodes exit_param_types = shd_rewrite_nodes(rewriter, get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); + Nodes exit_param_types = shd_rewrite_nodes(rewriter, shd_get_param_types(ctx->rewriter.src_arena, get_abstraction_params(exiting_node->node))); ExitValue* exit_params = shd_arena_alloc(ctx->arena, sizeof(ExitValue) * exit_param_types.count); for (size_t j = 0; j < exit_param_types.count; j++) { - exit_params[j].alloca = gen_stack_alloc(outer_bb, get_unqualified_type(exit_param_types.nodes[j])); - exit_params[j].uniform = is_qualified_type_uniform(exit_param_types.nodes[j]); + exit_params[j].alloca = gen_stack_alloc(outer_bb, shd_get_unqualified_type(exit_param_types.nodes[j])); + exit_params[j].uniform = shd_is_qualified_type_uniform(exit_param_types.nodes[j]); } exits[i] = (Exit) { .params = exit_params, @@ -240,7 +240,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); // make sure what was uniform still is for (size_t j = 0; j < inner_control_results.count; j++) { - if (is_qualified_type_uniform(nparams.nodes[j]->type)) + if (shd_is_qualified_type_uniform(nparams.nodes[j]->type)) inner_control_results = shd_change_node_at_index(arena, inner_control_results, j, prim_op_helper(arena, subgroup_assume_uniform_op, shd_empty(arena), shd_singleton(inner_control_results.nodes[j]))); } shd_set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); @@ -417,8 +417,8 @@ static const Node* process_node(Context* ctx, const Node* node) { //This should always contain a qualified type? //if (contains_qualified_type(types[j])) - types[j] = get_unqualified_type(qualified_type); - uniform_param[j] = is_qualified_type_uniform(qualified_type); + types[j] = shd_get_unqualified_type(qualified_type); + uniform_param[j] = shd_is_qualified_type_uniform(qualified_type); inner_args[j] = param(a, qualified_type, old_params.nodes[j]->payload.param.name); } diff --git a/src/shady/passes/restructure.c b/src/shady/passes/restructure.c index fcddff643..4a23a1aca 100644 --- a/src/shady/passes/restructure.c +++ b/src/shady/passes/restructure.c @@ -249,7 +249,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { LARRAY(const Node*, phis, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { const Type* type = yield_types.nodes[i]; - assert(is_data_type(type)); + assert(shd_is_data_type(type)); phis[i] = gen_local_alloc(bb_prelude, type); } diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 9d5d95ddd..9cf5b5f97 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -118,13 +118,13 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab Node* c2 = case_(a, shd_empty(a)); BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(c2)); const Type* jp_type = add_control.token->type; - deconstruct_qualified_type(&jp_type); + shd_deconstruct_qualified_type(&jp_type); assert(jp_type->tag == JoinPointType_TAG); Nodes results = gen_control(bb, jp_type->payload.join_point_type.yield_types, control_case); Nodes original_params = get_abstraction_params(dst); for (size_t j = 0; j < results.count; j++) { - if (is_qualified_type_uniform(original_params.nodes[j]->type)) + if (shd_is_qualified_type_uniform(original_params.nodes[j]->type)) results = shd_change_node_at_index(a, results, j, gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(results.nodes[j]))); } @@ -219,7 +219,7 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed } else { Nodes wrapper_params = remake_params(ctx, get_abstraction_params(dst)); Nodes join_args = wrapper_params; - Nodes yield_types = shd_rewrite_nodes(r, strip_qualifiers(a, get_param_types(a, get_abstraction_params(dst)))); + Nodes yield_types = shd_rewrite_nodes(r, shd_strip_qualifiers(a, shd_get_param_types(a, get_abstraction_params(dst)))); const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = yield_types diff --git a/src/shady/print.c b/src/shady/print.c index 3508717c6..18c49e75e 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -430,7 +430,7 @@ static bool print_type(PrinterCtx* ctx, const Node* node) { printf(RESET); printf("("); printf(BLUE); - printf(get_address_space_name(node->payload.ptr_type.address_space)); + printf(shd_get_address_space_name(node->payload.ptr_type.address_space)); printf(RESET); printf(", "); print_node(node->payload.ptr_type.pointed_type); @@ -906,7 +906,7 @@ static void print_decl(PrinterCtx* ctx, const Node* node) { printf(BLUE); printf("var "); printf(BLUE); - printf(get_address_space_name(gvar->address_space)); + printf(shd_get_address_space_name(gvar->address_space)); printf(" "); print_node(gvar->type); printf(BYELLOW); @@ -1168,7 +1168,7 @@ void _shd_print_node_operand_list(PrinterCtx* ctx, const Node* n, String name, N void _shd_print_node_operand_AddressSpace(PrinterCtx* ctx, const Node* n, String name, AddressSpace as) { print_operand_name_helper(ctx, name); - shd_print(ctx->printer, "%s", get_address_space_name(as)); + shd_print(ctx->printer, "%s", shd_get_address_space_name(as)); } void _shd_print_node_operand_Op(PrinterCtx* ctx, const Node* n, String name, Op op) { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 9014368bf..98a08479c 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -103,8 +103,8 @@ const Node* gen_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { } const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { - const Type* src_type = get_unqualified_type(lo->type); - assert(get_unqualified_type(hi->type) == src_type); + const Type* src_type = shd_get_unqualified_type(lo->type); + assert(shd_get_unqualified_type(hi->type) == src_type); assert(src_type->tag == Int_TAG); IntSizes size = src_type->payload.int_type.width; assert(size != IntSizeMax); @@ -238,7 +238,7 @@ const Node* access_decl(Rewriter* rewriter, const char* name) { } const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { - const Type* src_type = get_unqualified_type(src->type); + const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); assert(dst_type->tag == Int_TAG); @@ -251,7 +251,7 @@ const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* d } const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { - const Type* src_type = get_unqualified_type(src->type); + const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); assert(dst_type->tag == Int_TAG); @@ -264,7 +264,7 @@ const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* d } const Node* convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { - const Type* src_type = get_unqualified_type(src->type); + const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); assert(dst_type->tag == Int_TAG); @@ -278,7 +278,7 @@ const Node* convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const } const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { - const Type* src_type = get_unqualified_type(src->type); + const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); assert(dst_type->tag == Int_TAG); diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 08955484b..0a0015345 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -66,7 +66,7 @@ TypeMemLayout shd_get_mem_layout(IrArena* a, const Type* type) { case AsShared: case AsGlobal: case AsGeneric: return shd_get_mem_layout(a, int_type(a, (Int) { .width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false })); // TODO: use per-as layout - default: shd_error("Pointers in address space '%s' does not have a defined memory layout", get_address_space_name(type->payload.ptr_type.address_space)); + default: shd_error("Pointers in address space '%s' does not have a defined memory layout", shd_get_address_space_name(type->payload.ptr_type.address_space)); } case Int_TAG: return (TypeMemLayout) { .type = type, @@ -130,3 +130,18 @@ IntSizes shd_float_to_int_width(FloatSizes width) { case FloatTy64: return IntTy64; } } + +size_t shd_get_type_bitwidth(const Type* t) { + const ArenaConfig* aconfig = shd_get_arena_config(t->arena); + switch (t->tag) { + case Int_TAG: return int_size_in_bytes(t->payload.int_type.width) * 8; + case Float_TAG: return float_size_in_bytes(t->payload.float_type.width) * 8; + case PtrType_TAG: { + if (aconfig->address_spaces[t->payload.ptr_type.address_space].physical) + return int_size_in_bytes(aconfig->memory.ptr_size) * 8; + break; + } + default: break; + } + return SIZE_MAX; +} From 61ff407c445be5d76e738a839cc149e949029dfe Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 10 Oct 2024 12:26:46 +0200 Subject: [PATCH 643/693] don't trust clion's move refactor :/ --- SPIRV-Headers | 2 +- src/shady/ir/annotation.c | 1 + src/shady/ir/builtin.c | 11 ++++++----- src/shady/ir/grammar.c | 10 +++++----- src/shady/ir/mem.c | 2 +- src/shady/ir/module.c | 4 ++-- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/SPIRV-Headers b/SPIRV-Headers index 1c9115b56..efb6b4099 160000 --- a/SPIRV-Headers +++ b/SPIRV-Headers @@ -1 +1 @@ -Subproject commit 1c9115b562bab79ee2160fbd845f41b815b9f21f +Subproject commit efb6b4099ddb8fa60f62956dee592c4b94ec6a49 diff --git a/src/shady/ir/annotation.c b/src/shady/ir/annotation.c index d38891a1d..fb56b03bf 100644 --- a/src/shady/ir/annotation.c +++ b/src/shady/ir/annotation.c @@ -1,4 +1,5 @@ #include "ir_private.h" + #include "log.h" #include "portability.h" diff --git a/src/shady/ir/builtin.c b/src/shady/ir/builtin.c index 6fb075774..c4633d13f 100644 --- a/src/shady/ir/builtin.c +++ b/src/shady/ir/builtin.c @@ -1,10 +1,11 @@ -#include "../../../include/shady/ir/builtin.h" -#include "../../../include/shady/ir/annotation.h" +#include "shady/ir/builtin.h" +#include "shady/ir/annotation.h" -#include "../../../SPIRV-Headers/include/spirv/unified1/spirv.h" +#include "log.h" +#include "portability.h" + +#include -#include "../../common/log.h" -#include "../../common/portability.h" #include static AddressSpace builtin_as[] = { diff --git a/src/shady/ir/grammar.c b/src/shady/ir/grammar.c index 2eb0b9d4a..0cc2830c6 100644 --- a/src/shady/ir/grammar.c +++ b/src/shady/ir/grammar.c @@ -1,10 +1,10 @@ -#include "../../../include/shady/ir/grammar.h" +#include "shady/ir/grammar.h" #include "../fold.h" -#include "../../common/log.h" -#include "../../common/portability.h" -#include "../../common/dict.h" +#include "log.h" +#include "portability.h" +#include "dict.h" #include #include @@ -57,4 +57,4 @@ Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh) { return alloc; } -#include "../../../cmake-build-debug/src/shady/constructors_generated.c" +#include "../constructors_generated.c" diff --git a/src/shady/ir/mem.c b/src/shady/ir/mem.c index 1375aba62..47737519c 100644 --- a/src/shady/ir/mem.c +++ b/src/shady/ir/mem.c @@ -1,4 +1,4 @@ -#include "../../../include/shady/ir.h" +#include "shady/ir/grammar.h" #include diff --git a/src/shady/ir/module.c b/src/shady/ir/module.c index 785f56f8b..f31e48fc5 100644 --- a/src/shady/ir/module.c +++ b/src/shady/ir/module.c @@ -1,7 +1,7 @@ #include "../ir_private.h" -#include "../../common/list.h" -#include "../../common/portability.h" +#include "list.h" +#include "portability.h" #include From fb80fe2cf6c2aa06252b76b528d8c319ef372504 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 10 Oct 2024 15:03:21 +0200 Subject: [PATCH 644/693] removed murmur3 as a dependency --- SPIRV-Headers | 2 +- murmur3 | 1 - src/CMakeLists.txt | 4 ---- src/backend/spirv/spirv_builder.c | 2 +- src/common/CMakeLists.txt | 1 - src/common/dict.c | 27 +++++++++++++------------- src/common/dict.h | 2 +- src/frontend/llvm/l2s.c | 2 +- src/frontend/spirv/s2s.c | 2 +- src/runtime/cuda/CMakeLists.txt | 1 - src/runtime/vulkan/CMakeLists.txt | 1 - src/runtime/vulkan/vk_runtime_device.c | 2 +- src/shady/analysis/callgraph.c | 2 +- src/shady/generator_node.c | 2 +- src/shady/ir.c | 6 +++--- src/shady/node.c | 2 +- vcc/vcc_lib.c | 4 ++-- 17 files changed, 28 insertions(+), 35 deletions(-) delete mode 160000 murmur3 diff --git a/SPIRV-Headers b/SPIRV-Headers index efb6b4099..1c9115b56 160000 --- a/SPIRV-Headers +++ b/SPIRV-Headers @@ -1 +1 @@ -Subproject commit efb6b4099ddb8fa60f62956dee592c4b94ec6a49 +Subproject commit 1c9115b562bab79ee2160fbd845f41b815b9f21f diff --git a/murmur3 b/murmur3 deleted file mode 160000 index dae94be0c..000000000 --- a/murmur3 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dae94be0c0f54a399d23ea6cbe54bca5a4e93ce4 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 48aae8d3e..f1480e0d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,3 @@ -add_library(murmur3 STATIC ../murmur3/murmur3.c) -target_include_directories(murmur3 INTERFACE ../murmur3) -set_target_properties(murmur3 PROPERTIES POSITION_INDEPENDENT_CODE ON) - add_subdirectory(common) add_subdirectory(shady) add_subdirectory(runtime) diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index 3ec44de31..a8e4ce52a 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -93,7 +93,7 @@ struct SpvbFileBuilder_ { struct Dict* extensions_set; }; -static KeyHash hash_u32(uint32_t* p) { return shd_hash_murmur(p, sizeof(uint32_t)); } +static KeyHash hash_u32(uint32_t* p) { return shd_hash(p, sizeof(uint32_t)); } static bool compare_u32s(uint32_t* a, uint32_t* b) { return *a == *b; } KeyHash shd_hash_string(const char** string); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e1c8da998..8d4ee5353 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,5 +1,4 @@ add_library(common list.c dict.c log.c portability.c util.c growy.c arena.c printer.c) -target_link_libraries(common PRIVATE "$") set_property(TARGET common PROPERTY POSITION_INDEPENDENT_CODE ON) # We need to export 'common' because otherwise when using static libraries we will not be able to resolve those symbols diff --git a/src/common/dict.c b/src/common/dict.c index 51f7723e0..3dc9ec144 100644 --- a/src/common/dict.c +++ b/src/common/dict.c @@ -382,22 +382,23 @@ bool shd_dict_iter(struct Dict* dict, size_t* iterator_state, void* key, void* v return true; } -#include "murmur3.h" - -KeyHash shd_hash_murmur(const void* data, size_t size) { - int32_t out[4]; - MurmurHash3_x64_128(data, (int) size, 0x1234567, &out); - - uint32_t final = 0; - final ^= out[0]; - final ^= out[1]; - final ^= out[2]; - final ^= out[3]; - return final; +KeyHash shd_hash(const void* data, size_t size) { + const char* data_chars = (const char*) data; + const unsigned int fnv_prime = 0x811C9DC5; + unsigned int hash = 0; + unsigned int i = 0; + + for (i = 0; i < size; data++, i++) + { + hash *= fnv_prime; + hash ^= (*data_chars); + } + + return hash; } KeyHash shd_hash_ptr(void** p) { - return shd_hash_murmur(p, sizeof(void*)); + return shd_hash(p, sizeof(void*)); } bool shd_compare_ptrs(void** a, void** b) { diff --git a/src/common/dict.h b/src/common/dict.h index b4bb79f3a..5e83b12d8 100644 --- a/src/common/dict.h +++ b/src/common/dict.h @@ -46,7 +46,7 @@ void* shd_dict_insert_get_key_impl(struct Dict*, void* key, void* value); #define shd_set_insert_get_result(K, dict, key) shd_dict_insert_impl(dict, (void*) (&(key)), NULL) bool shd_dict_insert_impl(struct Dict*, void* key, void* value); -KeyHash shd_hash_murmur(const void* data, size_t size); +KeyHash shd_hash(const void* data, size_t size); KeyHash shd_hash_ptr(void**); bool shd_compare_ptrs(void**, void**); diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 93ac240e4..8e288ae09 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -19,7 +19,7 @@ static KeyHash hash_opaque_ptr(OpaqueRef* pvalue) { if (!pvalue) return 0; size_t ptr = *(size_t*) pvalue; - return shd_hash_murmur(&ptr, sizeof(size_t)); + return shd_hash(&ptr, sizeof(size_t)); } static bool cmp_opaque_ptr(OpaqueRef* a, OpaqueRef* b) { diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index bbde9ea4e..b1322be2c 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -1334,7 +1334,7 @@ SpvDef* get_definition_by_id(SpvParser* parser, size_t id) { } KeyHash hash_spvid(SpvId* p) { - return shd_hash_murmur(p, sizeof(SpvId)); + return shd_hash(p, sizeof(SpvId)); } bool compare_spvid(SpvId* pa, SpvId* pb) { diff --git a/src/runtime/cuda/CMakeLists.txt b/src/runtime/cuda/CMakeLists.txt index b15f71e81..20378e635 100644 --- a/src/runtime/cuda/CMakeLists.txt +++ b/src/runtime/cuda/CMakeLists.txt @@ -11,7 +11,6 @@ if (SHADY_ENABLE_RUNTIME_CUDA) add_library(cuda_runtime STATIC cuda_runtime.c cuda_runtime_buffer.c cuda_runtime_program.c) target_link_libraries(cuda_runtime PRIVATE api) target_link_libraries(cuda_runtime PRIVATE "$") - target_link_libraries(cuda_runtime PRIVATE "$") target_link_libraries(cuda_runtime PRIVATE CUDA::cudart CUDA::cuda_driver CUDA::nvrtc) target_link_libraries(runtime PRIVATE "$") diff --git a/src/runtime/vulkan/CMakeLists.txt b/src/runtime/vulkan/CMakeLists.txt index 2eb95afc4..f3f0966d7 100644 --- a/src/runtime/vulkan/CMakeLists.txt +++ b/src/runtime/vulkan/CMakeLists.txt @@ -10,7 +10,6 @@ if (SHADY_ENABLE_RUNTIME_VULKAN) add_library(vk_runtime STATIC vk_runtime.c vk_runtime_device.c vk_runtime_program.c vk_runtime_dispatch.c vk_runtime_buffer.c) target_link_libraries(vk_runtime PRIVATE api) target_link_libraries(vk_runtime PRIVATE "$") - target_link_libraries(vk_runtime PRIVATE "$") target_link_libraries(vk_runtime PRIVATE Vulkan::Headers Vulkan::Vulkan) target_compile_definitions(runtime PUBLIC VK_BACKEND_PRESENT=1) diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index ebd75b2fb..662069586 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -212,7 +212,7 @@ KeyHash shd_hash_string(const char** string); bool shd_compare_string(const char** a, const char** b); static KeyHash hash_spec_program_key(SpecProgramKey* ptr) { - return shd_hash_murmur(ptr->base, sizeof(Program*)) ^ shd_hash_string(&ptr->entry_point); + return shd_hash(ptr->base, sizeof(Program*)) ^ shd_hash_string(&ptr->entry_point); } static bool cmp_spec_program_keys(SpecProgramKey* a, SpecProgramKey* b) { diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index 0a62690ae..4a255af82 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -16,7 +16,7 @@ KeyHash shd_hash_node(const Node**); bool shd_compare_node(const Node**, const Node**); KeyHash hash_cgedge(CGEdge* n) { - return shd_hash_murmur(n, sizeof(CGEdge)); + return shd_hash(n, sizeof(CGEdge)); } bool compare_cgedge(CGEdge* a, CGEdge* b) { diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 147020ec4..5b6661992 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -57,7 +57,7 @@ static void generate_node_payload_hash_fn(Growy* g, json_object* src, json_objec String op_name = json_object_get_string(json_object_object_get(op, "name")); bool ignore = json_object_get_boolean(json_object_object_get(op, "ignore")); if (!ignore) { - shd_growy_append_formatted(g, "\t\thash = hash ^ shd_hash_murmur(&payload.%s, sizeof(payload.%s));\n", op_name, op_name); + shd_growy_append_formatted(g, "\t\thash = hash ^ shd_hash(&payload.%s, sizeof(payload.%s));\n", op_name, op_name); } } shd_growy_append_formatted(g, "\t\tbreak;\n"); diff --git a/src/shady/ir.c b/src/shady/ir.c index 05e5bb55d..10c2db1f9 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -232,7 +232,7 @@ const char* unique_name(IrArena* arena, const char* str) { } KeyHash shd_hash_nodes(Nodes* nodes) { - return shd_hash_murmur(nodes->nodes, sizeof(const Node*) * nodes->count); + return shd_hash(nodes->nodes, sizeof(const Node*) * nodes->count); } bool shd_compare_nodes(Nodes* a, Nodes* b) { @@ -243,7 +243,7 @@ bool shd_compare_nodes(Nodes* a, Nodes* b) { } KeyHash shd_hash_strings(Strings* strings) { - return shd_hash_murmur(strings->strings, sizeof(char*) * strings->count); + return shd_hash(strings->strings, sizeof(char*) * strings->count); } bool shd_compare_strings(Strings* a, Strings* b) { @@ -256,7 +256,7 @@ bool shd_compare_strings(Strings* a, Strings* b) { KeyHash shd_hash_string(const char** string) { if (!*string) return 0; - return shd_hash_murmur(*string, strlen(*string)); + return shd_hash(*string, strlen(*string)); } bool shd_compare_string(const char** a, const char** b) { diff --git a/src/shady/node.c b/src/shady/node.c index 92b276743..87a2ff768 100644 --- a/src/shady/node.c +++ b/src/shady/node.c @@ -26,7 +26,7 @@ KeyHash shd_hash_node(Node** pnode) { goto end; } - KeyHash tag_hash = shd_hash_murmur(&node->tag, sizeof(NodeTag)); + KeyHash tag_hash = shd_hash(&node->tag, sizeof(NodeTag)); KeyHash payload_hash = 0; if (node_type_has_payload[node->tag]) { diff --git a/vcc/vcc_lib.c b/vcc/vcc_lib.c index 132005047..e15504fe8 100644 --- a/vcc/vcc_lib.c +++ b/vcc/vcc_lib.c @@ -13,7 +13,7 @@ #define STRINGIFY(x) STRINGIFY2(x) #define VCC_CLANG STRINGIFY(VCC_CLANG_EXECUTABLE_NAME) -uint32_t shd_hash_murmur(const void* data, size_t size); +uint32_t shd_hash(const void* data, size_t size); void cli_parse_vcc_args(VccConfig* options, int* pargc, char** argv) { int argc = *pargc; @@ -98,7 +98,7 @@ void vcc_run_clang(VccConfig* vcc_options, size_t num_source_files, String* inpu uint32_t hash = 0; for (size_t i = 0; i < num_source_files; i++) { String filename = input_filenames[i]; - hash ^= shd_hash_murmur(filename, strlen(filename)); + hash ^= shd_hash(filename, strlen(filename)); } srand(hash); for (size_t i = 0; i < 32; i++) { From 4a716277d3e5c471370c30f14b5f6683b422c558 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 11 Oct 2024 13:48:43 +0200 Subject: [PATCH 645/693] reorganise built-in code in C backend --- src/backend/c/CMakeLists.txt | 13 +-- src/backend/c/emit_c.c | 85 +++++++++---------- src/backend/c/emit_c.h | 1 - src/backend/c/emit_c_value.c | 15 ++-- src/backend/c/{cuda_prelude.cu => prelude.cu} | 0 .../c/{cuda_builtins.cu => runtime.cu} | 0 src/backend/c/runtime.ispc | 0 ...sl_120_polyfills.glsl => runtime_120.glsl} | 0 8 files changed, 60 insertions(+), 54 deletions(-) rename src/backend/c/{cuda_prelude.cu => prelude.cu} (100%) rename src/backend/c/{cuda_builtins.cu => runtime.cu} (100%) create mode 100644 src/backend/c/runtime.ispc rename src/backend/c/{glsl_120_polyfills.glsl => runtime_120.glsl} (100%) diff --git a/src/backend/c/CMakeLists.txt b/src/backend/c/CMakeLists.txt index b44988143..e65035f52 100644 --- a/src/backend/c/CMakeLists.txt +++ b/src/backend/c/CMakeLists.txt @@ -14,12 +14,15 @@ target_link_libraries(shady_c INTERFACE "$") target_link_libraries(shady_c PRIVATE "$") target_link_libraries(shady_c PRIVATE "$") -embed_file(string shady_cuda_prelude_src cuda_prelude.cu) -embed_file(string shady_cuda_builtins_src cuda_builtins.cu) +embed_file(string shady_cuda_prelude_src prelude.cu) +embed_file(string shady_cuda_runtime_src runtime.cu) target_link_libraries(shady_c PRIVATE "$") -target_link_libraries(shady_c PRIVATE "$") +target_link_libraries(shady_c PRIVATE "$") -embed_file(string shady_glsl_120_polyfills_src glsl_120_polyfills.glsl) -target_link_libraries(shady_c PRIVATE "$") +embed_file(string shady_glsl_runtime_120_src runtime_120.glsl) +target_link_libraries(shady_c PRIVATE "$") + +embed_file(string shady_ispc_runtime_src runtime.ispc) +target_link_libraries(shady_c PRIVATE "$") target_link_libraries(driver PUBLIC "$") diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 012357700..9c963b61a 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -7,8 +7,9 @@ #include "../shady/analysis/scheduler.h" #include "shady_cuda_prelude_src.h" -#include "shady_cuda_builtins_src.h" -#include "shady_glsl_120_polyfills_src.h" +#include "shady_cuda_runtime_src.h" +#include "shady_glsl_runtime_120_src.h" +#include "shady_ispc_runtime_src.h" #include "portability.h" #include "dict.h" @@ -440,52 +441,14 @@ void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Mo .emitted_types = shd_new_dict(Node*, String, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; - // builtins magic (hack) for CUDA - if (emitter.config.dialect == CDialect_CUDA) { - emitter.total_workgroup_size = emitter.arena->config.specializations.workgroup_size[0]; - emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[1]; - emitter.total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[2]; - shd_print(emitter.type_decls, "\ntypedef %s;\n", c_emit_type(&emitter, arr_type(arena, (ArrType) { - .size = shd_int32_literal(arena, 3), - .element_type = shd_uint32_type(arena) - }), "uvec3")); - shd_print(emitter.fn_defs, shady_cuda_builtins_src); - - String private_globals = collect_private_globals_in_struct(&emitter, mod); - if (private_globals) { - emitter.use_private_globals = true; - shd_print(emitter.type_decls, private_globals); - free((void*)private_globals); - } - } - - Nodes decls = shd_module_get_declarations(mod); - for (size_t i = 0; i < decls.count; i++) - c_emit_decl(&emitter, decls.nodes[i]); - - shd_destroy_printer(emitter.type_decls); - shd_destroy_printer(emitter.fn_decls); - shd_destroy_printer(emitter.fn_defs); - Growy* final = shd_new_growy(); Printer* finalp = shd_new_printer_from_growy(final); - if (emitter.config.dialect == CDialect_GLSL) { - shd_print(finalp, "#version %d\n", emitter.config.glsl_version); - } - shd_print(finalp, "/* file generated by shady */\n"); switch (emitter.config.dialect) { - case CDialect_ISPC: - break; - case CDialect_CUDA: { - shd_print(finalp, "#define __shady_workgroup_size %d\n", emitter.total_workgroup_size); - shd_print(finalp, "#define __shady_replicate_thread_local(v) { "); - for (size_t i = 0; i < emitter.total_workgroup_size; i++) - shd_print(finalp, "v, "); - shd_print(finalp, "}\n"); - shd_print(finalp, shady_cuda_prelude_src); + case CDialect_ISPC: { + shd_print(emitter.fn_defs, shady_ispc_runtime_src); break; } case CDialect_C11: @@ -496,16 +459,48 @@ void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Mo shd_print(finalp, "\n#include "); break; case CDialect_GLSL: + shd_print(finalp, "#version %d\n", emitter.config.glsl_version); if (emitter.need_64b_ext) shd_print(finalp, "#extension GL_ARB_gpu_shader_int64: require\n"); shd_print(finalp, "#define ubyte uint\n"); shd_print(finalp, "#define uchar uint\n"); shd_print(finalp, "#define ulong uint\n"); if (emitter.config.glsl_version <= 120) - shd_print(finalp, shady_glsl_120_polyfills_src); + shd_print(finalp, shady_glsl_runtime_120_src); break; + case CDialect_CUDA: { + size_t total_workgroup_size = emitter.arena->config.specializations.workgroup_size[0]; + total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[1]; + total_workgroup_size *= emitter.arena->config.specializations.workgroup_size[2]; + + shd_print(finalp, "#define __shady_workgroup_size %d\n", total_workgroup_size); + shd_print(finalp, "#define __shady_replicate_thread_local(v) { "); + for (size_t i = 0; i < total_workgroup_size; i++) + shd_print(finalp, "v, "); + shd_print(finalp, "}\n"); + shd_print(finalp, shady_cuda_prelude_src); + + shd_print(emitter.type_decls, "\ntypedef %s;\n", c_emit_type(&emitter, arr_type(arena, (ArrType) { + .size = shd_int32_literal(arena, 3), + .element_type = shd_uint32_type(arena) + }), "uvec3")); + shd_print(emitter.fn_defs, shady_cuda_runtime_src); + + String private_globals = collect_private_globals_in_struct(&emitter, mod); + if (private_globals) { + emitter.use_private_globals = true; + shd_print(emitter.type_decls, private_globals); + free((void*) private_globals); + } + break; + } + default: break; } + Nodes decls = shd_module_get_declarations(mod); + for (size_t i = 0; i < decls.count; i++) + c_emit_decl(&emitter, decls.nodes[i]); + shd_print(finalp, "\n/* types: */\n"); shd_growy_append_bytes(final, shd_growy_size(type_decls_g), shd_growy_data(type_decls_g)); @@ -520,6 +515,10 @@ void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Mo shd_print(finalp, "\n"); shd_growy_append_bytes(final, 1, "\0"); + shd_destroy_printer(emitter.type_decls); + shd_destroy_printer(emitter.fn_decls); + shd_destroy_printer(emitter.fn_defs); + shd_destroy_growy(type_decls_g); shd_destroy_growy(fn_decls_g); shd_destroy_growy(fn_defs_g); diff --git a/src/backend/c/emit_c.h b/src/backend/c/emit_c.h index e06288ebf..0aa0f3a5f 100644 --- a/src/backend/c/emit_c.h +++ b/src/backend/c/emit_c.h @@ -45,7 +45,6 @@ typedef struct { struct Dict* emitted_terms; struct Dict* emitted_types; - int total_workgroup_size; bool use_private_globals; Printer* entrypoint_prelude; diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index b5e74b49d..66163dd84 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -698,9 +698,11 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } case subgroup_assume_uniform_op: { - if (emitter->config.dialect != CDialect_ISPC) { - return c_emit_value(emitter, fn, prim_op->operands.nodes[0]); + if (emitter->config.dialect == CDialect_ISPC) { + CTerm value = c_emit_value(emitter, fn, prim_op->operands.nodes[0]); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; } + return c_emit_value(emitter, fn, prim_op->operands.nodes[0]); } case empty_mask_op: case mask_is_thread_active_op: shd_error("lower_me"); @@ -721,8 +723,8 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E case SpvOpGroupNonUniformBroadcastFirst: { CValue value = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(instr.operands))); switch (emitter->config.dialect) { - case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); break; - case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; + case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); + case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); case CDialect_C11: case CDialect_GLSL: shd_error("TODO") } @@ -892,7 +894,10 @@ static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* instr) { String variable_name = unique_name(emitter->arena, "alloca"); CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; c_emit_variable_declaration(emitter, p, get_allocated_type(instr), variable_name, true, NULL); - if (emitter->config.dialect == CDialect_ISPC) { + const Type* ptr_type = instr->type; + shd_deconstruct_qualified_type(&ptr_type); + assert(ptr_type->tag == PtrType_TAG); + if (emitter->config.dialect == CDialect_ISPC && !ptr_type->payload.ptr_type.is_reference) { variable = ispc_varying_ptr_helper(emitter, p, shd_get_unqualified_type(instr->type), variable); } return variable; diff --git a/src/backend/c/cuda_prelude.cu b/src/backend/c/prelude.cu similarity index 100% rename from src/backend/c/cuda_prelude.cu rename to src/backend/c/prelude.cu diff --git a/src/backend/c/cuda_builtins.cu b/src/backend/c/runtime.cu similarity index 100% rename from src/backend/c/cuda_builtins.cu rename to src/backend/c/runtime.cu diff --git a/src/backend/c/runtime.ispc b/src/backend/c/runtime.ispc new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/c/glsl_120_polyfills.glsl b/src/backend/c/runtime_120.glsl similarity index 100% rename from src/backend/c/glsl_120_polyfills.glsl rename to src/backend/c/runtime_120.glsl From 5882b6178864e96af7edc1a6fa298f6458683d93 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 14:20:32 +0200 Subject: [PATCH 646/693] use static inline wrappers for nominal defs --- include/shady/ir/base.h | 2 +- include/shady/ir/composite.h | 4 ++-- include/shady/ir/decl.h | 7 +++++-- include/shady/ir/function.h | 17 ++++++++--------- include/shady/ir/type.h | 3 ++- src/backend/c/emit_c.c | 2 +- src/backend/c/emit_c_control_flow.c | 6 +++--- src/backend/c/emit_c_type.c | 4 ++-- src/backend/c/emit_c_value.c | 18 +++++++++--------- src/frontend/llvm/l2s_instr.c | 2 +- src/frontend/llvm/l2s_meta.c | 2 +- src/frontend/llvm/l2s_value.c | 2 +- src/frontend/slim/infer.c | 2 +- src/frontend/spirv/s2s.c | 12 ++++++------ src/shady/check.c | 4 ++-- src/shady/ir.c | 2 +- src/shady/ir/composite.c | 6 +++--- src/shady/ir/decl.c | 4 ++-- src/shady/ir/function.c | 8 ++++---- src/shady/ir/type.c | 4 ++-- src/shady/passes/lower_cf_instrs.c | 4 ++-- src/shady/passes/normalize_builtins.c | 2 +- src/shady/passes/restructure.c | 2 +- src/shady/passes/scope_heuristic.c | 2 +- zhady/shady.i | 2 ++ 25 files changed, 64 insertions(+), 59 deletions(-) diff --git a/include/shady/ir/base.h b/include/shady/ir/base.h index b44a72243..d6fdfe4e5 100644 --- a/include/shady/ir/base.h +++ b/include/shady/ir/base.h @@ -49,6 +49,6 @@ String string(IrArena*, const char*); // see also: format_string in util.h String shd_fmt_string_irarena(IrArena* arena, const char* str, ...); -String unique_name(IrArena*, const char* base_name); +String shd_make_unique_name(IrArena* arena, const char* str); #endif diff --git a/include/shady/ir/composite.h b/include/shady/ir/composite.h index 19cf7e756..1f47d89a7 100644 --- a/include/shady/ir/composite.h +++ b/include/shady/ir/composite.h @@ -8,7 +8,7 @@ const Node* extract_helper(const Node* composite, const Node* index); const Node* tuple_helper(IrArena*, Nodes contents); -void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); -void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack); +void shd_enter_composite_type(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); +void shd_enter_composite_type_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack); #endif diff --git a/include/shady/ir/decl.h b/include/shady/ir/decl.h index 4f31934bd..a2e3f42e0 100644 --- a/include/shady/ir/decl.h +++ b/include/shady/ir/decl.h @@ -4,7 +4,10 @@ #include "shady/ir/base.h" #include "shady/ir/grammar.h" -Node* constant(Module*, Nodes annotations, const Type*, const char* name); -Node* global_var(Module*, Nodes annotations, const Type*, String, AddressSpace); +Node* _shd_constant(Module*, Nodes annotations, const Type*, const char* name); +Node* _shd_global_var(Module*, Nodes annotations, const Type*, String, AddressSpace); + +static inline Node* constant(Module* m, Nodes annotations, const Type* t, const char* name) { return _shd_constant(m, annotations, t, name); } +static inline Node* global_var(Module* m, Nodes annotations, const Type* t, String name, AddressSpace as) { return _shd_global_var(m, annotations, t, name, as); } #endif diff --git a/include/shady/ir/function.h b/include/shady/ir/function.h index 00da58d1b..dfbb2ceea 100644 --- a/include/shady/ir/function.h +++ b/include/shady/ir/function.h @@ -4,15 +4,14 @@ #include "shady/ir/grammar.h" #include "shady/ir/type.h" -Node* param(IrArena*, const Type* type, const char* name); - -Node* function(Module*, Nodes params, const char* name, Nodes annotations, Nodes return_types); - -// basic blocks -Node* basic_block(IrArena*, Nodes params, const char* name); -static inline Node* case_(IrArena* a, Nodes params) { - return basic_block(a, params, NULL); -} +Node* _shd_param(IrArena*, const Type* type, const char* name); +Node* _shd_function(Module*, Nodes params, const char* name, Nodes annotations, Nodes return_types); +Node* _shd_basic_block(IrArena*, Nodes params, const char* name); + +static inline Node* param(IrArena* a, const Type* type, const char* name) { return _shd_param(a, type, name); } +static inline Node* function(Module* m, Nodes params, const char* name, Nodes annotations, Nodes return_types) { return _shd_function(m, params, name, annotations, return_types); } +static inline Node* basic_block(IrArena* a, Nodes params, const char* name) { return _shd_basic_block(a, params, name); } +static inline Node* case_(IrArena* a, Nodes params) { return basic_block(a, params, NULL); } /// For typing instructions that return nothing (equivalent to C's void f()) static inline const Type* empty_multiple_return_type(IrArena* arena) { diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index 33d1fceee..7100666d8 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -11,7 +11,8 @@ static inline const Node* unit_type(IrArena* arena) { }); } -Type* nominal_type(Module*, Nodes annotations, String name); +Type* _shd_nominal_type(Module*, Nodes annotations, String name); +static inline Type* nominal_type(Module* m, Nodes annotations, String name) { return _shd_nominal_type(m, annotations, name); } const Type* shd_get_actual_mask_type(IrArena* arena); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 9c963b61a..e795ebcee 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -107,7 +107,7 @@ static bool has_forward_declarations(CDialect dialect) { /// hack for ISPC: there is no nice way to get a set of varying pointers (instead of a "pointer to a varying") pointing to a varying global CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term) { - String interm = unique_name(emitter->arena, "intermediary_ptr_value"); + String interm = shd_make_unique_name(emitter->arena, "intermediary_ptr_value"); assert(ptr_type->tag == PtrType_TAG); const Type* ut = shd_as_qualified_type(ptr_type, true); const Type* vt = shd_as_qualified_type(ptr_type, false); diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index 675795a06..99d11df52 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -44,7 +44,7 @@ static Strings emit_variable_declarations(Emitter* emitter, FnEmitter* fn, Print for (size_t i = 0; i < types.count; i++) { String name = given_names ? given_names->strings[i] : given_name; assert(name); - names[i] = unique_name(emitter->arena, name); + names[i] = shd_make_unique_name(emitter->arena, name); if (init_values) { CTerm initializer = c_emit_value(emitter, fn, init_values->nodes[i]); c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); @@ -145,7 +145,7 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { for (size_t i = 0; i < variables.count; i++) { arr[i] = shd_get_value_name_unsafe(variables.nodes[i]); if (!arr[i]) - arr[i] = unique_name(emitter->arena, "phi"); + arr[i] = shd_make_unique_name(emitter->arena, "phi"); } Strings param_names = shd_strings(emitter->arena, variables.count, arr); Strings eparams = emit_variable_declarations(emitter, fn, p, NULL, ¶m_names, shd_get_param_types(emitter->arena, params), true, &loop.initial_args); @@ -192,7 +192,7 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin } else if (args.count == 1) { shd_print(block_printer, "\nreturn %s;", to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[0]))); } else { - String packed = unique_name(emitter->arena, "pack_return"); + String packed = shd_make_unique_name(emitter->arena, "pack_return"); LARRAY(CValue, values, args.count); for (size_t i = 0; i < args.count; i++) values[i] = to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i])); diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index 6b86ae3f4..539d731bc 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -213,7 +213,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { // break; //} - emitted = unique_name(emitter->arena, "Record"); + emitted = shd_make_unique_name(emitter->arena, "Record"); String prefixed = shd_format_string_arena(emitter->arena->arena, "struct %s", emitted); c_emit_nominal_type_body(emitter, prefixed, type); // C puts structs in their own namespace so we always need the prefix @@ -247,7 +247,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { return c_emit_fn_head(emitter, type, center, NULL); } case Type_ArrType_TAG: { - emitted = unique_name(emitter->arena, "Array"); + emitted = shd_make_unique_name(emitter->arena, "Array"); String prefixed = shd_format_string_arena(emitter->arena->arena, "struct %s", emitted); Growy* g = shd_new_growy(); Printer* p = shd_new_printer_from_growy(g); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 66163dd84..082ab154f 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -111,7 +111,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No case Value_Undef_TAG: { if (emitter->config.dialect == CDialect_GLSL) return c_emit_value(emitter, fn, get_default_zero_value(emitter->arena, value->payload.undef.type)); - String name = unique_name(emitter->arena, "undef"); + String name = shd_make_unique_name(emitter->arena, "undef"); // c_emit_variable_declaration(emitter, block_printer, value->type, name, true, NULL); c_emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); emitted = name; @@ -156,7 +156,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No emitted = shd_format_string_arena(emitter->arena->arena, "{ %s }", emitted); if (p2) { - String tmp = unique_name(emitter->arena, "composite"); + String tmp = shd_make_unique_name(emitter->arena, "composite"); shd_print(p2, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); emitted = tmp; } else { @@ -239,7 +239,7 @@ CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CT shd_print(p, "%s;", to_cvalue(emitter, term)); return empty_term(); } - String bind_to = unique_name(emitter->arena, ""); + String bind_to = shd_make_unique_name(emitter->arena, ""); c_emit_variable_declaration(emitter, p, t, bind_to, false, &term); return term_from_cvalue(bind_to); } @@ -548,8 +548,8 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node switch (emitter->config.dialect) { case CDialect_CUDA: case CDialect_C11: { - String src = unique_name(arena, "bitcast_src"); - String dst = unique_name(arena, "bitcast_result"); + String src = shd_make_unique_name(arena, "bitcast_src"); + String dst = shd_make_unique_name(arena, "bitcast_result"); shd_print(p, "\n%s = %s;", c_emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); shd_print(p, "\n%s;", c_emit_type(emitter, dst_type, dst)); shd_print(p, "\nmemcpy(&%s, &%s, sizeof(%s));", dst, src, src); @@ -619,7 +619,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node bool insert = prim_op->op == insert_op; if (insert) { - String dst = unique_name(arena, "modified"); + String dst = shd_make_unique_name(arena, "modified"); shd_print(p, "\n%s = %s;", c_emit_type(emitter, node->type, dst), acc); acc = dst; term = term_from_cvalue(dst); @@ -671,7 +671,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } case shuffle_op: { - String dst = unique_name(arena, "shuffled"); + String dst = shd_make_unique_name(arena, "shuffled"); const Node* lhs = prim_op->operands.nodes[0]; const Node* rhs = prim_op->operands.nodes[1]; String lhs_e = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[0])); @@ -822,7 +822,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer // so hum we just need to introduce a temporary variable to hold the pointer expression so far, and go again from there // See https://github.com/ispc/ispc/issues/2496 if (emitter->config.dialect == CDialect_ISPC) { - String interm = unique_name(arena, "lea_intermediary_ptr_value"); + String interm = shd_make_unique_name(arena, "lea_intermediary_ptr_value"); shd_print(p, "\n%s = %s;", c_emit_type(emitter, shd_as_qualified_type(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); acc = term_from_cvalue(interm); } @@ -891,7 +891,7 @@ static const Type* get_allocated_type(const Node* alloc) { } static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* instr) { - String variable_name = unique_name(emitter->arena, "alloca"); + String variable_name = shd_make_unique_name(emitter->arena, "alloca"); CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; c_emit_variable_declaration(emitter, p, get_allocated_type(instr), variable_name, true, NULL); const Type* ptr_type = instr->type; diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index aee2a963f..8c8b6af0c 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -274,7 +274,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); bool idk; //element_t = shd_as_qualified_type(element_t, false); - enter_composite_indices(&element_t, &idk, shd_nodes(a, ops.count - 2, &ops.nodes[2]), true); + shd_enter_composite_type_indices(&element_t, &idk, shd_nodes(a, ops.count - 2, &ops.nodes[2]), true); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); r = prim_op_helper(a, reinterpret_op, shd_singleton(untyped_ptr_t), BIND_PREV_R(typed_ptr)); } diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index 1f9c5d46c..fbb4a5b97 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -26,7 +26,7 @@ static const Node* convert_named_tuple_metadata(Parser* p, LLVMValueRef v, Strin IrArena* a = shd_module_get_arena(p->dst); String name = LLVMGetValueName(v); if (!name || strlen(name) == 0) - name = unique_name(a, node_name); + name = shd_make_unique_name(a, node_name); Node* g = global_var(p->dst, shd_singleton(annotation(a, (Annotation) { .name = "LLVMMetaData" })), unit_type(a), name, AsDebugInfo); const Node* r = ref_decl_helper(a, g); shd_dict_insert(LLVMValueRef, const Type*, p->map, v, r); diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index 5d1259b61..2eab7f0f3 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -77,7 +77,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { case LLVMConstantExprValueKind: { String name = LLVMGetValueName(v); if (!name || strlen(name) == 0) - name = unique_name(a, "constant_expr"); + name = shd_make_unique_name(a, "constant_expr"); Nodes annotations = shd_singleton(annotation(a, (Annotation) { .name = "Inline" })); assert(t); Node* decl = constant(p->dst, annotations, t, name); diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 0ba5b2a24..071b454e3 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -291,7 +291,7 @@ static const Node* infer_case(Context* ctx, const Node* node, Nodes inferred_arg for (size_t i = 0; i < inferred_arg_type.count; i++) { if (node->payload.basic_block.params.count == 0) { // syntax sugar: make up a parameter if there was none - nparams[i] = param(a, inferred_arg_type.nodes[i], unique_name(a, "_")); + nparams[i] = param(a, inferred_arg_type.nodes[i], shd_make_unique_name(a, "_")); } else { const Param* old_param = &node->payload.basic_block.params.nodes[i]->payload.param; // for the param type: use the inferred one if none is already provided diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index b1322be2c..9712fc022 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -626,7 +626,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpTypeStruct: { parser->defs[result].type = Typ; String name = get_name(parser, result); - name = name ? name : unique_name(parser->arena, "struct_type"); + name = name ? name : shd_make_unique_name(parser->arena, "struct_type"); Node* nominal_type_decl = nominal_type(parser->mod, shd_empty(parser->arena), name); const Node* nom_t_ref = type_decl_ref(parser->arena, (TypeDeclRef) { .decl = nominal_type_decl @@ -732,7 +732,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } case SpvOpVariable: { String name = get_name(parser, result); - name = name ? name : unique_name(parser->arena, "global_variable"); + name = name ? name : shd_make_unique_name(parser->arena, "global_variable"); AddressSpace as = convert_storage_class(instruction[3]); const Type* contents_t = get_def_type(parser, result_t); @@ -776,9 +776,9 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { String name = get_name(parser, result); if (!name) - name = unique_name(parser->arena, "function"); + name = shd_make_unique_name(parser->arena, "function"); else - name = unique_name(parser->arena, name); + name = shd_make_unique_name(parser->arena, name); Nodes annotations = shd_empty(parser->arena); annotations = shd_nodes_append(parser->arena, annotations, annotation(parser->arena, (Annotation) { .name = "Restructure" })); @@ -896,7 +896,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { parser->defs[result].type = BB; String bb_name = get_name(parser, result); - bb_name = bb_name ? bb_name : unique_name(parser->arena, "basic_block"); + bb_name = bb_name ? bb_name : shd_make_unique_name(parser->arena, "basic_block"); Node* block = basic_block(parser->arena, params, bb_name); parser->defs[result].node = block; @@ -917,7 +917,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpPhi: { parser->defs[result].type = Value; String phi_name = get_name(parser, result); - phi_name = phi_name ? phi_name : unique_name(parser->arena, "phi"); + phi_name = phi_name ? phi_name : shd_make_unique_name(parser->arena, "phi"); parser->defs[result].node = param(parser->arena, shd_as_qualified_type(get_def_type(parser, result_t), false), phi_name); assert(size % 2 == 1); diff --git a/src/shady/check.c b/src/shady/check.c index 647702d27..ac461d51b 100644 --- a/src/shady/check.c +++ b/src/shady/check.c @@ -462,7 +462,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* t = source->type; bool uniform = shd_deconstruct_qualified_type(&t); - enter_composite_indices(&t, &uniform, indices, true); + shd_enter_composite_type_indices(&t, &uniform, indices, true); if (prim_op.op == insert_op) { const Node* inserted_data = prim_op.operands.nodes[1]; @@ -766,7 +766,7 @@ const Type* check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); const Type* pointee_type = base_ptr_type->payload.ptr_type.pointed_type; - enter_composite(&pointee_type, &uniform, lea.index, true); + shd_enter_composite_type(&pointee_type, &uniform, lea.index, true); return qualified_type(a, (QualifiedType) { .is_uniform = uniform, diff --git a/src/shady/ir.c b/src/shady/ir.c index 10c2db1f9..931b08afe 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -227,7 +227,7 @@ String shd_fmt_string_irarena(IrArena* arena, const char* str, ...) { return result; } -const char* unique_name(IrArena* arena, const char* str) { +const char* shd_make_unique_name(IrArena* arena, const char* str) { return shd_fmt_string_irarena(arena, "%s_%d", str, _shd_allocate_node_id(arena, NULL)); } diff --git a/src/shady/ir/composite.c b/src/shady/ir/composite.c index 1cf22f209..14b59e8a2 100644 --- a/src/shady/ir/composite.c +++ b/src/shady/ir/composite.c @@ -28,7 +28,7 @@ const Node* tuple_helper(IrArena* a, Nodes contents) { return composite_helper(a, t, contents); } -void enter_composite(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack) { +void shd_enter_composite_type(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack) { const Type* current_type = *datatype; if (selector->arena->config.check_types) { @@ -77,9 +77,9 @@ void enter_composite(const Type** datatype, bool* uniform, const Node* selector, *datatype = current_type; } -void enter_composite_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack) { +void shd_enter_composite_type_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack) { for(size_t i = 0; i < indices.count; i++) { const Node* selector = indices.nodes[i]; - enter_composite(datatype, uniform, selector, allow_entering_pack); + shd_enter_composite_type(datatype, uniform, selector, allow_entering_pack); } } diff --git a/src/shady/ir/decl.c b/src/shady/ir/decl.c index f1a9f9b48..dcd84e3d1 100644 --- a/src/shady/ir/decl.c +++ b/src/shady/ir/decl.c @@ -6,7 +6,7 @@ bool shd_compare_nodes(Nodes* a, Nodes* b); -Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { +Node* _shd_constant(Module* mod, Nodes annotations, const Type* hint, String name) { IrArena* arena = mod->arena; Constant cnst = { .annotations = annotations, @@ -26,7 +26,7 @@ Node* constant(Module* mod, Nodes annotations, const Type* hint, String name) { return decl; } -Node* global_var(Module* mod, Nodes annotations, const Type* type, const char* name, AddressSpace as) { +Node* _shd_global_var(Module* mod, Nodes annotations, const Type* type, const char* name, AddressSpace as) { const Node* existing = shd_module_get_declaration(mod, name); if (existing) { assert(existing->tag == GlobalVariable_TAG); diff --git a/src/shady/ir/function.c b/src/shady/ir/function.c index 4bd540a5b..5345056cb 100644 --- a/src/shady/ir/function.c +++ b/src/shady/ir/function.c @@ -4,7 +4,7 @@ #include -Node* param(IrArena* arena, const Type* type, const char* name) { +Node* _shd_param(IrArena* arena, const Type* type, const char* name) { Param param = { .type = type, .name = string(arena, name), @@ -20,7 +20,7 @@ Node* param(IrArena* arena, const Type* type, const char* name) { return _shd_create_node_helper(arena, node, NULL); } -Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, Nodes return_types) { +Node* _shd_function(Module* mod, Nodes params, const char* name, Nodes annotations, Nodes return_types) { assert(!mod->sealed); IrArena* arena = mod->arena; Function payload = { @@ -53,7 +53,7 @@ Node* function(Module* mod, Nodes params, const char* name, Nodes annotations, N return fn; } -Node* basic_block(IrArena* arena, Nodes params, const char* name) { +Node* _shd_basic_block(IrArena* arena, Nodes params, const char* name) { BasicBlock payload = { .params = params, .body = NULL, @@ -141,4 +141,4 @@ void shd_set_abstraction_body(Node* abs, const Node* body) { case BasicBlock_TAG: abs->payload.basic_block.body = body; break; default: assert(false); } -} \ No newline at end of file +} diff --git a/src/shady/ir/type.c b/src/shady/ir/type.c index 8419f4376..79cd6e3e2 100644 --- a/src/shady/ir/type.c +++ b/src/shady/ir/type.c @@ -320,7 +320,7 @@ String shd_get_type_name(IrArena* arena, const Type* t) { case Type_TypeDeclRef_TAG: return t->payload.type_decl_ref.decl->payload.nom_type.name; default: break; } - return unique_name(arena, shd_get_node_tag_string(t->tag)); + return shd_make_unique_name(arena, shd_get_node_tag_string(t->tag)); } const Type* maybe_multiple_return(IrArena* arena, Nodes types) { @@ -553,7 +553,7 @@ const Node* get_fill_type_size(const Type* composite_t) { } } -Type* nominal_type(Module* mod, Nodes annotations, String name) { +Type* _shd_nominal_type(Module* mod, Nodes annotations, String name) { IrArena* arena = shd_module_get_arena(mod); NominalType payload = { .name = string(arena, name), diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 77f7e255d..7722ece49 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -61,7 +61,7 @@ static const Node* process_node(Context* ctx, const Node* node) { false_block = shd_rewrite_node(r, payload.if_false); } else { assert(yield_types.count == 0); - false_block = basic_block(a, shd_nodes(a, 0, NULL), unique_name(a, "if_false")); + false_block = basic_block(a, shd_nodes(a, 0, NULL), shd_make_unique_name(a, "if_false")); shd_set_abstraction_body((Node*) false_block, join(a, (Join) { .join_point = jp, .args = shd_nodes(a, 0, NULL), .mem = shd_get_abstraction_mem(false_block) })); } @@ -101,7 +101,7 @@ static const Node* process_node(Context* ctx, const Node* node) { shd_dict_insert(const Node*, Nodes, ctx->structured_join_tokens, node, jps); Nodes new_params = shd_recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_block)); - Node* loop_header_block = basic_block(a, new_params, unique_name(a, "loop_header")); + Node* loop_header_block = basic_block(a, new_params, shd_make_unique_name(a, "loop_header")); BodyBuilder* inner_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_header_block)); Node* inner_control_case = case_(a, shd_singleton(continue_point)); diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 71f143a2d..1ff24f7d7 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -39,7 +39,7 @@ static const Type* get_req_cast(Context* ctx, const Node* src) { const Type* src_req_cast = get_req_cast(ctx, src->payload.ptr_composite_element.ptr); if (src_req_cast) { bool u = shd_deconstruct_qualified_type(&src_req_cast); - enter_composite(&src_req_cast, &u, src->payload.ptr_composite_element.index, false); + shd_enter_composite_type(&src_req_cast, &u, src->payload.ptr_composite_element.index, false); return src_req_cast; } break; diff --git a/src/shady/passes/restructure.c b/src/shady/passes/restructure.c index 4a23a1aca..192fc3385 100644 --- a/src/shady/passes/restructure.c +++ b/src/shady/passes/restructure.c @@ -146,7 +146,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, } // We use a basic block for the exit ladder because we don't know what the ladder needs to do ahead of time - Node* inner_exit_ladder_bb = basic_block(a, shd_empty(a), unique_name(a, "exit_ladder_inline_me")); + Node* inner_exit_ladder_bb = basic_block(a, shd_empty(a), shd_make_unique_name(a, "exit_ladder_inline_me")); // Just jumps to the actual ladder Node* structured_target = case_(a, shd_nodes(a, oargs.count, nparams)); diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index 4e6c440fa..2a1f02be9 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -115,7 +115,7 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, visit_acyclic_cfg_domtree(sub_cfg->entry, a, arr, flipped, node, lt); if (is_loop > 0) - surrounding = shd_nodes_prepend(a, surrounding, string_lit_helper(a, unique_name(a, "loop_body"))); + surrounding = shd_nodes_prepend(a, surrounding, string_lit_helper(a, shd_make_unique_name(a, "loop_body"))); visit_looptree_prepend(a, arr, node, surrounding); // Remove one level of scoping for the loop headers (forcing reconvergence) diff --git a/zhady/shady.i b/zhady/shady.i index aaf87f699..87e6ccd03 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -8,6 +8,8 @@ * arena +* arena + * m * m From 7affa7b41fafa467e72072e4950bd53ddf2e9723 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 14:24:12 +0200 Subject: [PATCH 647/693] type.c: add shd_ to most remaining helpers --- include/shady/ir/type.h | 36 ++++++------- src/backend/c/emit_c_type.c | 2 +- src/backend/c/emit_c_value.c | 6 +-- src/backend/spirv/emit_spv_type.c | 2 +- src/frontend/llvm/l2s_value.c | 4 +- src/frontend/slim/infer.c | 4 +- src/frontend/spirv/s2s.c | 4 +- src/runtime/vulkan/vk_runtime_program.c | 2 +- src/shady/check.c | 60 +++++++++++----------- src/shady/ir/type.c | 62 +++++++++++------------ src/shady/passes/lower_fill.c | 2 +- src/shady/passes/lower_logical_pointers.c | 10 ++-- src/shady/passes/lower_memory_layout.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 10 ++-- src/shady/passes/lower_subgroup_ops.c | 4 +- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/opt_demote_alloca.c | 4 +- src/shady/transform/ir_gen_helpers.c | 2 +- zhady/shady.i | 17 ------- 19 files changed, 109 insertions(+), 126 deletions(-) diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index 7100666d8..c536b5375 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -46,8 +46,8 @@ bool shd_is_addr_space_uniform(IrArena*, AddressSpace); String shd_get_type_name(IrArena* arena, const Type* t); -const Type* maybe_multiple_return(IrArena* arena, Nodes types); -Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type); +const Type* shd_maybe_multiple_return(IrArena* arena, Nodes types); +Nodes shd_unwrap_multiple_yield_types(IrArena* arena, const Type* type); /// Collects the annotated types in the list of variables /// NB: this is different from get_values_types, that function uses node.type, whereas this one uses node.payload.var.type @@ -68,32 +68,32 @@ Nodes shd_strip_qualifiers(IrArena*, Nodes); Nodes shd_add_qualifiers(IrArena*, Nodes, bool); // Pack (vector) type helpers -const Type* get_packed_type_element(const Type*); -size_t get_packed_type_width(const Type*); -size_t deconstruct_packed_type(const Type**); +const Type* shd_get_packed_type_element(const Type* type); +size_t shd_get_packed_type_width(const Type* type); +size_t shd_deconstruct_packed_type(const Type** type); /// Helper for creating pack types, wraps type in a pack_type if width > 1 -const Type* maybe_packed_type_helper(const Type*, size_t width); +const Type* shd_maybe_packed_type_helper(const Type* type, size_t width); /// 'Maybe' variants that work with any types, and assume width=1 for non-packed types /// Useful for writing generic type checking code ! -const Type* get_maybe_packed_type_element(const Type*); -size_t get_maybe_packed_type_width(const Type*); -size_t deconstruct_maybe_packed_type(const Type**); +const Type* shd_get_maybe_packed_type_element(const Type* type); +size_t shd_get_maybe_packed_type_width(const Type* type); +size_t shd_deconstruct_maybe_packed_type(const Type** type); // Pointer type helpers -const Type* get_pointer_type_element(const Type*); -AddressSpace deconstruct_pointer_type(const Type**); +const Type* shd_get_pointer_type_element(const Type* type); +AddressSpace shd_deconstruct_pointer_type(const Type** type); // Nominal type helpers -const Node* get_nominal_type_decl(const Type*); -const Type* get_nominal_type_body(const Type*); -const Node* get_maybe_nominal_type_decl(const Type*); -const Type* get_maybe_nominal_type_body(const Type*); +const Node* shd_get_nominal_type_decl(const Type* type); +const Type* shd_get_nominal_type_body(const Type* type); +const Node* shd_get_maybe_nominal_type_decl(const Type* type); +const Type* shd_get_maybe_nominal_type_body(const Type* type); // Composite type helpers -Nodes get_composite_type_element_types(const Type*); -const Node* get_fill_type_element_type(const Type*); -const Node* get_fill_type_size(const Type*); +Nodes shd_get_composite_type_element_types(const Type* type); +const Node* shd_get_fill_type_element_type(const Type* composite_t); +const Node* shd_get_fill_type_size(const Type* composite_t); #endif diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index 539d731bc..c08d87640 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -98,7 +98,7 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons } free_tmp_str(parameters); - String c_decl = c_emit_type(emitter, maybe_multiple_return(emitter->arena, codom), center); + String c_decl = c_emit_type(emitter, shd_maybe_multiple_return(emitter->arena, codom), center); if (entry_point) { switch (emitter->config.dialect) { case CDialect_C11: diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 082ab154f..74a16c150 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -247,7 +247,7 @@ CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CT static const Type* get_first_op_scalar_type(Nodes ops) { const Type* t = shd_first(ops)->type; shd_deconstruct_qualified_type(&t); - deconstruct_maybe_packed_type(&t); + shd_deconstruct_maybe_packed_type(&t); return t; } @@ -510,7 +510,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case offset_of_op: { const Type* t = shd_first(prim_op->type_arguments); while (t->tag == TypeDeclRef_TAG) { - t = get_nominal_type_body(t); + t = shd_get_nominal_type_body(t); } const Node* index = shd_first(prim_op->operands); uint64_t index_literal = shd_get_int_literal_value(*shd_resolve_to_int_literal(index), false); @@ -813,7 +813,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer break; } case TypeDeclRef_TAG: { - pointee_type = get_nominal_type_body(pointee_type); + pointee_type = shd_get_nominal_type_body(pointee_type); SHADY_FALLTHROUGH } case RecordType_TAG: { diff --git a/src/backend/spirv/emit_spv_type.c b/src/backend/spirv/emit_spv_type.c index f2f734671..f0a53ff95 100644 --- a/src/backend/spirv/emit_spv_type.c +++ b/src/backend/spirv/emit_spv_type.c @@ -139,7 +139,7 @@ SpvId spv_emit_type(Emitter* emitter, const Type* type) { } case PtrType_TAG: { SpvStorageClass sc = spv_emit_addr_space(emitter, type->payload.ptr_type.address_space); const Type* pointed_type = type->payload.ptr_type.pointed_type; - if (get_maybe_nominal_type_decl(pointed_type) && sc == SpvStorageClassPhysicalStorageBuffer) { + if (shd_get_maybe_nominal_type_decl(pointed_type) && sc == SpvStorageClassPhysicalStorageBuffer) { new = spvb_forward_ptr_type(emitter->file_builder, sc); spv_register_emitted(emitter, NULL, type, new); SpvId pointee = spv_emit_type(emitter, pointed_type); diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index 2eab7f0f3..cd0c349ae 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -12,7 +12,7 @@ static const Node* data_composite(const Type* t, size_t size, LLVMValueRef v) { size_t idc; const char* raw_bytes = LLVMGetAsString(v, &idc); for (size_t i = 0; i < size; i++) { - const Type* et = get_fill_type_element_type(t); + const Type* et = shd_get_fill_type_element_type(t); switch (et->tag) { case Int_TAG: { switch (et->payload.int_type.width) { @@ -100,7 +100,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { return data_composite(t, width, v); } case LLVMConstantStructValueKind: { - const Node* actual_t = get_maybe_nominal_type_body(t); + const Node* actual_t = shd_get_maybe_nominal_type_body(t); assert(actual_t->tag == RecordType_TAG); size_t size = actual_t->payload.record_type.members.count; LARRAY(const Node*, elements, size); diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index 071b454e3..b82568dbf 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -246,7 +246,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec Nodes omembers = node->payload.composite.contents; LARRAY(const Node*, inferred, omembers.count); if (elem_type) { - Nodes expected_members = get_composite_type_element_types(elem_type); + Nodes expected_members = shd_get_composite_type_element_types(elem_type); for (size_t i = 0; i < omembers.count; i++) inferred[i] = infer(ctx, omembers.nodes[i], qualified_type(a, (QualifiedType) { .is_uniform = uniform, .type = expected_members.nodes[i] })); } else { @@ -272,7 +272,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec composite_t = expected_type; } assert(composite_t); - const Node* element_t = get_fill_type_element_type(composite_t); + const Node* element_t = shd_get_fill_type_element_type(composite_t); const Node* value = infer(ctx, node->payload.fill.value, qualified_type(a, (QualifiedType) { .is_uniform = uniform, .type = element_t })); return fill(a, (Fill) { .type = composite_t, .value = value }); } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 9712fc022..0199261e4 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -736,7 +736,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { AddressSpace as = convert_storage_class(instruction[3]); const Type* contents_t = get_def_type(parser, result_t); - AddressSpace as2 = deconstruct_pointer_type(&contents_t); + AddressSpace as2 = shd_deconstruct_pointer_type(&contents_t); assert(as == as2); assert(shd_is_data_type(contents_t)); @@ -1087,7 +1087,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { if (op == SpvOpCopyMemory) { const Type* elem_t = src->type; shd_deconstruct_qualified_type(&elem_t); - deconstruct_pointer_type(&elem_t); + shd_deconstruct_pointer_type(&elem_t); cnt = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = size_of_op, .type_arguments = shd_singleton(elem_t), diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 75f1b2e41..2c8faf7ed 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -56,7 +56,7 @@ static void write_value(unsigned char* tgt, const Node* value) { case Composite_TAG: { Nodes values = value->payload.composite.contents; const Type* struct_t = value->payload.composite.type; - struct_t = get_maybe_nominal_type_body(struct_t); + struct_t = shd_get_maybe_nominal_type_body(struct_t); if (struct_t->tag == RecordType_TAG) { LARRAY(FieldLayout, fields, values.count); diff --git a/src/shady/check.c b/src/shady/check.c index ac461d51b..019f8a510 100644 --- a/src/shady/check.c +++ b/src/shady/check.c @@ -76,7 +76,7 @@ const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { } const Node* maybe_record_type = ptr_type.pointed_type; if (maybe_record_type->tag == TypeDeclRef_TAG) - maybe_record_type = get_nominal_type_body(maybe_record_type); + maybe_record_type = shd_get_nominal_type_body(maybe_record_type); if (maybe_record_type && maybe_record_type->tag == RecordType_TAG && maybe_record_type->payload.record_type.special == DecorateBlock) { return NULL; } @@ -130,7 +130,7 @@ const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { const Type* check_type_composite(IrArena* arena, Composite composite) { if (composite.type) { assert(shd_is_data_type(composite.type)); - Nodes expected_member_types = get_composite_type_element_types(composite.type); + Nodes expected_member_types = shd_get_composite_type_element_types(composite.type); bool is_uniform = true; assert(composite.contents.count == expected_member_types.count); for (size_t i = 0; i < composite.contents.count; i++) { @@ -160,7 +160,7 @@ const Type* check_type_composite(IrArena* arena, Composite composite) { const Type* check_type_fill(IrArena* arena, Fill payload) { assert(shd_is_data_type(payload.type)); - const Node* element_t = get_fill_type_element_type(payload.type); + const Node* element_t = shd_get_fill_type_element_type(payload.type); const Node* value_t = payload.value->type; bool u = shd_deconstruct_qualified_type(&value_t); assert(shd_is_subtype(element_t, value_t)); @@ -228,7 +228,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 1); const Type* type = shd_first(prim_op.operands)->type; - assert(shd_is_arithm_type(get_maybe_packed_type_element(shd_get_unqualified_type(type)))); + assert(shd_is_arithm_type(shd_get_maybe_packed_type_element(shd_get_unqualified_type(type)))); return type; } case rshift_arithm_op: @@ -242,14 +242,14 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { bool uniform_result = shd_deconstruct_qualified_type(&first_operand_type); uniform_result &= shd_deconstruct_qualified_type(&second_operand_type); - size_t value_simd_width = deconstruct_maybe_packed_type(&first_operand_type); - size_t shift_simd_width = deconstruct_maybe_packed_type(&second_operand_type); + size_t value_simd_width = shd_deconstruct_maybe_packed_type(&first_operand_type); + size_t shift_simd_width = shd_deconstruct_maybe_packed_type(&second_operand_type); assert(value_simd_width == shift_simd_width); assert(first_operand_type->tag == Int_TAG); assert(second_operand_type->tag == Int_TAG); - return shd_as_qualified_type(maybe_packed_type_helper(first_operand_type, value_simd_width), uniform_result); + return shd_as_qualified_type(shd_maybe_packed_type_helper(first_operand_type, value_simd_width), uniform_result); } case add_carry_op: case sub_borrow_op: @@ -271,7 +271,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* operand_type = arg->type; bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); - assert(shd_is_arithm_type(get_maybe_packed_type_element(operand_type))); + assert(shd_is_arithm_type(shd_get_maybe_packed_type_element(operand_type))); assert(first_operand_type == operand_type && "operand type mismatch"); result_uniform &= operand_uniform; @@ -290,7 +290,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 1); const Type* type = shd_first(prim_op.operands)->type; - assert(shd_has_boolean_ops(get_maybe_packed_type_element(shd_get_unqualified_type(type)))); + assert(shd_has_boolean_ops(shd_get_maybe_packed_type_element(shd_get_unqualified_type(type)))); return type; } case or_op: @@ -306,7 +306,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* operand_type = arg->type; bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); - assert(shd_has_boolean_ops(get_maybe_packed_type_element(operand_type))); + assert(shd_has_boolean_ops(shd_get_maybe_packed_type_element(operand_type))); assert(first_operand_type == operand_type && "operand type mismatch"); result_uniform &= operand_uniform; @@ -323,7 +323,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.type_arguments.count == 0); assert(prim_op.operands.count == 2); const Type* first_operand_type = shd_get_unqualified_type(shd_first(prim_op.operands)->type); - size_t first_operand_width = get_maybe_packed_type_width(first_operand_type); + size_t first_operand_width = shd_get_maybe_packed_type_width(first_operand_type); bool result_uniform = true; for (size_t i = 0; i < prim_op.operands.count; i++) { @@ -331,13 +331,13 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* operand_type = arg->type; bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); - assert((ordered ? shd_is_ordered_type : shd_is_comparable_type)(get_maybe_packed_type_element(operand_type))); + assert((ordered ? shd_is_ordered_type : shd_is_comparable_type)(shd_get_maybe_packed_type_element(operand_type))); assert(first_operand_type == operand_type && "operand type mismatch"); result_uniform &= operand_uniform; } - return shd_as_qualified_type(maybe_packed_type_helper(bool_type(arena), first_operand_width), + return shd_as_qualified_type(shd_maybe_packed_type_helper(bool_type(arena), first_operand_width), result_uniform); } case sqrt_op: @@ -354,9 +354,9 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 1); const Node* src_type = shd_first(prim_op.operands)->type; bool uniform = shd_deconstruct_qualified_type(&src_type); - size_t width = deconstruct_maybe_packed_type(&src_type); + size_t width = shd_deconstruct_maybe_packed_type(&src_type); assert(src_type->tag == Float_TAG); - return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); + return shd_as_qualified_type(shd_maybe_packed_type_helper(src_type, width), uniform); } case pow_op: { assert(prim_op.type_arguments.count == 0); @@ -369,7 +369,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* operand_type = arg->type; bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); - assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); + assert(shd_get_maybe_packed_type_element(operand_type)->tag == Float_TAG); assert(first_operand_type == operand_type && "operand type mismatch"); result_uniform &= operand_uniform; @@ -388,7 +388,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { const Type* operand_type = arg->type; bool operand_uniform = shd_deconstruct_qualified_type(&operand_type); - assert(get_maybe_packed_type_element(operand_type)->tag == Float_TAG); + assert(shd_get_maybe_packed_type_element(operand_type)->tag == Float_TAG); assert(first_operand_type == operand_type && "operand type mismatch"); result_uniform &= operand_uniform; @@ -403,9 +403,9 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 1); const Node* src_type = shd_first(prim_op.operands)->type; bool uniform = shd_deconstruct_qualified_type(&src_type); - size_t width = deconstruct_maybe_packed_type(&src_type); + size_t width = shd_deconstruct_maybe_packed_type(&src_type); assert(src_type->tag == Float_TAG || src_type->tag == Int_TAG && src_type->payload.int_type.is_signed); - return shd_as_qualified_type(maybe_packed_type_helper(src_type, width), uniform); + return shd_as_qualified_type(shd_maybe_packed_type_helper(src_type, width), uniform); } case align_of_op: case size_of_op: { @@ -432,14 +432,14 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(prim_op.operands.count == 3); const Type* condition_type = prim_op.operands.nodes[0]->type; bool condition_uniform = shd_deconstruct_qualified_type(&condition_type); - size_t width = deconstruct_maybe_packed_type(&condition_type); + size_t width = shd_deconstruct_maybe_packed_type(&condition_type); const Type* alternatives_types[2]; bool alternatives_all_uniform = true; for (size_t i = 0; i < 2; i++) { alternatives_types[i] = prim_op.operands.nodes[1 + i]->type; alternatives_all_uniform &= shd_deconstruct_qualified_type(&alternatives_types[i]); - size_t alternative_width = deconstruct_maybe_packed_type(&alternatives_types[i]); + size_t alternative_width = shd_deconstruct_maybe_packed_type(&alternatives_types[i]); assert(alternative_width == width); } @@ -447,7 +447,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { // todo find true supertype assert(are_types_identical(2, alternatives_types)); - return shd_as_qualified_type(maybe_packed_type_helper(alternatives_types[0], width), + return shd_as_qualified_type(shd_maybe_packed_type_helper(alternatives_types[0], width), alternatives_all_uniform && condition_uniform); } case insert_op: @@ -569,8 +569,8 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { assert(sampled_image_t->tag == SampledImageType_TAG); const Type* image_t = sampled_image_t->payload.sampled_image_type.image_type; assert(image_t->tag == ImageType_TAG); - size_t coords_dim = deconstruct_packed_type(&coords_t); - return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = maybe_packed_type_helper(image_t->payload.image_type.sampled_type, 4) }); + size_t coords_dim = shd_deconstruct_packed_type(&coords_t); + return qualified_type(arena, (QualifiedType) { .is_uniform = false, .type = shd_maybe_packed_type_helper(image_t->payload.image_type.sampled_type, 4) }); } case PRIMOPS_COUNT: assert(false); } @@ -593,7 +593,7 @@ static Nodes check_value_call(const Node* callee, Nodes argument_types) { const Type* callee_type = callee->type; SHADY_UNUSED bool callee_uniform = shd_deconstruct_qualified_type(&callee_type); - AddressSpace as = deconstruct_pointer_type(&callee_type); + AddressSpace as = shd_deconstruct_pointer_type(&callee_type); assert(as == AsGeneric); assert(callee_type->tag == FnType_TAG); @@ -611,7 +611,7 @@ const Type* check_type_call(IrArena* arena, Call call) { assert(is_value(argument)); } Nodes argument_types = shd_get_values_types(arena, args); - return maybe_multiple_return(arena, check_value_call(call.callee, argument_types)); + return shd_maybe_multiple_return(arena, check_value_call(call.callee, argument_types)); } static void ensure_types_are_data_types(const Nodes* yield_types) { @@ -704,12 +704,12 @@ const Type* check_type_local_alloc(IrArena* a, LocalAlloc alloc) { const Type* check_type_load(IrArena* a, Load load) { const Node* ptr_type = load.ptr->type; bool ptr_uniform = shd_deconstruct_qualified_type(&ptr_type); - size_t width = deconstruct_maybe_packed_type(&ptr_type); + size_t width = shd_deconstruct_maybe_packed_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); const PtrType* node_ptr_type_ = &ptr_type->payload.ptr_type; const Type* elem_type = node_ptr_type_->pointed_type; - elem_type = maybe_packed_type_helper(elem_type, width); + elem_type = shd_maybe_packed_type_helper(elem_type, width); return shd_as_qualified_type(elem_type, ptr_uniform && shd_is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); } @@ -717,12 +717,12 @@ const Type* check_type_load(IrArena* a, Load load) { const Type* check_type_store(IrArena* a, Store store) { const Node* ptr_type = store.ptr->type; bool ptr_uniform = shd_deconstruct_qualified_type(&ptr_type); - size_t width = deconstruct_maybe_packed_type(&ptr_type); + size_t width = shd_deconstruct_maybe_packed_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); const PtrType* ptr_type_payload = &ptr_type->payload.ptr_type; const Type* elem_type = ptr_type_payload->pointed_type; assert(elem_type); - elem_type = maybe_packed_type_helper(elem_type, width); + elem_type = shd_maybe_packed_type_helper(elem_type, width); // we don't enforce uniform stores - but we care about storing the right thing :) const Type* val_expected_type = qualified_type(a, (QualifiedType) { .is_uniform = !a->config.is_simt, diff --git a/src/shady/ir/type.c b/src/shady/ir/type.c index 79cd6e3e2..7f8d32726 100644 --- a/src/shady/ir/type.c +++ b/src/shady/ir/type.c @@ -185,7 +185,7 @@ bool shd_is_data_type(const Type* type) { return type->payload.record_type.special == NotSpecial; } case Type_TypeDeclRef_TAG: - return !get_nominal_type_body(type) || shd_is_data_type(get_nominal_type_body(type)); + return !shd_get_nominal_type_body(type) || shd_is_data_type(shd_get_nominal_type_body(type)); // qualified types are not data types because that information is only meant for values case Type_QualifiedType_TAG: return false; // values cannot contain abstractions @@ -323,7 +323,7 @@ String shd_get_type_name(IrArena* arena, const Type* t) { return shd_make_unique_name(arena, shd_get_node_tag_string(t->tag)); } -const Type* maybe_multiple_return(IrArena* arena, Nodes types) { +const Type* shd_maybe_multiple_return(IrArena* arena, Nodes types) { switch (types.count) { case 0: return empty_multiple_return_type(arena); case 1: return types.nodes[0]; @@ -336,7 +336,7 @@ const Type* maybe_multiple_return(IrArena* arena, Nodes types) { SHADY_UNREACHABLE; } -Nodes unwrap_multiple_yield_types(IrArena* arena, const Type* type) { +Nodes shd_unwrap_multiple_yield_types(IrArena* arena, const Type* type) { switch (type->tag) { case RecordType_TAG: if (type->payload.record_type.special == MultipleReturn) @@ -424,34 +424,34 @@ Nodes shd_add_qualifiers(IrArena* arena, Nodes tys, bool uniform) { return shd_nodes(arena, tys.count, arr); } -const Type* get_packed_type_element(const Type* type) { +const Type* shd_get_packed_type_element(const Type* type) { const Type* t = type; - deconstruct_packed_type(&t); + shd_deconstruct_packed_type(&t); return t; } -size_t get_packed_type_width(const Type* type) { +size_t shd_get_packed_type_width(const Type* type) { const Type* t = type; - return deconstruct_packed_type(&t); + return shd_deconstruct_packed_type(&t); } -size_t deconstruct_packed_type(const Type** type) { +size_t shd_deconstruct_packed_type(const Type** type) { assert((*type)->tag == PackType_TAG); - return deconstruct_maybe_packed_type(type); + return shd_deconstruct_maybe_packed_type(type); } -const Type* get_maybe_packed_type_element(const Type* type) { +const Type* shd_get_maybe_packed_type_element(const Type* type) { const Type* t = type; - deconstruct_maybe_packed_type(&t); + shd_deconstruct_maybe_packed_type(&t); return t; } -size_t get_maybe_packed_type_width(const Type* type) { +size_t shd_get_maybe_packed_type_width(const Type* type) { const Type* t = type; - return deconstruct_maybe_packed_type(&t); + return shd_deconstruct_maybe_packed_type(&t); } -size_t deconstruct_maybe_packed_type(const Type** type) { +size_t shd_deconstruct_maybe_packed_type(const Type** type) { const Type* t = *type; assert(shd_is_data_type(t)); if (t->tag == PackType_TAG) { @@ -461,7 +461,7 @@ size_t deconstruct_maybe_packed_type(const Type** type) { return 1; } -const Type* maybe_packed_type_helper(const Type* type, size_t width) { +const Type* shd_maybe_packed_type_helper(const Type* type, size_t width) { assert(width > 0); if (width == 1) return type; @@ -471,30 +471,30 @@ const Type* maybe_packed_type_helper(const Type* type, size_t width) { }); } -const Type* get_pointer_type_element(const Type* type) { +const Type* shd_get_pointer_type_element(const Type* type) { const Type* t = type; - deconstruct_pointer_type(&t); + shd_deconstruct_pointer_type(&t); return t; } -AddressSpace deconstruct_pointer_type(const Type** type) { +AddressSpace shd_deconstruct_pointer_type(const Type** type) { const Type* t = *type; assert(t->tag == PtrType_TAG); *type = t->payload.ptr_type.pointed_type; return t->payload.ptr_type.address_space; } -const Node* get_nominal_type_decl(const Type* type) { +const Node* shd_get_nominal_type_decl(const Type* type) { assert(type->tag == TypeDeclRef_TAG); - return get_maybe_nominal_type_decl(type); + return shd_get_maybe_nominal_type_decl(type); } -const Type* get_nominal_type_body(const Type* type) { +const Type* shd_get_nominal_type_body(const Type* type) { assert(type->tag == TypeDeclRef_TAG); - return get_maybe_nominal_type_body(type); + return shd_get_maybe_nominal_type_body(type); } -const Node* get_maybe_nominal_type_decl(const Type* type) { +const Node* shd_get_maybe_nominal_type_decl(const Type* type) { if (type->tag == TypeDeclRef_TAG) { const Node* decl = type->payload.type_decl_ref.decl; assert(decl->tag == NominalType_TAG); @@ -503,17 +503,17 @@ const Node* get_maybe_nominal_type_decl(const Type* type) { return NULL; } -const Type* get_maybe_nominal_type_body(const Type* type) { - const Node* decl = get_maybe_nominal_type_decl(type); +const Type* shd_get_maybe_nominal_type_body(const Type* type) { + const Node* decl = shd_get_maybe_nominal_type_decl(type); if (decl) return decl->payload.nom_type.body; return type; } -Nodes get_composite_type_element_types(const Type* type) { +Nodes shd_get_composite_type_element_types(const Type* type) { switch (is_type(type)) { case Type_TypeDeclRef_TAG: { - type = get_nominal_type_body(type); + type = shd_get_nominal_type_body(type); assert(type->tag == RecordType_TAG); SHADY_FALLTHROUGH } @@ -522,11 +522,11 @@ Nodes get_composite_type_element_types(const Type* type) { } case Type_ArrType_TAG: case Type_PackType_TAG: { - size_t size = shd_get_int_literal_value(*shd_resolve_to_int_literal(get_fill_type_size(type)), false); + size_t size = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_fill_type_size(type)), false); if (size >= 1024) { shd_warn_print("Potential performance issue: creating a really big array of composites of types (size=%d)!\n", size); } - const Type* element_type = get_fill_type_element_type(type); + const Type* element_type = shd_get_fill_type_element_type(type); LARRAY(const Type*, types, size); for (size_t i = 0; i < size; i++) { types[i] = element_type; @@ -537,7 +537,7 @@ Nodes get_composite_type_element_types(const Type* type) { } } -const Node* get_fill_type_element_type(const Type* composite_t) { +const Node* shd_get_fill_type_element_type(const Type* composite_t) { switch (composite_t->tag) { case ArrType_TAG: return composite_t->payload.arr_type.element_type; case PackType_TAG: return composite_t->payload.pack_type.element_type; @@ -545,7 +545,7 @@ const Node* get_fill_type_element_type(const Type* composite_t) { } } -const Node* get_fill_type_size(const Type* composite_t) { +const Node* shd_get_fill_type_size(const Type* composite_t) { switch (composite_t->tag) { case ArrType_TAG: return composite_t->payload.arr_type.size; case PackType_TAG: return shd_int32_literal(composite_t->arena, composite_t->payload.pack_type.width); diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index a16ab5286..733b8be61 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -16,7 +16,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case Fill_TAG: { const Type* composite_t = shd_rewrite_node(r, node->payload.fill.type); - size_t actual_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(get_fill_type_size(composite_t)), false); + size_t actual_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_fill_type_size(composite_t)), false); const Node* value = shd_rewrite_node(r, node->payload.fill.value); LARRAY(const Node*, copies, actual_size); for (size_t i = 0; i < actual_size; i++) { diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index dcbc3fe88..2d6b31935 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -19,11 +19,11 @@ static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node while (true) { const Type* actual_type = shd_get_unqualified_type(ptr->type); assert(actual_type->tag == PtrType_TAG); - actual_type = get_pointer_type_element(actual_type); + actual_type = shd_get_pointer_type_element(actual_type); if (expected_type == actual_type) break; - actual_type = get_maybe_nominal_type_body(actual_type); + actual_type = shd_get_maybe_nominal_type_body(actual_type); assert(expected_type != actual_type && "todo: rework this function if we change how nominal types are handled"); switch (actual_type->tag) { @@ -76,7 +76,7 @@ static const Node* process(Context* ctx, const Node* old) { const Type* actual_type = shd_get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) - ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); + ptr = guess_pointer_casts(ctx, bb, ptr, shd_get_pointer_type_element(expected_type)); return bind_last_instruction_and_wrap_in_block(bb, ptr_composite_element(a, (PtrCompositeElement) { .ptr = ptr, .index = shd_rewrite_node(r, payload.index)})); } case PrimOp_TAG: { @@ -104,7 +104,7 @@ static const Node* process(Context* ctx, const Node* old) { const Type* actual_type = shd_get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) - ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); + ptr = guess_pointer_casts(ctx, bb, ptr, shd_get_pointer_type_element(expected_type)); return load(a, (Load) { .ptr = yield_value_and_wrap_in_block(bb, ptr), .mem = shd_rewrite_node(r, payload.mem) }); } case Store_TAG: { @@ -117,7 +117,7 @@ static const Node* process(Context* ctx, const Node* old) { const Type* actual_type = shd_get_unqualified_type(ptr->type); BodyBuilder* bb = begin_block_pure(a); if (expected_type != actual_type) - ptr = guess_pointer_casts(ctx, bb, ptr, get_pointer_type_element(expected_type)); + ptr = guess_pointer_casts(ctx, bb, ptr, shd_get_pointer_type_element(expected_type)); return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { .ptr = ptr, .value = shd_rewrite_node(r, payload.value), .mem = shd_rewrite_node(r, payload.mem) })); } case GlobalVariable_TAG: { diff --git a/src/shady/passes/lower_memory_layout.c b/src/shady/passes/lower_memory_layout.c index 09b219d32..b93bd04a4 100644 --- a/src/shady/passes/lower_memory_layout.c +++ b/src/shady/passes/lower_memory_layout.c @@ -32,7 +32,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* n = shd_rewrite_node(&ctx->rewriter, shd_first(old->payload.prim_op.operands)); const IntLiteral* literal = shd_resolve_to_int_literal(n); assert(literal); - t = get_maybe_nominal_type_body(t); + t = shd_get_maybe_nominal_type_body(t); uint64_t offset_in_bytes = (uint64_t) shd_get_record_field_offset_in_bytes(a, t, literal->value); const Node* offset_literal = int_literal(a, (IntLiteral) { .width = shd_get_arena_config(a)->memory.ptr_size, .is_signed = false, .value = offset_in_bytes }); return offset_literal; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 778c71bce..095e3b139 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -107,7 +107,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type case TypeDeclRef_TAG: case RecordType_TAG: { const Type* compound_type = element_type; - compound_type = get_maybe_nominal_type_body(compound_type); + compound_type = shd_get_maybe_nominal_type_body(compound_type); Nodes member_types = compound_type->payload.record_type.members; LARRAY(const Node*, loaded, member_types.count); @@ -120,14 +120,14 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type } case ArrType_TAG: case PackType_TAG: { - const Node* size = get_fill_type_size(element_type); + const Node* size = shd_get_fill_type_size(element_type); if (size->tag != IntLiteral_TAG) { shd_error_print("Size of type "); shd_log_node(ERROR, element_type); shd_error_print(" is not known a compile-time!\n"); } size_t components_count = shd_get_int_literal_value(*shd_resolve_to_int_literal(size), 0); - const Type* component_type = get_fill_type_element_type(element_type); + const Type* component_type = shd_get_fill_type_element_type(element_type); LARRAY(const Node*, components, components_count); const Node* offset = address; for (size_t i = 0; i < components_count; i++) { @@ -224,14 +224,14 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element } case ArrType_TAG: case PackType_TAG: { - const Node* size = get_fill_type_size(element_type); + const Node* size = shd_get_fill_type_size(element_type); if (size->tag != IntLiteral_TAG) { shd_error_print("Size of type "); shd_log_node(ERROR, element_type); shd_error_print(" is not known a compile-time!\n"); } size_t components_count = shd_get_int_literal_value(*shd_resolve_to_int_literal(size), 0); - const Type* component_type = get_fill_type_element_type(element_type); + const Type* component_type = shd_get_fill_type_element_type(element_type); const Node* offset = address; for (size_t i = 0; i < components_count; i++) { gen_serialisation(ctx, bb, component_type, arr, offset, gen_extract(bb, value, shd_singleton(shd_int32_literal(a, i)))); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 50f6509e2..637fa1921 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -46,12 +46,12 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, const Node* t, const Node* param) { IrArena* a = ctx->rewriter.dst_arena; const Type* original_t = t; - t = get_maybe_nominal_type_body(t); + t = shd_get_maybe_nominal_type_body(t); switch (is_type(t)) { case Type_ArrType_TAG: case Type_RecordType_TAG: { assert(t->payload.record_type.special == 0); - Nodes element_types = get_composite_type_element_types(t); + Nodes element_types = shd_get_composite_type_element_types(t); LARRAY(const Node*, elements, element_types.count); for (size_t i = 0; i < element_types.count; i++) { const Node* e = gen_extract(bb, param, shd_singleton(shd_uint32_literal(a, i))); diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index 89a97cbd1..f3725450b 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -13,7 +13,7 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { IrArena* a = ctx->rewriter.dst_arena; const Type* dst_type = old->type; shd_deconstruct_qualified_type(&dst_type); - size_t width = deconstruct_maybe_packed_type(&dst_type); + size_t width = shd_deconstruct_maybe_packed_type(&dst_type); if (width == 1) return shd_recreate_node(&ctx->rewriter, old); LARRAY(const Node*, elements, width); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index b46c9ab69..9de776a2e 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -193,7 +193,7 @@ static const Node* process(Context* ctx, const Node* old) { shd_rewrite_node(r, payload.mem); PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { - const Type* access_type = get_pointer_type_element(shd_get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); + const Type* access_type = shd_get_pointer_type_element(shd_get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); if (shd_is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { if (k.src_alloca->new == shd_rewrite_node(r, payload.ptr)) break; @@ -211,7 +211,7 @@ static const Node* process(Context* ctx, const Node* old) { shd_rewrite_node(r, payload.mem); PtrSourceKnowledge k = get_ptr_source_knowledge(ctx, payload.ptr); if (k.src_alloca) { - const Type* access_type = get_pointer_type_element(shd_get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); + const Type* access_type = shd_get_pointer_type_element(shd_get_unqualified_type(shd_rewrite_node(r, payload.ptr->type))); if (shd_is_reinterpret_cast_legal(access_type, k.src_alloca->type)) { if (k.src_alloca->new == shd_rewrite_node(r, payload.ptr)) break; diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 98a08479c..666d30405 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -303,7 +303,7 @@ const Node* get_default_zero_value(IrArena* a, const Type* t) { case Type_ArrType_TAG: case Type_PackType_TAG: case Type_TypeDeclRef_TAG: { - Nodes elem_tys = get_composite_type_element_types(t); + Nodes elem_tys = shd_get_composite_type_element_types(t); if (elem_tys.count >= 1024) { shd_warn_print("Potential performance issue: creating a really composite full of zero/default values (size=%d)!\n", elem_tys.count); } diff --git a/zhady/shady.i b/zhady/shady.i index 87e6ccd03..1b688b2b4 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -5,23 +5,6 @@ %module shady %{ #include "shady/ir.h" - -* arena - -* arena - -* m - -* m - -* m - -* mname - -* v - -* arena* node - #include "shady/runtime.h" #include "shady/driver.h" #include "shady/config.h" From 1e1c73a7483c955794d060e43350637d83dea0f3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 14:35:15 +0200 Subject: [PATCH 648/693] start melting ir_gen_helpers away --- include/shady/ir/builtin.h | 2 + include/shady/ir/memory_layout.h | 3 ++ include/shady/ir/type.h | 1 + src/backend/c/emit_c_value.c | 2 +- src/frontend/llvm/l2s_instr.c | 2 + src/frontend/llvm/l2s_value.c | 2 +- src/frontend/spirv/s2s.c | 2 +- src/shady/ir/builtin.c | 22 ++++++++ src/shady/ir/type.c | 26 ++++++++++ src/shady/passes/specialize_entry_point.c | 2 +- src/shady/transform/ir_gen_helpers.c | 62 ----------------------- src/shady/transform/ir_gen_helpers.h | 6 --- src/shady/transform/memory_layout.c | 14 +++++ 13 files changed, 74 insertions(+), 72 deletions(-) diff --git a/include/shady/ir/builtin.h b/include/shady/ir/builtin.h index 470ad2459..40dbe0844 100644 --- a/include/shady/ir/builtin.h +++ b/include/shady/ir/builtin.h @@ -56,4 +56,6 @@ Builtin shd_get_decl_builtin(const Node* decl); int32_t shd_get_builtin_spv_id(Builtin builtin); +bool shd_is_builtin_load_op(const Node* n, Builtin* out); + #endif diff --git a/include/shady/ir/memory_layout.h b/include/shady/ir/memory_layout.h index c1178c00f..543896f8b 100644 --- a/include/shady/ir/memory_layout.h +++ b/include/shady/ir/memory_layout.h @@ -35,4 +35,7 @@ IntSizes shd_float_to_int_width(FloatSizes width); size_t shd_get_type_bitwidth(const Type* t); +const Node* _shd_lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes indices); +static inline const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes indices) { return _shd_lea_helper(a, ptr, offset, indices); } + #endif diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index c536b5375..06bca8cdc 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -15,6 +15,7 @@ Type* _shd_nominal_type(Module*, Nodes annotations, String name); static inline Type* nominal_type(Module* m, Nodes annotations, String name) { return _shd_nominal_type(m, annotations, name); } const Type* shd_get_actual_mask_type(IrArena* arena); +const Node* shd_get_default_value(IrArena* a, const Type* t); bool shd_is_subtype(const Type* supertype, const Type* type); void shd_check_subtype(const Type* supertype, const Type* type); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 74a16c150..b21bed171 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -110,7 +110,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No case Value_False_TAG: return term_from_cvalue("false"); case Value_Undef_TAG: { if (emitter->config.dialect == CDialect_GLSL) - return c_emit_value(emitter, fn, get_default_zero_value(emitter->arena, value->payload.undef.type)); + return c_emit_value(emitter, fn, shd_get_default_value(emitter->arena, value->payload.undef.type)); String name = shd_make_unique_name(emitter->arena, "undef"); // c_emit_variable_declaration(emitter, block_printer, value->type, name, true, NULL); c_emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 8c8b6af0c..400b20708 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -1,5 +1,7 @@ #include "l2s_private.h" +#include "shady/ir/memory_layout.h" + #include "../shady/transform/ir_gen_helpers.h" #include "portability.h" diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index cd0c349ae..b8b3eb2da 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -125,7 +125,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { case LLVMUndefValueValueKind: return undef(a, (Undef) { .type = convert_type(p, LLVMTypeOf(v)) }); case LLVMConstantAggregateZeroValueKind: - return get_default_zero_value(a, convert_type(p, LLVMTypeOf(v))); + return shd_get_default_value(a, convert_type(p, LLVMTypeOf(v))); case LLVMConstantArrayValueKind: { assert(t->tag == ArrType_TAG); size_t arr_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(t->payload.arr_type.size), false); diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index 0199261e4..a56cf64bf 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -707,7 +707,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpConstantNull: { const Type* element_t = get_def_type(parser, result_t); parser->defs[result].type = Value; - parser->defs[result].node = get_default_zero_value(parser->arena, element_t); + parser->defs[result].node = shd_get_default_value(parser->arena, element_t); break; } case SpvOpConstantFalse: { diff --git a/src/shady/ir/builtin.c b/src/shady/ir/builtin.c index c4633d13f..358065f02 100644 --- a/src/shady/ir/builtin.c +++ b/src/shady/ir/builtin.c @@ -86,3 +86,25 @@ int32_t shd_get_builtin_spv_id(Builtin builtin) { return 0; return spv_builtins[builtin]; } + +bool shd_is_builtin_load_op(const Node* n, Builtin* out) { + assert(is_instruction(n)); + if (n->tag == Load_TAG) { + const Node* src = n->payload.load.ptr; + if (src->tag == RefDecl_TAG) + src = src->payload.ref_decl.decl; + if (src->tag == GlobalVariable_TAG) { + const Node* a = shd_lookup_annotation(src, "Builtin"); + if (a) { + String bn = shd_get_annotation_string_payload(a); + assert(bn); + Builtin b = shd_get_builtin_by_name(bn); + if (b != BuiltinsCount) { + *out = b; + return true; + } + } + } + } + return false; +} diff --git a/src/shady/ir/type.c b/src/shady/ir/type.c index 7f8d32726..1a5b4da04 100644 --- a/src/shady/ir/type.c +++ b/src/shady/ir/type.c @@ -574,3 +574,29 @@ Type* _shd_nominal_type(Module* mod, Nodes annotations, String name) { _shd_module_add_decl(mod, decl); return decl; } + +const Node* shd_get_default_value(IrArena* a, const Type* t) { + switch (is_type(t)) { + case NotAType: shd_error("") + case Type_Int_TAG: return int_literal(a, (IntLiteral) { .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed, .value = 0 }); + case Type_Float_TAG: return float_literal(a, (FloatLiteral) { .width = t->payload.float_type.width, .value = 0 }); + case Type_Bool_TAG: return false_lit(a); + case Type_PtrType_TAG: return null_ptr(a, (NullPtr) { .ptr_type = t }); + case Type_QualifiedType_TAG: return shd_get_default_value(a, t->payload.qualified_type.type); + case Type_RecordType_TAG: + case Type_ArrType_TAG: + case Type_PackType_TAG: + case Type_TypeDeclRef_TAG: { + Nodes elem_tys = shd_get_composite_type_element_types(t); + if (elem_tys.count >= 1024) { + shd_warn_print("Potential performance issue: creating a really composite full of zero/default values (size=%d)!\n", elem_tys.count); + } + LARRAY(const Node*, elems, elem_tys.count); + for (size_t i = 0; i < elem_tys.count; i++) + elems[i] = shd_get_default_value(a, elem_tys.nodes[i]); + return composite_helper(a, t, shd_nodes(a, elem_tys.count, elems)); + } + default: break; + } + return NULL; +} diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index 37f325a31..cb480ce73 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -20,7 +20,7 @@ static const Node* process(Context* ctx, const Node* node) { switch (node->tag) { case PrimOp_TAG: { Builtin b; - if (is_builtin_load_op(node, &b) && b == BuiltinWorkgroupSize) { + if (shd_is_builtin_load_op(node, &b) && b == BuiltinWorkgroupSize) { const Type* t = pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }); uint32_t wg_size[3]; wg_size[0] = a->config.specializations.workgroup_size[0]; diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 666d30405..e9ac58c36 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -13,20 +13,6 @@ #include #include -const Node* lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes indices) { - const Node* lea = ptr_array_element_offset(a, (PtrArrayElementOffset) { - .ptr = ptr, - .offset = offset, - }); - for (size_t i = 0; i < indices.count; i++) { - lea = ptr_composite_element(a, (PtrCompositeElement) { - .ptr = lea, - .index = indices.nodes[i], - }); - } - return lea; -} - Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { assert(shd_get_arena_config(_shd_get_bb_arena(bb))->check_types); const Node* instruction = call(_shd_get_bb_arena(bb), (Call) { .callee = callee, .args = args, .mem = bb_mem(bb) }); @@ -196,28 +182,6 @@ const Node* gen_builtin_load(Module* m, BodyBuilder* bb, Builtin b) { return gen_load(bb, ref_decl_helper(_shd_get_bb_arena(bb), get_or_create_builtin(m, b, NULL))); } -bool is_builtin_load_op(const Node* n, Builtin* out) { - assert(is_instruction(n)); - if (n->tag == Load_TAG) { - const Node* src = n->payload.load.ptr; - if (src->tag == RefDecl_TAG) - src = src->payload.ref_decl.decl; - if (src->tag == GlobalVariable_TAG) { - const Node* a = shd_lookup_annotation(src, "Builtin"); - if (a) { - String bn = shd_get_annotation_string_payload(a); - assert(bn); - Builtin b = shd_get_builtin_by_name(bn); - if (b != BuiltinsCount) { - *out = b; - return true; - } - } - } - } - return false; -} - const Node* find_or_process_decl(Rewriter* rewriter, const char* name) { Nodes old_decls = shd_module_get_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { @@ -290,29 +254,3 @@ const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, cons val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } - -const Node* get_default_zero_value(IrArena* a, const Type* t) { - switch (is_type(t)) { - case NotAType: shd_error("") - case Type_Int_TAG: return int_literal(a, (IntLiteral) { .width = t->payload.int_type.width, .is_signed = t->payload.int_type.is_signed, .value = 0 }); - case Type_Float_TAG: return float_literal(a, (FloatLiteral) { .width = t->payload.float_type.width, .value = 0 }); - case Type_Bool_TAG: return false_lit(a); - case Type_PtrType_TAG: return null_ptr(a, (NullPtr) { .ptr_type = t }); - case Type_QualifiedType_TAG: return get_default_zero_value(a, t->payload.qualified_type.type); - case Type_RecordType_TAG: - case Type_ArrType_TAG: - case Type_PackType_TAG: - case Type_TypeDeclRef_TAG: { - Nodes elem_tys = shd_get_composite_type_element_types(t); - if (elem_tys.count >= 1024) { - shd_warn_print("Potential performance issue: creating a really composite full of zero/default values (size=%d)!\n", elem_tys.count); - } - LARRAY(const Node*, elems, elem_tys.count); - for (size_t i = 0; i < elem_tys.count; i++) - elems[i] = get_default_zero_value(a, elem_tys.nodes[i]); - return composite_helper(a, t, shd_nodes(a, elem_tys.count, elems)); - } - default: break; - } - return NULL; -} diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index e74eaefc4..9a1b1869b 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -4,8 +4,6 @@ #include "shady/ir.h" #include "shady/ir/builtin.h" -const Node* lea_helper(IrArena*, const Node*, const Node*, Nodes); - void gen_push_value_stack(BodyBuilder* bb, const Node* value); void gen_push_values_stack(BodyBuilder* bb, Nodes values); const Node* gen_pop_value_stack(BodyBuilder*, const Type* type); @@ -49,8 +47,4 @@ const Node* convert_int_extend_according_to_dst_t(BodyBuilder*, const Type* dst_ const Node* convert_int_zero_extend(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_sign_extend(BodyBuilder*, const Type* dst_type, const Node* src); -const Node* get_default_zero_value(IrArena*, const Type*); - -bool is_builtin_load_op(const Node*, Builtin*); - #endif diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index 0a0015345..a65f18376 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -145,3 +145,17 @@ size_t shd_get_type_bitwidth(const Type* t) { } return SIZE_MAX; } + +const Node* _shd_lea_helper(IrArena* a, const Node* ptr, const Node* offset, Nodes indices) { + const Node* lea = ptr_array_element_offset(a, (PtrArrayElementOffset) { + .ptr = ptr, + .offset = offset, + }); + for (size_t i = 0; i < indices.count; i++) { + lea = ptr_composite_element(a, (PtrCompositeElement) { + .ptr = lea, + .index = indices.nodes[i], + }); + } + return lea; +} From aa7fdce5f1b15839080d7dd638c024e3fa41f520 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 14:51:56 +0200 Subject: [PATCH 649/693] rename all functions in body_builder.h --- include/shady/body_builder.h | 61 +++++---- src/backend/spirv/spirv_lift_globals_ssbo.c | 6 +- src/frontend/llvm/l2s.c | 4 +- src/frontend/llvm/l2s_instr.c | 60 ++++----- src/frontend/llvm/l2s_postprocess.c | 4 +- src/frontend/llvm/l2s_value.c | 4 +- src/frontend/slim/bind.c | 14 +- src/frontend/slim/infer.c | 4 +- src/frontend/slim/parser.c | 94 ++++++------- src/frontend/spirv/s2s.c | 44 +++---- src/shady/body_builder.c | 138 ++++++++++---------- src/shady/ir/function.c | 2 +- src/shady/ir_private.h | 2 +- src/shady/passes/lift_indirect_targets.c | 12 +- src/shady/passes/lower_alloca.c | 10 +- src/shady/passes/lower_callf.c | 16 +-- src/shady/passes/lower_cf_instrs.c | 18 +-- src/shady/passes/lower_entrypoint_args.c | 6 +- src/shady/passes/lower_generic_ptrs.c | 24 ++-- src/shady/passes/lower_int64.c | 18 +-- src/shady/passes/lower_lea.c | 8 +- src/shady/passes/lower_logical_pointers.c | 12 +- src/shady/passes/lower_mask.c | 4 +- src/shady/passes/lower_memcpy.c | 32 ++--- src/shady/passes/lower_nullptr.c | 4 +- src/shady/passes/lower_physical_ptrs.c | 28 ++-- src/shady/passes/lower_stack.c | 32 ++--- src/shady/passes/lower_subgroup_ops.c | 10 +- src/shady/passes/lower_subgroup_vars.c | 6 +- src/shady/passes/lower_switch_btree.c | 2 +- src/shady/passes/lower_tailcalls.c | 60 ++++----- src/shady/passes/lower_vec_arr.c | 4 +- src/shady/passes/lower_workgroups.c | 20 +-- src/shady/passes/normalize_builtins.c | 6 +- src/shady/passes/opt_demote_alloca.c | 8 +- src/shady/passes/opt_inline.c | 4 +- src/shady/passes/reconvergence_heuristics.c | 32 ++--- src/shady/passes/restructure.c | 44 +++---- src/shady/passes/scope2control.c | 6 +- src/shady/passes/scope_heuristic.c | 12 +- src/shady/passes/setup_stack_frames.c | 14 +- src/shady/transform/ir_gen_helpers.c | 32 ++--- test/test_builder.c | 42 +++--- zhady/shady.i | 53 ++++++++ 44 files changed, 531 insertions(+), 485 deletions(-) diff --git a/include/shady/body_builder.h b/include/shady/body_builder.h index 37da64ace..d194f19ef 100644 --- a/include/shady/body_builder.h +++ b/include/shady/body_builder.h @@ -6,28 +6,31 @@ typedef struct BodyBuilder_ BodyBuilder; /// Used to build a chain of let -BodyBuilder* begin_body_with_mem(IrArena*, const Node*); -BodyBuilder* begin_block_pure(IrArena*); -BodyBuilder* begin_block_with_side_effects(IrArena*, const Node*); +BodyBuilder* shd_bld_begin(IrArena* a, const Node* mem); +BodyBuilder* shd_bld_begin_pure(IrArena* a); +BodyBuilder* shd_bld_begin_pseudo_instr(IrArena* a, const Node* mem); /// Appends an instruction to the builder, may apply optimisations. /// If the arena is typed, returns a list of variables bound to the values yielded by that instruction -Nodes bind_instruction(BodyBuilder*, const Node* instruction); -const Node* bind_instruction_single(BodyBuilder*, const Node* instruction); -Nodes bind_instruction_named(BodyBuilder*, const Node* instruction, String const output_names[]); +Nodes shd_bld_add_instruction_extract(BodyBuilder* bb, const Node* instruction); +const Node* shd_bld_add_instruction(BodyBuilder* bb, const Node* instr); -Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count); +/// Like append shd_bld_add_instruction_extract, but you explicitly give it information about any yielded values +/// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! +Nodes shd_bld_add_instruction_extract_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count); + +Nodes shd_deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count); -Nodes gen_if(BodyBuilder*, Nodes, const Node*, const Node*, Node*); -Nodes gen_match(BodyBuilder*, Nodes, const Node*, Nodes, Nodes, Node*); -Nodes gen_loop(BodyBuilder*, Nodes, Nodes, Node*); +Nodes shd_bld_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, Node* false_case); +Nodes shd_bld_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, Node* default_case); +Nodes shd_bld_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, Node* body); typedef struct { Nodes results; Node* case_; const Node* jp; } begin_control_t; -begin_control_t begin_control(BodyBuilder*, Nodes); +begin_control_t shd_bld_begin_control(BodyBuilder* bb, Nodes yield_types); typedef struct { Nodes results; @@ -36,31 +39,27 @@ typedef struct { const Node* continue_jp; const Node* break_jp; } begin_loop_helper_t; -begin_loop_helper_t begin_loop_helper(BodyBuilder*, Nodes, Nodes, Nodes); +begin_loop_helper_t shd_bld_begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes arg_types, Nodes initial_values); -Nodes gen_control(BodyBuilder*, Nodes, Node*); +Nodes shd_bld_control(BodyBuilder* bb, Nodes yield_types, Node* body); -const Node* bb_mem(BodyBuilder*); - -/// Like append bind_instruction, but you explicitly give it information about any yielded values -/// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! -Nodes bind_instruction_outputs_count(BodyBuilder*, const Node* initial_value, size_t outputs_count); +const Node* shd_bb_mem(BodyBuilder* bb); -const Node* finish_body(BodyBuilder*, const Node* terminator); -const Node* finish_body_with_return(BodyBuilder*, Nodes args); -const Node* finish_body_with_unreachable(BodyBuilder*); -const Node* finish_body_with_selection_merge(BodyBuilder*, Nodes args); -const Node* finish_body_with_loop_continue(BodyBuilder*, Nodes args); -const Node* finish_body_with_loop_break(BodyBuilder*, Nodes args); -const Node* finish_body_with_join(BodyBuilder*, const Node* jp, Nodes args); -const Node* finish_body_with_jump(BodyBuilder*, const Node* target, Nodes args); +const Node* shd_bld_finish(BodyBuilder* bb, const Node* terminator); +const Node* shd_bld_return(BodyBuilder* bb, Nodes args); +const Node* shd_bld_unreachable(BodyBuilder* bb); +const Node* shd_bld_selection_merge(BodyBuilder* bb, Nodes args); +const Node* shd_bld_loop_continue(BodyBuilder* bb, Nodes args); +const Node* shd_bld_loop_break(BodyBuilder* bb, Nodes args); +const Node* shd_bld_join(BodyBuilder* bb, const Node* jp, Nodes args); +const Node* shd_bld_jump(BodyBuilder* bb, const Node* target, Nodes args); -void cancel_body(BodyBuilder*); +void shd_bld_cancel(BodyBuilder* bb); -const Node* yield_value_and_wrap_in_block(BodyBuilder*, const Node*); -const Node* yield_values_and_wrap_in_block(BodyBuilder*, Nodes); -const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder*, const Node*); +const Node* shd_bld_to_instr_yield_value(BodyBuilder* bb, const Node* value); +const Node* shd_bld_to_instr_yield_values(BodyBuilder* bb, Nodes values); +const Node* shd_bld_to_instr_with_last_instr(BodyBuilder* bb, const Node* instruction); -const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder*, Nodes); +const Node* shd_bld_to_instr_pure_with_values(BodyBuilder* bb, Nodes values); #endif diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 5fc6ad186..886409d21 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -26,12 +26,12 @@ static const Node* process(Context* ctx, const Node* node) { functx.rewriter.map = shd_clone_dict(functx.rewriter.map); shd_dict_clear(functx.rewriter.map); shd_register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); - functx.bb = begin_body_with_mem(a, shd_get_abstraction_mem(newfun)); + functx.bb = shd_bld_begin(a, shd_get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); shd_register_processed(&functx.rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(post_prelude)); shd_set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); - shd_set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, - shd_empty(a)))); + shd_set_abstraction_body(newfun, shd_bld_finish(functx.bb, jump_helper(a, shd_bb_mem(functx.bb), post_prelude, + shd_empty(a)))); shd_destroy_dict(functx.rewriter.map); } return newfun; diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 8e288ae09..3ad270c2d 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -42,7 +42,7 @@ int vcc_get_linked_major_llvm_version() { #endif static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { - bb_ctx->builder = begin_body_with_mem(bb_ctx->nbb->arena, shd_get_abstraction_mem(bb_ctx->nbb)); + bb_ctx->builder = shd_bld_begin(bb_ctx->nbb->arena, shd_get_abstraction_mem(bb_ctx->nbb)); LLVMValueRef instr; LLVMBasicBlockRef bb = bb_ctx->bb; for (instr = bb_ctx->instr; instr; instr = LLVMGetNextInstruction(instr)) { @@ -65,7 +65,7 @@ static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { static void write_bb_tail(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { LLVMBasicBlockRef bb = bb_ctx->bb; LLVMValueRef instr = LLVMGetLastInstruction(bb); - shd_set_abstraction_body(bb_ctx->nbb, finish_body(bb_ctx->builder, convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr))); + shd_set_abstraction_body(bb_ctx->nbb, shd_bld_finish(bb_ctx->builder, convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr))); } static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasicBlockRef bb) { diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 400b20708..29c08fa06 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -39,7 +39,7 @@ static Nodes reinterpret_operands(BodyBuilder* b, Nodes ops, const Type* dst_t) IrArena* a = dst_t->arena; LARRAY(const Node*, nops, ops.count); for (size_t i = 0; i < ops.count; i++) - nops[i] = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(dst_t), shd_singleton(ops.nodes[i])), 1)); + nops[i] = shd_first(shd_bld_add_instruction_extract_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(dst_t), shd_singleton(ops.nodes[i])), 1)); return shd_nodes(a, ops.count, nops); } @@ -107,7 +107,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Type* t = convert_type(p, LLVMTypeOf(instr)); -#define BIND_PREV_R(t) bind_instruction_outputs_count(b, r, 1) +#define BIND_PREV_R(t) shd_bld_add_instruction_extract_count(b, r, 1) //if (LLVMIsATerminatorInst(instr)) { //if (LLVMIsAInstruction(instr) && !LLVMIsATerminatorInst(instr)) { @@ -127,13 +127,13 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B shd_debugv_print(" -> "); } shd_debugv_print(" (depth= %zu)\n", str.count); - bind_instruction_single(b, ext_instr(a, (ExtInstr) { - .set = "shady.scope", - .opcode = 0, - .result_t = unit_type(a), - .mem = bb_mem(b), - .operands = str, - })); + shd_bld_add_instruction(b, ext_instr(a, (ExtInstr) { + .set = "shady.scope", + .opcode = 0, + .result_t = unit_type(a), + .mem = shd_bb_mem(b), + .operands = str, + })); //} } } @@ -141,7 +141,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B switch (opcode) { case LLVMRet: return fn_ret(a, (Return) { .args = num_ops == 0 ? shd_empty(a) : convert_operands(p, num_ops, instr), - .mem = bb_mem(b), + .mem = shd_bb_mem(b), }); case LLVMBr: { unsigned n_targets = LLVMGetNumSuccessors(instr); @@ -153,38 +153,38 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Node* condition = convert_value(p, LLVMGetCondition(instr)); return branch(a, (Branch) { .condition = condition, - .true_jump = convert_jump(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)), - .false_jump = convert_jump(p, fn_ctx, fn_or_bb, targets[1], bb_mem(b)), - .mem = bb_mem(b), + .true_jump = convert_jump(p, fn_ctx, fn_or_bb, targets[0], shd_bb_mem(b)), + .false_jump = convert_jump(p, fn_ctx, fn_or_bb, targets[1], shd_bb_mem(b)), + .mem = shd_bb_mem(b), }); } else { assert(n_targets == 1); - return convert_jump(p, fn_ctx, fn_or_bb, targets[0], bb_mem(b)); + return convert_jump(p, fn_ctx, fn_or_bb, targets[0], shd_bb_mem(b)); } } case LLVMSwitch: { const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); - const Node* default_jump = convert_jump(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, 1), bb_mem(b)); + const Node* default_jump = convert_jump(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, 1), shd_bb_mem(b)); int n_targets = LLVMGetNumOperands(instr) / 2 - 1; LARRAY(const Node*, targets, n_targets); LARRAY(const Node*, literals, n_targets); for (size_t i = 0; i < n_targets; i++) { literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); - targets[i] = convert_jump(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3), bb_mem(b)); + targets[i] = convert_jump(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3), shd_bb_mem(b)); } return br_switch(a, (Switch) { .switch_value = inspectee, .default_jump = default_jump, .case_values = shd_nodes(a, n_targets, literals), .case_jumps = shd_nodes(a, n_targets, targets), - .mem = bb_mem(b), + .mem = shd_bb_mem(b), }); } case LLVMIndirectBr: goto unimplemented; case LLVMInvoke: goto unimplemented; - case LLVMUnreachable: return unreachable(a, (Unreachable) { .mem = bb_mem(b) }); + case LLVMUnreachable: return unreachable(a, (Unreachable) { .mem = shd_bb_mem(b) }); case LLVMCallBr: goto unimplemented; case LLVMFNeg: @@ -228,10 +228,10 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B assert(t->tag == PtrType_TAG); const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivate }); - const Node* r = shd_first(bind_instruction_outputs_count(b, stack_alloc(a, (StackAlloc) { .type = allocated_t, .mem = bb_mem(b) }), 1)); + const Node* r = shd_first(shd_bld_add_instruction_extract_count(b, stack_alloc(a, (StackAlloc) { .type = allocated_t, .mem = shd_bb_mem(b) }), 1)); if (UNTYPED_POINTERS) { const Type* untyped_ptr_t = ptr_type(a, (PtrType) { .pointed_type = unit_type(a), .address_space = AsPrivate }); - r = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(untyped_ptr_t), shd_singleton(r)), 1)); + r = shd_first(shd_bld_add_instruction_extract_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(untyped_ptr_t), shd_singleton(r)), 1)); } return prim_op_helper(a, convert_op, shd_singleton(t), shd_singleton(r)); } @@ -243,9 +243,9 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Type* element_t = t; const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); + ptr = shd_first(shd_bld_add_instruction_extract_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } - return bind_instruction_single(b, load(a, (Load) { .ptr = ptr, .mem = bb_mem(b) })); + return shd_bld_add_instruction(b, load(a, (Load) { .ptr = ptr, .mem = shd_bb_mem(b) })); } case LLVMStore: { num_results = 0; @@ -256,9 +256,9 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Type* element_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 1))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); + ptr = shd_first(shd_bld_add_instruction_extract_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } - return bind_instruction_single(b, store(a, (Store) { .ptr = ptr, .value = ops.nodes[0], .mem = bb_mem(b) })); + return shd_bld_add_instruction(b, store(a, (Store) { .ptr = ptr, .value = ops.nodes[0], .mem = shd_bb_mem(b) })); } case LLVMGetElementPtr: { Nodes ops = convert_operands(p, num_ops, instr); @@ -267,7 +267,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); - ptr = shd_first(bind_instruction_outputs_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); + ptr = shd_first(shd_bld_add_instruction_extract_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } ops = shd_change_node_at_index(a, ops, 0, ptr); const Node* r = lea_helper(a, ops.nodes[0], ops.nodes[1], shd_nodes(a, ops.count - 2, &ops.nodes[2])); @@ -493,10 +493,10 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B } if (shd_string_starts_with(intrinsic, "llvm.memcpy")) { Nodes ops = convert_operands(p, num_ops, instr); - return bind_instruction_single(b, copy_bytes(a, (CopyBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = bb_mem(b) })); + return shd_bld_add_instruction(b, copy_bytes(a, (CopyBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = shd_bb_mem(b) })); } else if (shd_string_starts_with(intrinsic, "llvm.memset")) { Nodes ops = convert_operands(p, num_ops, instr); - return bind_instruction_single(b, fill_bytes(a, (FillBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = bb_mem(b) })); + return shd_bld_add_instruction(b, fill_bytes(a, (FillBytes) { .dst = ops.nodes[0], .src = ops.nodes[1], .count = ops.nodes[2], .mem = shd_bb_mem(b) })); } else if (shd_string_starts_with(intrinsic, "llvm.fmuladd")) { Nodes ops = convert_operands(p, num_ops, instr); return prim_op_helper(a, fma_op, shd_empty(a), shd_nodes(a, 3, ops.nodes)); @@ -557,7 +557,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B LARRAY(const Node*, processed_ops, ops.count); for (i = 0; i < num_args; i++) { if (decoded[i].is_byval) - processed_ops[i] = shd_first(bind_instruction_outputs_count(b, load(a, (Load) { .ptr = ops.nodes[i], .mem = bb_mem(b) }), 1)); + processed_ops[i] = shd_first(shd_bld_add_instruction_extract_count(b, load(a, (Load) { .ptr = ops.nodes[i], .mem = shd_bb_mem(b) }), 1)); else processed_ops[i] = ops.nodes[i]; } @@ -590,8 +590,8 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B if (!r) { Nodes ops = convert_operands(p, num_ops, instr); - r = bind_instruction_single(b, call(a, (Call) { - .mem = bb_mem(b), + r = shd_bld_add_instruction(b, call(a, (Call) { + .mem = shd_bb_mem(b), .callee = prim_op_helper(a, reinterpret_op, shd_singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, .pointed_type = convert_type(p, callee_type) diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index c263051b9..6e7050a65 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -46,10 +46,10 @@ static const Node* process_node(Context* ctx, const Node* node) { } case Constant_TAG: { Node* new = (Node*) shd_recreate_node(r, node); - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); const Node* value = new->payload.constant.value; value = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(value)); - new->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(value)); + new->payload.constant.value = shd_bld_to_instr_pure_with_values(bb, shd_singleton(value)); return new; } case Function_TAG: { diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index b8b3eb2da..d47e83aa3 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -83,8 +83,8 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { Node* decl = constant(p->dst, annotations, t, name); r = ref_decl_helper(a, decl); shd_dict_insert(LLVMTypeRef, const Type*, p->map, v, r); - BodyBuilder* bb = begin_block_pure(a); - decl->payload.constant.value = yield_value_and_wrap_in_block(bb, convert_instruction(p, NULL, NULL, bb, v)); + BodyBuilder* bb = shd_bld_begin_pure(a); + decl->payload.constant.value = shd_bld_to_instr_yield_value(bb, convert_instruction(p, NULL, NULL, bb, v)); return r; } case LLVMConstantDataArrayValueKind: { diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 4e53a848c..8eda5d702 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -135,14 +135,14 @@ static const Node* get_node_address(Context* ctx, const Node* node) { static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { Rewriter* r = &ctx->rewriter; IrArena* a = r->dst_arena; - BodyBuilder* bb = instr.mem ? begin_body_with_mem(a, shd_rewrite_node(r, instr.mem)) : begin_block_pure(a); + BodyBuilder* bb = instr.mem ? shd_bld_begin(a, shd_rewrite_node(r, instr.mem)) : shd_bld_begin_pure(a); switch (instr.opcode) { case SlimOpBindVal: { size_t names_count = instr.operands.count - 1; const Node** names = &instr.operands.nodes[1]; const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); - Nodes results = deconstruct_composite(a, bb, value, names_count); + Nodes results = shd_deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = shd_get_string_literal(a, names[i]); shd_log_fmt(DEBUGV, "Bound immutable variable '%s'\n", name); @@ -155,15 +155,15 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { const Node** names = &instr.operands.nodes[1]; const Node** types = &instr.operands.nodes[1 + names_count]; const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); - Nodes results = deconstruct_composite(a, bb, value, names_count); + Nodes results = shd_deconstruct_composite(a, bb, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = shd_get_string_literal(a, names[i]); const Type* type_annotation = types[i]; assert(type_annotation); - const Node* alloca = stack_alloc(a, (StackAlloc) { .type = shd_rewrite_node(&ctx->rewriter, type_annotation), .mem = bb_mem(bb) }); - const Node* ptr = bind_instruction_outputs_count(bb, alloca, 1).nodes[0]; + const Node* alloca = stack_alloc(a, (StackAlloc) { .type = shd_rewrite_node(&ctx->rewriter, type_annotation), .mem = shd_bb_mem(bb) }); + const Node* ptr = shd_bld_add_instruction_extract_count(bb, alloca, 1).nodes[0]; shd_set_value_name(ptr, name); - bind_instruction_outputs_count(bb, store(a, (Store) { .ptr = ptr, .value = results.nodes[0], .mem = bb_mem(bb) }), 0); + shd_bld_add_instruction_extract_count(bb, store(a, (Store) { .ptr = ptr, .value = results.nodes[0], .mem = shd_bb_mem(bb) }), 0); add_binding(ctx, true, name, ptr); shd_log_fmt(DEBUGV, "Bound mutable variable '%s'\n", name); @@ -198,7 +198,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { } } - return yield_values_and_wrap_in_block(bb, shd_empty(a)); + return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } static const Node* rewrite_decl(Context* ctx, const Node* decl) { diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index b82568dbf..db4e45d3a 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -349,7 +349,7 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe Nodes type_args = infer_nodes(ctx, old_type_args); Nodes old_operands = node->payload.prim_op.operands; - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); Op op = node->payload.prim_op.op; LARRAY(const Node*, new_operands, old_operands.count); Nodes input_types = shd_empty(a); @@ -390,7 +390,7 @@ static const Node* infer_primop(Context* ctx, const Node* node, const Node* expe .type_arguments = type_args, .operands = shd_nodes(a, old_operands.count, new_operands) }); - return bind_last_instruction_and_wrap_in_block(bb, new_instruction); + return shd_bld_to_instr_with_last_instr(bb, new_instruction); } } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 8491d01f1..030fb78fe 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -280,7 +280,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { if (op != PRIMOPS_COUNT) { if (!bb) syntax_error("primops cannot be used outside of a function"); - return bind_instruction_single(bb, prim_op(arena, (PrimOp) { + return shd_bld_add_instruction(bb, prim_op(arena, (PrimOp) { .op = op, .type_arguments = accept_type_arguments(ctx), .operands = expect_operands(ctx, bb) @@ -297,32 +297,32 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { expect(type, "type"); expect(accept_token(ctx, rsbracket_tok), "]"); Nodes ops = expect_operands(ctx, bb); - return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { + return shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .result_t = type, .set = set->payload.string_lit.string, .opcode = strtoll(opcode->payload.untyped_number.plaintext, NULL, 10), - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), .operands = ops, })); } else if (strcmp(id, "alloca") == 0) { const Node* type = shd_first(accept_type_arguments(ctx)); Nodes ops = expect_operands(ctx, bb); expect(ops.count == 0, "no operands"); - return bind_instruction_single(bb, stack_alloc(arena, (StackAlloc) { + return shd_bld_add_instruction(bb, stack_alloc(arena, (StackAlloc) { .type = type, - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } else if (strcmp(id, "debug_printf") == 0) { Nodes ops = expect_operands(ctx, bb); - return bind_instruction_single(bb, debug_printf(arena, (DebugPrintf) { + return shd_bld_add_instruction(bb, debug_printf(arena, (DebugPrintf) { .string = shd_get_string_literal(arena, shd_first(ops)), .args = shd_nodes(arena, ops.count - 1, &ops.nodes[1]), - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } if (bb) - return bind_instruction_single(bb, make_unbound(arena, bb_mem(bb), id)); + return shd_bld_add_instruction(bb, make_unbound(arena, shd_bb_mem(bb), id)); return make_unbound(arena, NULL, id); } case hex_lit_tok: @@ -601,31 +601,31 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { .value = -shd_get_int_literal_value(*shd_resolve_to_int_literal(expr), true) }); } else { - return bind_instruction_single(bb, prim_op(arena, (PrimOp) { + return shd_bld_add_instruction(bb, prim_op(arena, (PrimOp) { .op = neg_op, - .operands = shd_nodes(arena, 1, (const Node* []) {expr}) + .operands = shd_nodes(arena, 1, (const Node* []) { expr }) })); } } else if (accept_token(ctx, unary_excl_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr, "expression"); - return bind_instruction_single(bb, prim_op(arena, (PrimOp) { + return shd_bld_add_instruction(bb, prim_op(arena, (PrimOp) { .op = not_op, .operands = shd_singleton(expr), })); } else if (accept_token(ctx, star_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr, "expression"); - return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpDereference, .operands = shd_singleton(expr), .mem = bb_mem(bb) })); + return shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpDereference, .operands = shd_singleton(expr), .mem = shd_bb_mem(bb) })); } else if (accept_token(ctx, infix_and_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr, "expression"); - return bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { + return shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpAddrOf, .operands = shd_singleton(expr), - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } @@ -646,28 +646,28 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) expect(rhs, "expression"); Op primop_op; if (is_primop_op(infix, &primop_op)) { - expr = bind_instruction_single(bb, prim_op(arena, (PrimOp) { + expr = shd_bld_add_instruction(bb, prim_op(arena, (PrimOp) { .op = primop_op, - .operands = shd_nodes(arena, 2, (const Node* []) {expr, rhs}) + .operands = shd_nodes(arena, 2, (const Node* []) { expr, rhs }) })); } else switch (infix) { case InfixAss: { - expr = bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { + expr = shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .opcode = SlimOpAssign, .result_t = unit_type(arena), - .operands = shd_nodes(arena, 2, (const Node* []) {expr, rhs}), - .mem = bb_mem(bb), + .operands = shd_nodes(arena, 2, (const Node* []) { expr, rhs }), + .mem = shd_bb_mem(bb), })); break; } case InfixSbs: { - expr = bind_instruction_single(bb, ext_instr(arena, (ExtInstr) { + expr = shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .opcode = SlimOpSubscript, .result_t = unit_type(arena), - .operands = shd_nodes(arena, 2, (const Node* []) {expr, rhs}), - .mem = bb_mem(bb), + .operands = shd_nodes(arena, 2, (const Node* []) { expr, rhs }), + .mem = shd_bb_mem(bb), })); break; } @@ -679,10 +679,10 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) switch (shd_curr_token(tokenizer).tag) { case lpar_tok: { Nodes ops = expect_operands(ctx, bb); - expr = bind_instruction_single(bb, call(arena, (Call) { + expr = shd_bld_add_instruction(bb, call(arena, (Call) { .callee = expr, .args = ops, - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); continue; } @@ -759,7 +759,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { false_case = case_(arena, shd_nodes(arena, 0, NULL)); shd_set_abstraction_body(false_case, expect_body(ctx, shd_get_abstraction_mem(false_case), merge)); } - return maybe_tuple_helper(arena, gen_if(bb, yield_types, condition, true_case, false_case)); + return maybe_tuple_helper(arena, shd_bld_if(bb, yield_types, condition, true_case, false_case)); } case loop_tok: { shd_next_token(tokenizer); @@ -771,7 +771,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { const Node* (*default_loop_end_behaviour)(const Node*) = config->front_end ? make_loop_continue : NULL; Node* loop_case = case_(arena, parameters); shd_set_abstraction_body(loop_case, expect_body(ctx, shd_get_abstraction_mem(loop_case), default_loop_end_behaviour)); - return maybe_tuple_helper(arena, gen_loop(bb, yield_types, initial_arguments, loop_case)); + return maybe_tuple_helper(arena, shd_bld_loop(bb, yield_types, initial_arguments, loop_case)); } case control_tok: { shd_next_token(tokenizer); @@ -785,7 +785,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { expect(accept_token(ctx, rpar_tok), "')'"); Node* control_case = case_(arena, shd_singleton(jp)); shd_set_abstraction_body(control_case, expect_body(ctx, shd_get_abstraction_mem(control_case), NULL)); - return maybe_tuple_helper(arena, gen_control(bb, yield_types, control_case)); + return maybe_tuple_helper(arena, shd_bld_control(bb, yield_types, control_case)); } default: break; } @@ -877,12 +877,12 @@ static const Node* expect_jump(ctxparams, BodyBuilder* bb) { String target = accept_identifier(ctx); expect(target, "jump target name"); Nodes args = expect_operands(ctx, bb); - const Node* tgt = make_unbound(arena, bb_mem(bb), target); - bind_instruction_single(bb, tgt); + const Node* tgt = make_unbound(arena, shd_bb_mem(bb), target); + shd_bld_add_instruction(bb, tgt); return jump(arena, (Jump) { .target = tgt, .args = args, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) }); } @@ -909,7 +909,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { .condition = condition, .true_jump = true_target, .false_jump = false_target, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) }); } case switch_tok: { @@ -943,7 +943,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { .case_values = values, .case_jumps = cases, .default_jump = default_jump, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) }); } case return_tok: { @@ -951,7 +951,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { Nodes args = expect_operands(ctx, bb); return fn_ret(arena, (Return) { .args = args, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) }); } case merge_selection_tok: { @@ -959,7 +959,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { Nodes args = shd_curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_selection(arena, (MergeSelection) { .args = args, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) }); } case continue_tok: { @@ -967,7 +967,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { Nodes args = shd_curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_continue(arena, (MergeContinue) { .args = args, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) }); } case break_tok: { @@ -975,7 +975,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { Nodes args = shd_curr_token(tokenizer).tag == lpar_tok ? expect_operands(ctx, bb) : shd_nodes(arena, 0, NULL); return merge_break(arena, (MergeBreak) { .args = args, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) }); } case join_tok: { @@ -987,14 +987,14 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { return join(arena, (Join) { .join_point = jp, .args = args, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) }); } case unreachable_tok: { shd_next_token(tokenizer); expect(accept_token(ctx, lpar_tok), "'('"); expect(accept_token(ctx, rpar_tok), "')'"); - return unreachable(arena, (Unreachable) { .mem = bb_mem(bb) }); + return unreachable(arena, (Unreachable) { .mem = shd_bb_mem(bb) }); } default: break; } @@ -1003,7 +1003,7 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { static const Node* expect_body(ctxparams, const Node* mem, const Node* default_terminator(const Node*)) { expect(accept_token(ctx, lbracket_tok), "'['"); - BodyBuilder* bb = begin_body_with_mem(arena, mem); + BodyBuilder* bb = shd_bld_begin(arena, mem); while (true) { if (!accept_statement(ctx, bb)) @@ -1011,7 +1011,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t } Node* terminator_case = case_(arena, shd_empty(arena)); - BodyBuilder* terminator_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(terminator_case)); + BodyBuilder* terminator_bb = shd_bld_begin(arena, shd_get_abstraction_mem(terminator_case)); const Node* terminator = accept_terminator(ctx, terminator_bb); if (terminator) @@ -1019,15 +1019,15 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t if (!terminator) { if (default_terminator) - terminator = default_terminator(bb_mem(terminator_bb)); + terminator = default_terminator(shd_bb_mem(terminator_bb)); else syntax_error("expected terminator: return, jump, branch ..."); } - shd_set_abstraction_body(terminator_case, finish_body(terminator_bb, terminator)); + shd_set_abstraction_body(terminator_case, shd_bld_finish(terminator_bb, terminator)); Node* cont_wrapper_case = case_(arena, shd_empty(arena)); - BodyBuilder* cont_wrapper_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(cont_wrapper_case)); + BodyBuilder* cont_wrapper_bb = shd_bld_begin(arena, shd_get_abstraction_mem(cont_wrapper_case)); Nodes ids = shd_empty(arena); Nodes conts = shd_empty(arena); @@ -1049,8 +1049,8 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t gen_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), shd_concat_nodes(arena, ids, conts)); expect(accept_token(ctx, rbracket_tok), "']'"); - shd_set_abstraction_body(cont_wrapper_case, finish_body_with_jump(cont_wrapper_bb, terminator_case, shd_empty(arena))); - return finish_body_with_jump(bb, cont_wrapper_case, shd_empty(arena)); + shd_set_abstraction_body(cont_wrapper_case, shd_bld_jump(cont_wrapper_bb, terminator_case, shd_empty(arena))); + return shd_bld_jump(bb, cont_wrapper_case, shd_empty(arena)); } static Nodes accept_annotations(ctxparams) { @@ -1119,14 +1119,14 @@ static const Node* accept_const(ctxparams, Nodes annotations) { const char* id = accept_identifier(ctx); expect(id, "constant name"); expect(accept_token(ctx, equal_tok), "'='"); - BodyBuilder* bb = begin_block_pure(arena); + BodyBuilder* bb = shd_bld_begin_pure(arena); const Node* definition = accept_expr(ctx, bb, max_precedence()); expect(definition, "expression"); expect(accept_token(ctx, semi_tok), "';'"); Node* cnst = constant(mod, annotations, type, id); - cnst->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(definition)); + cnst->payload.constant.value = shd_bld_to_instr_pure_with_values(bb, shd_singleton(definition)); return cnst; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index a56cf64bf..e0f317dd3 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -457,7 +457,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < num_ops; i++) ops[i] = get_def_ssa_value(parser, instruction[shd_op.ops_offset + i]); int results_count = has_result ? 1 : 0; - Nodes results = bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + Nodes results = shd_bld_add_instruction_extract_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = shd_op.op, .type_arguments = shd_empty(parser->arena), .operands = shd_nodes(parser->arena, num_ops, ops) @@ -741,13 +741,13 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { assert(shd_is_data_type(contents_t)); if (parser->fun) { - const Node* ptr = shd_first(bind_instruction_outputs_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { .type = contents_t, .mem = bb_mem(parser->current_block.builder) }), 1)); + const Node* ptr = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, stack_alloc(parser->arena, (StackAlloc) { .type = contents_t, .mem = shd_bb_mem(parser->current_block.builder) }), 1)); parser->defs[result].type = Value; parser->defs[result].node = ptr; if (size == 5) - bind_instruction_outputs_count(parser->current_block.builder, store(parser->arena, (Store) { .ptr = ptr, .value = get_def_ssa_value(parser, instruction[4]), .mem = bb_mem(parser->current_block.builder) }), 1); + shd_bld_add_instruction_extract_count(parser->current_block.builder, store(parser->arena, (Store) { .ptr = ptr, .value = get_def_ssa_value(parser, instruction[4]), .mem = shd_bb_mem(parser->current_block.builder) }), 1); } else { Nodes annotations = shd_empty(parser->arena); SpvDeco* builtin = find_decoration(parser, result, -1, SpvDecorationBuiltIn); @@ -900,7 +900,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { Node* block = basic_block(parser->arena, params, bb_name); parser->defs[result].node = block; - BodyBuilder* bb = begin_body_with_mem(parser->arena, shd_get_abstraction_mem(block)); + BodyBuilder* bb = shd_bld_begin(parser->arena, shd_get_abstraction_mem(block)); parser->current_block.builder = bb; parser->current_block.finished = NULL; while (parser->current_block.builder) { @@ -966,7 +966,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { const Type* src = get_def_ssa_value(parser, instruction[3]); const Type* dst_t = get_def_type(parser, result_t); parser->defs[result].type = Value; - parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + parser->defs[result].node = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = convert_op, .type_arguments = shd_singleton(dst_t), .operands = shd_singleton(src) @@ -979,7 +979,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { const Type* src = get_def_ssa_value(parser, instruction[3]); const Type* dst_t = get_def_type(parser, result_t); parser->defs[result].type = Value; - parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + parser->defs[result].node = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = reinterpret_op, .type_arguments = shd_singleton(dst_t), .operands = shd_singleton(src) @@ -1013,7 +1013,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < num_indices; i++) ops[1 + i] = shd_int32_literal(parser->arena, instruction[4 + i]); parser->defs[result].type = Value; - parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + parser->defs[result].node = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = extract_op, .type_arguments = shd_empty(parser->arena), .operands = shd_nodes(parser->arena, 1 + num_indices, ops) @@ -1028,7 +1028,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { for (size_t i = 0; i < num_indices; i++) ops[2 + i] = shd_int32_literal(parser->arena, instruction[5 + i]); parser->defs[result].type = Value; - parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + parser->defs[result].node = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = insert_op, .type_arguments = shd_empty(parser->arena), .operands = shd_nodes(parser->arena, 2 + num_indices, ops) @@ -1053,7 +1053,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { index -= num_components_a; src = src_b; } - components[i] = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + components[i] = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = extract_op, .type_arguments = shd_empty(parser->arena), .operands = mk_nodes(parser->arena, src, shd_int32_literal(parser->arena, index)) @@ -1070,13 +1070,13 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpLoad: { const Type* src = get_def_ssa_value(parser, instruction[3]); parser->defs[result].type = Value; - parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, load(a, (Load) { .ptr = src, .mem = bb_mem(parser->current_block.builder) }), 1)); + parser->defs[result].node = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, load(a, (Load) { .ptr = src, .mem = shd_bb_mem(parser->current_block.builder) }), 1)); break; } case SpvOpStore: { const Type* ptr = get_def_ssa_value(parser, instruction[1]); const Type* value = get_def_ssa_value(parser, instruction[2]); - bind_instruction_outputs_count(parser->current_block.builder, store(a, (Store) { .ptr = ptr, .value = value, .mem = bb_mem(parser->current_block.builder) }), 0); + shd_bld_add_instruction_extract_count(parser->current_block.builder, store(a, (Store) { .ptr = ptr, .value = value, .mem = shd_bb_mem(parser->current_block.builder) }), 0); break; } case SpvOpCopyMemory: @@ -1088,7 +1088,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { const Type* elem_t = src->type; shd_deconstruct_qualified_type(&elem_t); shd_deconstruct_pointer_type(&elem_t); - cnt = shd_first(bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + cnt = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = size_of_op, .type_arguments = shd_singleton(elem_t), .operands = shd_empty(parser->arena) @@ -1096,7 +1096,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } else { cnt = get_def_ssa_value(parser, instruction[3]); } - bind_instruction_outputs_count(parser->current_block.builder, copy_bytes(parser->arena, (CopyBytes) { + shd_bld_add_instruction_extract_count(parser->current_block.builder, copy_bytes(parser->arena, (CopyBytes) { .src = src, .dst = dst, .count = cnt, @@ -1138,7 +1138,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } assert(op != PRIMOPS_COUNT); //assert(false && intrinsic); - Nodes rslts = bind_instruction_outputs_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { + Nodes rslts = shd_bld_add_instruction_extract_count(parser->current_block.builder, prim_op(parser->arena, (PrimOp) { .op = op, .type_arguments = shd_empty(parser->arena), .operands = shd_nodes(parser->arena, num_args, args) @@ -1150,7 +1150,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { break; } } - Nodes rslts = bind_instruction_outputs_count(parser->current_block.builder, call(parser->arena, (Call) { + Nodes rslts = shd_bld_add_instruction_extract_count(parser->current_block.builder, call(parser->arena, (Call) { .callee = fn_addr_helper(parser->arena, callee), .args = shd_nodes(parser->arena, num_args, args) }), rslts_count); @@ -1273,15 +1273,15 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { } parser->defs[result].type = Value; - parser->defs[result].node = shd_first(bind_instruction_outputs_count(parser->current_block.builder, instr, 1)); + parser->defs[result].node = shd_first(shd_bld_add_instruction_extract_count(parser->current_block.builder, instr, 1)); break; } case SpvOpBranch: { BodyBuilder* bb = parser->current_block.builder; - parser->current_block.finished = finish_body(bb, jump(parser->arena, (Jump) { + parser->current_block.finished = shd_bld_finish(bb, jump(parser->arena, (Jump) { .target = get_def_block(parser, instruction[1]), .args = get_args_from_phi(parser, instruction[1], parser->current_block.id), - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) })); parser->current_block.builder = NULL; break; @@ -1289,10 +1289,10 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { case SpvOpBranchConditional: { SpvId destinations[2] = { instruction[2], instruction[3] }; BodyBuilder* bb = parser->current_block.builder; - parser->current_block.finished = finish_body(bb, branch(parser->arena, (Branch) { - .true_jump = jump_helper(parser->arena, bb_mem(bb), get_def_block(parser, destinations[0]), + parser->current_block.finished = shd_bld_finish(bb, branch(parser->arena, (Branch) { + .true_jump = jump_helper(parser->arena, shd_bb_mem(bb), get_def_block(parser, destinations[0]), get_args_from_phi(parser, destinations[0], parser->current_block.id)), - .false_jump = jump_helper(parser->arena, bb_mem(bb), get_def_block(parser, destinations[1]), + .false_jump = jump_helper(parser->arena, shd_bb_mem(bb), get_def_block(parser, destinations[1]), get_args_from_phi(parser, destinations[1], parser->current_block.id)), .condition = get_def_ssa_value(parser, instruction[1]), })); @@ -1307,7 +1307,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { else args = shd_singleton(get_def_ssa_value(parser, instruction[1])); BodyBuilder* bb = parser->current_block.builder; - parser->current_block.finished = finish_body(bb, fn_ret(parser->arena, (Return) { + parser->current_block.finished = shd_bld_finish(bb, fn_ret(parser->arena, (Return) { .args = args, })); parser->current_block.builder = NULL; diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index a14acb6ce..2a8ce565c 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -31,7 +31,7 @@ typedef struct { Nodes vars; } StackEntry; -BodyBuilder* begin_body_with_mem(IrArena* a, const Node* mem) { +BodyBuilder* shd_bld_begin(IrArena* a, const Node* mem) { BodyBuilder* bb = malloc(sizeof(BodyBuilder)); *bb = (BodyBuilder) { .arena = a, @@ -41,17 +41,17 @@ BodyBuilder* begin_body_with_mem(IrArena* a, const Node* mem) { return bb; } -BodyBuilder* begin_block_with_side_effects(IrArena* a, const Node* mem) { +BodyBuilder* shd_bld_begin_pseudo_instr(IrArena* a, const Node* mem) { Node* block = basic_block(a, shd_empty(a), NULL); - BodyBuilder* builder = begin_body_with_mem(a, shd_get_abstraction_mem(block)); + BodyBuilder* builder = shd_bld_begin(a, shd_get_abstraction_mem(block)); builder->tail_block = block; builder->block_entry_block = block; builder->block_entry_mem = mem; return builder; } -BodyBuilder* begin_block_pure(IrArena* a) { - BodyBuilder* builder = begin_body_with_mem(a, NULL); +BodyBuilder* shd_bld_begin_pure(IrArena* a) { + BodyBuilder* builder = shd_bld_begin(a, NULL); return builder; } @@ -67,11 +67,11 @@ const Node* _shd_bb_insert_block(BodyBuilder* bb) { return bb->block_entry_block; } -const Node* bb_mem(BodyBuilder* bb) { +const Node* shd_bb_mem(BodyBuilder* bb) { return bb->mem; } -Nodes deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count) { +Nodes shd_deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count) { if (outputs_count > 1) { LARRAY(const Node*, extracted, outputs_count); for (size_t i = 0; i < outputs_count; i++) @@ -89,25 +89,19 @@ static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outp } if (is_mem(instruction) && /* avoid things like ExtInstr with null mem input! */ shd_get_parent_mem(instruction)) bb->mem = instruction; - return deconstruct_composite(bb->arena, bb, instruction, outputs_count); + return shd_deconstruct_composite(bb->arena, bb, instruction, outputs_count); } -Nodes bind_instruction(BodyBuilder* bb, const Node* instruction) { - assert(shd_get_arena_config(bb->arena)->check_types); - return bind_internal(bb, instruction, shd_singleton(instruction->type).count); -} - -const Node* bind_instruction_single(BodyBuilder* bb, const Node* instr) { - return shd_first(bind_instruction_outputs_count(bb, instr, 1)); +const Node* shd_bld_add_instruction(BodyBuilder* bb, const Node* instr) { + return shd_first(shd_bld_add_instruction_extract_count(bb, instr, 1)); } -Nodes bind_instruction_named(BodyBuilder* bb, const Node* instruction, String const output_names[]) { +Nodes shd_bld_add_instruction_extract(BodyBuilder* bb, const Node* instruction) { assert(shd_get_arena_config(bb->arena)->check_types); - assert(output_names); return bind_internal(bb, instruction, shd_singleton(instruction->type).count); } -Nodes bind_instruction_outputs_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { +Nodes shd_bld_add_instruction_extract_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { return bind_internal(bb, instruction, outputs_count); } @@ -141,7 +135,7 @@ static const Node* build_body(BodyBuilder* bb, const Node* terminator) { return terminator; } -const Node* finish_body(BodyBuilder* bb, const Node* terminator) { +const Node* shd_bld_finish(BodyBuilder* bb, const Node* terminator) { assert(bb->mem && !bb->block_entry_mem); terminator = build_body(bb, terminator); shd_destroy_list(bb->stack); @@ -149,61 +143,61 @@ const Node* finish_body(BodyBuilder* bb, const Node* terminator) { return terminator; } -const Node* finish_body_with_return(BodyBuilder* bb, Nodes args) { - return finish_body(bb, fn_ret(bb->arena, (Return) { +const Node* shd_bld_return(BodyBuilder* bb, Nodes args) { + return shd_bld_finish(bb, fn_ret(bb->arena, (Return) { .args = args, - .mem = bb_mem(bb) + .mem = shd_bb_mem(bb) })); } -const Node* finish_body_with_unreachable(BodyBuilder* bb) { - return finish_body(bb, unreachable(bb->arena, (Unreachable) { - .mem = bb_mem(bb) +const Node* shd_bld_unreachable(BodyBuilder* bb) { + return shd_bld_finish(bb, unreachable(bb->arena, (Unreachable) { + .mem = shd_bb_mem(bb) })); } -const Node* finish_body_with_selection_merge(BodyBuilder* bb, Nodes args) { - return finish_body(bb, merge_selection(bb->arena, (MergeSelection) { +const Node* shd_bld_selection_merge(BodyBuilder* bb, Nodes args) { + return shd_bld_finish(bb, merge_selection(bb->arena, (MergeSelection) { .args = args, - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } -const Node* finish_body_with_loop_continue(BodyBuilder* bb, Nodes args) { - return finish_body(bb, merge_continue(bb->arena, (MergeContinue) { +const Node* shd_bld_loop_continue(BodyBuilder* bb, Nodes args) { + return shd_bld_finish(bb, merge_continue(bb->arena, (MergeContinue) { .args = args, - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } -const Node* finish_body_with_loop_break(BodyBuilder* bb, Nodes args) { - return finish_body(bb, merge_break(bb->arena, (MergeBreak) { +const Node* shd_bld_loop_break(BodyBuilder* bb, Nodes args) { + return shd_bld_finish(bb, merge_break(bb->arena, (MergeBreak) { .args = args, - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } -const Node* finish_body_with_join(BodyBuilder* bb, const Node* jp, Nodes args) { - return finish_body(bb, join(bb->arena, (Join) { +const Node* shd_bld_join(BodyBuilder* bb, const Node* jp, Nodes args) { + return shd_bld_finish(bb, join(bb->arena, (Join) { .join_point = jp, .args = args, - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } -const Node* finish_body_with_jump(BodyBuilder* bb, const Node* target, Nodes args) { - return finish_body(bb, jump(bb->arena, (Jump) { +const Node* shd_bld_jump(BodyBuilder* bb, const Node* target, Nodes args) { + return shd_bld_finish(bb, jump(bb->arena, (Jump) { .target = target, .args = args, - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } -const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { +const Node* shd_bld_to_instr_yield_value(BodyBuilder* bb, const Node* value) { IrArena* a = bb->arena; if (!bb->tail_block && shd_list_count(bb->stack) == 0) { - const Node* last_mem = bb_mem(bb); - cancel_body(bb); + const Node* last_mem = shd_bb_mem(bb); + shd_bld_cancel(bb); if (last_mem) return mem_and_value(a, (MemAndValue) { .mem = last_mem, @@ -211,20 +205,20 @@ const Node* yield_value_and_wrap_in_block(BodyBuilder* bb, const Node* value) { }); return value; } - assert(bb->block_entry_mem && "This builder wasn't started with 'begin_block'"); + assert(bb->block_entry_mem && "This builder wasn't started with 'shd_bld_begin_pure' or 'shd_bld_begin_pseudo_instr'"); bb->tail_block->payload.basic_block.insert = bb; const Node* r = mem_and_value(bb->arena, (MemAndValue) { - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), .value = value }); return r; } -const Node* yield_values_and_wrap_in_block(BodyBuilder* bb, Nodes values) { - return yield_value_and_wrap_in_block(bb, maybe_tuple_helper(bb->arena, values)); +const Node* shd_bld_to_instr_yield_values(BodyBuilder* bb, Nodes values) { + return shd_bld_to_instr_yield_value(bb, maybe_tuple_helper(bb->arena, values)); } -const Node* _shd_finish_block_body(BodyBuilder* bb, const Node* terminator) { +const Node* _shd_bld_finish_pseudo_instr(BodyBuilder* bb, const Node* terminator) { assert(bb->block_entry_mem); terminator = build_body(bb, terminator); shd_destroy_list(bb->stack); @@ -232,20 +226,20 @@ const Node* _shd_finish_block_body(BodyBuilder* bb, const Node* terminator) { return terminator; } -const Node* bind_last_instruction_and_wrap_in_block(BodyBuilder* bb, const Node* instruction) { +const Node* shd_bld_to_instr_with_last_instr(BodyBuilder* bb, const Node* instruction) { size_t stack_size = shd_list_count(bb->stack); if (stack_size == 0) { - cancel_body(bb); + shd_bld_cancel(bb); return instruction; } bind_internal(bb, instruction, 0); - return yield_value_and_wrap_in_block(bb, instruction); + return shd_bld_to_instr_yield_value(bb, instruction); } -const Node* yield_values_and_wrap_in_compound_instruction(BodyBuilder* bb, Nodes values) { +const Node* shd_bld_to_instr_pure_with_values(BodyBuilder* bb, Nodes values) { IrArena* arena = bb->arena; assert(!bb->mem && !bb->block_entry_mem && shd_list_count(bb->stack) == 0); - cancel_body(bb); + shd_bld_cancel(bb); return maybe_tuple_helper(arena, values); } @@ -259,7 +253,7 @@ static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { return shd_nodes(a, yield_types.count, tail_params); } -Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constructTag tag, union NodesUnion payload) { +static Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constructTag tag, union NodesUnion payload) { Node* tail = basic_block(bb->arena, params, NULL); StackEntry entry = { .structured = { @@ -272,22 +266,22 @@ Nodes add_structured_construct(BodyBuilder* bb, Nodes params, Structured_constru case NotAStructured_construct: shd_error("") case Structured_construct_If_TAG: { entry.structured.payload.if_instr.tail = tail; - entry.structured.payload.if_instr.mem = bb_mem(bb); + entry.structured.payload.if_instr.mem = shd_bb_mem(bb); break; } case Structured_construct_Match_TAG: { entry.structured.payload.match_instr.tail = tail; - entry.structured.payload.match_instr.mem = bb_mem(bb); + entry.structured.payload.match_instr.mem = shd_bb_mem(bb); break; } case Structured_construct_Loop_TAG: { entry.structured.payload.loop_instr.tail = tail; - entry.structured.payload.loop_instr.mem = bb_mem(bb); + entry.structured.payload.loop_instr.mem = shd_bb_mem(bb); break; } case Structured_construct_Control_TAG: { entry.structured.payload.control.tail = tail; - entry.structured.payload.control.mem = bb_mem(bb); + entry.structured.payload.control.mem = shd_bb_mem(bb); break; } } @@ -301,7 +295,7 @@ static Nodes gen_structured_construct(BodyBuilder* bb, Nodes yield_types, Struct return add_structured_construct(bb, gen_variables(bb, yield_types), tag, payload); } -Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, Node* false_case) { +Nodes shd_bld_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, Node* false_case) { return gen_structured_construct(bb, yield_types, Structured_construct_If_TAG, (union NodesUnion) { .if_instr = { .condition = condition, @@ -312,7 +306,7 @@ Nodes gen_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const No }); } -Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, Node* default_case) { +Nodes shd_bld_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, Node* default_case) { return gen_structured_construct(bb, yield_types, Structured_construct_Match_TAG, (union NodesUnion) { .match_instr = { .yield_types = yield_types, @@ -324,7 +318,7 @@ Nodes gen_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes }); } -Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, Node* body) { +Nodes shd_bld_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, Node* body) { return gen_structured_construct(bb, yield_types, Structured_construct_Loop_TAG, (union NodesUnion) { .loop_instr = { .yield_types = yield_types, @@ -334,7 +328,7 @@ Nodes gen_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, Node* bod }); } -Nodes gen_control(BodyBuilder* bb, Nodes yield_types, Node* body) { +Nodes shd_bld_control(BodyBuilder* bb, Nodes yield_types, Node* body) { return gen_structured_construct(bb, yield_types, Structured_construct_Control_TAG, (union NodesUnion) { .control = { .yield_types = yield_types, @@ -343,7 +337,7 @@ Nodes gen_control(BodyBuilder* bb, Nodes yield_types, Node* body) { }); } -begin_control_t begin_control(BodyBuilder* bb, Nodes yield_types) { +begin_control_t shd_bld_begin_control(BodyBuilder* bb, Nodes yield_types) { IrArena* a = bb->arena; const Type* jp_type = qualified_type(a, (QualifiedType) { .type = join_point_type(a, (JoinPointType) { .yield_types = yield_types }), @@ -352,26 +346,26 @@ begin_control_t begin_control(BodyBuilder* bb, Nodes yield_types) { const Node* jp = param(a, jp_type, NULL); Node* c = case_(a, shd_singleton(jp)); return (begin_control_t) { - .results = gen_control(bb, yield_types, c), + .results = shd_bld_control(bb, yield_types, c), .case_ = c, .jp = jp }; } -begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes arg_types, Nodes initial_values) { +begin_loop_helper_t shd_bld_begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes arg_types, Nodes initial_values) { assert(arg_types.count == initial_values.count); IrArena* a = bb->arena; - begin_control_t outer_control = begin_control(bb, yield_types); - BodyBuilder* outer_control_case_builder = begin_body_with_mem(a, shd_get_abstraction_mem(outer_control.case_)); + begin_control_t outer_control = shd_bld_begin_control(bb, yield_types); + BodyBuilder* outer_control_case_builder = shd_bld_begin(a, shd_get_abstraction_mem(outer_control.case_)); LARRAY(const Node*, params, arg_types.count); for (size_t i = 0; i < arg_types.count; i++) { params[i] = param(a, shd_as_qualified_type(arg_types.nodes[i], false), NULL); } Node* loop_header = case_(a, shd_nodes(a, arg_types.count, params)); - shd_set_abstraction_body(outer_control.case_, finish_body_with_jump(outer_control_case_builder, loop_header, initial_values)); - BodyBuilder* loop_header_builder = begin_body_with_mem(a, shd_get_abstraction_mem(loop_header)); - begin_control_t inner_control = begin_control(loop_header_builder, arg_types); - shd_set_abstraction_body(loop_header, finish_body_with_jump(loop_header_builder, loop_header, inner_control.results)); + shd_set_abstraction_body(outer_control.case_, shd_bld_jump(outer_control_case_builder, loop_header, initial_values)); + BodyBuilder* loop_header_builder = shd_bld_begin(a, shd_get_abstraction_mem(loop_header)); + begin_control_t inner_control = shd_bld_begin_control(loop_header_builder, arg_types); + shd_set_abstraction_body(loop_header, shd_bld_jump(loop_header_builder, loop_header, inner_control.results)); return (begin_loop_helper_t) { .results = outer_control.results, @@ -382,7 +376,7 @@ begin_loop_helper_t begin_loop_helper(BodyBuilder* bb, Nodes yield_types, Nodes }; } -void cancel_body(BodyBuilder* bb) { +void shd_bld_cancel(BodyBuilder* bb) { for (size_t i = 0; i < shd_list_count(bb->stack); i++) { StackEntry entry = shd_read_list(StackEntry, bb->stack)[i]; // if (entry.structured.tag != NotAStructured_construct) diff --git a/src/shady/ir/function.c b/src/shady/ir/function.c index 5345056cb..75150bf9f 100644 --- a/src/shady/ir/function.c +++ b/src/shady/ir/function.c @@ -125,7 +125,7 @@ void shd_set_abstraction_body(Node* abs, const Node* body) { if (insert && mem_abs != abs) { const Node* mem = _shd_bb_insert_mem(insert); const Node* block = _shd_bb_insert_block(insert); - shd_set_abstraction_body((Node*) block, _shd_finish_block_body(insert, body)); + shd_set_abstraction_body((Node*) block, _shd_bld_finish_pseudo_instr(insert, body)); body = jump_helper(a, mem, block, shd_empty(a)); // mem_abs->payload.basic_block.insert = NULL; continue; diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index a9fc73ac9..948eea1fc 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -39,7 +39,7 @@ NodeId _shd_allocate_node_id(IrArena* arena, const Node* n); IrArena* _shd_get_bb_arena(BodyBuilder* bb); const Node* _shd_bb_insert_mem(BodyBuilder* bb); const Node* _shd_bb_insert_block(BodyBuilder* bb); -const Node* _shd_finish_block_body(BodyBuilder* bb, const Node* terminator); +const Node* _shd_bld_finish_pseudo_instr(BodyBuilder* bb, const Node* terminator); struct List; Nodes shd_list_to_nodes(IrArena* arena, struct List* list); diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index b4fe540ed..e7d3e71a1 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -129,7 +129,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { lifted_cont->lifted_fn = new_fn; // Recover that stuff inside the new body - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_fn)); gen_set_stack_size(bb, payload); for (size_t i = recover_context_size - 1; i < recover_context_size; i--) { const Node* ovar = frontier.nodes[i]; @@ -148,13 +148,13 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { shd_register_processed(r, ovar, recovered_value); } - shd_register_processed(r, shd_get_abstraction_mem(liftee), bb_mem(bb)); + shd_register_processed(r, shd_get_abstraction_mem(liftee), shd_bb_mem(bb)); shd_register_processed(r, liftee, new_fn); const Node* substituted = shd_rewrite_node(r, obody); shd_destroy_rewriter(r); assert(is_terminator(substituted)); - shd_set_abstraction_body(new_fn, finish_body(bb, substituted)); + shd_set_abstraction_body(new_fn, shd_bld_finish(bb, substituted)); return lifted_cont; } @@ -195,7 +195,7 @@ static const Node* process_node(Context* ctx, const Node* node) { *ctx->todo = true; const Node* otail = get_structured_construct_tail(node); - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, node->payload.control.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, node->payload.control.mem)); LiftedCont* lifted_tail = lambda_lift(ctx, ctx->cfg, otail); const Node* sp = add_spill_instrs(ctx, bb, lifted_tail->save_values); const Node* tail_ptr = fn_addr_helper(a, lifted_tail->lifted_fn); @@ -209,9 +209,9 @@ static const Node* process_node(Context* ctx, const Node* node) { jp = gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(jp)); shd_register_processed(r, shd_first(get_abstraction_params(oinside)), jp); - shd_register_processed(r, shd_get_abstraction_mem(oinside), bb_mem(bb)); + shd_register_processed(r, shd_get_abstraction_mem(oinside), shd_bb_mem(bb)); shd_register_processed(r, oinside, NULL); - return finish_body(bb, shd_rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); + return shd_bld_finish(bb, shd_rewrite_node(&ctx->rewriter, get_abstraction_body(oinside))); } break; } diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 6e9583b0b..2cb9371c8 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -88,7 +88,7 @@ static const Node* process(Context* ctx, const Node* node) { return fun; } - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); ctx2.prepared_offsets = shd_new_dict(const Node*, StackSlot, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); ctx2.base_stack_addr_on_entry = gen_get_stack_base_addr(bb); ctx2.stack_size_on_entry = gen_get_stack_size(bb); @@ -119,8 +119,8 @@ static const Node* process(Context* ctx, const Node* node) { ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); // make sure to use the new mem from then on - shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); - shd_set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); + shd_register_processed(r, shd_get_abstraction_mem(node), shd_bb_mem(bb)); + shd_set_abstraction_body(fun, shd_bld_finish(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(node)))); shd_destroy_dict(ctx2.prepared_offsets); return fun; @@ -136,7 +136,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_error_die(); } - BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, node->payload.stack_alloc.mem)); + BodyBuilder* bb = shd_bld_begin_pseudo_instr(a, shd_rewrite_node(r, node->payload.stack_alloc.mem)); if (!ctx->stack_size_on_entry) { //String tmp_name = format_string_arena(a->arena, "stack_ptr_before_alloca_%s", get_abstraction_name(fun)); assert(false); @@ -153,7 +153,7 @@ static const Node* process(Context* ctx, const Node* node) { gen_set_stack_size(bb, updated_stack_ptr); //} - return yield_values_and_wrap_in_block(bb, shd_singleton(slot)); + return shd_bld_to_instr_yield_values(bb, shd_singleton(slot)); } break; } diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 1ff2b98db..b0849d4f2 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -35,7 +35,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { Nodes nannots = shd_rewrite_nodes(&ctx->rewriter, old->payload.fun.annotations); Node* prelude = case_(a, shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(prelude)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(prelude)); // Supplement an additional parameter for the join point const Type* jp_type = join_point_type(a, (JoinPointType) { @@ -54,8 +54,8 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { Node* fun = function(ctx->rewriter.dst_module, nparams, shd_get_abstraction_name(old), nannots, shd_empty(a)); shd_register_processed(&ctx->rewriter, old, fun); - shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); - shd_set_abstraction_body(prelude, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body))); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), shd_bb_mem(bb)); + shd_set_abstraction_body(prelude, shd_bld_finish(bb, shd_rewrite_node(&ctx2.rewriter, old->payload.fun.body))); shd_set_abstraction_body(fun, jump_helper(a, shd_get_abstraction_mem(fun), prelude, shd_empty(a))); return fun; } @@ -88,13 +88,13 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { const Node* return_jp = ctx->return_jp; if (return_jp) { - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, old->payload.fn_ret.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, old->payload.fn_ret.mem)); return_jp = gen_primop_ce(bb, subgroup_assume_uniform_op, 1, (const Node* []) { return_jp }); // Join up at the return address instead of returning - return finish_body(bb, join(a, (Join) { + return shd_bld_finish(bb, join(a, (Join) { .join_point = return_jp, .args = nargs, - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), })); } else { assert(false); @@ -137,8 +137,8 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { .mem = shd_get_abstraction_mem(control_case), }); shd_set_abstraction_body(control_case, control_body); - BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); - return yield_values_and_wrap_in_block(bb, gen_control(bb, shd_strip_qualifiers(a, returned_types), control_case)); + BodyBuilder* bb = shd_bld_begin_pseudo_instr(a, shd_rewrite_node(r, payload.mem)); + return shd_bld_to_instr_yield_values(bb, shd_bld_control(bb, shd_strip_qualifiers(a, returned_types), control_case)); } default: break; } diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 7722ece49..5143756fd 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -74,9 +74,9 @@ static const Node* process_node(Context* ctx, const Node* node) { }); shd_set_abstraction_body(control_case, control_body); - BodyBuilder* bb = begin_body_with_mem(a, nmem); - Nodes results = gen_control(bb, yield_types, control_case); - return finish_body(bb, jump_helper(a, bb_mem(bb), shd_rewrite_node(r, payload.tail), results)); + BodyBuilder* bb = shd_bld_begin(a, nmem); + Nodes results = shd_bld_control(bb, yield_types, control_case); + return shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), shd_rewrite_node(r, payload.tail), results)); } // TODO: match case Loop_TAG: { @@ -103,13 +103,13 @@ static const Node* process_node(Context* ctx, const Node* node) { Nodes new_params = shd_recreate_params(&ctx->rewriter, get_abstraction_params(old_loop_block)); Node* loop_header_block = basic_block(a, new_params, shd_make_unique_name(a, "loop_header")); - BodyBuilder* inner_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_header_block)); + BodyBuilder* inner_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_header_block)); Node* inner_control_case = case_(a, shd_singleton(continue_point)); shd_set_abstraction_body(inner_control_case, jump_helper(a, shd_get_abstraction_mem(inner_control_case), shd_rewrite_node(r, old_loop_block), new_params)); - Nodes args = gen_control(inner_bb, param_types, inner_control_case); + Nodes args = shd_bld_control(inner_bb, param_types, inner_control_case); - shd_set_abstraction_body(loop_header_block, finish_body(inner_bb, jump(a, (Jump) { .target = loop_header_block, .args = args, .mem = bb_mem(inner_bb) }))); + shd_set_abstraction_body(loop_header_block, shd_bld_finish(inner_bb, jump(a, (Jump) { .target = loop_header_block, .args = args, .mem = shd_bb_mem(inner_bb) }))); Node* outer_control_case = case_(a, shd_singleton(break_point)); const Node* first_iteration_jump = jump(a, (Jump) { @@ -119,9 +119,9 @@ static const Node* process_node(Context* ctx, const Node* node) { }); shd_set_abstraction_body(outer_control_case, first_iteration_jump); - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); - Nodes results = gen_control(bb, yield_types, outer_control_case); - return finish_body(bb, jump_helper(a, bb_mem(bb), shd_rewrite_node(r, payload.tail), results)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); + Nodes results = shd_bld_control(bb, yield_types, outer_control_case); + return shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), shd_rewrite_node(r, payload.tail), results)); } case MergeSelection_TAG: { MergeSelection payload = node->payload.merge_selection; diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 8fd5f92e8..2323e43e2 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -59,7 +59,7 @@ static const Node* generate_arg_struct(Rewriter* rewriter, const Node* old_entry static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const Node* new, const Node* arg_struct) { IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new)); Nodes params = old_entry_point->payload.fun.params; @@ -69,8 +69,8 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const shd_register_processed(&ctx->rewriter, params.nodes[i], val); } - shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(old_entry_point), bb_mem(bb)); - return finish_body(bb, shd_rewrite_node(&ctx->rewriter, old_entry_point->payload.fun.body)); + shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(old_entry_point), shd_bb_mem(bb)); + return shd_bld_finish(bb, shd_rewrite_node(&ctx->rewriter, old_entry_point->payload.fun.body)); } static const Node* process(Context* ctx, const Node* node) { diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 429bfc7cd..e62c5d0ca 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -107,9 +107,9 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo size_t max_tag = sizeof(generic_ptr_tags) / sizeof(generic_ptr_tags[0]); switch (which) { case LoadFn: { - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); - begin_control_t r = begin_control(bb, shd_singleton(t)); + begin_control_t r = shd_bld_begin_control(bb, shd_singleton(t)); const Node* final_loaded_value = shd_first(r.results); LARRAY(const Node*, literals, max_tag); @@ -123,10 +123,10 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo continue; } Node* tag_case = case_(a, shd_empty(a)); - BodyBuilder* case_bb = begin_body_with_mem(a, shd_get_abstraction_mem(tag_case)); + BodyBuilder* case_bb = shd_bld_begin(a, shd_get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); - shd_set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_singleton(loaded_value))); + shd_set_abstraction_body(tag_case, shd_bld_join(case_bb, r.jp, shd_singleton(loaded_value))); jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example @@ -141,13 +141,13 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo .case_jumps = shd_nodes(a, max_tag, jumps), .default_jump = jump_helper(a, shd_get_abstraction_mem(r.case_), default_case, shd_empty(a)) })); - shd_set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_singleton(final_loaded_value), .mem = bb_mem(bb) }))); + shd_set_abstraction_body(new_fn, shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_singleton(final_loaded_value), .mem = shd_bb_mem(bb) }))); break; } case StoreFn: { - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_fn)); gen_comment(bb, "Generated generic ptr store"); - begin_control_t r = begin_control(bb, shd_empty(a)); + begin_control_t r = shd_bld_begin_control(bb, shd_empty(a)); LARRAY(const Node*, literals, max_tag); LARRAY(const Node*, jumps, max_tag); @@ -160,10 +160,10 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo continue; } Node* tag_case = case_(a, shd_empty(a)); - BodyBuilder* case_bb = begin_body_with_mem(a, shd_get_abstraction_mem(tag_case)); + BodyBuilder* case_bb = shd_bld_begin(a, shd_get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); gen_store(case_bb, reinterpreted_ptr, value_param); - shd_set_abstraction_body(tag_case, finish_body_with_join(case_bb, r.jp, shd_empty(a))); + shd_set_abstraction_body(tag_case, shd_bld_join(case_bb, r.jp, shd_empty(a))); jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example @@ -178,7 +178,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo .case_jumps = shd_nodes(a, max_tag, jumps), .default_jump = jump_helper(a, shd_get_abstraction_mem(r.case_), default_case, shd_empty(a)) })); - shd_set_abstraction_body(new_fn, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); + shd_set_abstraction_body(new_fn, shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) }))); break; } } @@ -241,7 +241,7 @@ static const Node* process(Context* ctx, const Node* old) { // cast _into_ generic AddressSpace src_as = old_src_t->payload.ptr_type.address_space; size_t tag = get_tag_for_addr_space(src_as); - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); // TODO: find another way to annotate this ? // String x = format_string_arena(a->arena, "Generated generic ptr convert src %d tag %d", src_as, tag); // gen_comment(bb, x); @@ -253,7 +253,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* shifted_tag = size_t_literal(a, (tag << (uint64_t) (shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr | 01000000 ... 000 generic_ptr = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, generic_ptr, shifted_tag)); - return yield_values_and_wrap_in_block(bb, shd_singleton(generic_ptr)); + return shd_bld_to_instr_yield_values(bb, shd_singleton(generic_ptr)); } else if (old_src_t->tag == PtrType_TAG && old_src_t->payload.ptr_type.address_space == AsGeneric) { // cast _from_ generic shd_error("TODO"); diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 0dd633fc4..124a8cda3 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -17,10 +17,10 @@ static bool should_convert(Context* ctx, const Type* t) { } static void extract_low_hi_halves(IrArena* a, BodyBuilder* bb, const Node* src, const Node** lo, const Node** hi) { - *lo = shd_first(bind_instruction(bb, prim_op(a, - (PrimOp) { .op = extract_op, .operands = mk_nodes(a, src, shd_int32_literal(a, 0)) }))); - *hi = shd_first(bind_instruction(bb, prim_op(a, - (PrimOp) { .op = extract_op, .operands = mk_nodes(a, src, shd_int32_literal(a, 1)) }))); + *lo = shd_first(shd_bld_add_instruction_extract(bb, prim_op(a, + (PrimOp) { .op = extract_op, .operands = mk_nodes(a, src, shd_int32_literal(a, 0)) }))); + *hi = shd_first(shd_bld_add_instruction_extract(bb, prim_op(a, + (PrimOp) { .op = extract_op, .operands = mk_nodes(a, src, shd_int32_literal(a, 1)) }))); } static void extract_low_hi_halves_list(IrArena* a, BodyBuilder* bb, Nodes src, const Node** lows, const Node** his) { @@ -58,14 +58,14 @@ static const Node* process(Context* ctx, const Node* node) { case add_op: if (should_convert(ctx, shd_first(old_nodes)->type)) { Nodes new_nodes = shd_rewrite_nodes(&ctx->rewriter, old_nodes); // TODO: convert into and then out of unsigned - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); extract_low_hi_halves_list(a, bb, new_nodes, lows, his); - Nodes low_and_carry = bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_carry_op, .operands = shd_nodes(a, 2, lows)})); + Nodes low_and_carry = shd_bld_add_instruction_extract(bb, prim_op(a, (PrimOp) { .op = add_carry_op, .operands = shd_nodes(a, 2, lows) })); const Node* lo = shd_first(low_and_carry); // compute the high side, without forgetting the carry bit - const Node* hi = shd_first(bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = shd_nodes(a, 2, his) }))); - hi = shd_first(bind_instruction(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = mk_nodes(a, hi, low_and_carry.nodes[1]) }))); - return yield_values_and_wrap_in_block(bb, shd_singleton(tuple_helper(a, mk_nodes(a, lo, hi)))); + const Node* hi = shd_first(shd_bld_add_instruction_extract(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = shd_nodes(a, 2, his) }))); + hi = shd_first(shd_bld_add_instruction_extract(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = mk_nodes(a, hi, low_and_carry.nodes[1]) }))); + return shd_bld_to_instr_yield_values(bb, shd_singleton(tuple_helper(a, mk_nodes(a, lo, hi)))); } break; default: break; } diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index c407c9b36..8cdba2d1e 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -126,14 +126,14 @@ static const Node* process(Context* ctx, const Node* old) { must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference && is_as_emulated(ctx, old_base_ptr_t->payload.ptr_type.address_space); if (!must_lower) break; - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, shd_rewrite_node(r, lea.ptr)); const Type* new_base_t = shd_rewrite_node(&ctx->rewriter, old_base_ptr_t); const Node* result = lower_ptr_offset(ctx, bb, new_base_t, cast_base, shd_rewrite_node(r, lea.offset)); const Type* new_ptr_t = shd_rewrite_node(&ctx->rewriter, old_result_t); const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); - return yield_values_and_wrap_in_block(bb, shd_singleton(cast_result)); + return shd_bld_to_instr_yield_values(bb, shd_singleton(cast_result)); } case PtrCompositeElement_TAG: { PtrCompositeElement lea = old->payload.ptr_composite_element; @@ -149,14 +149,14 @@ static const Node* process(Context* ctx, const Node* old) { must_lower |= ctx->config->lower.emulate_physical_memory && !old_base_ptr_t->payload.ptr_type.is_reference && is_as_emulated(ctx, old_base_ptr_t->payload.ptr_type.address_space); if (!must_lower) break; - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, shd_rewrite_node(r, lea.ptr)); const Type* new_base_t = shd_rewrite_node(&ctx->rewriter, old_base_ptr_t); const Node* result = lower_ptr_index(ctx, bb, new_base_t, cast_base, shd_rewrite_node(r, lea.index)); const Type* new_ptr_t = shd_rewrite_node(&ctx->rewriter, old_result_t); const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); - return yield_values_and_wrap_in_block(bb, shd_singleton(cast_result)); + return shd_bld_to_instr_yield_values(bb, shd_singleton(cast_result)); } default: break; } diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 2d6b31935..78d5ef32e 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -74,10 +74,10 @@ static const Node* process(Context* ctx, const Node* old) { const Type* expected_type = shd_rewrite_node(r, optr_t); const Node* ptr = shd_rewrite_node(r, payload.ptr); const Type* actual_type = shd_get_unqualified_type(ptr->type); - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, shd_get_pointer_type_element(expected_type)); - return bind_last_instruction_and_wrap_in_block(bb, ptr_composite_element(a, (PtrCompositeElement) { .ptr = ptr, .index = shd_rewrite_node(r, payload.index)})); + return shd_bld_to_instr_with_last_instr(bb, ptr_composite_element(a, (PtrCompositeElement) { .ptr = ptr, .index = shd_rewrite_node(r, payload.index) })); } case PrimOp_TAG: { PrimOp payload = old->payload.prim_op; @@ -102,10 +102,10 @@ static const Node* process(Context* ctx, const Node* old) { const Type* expected_type = shd_rewrite_node(r, optr_t); const Node* ptr = shd_rewrite_node(r, payload.ptr); const Type* actual_type = shd_get_unqualified_type(ptr->type); - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, shd_get_pointer_type_element(expected_type)); - return load(a, (Load) { .ptr = yield_value_and_wrap_in_block(bb, ptr), .mem = shd_rewrite_node(r, payload.mem) }); + return load(a, (Load) { .ptr = shd_bld_to_instr_yield_value(bb, ptr), .mem = shd_rewrite_node(r, payload.mem) }); } case Store_TAG: { Store payload = old->payload.store; @@ -115,10 +115,10 @@ static const Node* process(Context* ctx, const Node* old) { const Type* expected_type = shd_rewrite_node(r, optr_t); const Node* ptr = shd_rewrite_node(r, payload.ptr); const Type* actual_type = shd_get_unqualified_type(ptr->type); - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); if (expected_type != actual_type) ptr = guess_pointer_casts(ctx, bb, ptr, shd_get_pointer_type_element(expected_type)); - return bind_last_instruction_and_wrap_in_block(bb, store(a, (Store) { .ptr = ptr, .value = shd_rewrite_node(r, payload.value), .mem = shd_rewrite_node(r, payload.mem) })); + return shd_bld_to_instr_with_last_instr(bb, store(a, (Store) { .ptr = ptr, .value = shd_rewrite_node(r, payload.value), .mem = shd_rewrite_node(r, payload.mem) })); } case GlobalVariable_TAG: { AddressSpace as = old->payload.global_variable.address_space; diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index b7ed855c6..39bd86a2a 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -25,7 +25,7 @@ static const Node* process(Context* ctx, const Node* node) { case empty_mask_op: return ctx->zero; // extract the relevant bit case mask_is_thread_active_op: { - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); const Node* mask = shd_rewrite_node(&ctx->rewriter, old_nodes.nodes[0]); const Node* index = shd_rewrite_node(&ctx->rewriter, old_nodes.nodes[1]); index = gen_conversion(bb, shd_get_actual_mask_type(ctx->rewriter.dst_arena), index); @@ -36,7 +36,7 @@ static const Node* process(Context* ctx, const Node* node) { acc = gen_primop_ce(bb, and_op, 2, (const Node* []) { acc, ctx->one }); // acc == 1 acc = gen_primop_ce(bb, eq_op, 2, (const Node* []) { acc, ctx->one }); - return yield_value_and_wrap_in_block(bb, acc); + return shd_bld_to_instr_yield_value(bb, acc); } default: break; } diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index f0851b992..824e0f4b2 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -24,7 +24,7 @@ static const Node* process(Context* ctx, const Node* old) { CopyBytes payload = old->payload.copy_bytes; const Type* word_type = int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin_pseudo_instr(a, shd_rewrite_node(r, payload.mem)); const Node* dst_addr = shd_rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; @@ -49,12 +49,12 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), shd_rewrite_node(&ctx->rewriter, payload.count)); const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num_in_bytes)); - begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); + begin_loop_helper_t l = shd_bld_begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); const Node* index = shd_first(l.params); shd_set_value_name(index, "memcpy_i"); Node* loop_case = l.loop_body; - BodyBuilder* loop_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_case)); + BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_case)); const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, shd_empty(a))); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); @@ -64,14 +64,14 @@ static const Node* process(Context* ctx, const Node* old) { Node* false_case = case_(a, shd_empty(a)); shd_set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = shd_get_abstraction_mem(false_case), .args = shd_empty(a) })); - shd_set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { - .mem = bb_mem(loop_bb), + shd_set_abstraction_body(loop_case, shd_bld_finish(loop_bb, branch(a, (Branch) { + .mem = shd_bb_mem(loop_bb), .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), - .true_jump = jump_helper(a, bb_mem(loop_bb), true_case, shd_empty(a)), - .false_jump = jump_helper(a, bb_mem(loop_bb), false_case, shd_empty(a)), + .true_jump = jump_helper(a, shd_bb_mem(loop_bb), true_case, shd_empty(a)), + .false_jump = jump_helper(a, shd_bb_mem(loop_bb), false_case, shd_empty(a)), }))); - return yield_values_and_wrap_in_block(bb, shd_empty(a)); + return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } case FillBytes_TAG: { FillBytes payload = old->payload.fill_bytes; @@ -81,7 +81,7 @@ static const Node* process(Context* ctx, const Node* old) { assert(src_type->tag == Int_TAG); const Type* word_type = src_type;// int_type(a, (Int) { .is_signed = false, .width = a->config.memory.word_size }); - BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin_pseudo_instr(a, shd_rewrite_node(r, payload.mem)); const Node* dst_addr = shd_rewrite_node(&ctx->rewriter, payload.dst); const Type* dst_addr_type = dst_addr->type; @@ -96,12 +96,12 @@ static const Node* process(Context* ctx, const Node* old) { const Node* num = shd_rewrite_node(&ctx->rewriter, payload.count); const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num)); - begin_loop_helper_t l = begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); + begin_loop_helper_t l = shd_bld_begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); const Node* index = shd_first(l.params); shd_set_value_name(index, "memset_i"); Node* loop_case = l.loop_body; - BodyBuilder* loop_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_case)); + BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_case)); gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); @@ -110,13 +110,13 @@ static const Node* process(Context* ctx, const Node* old) { Node* false_case = case_(a, shd_empty(a)); shd_set_abstraction_body(false_case, join(a, (Join) { .join_point = l.break_jp, .mem = shd_get_abstraction_mem(false_case), .args = shd_empty(a) })); - shd_set_abstraction_body(loop_case, finish_body(loop_bb, branch(a, (Branch) { - .mem = bb_mem(loop_bb), + shd_set_abstraction_body(loop_case, shd_bld_finish(loop_bb, branch(a, (Branch) { + .mem = shd_bb_mem(loop_bb), .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), - .true_jump = jump_helper(a, bb_mem(loop_bb), true_case, shd_empty(a)), - .false_jump = jump_helper(a, bb_mem(loop_bb), false_case, shd_empty(a)), + .true_jump = jump_helper(a, shd_bb_mem(loop_bb), true_case, shd_empty(a)), + .false_jump = jump_helper(a, shd_bb_mem(loop_bb), false_case, shd_empty(a)), }))); - return yield_values_and_wrap_in_block(bb, shd_empty(a)); + return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } default: break; } diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 08799e6b5..759c1b271 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -18,12 +18,12 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { if (found) return *found; - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); const Node* nul = gen_reinterpret_cast(bb, t, shd_uint64_literal(a, 0)); Node* decl = constant(ctx->rewriter.dst_module, shd_singleton(annotation(a, (Annotation) { .name = "Generated", })), t, shd_fmt_string_irarena(a, "nullptr_%s", shd_get_type_name(a, t))); - decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(nul)); + decl->payload.constant.value = shd_bld_to_instr_pure_with_values(bb, shd_singleton(nul)); const Node* ref = ref_decl_helper(a, decl); shd_dict_insert(const Type*, const Node*, ctx->map, t, ref); return ref; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 095e3b139..64b239824 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -272,15 +272,15 @@ static const Node* gen_serdes_fn(Context* ctx, const Type* element_type, bool un Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); const Node* base = *get_emulated_as_word_array(ctx, as); if (ser) { gen_serialisation(ctx, bb, element_type, base, address_param, value_param); - shd_set_abstraction_body(fun, finish_body_with_return(bb, shd_empty(a))); + shd_set_abstraction_body(fun, shd_bld_return(bb, shd_empty(a))); } else { const Node* loaded_value = gen_deserialisation(ctx, bb, element_type, base, address_param); assert(loaded_value); - shd_set_abstraction_body(fun, finish_body_with_return(bb, shd_singleton(loaded_value))); + shd_set_abstraction_body(fun, shd_bld_return(bb, shd_singleton(loaded_value))); } return fun; } @@ -297,12 +297,12 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; - BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin_pseudo_instr(a, shd_rewrite_node(r, payload.mem)); const Type* element_type = shd_rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); const Node* pointer_as_offset = shd_rewrite_node(&ctx->rewriter, payload.ptr); const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, false, ptr_type->payload.ptr_type.address_space); Nodes results = gen_call(bb, fn_addr_helper(a, fn), shd_singleton(pointer_as_offset)); - return yield_values_and_wrap_in_block(bb, results); + return shd_bld_to_instr_yield_values(bb, results); } case Store_TAG: { Store payload = old->payload.store; @@ -311,7 +311,7 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ptr_type->tag == PtrType_TAG); if (ptr_type->payload.ptr_type.is_reference || !is_as_emulated(ctx, ptr_type->payload.ptr_type.address_space)) break; - BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin_pseudo_instr(a, shd_rewrite_node(r, payload.mem)); const Type* element_type = shd_rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); const Node* pointer_as_offset = shd_rewrite_node(&ctx->rewriter, payload.ptr); @@ -319,7 +319,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* value = shd_rewrite_node(&ctx->rewriter, payload.value); gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, pointer_as_offset, value)); - return yield_values_and_wrap_in_block(bb, shd_empty(a)); + return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } case StackAlloc_TAG: shd_error("This needs to be lowered (see setup_stack_frames.c)") case PtrType_TAG: { @@ -343,13 +343,13 @@ static const Node* process_node(Context* ctx, const Node* old) { case Function_TAG: { if (strcmp(shd_get_abstraction_name(old), "generated_init") == 0) { Node* new = shd_recreate_node_head(&ctx->rewriter, old); - BodyBuilder *bb = begin_body_with_mem(a, shd_get_abstraction_mem(new)); + BodyBuilder *bb = shd_bld_begin(a, shd_get_abstraction_mem(new)); for (AddressSpace as = 0; as < NumAddressSpaces; as++) { if (is_as_emulated(ctx, as)) store_init_data(ctx, as, ctx->collected[as], bb); } - shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); - shd_set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); + shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(old), shd_bb_mem(bb)); + shd_set_abstraction_body(new, shd_bld_finish(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } break; @@ -406,9 +406,9 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect // we need to compute the actual pointer by getting the offset and dividing it // after lower_memory_layout, optimisations will eliminate this and resolve to a value - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); const Node* offset = gen_primop_e(bb, offset_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_singleton(size_t_literal(a, i))); - new_address->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(offset)); + new_address->payload.constant.value = shd_bld_to_instr_pure_with_values(bb, shd_singleton(offset)); shd_register_processed(&ctx->rewriter, decl, new_address); } @@ -462,12 +462,12 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { Nodes annotations = shd_singleton(annotation(a, (Annotation) { .name = "Generated" })); // compute the size - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); const Node* size_of = gen_primop_e(bb, size_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_empty(a)); const Node* size_in_words = shd_bytes_to_words(bb, size_of); Node* constant_decl = constant(m, annotations, ptr_size_type, shd_fmt_string_irarena(a, "memory_%s_size", as_name)); - constant_decl->payload.constant.value = yield_values_and_wrap_in_compound_instruction(bb, shd_singleton(size_in_words)); + constant_decl->payload.constant.value = shd_bld_to_instr_pure_with_values(bb, shd_singleton(size_in_words)); const Type* words_array_type = arr_type(a, (ArrType) { .element_type = word_type, diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 363117692..2f1de5408 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -42,7 +42,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { Node* fun = function(ctx->rewriter.dst_module, params, name, mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), return_ts); shd_dict_insert(const Node*, Node*, cache, element_type, fun); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); const Node* element_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); element_size = gen_conversion(bb, shd_uint32_type(a), element_size); @@ -79,10 +79,10 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { } if (push) { - shd_set_abstraction_body(fun, finish_body_with_return(bb, shd_empty(a))); + shd_set_abstraction_body(fun, shd_bld_return(bb, shd_empty(a))); } else { assert(popped_value); - shd_set_abstraction_body(fun, finish_body_with_return(bb, shd_singleton(popped_value))); + shd_set_abstraction_body(fun, shd_bld_return(bb, shd_singleton(popped_value))); } return fun; } @@ -93,7 +93,7 @@ static const Node* process_node(Context* ctx, const Node* old) { if (old->tag == Function_TAG && strcmp(shd_get_abstraction_name(old), "generated_init") == 0) { Node* new = shd_recreate_node_head(&ctx->rewriter, old); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new)); // Make sure to zero-init the stack pointers // TODO isn't this redundant with thoose things having an initial value already ? @@ -102,8 +102,8 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* stack_pointer = ctx->stack_pointer; gen_store(bb, stack_pointer, shd_uint32_literal(a, 0)); } - shd_register_processed(r, shd_get_abstraction_mem(old), bb_mem(bb)); - shd_set_abstraction_body(new, finish_body(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); + shd_register_processed(r, shd_get_abstraction_mem(old), shd_bb_mem(bb)); + shd_set_abstraction_body(new, shd_bld_finish(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); return new; } @@ -111,34 +111,34 @@ static const Node* process_node(Context* ctx, const Node* old) { case GetStackSize_TAG: { assert(ctx->stack); GetStackSize payload = old->payload.get_stack_size; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* sp = gen_load(bb, ctx->stack_pointer); - return yield_values_and_wrap_in_block(bb, shd_singleton(sp)); + return shd_bld_to_instr_yield_values(bb, shd_singleton(sp)); } case SetStackSize_TAG: { assert(ctx->stack); SetStackSize payload = old->payload.set_stack_size; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* val = shd_rewrite_node(r, old->payload.set_stack_size.value); gen_store(bb, ctx->stack_pointer, val); - return yield_values_and_wrap_in_block(bb, shd_empty(a)); + return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } case GetStackBaseAddr_TAG: { assert(ctx->stack); GetStackBaseAddr payload = old->payload.get_stack_base_addr; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* stack_pointer = ctx->stack_pointer; const Node* stack_size = gen_load(bb, stack_pointer); const Node* stack_base_ptr = gen_lea(bb, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { gen_debug_printf(bb, "trace: stack_size=%d\n", shd_singleton(stack_size)); } - return yield_values_and_wrap_in_block(bb, shd_singleton(stack_base_ptr)); + return shd_bld_to_instr_yield_values(bb, shd_singleton(stack_base_ptr)); } case PushStack_TAG:{ assert(ctx->stack); PushStack payload = old->payload.push_stack; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Type* element_type = shd_rewrite_node(&ctx->rewriter, shd_get_unqualified_type(old->payload.push_stack.value->type)); bool push = true; @@ -147,12 +147,12 @@ static const Node* process_node(Context* ctx, const Node* old) { Nodes args = shd_singleton(shd_rewrite_node(&ctx->rewriter, old->payload.push_stack.value)); gen_call(bb, fn_addr_helper(a, fn), args); - return yield_values_and_wrap_in_block(bb, shd_empty(a)); + return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } case PopStack_TAG: { assert(ctx->stack); PopStack payload = old->payload.pop_stack; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Type* element_type = shd_rewrite_node(&ctx->rewriter, old->payload.pop_stack.type); bool push = false; @@ -161,7 +161,7 @@ static const Node* process_node(Context* ctx, const Node* old) { Nodes results = gen_call(bb, fn_addr_helper(a, fn), shd_empty(a)); assert(results.count == 1); - return yield_values_and_wrap_in_block(bb, results); + return shd_bld_to_instr_yield_values(bb, results); } default: break; } diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 637fa1921..1aa68ce94 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -85,12 +85,12 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co static void build_fn_body(Context* ctx, Node* fn, const Node* scope, const Node* param, const Type* t) { IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fn)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fn)); const Node* result = generate(ctx, bb, scope, t, param); if (result) { - shd_set_abstraction_body(fn, finish_body(bb, fn_ret(a, (Return) { + shd_set_abstraction_body(fn, shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_singleton(result), - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), }))); return; } @@ -134,8 +134,8 @@ static const Node* process(Context* ctx, const Node* node) { case ExtInstr_TAG: { ExtInstr payload = node->payload.ext_instr; if (strcmp(payload.set, "spirv.core") == 0 && payload.opcode == SpvOpGroupNonUniformBroadcastFirst) { - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); - return yield_values_and_wrap_in_block(bb, shd_singleton( + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); + return shd_bld_to_instr_yield_values(bb, shd_singleton( build_subgroup_first(ctx, bb, shd_rewrite_node(r, payload.operands.nodes[0]), shd_rewrite_node(r, payload.operands.nodes[1])))); } } diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index f94c9cba1..3a7f6d41d 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -24,12 +24,12 @@ static const Node* process(Context* ctx, const Node* node) { functx.rewriter.map = shd_clone_dict(functx.rewriter.map); shd_dict_clear(functx.rewriter.map); shd_register_processed_list(&functx.rewriter, get_abstraction_params(node), get_abstraction_params(newfun)); - functx.bb = begin_body_with_mem(a, shd_get_abstraction_mem(newfun)); + functx.bb = shd_bld_begin(a, shd_get_abstraction_mem(newfun)); Node* post_prelude = basic_block(a, shd_empty(a), "post-prelude"); shd_register_processed(&functx.rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(post_prelude)); shd_set_abstraction_body(post_prelude, shd_rewrite_node(&functx.rewriter, get_abstraction_body(node))); - shd_set_abstraction_body(newfun, finish_body(functx.bb, jump_helper(a, bb_mem(functx.bb), post_prelude, - shd_empty(a)))); + shd_set_abstraction_body(newfun, shd_bld_finish(functx.bb, jump_helper(a, shd_bb_mem(functx.bb), post_prelude, + shd_empty(a)))); shd_destroy_dict(functx.rewriter.map); } return newfun; diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index a00a6974a..c1a13e465 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -152,7 +152,7 @@ static const Node* process(Context* ctx, const Node* node) { root = insert(root, t); } - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* run_default_case = gen_stack_alloc(bb, bool_type(a)); gen_store(bb, run_default_case, false_lit(a)); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 73bb334a2..2304d4ccd 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -75,7 +75,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { Nodes rewritten_params = shd_recreate_params(&ctx2.rewriter, old->payload.fun.params); Node* new_entry_pt = function(ctx2.rewriter.dst_module, rewritten_params, old->payload.fun.name, shd_rewrite_nodes(&ctx2.rewriter, old->payload.fun.annotations), shd_nodes(a, 0, NULL)); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_entry_pt)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_entry_pt)); gen_call(bb, fn_addr_helper(a, ctx->init_fn), shd_empty(a)); gen_call(bb, access_decl(&ctx->rewriter, "builtin_init_scheduler"), shd_empty(a)); @@ -97,9 +97,9 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { gen_call(bb, fn_addr_helper(a, *ctx->top_dispatcher_fn), shd_empty(a)); - shd_set_abstraction_body(new_entry_pt, finish_body(bb, fn_ret(a, (Return) { + shd_set_abstraction_body(new_entry_pt, shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_nodes(a, 0, NULL), - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), }))); } @@ -120,12 +120,12 @@ static const Node* process(Context* ctx, const Node* old) { if (ctx2.disable_lowering) { Node* fun = shd_recreate_node_head(&ctx2.rewriter, old); if (old->payload.fun.body) { - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); if (entry_point_annotation) { gen_call(bb, fn_addr_helper(a, ctx2.init_fn), shd_empty(a)); } - shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); - shd_set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), shd_bb_mem(bb)); + shd_set_abstraction_body(fun, shd_bld_finish(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); } destroy_uses_map(ctx2.uses); @@ -147,7 +147,7 @@ static const Node* process(Context* ctx, const Node* old) { if (entry_point_annotation) lift_entry_point(ctx, old, fun); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); // Params become stack pops ! for (size_t i = 0; i < old->payload.fun.params.count; i++) { const Node* old_param = old->payload.fun.params.nodes[i]; @@ -160,8 +160,8 @@ static const Node* process(Context* ctx, const Node* old) { shd_set_value_name((Node*) popped, old_param->payload.param.name); shd_register_processed(&ctx->rewriter, old_param, popped); } - shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), bb_mem(bb)); - shd_set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), shd_bb_mem(bb)); + shd_set_abstraction_body(fun, shd_bld_finish(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); destroy_uses_map(ctx2.uses); destroy_cfg(ctx2.cfg); return fun; @@ -205,13 +205,13 @@ static const Node* process(Context* ctx, const Node* old) { //if (ctx->disable_lowering) // return recreate_node_identity(&ctx->rewriter, old); TailCall payload = old->payload.tail_call; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); gen_push_values_stack(bb, shd_rewrite_nodes(&ctx->rewriter, payload.args)); const Node* target = shd_rewrite_node(&ctx->rewriter, payload.callee); target = gen_conversion(bb, shd_uint32_type(a), target); gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); - return finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) })); + return shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) })); } case Join_TAG: { Join payload = old->payload.join; @@ -224,7 +224,7 @@ static const Node* process(Context* ctx, const Node* old) { if (jp_type->tag == JoinPointType_TAG) break; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); gen_push_values_stack(bb, shd_rewrite_nodes(&ctx->rewriter, old->payload.join.args)); const Node* jp_payload = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 2))); gen_push_value_stack(bb, jp_payload); @@ -232,7 +232,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* tree_node = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 0))); gen_call(bb, access_decl(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); - return finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) })); + return shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) })); } case PtrType_TAG: { const Node* pointee = old->payload.ptr_type.pointed_type; @@ -283,7 +283,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { assert((*ctx->top_dispatcher_fn)->tag == Function_TAG); IrArena* a = ctx->rewriter.dst_arena; - BodyBuilder* dispatcher_body_builder = begin_body_with_mem(a, shd_get_abstraction_mem(*ctx->top_dispatcher_fn)); + BodyBuilder* dispatcher_body_builder = shd_bld_begin(a, shd_get_abstraction_mem(*ctx->top_dispatcher_fn)); bool count_iterations = ctx->config->shader_diagnostics.max_top_iterations > 0; @@ -293,11 +293,11 @@ static void generate_top_level_dispatch_fn(Context* ctx) { // Node* loop_inside_case = case_(a, count_iterations ? singleton(iterations_count_param) : shd_nodes(a, 0, NULL)); // gen_loop(dispatcher_body_builder, empty(a), count_iterations ? singleton(int32_literal(a, 0)) : empty(a), loop_inside_case); - begin_loop_helper_t l = begin_loop_helper(dispatcher_body_builder, shd_empty(a), count_iterations ? shd_singleton(shd_int32_type(a)) : shd_empty(a), count_iterations ? shd_singleton(shd_int32_literal(a, 0)) : shd_empty(a)); + begin_loop_helper_t l = shd_bld_begin_loop_helper(dispatcher_body_builder, shd_empty(a), count_iterations ? shd_singleton(shd_int32_type(a)) : shd_empty(a), count_iterations ? shd_singleton(shd_int32_literal(a, 0)) : shd_empty(a)); Node* loop_inside_case = l.loop_body; if (count_iterations) iterations_count_param = shd_first(l.params); - BodyBuilder* loop_body_builder = begin_body_with_mem(a, shd_get_abstraction_mem(loop_inside_case)); + BodyBuilder* loop_body_builder = shd_bld_begin(a, shd_get_abstraction_mem(loop_inside_case)); const Node* next_function = gen_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); const Node* get_active_branch_fn = access_decl(&ctx->rewriter, "builtin_get_active_branch"); @@ -318,7 +318,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, 1))); if (ctx->config->shader_diagnostics.max_top_iterations > 0) { - begin_control_t c = begin_control(loop_body_builder, shd_empty(a)); + begin_control_t c = shd_bld_begin_control(loop_body_builder, shd_empty(a)); const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); Node* bail_case = case_(a, shd_empty(a)); const Node* break_terminator = join(a, (Join) { .args = shd_empty(a), .join_point = l.break_jp, .mem = shd_get_abstraction_mem(bail_case) }); @@ -344,20 +344,20 @@ static void generate_top_level_dispatch_fn(Context* ctx) { // Build 'zero' case (exits the program) Node* zero_case_lam = case_(a, shd_nodes(a, 0, NULL)); Node* zero_if_true_lam = case_(a, shd_empty(a)); - BodyBuilder* zero_if_case_builder = begin_body_with_mem(a, shd_get_abstraction_mem(zero_if_true_lam)); + BodyBuilder* zero_if_case_builder = shd_bld_begin(a, shd_get_abstraction_mem(zero_if_true_lam)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } - shd_set_abstraction_body(zero_if_true_lam, finish_body_with_join(zero_if_case_builder, l.break_jp, shd_empty(a))); + shd_set_abstraction_body(zero_if_true_lam, shd_bld_join(zero_if_case_builder, l.break_jp, shd_empty(a))); Node* zero_if_false = case_(a, shd_empty(a)); - BodyBuilder* zero_false_builder = begin_body_with_mem(a, shd_get_abstraction_mem(zero_if_false)); + BodyBuilder* zero_false_builder = shd_bld_begin(a, shd_get_abstraction_mem(zero_if_false)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, zero_false_builder, BuiltinSubgroupId); gen_debug_printf(zero_false_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } - shd_set_abstraction_body(zero_if_false, finish_body_with_join(zero_false_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); + shd_set_abstraction_body(zero_if_false, shd_bld_join(zero_false_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); shd_set_abstraction_body(zero_case_lam, branch(a, (Branch) { .mem = shd_get_abstraction_mem(zero_case_lam), @@ -368,7 +368,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { const Node* zero_lit = shd_uint64_literal(a, 0); shd_list_append(const Node*, literals, zero_lit); - const Node* zero_jump = jump_helper(a, bb_mem(loop_body_builder), zero_case_lam, shd_empty(a)); + const Node* zero_jump = jump_helper(a, shd_bb_mem(loop_body_builder), zero_case_lam, shd_empty(a)); shd_list_append(const Node*, jumps, zero_jump); Nodes old_decls = shd_module_get_declarations(ctx->rewriter.src_module); @@ -381,13 +381,13 @@ static void generate_top_level_dispatch_fn(Context* ctx) { const Node* fn_lit = shd_uint32_literal(a, get_fn_ptr(ctx, decl)); Node* if_true_case = case_(a, shd_empty(a)); - BodyBuilder* if_builder = begin_body_with_mem(a, shd_get_abstraction_mem(if_true_case)); + BodyBuilder* if_builder = shd_bld_begin(a, shd_get_abstraction_mem(if_true_case)); if (ctx->config->printf_trace.god_function) { const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } gen_call(if_builder, fn_addr_helper(a, shd_rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); - shd_set_abstraction_body(if_true_case, finish_body_with_join(if_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); + shd_set_abstraction_body(if_true_case, shd_bld_join(if_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); Node* if_false = case_(a, shd_empty(a)); shd_set_abstraction_body(if_false, join(a, (Join) { @@ -405,7 +405,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { })); shd_list_append(const Node*, literals, fn_lit); - const Node* j = jump_helper(a, bb_mem(loop_body_builder), fn_case, shd_empty(a)); + const Node* j = jump_helper(a, shd_bb_mem(loop_body_builder), fn_case, shd_empty(a)); shd_list_append(const Node*, jumps, j); } } @@ -413,12 +413,12 @@ static void generate_top_level_dispatch_fn(Context* ctx) { Node* default_case = case_(a, shd_nodes(a, 0, NULL)); shd_set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); - shd_set_abstraction_body(loop_inside_case, finish_body(loop_body_builder, br_switch(a, (Switch) { - .mem = bb_mem(loop_body_builder), + shd_set_abstraction_body(loop_inside_case, shd_bld_finish(loop_body_builder, br_switch(a, (Switch) { + .mem = shd_bb_mem(loop_body_builder), .switch_value = next_function, .case_values = shd_nodes(a, shd_list_count(literals), shd_read_list(const Node*, literals)), .case_jumps = shd_nodes(a, shd_list_count(jumps), shd_read_list(const Node*, jumps)), - .default_jump = jump_helper(a, bb_mem(loop_body_builder), default_case, shd_empty(a)) + .default_jump = jump_helper(a, shd_bb_mem(loop_body_builder), default_case, shd_empty(a)) }))); shd_destroy_list(literals); @@ -427,9 +427,9 @@ static void generate_top_level_dispatch_fn(Context* ctx) { if (ctx->config->printf_trace.god_function) gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", shd_empty(a)); - shd_set_abstraction_body(*ctx->top_dispatcher_fn, finish_body(dispatcher_body_builder, fn_ret(a, (Return) { + shd_set_abstraction_body(*ctx->top_dispatcher_fn, shd_bld_finish(dispatcher_body_builder, fn_ret(a, (Return) { .args = shd_nodes(a, 0, NULL), - .mem = bb_mem(dispatcher_body_builder), + .mem = shd_bb_mem(dispatcher_body_builder), }))); } diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index f3725450b..b2fd78670 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -17,7 +17,7 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { if (width == 1) return shd_recreate_node(&ctx->rewriter, old); LARRAY(const Node*, elements, width); - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); Nodes noperands = shd_rewrite_nodes(&ctx->rewriter, old->payload.prim_op.operands); for (size_t i = 0; i < width; i++) { LARRAY(const Node*, nops, noperands.count); @@ -29,7 +29,7 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { .element_type = shd_rewrite_node(&ctx->rewriter, dst_type), .size = shd_int32_literal(a, width) }); - return yield_values_and_wrap_in_block(bb, shd_singleton(composite_helper(a, t, shd_nodes(a, width, elements)))); + return shd_bld_to_instr_yield_values(bb, shd_singleton(composite_helper(a, t, shd_nodes(a, width, elements)))); } static const Node* process(Context* ctx, const Node* node) { diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index a5ad2dede..ab49a8e8a 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -22,7 +22,7 @@ static void add_bounds_check(IrArena* a, BodyBuilder* bb, const Node* i, const N .args = shd_empty(a), .mem = shd_get_abstraction_mem(out_of_bounds_case) })); - gen_if(bb, shd_empty(a), gen_primop_e(bb, gte_op, shd_empty(a), mk_nodes(a, i, max)), out_of_bounds_case, NULL); + shd_bld_if(bb, shd_empty(a), gen_primop_e(bb, gte_op, shd_empty(a), mk_nodes(a, i, max)), out_of_bounds_case, NULL); } static const Node* process(Context* ctx, const Node* node) { @@ -72,7 +72,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_register_processed(&ctx->rewriter, shd_get_abstraction_mem(node), shd_get_abstraction_mem(inner)); shd_set_abstraction_body(inner, shd_recreate_node(&ctx->rewriter, node->payload.fun.body)); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(wrapper)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(wrapper)); const Node* num_workgroups_var = shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); const Node* workgroup_num_vec3 = gen_load(bb, ref_decl_helper(a, num_workgroups_var)); @@ -116,7 +116,7 @@ static const Node* process(Context* ctx, const Node* node) { for (int dim = 0; dim < 3; dim++) { Node* loop_body = case_(a, shd_singleton(params[dim])); cases[scope * 3 + dim] = loop_body; - BodyBuilder* loop_bb = begin_body_with_mem(a, shd_get_abstraction_mem(loop_body)); + BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_body)); builders[scope * 3 + dim] = loop_bb; add_bounds_check(a, loop_bb, params[dim], maxes[dim]); } @@ -155,15 +155,15 @@ static const Node* process(Context* ctx, const Node* node) { Node* loop_body = cases[depth]; BodyBuilder* body_bb = builders[depth]; - shd_set_abstraction_body(loop_body, finish_body(body_bb, merge_continue(a, (MergeContinue) { + shd_set_abstraction_body(loop_body, shd_bld_finish(body_bb, merge_continue(a, (MergeContinue) { .args = shd_singleton(gen_primop_e(body_bb, add_op, shd_empty(a), mk_nodes(a, params[dim], shd_uint32_literal(a, 1)))), - .mem = bb_mem(body_bb) + .mem = shd_bb_mem(body_bb) }))); - gen_loop(depth > 0 ? builders[depth - 1] : bb, shd_empty(a), shd_singleton(shd_uint32_literal(a, 0)), loop_body); + shd_bld_loop(depth > 0 ? builders[depth - 1] : bb, shd_empty(a), shd_singleton(shd_uint32_literal(a, 0)), loop_body); } } - shd_set_abstraction_body(wrapper, finish_body(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = bb_mem(bb) }))); + shd_set_abstraction_body(wrapper, shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) }))); return wrapper; } return shd_recreate_node(&ctx2.rewriter, node); @@ -174,10 +174,10 @@ static const Node* process(Context* ctx, const Node* node) { if (ptr->tag == RefDecl_TAG) ptr = ptr->payload.ref_decl.decl; if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); - const Node* loaded = shd_first(bind_instruction(bb, shd_recreate_node(&ctx->rewriter, node))); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); + const Node* loaded = shd_first(shd_bld_add_instruction_extract(bb, shd_recreate_node(&ctx->rewriter, node))); const Node* uniformized = shd_first(gen_primop(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(loaded))); - return yield_values_and_wrap_in_block(bb, shd_singleton(uniformized)); + return shd_bld_to_instr_yield_values(bb, shd_singleton(uniformized)); } } default: break; diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 1ff24f7d7..1d58618aa 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -78,10 +78,10 @@ static const Node* process(Context* ctx, const Node* node) { const Type* req_cast = get_req_cast(ctx, node->payload.load.ptr); if (req_cast) { assert(shd_is_data_type(req_cast)); - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, node->payload.load.mem)); - const Node* r1 = shd_first(bind_instruction(bb, shd_recreate_node(r, node))); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, node->payload.load.mem)); + const Node* r1 = shd_first(shd_bld_add_instruction_extract(bb, shd_recreate_node(r, node))); const Node* r2 = shd_first(gen_primop(bb, reinterpret_op, shd_singleton(req_cast), shd_singleton(r1))); - return yield_values_and_wrap_in_block(bb, shd_singleton(r2)); + return shd_bld_to_instr_yield_values(bb, shd_singleton(r2)); } break; } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 9de776a2e..9bb286e99 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -198,10 +198,10 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca->new == shd_rewrite_node(r, payload.ptr)) break; *ctx->todo |= true; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* data = gen_load(bb, k.src_alloca->new); data = gen_reinterpret_cast(bb, access_type, data); - return yield_value_and_wrap_in_block(bb, data); + return shd_bld_to_instr_yield_value(bb, data); } } break; @@ -216,10 +216,10 @@ static const Node* process(Context* ctx, const Node* old) { if (k.src_alloca->new == shd_rewrite_node(r, payload.ptr)) break; *ctx->todo |= true; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* data = gen_reinterpret_cast(bb, access_type, shd_rewrite_node(r, payload.value)); gen_store(bb, k.src_alloca->new, data); - return yield_values_and_wrap_in_block(bb, shd_empty(a)); + return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } } break; diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index 39d174783..d561e6686 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -179,8 +179,8 @@ static const Node* process(Context* ctx, const Node* node) { const Node* nbody = inline_call(ctx, ocallee, shd_get_abstraction_mem(control_case), nargs, join_point); shd_set_abstraction_body(control_case, nbody); - BodyBuilder* bb = begin_block_with_side_effects(a, shd_rewrite_node(r, payload.mem)); - return yield_values_and_wrap_in_block(bb, gen_control(bb, nyield_types, control_case)); + BodyBuilder* bb = shd_bld_begin_pseudo_instr(a, shd_rewrite_node(r, payload.mem)); + return shd_bld_to_instr_yield_values(bb, shd_bld_control(bb, nyield_types, control_case)); } } break; diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index d9de85228..4e2fa0c00 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -125,7 +125,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (exiting_nodes_count > 0) { Nodes nparams = shd_recreate_params(rewriter, get_abstraction_params(node)); Node* loop_container = basic_block(arena, nparams, node->payload.basic_block.name); - BodyBuilder* outer_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(loop_container)); + BodyBuilder* outer_bb = shd_bld_begin(arena, shd_get_abstraction_mem(loop_container)); Nodes inner_yield_types = shd_strip_qualifiers(arena, shd_get_param_types(arena, nparams)); LARRAY(Exit, exits, exiting_nodes_count); @@ -208,7 +208,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; assert(exiting_node->node && exiting_node->node->tag != Function_TAG); Nodes exit_wrapper_params = get_abstraction_params(exits[i].wrapper); - BodyBuilder* exit_wrapper_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(exits[i].wrapper)); + BodyBuilder* exit_wrapper_bb = shd_bld_begin(arena, shd_get_abstraction_mem(exits[i].wrapper)); for (size_t j = 0; j < exits[i].params_count; j++) gen_store(exit_wrapper_bb, exits[i].params[j].alloca, exit_wrapper_params.nodes[j]); @@ -216,7 +216,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (exiting_nodes_count > 1) gen_store(exit_wrapper_bb, exit_destination_alloca, shd_int32_literal(arena, i)); - shd_set_abstraction_body(exits[i].wrapper, finish_body_with_join(exit_wrapper_bb, join_token_exit, shd_empty(arena))); + shd_set_abstraction_body(exits[i].wrapper, shd_bld_join(exit_wrapper_bb, join_token_exit, shd_empty(arena))); } shd_set_abstraction_body(inner_control_case, loop_body); @@ -236,21 +236,21 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { shd_register_processed(rewriter, node, *cached_entry); Node* loop_outer = basic_block(arena, inner_loop_params, "loop_outer"); - BodyBuilder* inner_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(loop_outer)); - Nodes inner_control_results = gen_control(inner_bb, inner_yield_types, inner_control_case); + BodyBuilder* inner_bb = shd_bld_begin(arena, shd_get_abstraction_mem(loop_outer)); + Nodes inner_control_results = shd_bld_control(inner_bb, inner_yield_types, inner_control_case); // make sure what was uniform still is for (size_t j = 0; j < inner_control_results.count; j++) { if (shd_is_qualified_type_uniform(nparams.nodes[j]->type)) inner_control_results = shd_change_node_at_index(arena, inner_control_results, j, prim_op_helper(arena, subgroup_assume_uniform_op, shd_empty(arena), shd_singleton(inner_control_results.nodes[j]))); } - shd_set_abstraction_body(loop_outer, finish_body_with_jump(inner_bb, loop_outer, inner_control_results)); + shd_set_abstraction_body(loop_outer, shd_bld_jump(inner_bb, loop_outer, inner_control_results)); Node* outer_control_case = case_(arena, shd_singleton(join_token_exit)); shd_set_abstraction_body(outer_control_case, jump(arena, (Jump) { .target = loop_outer, .args = nparams, .mem = shd_get_abstraction_mem(outer_control_case), })); - gen_control(outer_bb, shd_empty(arena), outer_control_case); + shd_bld_control(outer_bb, shd_empty(arena), outer_control_case); LARRAY(const Node*, exit_numbers, exiting_nodes_count); LARRAY(const Node*, exit_jumps, exiting_nodes_count); @@ -258,7 +258,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { CFNode* exiting_node = shd_read_list(CFNode*, exiting_nodes)[i]; Node* exit_bb = basic_block(arena, shd_empty(arena), shd_format_string_arena(arena->arena, "exit_recover_values_%s", shd_get_abstraction_name_safe(exiting_node->node))); - BodyBuilder* exit_recover_bb = begin_body_with_mem(arena, shd_get_abstraction_mem(exit_bb)); + BodyBuilder* exit_recover_bb = shd_bld_begin(arena, shd_get_abstraction_mem(exit_bb)); const Node* recreated_exit = shd_rewrite_node(rewriter, exiting_node->node); @@ -270,21 +270,21 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { } exit_numbers[i] = shd_int32_literal(arena, i); - shd_set_abstraction_body(exit_bb, finish_body_with_jump(exit_recover_bb, recreated_exit, shd_nodes(arena, exits[i].params_count, recovered_args))); - exit_jumps[i] = jump_helper(arena, bb_mem(outer_bb), exit_bb, shd_empty(arena)); + shd_set_abstraction_body(exit_bb, shd_bld_jump(exit_recover_bb, recreated_exit, shd_nodes(arena, exits[i].params_count, recovered_args))); + exit_jumps[i] = jump_helper(arena, shd_bb_mem(outer_bb), exit_bb, shd_empty(arena)); } const Node* outer_body; if (exiting_nodes_count == 1) - outer_body = finish_body(outer_bb, exit_jumps[0]); + outer_body = shd_bld_finish(outer_bb, exit_jumps[0]); else { const Node* loaded_destination = gen_load(outer_bb, exit_destination_alloca); - outer_body = finish_body(outer_bb, br_switch(arena, (Switch) { + outer_body = shd_bld_finish(outer_bb, br_switch(arena, (Switch) { .switch_value = loaded_destination, .default_jump = exit_jumps[0], .case_values = shd_nodes(arena, exiting_nodes_count, exit_numbers), .case_jumps = shd_nodes(arena, exiting_nodes_count, exit_jumps), - .mem = bb_mem(outer_bb) + .mem = shd_bb_mem(outer_bb) })); } shd_set_abstraction_body(loop_container, outer_body); @@ -465,14 +465,14 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* join_target = shd_rewrite_node(r, post_dominator); - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, node->payload.branch.mem)); - Nodes results = gen_control(bb, yield_types, control_case); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, node->payload.branch.mem)); + Nodes results = shd_bld_control(bb, yield_types, control_case); // make sure what was uniform still is for (size_t j = 0; j < old_params.count; j++) { if (uniform_param[j]) results = shd_change_node_at_index(a, results, j, prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(results.nodes[j]))); } - return finish_body_with_jump(bb, join_target, results); + return shd_bld_jump(bb, join_target, results); } default: break; } diff --git a/src/shady/passes/restructure.c b/src/shady/passes/restructure.c index 192fc3385..48ae2a0e0 100644 --- a/src/shady/passes/restructure.c +++ b/src/shady/passes/restructure.c @@ -51,7 +51,7 @@ static TmpAllocCleanupClosure create_delete_dict_closure(struct Dict* d) { static TmpAllocCleanupClosure create_cancel_body_closure(BodyBuilder* bb) { return (TmpAllocCleanupClosure) { - .fn = (TmpAllocCleanupFn) cancel_body, + .fn = (TmpAllocCleanupFn) shd_bld_cancel, .payload = bb, }; } @@ -133,7 +133,7 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, DFSStackEntry dfs_entry = { .parent = ctx->dfs_stack, .old = old_target, .containing_control = ctx->control_stack }; ctx2.dfs_stack = &dfs_entry; - BodyBuilder* bb = begin_body_with_mem(a, mem); + BodyBuilder* bb = shd_bld_begin(a, mem); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); struct Dict* tmp_processed = shd_clone_dict(ctx->rewriter.map); @@ -162,17 +162,17 @@ static const Node* handle_bb_callsite(Context* ctx, Jump jump, const Node* mem, if (dfs_entry.loop_header) { // Use the structured target as the body of a loop - gen_loop(bb, shd_empty(a), shd_rewrite_nodes(&ctx->rewriter, oargs), structured_target); + shd_bld_loop(bb, shd_empty(a), shd_rewrite_nodes(&ctx->rewriter, oargs), structured_target); // The exit ladder must exit that new loop shd_set_abstraction_body(inner_exit_ladder_bb, merge_break(a, (MergeBreak) { .args = shd_empty(a), .mem = shd_get_abstraction_mem(inner_exit_ladder_bb) })); // After that we jump to the parent exit - return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); + return shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), exit, shd_empty(a))); } else { // Simply jmp to the exit once done shd_set_abstraction_body(inner_exit_ladder_bb, jump_helper(a, shd_get_abstraction_mem(inner_exit_ladder_bb), exit, shd_empty(a))); // Jump into the new structured target - return finish_body(bb, jump_helper(a, bb_mem(bb), structured_target, shd_rewrite_nodes(&ctx->rewriter, oargs))); + return shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), structured_target, shd_rewrite_nodes(&ctx->rewriter, oargs))); } } } @@ -213,9 +213,9 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { Node* false_case = case_(a, shd_empty(a)); shd_set_abstraction_body(false_case, handle_bb_callsite(ctx, payload.false_jump->payload.jump, shd_get_abstraction_mem(false_case), make_selection_merge_case(a))); - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); - gen_if(bb, shd_empty(a), condition, true_case, false_case); - return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); + shd_bld_if(bb, shd_empty(a), condition, true_case, false_case); + return shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), exit, shd_empty(a))); } case Switch_TAG: { Switch payload = body->payload.br_switch; @@ -231,9 +231,9 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { shd_set_abstraction_body(cases[i], handle_bb_callsite(ctx, payload.case_jumps.nodes[i]->payload.jump, shd_get_abstraction_mem(cases[i]), make_selection_merge_case(a))); } - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); - gen_match(bb, shd_empty(a), switch_value, shd_rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), shd_nodes(a, body->payload.br_switch.case_jumps.count, (const Node**) cases), default_case); - return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); + shd_bld_match(bb, shd_empty(a), switch_value, shd_rewrite_nodes(&ctx->rewriter, body->payload.br_switch.case_values), shd_nodes(a, body->payload.br_switch.case_jumps.count, (const Node**) cases), default_case); + return shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), exit, shd_empty(a))); } // let(control(body), tail) // var phi = undef; level = N+1; structurize[body, if (level == N+1, _ => tail(load(phi))); structured_exit_terminator] @@ -244,7 +244,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { assert(old_control_params.count == 1); // Create N temporary variables to hold the join point arguments - BodyBuilder* bb_prelude = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb_prelude = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); Nodes yield_types = shd_rewrite_nodes(&ctx->rewriter, body->payload.control.yield_types); LARRAY(const Node*, phis, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { @@ -269,7 +269,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() Node* tail = case_(a, shd_empty(a)); - BodyBuilder* bb_tail = begin_body_with_mem(a, shd_get_abstraction_mem(tail)); + BodyBuilder* bb_tail = shd_bld_begin(a, shd_get_abstraction_mem(tail)); LARRAY(const Node*, phi_values, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { phi_values[i] = gen_load(bb_tail, phis[i]); @@ -282,11 +282,11 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { Node* true_case = case_(a, shd_empty(a)); shd_register_processed(r, shd_get_abstraction_mem(get_structured_construct_tail(body)), shd_get_abstraction_mem(true_case)); shd_set_abstraction_body(true_case, structure(ctx, get_abstraction_body(get_structured_construct_tail(body)), make_selection_merge_case(a))); - gen_if(bb_tail, shd_empty(a), guard, true_case, NULL); - shd_set_abstraction_body(tail, finish_body(bb_tail, jump_helper(a, bb_mem(bb_tail), exit, shd_empty(a)))); + shd_bld_if(bb_tail, shd_empty(a), guard, true_case, NULL); + shd_set_abstraction_body(tail, shd_bld_finish(bb_tail, jump_helper(a, shd_bb_mem(bb_tail), exit, shd_empty(a)))); - shd_register_processed(r, shd_get_abstraction_mem(old_control_case), bb_mem(bb_prelude)); - return finish_body(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); + shd_register_processed(r, shd_get_abstraction_mem(old_control_case), shd_bb_mem(bb_prelude)); + return shd_bld_finish(bb_prelude, structure(&control_ctx, get_abstraction_body(old_control_case), tail)); } case Join_TAG: { Join payload = body->payload.join; @@ -294,7 +294,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { if (!control) longjmp(ctx->bail, 1); - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); gen_store(bb, ctx->level_ptr, shd_int32_literal(a, control->depth - 1)); Nodes args = shd_rewrite_nodes(&ctx->rewriter, body->payload.join.args); @@ -302,7 +302,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { gen_store(bb, control->phis[i], args.nodes[i]); } - return finish_body(bb, jump_helper(a, bb_mem(bb), exit, shd_empty(a))); + return shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), exit, shd_empty(a))); } case Return_TAG: @@ -353,7 +353,7 @@ static const Node* process(Context* ctx, const Node* node) { is_leaf = is_builtin || !node->payload.fun.body; } else { ctx2.lower = true; - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new)); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); const Node* ptr = gen_local_alloc(bb, shd_int32_type(a)); @@ -365,8 +365,8 @@ static const Node* process(Context* ctx, const Node* node) { TmpAllocCleanupClosure cj2 = create_delete_dict_closure(tmp_processed); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj2); ctx2.rewriter.map = tmp_processed; - shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), bb_mem(bb)); - shd_set_abstraction_body(new, finish_body(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), shd_bb_mem(bb)); + shd_set_abstraction_body(new, shd_bld_finish(bb, structure(&ctx2, get_abstraction_body(node), make_unreachable_case(a)))); is_leaf = true; // We made it! Pop off the pending cleanup stuff and do it ourselves. shd_list_pop_impl(ctx->cleanup_stack); diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 9cf5b5f97..aaa4166fb 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -116,11 +116,11 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab shd_set_abstraction_body(control_case, jump_helper(a, shd_get_abstraction_mem(control_case), c, shd_empty(a))); Node* c2 = case_(a, shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(c2)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(c2)); const Type* jp_type = add_control.token->type; shd_deconstruct_qualified_type(&jp_type); assert(jp_type->tag == JoinPointType_TAG); - Nodes results = gen_control(bb, jp_type->payload.join_point_type.yield_types, control_case); + Nodes results = shd_bld_control(bb, jp_type->payload.join_point_type.yield_types, control_case); Nodes original_params = get_abstraction_params(dst); for (size_t j = 0; j < results.count; j++) { @@ -129,7 +129,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab } c = c2; - shd_set_abstraction_body(c2, finish_body(bb, jump_helper(a, bb_mem(bb), shd_find_processed(r, dst), results))); + shd_set_abstraction_body(c2, shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), shd_find_processed(r, dst), results))); } const Node* body = jump_helper(a, shd_get_abstraction_mem(nabs), c, shd_empty(a)); diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index 2a1f02be9..e558a4241 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -172,10 +172,10 @@ static const Node* process(Context* ctx, const Node* node) { fn_ctx.cfg = build_fn_cfg(node); fn_ctx.depth_per_rpo = compute_scope_depth(a, fn_ctx.cfg); Node* new_fn = shd_recreate_node_head(r, node); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_fn)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_fn)); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), shd_empty(a)); - shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); - shd_set_abstraction_body(new_fn, finish_body(bb, shd_rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); + shd_register_processed(r, shd_get_abstraction_mem(node), shd_bb_mem(bb)); + shd_set_abstraction_body(new_fn, shd_bld_finish(bb, shd_rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); destroy_cfg(fn_ctx.cfg); free(fn_ctx.depth_per_rpo); return new_fn; @@ -185,11 +185,11 @@ static const Node* process(Context* ctx, const Node* node) { shd_register_processed_list(r, get_abstraction_params(node), nparams); Node* new_bb = basic_block(a, nparams, shd_get_abstraction_name_unsafe(node)); shd_register_processed(r, node, new_bb); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(new_bb)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_bb)); CFNode* n = cfg_lookup(ctx->cfg, node); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); - shd_register_processed(r, shd_get_abstraction_mem(node), bb_mem(bb)); - shd_set_abstraction_body(new_bb, finish_body(bb, shd_rewrite_node(r, get_abstraction_body(node)))); + shd_register_processed(r, shd_get_abstraction_mem(node), shd_bb_mem(bb)); + shd_set_abstraction_body(new_bb, shd_bld_finish(bb, shd_rewrite_node(r, get_abstraction_body(node)))); return new_bb; } default: break; diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 0af6182be..444f23878 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -29,28 +29,28 @@ static const Node* process(Context* ctx, const Node* node) { Context ctx2 = *ctx; ctx2.disable_lowering = shd_lookup_annotation_with_string_payload(node, "DisablePass", "setup_stack_frames") || ctx->config->per_thread_stack_size == 0; - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); if (!ctx2.disable_lowering) { ctx2.stack_size_on_entry = gen_get_stack_size(bb); shd_set_value_name((Node*) ctx2.stack_size_on_entry, shd_format_string_arena(a->arena, "saved_stack_ptr_entering_%s", shd_get_abstraction_name(fun))); } - shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), bb_mem(bb)); + shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), shd_bb_mem(bb)); if (node->payload.fun.body) - shd_set_abstraction_body(fun, finish_body(bb, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body))); + shd_set_abstraction_body(fun, shd_bld_finish(bb, shd_rewrite_node(&ctx2.rewriter, node->payload.fun.body))); else - cancel_body(bb); + shd_bld_cancel(bb); return fun; } case Return_TAG: { Return payload = node->payload.fn_ret; - BodyBuilder* bb = begin_body_with_mem(a, shd_rewrite_node(r, payload.mem)); + BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); if (!ctx->disable_lowering) { assert(ctx->stack_size_on_entry); // Restore SP before calling exit gen_set_stack_size(bb, ctx->stack_size_on_entry); } - return finish_body(bb, fn_ret(a, (Return) { - .mem = bb_mem(bb), + return shd_bld_finish(bb, fn_ret(a, (Return) { + .mem = shd_bb_mem(bb), .args = shd_rewrite_nodes(r, payload.args), })); } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index e9ac58c36..73171a112 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -15,8 +15,8 @@ Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { assert(shd_get_arena_config(_shd_get_bb_arena(bb))->check_types); - const Node* instruction = call(_shd_get_bb_arena(bb), (Call) { .callee = callee, .args = args, .mem = bb_mem(bb) }); - return bind_instruction(bb, instruction); + const Node* instruction = call(_shd_get_bb_arena(bb), (Call) { .callee = callee, .args = args, .mem = shd_bb_mem(bb) }); + return shd_bld_add_instruction_extract(bb, instruction); } Nodes gen_primop(BodyBuilder* bb, Op op, Nodes type_args, Nodes operands) { @@ -41,8 +41,8 @@ const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { } const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { - return bind_instruction_single(bb, ext_instr(_shd_get_bb_arena(bb), (ExtInstr) { - .mem = bb_mem(bb), + return shd_bld_add_instruction(bb, ext_instr(_shd_get_bb_arena(bb), (ExtInstr) { + .mem = shd_bb_mem(bb), .set = set, .opcode = opcode, .result_t = return_t, @@ -51,7 +51,7 @@ const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const T } void gen_push_value_stack(BodyBuilder* bb, const Node* value) { - bind_instruction(bb, push_stack(_shd_get_bb_arena(bb), (PushStack) { .value = value, .mem = bb_mem(bb) })); + shd_bld_add_instruction_extract(bb, push_stack(_shd_get_bb_arena(bb), (PushStack) { .value = value, .mem = shd_bb_mem(bb) })); } void gen_push_values_stack(BodyBuilder* bb, Nodes values) { @@ -62,20 +62,20 @@ void gen_push_values_stack(BodyBuilder* bb, Nodes values) { } const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { - const Node* instruction = pop_stack(_shd_get_bb_arena(bb), (PopStack) { .type = type, .mem = bb_mem(bb) }); - return shd_first(bind_instruction(bb, instruction)); + const Node* instruction = pop_stack(_shd_get_bb_arena(bb), (PopStack) { .type = type, .mem = shd_bb_mem(bb) }); + return shd_first(shd_bld_add_instruction_extract(bb, instruction)); } const Node* gen_get_stack_base_addr(BodyBuilder* bb) { - return get_stack_base_addr(_shd_get_bb_arena(bb), (GetStackBaseAddr) { .mem = bb_mem(bb) }); + return get_stack_base_addr(_shd_get_bb_arena(bb), (GetStackBaseAddr) { .mem = shd_bb_mem(bb) }); } const Node* gen_get_stack_size(BodyBuilder* bb) { - return shd_first(bind_instruction(bb, get_stack_size(_shd_get_bb_arena(bb), (GetStackSize) { .mem = bb_mem(bb) }))); + return shd_first(shd_bld_add_instruction_extract(bb, get_stack_size(_shd_get_bb_arena(bb), (GetStackSize) { .mem = shd_bb_mem(bb) }))); } void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { - bind_instruction(bb, set_stack_size(_shd_get_bb_arena(bb), (SetStackSize) { .value = new_size, .mem = bb_mem(bb) })); + shd_bld_add_instruction_extract(bb, set_stack_size(_shd_get_bb_arena(bb), (SetStackSize) { .value = new_size, .mem = shd_bb_mem(bb) })); } const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { @@ -106,11 +106,11 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { } const Node* gen_stack_alloc(BodyBuilder* bb, const Type* type) { - return shd_first(bind_instruction(bb, stack_alloc(_shd_get_bb_arena(bb), (StackAlloc) { .type = type, .mem = bb_mem(bb) }))); + return shd_first(shd_bld_add_instruction_extract(bb, stack_alloc(_shd_get_bb_arena(bb), (StackAlloc) { .type = type, .mem = shd_bb_mem(bb) }))); } const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { - return shd_first(bind_instruction(bb, local_alloc(_shd_get_bb_arena(bb), (LocalAlloc) { .type = type, .mem = bb_mem(bb) }))); + return shd_first(shd_bld_add_instruction_extract(bb, local_alloc(_shd_get_bb_arena(bb), (LocalAlloc) { .type = type, .mem = shd_bb_mem(bb) }))); } const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Node* index) { @@ -118,11 +118,11 @@ const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Nod } const Node* gen_load(BodyBuilder* bb, const Node* ptr) { - return shd_first(bind_instruction(bb, load(_shd_get_bb_arena(bb), (Load) { .ptr = ptr, .mem = bb_mem(bb) }))); + return shd_first(shd_bld_add_instruction_extract(bb, load(_shd_get_bb_arena(bb), (Load) { .ptr = ptr, .mem = shd_bb_mem(bb) }))); } void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { - bind_instruction(bb, store(_shd_get_bb_arena(bb), (Store) { .ptr = ptr, .value = value, .mem = bb_mem(bb) })); + shd_bld_add_instruction_extract(bb, store(_shd_get_bb_arena(bb), (Store) { .ptr = ptr, .value = value, .mem = shd_bb_mem(bb) })); } const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { @@ -138,11 +138,11 @@ const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { } void gen_comment(BodyBuilder* bb, String str) { - bind_instruction(bb, comment(_shd_get_bb_arena(bb), (Comment) { .string = str, .mem = bb_mem(bb) })); + shd_bld_add_instruction_extract(bb, comment(_shd_get_bb_arena(bb), (Comment) { .string = str, .mem = shd_bb_mem(bb) })); } void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { - bind_instruction_single(bb, debug_printf(_shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = bb_mem(bb) })); + shd_bld_add_instruction(bb, debug_printf(_shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = shd_bb_mem(bb) })); } const Node* get_builtin(Module* m, Builtin b) { diff --git a/test/test_builder.c b/test/test_builder.c index c25dabef0..297e08ffd 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -14,9 +14,9 @@ #define CHECK(x, failure_handler) { if (!(x)) { shd_error_print(#x " failed\n"); failure_handler; } } static void test_body_builder_constants(IrArena* a) { - BodyBuilder* bb = begin_block_pure(a); + BodyBuilder* bb = shd_bld_begin_pure(a); const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, shd_int32_literal(a, 4), shd_int32_literal(a, 38))); - const Node* result = yield_value_and_wrap_in_block(bb, sum); + const Node* result = shd_bld_to_instr_yield_value(bb, sum); CHECK(sum == result, exit(-1)); CHECK(result->tag == IntLiteral_TAG, exit(-1)); CHECK(shd_get_int_literal_value(result->payload.int_literal, false) == 42, exit(-1)); @@ -35,24 +35,24 @@ static void test_body_builder_fun_body(IrArena* a) { // const Node* p3 = param(a, shd_as_qualified_type(bool_type(a), false), NULL); // const Node* p4 = param(a, shd_as_qualified_type(uint32_type(a), false), NULL); Node* fun = function(m, mk_nodes(a, p1, p2), "fun", shd_empty(a), shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); const Node* p1_value = gen_load(bb, p1); CHECK(p1_value->tag == Load_TAG, exit(-1)); Node* true_case = case_(a, shd_empty(a)); - BodyBuilder* tc_builder = begin_body_with_mem(a, shd_get_abstraction_mem(true_case)); + BodyBuilder* tc_builder = shd_bld_begin(a, shd_get_abstraction_mem(true_case)); gen_store(tc_builder, p1, shd_uint32_literal(a, 0)); - shd_set_abstraction_body(true_case, finish_body_with_selection_merge(tc_builder, shd_empty(a))); - gen_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, shd_uint32_literal(a, 0))), true_case, NULL); + shd_set_abstraction_body(true_case, shd_bld_selection_merge(tc_builder, shd_empty(a))); + shd_bld_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, shd_uint32_literal(a, 0))), true_case, NULL); const Node* p2_value = gen_load(bb, p2); const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, p1_value, p2_value)); const Node* return_terminator = fn_ret(a, (Return) { - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), .args = shd_singleton(sum) }); - shd_set_abstraction_body(fun, finish_body(bb, return_terminator)); + shd_set_abstraction_body(fun, shd_bld_finish(bb, return_terminator)); // set_abstraction_body(fun, finish_body_with_return(bb, singleton(sum))); shd_dump_module(m); @@ -91,22 +91,22 @@ static void test_body_builder_impure_block(IrArena* a) { .pointed_type = shd_uint32_type(a), }), false), NULL); Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); const Node* first_load = gen_load(bb, p1); - BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); + BodyBuilder* block_builder = shd_bld_begin_pseudo_instr(a, shd_bb_mem(bb)); gen_store(block_builder, p1, shd_uint32_literal(a, 0)); - bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, shd_empty(a))); + shd_bld_add_instruction_extract(bb, shd_bld_to_instr_yield_values(block_builder, shd_empty(a))); const Node* second_load = gen_load(bb, p1); const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); const Node* return_terminator = fn_ret(a, (Return) { - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), .args = shd_singleton(sum) }); - shd_set_abstraction_body(fun, finish_body(bb, return_terminator)); + shd_set_abstraction_body(fun, shd_bld_finish(bb, return_terminator)); shd_dump_module(m); @@ -130,26 +130,26 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { .pointed_type = shd_uint32_type(a), }), false), NULL); Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); - BodyBuilder* bb = begin_body_with_mem(a, shd_get_abstraction_mem(fun)); + BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); const Node* first_load = gen_load(bb, p1); - BodyBuilder* block_builder = begin_block_with_side_effects(a, bb_mem(bb)); + BodyBuilder* block_builder = shd_bld_begin_pseudo_instr(a, shd_bb_mem(bb)); Node* if_true_case = case_(a, shd_empty(a)); - BodyBuilder* if_true_builder = begin_body_with_mem(a, shd_get_abstraction_mem(if_true_case)); + BodyBuilder* if_true_builder = shd_bld_begin(a, shd_get_abstraction_mem(if_true_case)); gen_store(if_true_builder, p1, shd_uint32_literal(a, 0)); - shd_set_abstraction_body(if_true_case, finish_body_with_selection_merge(if_true_builder, shd_empty(a))); - gen_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, shd_uint32_literal(a, 0))), if_true_case, NULL); - bind_instruction(bb, yield_values_and_wrap_in_block(block_builder, shd_empty(a))); + shd_set_abstraction_body(if_true_case, shd_bld_selection_merge(if_true_builder, shd_empty(a))); + shd_bld_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, shd_uint32_literal(a, 0))), if_true_case, NULL); + shd_bld_add_instruction_extract(bb, shd_bld_to_instr_yield_values(block_builder, shd_empty(a))); const Node* second_load = gen_load(bb, p1); const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); const Node* return_terminator = fn_ret(a, (Return) { - .mem = bb_mem(bb), + .mem = shd_bb_mem(bb), .args = shd_singleton(sum) }); - shd_set_abstraction_body(fun, finish_body(bb, return_terminator)); + shd_set_abstraction_body(fun, shd_bld_finish(bb, return_terminator)); shd_dump_module(m); } diff --git a/zhady/shady.i b/zhady/shady.i index 1b688b2b4..bbb54e950 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -5,6 +5,59 @@ %module shady %{ #include "shady/ir.h" + +* bb + +* bbyield_typesarg_typesinitial_values + +* bbyield_types + +* bbyield_types* body + +* bbyield_typesinitial_args* body + +* bbyield_types* inspecteeliteralscases* default_case + +* bbyield_types* condition* true_case* false_case + +* bbvalues + +* bb* instruction + +* bbvalues + +* bb* value + +* bb + +* bb + +* bb + +* bb + +* bb + +* bb + +* bb + +* bb + +* bb + +* bb + +* bb + +* bb + +* a + +* a* mem + +* a* mem + #include "shady/runtime.h" #include "shady/driver.h" #include "shady/config.h" From e19e2e88b24ee773d2fafcf4bcee237b5d7bc30d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 14:56:24 +0200 Subject: [PATCH 650/693] move builer.h into shady/ir/ --- include/shady/ir.h | 2 +- include/shady/{body_builder.h => ir/builder.h} | 6 ++---- include/shady/ir/composite.h | 2 ++ src/frontend/slim/bind.c | 4 ++-- src/shady/body_builder.c | 16 ++-------------- src/shady/ir/composite.c | 14 ++++++++++++++ src/shady/transform/ir_gen_helpers.c | 2 +- src/shady/transform/ir_gen_helpers.h | 4 ++-- 8 files changed, 26 insertions(+), 24 deletions(-) rename include/shady/{body_builder.h => ir/builder.h} (94%) diff --git a/include/shady/ir.h b/include/shady/ir.h index ae8090fd9..c266ddea6 100644 --- a/include/shady/ir.h +++ b/include/shady/ir.h @@ -19,7 +19,7 @@ #include "shady/ir/function.h" #include "shady/ir/decl.h" -#include "shady/body_builder.h" +#include "shady/ir/builder.h" #include "shady/analysis/literal.h" #endif diff --git a/include/shady/body_builder.h b/include/shady/ir/builder.h similarity index 94% rename from include/shady/body_builder.h rename to include/shady/ir/builder.h index d194f19ef..2a0c8d764 100644 --- a/include/shady/body_builder.h +++ b/include/shady/ir/builder.h @@ -1,5 +1,5 @@ -#ifndef SHADY_BODY_BUILDER_H -#define SHADY_BODY_BUILDER_H +#ifndef SHADY_BUILDER_H +#define SHADY_BUILDER_H #include "shady/ir/base.h" @@ -19,8 +19,6 @@ const Node* shd_bld_add_instruction(BodyBuilder* bb, const Node* instr); /// ! In untyped arenas, you need to call this because we can't guess how many things are returned without typing info ! Nodes shd_bld_add_instruction_extract_count(BodyBuilder* bb, const Node* instruction, size_t outputs_count); -Nodes shd_deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count); - Nodes shd_bld_if(BodyBuilder* bb, Nodes yield_types, const Node* condition, const Node* true_case, Node* false_case); Nodes shd_bld_match(BodyBuilder* bb, Nodes yield_types, const Node* inspectee, Nodes literals, Nodes cases, Node* default_case); Nodes shd_bld_loop(BodyBuilder* bb, Nodes yield_types, Nodes initial_args, Node* body); diff --git a/include/shady/ir/composite.h b/include/shady/ir/composite.h index 1f47d89a7..c6ca31d2c 100644 --- a/include/shady/ir/composite.h +++ b/include/shady/ir/composite.h @@ -11,4 +11,6 @@ const Node* tuple_helper(IrArena*, Nodes contents); void shd_enter_composite_type(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); void shd_enter_composite_type_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack); +Nodes shd_deconstruct_composite(IrArena* a, const Node* value, size_t outputs_count); + #endif diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 8eda5d702..8408cbb94 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -142,7 +142,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { size_t names_count = instr.operands.count - 1; const Node** names = &instr.operands.nodes[1]; const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); - Nodes results = shd_deconstruct_composite(a, bb, value, names_count); + Nodes results = shd_deconstruct_composite(a, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = shd_get_string_literal(a, names[i]); shd_log_fmt(DEBUGV, "Bound immutable variable '%s'\n", name); @@ -155,7 +155,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { const Node** names = &instr.operands.nodes[1]; const Node** types = &instr.operands.nodes[1 + names_count]; const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); - Nodes results = shd_deconstruct_composite(a, bb, value, names_count); + Nodes results = shd_deconstruct_composite(a, value, names_count); for (size_t i = 0; i < names_count; i++) { String name = shd_get_string_literal(a, names[i]); const Type* type_annotation = types[i]; diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 2a8ce565c..05bd75a17 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -1,4 +1,4 @@ -#include "shady/body_builder.h" +#include "shady/ir/builder.h" #include "transform/ir_gen_helpers.h" @@ -71,25 +71,13 @@ const Node* shd_bb_mem(BodyBuilder* bb) { return bb->mem; } -Nodes shd_deconstruct_composite(IrArena* a, BodyBuilder* bb, const Node* value, size_t outputs_count) { - if (outputs_count > 1) { - LARRAY(const Node*, extracted, outputs_count); - for (size_t i = 0; i < outputs_count; i++) - extracted[i] = gen_extract_single(bb, value, shd_int32_literal(bb->arena, i)); - return shd_nodes(bb->arena, outputs_count, extracted); - } else if (outputs_count == 1) - return shd_singleton(value); - else - return shd_empty(bb->arena); -} - static Nodes bind_internal(BodyBuilder* bb, const Node* instruction, size_t outputs_count) { if (shd_get_arena_config(bb->arena)->check_types) { assert(is_mem(instruction)); } if (is_mem(instruction) && /* avoid things like ExtInstr with null mem input! */ shd_get_parent_mem(instruction)) bb->mem = instruction; - return shd_deconstruct_composite(bb->arena, bb, instruction, outputs_count); + return shd_deconstruct_composite(bb->arena, instruction, outputs_count); } const Node* shd_bld_add_instruction(BodyBuilder* bb, const Node* instr) { diff --git a/src/shady/ir/composite.c b/src/shady/ir/composite.c index 14b59e8a2..e23e9aa9b 100644 --- a/src/shady/ir/composite.c +++ b/src/shady/ir/composite.c @@ -1,8 +1,10 @@ #include "shady/ir/composite.h" #include "ir_private.h" +#include "transform/ir_gen_helpers.h" #include "log.h" +#include "portability.h" #include @@ -83,3 +85,15 @@ void shd_enter_composite_type_indices(const Type** datatype, bool* uniform, Node shd_enter_composite_type(datatype, uniform, selector, allow_entering_pack); } } + +Nodes shd_deconstruct_composite(IrArena* a, const Node* value, size_t outputs_count) { + if (outputs_count > 1) { + LARRAY(const Node*, extracted, outputs_count); + for (size_t i = 0; i < outputs_count; i++) + extracted[i] = gen_extract_single(a, value, shd_int32_literal(a, i)); + return shd_nodes(a, outputs_count, extracted); + } else if (outputs_count == 1) + return shd_singleton(value); + else + return shd_empty(a); +} diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 73171a112..1639b5064 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -113,7 +113,7 @@ const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { return shd_first(shd_bld_add_instruction_extract(bb, local_alloc(_shd_get_bb_arena(bb), (LocalAlloc) { .type = type, .mem = shd_bb_mem(bb) }))); } -const Node* gen_extract_single(BodyBuilder* bb, const Node* composite, const Node* index) { +const Node* gen_extract_single(IrArena* a, const Node* composite, const Node* index) { return extract_helper(composite, index); } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 9a1b1869b..31235b85c 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -25,12 +25,12 @@ const Node* gen_merge_halves(BodyBuilder*, const Node* lo, const Node* hi); const Node* gen_stack_alloc(BodyBuilder*, const Type* ptr); const Node* gen_local_alloc(BodyBuilder*, const Type* ptr); -const Node* gen_extract_single(BodyBuilder*, const Node* composite, const Node* index); +const Node* gen_extract(BodyBuilder*, const Node* base, Nodes selectors); +const Node* gen_extract_single(IrArena*, const Node* composite, const Node* index); const Node* gen_load(BodyBuilder*, const Node* ptr); void gen_store(BodyBuilder*, const Node* ptr, const Node* value); const Node* gen_lea(BodyBuilder*, const Node* base, const Node* offset, Nodes selectors); -const Node* gen_extract(BodyBuilder*, const Node* base, Nodes selectors); void gen_comment(BodyBuilder*, String str); void gen_debug_printf(BodyBuilder*, String pattern, Nodes args); const Node* get_builtin(Module* m, Builtin b); From c5a0cfb6bb7df3cfe827dd815dafd49559ede12b Mon Sep 17 00:00:00 2001 From: Jacki Date: Sun, 13 Oct 2024 08:37:37 +0200 Subject: [PATCH 651/693] Fix hash algorithm Signed-off-by: Jacki --- src/common/dict.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dict.c b/src/common/dict.c index 3dc9ec144..afa0294f9 100644 --- a/src/common/dict.c +++ b/src/common/dict.c @@ -388,7 +388,7 @@ KeyHash shd_hash(const void* data, size_t size) { unsigned int hash = 0; unsigned int i = 0; - for (i = 0; i < size; data++, i++) + for (i = 0; i < size; data_chars++, i++) { hash *= fnv_prime; hash ^= (*data_chars); From 6be16aee8a7ea544f4d86e9921dfa61c5c20a2b5 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:05:52 +0200 Subject: [PATCH 652/693] more renaming/moving --- include/shady/ir/composite.h | 7 ++-- src/frontend/llvm/l2s_instr.c | 2 +- src/frontend/llvm/l2s_meta.c | 4 +- src/frontend/slim/parser.c | 10 ++--- src/shady/body_builder.c | 4 +- src/shady/fold.c | 2 +- src/shady/ir/composite.c | 19 ++++++--- src/shady/passes/lower_int64.c | 4 +- src/shady/passes/lower_physical_ptrs.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/lower_workgroups.c | 2 +- src/shady/transform/ir_gen_helpers.c | 12 ------ src/shady/transform/ir_gen_helpers.h | 3 -- zhady/shady.i | 53 -------------------------- 15 files changed, 34 insertions(+), 94 deletions(-) diff --git a/include/shady/ir/composite.h b/include/shady/ir/composite.h index c6ca31d2c..e34eab39c 100644 --- a/include/shady/ir/composite.h +++ b/include/shady/ir/composite.h @@ -3,10 +3,11 @@ #include "shady/ir/grammar.h" -const Node* maybe_tuple_helper(IrArena* a, Nodes values); -const Node* extract_helper(const Node* composite, const Node* index); +const Node* shd_maybe_tuple_helper(IrArena* a, Nodes values); +const Node* shd_tuple_helper(IrArena*, Nodes contents); -const Node* tuple_helper(IrArena*, Nodes contents); +const Node* shd_extract_helper(IrArena* a, const Node* base, Nodes selectors); +const Node* shd_extract_single_helper(IrArena* a, const Node* composite, const Node* index); void shd_enter_composite_type(const Type** datatype, bool* uniform, const Node* selector, bool allow_entering_pack); void shd_enter_composite_type_indices(const Type** datatype, bool* uniform, Nodes indices, bool allow_entering_pack); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 29c08fa06..0e0bbd728 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -572,7 +572,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B shd_error("DebugPrintf called without arguments"); size_t whocares; gen_debug_printf(b, LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), shd_nodes(a, ops.count - 1, &ops.nodes[1])); - return tuple_helper(a, shd_empty(a)); + return shd_tuple_helper(a, shd_empty(a)); } shd_error_print("Unrecognised shady instruction '%s'\n", instructionname); diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index fbb4a5b97..113d14905 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -33,7 +33,7 @@ static const Node* convert_named_tuple_metadata(Parser* p, LLVMValueRef v, Strin Nodes args = convert_mdnode_operands(p, v); args = shd_nodes_prepend(a, args, string_lit_helper(a, node_name)); - g->payload.global_variable.init = tuple_helper(a, args); + g->payload.global_variable.init = shd_tuple_helper(a, args); return r; } @@ -133,7 +133,7 @@ const Node* convert_metadata(Parser* p, LLVMMetadataRef meta) { } switch (kind) { - case LLVMMDTupleMetadataKind: return tuple_helper(a, convert_mdnode_operands(p, v)); + case LLVMMDTupleMetadataKind: return shd_tuple_helper(a, convert_mdnode_operands(p, v)); case LLVMDICompileUnitMetadataKind: return string_lit_helper(a, "CompileUnit"); } diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 030fb78fe..1ec1230ce 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -347,7 +347,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { case lpar_tok: { shd_next_token(tokenizer); if (accept_token(ctx, rpar_tok)) { - return tuple_helper(arena, shd_empty(arena)); + return shd_tuple_helper(arena, shd_empty(arena)); } const Node* atom = expect_operand(ctx, bb); if (shd_curr_token(tokenizer).tag == rpar_tok) { @@ -364,7 +364,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { Nodes tcontents = shd_nodes(arena, shd_list_count(elements), shd_read_list(const Node*, elements)); shd_destroy_list(elements); - atom = tuple_helper(arena, tcontents); + atom = shd_tuple_helper(arena, tcontents); } return atom; } @@ -759,7 +759,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { false_case = case_(arena, shd_nodes(arena, 0, NULL)); shd_set_abstraction_body(false_case, expect_body(ctx, shd_get_abstraction_mem(false_case), merge)); } - return maybe_tuple_helper(arena, shd_bld_if(bb, yield_types, condition, true_case, false_case)); + return shd_maybe_tuple_helper(arena, shd_bld_if(bb, yield_types, condition, true_case, false_case)); } case loop_tok: { shd_next_token(tokenizer); @@ -771,7 +771,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { const Node* (*default_loop_end_behaviour)(const Node*) = config->front_end ? make_loop_continue : NULL; Node* loop_case = case_(arena, parameters); shd_set_abstraction_body(loop_case, expect_body(ctx, shd_get_abstraction_mem(loop_case), default_loop_end_behaviour)); - return maybe_tuple_helper(arena, shd_bld_loop(bb, yield_types, initial_arguments, loop_case)); + return shd_maybe_tuple_helper(arena, shd_bld_loop(bb, yield_types, initial_arguments, loop_case)); } case control_tok: { shd_next_token(tokenizer); @@ -785,7 +785,7 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { expect(accept_token(ctx, rpar_tok), "')'"); Node* control_case = case_(arena, shd_singleton(jp)); shd_set_abstraction_body(control_case, expect_body(ctx, shd_get_abstraction_mem(control_case), NULL)); - return maybe_tuple_helper(arena, shd_bld_control(bb, yield_types, control_case)); + return shd_maybe_tuple_helper(arena, shd_bld_control(bb, yield_types, control_case)); } default: break; } diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 05bd75a17..b619f17c1 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -203,7 +203,7 @@ const Node* shd_bld_to_instr_yield_value(BodyBuilder* bb, const Node* value) { } const Node* shd_bld_to_instr_yield_values(BodyBuilder* bb, Nodes values) { - return shd_bld_to_instr_yield_value(bb, maybe_tuple_helper(bb->arena, values)); + return shd_bld_to_instr_yield_value(bb, shd_maybe_tuple_helper(bb->arena, values)); } const Node* _shd_bld_finish_pseudo_instr(BodyBuilder* bb, const Node* terminator) { @@ -228,7 +228,7 @@ const Node* shd_bld_to_instr_pure_with_values(BodyBuilder* bb, Nodes values) { IrArena* arena = bb->arena; assert(!bb->mem && !bb->block_entry_mem && shd_list_count(bb->stack) == 0); shd_bld_cancel(bb); - return maybe_tuple_helper(arena, values); + return shd_maybe_tuple_helper(arena, values); } static Nodes gen_variables(BodyBuilder* bb, Nodes yield_types) { diff --git a/src/shady/fold.c b/src/shady/fold.c index 7d55dd437..f5a562940 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -347,7 +347,7 @@ static const Node* fold_memory_poison(IrArena* arena, const Node* node) { } case Store_TAG: { if (node->payload.store.ptr->tag == Undef_TAG) - return mem_and_value(arena, (MemAndValue) { .value = tuple_helper(arena, shd_empty(arena)), .mem = node->payload.store.mem }); + return mem_and_value(arena, (MemAndValue) { .value = shd_tuple_helper(arena, shd_empty(arena)), .mem = node->payload.store.mem }); break; } case PtrArrayElementOffset_TAG: { diff --git a/src/shady/ir/composite.c b/src/shady/ir/composite.c index e23e9aa9b..33828ab49 100644 --- a/src/shady/ir/composite.c +++ b/src/shady/ir/composite.c @@ -8,18 +8,25 @@ #include -const Node* extract_helper(const Node* composite, const Node* index) { - IrArena* a = composite->arena; +const Node* shd_extract_helper(IrArena* a, const Node* base, Nodes selectors) { + LARRAY(const Node*, ops, 1 + selectors.count); + ops[0] = base; + for (size_t i = 0; i < selectors.count; i++) + ops[1 + i] = selectors.nodes[i]; + return prim_op_helper(a, extract_op, shd_empty(a), shd_nodes(a, 1 + selectors.count, ops)); +} + +const Node* shd_extract_single_helper(IrArena* a, const Node* composite, const Node* index) { return prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, composite, index)); } -const Node* maybe_tuple_helper(IrArena* a, Nodes values) { +const Node* shd_maybe_tuple_helper(IrArena* a, Nodes values) { if (values.count == 1) return shd_first(values); - return tuple_helper(a, values); + return shd_tuple_helper(a, values); } -const Node* tuple_helper(IrArena* a, Nodes contents) { +const Node* shd_tuple_helper(IrArena* a, Nodes contents) { const Type* t = NULL; if (a->config.check_types) { // infer the type of the tuple @@ -90,7 +97,7 @@ Nodes shd_deconstruct_composite(IrArena* a, const Node* value, size_t outputs_co if (outputs_count > 1) { LARRAY(const Node*, extracted, outputs_count); for (size_t i = 0; i < outputs_count; i++) - extracted[i] = gen_extract_single(a, value, shd_int32_literal(a, i)); + extracted[i] = shd_extract_single_helper(a, value, shd_int32_literal(a, i)); return shd_nodes(a, outputs_count, extracted); } else if (outputs_count == 1) return shd_singleton(value); diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 124a8cda3..3be9be8ab 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -46,7 +46,7 @@ static const Node* process(Context* ctx, const Node* node) { uint64_t raw = node->payload.int_literal.value; const Node* lower = shd_uint32_literal(a, (uint32_t) raw); const Node* upper = shd_uint32_literal(a, (uint32_t) (raw >> 32)); - return tuple_helper(a, mk_nodes(a, lower, upper)); + return shd_tuple_helper(a, mk_nodes(a, lower, upper)); } break; case PrimOp_TAG: { @@ -65,7 +65,7 @@ static const Node* process(Context* ctx, const Node* node) { // compute the high side, without forgetting the carry bit const Node* hi = shd_first(shd_bld_add_instruction_extract(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = shd_nodes(a, 2, his) }))); hi = shd_first(shd_bld_add_instruction_extract(bb, prim_op(a, (PrimOp) { .op = add_op, .operands = mk_nodes(a, hi, low_and_carry.nodes[1]) }))); - return shd_bld_to_instr_yield_values(bb, shd_singleton(tuple_helper(a, mk_nodes(a, lo, hi)))); + return shd_bld_to_instr_yield_values(bb, shd_singleton(shd_tuple_helper(a, mk_nodes(a, lo, hi)))); } break; default: break; } diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 64b239824..913e5bb67 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -234,7 +234,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Type* component_type = shd_get_fill_type_element_type(element_type); const Node* offset = address; for (size_t i = 0; i < components_count; i++) { - gen_serialisation(ctx, bb, component_type, arr, offset, gen_extract(bb, value, shd_singleton(shd_int32_literal(a, i)))); + gen_serialisation(ctx, bb, component_type, arr, offset, shd_extract_helper(a, value, shd_singleton(shd_int32_literal(a, i)))); offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, shd_singleton(component_type), shd_empty(a)))); } return; diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 1aa68ce94..e3dbd8fe1 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -54,7 +54,7 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co Nodes element_types = shd_get_composite_type_element_types(t); LARRAY(const Node*, elements, element_types.count); for (size_t i = 0; i < element_types.count; i++) { - const Node* e = gen_extract(bb, param, shd_singleton(shd_uint32_literal(a, i))); + const Node* e = shd_extract_helper(a, param, shd_singleton(shd_uint32_literal(a, i))); elements[i] = build_subgroup_first(ctx, bb, scope, e); } return composite_helper(a, original_t, shd_nodes(a, element_types.count, elements)); diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index b2fd78670..cfe00add1 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -22,7 +22,7 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { for (size_t i = 0; i < width; i++) { LARRAY(const Node*, nops, noperands.count); for (size_t j = 0; j < noperands.count; j++) - nops[j] = gen_extract(bb, noperands.nodes[j], shd_singleton(shd_int32_literal(a, i))); + nops[j] = shd_extract_helper(a, noperands.nodes[j], shd_singleton(shd_int32_literal(a, i))); elements[i] = gen_primop_e(bb, old->payload.prim_op.op, shd_empty(a), shd_nodes(a, noperands.count, nops)); } const Type* t = arr_type(a, (ArrType) { diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index ab49a8e8a..cff70b130 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -82,7 +82,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* num_workgroups[3]; for (int dim = 0; dim < 3; dim++) { workgroup_id[dim] = param(a, shd_as_qualified_type(shd_uint32_type(a), false), names[dim]); - num_workgroups[dim] = gen_extract(bb, workgroup_num_vec3, shd_singleton(shd_uint32_literal(a, dim))); + num_workgroups[dim] = shd_extract_helper(a, workgroup_num_vec3, shd_singleton(shd_uint32_literal(a, dim))); } // Prepare variables for iterating inside workgroups diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 1639b5064..7387fe4a0 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -113,10 +113,6 @@ const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { return shd_first(shd_bld_add_instruction_extract(bb, local_alloc(_shd_get_bb_arena(bb), (LocalAlloc) { .type = type, .mem = shd_bb_mem(bb) }))); } -const Node* gen_extract_single(IrArena* a, const Node* composite, const Node* index) { - return extract_helper(composite, index); -} - const Node* gen_load(BodyBuilder* bb, const Node* ptr) { return shd_first(shd_bld_add_instruction_extract(bb, load(_shd_get_bb_arena(bb), (Load) { .ptr = ptr, .mem = shd_bb_mem(bb) }))); } @@ -129,14 +125,6 @@ const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes return lea_helper(_shd_get_bb_arena(bb), base, offset, selectors); } -const Node* gen_extract(BodyBuilder* bb, const Node* base, Nodes selectors) { - LARRAY(const Node*, ops, 1 + selectors.count); - ops[0] = base; - for (size_t i = 0; i < selectors.count; i++) - ops[1 + i] = selectors.nodes[i]; - return gen_primop_ce(bb, extract_op, 1 + selectors.count, ops); -} - void gen_comment(BodyBuilder* bb, String str) { shd_bld_add_instruction_extract(bb, comment(_shd_get_bb_arena(bb), (Comment) { .string = str, .mem = shd_bb_mem(bb) })); } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 31235b85c..179070cda 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -25,9 +25,6 @@ const Node* gen_merge_halves(BodyBuilder*, const Node* lo, const Node* hi); const Node* gen_stack_alloc(BodyBuilder*, const Type* ptr); const Node* gen_local_alloc(BodyBuilder*, const Type* ptr); -const Node* gen_extract(BodyBuilder*, const Node* base, Nodes selectors); -const Node* gen_extract_single(IrArena*, const Node* composite, const Node* index); - const Node* gen_load(BodyBuilder*, const Node* ptr); void gen_store(BodyBuilder*, const Node* ptr, const Node* value); const Node* gen_lea(BodyBuilder*, const Node* base, const Node* offset, Nodes selectors); diff --git a/zhady/shady.i b/zhady/shady.i index bbb54e950..1b688b2b4 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -5,59 +5,6 @@ %module shady %{ #include "shady/ir.h" - -* bb - -* bbyield_typesarg_typesinitial_values - -* bbyield_types - -* bbyield_types* body - -* bbyield_typesinitial_args* body - -* bbyield_types* inspecteeliteralscases* default_case - -* bbyield_types* condition* true_case* false_case - -* bbvalues - -* bb* instruction - -* bbvalues - -* bb* value - -* bb - -* bb - -* bb - -* bb - -* bb - -* bb - -* bb - -* bb - -* bb - -* bb - -* bb - -* bb - -* a - -* a* mem - -* a* mem - #include "shady/runtime.h" #include "shady/driver.h" #include "shady/config.h" From b833264564cc0e97ec791c659b8aa91580c46117 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:10:03 +0200 Subject: [PATCH 653/693] move builin-related builder fns to builder.h --- include/shady/ir/builtin.h | 4 +++ src/backend/spirv/emit_spv_value.c | 2 +- src/shady/ir/builtin.c | 38 ++++++++++++++++++++++++++ src/shady/passes/lower_subgroup_vars.c | 2 +- src/shady/passes/lower_tailcalls.c | 10 +++---- src/shady/passes/lower_workgroups.c | 14 +++++----- src/shady/transform/ir_gen_helpers.c | 37 ------------------------- src/shady/transform/ir_gen_helpers.h | 3 -- 8 files changed, 56 insertions(+), 54 deletions(-) diff --git a/include/shady/ir/builtin.h b/include/shady/ir/builtin.h index 40dbe0844..67bcd80d4 100644 --- a/include/shady/ir/builtin.h +++ b/include/shady/ir/builtin.h @@ -58,4 +58,8 @@ int32_t shd_get_builtin_spv_id(Builtin builtin); bool shd_is_builtin_load_op(const Node* n, Builtin* out); +const Node* shd_get_builtin(Module* m, Builtin b); +const Node* shd_get_or_create_builtin(Module* m, Builtin b, String n); +const Node* shd_bld_builtin_load(Module* m, BodyBuilder* bb, Builtin b); + #endif diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 78ca71cd6..c59f0b047 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -284,7 +284,7 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b SpvId scope_subgroup = spv_emit_value(emitter, fn_builder, shd_int32_literal(emitter->arena, SpvScopeSubgroup)); if (emitter->configuration->hacks.spv_shuffle_instead_of_broadcast_first) { spvb_capability(emitter->file_builder, SpvCapabilityGroupNonUniformShuffle); - const Node* b = ref_decl_helper(emitter->arena, get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); + const Node* b = ref_decl_helper(emitter->arena, shd_get_or_create_builtin(emitter->module, BuiltinSubgroupLocalInvocationId, NULL)); SpvId local_id = spvb_op(bb_builder, SpvOpLoad, spv_emit_type(emitter, shd_uint32_type(emitter->arena)), 1, (SpvId []) { spv_emit_value(emitter, fn_builder, b) }); return spvb_group_shuffle(bb_builder, spv_emit_type(emitter, instr.result_t), scope_subgroup, spv_emit_value(emitter, fn_builder, shd_first(instr.operands)), local_id); } diff --git a/src/shady/ir/builtin.c b/src/shady/ir/builtin.c index 358065f02..27251c93f 100644 --- a/src/shady/ir/builtin.c +++ b/src/shady/ir/builtin.c @@ -1,5 +1,9 @@ #include "shady/ir/builtin.h" +#include "shady/ir/builder.h" #include "shady/ir/annotation.h" +#include "shady/ir/module.h" + +#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" @@ -108,3 +112,37 @@ bool shd_is_builtin_load_op(const Node* n, Builtin* out) { } return false; } + +const Node* shd_get_builtin(Module* m, Builtin b) { + Nodes decls = shd_module_get_declarations(m); + for (size_t i = 0; i < decls.count; i++) { + const Node* decl = decls.nodes[i]; + if (decl->tag != GlobalVariable_TAG) + continue; + const Node* a = shd_lookup_annotation(decl, "Builtin"); + if (!a) + continue; + String builtin_name = shd_get_annotation_string_payload(a); + assert(builtin_name); + if (strcmp(builtin_name, shd_get_builtin_name(b)) == 0) + return decl; + } + + return NULL; +} + +const Node* shd_get_or_create_builtin(Module* m, Builtin b, String n) { + const Node* decl = shd_get_builtin(m, b); + if (decl) + return decl; + + AddressSpace as = shd_get_builtin_address_space(b); + IrArena* a = shd_module_get_arena(m); + decl = global_var(m, shd_singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a,shd_get_builtin_name(b)))), + shd_get_builtin_type(a, b), n ? n : shd_fmt_string_irarena(a, "builtin_%s", shd_get_builtin_name(b)), as); + return decl; +} + +const Node* shd_bld_builtin_load(Module* m, BodyBuilder* bb, Builtin b) { + return gen_load(bb, ref_decl_helper(shd_module_get_arena(m), shd_get_or_create_builtin(m, b, NULL))); +} diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 3a7f6d41d..737b25366 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -47,7 +47,7 @@ static const Node* process(Context* ctx, const Node* node) { break; const Node* ndecl = shd_rewrite_node(&ctx->rewriter, odecl); assert(ctx->bb); - const Node* index = gen_builtin_load(ctx->rewriter.dst_module, ctx->bb, BuiltinSubgroupId); + const Node* index = shd_bld_builtin_load(ctx->rewriter.dst_module, ctx->bb, BuiltinSubgroupId); const Node* slice = gen_lea(ctx->bb, ref_decl_helper(a, ndecl), shd_int32_literal(a, 0), mk_nodes(a, index)); return slice; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 2304d4ccd..ecbab2628 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -302,11 +302,11 @@ static void generate_top_level_dispatch_fn(Context* ctx) { const Node* next_function = gen_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); const Node* get_active_branch_fn = access_decl(&ctx->rewriter, "builtin_get_active_branch"); const Node* next_mask = shd_first(gen_call(loop_body_builder, get_active_branch_fn, shd_empty(a))); - const Node* local_id = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); + const Node* local_id = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); const Node* should_run = gen_primop_e(loop_body_builder, mask_is_thread_active_op, shd_empty(a), mk_nodes(a, next_mask, local_id)); if (ctx->config->printf_trace.god_function) { - const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); + const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); if (count_iterations) gen_debug_printf(loop_body_builder, "trace: top loop, thread:%d:%d iteration=%d next_fn=%d next_mask=%lx\n", mk_nodes(a, sid, local_id, iterations_count_param, next_function, next_mask)); else @@ -346,7 +346,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { Node* zero_if_true_lam = case_(a, shd_empty(a)); BodyBuilder* zero_if_case_builder = shd_bld_begin(a, shd_get_abstraction_mem(zero_if_true_lam)); if (ctx->config->printf_trace.god_function) { - const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); + const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } shd_set_abstraction_body(zero_if_true_lam, shd_bld_join(zero_if_case_builder, l.break_jp, shd_empty(a))); @@ -354,7 +354,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { Node* zero_if_false = case_(a, shd_empty(a)); BodyBuilder* zero_false_builder = shd_bld_begin(a, shd_get_abstraction_mem(zero_if_false)); if (ctx->config->printf_trace.god_function) { - const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, zero_false_builder, BuiltinSubgroupId); + const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, zero_false_builder, BuiltinSubgroupId); gen_debug_printf(zero_false_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } shd_set_abstraction_body(zero_if_false, shd_bld_join(zero_false_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); @@ -383,7 +383,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { Node* if_true_case = case_(a, shd_empty(a)); BodyBuilder* if_builder = shd_bld_begin(a, shd_get_abstraction_mem(if_true_case)); if (ctx->config->printf_trace.god_function) { - const Node* sid = gen_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); + const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } gen_call(if_builder, fn_addr_helper(a, shd_rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index cff70b130..46b43f60c 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -47,7 +47,7 @@ static const Node* process(Context* ctx, const Node* node) { default: break; } - return get_or_create_builtin(ctx->rewriter.dst_module, b, get_declaration_name(node)); + return shd_get_or_create_builtin(ctx->rewriter.dst_module, b, get_declaration_name(node)); } break; } @@ -73,7 +73,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_set_abstraction_body(inner, shd_recreate_node(&ctx->rewriter, node->payload.fun.body)); BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(wrapper)); - const Node* num_workgroups_var = shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); + const Node* num_workgroups_var = shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); const Node* workgroup_num_vec3 = gen_load(bb, ref_decl_helper(a, num_workgroups_var)); // prepare variables for iterating over workgroups @@ -125,19 +125,19 @@ static const Node* process(Context* ctx, const Node* node) { // BodyBuilder* bb2 = begin_block_with_side_effects(a, bb_mem(builders[5])); BodyBuilder* bb2 = builders[5]; // write the workgroup ID - gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); + gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); // write the local ID const Node* local_id[3]; // local_id[0] = SUBGROUP_SIZE * subgroup_id[0] + subgroup_local_id - local_id[0] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), gen_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); + local_id[0] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), shd_bld_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); local_id[1] = subgroup_id[1]; local_id[2] = subgroup_id[2]; - gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); + gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); // write the global ID const Node* global_id[3]; for (int dim = 0; dim < 3; dim++) global_id[dim] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); - gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); + gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID gen_call(bb2, fn_addr_helper(a, inner), wparams); @@ -173,7 +173,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* ptr = payload.ptr; if (ptr->tag == RefDecl_TAG) ptr = ptr->payload.ref_decl.decl; - if (ptr == get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { + if (ptr == shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* loaded = shd_first(shd_bld_add_instruction_extract(bb, shd_recreate_node(&ctx->rewriter, node))); const Node* uniformized = shd_first(gen_primop(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(loaded))); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 7387fe4a0..25880d79a 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -133,43 +133,6 @@ void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { shd_bld_add_instruction(bb, debug_printf(_shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = shd_bb_mem(bb) })); } -const Node* get_builtin(Module* m, Builtin b) { - Nodes decls = shd_module_get_declarations(m); - for (size_t i = 0; i < decls.count; i++) { - const Node* decl = decls.nodes[i]; - if (decl->tag != GlobalVariable_TAG) - continue; - const Node* a = shd_lookup_annotation(decl, "Builtin"); - if (!a) - continue; - String builtin_name = shd_get_annotation_string_payload(a); - assert(builtin_name); - if (strcmp(builtin_name, shd_get_builtin_name(b)) == 0) - return decl; - } - - return NULL; -} - -const Node* get_or_create_builtin(Module* m, Builtin b, String n) { - const Node* decl = get_builtin(m, b); - if (decl) - return decl; - - AddressSpace as = shd_get_builtin_address_space(b); - IrArena* a = shd_module_get_arena(m); - decl = global_var(m, shd_singleton(annotation_value_helper(a, "Builtin", string_lit_helper(a, - shd_get_builtin_name(b)))), - shd_get_builtin_type(a, b), n ? n : shd_format_string_arena(a->arena, "builtin_%s", - shd_get_builtin_name( - b)), as); - return decl; -} - -const Node* gen_builtin_load(Module* m, BodyBuilder* bb, Builtin b) { - return gen_load(bb, ref_decl_helper(_shd_get_bb_arena(bb), get_or_create_builtin(m, b, NULL))); -} - const Node* find_or_process_decl(Rewriter* rewriter, const char* name) { Nodes old_decls = shd_module_get_declarations(rewriter->src_module); for (size_t i = 0; i < old_decls.count; i++) { diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 179070cda..3862bdb01 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -30,9 +30,6 @@ void gen_store(BodyBuilder*, const Node* ptr, const Node* value); const Node* gen_lea(BodyBuilder*, const Node* base, const Node* offset, Nodes selectors); void gen_comment(BodyBuilder*, String str); void gen_debug_printf(BodyBuilder*, String pattern, Nodes args); -const Node* get_builtin(Module* m, Builtin b); -const Node* get_or_create_builtin(Module* m, Builtin b, String n); -const Node* gen_builtin_load(Module*, BodyBuilder*, Builtin); typedef struct Rewriter_ Rewriter; From 79a5064629977cebd260e863247597f903cf2061 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:14:12 +0200 Subject: [PATCH 654/693] remove gen_lea --- src/backend/spirv/spirv_lift_globals_ssbo.c | 2 +- src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_logical_pointers.c | 3 ++- src/shady/passes/lower_memcpy.c | 6 +++--- src/shady/passes/lower_physical_ptrs.c | 8 ++++---- src/shady/passes/lower_stack.c | 5 +++-- src/shady/passes/lower_subgroup_vars.c | 3 ++- src/shady/transform/ir_gen_helpers.c | 4 ---- src/shady/transform/ir_gen_helpers.h | 1 - 9 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 886409d21..dbd06879b 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -41,7 +41,7 @@ static const Node* process(Context* ctx, const Node* node) { if (odecl->tag != GlobalVariable_TAG || odecl->payload.global_variable.address_space != AsGlobal) break; assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); - const Node* ptr_addr = gen_lea(ctx->bb, ref_decl_helper(a, ctx->lifted_globals_decl), shd_int32_literal(a, 0), shd_singleton(shd_rewrite_node(&ctx->rewriter, odecl))); + const Node* ptr_addr = lea_helper(a, ref_decl_helper(a, ctx->lifted_globals_decl), shd_int32_literal(a, 0), shd_singleton(shd_rewrite_node(&ctx->rewriter, odecl))); const Node* ptr = gen_load(ctx->bb, ptr_addr); return ptr; } diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 2323e43e2..6af6c7ec9 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -64,7 +64,7 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const Nodes params = old_entry_point->payload.fun.params; for (int i = 0; i < params.count; ++i) { - const Node* addr = gen_lea(bb, arg_struct, shd_int32_literal(a, 0), shd_singleton(shd_int32_literal(a, i))); + const Node* addr = lea_helper(a, arg_struct, shd_int32_literal(a, 0), shd_singleton(shd_int32_literal(a, i))); const Node* val = gen_load(bb, addr); shd_register_processed(&ctx->rewriter, params.nodes[i], val); } diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index 78d5ef32e..a368a5371 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/memory_layout.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -30,7 +31,7 @@ static const Node* guess_pointer_casts(Context* ctx, BodyBuilder* bb, const Node case RecordType_TAG: case ArrType_TAG: case PackType_TAG: { - ptr = gen_lea(bb, ptr, shd_int32_literal(a, 0), shd_singleton(shd_int32_literal(a, 0))); + ptr = lea_helper(a, ptr, shd_int32_literal(a, 0), shd_singleton(shd_int32_literal(a, 0))); continue; } default: break; diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 824e0f4b2..cfb1900d5 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -55,8 +55,8 @@ static const Node* process(Context* ctx, const Node* old) { shd_set_value_name(index, "memcpy_i"); Node* loop_case = l.loop_body; BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_case)); - const Node* loaded_word = gen_load(loop_bb, gen_lea(loop_bb, src_addr, index, shd_empty(a))); - gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), loaded_word); + const Node* loaded_word = gen_load(loop_bb, lea_helper(a, src_addr, index, shd_empty(a))); + gen_store(loop_bb, lea_helper(a, dst_addr, index, shd_empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); @@ -102,7 +102,7 @@ static const Node* process(Context* ctx, const Node* old) { shd_set_value_name(index, "memset_i"); Node* loop_case = l.loop_body; BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_case)); - gen_store(loop_bb, gen_lea(loop_bb, dst_addr, index, shd_empty(a)), src_value); + gen_store(loop_bb, lea_helper(a, dst_addr, index, shd_empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 913e5bb67..01bc26ea4 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -58,7 +58,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* zero = size_t_literal(a, 0); switch (element_type->tag) { case Bool_TAG: { - const Node* logical_ptr = gen_lea(bb, arr, zero, shd_singleton(address)); + const Node* logical_ptr = lea_helper(a, arr, zero, shd_singleton(address)); const Node* value = gen_load(bb, logical_ptr); return gen_primop_ce(bb, neq_op, 2, (const Node*[]) {value, int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size })}); } @@ -80,7 +80,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { - const Node* word = gen_load(bb, gen_lea(bb, arr, zero, shd_singleton(offset))); + const Node* word = gen_load(bb, lea_helper(a, arr, zero, shd_singleton(offset))); word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded word = shd_first(gen_primop(bb, lshift_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it acc = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, acc, word)); @@ -146,7 +146,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* zero = size_t_literal(a, 0); switch (element_type->tag) { case Bool_TAG: { - const Node* logical_ptr = gen_lea(bb, arr, zero, shd_singleton(address)); + const Node* logical_ptr = lea_helper(a, arr, zero, shd_singleton(address)); const Node* zero_b = int_literal(a, (IntLiteral) { .value = 1, .width = a->config.memory.word_size }); const Node* one_b = int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size }); const Node* int_value = gen_primop_ce(bb, select_op, 3, (const Node*[]) { value, one_b, zero_b }); @@ -186,7 +186,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* word = value; word = shd_first(gen_primop(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it word = gen_conversion(bb, int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }), word); // widen/truncate the word we want to store - gen_store(bb, gen_lea(bb, arr, zero, shd_singleton(offset)), word); + gen_store(bb, lea_helper(a, arr, zero, shd_singleton(offset)), word); offset = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); shift = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 2f1de5408..f22ad4f4a 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/memory_layout.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -56,7 +57,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { if (!push) // for pop, we decrease the stack size first stack_size = gen_primop_ce(bb, sub_op, 2, (const Node* []) { stack_size, element_size}); - const Node* addr = gen_lea(bb, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); + const Node* addr = lea_helper(a, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); assert(shd_get_unqualified_type(addr->type)->tag == PtrType_TAG); AddressSpace addr_space = shd_get_unqualified_type(addr->type)->payload.ptr_type.address_space; @@ -129,7 +130,7 @@ static const Node* process_node(Context* ctx, const Node* old) { BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* stack_pointer = ctx->stack_pointer; const Node* stack_size = gen_load(bb, stack_pointer); - const Node* stack_base_ptr = gen_lea(bb, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); + const Node* stack_base_ptr = lea_helper(a, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { gen_debug_printf(bb, "trace: stack_size=%d\n", shd_singleton(stack_size)); } diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 737b25366..7c92c78a4 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/memory_layout.h" #include "../transform/ir_gen_helpers.h" @@ -48,7 +49,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* ndecl = shd_rewrite_node(&ctx->rewriter, odecl); assert(ctx->bb); const Node* index = shd_bld_builtin_load(ctx->rewriter.dst_module, ctx->bb, BuiltinSubgroupId); - const Node* slice = gen_lea(ctx->bb, ref_decl_helper(a, ndecl), shd_int32_literal(a, 0), mk_nodes(a, index)); + const Node* slice = lea_helper(a, ref_decl_helper(a, ndecl), shd_int32_literal(a, 0), mk_nodes(a, index)); return slice; } case GlobalVariable_TAG: { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 25880d79a..70c5eab7c 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -121,10 +121,6 @@ void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { shd_bld_add_instruction_extract(bb, store(_shd_get_bb_arena(bb), (Store) { .ptr = ptr, .value = value, .mem = shd_bb_mem(bb) })); } -const Node* gen_lea(BodyBuilder* bb, const Node* base, const Node* offset, Nodes selectors) { - return lea_helper(_shd_get_bb_arena(bb), base, offset, selectors); -} - void gen_comment(BodyBuilder* bb, String str) { shd_bld_add_instruction_extract(bb, comment(_shd_get_bb_arena(bb), (Comment) { .string = str, .mem = shd_bb_mem(bb) })); } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 3862bdb01..2e12b8f70 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -27,7 +27,6 @@ const Node* gen_local_alloc(BodyBuilder*, const Type* ptr); const Node* gen_load(BodyBuilder*, const Node* ptr); void gen_store(BodyBuilder*, const Node* ptr, const Node* value); -const Node* gen_lea(BodyBuilder*, const Node* base, const Node* offset, Nodes selectors); void gen_comment(BodyBuilder*, String str); void gen_debug_printf(BodyBuilder*, String pattern, Nodes args); From ecdae61a3c4fa415b24e485f70eb85800bcb55a7 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:16:32 +0200 Subject: [PATCH 655/693] moved mem instr builders to mem.h --- include/shady/ir/builder.h | 2 + include/shady/ir/mem.h | 6 ++ src/backend/spirv/spirv_lift_globals_ssbo.c | 2 +- src/shady/body_builder.c | 2 +- src/shady/ir/builtin.c | 2 +- src/shady/ir/mem.c | 17 ++++++ src/shady/ir_private.h | 1 - src/shady/passes/lower_entrypoint_args.c | 2 +- src/shady/passes/lower_generic_ptrs.c | 4 +- src/shady/passes/lower_memcpy.c | 6 +- src/shady/passes/lower_physical_ptrs.c | 8 +-- src/shady/passes/lower_stack.c | 16 +++--- src/shady/passes/lower_switch_btree.c | 4 +- src/shady/passes/lower_tailcalls.c | 2 +- src/shady/passes/lower_workgroups.c | 8 +-- src/shady/passes/opt_demote_alloca.c | 4 +- src/shady/passes/reconvergence_heuristics.c | 12 ++-- src/shady/passes/restructure.c | 16 +++--- src/shady/transform/ir_gen_helpers.c | 62 ++++++++------------- src/shady/transform/ir_gen_helpers.h | 5 -- test/test_builder.c | 18 +++--- 21 files changed, 101 insertions(+), 98 deletions(-) diff --git a/include/shady/ir/builder.h b/include/shady/ir/builder.h index 2a0c8d764..3fce3e89a 100644 --- a/include/shady/ir/builder.h +++ b/include/shady/ir/builder.h @@ -10,6 +10,8 @@ BodyBuilder* shd_bld_begin(IrArena* a, const Node* mem); BodyBuilder* shd_bld_begin_pure(IrArena* a); BodyBuilder* shd_bld_begin_pseudo_instr(IrArena* a, const Node* mem); +IrArena* shd_get_bb_arena(BodyBuilder* bb); + /// Appends an instruction to the builder, may apply optimisations. /// If the arena is typed, returns a list of variables bound to the values yielded by that instruction Nodes shd_bld_add_instruction_extract(BodyBuilder* bb, const Node* instruction); diff --git a/include/shady/ir/mem.h b/include/shady/ir/mem.h index 5d0c83cb5..452fc5aed 100644 --- a/include/shady/ir/mem.h +++ b/include/shady/ir/mem.h @@ -6,4 +6,10 @@ const Node* shd_get_parent_mem(const Node* mem); const Node* shd_get_original_mem(const Node* mem); +const Node* shd_bld_stack_alloc(BodyBuilder* bb, const Type* type); +const Node* shd_bld_local_alloc(BodyBuilder* bb, const Type* type); + +const Node* shd_bld_load(BodyBuilder* bb, const Node* ptr); +void shd_bld_store(BodyBuilder* bb, const Node* ptr, const Node* value); + #endif diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index dbd06879b..711958332 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -42,7 +42,7 @@ static const Node* process(Context* ctx, const Node* node) { break; assert(ctx->bb && "this RefDecl node isn't appearing in an abstraction - we cannot replace it with a load!"); const Node* ptr_addr = lea_helper(a, ref_decl_helper(a, ctx->lifted_globals_decl), shd_int32_literal(a, 0), shd_singleton(shd_rewrite_node(&ctx->rewriter, odecl))); - const Node* ptr = gen_load(ctx->bb, ptr_addr); + const Node* ptr = shd_bld_load(ctx->bb, ptr_addr); return ptr; } case GlobalVariable_TAG: diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index b619f17c1..11cffadc2 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -55,7 +55,7 @@ BodyBuilder* shd_bld_begin_pure(IrArena* a) { return builder; } -IrArena* _shd_get_bb_arena(BodyBuilder* bb) { +IrArena* shd_get_bb_arena(BodyBuilder* bb) { return bb->arena; } diff --git a/src/shady/ir/builtin.c b/src/shady/ir/builtin.c index 27251c93f..c76531d72 100644 --- a/src/shady/ir/builtin.c +++ b/src/shady/ir/builtin.c @@ -144,5 +144,5 @@ const Node* shd_get_or_create_builtin(Module* m, Builtin b, String n) { } const Node* shd_bld_builtin_load(Module* m, BodyBuilder* bb, Builtin b) { - return gen_load(bb, ref_decl_helper(shd_module_get_arena(m), shd_get_or_create_builtin(m, b, NULL))); + return shd_bld_load(bb, ref_decl_helper(shd_module_get_arena(m), shd_get_or_create_builtin(m, b, NULL))); } diff --git a/src/shady/ir/mem.c b/src/shady/ir/mem.c index 47737519c..a3ff90620 100644 --- a/src/shady/ir/mem.c +++ b/src/shady/ir/mem.c @@ -1,4 +1,5 @@ #include "shady/ir/grammar.h" +#include "shady/ir/builder.h" #include @@ -68,3 +69,19 @@ const Node* shd_get_original_mem(const Node* mem) { return mem; } } + +const Node* shd_bld_stack_alloc(BodyBuilder* bb, const Type* type) { + return shd_first(shd_bld_add_instruction_extract(bb, stack_alloc(shd_get_bb_arena(bb), (StackAlloc) { .type = type, .mem = shd_bb_mem(bb) }))); +} + +const Node* shd_bld_local_alloc(BodyBuilder* bb, const Type* type) { + return shd_first(shd_bld_add_instruction_extract(bb, local_alloc(shd_get_bb_arena(bb), (LocalAlloc) { .type = type, .mem = shd_bb_mem(bb) }))); +} + +const Node* shd_bld_load(BodyBuilder* bb, const Node* ptr) { + return shd_first(shd_bld_add_instruction_extract(bb, load(shd_get_bb_arena(bb), (Load) { .ptr = ptr, .mem = shd_bb_mem(bb) }))); +} + +void shd_bld_store(BodyBuilder* bb, const Node* ptr, const Node* value) { + shd_bld_add_instruction_extract(bb, store(shd_get_bb_arena(bb), (Store) { .ptr = ptr, .value = value, .mem = shd_bb_mem(bb) })); +} diff --git a/src/shady/ir_private.h b/src/shady/ir_private.h index 948eea1fc..adb1ee238 100644 --- a/src/shady/ir_private.h +++ b/src/shady/ir_private.h @@ -36,7 +36,6 @@ void shd_destroy_module(Module* m); NodeId _shd_allocate_node_id(IrArena* arena, const Node* n); -IrArena* _shd_get_bb_arena(BodyBuilder* bb); const Node* _shd_bb_insert_mem(BodyBuilder* bb); const Node* _shd_bb_insert_block(BodyBuilder* bb); const Node* _shd_bld_finish_pseudo_instr(BodyBuilder* bb, const Node* terminator); diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 6af6c7ec9..99458e34a 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -65,7 +65,7 @@ static const Node* rewrite_body(Context* ctx, const Node* old_entry_point, const for (int i = 0; i < params.count; ++i) { const Node* addr = lea_helper(a, arg_struct, shd_int32_literal(a, 0), shd_singleton(shd_int32_literal(a, i))); - const Node* val = gen_load(bb, addr); + const Node* val = shd_bld_load(bb, addr); shd_register_processed(&ctx->rewriter, params.nodes[i], val); } diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index e62c5d0ca..02d6424ec 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -125,7 +125,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo Node* tag_case = case_(a, shd_empty(a)); BodyBuilder* case_bb = shd_bld_begin(a, shd_get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); - const Node* loaded_value = gen_load(case_bb, reinterpreted_ptr); + const Node* loaded_value = shd_bld_load(case_bb, reinterpreted_ptr); shd_set_abstraction_body(tag_case, shd_bld_join(case_bb, r.jp, shd_singleton(loaded_value))); jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } @@ -162,7 +162,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo Node* tag_case = case_(a, shd_empty(a)); BodyBuilder* case_bb = shd_bld_begin(a, shd_get_abstraction_mem(tag_case)); const Node* reinterpreted_ptr = recover_full_pointer(ctx, case_bb, tag, ptr_param, t); - gen_store(case_bb, reinterpreted_ptr, value_param); + shd_bld_store(case_bb, reinterpreted_ptr, value_param); shd_set_abstraction_body(tag_case, shd_bld_join(case_bb, r.jp, shd_empty(a))); jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index cfb1900d5..f1b6e7ae3 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -55,8 +55,8 @@ static const Node* process(Context* ctx, const Node* old) { shd_set_value_name(index, "memcpy_i"); Node* loop_case = l.loop_body; BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_case)); - const Node* loaded_word = gen_load(loop_bb, lea_helper(a, src_addr, index, shd_empty(a))); - gen_store(loop_bb, lea_helper(a, dst_addr, index, shd_empty(a)), loaded_word); + const Node* loaded_word = shd_bld_load(loop_bb, lea_helper(a, src_addr, index, shd_empty(a))); + shd_bld_store(loop_bb, lea_helper(a, dst_addr, index, shd_empty(a)), loaded_word); const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); @@ -102,7 +102,7 @@ static const Node* process(Context* ctx, const Node* old) { shd_set_value_name(index, "memset_i"); Node* loop_case = l.loop_body; BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_case)); - gen_store(loop_bb, lea_helper(a, dst_addr, index, shd_empty(a)), src_value); + shd_bld_store(loop_bb, lea_helper(a, dst_addr, index, shd_empty(a)), src_value); const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 01bc26ea4..8e43cdd61 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -59,7 +59,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type switch (element_type->tag) { case Bool_TAG: { const Node* logical_ptr = lea_helper(a, arr, zero, shd_singleton(address)); - const Node* value = gen_load(bb, logical_ptr); + const Node* value = shd_bld_load(bb, logical_ptr); return gen_primop_ce(bb, neq_op, 2, (const Node*[]) {value, int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size })}); } case PtrType_TAG: switch (element_type->payload.ptr_type.address_space) { @@ -80,7 +80,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* shift = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { - const Node* word = gen_load(bb, lea_helper(a, arr, zero, shd_singleton(offset))); + const Node* word = shd_bld_load(bb, lea_helper(a, arr, zero, shd_singleton(offset))); word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded word = shd_first(gen_primop(bb, lshift_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it acc = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, acc, word)); @@ -150,7 +150,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* zero_b = int_literal(a, (IntLiteral) { .value = 1, .width = a->config.memory.word_size }); const Node* one_b = int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size }); const Node* int_value = gen_primop_ce(bb, select_op, 3, (const Node*[]) { value, one_b, zero_b }); - gen_store(bb, logical_ptr, int_value); + shd_bld_store(bb, logical_ptr, int_value); return; } case PtrType_TAG: switch (element_type->payload.ptr_type.address_space) { @@ -186,7 +186,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* word = value; word = shd_first(gen_primop(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it word = gen_conversion(bb, int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }), word); // widen/truncate the word we want to store - gen_store(bb, lea_helper(a, arr, zero, shd_singleton(offset)), word); + shd_bld_store(bb, lea_helper(a, arr, zero, shd_singleton(offset)), word); offset = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); shift = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index f22ad4f4a..50b4de739 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -52,7 +52,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { const Node* stack_pointer = ctx->stack_pointer; const Node* stack = ctx->stack; - const Node* stack_size = gen_load(bb, stack_pointer); + const Node* stack_size = shd_bld_load(bb, stack_pointer); if (!push) // for pop, we decrease the stack size first stack_size = gen_primop_ce(bb, sub_op, 2, (const Node* []) { stack_size, element_size}); @@ -65,15 +65,15 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { const Node* popped_value = NULL; if (push) - gen_store(bb, addr, value_param); + shd_bld_store(bb, addr, value_param); else - popped_value = gen_load(bb, addr); + popped_value = shd_bld_load(bb, addr); if (push) // for push, we increase the stack size after the store stack_size = gen_primop_ce(bb, add_op, 2, (const Node* []) { stack_size, element_size}); // store updated stack size - gen_store(bb, stack_pointer, stack_size); + shd_bld_store(bb, stack_pointer, stack_size); if (ctx->config->printf_trace.stack_size) { gen_debug_printf(bb, name, shd_empty(a)); gen_debug_printf(bb, "stack size after: %d\n", shd_singleton(stack_size)); @@ -101,7 +101,7 @@ static const Node* process_node(Context* ctx, const Node* old) { // is this an old forgotten workaround ? if (ctx->stack) { const Node* stack_pointer = ctx->stack_pointer; - gen_store(bb, stack_pointer, shd_uint32_literal(a, 0)); + shd_bld_store(bb, stack_pointer, shd_uint32_literal(a, 0)); } shd_register_processed(r, shd_get_abstraction_mem(old), shd_bb_mem(bb)); shd_set_abstraction_body(new, shd_bld_finish(bb, shd_rewrite_node(&ctx->rewriter, old->payload.fun.body))); @@ -113,7 +113,7 @@ static const Node* process_node(Context* ctx, const Node* old) { assert(ctx->stack); GetStackSize payload = old->payload.get_stack_size; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); - const Node* sp = gen_load(bb, ctx->stack_pointer); + const Node* sp = shd_bld_load(bb, ctx->stack_pointer); return shd_bld_to_instr_yield_values(bb, shd_singleton(sp)); } case SetStackSize_TAG: { @@ -121,7 +121,7 @@ static const Node* process_node(Context* ctx, const Node* old) { SetStackSize payload = old->payload.set_stack_size; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* val = shd_rewrite_node(r, old->payload.set_stack_size.value); - gen_store(bb, ctx->stack_pointer, val); + shd_bld_store(bb, ctx->stack_pointer, val); return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } case GetStackBaseAddr_TAG: { @@ -129,7 +129,7 @@ static const Node* process_node(Context* ctx, const Node* old) { GetStackBaseAddr payload = old->payload.get_stack_base_addr; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* stack_pointer = ctx->stack_pointer; - const Node* stack_size = gen_load(bb, stack_pointer); + const Node* stack_size = shd_bld_load(bb, stack_pointer); const Node* stack_base_ptr = lea_helper(a, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { gen_debug_printf(bb, "trace: stack_size=%d\n", shd_singleton(stack_size)); diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index c1a13e465..2e2742727 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -153,8 +153,8 @@ static const Node* process(Context* ctx, const Node* node) { } BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); - const Node* run_default_case = gen_stack_alloc(bb, bool_type(a)); - gen_store(bb, run_default_case, false_lit(a)); + const Node* run_default_case = shd_bld_stack_alloc(bb, bool_type(a)); + shd_bld_store(bb, run_default_case, false_lit(a)); /*Context ctx2 = *ctx; ctx2.run_default_case = run_default_case; diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index ecbab2628..bbec5f0ea 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -299,7 +299,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { iterations_count_param = shd_first(l.params); BodyBuilder* loop_body_builder = shd_bld_begin(a, shd_get_abstraction_mem(loop_inside_case)); - const Node* next_function = gen_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); + const Node* next_function = shd_bld_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); const Node* get_active_branch_fn = access_decl(&ctx->rewriter, "builtin_get_active_branch"); const Node* next_mask = shd_first(gen_call(loop_body_builder, get_active_branch_fn, shd_empty(a))); const Node* local_id = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 46b43f60c..51122779c 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -74,7 +74,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(wrapper)); const Node* num_workgroups_var = shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinNumWorkgroups, NULL)); - const Node* workgroup_num_vec3 = gen_load(bb, ref_decl_helper(a, num_workgroups_var)); + const Node* workgroup_num_vec3 = shd_bld_load(bb, ref_decl_helper(a, num_workgroups_var)); // prepare variables for iterating over workgroups String names[] = { "gx", "gy", "gz" }; @@ -125,19 +125,19 @@ static const Node* process(Context* ctx, const Node* node) { // BodyBuilder* bb2 = begin_block_with_side_effects(a, bb_mem(builders[5])); BodyBuilder* bb2 = builders[5]; // write the workgroup ID - gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); + shd_bld_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinWorkgroupId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, workgroup_id[0], workgroup_id[1], workgroup_id[2]))); // write the local ID const Node* local_id[3]; // local_id[0] = SUBGROUP_SIZE * subgroup_id[0] + subgroup_local_id local_id[0] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), shd_bld_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); local_id[1] = subgroup_id[1]; local_id[2] = subgroup_id[2]; - gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); + shd_bld_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); // write the global ID const Node* global_id[3]; for (int dim = 0; dim < 3; dim++) global_id[dim] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); - gen_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); + shd_bld_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID gen_call(bb2, fn_addr_helper(a, inner), wparams); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 9bb286e99..5ba0c27cb 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -199,7 +199,7 @@ static const Node* process(Context* ctx, const Node* old) { break; *ctx->todo |= true; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); - const Node* data = gen_load(bb, k.src_alloca->new); + const Node* data = shd_bld_load(bb, k.src_alloca->new); data = gen_reinterpret_cast(bb, access_type, data); return shd_bld_to_instr_yield_value(bb, data); } @@ -218,7 +218,7 @@ static const Node* process(Context* ctx, const Node* old) { *ctx->todo |= true; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* data = gen_reinterpret_cast(bb, access_type, shd_rewrite_node(r, payload.value)); - gen_store(bb, k.src_alloca->new, data); + shd_bld_store(bb, k.src_alloca->new, data); return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } } diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 4e2fa0c00..79c2a8756 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -135,7 +135,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { ExitValue* exit_params = shd_arena_alloc(ctx->arena, sizeof(ExitValue) * exit_param_types.count); for (size_t j = 0; j < exit_param_types.count; j++) { - exit_params[j].alloca = gen_stack_alloc(outer_bb, shd_get_unqualified_type(exit_param_types.nodes[j])); + exit_params[j].alloca = shd_bld_stack_alloc(outer_bb, shd_get_unqualified_type(exit_param_types.nodes[j])); exit_params[j].uniform = shd_is_qualified_type_uniform(exit_param_types.nodes[j]); } exits[i] = (Exit) { @@ -146,7 +146,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { const Node* exit_destination_alloca = NULL; if (exiting_nodes_count > 1) - exit_destination_alloca = gen_stack_alloc(outer_bb, shd_int32_type(arena)); + exit_destination_alloca = shd_bld_stack_alloc(outer_bb, shd_int32_type(arena)); const Node* join_token_exit = param(arena, shd_as_qualified_type(join_point_type(arena, (JoinPointType) { .yield_types = shd_empty(arena) @@ -211,10 +211,10 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { BodyBuilder* exit_wrapper_bb = shd_bld_begin(arena, shd_get_abstraction_mem(exits[i].wrapper)); for (size_t j = 0; j < exits[i].params_count; j++) - gen_store(exit_wrapper_bb, exits[i].params[j].alloca, exit_wrapper_params.nodes[j]); + shd_bld_store(exit_wrapper_bb, exits[i].params[j].alloca, exit_wrapper_params.nodes[j]); // Set the destination if there's more than one option if (exiting_nodes_count > 1) - gen_store(exit_wrapper_bb, exit_destination_alloca, shd_int32_literal(arena, i)); + shd_bld_store(exit_wrapper_bb, exit_destination_alloca, shd_int32_literal(arena, i)); shd_set_abstraction_body(exits[i].wrapper, shd_bld_join(exit_wrapper_bb, join_token_exit, shd_empty(arena))); } @@ -264,7 +264,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { LARRAY(const Node*, recovered_args, exits[i].params_count); for (size_t j = 0; j < exits[i].params_count; j++) { - recovered_args[j] = gen_load(exit_recover_bb, exits[i].params[j].alloca); + recovered_args[j] = shd_bld_load(exit_recover_bb, exits[i].params[j].alloca); if (exits[i].params[j].uniform) recovered_args[j] = prim_op_helper(arena, subgroup_assume_uniform_op, shd_empty(arena), shd_singleton(recovered_args[j])); } @@ -278,7 +278,7 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { if (exiting_nodes_count == 1) outer_body = shd_bld_finish(outer_bb, exit_jumps[0]); else { - const Node* loaded_destination = gen_load(outer_bb, exit_destination_alloca); + const Node* loaded_destination = shd_bld_load(outer_bb, exit_destination_alloca); outer_body = shd_bld_finish(outer_bb, br_switch(arena, (Switch) { .switch_value = loaded_destination, .default_jump = exit_jumps[0], diff --git a/src/shady/passes/restructure.c b/src/shady/passes/restructure.c index 48ae2a0e0..c27289807 100644 --- a/src/shady/passes/restructure.c +++ b/src/shady/passes/restructure.c @@ -250,7 +250,7 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { for (size_t i = 0; i < yield_types.count; i++) { const Type* type = yield_types.nodes[i]; assert(shd_is_data_type(type)); - phis[i] = gen_local_alloc(bb_prelude, type); + phis[i] = shd_bld_local_alloc(bb_prelude, type); } // Create a new context to rewrite the body with @@ -265,19 +265,19 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { control_ctx.control_stack = &control_entry; // Set the depth for threads entering the control body - gen_store(bb_prelude, ctx->level_ptr, shd_int32_literal(a, control_entry.depth)); + shd_bld_store(bb_prelude, ctx->level_ptr, shd_int32_literal(a, control_entry.depth)); // Start building out the tail, first it needs to dereference the phi variables to recover the arguments given to join() Node* tail = case_(a, shd_empty(a)); BodyBuilder* bb_tail = shd_bld_begin(a, shd_get_abstraction_mem(tail)); LARRAY(const Node*, phi_values, yield_types.count); for (size_t i = 0; i < yield_types.count; i++) { - phi_values[i] = gen_load(bb_tail, phis[i]); + phi_values[i] = shd_bld_load(bb_tail, phis[i]); shd_register_processed(&ctx->rewriter, get_abstraction_params(get_structured_construct_tail(body)).nodes[i], phi_values[i]); } // Wrap the tail in a guarded if, to handle 'far' joins - const Node* level_value = gen_load(bb_tail, ctx->level_ptr); + const Node* level_value = shd_bld_load(bb_tail, ctx->level_ptr); const Node* guard = prim_op(a, (PrimOp) { .op = eq_op, .operands = mk_nodes(a, level_value, shd_int32_literal(a, ctx->control_stack ? ctx->control_stack->depth : 0)) }); Node* true_case = case_(a, shd_empty(a)); shd_register_processed(r, shd_get_abstraction_mem(get_structured_construct_tail(body)), shd_get_abstraction_mem(true_case)); @@ -295,11 +295,11 @@ static const Node* structure(Context* ctx, const Node* body, const Node* exit) { longjmp(ctx->bail, 1); BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); - gen_store(bb, ctx->level_ptr, shd_int32_literal(a, control->depth - 1)); + shd_bld_store(bb, ctx->level_ptr, shd_int32_literal(a, control->depth - 1)); Nodes args = shd_rewrite_nodes(&ctx->rewriter, body->payload.join.args); for (size_t i = 0; i < args.count; i++) { - gen_store(bb, control->phis[i], args.nodes[i]); + shd_bld_store(bb, control->phis[i], args.nodes[i]); } return shd_bld_finish(bb, jump_helper(a, shd_bb_mem(bb), exit, shd_empty(a))); @@ -356,9 +356,9 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new)); TmpAllocCleanupClosure cj1 = create_cancel_body_closure(bb); shd_list_append(TmpAllocCleanupClosure, ctx->cleanup_stack, cj1); - const Node* ptr = gen_local_alloc(bb, shd_int32_type(a)); + const Node* ptr = shd_bld_local_alloc(bb, shd_int32_type(a)); shd_set_value_name(ptr, "cf_depth"); - gen_store(bb, ptr, shd_int32_literal(a, 0)); + shd_bld_store(bb, ptr, shd_int32_literal(a, 0)); ctx2.level_ptr = ptr; ctx2.fn = new; struct Dict* tmp_processed = shd_clone_dict(ctx->rewriter.map); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 70c5eab7c..99a642a8c 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -14,19 +14,19 @@ #include Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { - assert(shd_get_arena_config(_shd_get_bb_arena(bb))->check_types); - const Node* instruction = call(_shd_get_bb_arena(bb), (Call) { .callee = callee, .args = args, .mem = shd_bb_mem(bb) }); + assert(shd_get_arena_config(shd_get_bb_arena(bb))->check_types); + const Node* instruction = call(shd_get_bb_arena(bb), (Call) { .callee = callee, .args = args, .mem = shd_bb_mem(bb) }); return shd_bld_add_instruction_extract(bb, instruction); } Nodes gen_primop(BodyBuilder* bb, Op op, Nodes type_args, Nodes operands) { - assert(shd_get_arena_config(_shd_get_bb_arena(bb))->check_types); - const Node* instruction = prim_op(_shd_get_bb_arena(bb), (PrimOp) { .op = op, .type_arguments = type_args, .operands = operands }); + assert(shd_get_arena_config(shd_get_bb_arena(bb))->check_types); + const Node* instruction = prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = op, .type_arguments = type_args, .operands = operands }); return shd_singleton(instruction); } Nodes gen_primop_c(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { - return gen_primop(bb, op, shd_empty(_shd_get_bb_arena(bb)), shd_nodes(_shd_get_bb_arena(bb), operands_count, operands)); + return gen_primop(bb, op, shd_empty(shd_get_bb_arena(bb)), shd_nodes(shd_get_bb_arena(bb), operands_count, operands)); } const Node* gen_primop_ce(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { @@ -41,7 +41,7 @@ const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { } const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { - return shd_bld_add_instruction(bb, ext_instr(_shd_get_bb_arena(bb), (ExtInstr) { + return shd_bld_add_instruction(bb, ext_instr(shd_get_bb_arena(bb), (ExtInstr) { .mem = shd_bb_mem(bb), .set = set, .opcode = opcode, @@ -51,7 +51,7 @@ const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const T } void gen_push_value_stack(BodyBuilder* bb, const Node* value) { - shd_bld_add_instruction_extract(bb, push_stack(_shd_get_bb_arena(bb), (PushStack) { .value = value, .mem = shd_bb_mem(bb) })); + shd_bld_add_instruction_extract(bb, push_stack(shd_get_bb_arena(bb), (PushStack) { .value = value, .mem = shd_bb_mem(bb) })); } void gen_push_values_stack(BodyBuilder* bb, Nodes values) { @@ -62,30 +62,30 @@ void gen_push_values_stack(BodyBuilder* bb, Nodes values) { } const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { - const Node* instruction = pop_stack(_shd_get_bb_arena(bb), (PopStack) { .type = type, .mem = shd_bb_mem(bb) }); + const Node* instruction = pop_stack(shd_get_bb_arena(bb), (PopStack) { .type = type, .mem = shd_bb_mem(bb) }); return shd_first(shd_bld_add_instruction_extract(bb, instruction)); } const Node* gen_get_stack_base_addr(BodyBuilder* bb) { - return get_stack_base_addr(_shd_get_bb_arena(bb), (GetStackBaseAddr) { .mem = shd_bb_mem(bb) }); + return get_stack_base_addr(shd_get_bb_arena(bb), (GetStackBaseAddr) { .mem = shd_bb_mem(bb) }); } const Node* gen_get_stack_size(BodyBuilder* bb) { - return shd_first(shd_bld_add_instruction_extract(bb, get_stack_size(_shd_get_bb_arena(bb), (GetStackSize) { .mem = shd_bb_mem(bb) }))); + return shd_first(shd_bld_add_instruction_extract(bb, get_stack_size(shd_get_bb_arena(bb), (GetStackSize) { .mem = shd_bb_mem(bb) }))); } void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { - shd_bld_add_instruction_extract(bb, set_stack_size(_shd_get_bb_arena(bb), (SetStackSize) { .value = new_size, .mem = shd_bb_mem(bb) })); + shd_bld_add_instruction_extract(bb, set_stack_size(shd_get_bb_arena(bb), (SetStackSize) { .value = new_size, .mem = shd_bb_mem(bb) })); } const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); - return prim_op(_shd_get_bb_arena(bb), (PrimOp) { .op = reinterpret_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); + return prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = reinterpret_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); } const Node* gen_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); - return prim_op(_shd_get_bb_arena(bb), (PrimOp) { .op = convert_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); + return prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = convert_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); } const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { @@ -94,39 +94,23 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { assert(src_type->tag == Int_TAG); IntSizes size = src_type->payload.int_type.width; assert(size != IntSizeMax); - const Type* dst_type = int_type(_shd_get_bb_arena(bb), (Int) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed }); + const Type* dst_type = int_type(shd_get_bb_arena(bb), (Int) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed }); // widen them lo = gen_conversion(bb, dst_type, lo); hi = gen_conversion(bb, dst_type, hi); // shift hi - const Node* shift_by = int_literal(_shd_get_bb_arena(bb), (IntLiteral) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed, .value = shd_get_type_bitwidth(src_type) }); + const Node* shift_by = int_literal(shd_get_bb_arena(bb), (IntLiteral) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed, .value = shd_get_type_bitwidth(src_type) }); hi = gen_primop_ce(bb, lshift_op, 2, (const Node* []) { hi, shift_by}); // Merge the two return gen_primop_ce(bb, or_op, 2, (const Node* []) { lo, hi }); } -const Node* gen_stack_alloc(BodyBuilder* bb, const Type* type) { - return shd_first(shd_bld_add_instruction_extract(bb, stack_alloc(_shd_get_bb_arena(bb), (StackAlloc) { .type = type, .mem = shd_bb_mem(bb) }))); -} - -const Node* gen_local_alloc(BodyBuilder* bb, const Type* type) { - return shd_first(shd_bld_add_instruction_extract(bb, local_alloc(_shd_get_bb_arena(bb), (LocalAlloc) { .type = type, .mem = shd_bb_mem(bb) }))); -} - -const Node* gen_load(BodyBuilder* bb, const Node* ptr) { - return shd_first(shd_bld_add_instruction_extract(bb, load(_shd_get_bb_arena(bb), (Load) { .ptr = ptr, .mem = shd_bb_mem(bb) }))); -} - -void gen_store(BodyBuilder* bb, const Node* ptr, const Node* value) { - shd_bld_add_instruction_extract(bb, store(_shd_get_bb_arena(bb), (Store) { .ptr = ptr, .value = value, .mem = shd_bb_mem(bb) })); -} - void gen_comment(BodyBuilder* bb, String str) { - shd_bld_add_instruction_extract(bb, comment(_shd_get_bb_arena(bb), (Comment) { .string = str, .mem = shd_bb_mem(bb) })); + shd_bld_add_instruction_extract(bb, comment(shd_get_bb_arena(bb), (Comment) { .string = str, .mem = shd_bb_mem(bb) })); } void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { - shd_bld_add_instruction(bb, debug_printf(_shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = shd_bb_mem(bb) })); + shd_bld_add_instruction(bb, debug_printf(shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = shd_bb_mem(bb) })); } const Node* find_or_process_decl(Rewriter* rewriter, const char* name) { @@ -154,7 +138,7 @@ const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* d assert(dst_type->tag == Int_TAG); // first convert to final bitsize then bitcast - const Type* extended_src_t = int_type(_shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = src_type->payload.int_type.is_signed }); + const Type* extended_src_t = int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = src_type->payload.int_type.is_signed }); const Node* val = src; val = gen_primop_e(bb, convert_op, shd_singleton(extended_src_t), shd_singleton(val)); val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); @@ -167,7 +151,7 @@ const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* d assert(dst_type->tag == Int_TAG); // first bitcast then convert to final bitsize - const Type* reinterpreted_src_t = int_type(_shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = dst_type->payload.int_type.is_signed }); + const Type* reinterpreted_src_t = int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = dst_type->payload.int_type.is_signed }); const Node* val = src; val = gen_primop_e(bb, reinterpret_op, shd_singleton(reinterpreted_src_t), shd_singleton(val)); val = gen_primop_e(bb, convert_op, shd_singleton(dst_type), shd_singleton(val)); @@ -181,9 +165,9 @@ const Node* convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const const Node* val = src; val = gen_primop_e(bb, reinterpret_op, shd_singleton( - int_type(_shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); + int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); val = gen_primop_e(bb, convert_op, shd_singleton( - int_type(_shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); + int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } @@ -195,9 +179,9 @@ const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, cons const Node* val = src; val = gen_primop_e(bb, reinterpret_op, shd_singleton( - int_type(_shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); + int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); val = gen_primop_e(bb, convert_op, shd_singleton( - int_type(_shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); + int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 2e12b8f70..2528e0eae 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -22,11 +22,6 @@ const Node* gen_reinterpret_cast(BodyBuilder*, const Type* dst, const Node* src) const Node* gen_conversion(BodyBuilder*, const Type* dst, const Node* src); const Node* gen_merge_halves(BodyBuilder*, const Node* lo, const Node* hi); -const Node* gen_stack_alloc(BodyBuilder*, const Type* ptr); -const Node* gen_local_alloc(BodyBuilder*, const Type* ptr); - -const Node* gen_load(BodyBuilder*, const Node* ptr); -void gen_store(BodyBuilder*, const Node* ptr, const Node* value); void gen_comment(BodyBuilder*, String str); void gen_debug_printf(BodyBuilder*, String pattern, Nodes args); diff --git a/test/test_builder.c b/test/test_builder.c index 297e08ffd..0353f01ab 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -37,15 +37,15 @@ static void test_body_builder_fun_body(IrArena* a) { Node* fun = function(m, mk_nodes(a, p1, p2), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); - const Node* p1_value = gen_load(bb, p1); + const Node* p1_value = shd_bld_load(bb, p1); CHECK(p1_value->tag == Load_TAG, exit(-1)); Node* true_case = case_(a, shd_empty(a)); BodyBuilder* tc_builder = shd_bld_begin(a, shd_get_abstraction_mem(true_case)); - gen_store(tc_builder, p1, shd_uint32_literal(a, 0)); + shd_bld_store(tc_builder, p1, shd_uint32_literal(a, 0)); shd_set_abstraction_body(true_case, shd_bld_selection_merge(tc_builder, shd_empty(a))); shd_bld_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, shd_uint32_literal(a, 0))), true_case, NULL); - const Node* p2_value = gen_load(bb, p2); + const Node* p2_value = shd_bld_load(bb, p2); const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, p1_value, p2_value)); const Node* return_terminator = fn_ret(a, (Return) { @@ -93,13 +93,13 @@ static void test_body_builder_impure_block(IrArena* a) { Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); - const Node* first_load = gen_load(bb, p1); + const Node* first_load = shd_bld_load(bb, p1); BodyBuilder* block_builder = shd_bld_begin_pseudo_instr(a, shd_bb_mem(bb)); - gen_store(block_builder, p1, shd_uint32_literal(a, 0)); + shd_bld_store(block_builder, p1, shd_uint32_literal(a, 0)); shd_bld_add_instruction_extract(bb, shd_bld_to_instr_yield_values(block_builder, shd_empty(a))); - const Node* second_load = gen_load(bb, p1); + const Node* second_load = shd_bld_load(bb, p1); const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); const Node* return_terminator = fn_ret(a, (Return) { @@ -132,17 +132,17 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { Node* fun = function(m, mk_nodes(a, p1), "fun", shd_empty(a), shd_empty(a)); BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); - const Node* first_load = gen_load(bb, p1); + const Node* first_load = shd_bld_load(bb, p1); BodyBuilder* block_builder = shd_bld_begin_pseudo_instr(a, shd_bb_mem(bb)); Node* if_true_case = case_(a, shd_empty(a)); BodyBuilder* if_true_builder = shd_bld_begin(a, shd_get_abstraction_mem(if_true_case)); - gen_store(if_true_builder, p1, shd_uint32_literal(a, 0)); + shd_bld_store(if_true_builder, p1, shd_uint32_literal(a, 0)); shd_set_abstraction_body(if_true_case, shd_bld_selection_merge(if_true_builder, shd_empty(a))); shd_bld_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, shd_uint32_literal(a, 0))), if_true_case, NULL); shd_bld_add_instruction_extract(bb, shd_bld_to_instr_yield_values(block_builder, shd_empty(a))); - const Node* second_load = gen_load(bb, p1); + const Node* second_load = shd_bld_load(bb, p1); const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); const Node* return_terminator = fn_ret(a, (Return) { From 9354900ebee0873471101693ce4cea18bedc5550 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:20:15 +0200 Subject: [PATCH 656/693] remove decl utilities from ir_gen_helpers --- include/shady/ir/decl.h | 3 +++ src/shady/ir/decl.c | 14 +++++++++++++- src/shady/passes/lower_tailcalls.c | 21 +++++++++++++-------- src/shady/transform/ir_gen_helpers.c | 19 ------------------- src/shady/transform/ir_gen_helpers.h | 5 ----- 5 files changed, 29 insertions(+), 33 deletions(-) diff --git a/include/shady/ir/decl.h b/include/shady/ir/decl.h index a2e3f42e0..6a2755da0 100644 --- a/include/shady/ir/decl.h +++ b/include/shady/ir/decl.h @@ -10,4 +10,7 @@ Node* _shd_global_var(Module*, Nodes annotations, const Type*, String, AddressSp static inline Node* constant(Module* m, Nodes annotations, const Type* t, const char* name) { return _shd_constant(m, annotations, t, name); } static inline Node* global_var(Module* m, Nodes annotations, const Type* t, String name, AddressSpace as) { return _shd_global_var(m, annotations, t, name, as); } +typedef struct Rewriter_ Rewriter; +const Node* shd_find_or_process_decl(Rewriter* rewriter, const char* name); + #endif diff --git a/src/shady/ir/decl.c b/src/shady/ir/decl.c index dcd84e3d1..f1b8d8ae3 100644 --- a/src/shady/ir/decl.c +++ b/src/shady/ir/decl.c @@ -1,4 +1,5 @@ #include "shady/ir/decl.h" +#include "shady/rewrite.h" #include "../ir_private.h" @@ -55,4 +56,15 @@ Node* _shd_global_var(Module* mod, Nodes annotations, const Type* type, const ch Node* decl = _shd_create_node_helper(arena, node, NULL); _shd_module_add_decl(mod, decl); return decl; -} \ No newline at end of file +} + +const Node* shd_find_or_process_decl(Rewriter* rewriter, const char* name) { + Nodes old_decls = shd_module_get_declarations(rewriter->src_module); + for (size_t i = 0; i < old_decls.count; i++) { + const Node* decl = old_decls.nodes[i]; + if (strcmp(get_declaration_name(decl), name) == 0) { + return shd_rewrite_node(rewriter, decl); + } + } + assert(false); +} diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index bbec5f0ea..0546e0c1c 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -35,6 +35,11 @@ typedef struct Context_ { static const Node* process(Context* ctx, const Node* old); +static const Node* get_fn(Rewriter* rewriter, const char* name) { + const Node* decl = shd_find_or_process_decl(rewriter, name); + return fn_addr_helper(rewriter->dst_arena, decl); +} + static const Type* lowered_fn_type(Context* ctx) { IrArena* a = ctx->rewriter.dst_arena; return shd_int_type_helper(a, false, ctx->config->target.memory.ptr_size); @@ -78,7 +83,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_entry_pt)); gen_call(bb, fn_addr_helper(a, ctx->init_fn), shd_empty(a)); - gen_call(bb, access_decl(&ctx->rewriter, "builtin_init_scheduler"), shd_empty(a)); + gen_call(bb, get_fn(&ctx->rewriter, "builtin_init_scheduler"), shd_empty(a)); // shove the arguments on the stack for (size_t i = rewritten_params.count - 1; i < rewritten_params.count; i--) { @@ -86,7 +91,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { } // Initialise next_fn/next_mask to the entry function - const Node* jump_fn = access_decl(&ctx->rewriter, "builtin_fork"); + const Node* jump_fn = get_fn(&ctx->rewriter, "builtin_fork"); const Node* fn_addr = shd_uint32_literal(a, get_fn_ptr(ctx, old)); // fn_addr = gen_conversion(bb, lowered_fn_type(ctx), fn_addr); gen_call(bb, jump_fn, shd_singleton(fn_addr)); @@ -177,7 +182,7 @@ static const Node* process(Context* ctx, const Node* old) { }); } case JoinPointType_TAG: return type_decl_ref(a, (TypeDeclRef) { - .decl = find_or_process_decl(&ctx->rewriter, "JoinPoint"), + .decl = shd_find_or_process_decl(&ctx->rewriter, "JoinPoint"), }); case ExtInstr_TAG: { ExtInstr payload = old->payload.ext_instr; @@ -195,7 +200,7 @@ static const Node* process(Context* ctx, const Node* old) { } return call(a, (Call) { .mem = shd_rewrite_node(r, payload.mem), - .callee = access_decl(r, callee_name), + .callee = get_fn(r, callee_name), .args = args, }); } @@ -210,7 +215,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* target = shd_rewrite_node(&ctx->rewriter, payload.callee); target = gen_conversion(bb, shd_uint32_type(a), target); - gen_call(bb, access_decl(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); + gen_call(bb, get_fn(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); return shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) })); } case Join_TAG: { @@ -231,7 +236,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* dst = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 1))); const Node* tree_node = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 0))); - gen_call(bb, access_decl(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); + gen_call(bb, get_fn(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); return shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) })); } case PtrType_TAG: { @@ -299,8 +304,8 @@ static void generate_top_level_dispatch_fn(Context* ctx) { iterations_count_param = shd_first(l.params); BodyBuilder* loop_body_builder = shd_bld_begin(a, shd_get_abstraction_mem(loop_inside_case)); - const Node* next_function = shd_bld_load(loop_body_builder, access_decl(&ctx->rewriter, "next_fn")); - const Node* get_active_branch_fn = access_decl(&ctx->rewriter, "builtin_get_active_branch"); + const Node* next_function = shd_bld_load(loop_body_builder, get_fn(&ctx->rewriter, "next_fn")); + const Node* get_active_branch_fn = get_fn(&ctx->rewriter, "builtin_get_active_branch"); const Node* next_mask = shd_first(gen_call(loop_body_builder, get_active_branch_fn, shd_empty(a))); const Node* local_id = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); const Node* should_run = gen_primop_e(loop_body_builder, mask_is_thread_active_op, shd_empty(a), mk_nodes(a, next_mask, local_id)); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 99a642a8c..04ebfe2a4 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -113,25 +113,6 @@ void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { shd_bld_add_instruction(bb, debug_printf(shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = shd_bb_mem(bb) })); } -const Node* find_or_process_decl(Rewriter* rewriter, const char* name) { - Nodes old_decls = shd_module_get_declarations(rewriter->src_module); - for (size_t i = 0; i < old_decls.count; i++) { - const Node* decl = old_decls.nodes[i]; - if (strcmp(get_declaration_name(decl), name) == 0) { - return shd_rewrite_node(rewriter, decl); - } - } - assert(false); -} - -const Node* access_decl(Rewriter* rewriter, const char* name) { - const Node* decl = find_or_process_decl(rewriter, name); - if (decl->tag == Function_TAG) - return fn_addr_helper(rewriter->dst_arena, decl); - else - return ref_decl_helper(rewriter->dst_arena, decl); -} - const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 2528e0eae..43a413eab 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -25,11 +25,6 @@ const Node* gen_merge_halves(BodyBuilder*, const Node* lo, const Node* hi); void gen_comment(BodyBuilder*, String str); void gen_debug_printf(BodyBuilder*, String pattern, Nodes args); -typedef struct Rewriter_ Rewriter; - -const Node* find_or_process_decl(Rewriter*, const char* name); -const Node* access_decl(Rewriter*, const char* name); - const Node* convert_int_extend_according_to_src_t(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_extend_according_to_dst_t(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_zero_extend(BodyBuilder*, const Type* dst_type, const Node* src); From 859e97777a00ccd5d2981edd1a9700e5de6ca77a Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:27:03 +0200 Subject: [PATCH 657/693] removed some variants of gen_primop --- src/shady/passes/lower_physical_ptrs.c | 12 ++++++------ src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/normalize_builtins.c | 4 ++-- src/shady/transform/ir_gen_helpers.c | 18 +++--------------- src/shady/transform/ir_gen_helpers.h | 2 -- 5 files changed, 12 insertions(+), 26 deletions(-) diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 8e43cdd61..2cab0a758 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -82,11 +82,11 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { const Node* word = shd_bld_load(bb, lea_helper(a, arr, zero, shd_singleton(offset))); word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded - word = shd_first(gen_primop(bb, lshift_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it + word = prim_op_helper(a, lshift_op, shd_empty(a), mk_nodes(a, word, shift)); // shift it acc = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, acc, word)); - offset = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); - shift = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); + offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1))); + shift = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth)); } if (config->printf_trace.memory_accesses) { AddressSpace as = shd_get_unqualified_type(arr->type)->payload.ptr_type.address_space; @@ -184,12 +184,12 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element // word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded }*/ const Node* word = value; - word = shd_first(gen_primop(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it + word = (prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it word = gen_conversion(bb, int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }), word); // widen/truncate the word we want to store shd_bld_store(bb, lea_helper(a, arr, zero, shd_singleton(offset)), word); - offset = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); - shift = shd_first(gen_primop(bb, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); + offset = (prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); + shift = (prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth))); } if (config->printf_trace.memory_accesses) { AddressSpace as = shd_get_unqualified_type(arr->type)->payload.ptr_type.address_space; diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 51122779c..6af83342a 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -176,7 +176,7 @@ static const Node* process(Context* ctx, const Node* node) { if (ptr == shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinSubgroupId, NULL)) { BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* loaded = shd_first(shd_bld_add_instruction_extract(bb, shd_recreate_node(&ctx->rewriter, node))); - const Node* uniformized = shd_first(gen_primop(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(loaded))); + const Node* uniformized = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(loaded)); return shd_bld_to_instr_yield_values(bb, shd_singleton(uniformized)); } } diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index 1d58618aa..f6d3cf016 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -79,8 +79,8 @@ static const Node* process(Context* ctx, const Node* node) { if (req_cast) { assert(shd_is_data_type(req_cast)); BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, node->payload.load.mem)); - const Node* r1 = shd_first(shd_bld_add_instruction_extract(bb, shd_recreate_node(r, node))); - const Node* r2 = shd_first(gen_primop(bb, reinterpret_op, shd_singleton(req_cast), shd_singleton(r1))); + const Node* r1 = shd_bld_add_instruction(bb, shd_recreate_node(r, node)); + const Node* r2 = prim_op_helper(a, reinterpret_op, shd_singleton(req_cast), shd_singleton(r1)); return shd_bld_to_instr_yield_values(bb, shd_singleton(r2)); } break; diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 04ebfe2a4..3486be203 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -19,25 +19,13 @@ Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { return shd_bld_add_instruction_extract(bb, instruction); } -Nodes gen_primop(BodyBuilder* bb, Op op, Nodes type_args, Nodes operands) { - assert(shd_get_arena_config(shd_get_bb_arena(bb))->check_types); - const Node* instruction = prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = op, .type_arguments = type_args, .operands = operands }); - return shd_singleton(instruction); -} - -Nodes gen_primop_c(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { - return gen_primop(bb, op, shd_empty(shd_get_bb_arena(bb)), shd_nodes(shd_get_bb_arena(bb), operands_count, operands)); -} - const Node* gen_primop_ce(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { - Nodes result = gen_primop_c(bb, op, operands_count, operands); - assert(result.count == 1); - return result.nodes[0]; + IrArena* a = shd_get_bb_arena(bb); + return prim_op_helper(a, op, shd_empty(a), shd_nodes(a, operands_count, operands)); } const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { - Nodes result = gen_primop(bb, op, ty, nodes); - return shd_first(result); + return prim_op_helper(shd_get_bb_arena(bb), op, ty, nodes); } const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 43a413eab..50eb6cf64 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -12,8 +12,6 @@ const Node* gen_get_stack_size(BodyBuilder*); void gen_set_stack_size(BodyBuilder*, const Node* new_size); Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); -Nodes gen_primop(BodyBuilder*, Op, Nodes, Nodes); -Nodes gen_primop_c(BodyBuilder*, Op op, size_t operands_count, const Node* operands[]); const Node* gen_primop_ce(BodyBuilder*, Op op, size_t operands_count, const Node* operands[]); const Node* gen_primop_e(BodyBuilder*, Op op, Nodes, Nodes); const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); From 800f476767928d65c18c23ac2e45b9032e62c060 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:33:50 +0200 Subject: [PATCH 658/693] removed gen_primop_ce --- src/shady/passes/lower_callf.c | 2 +- src/shady/passes/lower_lea.c | 10 +++++----- src/shady/passes/lower_mask.c | 6 +++--- src/shady/passes/lower_physical_ptrs.c | 4 ++-- src/shady/passes/lower_stack.c | 4 ++-- src/shady/transform/ir_gen_helpers.c | 10 +++------- src/shady/transform/ir_gen_helpers.h | 1 - 7 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index b0849d4f2..bafdfd07a 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -89,7 +89,7 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { const Node* return_jp = ctx->return_jp; if (return_jp) { BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, old->payload.fn_ret.mem)); - return_jp = gen_primop_ce(bb, subgroup_assume_uniform_op, 1, (const Node* []) { return_jp }); + return_jp = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(return_jp)); // Join up at the return address instead of returning return shd_bld_finish(bb, join(a, (Join) { .join_point = return_jp, diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 8cdba2d1e..773832ded 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -41,9 +41,9 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po const Node* element_t_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); const Node* new_index = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, index); - const Node* physical_offset = gen_primop_ce(bb, mul_op, 2, (const Node* []) {new_index, element_t_size}); + const Node* physical_offset = prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, new_index, element_t_size)); - ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, physical_offset }); + ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ptr, physical_offset)); pointer_type = ptr_type(a, (PtrType) { .pointed_type = element_type, @@ -66,7 +66,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po assert(n < member_types.count); const Node* offset_of = gen_primop_e(bb, offset_of_op, shd_singleton(pointed_type), shd_singleton(shd_uint64_literal(a, n))); - ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, offset_of }); + ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ptr, offset_of)); pointer_type = ptr_type(a, (PtrType) { .pointed_type = member_types.nodes[n], @@ -97,9 +97,9 @@ static const Node* lower_ptr_offset(Context* ctx, BodyBuilder* bb, const Type* p const Node* element_t_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); const Node* new_offset = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, offset); - const Node* physical_offset = gen_primop_ce(bb, mul_op, 2, (const Node* []) { new_offset, element_t_size}); + const Node* physical_offset = prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, new_offset, element_t_size)); - ptr = gen_primop_ce(bb, add_op, 2, (const Node* []) { ptr, physical_offset}); + ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ptr, physical_offset)); } return ptr; diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 39bd86a2a..a74101750 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -31,11 +31,11 @@ static const Node* process(Context* ctx, const Node* node) { index = gen_conversion(bb, shd_get_actual_mask_type(ctx->rewriter.dst_arena), index); const Node* acc = mask; // acc >>= index - acc = gen_primop_ce(bb, rshift_logical_op, 2, (const Node* []) { acc, index }); + acc = prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, acc, index)); // acc &= 0x1 - acc = gen_primop_ce(bb, and_op, 2, (const Node* []) { acc, ctx->one }); + acc = prim_op_helper(a, and_op, shd_empty(a), mk_nodes(a, acc, ctx->one)); // acc == 1 - acc = gen_primop_ce(bb, eq_op, 2, (const Node* []) { acc, ctx->one }); + acc = prim_op_helper(a, eq_op, shd_empty(a), mk_nodes(a, acc, ctx->one)); return shd_bld_to_instr_yield_value(bb, acc); } default: break; diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 2cab0a758..e95cf566e 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -60,7 +60,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type case Bool_TAG: { const Node* logical_ptr = lea_helper(a, arr, zero, shd_singleton(address)); const Node* value = shd_bld_load(bb, logical_ptr); - return gen_primop_ce(bb, neq_op, 2, (const Node*[]) {value, int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size })}); + return prim_op_helper(a, neq_op, shd_empty(a), mk_nodes(a, value, int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size }))); } case PtrType_TAG: switch (element_type->payload.ptr_type.address_space) { case AsGlobal: { @@ -149,7 +149,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* logical_ptr = lea_helper(a, arr, zero, shd_singleton(address)); const Node* zero_b = int_literal(a, (IntLiteral) { .value = 1, .width = a->config.memory.word_size }); const Node* one_b = int_literal(a, (IntLiteral) { .value = 0, .width = a->config.memory.word_size }); - const Node* int_value = gen_primop_ce(bb, select_op, 3, (const Node*[]) { value, one_b, zero_b }); + const Node* int_value = prim_op_helper(a, select_op, shd_empty(a), mk_nodes(a, value, one_b, zero_b)); shd_bld_store(bb, logical_ptr, int_value); return; } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 50b4de739..d8b15cdc5 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -55,7 +55,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { const Node* stack_size = shd_bld_load(bb, stack_pointer); if (!push) // for pop, we decrease the stack size first - stack_size = gen_primop_ce(bb, sub_op, 2, (const Node* []) { stack_size, element_size}); + stack_size = prim_op_helper(a, sub_op, shd_empty(a), mk_nodes(a, stack_size, element_size)); const Node* addr = lea_helper(a, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); assert(shd_get_unqualified_type(addr->type)->tag == PtrType_TAG); @@ -70,7 +70,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { popped_value = shd_bld_load(bb, addr); if (push) // for push, we increase the stack size after the store - stack_size = gen_primop_ce(bb, add_op, 2, (const Node* []) { stack_size, element_size}); + stack_size = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, stack_size, element_size)); // store updated stack size shd_bld_store(bb, stack_pointer, stack_size); diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 3486be203..b4322a23d 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -19,11 +19,6 @@ Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { return shd_bld_add_instruction_extract(bb, instruction); } -const Node* gen_primop_ce(BodyBuilder* bb, Op op, size_t operands_count, const Node* operands[]) { - IrArena* a = shd_get_bb_arena(bb); - return prim_op_helper(a, op, shd_empty(a), shd_nodes(a, operands_count, operands)); -} - const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { return prim_op_helper(shd_get_bb_arena(bb), op, ty, nodes); } @@ -77,6 +72,7 @@ const Node* gen_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { } const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { + IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(lo->type); assert(shd_get_unqualified_type(hi->type) == src_type); assert(src_type->tag == Int_TAG); @@ -88,9 +84,9 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { hi = gen_conversion(bb, dst_type, hi); // shift hi const Node* shift_by = int_literal(shd_get_bb_arena(bb), (IntLiteral) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed, .value = shd_get_type_bitwidth(src_type) }); - hi = gen_primop_ce(bb, lshift_op, 2, (const Node* []) { hi, shift_by}); + hi = prim_op_helper(a, lshift_op, shd_empty(a), mk_nodes(a, hi, shift_by)); // Merge the two - return gen_primop_ce(bb, or_op, 2, (const Node* []) { lo, hi }); + return prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, lo, hi)); } void gen_comment(BodyBuilder* bb, String str) { diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 50eb6cf64..876ff3afc 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -12,7 +12,6 @@ const Node* gen_get_stack_size(BodyBuilder*); void gen_set_stack_size(BodyBuilder*, const Node* new_size); Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); -const Node* gen_primop_ce(BodyBuilder*, Op op, size_t operands_count, const Node* operands[]); const Node* gen_primop_e(BodyBuilder*, Op op, Nodes, Nodes); const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); From e02118f8496f695904c27028d857dcfe6f5ce4fc Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:38:43 +0200 Subject: [PATCH 659/693] remove gen_primop_e --- src/shady/passes/lift_indirect_targets.c | 2 +- src/shady/passes/lower_alloca.c | 8 +++---- src/shady/passes/lower_generic_ptrs.c | 20 ++++++++--------- src/shady/passes/lower_lea.c | 6 ++--- src/shady/passes/lower_memcpy.c | 8 +++---- src/shady/passes/lower_physical_ptrs.c | 22 +++++++++---------- src/shady/passes/lower_stack.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 6 ++--- src/shady/passes/lower_tailcalls.c | 12 +++++----- src/shady/passes/lower_vec_arr.c | 2 +- src/shady/passes/lower_workgroups.c | 8 +++---- src/shady/passes/scope2control.c | 2 +- src/shady/transform/ir_gen_helpers.c | 28 ++++++++++++------------ src/shady/transform/ir_gen_helpers.h | 1 - src/shady/transform/memory_layout.c | 2 +- test/test_builder.c | 12 +++++----- 16 files changed, 70 insertions(+), 71 deletions(-) diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index e7d3e71a1..7f268e3cb 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -206,7 +206,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* jp = gen_ext_instruction(bb, "shady.internal", ShadyOpCreateJoinPoint, shd_as_qualified_type(jp_type, true), mk_nodes(a, tail_ptr, sp)); // dumbass hack - jp = gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(jp)); + jp = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(jp)); shd_register_processed(r, shd_first(get_abstraction_params(oinside)), jp); shd_register_processed(r, shd_get_abstraction_mem(oinside), shd_bb_mem(bb)); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 2cb9371c8..8267d42a1 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -53,7 +53,7 @@ static void search_operand_for_alloca(VContext* vctx, const Node* node) { const Type* element_type = shd_rewrite_node(&vctx->context->rewriter, node->payload.stack_alloc.type); assert(shd_is_data_type(element_type)); - const Node* slot_offset = gen_primop_e(vctx->bb, offset_of_op, shd_singleton(type_decl_ref_helper(a, vctx->nom_t)), shd_singleton(shd_int32_literal(a, shd_list_count(vctx->members)))); + const Node* slot_offset = prim_op_helper(a, offset_of_op, shd_singleton(type_decl_ref_helper(a, vctx->nom_t)), shd_singleton(shd_int32_literal(a, shd_list_count(vctx->members)))); shd_list_append(const Type*, vctx->members, element_type); StackSlot slot = { vctx->num_slots, slot_offset, element_type, AsPrivate }; @@ -115,7 +115,7 @@ static const Node* process(Context* ctx, const Node* node) { }); shd_destroy_list(vctx.members); ctx2.num_slots = vctx.num_slots; - ctx2.frame_size = gen_primop_e(bb, size_of_op, shd_singleton(type_decl_ref_helper(a, vctx.nom_t)), shd_empty(a)); + ctx2.frame_size = prim_op_helper(a, size_of_op, shd_singleton(type_decl_ref_helper(a, vctx.nom_t)), shd_empty(a)); ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); // make sure to use the new mem from then on @@ -144,12 +144,12 @@ static const Node* process(Context* ctx, const Node* node) { //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); - const Node* slot = ptr_array_element_offset(a, (PtrArrayElementOffset) { .ptr = ctx->base_stack_addr_on_entry, .offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)) }); + const Node* slot = ptr_array_element_offset(a, (PtrArrayElementOffset) { .ptr = ctx->base_stack_addr_on_entry, .offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)) }); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = gen_reinterpret_cast(bb, ptr_t, slot); //bool last = found_slot->i == ctx->num_slots - 1; //if (last) { - const Node* updated_stack_ptr = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, ctx->frame_size)); + const Node* updated_stack_ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, ctx->frame_size)); gen_set_stack_size(bb, updated_stack_ptr); //} diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index 02d6424ec..ce4718241 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -49,17 +49,17 @@ static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t const Node* generic_ptr_type = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false}); // first_non_tag_bit = nptr >> (64 - 2 - 1) - const Node* first_non_tag_bit = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, shd_get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth - 1))); + const Node* first_non_tag_bit = prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, shd_get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth - 1))); // first_non_tag_bit &= 1 - first_non_tag_bit = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); + first_non_tag_bit = prim_op_helper(a, and_op, shd_empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); // needs_sign_extension = first_non_tag_bit == 1 - const Node* needs_sign_extension = gen_primop_e(bb, eq_op, shd_empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); + const Node* needs_sign_extension = prim_op_helper(a, eq_op, shd_empty(a), mk_nodes(a, first_non_tag_bit, size_t_literal(a, 1))); // sign_extension_patch = needs_sign_extension ? ((1 << 2) - 1) << (64 - 2) : 0 - const Node* sign_extension_patch = gen_primop_e(bb, select_op, shd_empty(a), mk_nodes(a, needs_sign_extension, size_t_literal(a, ((size_t) ((1 << max_tag) - 1)) << (shd_get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth)), size_t_literal(a, 0))); + const Node* sign_extension_patch = prim_op_helper(a, select_op, shd_empty(a), mk_nodes(a, needs_sign_extension, size_t_literal(a, ((size_t) ((1 << max_tag) - 1)) << (shd_get_type_bitwidth(generic_ptr_type) - generic_ptr_tag_bitwidth)), size_t_literal(a, 0))); // patched_ptr = nptr & 0b00111 ... 111 - const Node* patched_ptr = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, SIZE_MAX >> generic_ptr_tag_bitwidth))); + const Node* patched_ptr = prim_op_helper(a, and_op, shd_empty(a), mk_nodes(a, nptr, size_t_literal(a, SIZE_MAX >> generic_ptr_tag_bitwidth))); // patched_ptr = patched_ptr | sign_extension_patch - patched_ptr = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, patched_ptr, sign_extension_patch)); + patched_ptr = prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, patched_ptr, sign_extension_patch)); const Type* dst_ptr_t = ptr_type(a, (PtrType) { .pointed_type = element_type, .address_space = get_addr_space_from_tag(tag) }); const Node* reinterpreted_ptr = gen_reinterpret_cast(bb, dst_ptr_t, patched_ptr); return reinterpreted_ptr; @@ -130,7 +130,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example - const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); + const Node* extracted_tag = prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, shd_empty(a)); shd_set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); @@ -167,7 +167,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo jumps[tag] = jump_helper(a, shd_get_abstraction_mem(r.case_), tag_case, shd_empty(a)); } // extracted_tag = nptr >> (64 - 2), for example - const Node* extracted_tag = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); + const Node* extracted_tag = prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, ptr_param, size_t_literal(a, shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); Node* default_case = case_(a, shd_empty(a)); shd_set_abstraction_body(default_case, unreachable(a, (Unreachable) { .mem = shd_get_abstraction_mem(default_case) })); @@ -249,10 +249,10 @@ static const Node* process(Context* ctx, const Node* old) { const Node* generic_ptr = gen_reinterpret_cast(bb, ctx->generic_ptr_type, src_ptr); const Node* ptr_mask = size_t_literal(a, (UINT64_MAX >> (uint64_t) (generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr & 0x001111 ... 111 - generic_ptr = gen_primop_e(bb, and_op, shd_empty(a), mk_nodes(a, generic_ptr, ptr_mask)); + generic_ptr = prim_op_helper(a, and_op, shd_empty(a), mk_nodes(a, generic_ptr, ptr_mask)); const Node* shifted_tag = size_t_literal(a, (tag << (uint64_t) (shd_get_type_bitwidth(ctx->generic_ptr_type) - generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr | 01000000 ... 000 - generic_ptr = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, generic_ptr, shifted_tag)); + generic_ptr = prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, generic_ptr, shifted_tag)); return shd_bld_to_instr_yield_values(bb, shd_singleton(generic_ptr)); } else if (old_src_t->tag == PtrType_TAG && old_src_t->payload.ptr_type.address_space == AsGeneric) { // cast _from_ generic diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 773832ded..350d7d8d7 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -38,7 +38,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po case ArrType_TAG: { const Type* element_type = pointed_type->payload.arr_type.element_type; - const Node* element_t_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); + const Node* element_t_size = prim_op_helper(a, size_of_op, shd_singleton(element_type), shd_empty(a)); const Node* new_index = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, index); const Node* physical_offset = prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, new_index, element_t_size)); @@ -65,7 +65,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po size_t n = selector_value->value; assert(n < member_types.count); - const Node* offset_of = gen_primop_e(bb, offset_of_op, shd_singleton(pointed_type), shd_singleton(shd_uint64_literal(a, n))); + const Node* offset_of = prim_op_helper(a, offset_of_op, shd_singleton(pointed_type), shd_singleton(shd_uint64_literal(a, n))); ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ptr, offset_of)); pointer_type = ptr_type(a, (PtrType) { @@ -94,7 +94,7 @@ static const Node* lower_ptr_offset(Context* ctx, BodyBuilder* bb, const Type* p // assert(arr_type->tag == ArrType_TAG); // const Type* element_type = arr_type->payload.arr_type.element_type; - const Node* element_t_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); + const Node* element_t_size = prim_op_helper(a, size_of_op, shd_singleton(element_type), shd_empty(a)); const Node* new_offset = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, offset); const Node* physical_offset = prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, new_offset, element_t_size)); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index f1b6e7ae3..8a0fc2855 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -57,7 +57,7 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_case)); const Node* loaded_word = shd_bld_load(loop_bb, lea_helper(a, src_addr, index, shd_empty(a))); shd_bld_store(loop_bb, lea_helper(a, dst_addr, index, shd_empty(a)), loaded_word); - const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); + const Node* next_index = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); shd_set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = shd_get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); @@ -66,7 +66,7 @@ static const Node* process(Context* ctx, const Node* old) { shd_set_abstraction_body(loop_case, shd_bld_finish(loop_bb, branch(a, (Branch) { .mem = shd_bb_mem(loop_bb), - .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), + .condition = prim_op_helper(a, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), .true_jump = jump_helper(a, shd_bb_mem(loop_bb), true_case, shd_empty(a)), .false_jump = jump_helper(a, shd_bb_mem(loop_bb), false_case, shd_empty(a)), }))); @@ -103,7 +103,7 @@ static const Node* process(Context* ctx, const Node* old) { Node* loop_case = l.loop_body; BodyBuilder* loop_bb = shd_bld_begin(a, shd_get_abstraction_mem(loop_case)); shd_bld_store(loop_bb, lea_helper(a, dst_addr, index, shd_empty(a)), src_value); - const Node* next_index = gen_primop_e(loop_bb, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); + const Node* next_index = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, index, shd_uint32_literal(a, 1))); Node* true_case = case_(a, shd_empty(a)); shd_set_abstraction_body(true_case, join(a, (Join) { .join_point = l.continue_jp, .mem = shd_get_abstraction_mem(true_case), .args = shd_singleton(next_index) })); @@ -112,7 +112,7 @@ static const Node* process(Context* ctx, const Node* old) { shd_set_abstraction_body(loop_case, shd_bld_finish(loop_bb, branch(a, (Branch) { .mem = shd_bb_mem(loop_bb), - .condition = gen_primop_e(loop_bb, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), + .condition = prim_op_helper(a, lt_op, shd_empty(a), mk_nodes(a, next_index, num_in_words)), .true_jump = jump_helper(a, shd_bb_mem(loop_bb), true_case, shd_empty(a)), .false_jump = jump_helper(a, shd_bb_mem(loop_bb), false_case, shd_empty(a)), }))); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index e95cf566e..662b4d5b5 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -83,7 +83,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* word = shd_bld_load(bb, lea_helper(a, arr, zero, shd_singleton(offset))); word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded word = prim_op_helper(a, lshift_op, shd_empty(a), mk_nodes(a, word, shift)); // shift it - acc = gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, acc, word)); + acc = prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, acc, word)); offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1))); shift = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, shift, word_bitwidth)); @@ -112,8 +112,8 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type Nodes member_types = compound_type->payload.record_type.members; LARRAY(const Node*, loaded, member_types.count); for (size_t i = 0; i < member_types.count; i++) { - const Node* field_offset = gen_primop_e(bb, offset_of_op, shd_singleton(element_type), shd_singleton(size_t_literal(a, i))); - const Node* adjusted_offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, address, field_offset)); + const Node* field_offset = prim_op_helper(a, offset_of_op, shd_singleton(element_type), shd_singleton(size_t_literal(a, i))); + const Node* adjusted_offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, address, field_offset)); loaded[i] = gen_deserialisation(ctx, bb, member_types.nodes[i], arr, adjusted_offset); } return composite_helper(a, element_type, shd_nodes(a, member_types.count, loaded)); @@ -132,7 +132,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* offset = address; for (size_t i = 0; i < components_count; i++) { components[i] = gen_deserialisation(ctx, bb, component_type, arr, offset); - offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, shd_singleton(component_type), shd_empty(a)))); + offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, offset, prim_op_helper(a, size_of_op, shd_singleton(component_type), shd_empty(a)))); } return composite_helper(a, element_type, shd_nodes(a, components_count, components)); } @@ -156,7 +156,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element case PtrType_TAG: switch (element_type->payload.ptr_type.address_space) { case AsGlobal: { const Type* ptr_int_t = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false }); - const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, shd_singleton(ptr_int_t), shd_singleton(value)); + const Node* unsigned_value = prim_op_helper(a, reinterpret_op, shd_singleton(ptr_int_t), shd_singleton(value)); return gen_serialisation(ctx, bb, ptr_int_t, arr, address, unsigned_value); } default: shd_error("TODO") @@ -203,15 +203,15 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element } case Float_TAG: { const Type* unsigned_int_t = int_type(a, (Int) {.width = shd_float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); - const Node* unsigned_value = gen_primop_e(bb, reinterpret_op, shd_singleton(unsigned_int_t), shd_singleton(value)); + const Node* unsigned_value = prim_op_helper(a, reinterpret_op, shd_singleton(unsigned_int_t), shd_singleton(value)); return gen_serialisation(ctx, bb, unsigned_int_t, arr, address, unsigned_value); } case RecordType_TAG: { Nodes member_types = element_type->payload.record_type.members; for (size_t i = 0; i < member_types.count; i++) { const Node* extracted_value = prim_op(a, (PrimOp) { .op = extract_op, .operands = mk_nodes(a, value, shd_int32_literal(a, i)), .type_arguments = shd_empty(a) }); - const Node* field_offset = gen_primop_e(bb, offset_of_op, shd_singleton(element_type), shd_singleton(size_t_literal(a, i))); - const Node* adjusted_offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, address, field_offset)); + const Node* field_offset = prim_op_helper(a, offset_of_op, shd_singleton(element_type), shd_singleton(size_t_literal(a, i))); + const Node* adjusted_offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, address, field_offset)); gen_serialisation(ctx, bb, member_types.nodes[i], arr, adjusted_offset, extracted_value); } return; @@ -235,7 +235,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* offset = address; for (size_t i = 0; i < components_count; i++) { gen_serialisation(ctx, bb, component_type, arr, offset, shd_extract_helper(a, value, shd_singleton(shd_int32_literal(a, i)))); - offset = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, offset, gen_primop_e(bb, size_of_op, shd_singleton(component_type), shd_empty(a)))); + offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, offset, prim_op_helper(a, size_of_op, shd_singleton(component_type), shd_empty(a)))); } return; } @@ -407,7 +407,7 @@ static const Node* make_record_type(Context* ctx, AddressSpace as, Nodes collect // we need to compute the actual pointer by getting the offset and dividing it // after lower_memory_layout, optimisations will eliminate this and resolve to a value BodyBuilder* bb = shd_bld_begin_pure(a); - const Node* offset = gen_primop_e(bb, offset_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_singleton(size_t_literal(a, i))); + const Node* offset = prim_op_helper(a, offset_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_singleton(size_t_literal(a, i))); new_address->payload.constant.value = shd_bld_to_instr_pure_with_values(bb, shd_singleton(offset)); shd_register_processed(&ctx->rewriter, decl, new_address); @@ -463,7 +463,7 @@ static void construct_emulated_memory_array(Context* ctx, AddressSpace as) { // compute the size BodyBuilder* bb = shd_bld_begin_pure(a); - const Node* size_of = gen_primop_e(bb, size_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_empty(a)); + const Node* size_of = prim_op_helper(a, size_of_op, shd_singleton(type_decl_ref(a, (TypeDeclRef) { .decl = global_struct_t })), shd_empty(a)); const Node* size_in_words = shd_bytes_to_words(bb, size_of); Node* constant_decl = constant(m, annotations, ptr_size_type, shd_fmt_string_irarena(a, "memory_%s_size", as_name)); diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index d8b15cdc5..b350f1d57 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -45,7 +45,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); - const Node* element_size = gen_primop_e(bb, size_of_op, shd_singleton(element_type), shd_empty(a)); + const Node* element_size = prim_op_helper(a, size_of_op, shd_singleton(element_type), shd_empty(a)); element_size = gen_conversion(bb, shd_uint32_type(a), element_size); // TODO somehow annotate the uniform guys as uniform diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index e3dbd8fe1..62cf77995 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -61,7 +61,7 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co } case Type_Int_TAG: { if (t->payload.int_type.width == IntTy64) { - const Node* hi = gen_primop_e(bb, rshift_logical_op, shd_empty(a), mk_nodes(a, param, shd_int32_literal(a, 32))); + const Node* hi = prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, param, shd_int32_literal(a, 32))); hi = convert_int_zero_extend(bb, shd_int32_type(a), hi); const Node* lo = convert_int_zero_extend(bb, shd_int32_type(a), param); hi = build_subgroup_first(ctx, bb, scope, hi); @@ -69,8 +69,8 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co const Node* it = int_type(a, (Int) { .width = IntTy64, .is_signed = t->payload.int_type.is_signed }); hi = convert_int_zero_extend(bb, it, hi); lo = convert_int_zero_extend(bb, it, lo); - hi = gen_primop_e(bb, lshift_op, shd_empty(a), mk_nodes(a, hi, shd_int32_literal(a, 32))); - return gen_primop_e(bb, or_op, shd_empty(a), mk_nodes(a, lo, hi)); + hi = prim_op_helper(a, lshift_op, shd_empty(a), mk_nodes(a, hi, shd_int32_literal(a, 32))); + return prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, lo, hi)); } break; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 0546e0c1c..6d0d57d35 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -231,10 +231,10 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); gen_push_values_stack(bb, shd_rewrite_nodes(&ctx->rewriter, old->payload.join.args)); - const Node* jp_payload = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 2))); + const Node* jp_payload = prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 2))); gen_push_value_stack(bb, jp_payload); - const Node* dst = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 1))); - const Node* tree_node = gen_primop_e(bb, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 0))); + const Node* dst = prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 1))); + const Node* tree_node = prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 0))); gen_call(bb, get_fn(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); return shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) })); @@ -308,7 +308,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { const Node* get_active_branch_fn = get_fn(&ctx->rewriter, "builtin_get_active_branch"); const Node* next_mask = shd_first(gen_call(loop_body_builder, get_active_branch_fn, shd_empty(a))); const Node* local_id = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); - const Node* should_run = gen_primop_e(loop_body_builder, mask_is_thread_active_op, shd_empty(a), mk_nodes(a, next_mask, local_id)); + const Node* should_run = prim_op_helper(a, mask_is_thread_active_op, shd_empty(a), mk_nodes(a, next_mask, local_id)); if (ctx->config->printf_trace.god_function) { const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); @@ -320,11 +320,11 @@ static void generate_top_level_dispatch_fn(Context* ctx) { const Node* iteration_count_plus_one = NULL; if (count_iterations) - iteration_count_plus_one = gen_primop_e(loop_body_builder, add_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, 1))); + iteration_count_plus_one = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, 1))); if (ctx->config->shader_diagnostics.max_top_iterations > 0) { begin_control_t c = shd_bld_begin_control(loop_body_builder, shd_empty(a)); - const Node* bail_condition = gen_primop_e(loop_body_builder, gt_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); + const Node* bail_condition = prim_op_helper(a, gt_op, shd_empty(a), mk_nodes(a, iterations_count_param, shd_int32_literal(a, ctx->config->shader_diagnostics.max_top_iterations))); Node* bail_case = case_(a, shd_empty(a)); const Node* break_terminator = join(a, (Join) { .args = shd_empty(a), .join_point = l.break_jp, .mem = shd_get_abstraction_mem(bail_case) }); shd_set_abstraction_body(bail_case, break_terminator); diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index cfe00add1..cbebb3e67 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -23,7 +23,7 @@ static const Node* scalarify_primop(Context* ctx, const Node* old) { LARRAY(const Node*, nops, noperands.count); for (size_t j = 0; j < noperands.count; j++) nops[j] = shd_extract_helper(a, noperands.nodes[j], shd_singleton(shd_int32_literal(a, i))); - elements[i] = gen_primop_e(bb, old->payload.prim_op.op, shd_empty(a), shd_nodes(a, noperands.count, nops)); + elements[i] = prim_op_helper(a, old->payload.prim_op.op, shd_empty(a), shd_nodes(a, noperands.count, nops)); } const Type* t = arr_type(a, (ArrType) { .element_type = shd_rewrite_node(&ctx->rewriter, dst_type), diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index 6af83342a..dc55ef30d 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -22,7 +22,7 @@ static void add_bounds_check(IrArena* a, BodyBuilder* bb, const Node* i, const N .args = shd_empty(a), .mem = shd_get_abstraction_mem(out_of_bounds_case) })); - shd_bld_if(bb, shd_empty(a), gen_primop_e(bb, gte_op, shd_empty(a), mk_nodes(a, i, max)), out_of_bounds_case, NULL); + shd_bld_if(bb, shd_empty(a), prim_op_helper(a, gte_op, shd_empty(a), mk_nodes(a, i, max)), out_of_bounds_case, NULL); } static const Node* process(Context* ctx, const Node* node) { @@ -129,14 +129,14 @@ static const Node* process(Context* ctx, const Node* node) { // write the local ID const Node* local_id[3]; // local_id[0] = SUBGROUP_SIZE * subgroup_id[0] + subgroup_local_id - local_id[0] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), shd_bld_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); + local_id[0] = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, ctx->config->specialization.subgroup_size), subgroup_id[0])), shd_bld_builtin_load(m, bb, BuiltinSubgroupLocalInvocationId))); local_id[1] = subgroup_id[1]; local_id[2] = subgroup_id[2]; shd_bld_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinLocalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, local_id[0], local_id[1], local_id[2]))); // write the global ID const Node* global_id[3]; for (int dim = 0; dim < 3; dim++) - global_id[dim] = gen_primop_e(bb2, add_op, shd_empty(a), mk_nodes(a, gen_primop_e(bb2, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); + global_id[dim] = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); shd_bld_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID gen_call(bb2, fn_addr_helper(a, inner), wparams); @@ -156,7 +156,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* body_bb = builders[depth]; shd_set_abstraction_body(loop_body, shd_bld_finish(body_bb, merge_continue(a, (MergeContinue) { - .args = shd_singleton(gen_primop_e(body_bb, add_op, shd_empty(a), mk_nodes(a, params[dim], shd_uint32_literal(a, 1)))), + .args = shd_singleton(prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, params[dim], shd_uint32_literal(a, 1)))), .mem = shd_bb_mem(body_bb) }))); shd_bld_loop(depth > 0 ? builders[depth - 1] : bb, shd_empty(a), shd_singleton(shd_uint32_literal(a, 0)), loop_body); diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index aaa4166fb..08dc00205 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -125,7 +125,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab Nodes original_params = get_abstraction_params(dst); for (size_t j = 0; j < results.count; j++) { if (shd_is_qualified_type_uniform(original_params.nodes[j]->type)) - results = shd_change_node_at_index(a, results, j, gen_primop_e(bb, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(results.nodes[j]))); + results = shd_change_node_at_index(a, results, j, prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(results.nodes[j]))); } c = c2; diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index b4322a23d..401df0358 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -19,10 +19,6 @@ Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { return shd_bld_add_instruction_extract(bb, instruction); } -const Node* gen_primop_e(BodyBuilder* bb, Op op, Nodes ty, Nodes nodes) { - return prim_op_helper(shd_get_bb_arena(bb), op, ty, nodes); -} - const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { return shd_bld_add_instruction(bb, ext_instr(shd_get_bb_arena(bb), (ExtInstr) { .mem = shd_bb_mem(bb), @@ -98,6 +94,7 @@ void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { } const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { + IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); assert(dst_type->tag == Int_TAG); @@ -105,12 +102,13 @@ const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* d // first convert to final bitsize then bitcast const Type* extended_src_t = int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = src_type->payload.int_type.is_signed }); const Node* val = src; - val = gen_primop_e(bb, convert_op, shd_singleton(extended_src_t), shd_singleton(val)); - val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); + val = prim_op_helper(a, convert_op, shd_singleton(extended_src_t), shd_singleton(val)); + val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { + IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); assert(dst_type->tag == Int_TAG); @@ -118,35 +116,37 @@ const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* d // first bitcast then convert to final bitsize const Type* reinterpreted_src_t = int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = dst_type->payload.int_type.is_signed }); const Node* val = src; - val = gen_primop_e(bb, reinterpret_op, shd_singleton(reinterpreted_src_t), shd_singleton(val)); - val = gen_primop_e(bb, convert_op, shd_singleton(dst_type), shd_singleton(val)); + val = prim_op_helper(a, reinterpret_op, shd_singleton(reinterpreted_src_t), shd_singleton(val)); + val = prim_op_helper(a, convert_op, shd_singleton(dst_type), shd_singleton(val)); return val; } const Node* convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { + IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); assert(dst_type->tag == Int_TAG); const Node* val = src; - val = gen_primop_e(bb, reinterpret_op, shd_singleton( + val = prim_op_helper(a, reinterpret_op, shd_singleton( int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); - val = gen_primop_e(bb, convert_op, shd_singleton( + val = prim_op_helper(a, convert_op, shd_singleton( int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); - val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); + val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { + IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(src->type); assert(src_type->tag == Int_TAG); assert(dst_type->tag == Int_TAG); const Node* val = src; - val = gen_primop_e(bb, reinterpret_op, shd_singleton( + val = prim_op_helper(a, reinterpret_op, shd_singleton( int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); - val = gen_primop_e(bb, convert_op, shd_singleton( + val = prim_op_helper(a, convert_op, shd_singleton( int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); - val = gen_primop_e(bb, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); + val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); return val; } diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 876ff3afc..26fec1af4 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -12,7 +12,6 @@ const Node* gen_get_stack_size(BodyBuilder*); void gen_set_stack_size(BodyBuilder*, const Node* new_size); Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); -const Node* gen_primop_e(BodyBuilder*, Op op, Nodes, Nodes); const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); const Node* gen_reinterpret_cast(BodyBuilder*, const Type* dst, const Node* src); diff --git a/src/shady/transform/memory_layout.c b/src/shady/transform/memory_layout.c index a65f18376..de754f34c 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/transform/memory_layout.c @@ -115,7 +115,7 @@ const Node* shd_bytes_to_words(BodyBuilder* bb, const Node* bytes) { const Type* word_type = int_type(a, (Int) { .width = shd_get_arena_config(a)->memory.word_size, .is_signed = false }); size_t word_width = shd_get_type_bitwidth(word_type); const Node* bytes_per_word = size_t_literal(a, word_width / 8); - return gen_primop_e(bb, div_op, shd_empty(a), mk_nodes(a, bytes, bytes_per_word)); + return prim_op_helper(a, div_op, shd_empty(a), mk_nodes(a, bytes, bytes_per_word)); } uint64_t shd_bytes_to_words_static(const IrArena* a, uint64_t bytes) { diff --git a/test/test_builder.c b/test/test_builder.c index 0353f01ab..445c4a2fe 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -15,7 +15,7 @@ static void test_body_builder_constants(IrArena* a) { BodyBuilder* bb = shd_bld_begin_pure(a); - const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, shd_int32_literal(a, 4), shd_int32_literal(a, 38))); + const Node* sum = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, shd_int32_literal(a, 4), shd_int32_literal(a, 38))); const Node* result = shd_bld_to_instr_yield_value(bb, sum); CHECK(sum == result, exit(-1)); CHECK(result->tag == IntLiteral_TAG, exit(-1)); @@ -43,11 +43,11 @@ static void test_body_builder_fun_body(IrArena* a) { BodyBuilder* tc_builder = shd_bld_begin(a, shd_get_abstraction_mem(true_case)); shd_bld_store(tc_builder, p1, shd_uint32_literal(a, 0)); shd_set_abstraction_body(true_case, shd_bld_selection_merge(tc_builder, shd_empty(a))); - shd_bld_if(bb, shd_empty(a), gen_primop_e(bb, gt_op, shd_empty(a), mk_nodes(a, p1_value, shd_uint32_literal(a, 0))), true_case, NULL); + shd_bld_if(bb, shd_empty(a), prim_op_helper(a, gt_op, shd_empty(a), mk_nodes(a, p1_value, shd_uint32_literal(a, 0))), true_case, NULL); const Node* p2_value = shd_bld_load(bb, p2); - const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, p1_value, p2_value)); + const Node* sum = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, p1_value, p2_value)); const Node* return_terminator = fn_ret(a, (Return) { .mem = shd_bb_mem(bb), .args = shd_singleton(sum) @@ -101,7 +101,7 @@ static void test_body_builder_impure_block(IrArena* a) { const Node* second_load = shd_bld_load(bb, p1); - const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); + const Node* sum = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); const Node* return_terminator = fn_ret(a, (Return) { .mem = shd_bb_mem(bb), .args = shd_singleton(sum) @@ -139,12 +139,12 @@ static void test_body_builder_impure_block_with_control_flow(IrArena* a) { BodyBuilder* if_true_builder = shd_bld_begin(a, shd_get_abstraction_mem(if_true_case)); shd_bld_store(if_true_builder, p1, shd_uint32_literal(a, 0)); shd_set_abstraction_body(if_true_case, shd_bld_selection_merge(if_true_builder, shd_empty(a))); - shd_bld_if(block_builder, shd_empty(a), gen_primop_e(block_builder, neq_op, shd_empty(a), mk_nodes(a, first_load, shd_uint32_literal(a, 0))), if_true_case, NULL); + shd_bld_if(block_builder, shd_empty(a), prim_op_helper(a, neq_op, shd_empty(a), mk_nodes(a, first_load, shd_uint32_literal(a, 0))), if_true_case, NULL); shd_bld_add_instruction_extract(bb, shd_bld_to_instr_yield_values(block_builder, shd_empty(a))); const Node* second_load = shd_bld_load(bb, p1); - const Node* sum = gen_primop_e(bb, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); + const Node* sum = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, first_load, second_load)); const Node* return_terminator = fn_ret(a, (Return) { .mem = shd_bb_mem(bb), .args = shd_singleton(sum) From 7761136ad0fcec5b8cd4f2ec67c8bf9137d25468 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:47:13 +0200 Subject: [PATCH 660/693] fix regression in lower_tailcalls --- src/shady/passes/lower_tailcalls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 6d0d57d35..1d9ab2561 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -304,7 +304,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { iterations_count_param = shd_first(l.params); BodyBuilder* loop_body_builder = shd_bld_begin(a, shd_get_abstraction_mem(loop_inside_case)); - const Node* next_function = shd_bld_load(loop_body_builder, get_fn(&ctx->rewriter, "next_fn")); + const Node* next_function = shd_bld_load(loop_body_builder, ref_decl_helper(a, shd_find_or_process_decl(&ctx->rewriter, "next_fn"))); const Node* get_active_branch_fn = get_fn(&ctx->rewriter, "builtin_get_active_branch"); const Node* next_mask = shd_first(gen_call(loop_body_builder, get_active_branch_fn, shd_empty(a))); const Node* local_id = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); From 46f32320323a339c7a272af48eaad5fb5131887d Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:48:31 +0200 Subject: [PATCH 661/693] move memory_layout.c to shady/ir/ --- src/shady/ir/CMakeLists.txt | 1 + src/shady/{transform => ir}/memory_layout.c | 2 +- src/shady/transform/CMakeLists.txt | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) rename src/shady/{transform => ir}/memory_layout.c (99%) diff --git a/src/shady/ir/CMakeLists.txt b/src/shady/ir/CMakeLists.txt index 9afdaf292..841bb4cdb 100644 --- a/src/shady/ir/CMakeLists.txt +++ b/src/shady/ir/CMakeLists.txt @@ -11,4 +11,5 @@ target_sources(shady PRIVATE type.c grammar.c debug.c + memory_layout.c ) \ No newline at end of file diff --git a/src/shady/transform/memory_layout.c b/src/shady/ir/memory_layout.c similarity index 99% rename from src/shady/transform/memory_layout.c rename to src/shady/ir/memory_layout.c index de754f34c..9baadd909 100644 --- a/src/shady/transform/memory_layout.c +++ b/src/shady/ir/memory_layout.c @@ -1,6 +1,6 @@ #include "shady/ir/memory_layout.h" -#include "ir_gen_helpers.h" +#include "transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/transform/CMakeLists.txt b/src/shady/transform/CMakeLists.txt index 2cd22ba9f..965a6bdd2 100644 --- a/src/shady/transform/CMakeLists.txt +++ b/src/shady/transform/CMakeLists.txt @@ -1,5 +1,4 @@ target_sources(shady PRIVATE internal_constants.c ir_gen_helpers.c - memory_layout.c ) From b9b7dee304ea543ccfb4a066885084c6cd5d2fca Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:53:44 +0200 Subject: [PATCH 662/693] move stack stuff to a new file --- include/shady/ir/stack.h | 14 +++++++++++ src/shady/ir/CMakeLists.txt | 1 + src/shady/ir/stack.c | 31 ++++++++++++++++++++++++ src/shady/passes/lift_indirect_targets.c | 14 ++++++----- src/shady/passes/lower_alloca.c | 7 +++--- src/shady/passes/lower_tailcalls.c | 14 ++++++----- src/shady/passes/setup_stack_frames.c | 6 ++--- src/shady/transform/ir_gen_helpers.c | 28 --------------------- src/shady/transform/ir_gen_helpers.h | 7 ------ 9 files changed, 69 insertions(+), 53 deletions(-) create mode 100644 include/shady/ir/stack.h create mode 100644 src/shady/ir/stack.c diff --git a/include/shady/ir/stack.h b/include/shady/ir/stack.h new file mode 100644 index 000000000..690e4bd8f --- /dev/null +++ b/include/shady/ir/stack.h @@ -0,0 +1,14 @@ +#ifndef SHADY_IR_STACK_H +#define SHADY_IR_STACK_H + +#include "shady/ir/base.h" +#include "shady/ir/builder.h" + +void shd_bld_stack_push_value(BodyBuilder* bb, const Node* value); +void shd_bld_stack_push_values(BodyBuilder* bb, Nodes values); +const Node* shd_bld_stack_pop_value(BodyBuilder* bb, const Type* type); +const Node* shd_bld_get_stack_base_addr(BodyBuilder* bb); +const Node* shd_bld_get_stack_size(BodyBuilder* bb); +void shd_bld_set_stack_size(BodyBuilder* bb, const Node* new_size); + +#endif diff --git a/src/shady/ir/CMakeLists.txt b/src/shady/ir/CMakeLists.txt index 841bb4cdb..d811dcd62 100644 --- a/src/shady/ir/CMakeLists.txt +++ b/src/shady/ir/CMakeLists.txt @@ -12,4 +12,5 @@ target_sources(shady PRIVATE grammar.c debug.c memory_layout.c + stack.c ) \ No newline at end of file diff --git a/src/shady/ir/stack.c b/src/shady/ir/stack.c new file mode 100644 index 000000000..1a9934f4a --- /dev/null +++ b/src/shady/ir/stack.c @@ -0,0 +1,31 @@ +#include "shady/ir/stack.h" + +#include "shady/ir/grammar.h" + +void shd_bld_stack_push_value(BodyBuilder* bb, const Node* value) { + shd_bld_add_instruction_extract(bb, push_stack(shd_get_bb_arena(bb), (PushStack) { .value = value, .mem = shd_bb_mem(bb) })); +} + +void shd_bld_stack_push_values(BodyBuilder* bb, Nodes values) { + for (size_t i = values.count - 1; i < values.count; i--) { + const Node* value = values.nodes[i]; + shd_bld_stack_push_value(bb, value); + } +} + +const Node* shd_bld_stack_pop_value(BodyBuilder* bb, const Type* type) { + const Node* instruction = pop_stack(shd_get_bb_arena(bb), (PopStack) { .type = type, .mem = shd_bb_mem(bb) }); + return shd_first(shd_bld_add_instruction_extract(bb, instruction)); +} + +const Node* shd_bld_get_stack_base_addr(BodyBuilder* bb) { + return get_stack_base_addr(shd_get_bb_arena(bb), (GetStackBaseAddr) { .mem = shd_bb_mem(bb) }); +} + +const Node* shd_bld_get_stack_size(BodyBuilder* bb) { + return shd_first(shd_bld_add_instruction_extract(bb, get_stack_size(shd_get_bb_arena(bb), (GetStackSize) { .mem = shd_bb_mem(bb) }))); +} + +void shd_bld_set_stack_size(BodyBuilder* bb, const Node* new_size) { + shd_bld_add_instruction_extract(bb, set_stack_size(shd_get_bb_arena(bb), (SetStackSize) { .value = new_size, .mem = shd_bb_mem(bb) })); +} diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 7f268e3cb..8aa396796 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -1,8 +1,10 @@ -#include "shady/pass.h" #include "join_point_ops.h" -#include "../ir_private.h" +#include "shady/pass.h" #include "shady/visit.h" +#include "shady/ir/stack.h" + +#include "../ir_private.h" #include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" @@ -52,10 +54,10 @@ static const Node* add_spill_instrs(Context* ctx, BodyBuilder* builder, Nodes sp const Type* t = nvar->type; shd_deconstruct_qualified_type(&t); assert(t->tag != PtrType_TAG || !t->payload.ptr_type.is_reference && "References cannot be spilled"); - gen_push_value_stack(builder, nvar); + shd_bld_stack_push_value(builder, nvar); } - return gen_get_stack_size(builder); + return shd_bld_get_stack_size(builder); } static Nodes set2nodes(IrArena* a, struct Dict* set) { @@ -130,7 +132,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { // Recover that stuff inside the new body BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_fn)); - gen_set_stack_size(bb, payload); + shd_bld_set_stack_size(bb, payload); for (size_t i = recover_context_size - 1; i < recover_context_size; i--) { const Node* ovar = frontier.nodes[i]; // assert(ovar->tag == Variable_TAG); @@ -138,7 +140,7 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { const Type* value_type = shd_rewrite_node(r, ovar->type); //String param_name = get_value_name_unsafe(ovar); - const Node* recovered_value = gen_pop_value_stack(bb, shd_get_unqualified_type(value_type)); + const Node* recovered_value = shd_bld_stack_pop_value(bb, shd_get_unqualified_type(value_type)); //if (param_name) // set_value_name(recovered_value, param_name); diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 8267d42a1..ac3efd143 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -1,5 +1,6 @@ #include "shady/pass.h" #include "shady/visit.h" +#include "shady/ir/stack.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -90,8 +91,8 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); ctx2.prepared_offsets = shd_new_dict(const Node*, StackSlot, (HashFn) shd_hash_node, (CmpFn) shd_compare_node); - ctx2.base_stack_addr_on_entry = gen_get_stack_base_addr(bb); - ctx2.stack_size_on_entry = gen_get_stack_size(bb); + ctx2.base_stack_addr_on_entry = shd_bld_get_stack_base_addr(bb); + ctx2.stack_size_on_entry = shd_bld_get_stack_size(bb); shd_set_value_name((Node*) ctx2.stack_size_on_entry, "stack_size_before_alloca"); Node* nom_t = nominal_type(m, shd_empty(a), shd_format_string_arena(a->arena, "%s_stack_frame", shd_get_abstraction_name(node))); @@ -150,7 +151,7 @@ static const Node* process(Context* ctx, const Node* node) { //bool last = found_slot->i == ctx->num_slots - 1; //if (last) { const Node* updated_stack_ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, ctx->frame_size)); - gen_set_stack_size(bb, updated_stack_ptr); + shd_bld_set_stack_size(bb, updated_stack_ptr); //} return shd_bld_to_instr_yield_values(bb, shd_singleton(slot)); diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 1d9ab2561..6097ef576 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -1,6 +1,8 @@ -#include "shady/pass.h" #include "join_point_ops.h" +#include "shady/pass.h" +#include "shady/ir/stack.h" + #include "../ir_private.h" #include "../analysis/cfg.h" @@ -87,7 +89,7 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { // shove the arguments on the stack for (size_t i = rewritten_params.count - 1; i < rewritten_params.count; i--) { - gen_push_value_stack(bb, rewritten_params.nodes[i]); + shd_bld_stack_push_value(bb, rewritten_params.nodes[i]); } // Initialise next_fn/next_mask to the entry function @@ -157,7 +159,7 @@ static const Node* process(Context* ctx, const Node* old) { for (size_t i = 0; i < old->payload.fun.params.count; i++) { const Node* old_param = old->payload.fun.params.nodes[i]; const Type* new_param_type = shd_rewrite_node(&ctx->rewriter, shd_get_unqualified_type(old_param->type)); - const Node* popped = gen_pop_value_stack(bb, new_param_type); + const Node* popped = shd_bld_stack_pop_value(bb, new_param_type); // TODO use the uniform stack instead ? or no ? if (shd_is_qualified_type_uniform(old_param->type)) popped = prim_op(a, (PrimOp) { .op = subgroup_assume_uniform_op, .type_arguments = shd_empty(a), .operands = shd_singleton(popped) }); @@ -211,7 +213,7 @@ static const Node* process(Context* ctx, const Node* old) { // return recreate_node_identity(&ctx->rewriter, old); TailCall payload = old->payload.tail_call; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); - gen_push_values_stack(bb, shd_rewrite_nodes(&ctx->rewriter, payload.args)); + shd_bld_stack_push_values(bb, shd_rewrite_nodes(&ctx->rewriter, payload.args)); const Node* target = shd_rewrite_node(&ctx->rewriter, payload.callee); target = gen_conversion(bb, shd_uint32_type(a), target); @@ -230,9 +232,9 @@ static const Node* process(Context* ctx, const Node* old) { break; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); - gen_push_values_stack(bb, shd_rewrite_nodes(&ctx->rewriter, old->payload.join.args)); + shd_bld_stack_push_values(bb, shd_rewrite_nodes(&ctx->rewriter, old->payload.join.args)); const Node* jp_payload = prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 2))); - gen_push_value_stack(bb, jp_payload); + shd_bld_stack_push_value(bb, jp_payload); const Node* dst = prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 1))); const Node* tree_node = prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 0))); diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index 444f23878..b28c63825 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -1,6 +1,6 @@ #include "shady/pass.h" - #include "shady/visit.h" +#include "shady/ir/stack.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -31,7 +31,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); if (!ctx2.disable_lowering) { - ctx2.stack_size_on_entry = gen_get_stack_size(bb); + ctx2.stack_size_on_entry = shd_bld_get_stack_size(bb); shd_set_value_name((Node*) ctx2.stack_size_on_entry, shd_format_string_arena(a->arena, "saved_stack_ptr_entering_%s", shd_get_abstraction_name(fun))); } shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), shd_bb_mem(bb)); @@ -47,7 +47,7 @@ static const Node* process(Context* ctx, const Node* node) { if (!ctx->disable_lowering) { assert(ctx->stack_size_on_entry); // Restore SP before calling exit - gen_set_stack_size(bb, ctx->stack_size_on_entry); + shd_bld_set_stack_size(bb, ctx->stack_size_on_entry); } return shd_bld_finish(bb, fn_ret(a, (Return) { .mem = shd_bb_mem(bb), diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 401df0358..c0673e031 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -29,34 +29,6 @@ const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const T })); } -void gen_push_value_stack(BodyBuilder* bb, const Node* value) { - shd_bld_add_instruction_extract(bb, push_stack(shd_get_bb_arena(bb), (PushStack) { .value = value, .mem = shd_bb_mem(bb) })); -} - -void gen_push_values_stack(BodyBuilder* bb, Nodes values) { - for (size_t i = values.count - 1; i < values.count; i--) { - const Node* value = values.nodes[i]; - gen_push_value_stack(bb, value); - } -} - -const Node* gen_pop_value_stack(BodyBuilder* bb, const Type* type) { - const Node* instruction = pop_stack(shd_get_bb_arena(bb), (PopStack) { .type = type, .mem = shd_bb_mem(bb) }); - return shd_first(shd_bld_add_instruction_extract(bb, instruction)); -} - -const Node* gen_get_stack_base_addr(BodyBuilder* bb) { - return get_stack_base_addr(shd_get_bb_arena(bb), (GetStackBaseAddr) { .mem = shd_bb_mem(bb) }); -} - -const Node* gen_get_stack_size(BodyBuilder* bb) { - return shd_first(shd_bld_add_instruction_extract(bb, get_stack_size(shd_get_bb_arena(bb), (GetStackSize) { .mem = shd_bb_mem(bb) }))); -} - -void gen_set_stack_size(BodyBuilder* bb, const Node* new_size) { - shd_bld_add_instruction_extract(bb, set_stack_size(shd_get_bb_arena(bb), (SetStackSize) { .value = new_size, .mem = shd_bb_mem(bb) })); -} - const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { assert(is_type(dst)); return prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = reinterpret_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 26fec1af4..5c9c75a5c 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -4,13 +4,6 @@ #include "shady/ir.h" #include "shady/ir/builtin.h" -void gen_push_value_stack(BodyBuilder* bb, const Node* value); -void gen_push_values_stack(BodyBuilder* bb, Nodes values); -const Node* gen_pop_value_stack(BodyBuilder*, const Type* type); -const Node* gen_get_stack_base_addr(BodyBuilder*); -const Node* gen_get_stack_size(BodyBuilder*); -void gen_set_stack_size(BodyBuilder*, const Node* new_size); - Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); From b2cc958a4d0fddab5d5e859db181c65fec2fb957 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:55:43 +0200 Subject: [PATCH 663/693] move comments & debug printf to debug.h --- include/shady/ir/debug.h | 6 +++++- src/frontend/llvm/l2s_instr.c | 2 +- src/shady/ir/debug.c | 9 +++++++++ src/shady/passes/lower_generic_ptrs.c | 4 ++-- src/shady/passes/lower_physical_ptrs.c | 4 ++-- src/shady/passes/lower_stack.c | 6 +++--- src/shady/passes/lower_tailcalls.c | 12 ++++++------ src/shady/transform/ir_gen_helpers.c | 8 -------- src/shady/transform/ir_gen_helpers.h | 3 --- zhady/shady.i | 5 +++++ 10 files changed, 33 insertions(+), 26 deletions(-) diff --git a/include/shady/ir/debug.h b/include/shady/ir/debug.h index 631619e5f..694ba0178 100644 --- a/include/shady/ir/debug.h +++ b/include/shady/ir/debug.h @@ -1,11 +1,15 @@ #ifndef SHADY_IR_DEBUG_H #define SHADY_IR_DEBUG_H -#include "shady/ir/grammar.h" +#include "shady/ir/base.h" +#include "shady/ir/builder.h" /// Get the name out of a global variable, function or constant String shd_get_value_name_safe(const Node* v); String shd_get_value_name_unsafe(const Node* v); void shd_set_value_name(const Node* var, String name); +void shd_bld_comment(BodyBuilder* bb, String str); +void shd_bld_debug_printf(BodyBuilder* bb, String pattern, Nodes args); + #endif diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 0e0bbd728..b09aae29f 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -571,7 +571,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B if (ops.count == 0) shd_error("DebugPrintf called without arguments"); size_t whocares; - gen_debug_printf(b, LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), shd_nodes(a, ops.count - 1, &ops.nodes[1])); + shd_bld_debug_printf(b, LLVMGetAsString(LLVMGetInitializer(LLVMGetOperand(instr, 0)), &whocares), shd_nodes(a, ops.count - 1, &ops.nodes[1])); return shd_tuple_helper(a, shd_empty(a)); } diff --git a/src/shady/ir/debug.c b/src/shady/ir/debug.c index b92747a27..42690cab9 100644 --- a/src/shady/ir/debug.c +++ b/src/shady/ir/debug.c @@ -1,4 +1,5 @@ #include "shady/ir/debug.h" +#include "shady/ir/grammar.h" #include #include @@ -24,3 +25,11 @@ void shd_set_value_name(const Node* var, String name) { // if (var->tag == Variablez_TAG) // var->payload.varz.name = string(var->arena, name); } + +void shd_bld_comment(BodyBuilder* bb, String str) { + shd_bld_add_instruction_extract(bb, comment(shd_get_bb_arena(bb), (Comment) { .string = str, .mem = shd_bb_mem(bb) })); +} + +void shd_bld_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { + shd_bld_add_instruction(bb, debug_printf(shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = shd_bb_mem(bb) })); +} diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index ce4718241..a1f7271b9 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -108,7 +108,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo switch (which) { case LoadFn: { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_fn)); - gen_comment(bb, "Generated generic ptr store"); + shd_bld_comment(bb, "Generated generic ptr store"); begin_control_t r = shd_bld_begin_control(bb, shd_singleton(t)); const Node* final_loaded_value = shd_first(r.results); @@ -146,7 +146,7 @@ static const Node* get_or_make_access_fn(Context* ctx, WhichFn which, bool unifo } case StoreFn: { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_fn)); - gen_comment(bb, "Generated generic ptr store"); + shd_bld_comment(bb, "Generated generic ptr store"); begin_control_t r = shd_bld_begin_control(bb, shd_empty(a)); LARRAY(const Node*, literals, max_tag); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 662b4d5b5..2a21c4d59 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -94,7 +94,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* widened = acc; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, shd_uint32_type(a), acc); - gen_debug_printf(bb, template, mk_nodes(a, widened, address)); + shd_bld_debug_printf(bb, template, mk_nodes(a, widened, address)); } acc = gen_reinterpret_cast(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = element_type->payload.int_type.is_signed }), acc);\ return acc; @@ -197,7 +197,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element const Node* widened = value; if (element_type->payload.int_type.width < IntTy32) widened = gen_conversion(bb, shd_uint32_type(a), value); - gen_debug_printf(bb, template, mk_nodes(a, widened, address)); + shd_bld_debug_printf(bb, template, mk_nodes(a, widened, address)); } return; } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index b350f1d57..441d6e119 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -75,8 +75,8 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { // store updated stack size shd_bld_store(bb, stack_pointer, stack_size); if (ctx->config->printf_trace.stack_size) { - gen_debug_printf(bb, name, shd_empty(a)); - gen_debug_printf(bb, "stack size after: %d\n", shd_singleton(stack_size)); + shd_bld_debug_printf(bb, name, shd_empty(a)); + shd_bld_debug_printf(bb, "stack size after: %d\n", shd_singleton(stack_size)); } if (push) { @@ -132,7 +132,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* stack_size = shd_bld_load(bb, stack_pointer); const Node* stack_base_ptr = lea_helper(a, ctx->stack, shd_int32_literal(a, 0), shd_singleton(stack_size)); if (ctx->config->printf_trace.stack_size) { - gen_debug_printf(bb, "trace: stack_size=%d\n", shd_singleton(stack_size)); + shd_bld_debug_printf(bb, "trace: stack_size=%d\n", shd_singleton(stack_size)); } return shd_bld_to_instr_yield_values(bb, shd_singleton(stack_base_ptr)); } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 6097ef576..d043047c0 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -315,9 +315,9 @@ static void generate_top_level_dispatch_fn(Context* ctx) { if (ctx->config->printf_trace.god_function) { const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); if (count_iterations) - gen_debug_printf(loop_body_builder, "trace: top loop, thread:%d:%d iteration=%d next_fn=%d next_mask=%lx\n", mk_nodes(a, sid, local_id, iterations_count_param, next_function, next_mask)); + shd_bld_debug_printf(loop_body_builder, "trace: top loop, thread:%d:%d iteration=%d next_fn=%d next_mask=%lx\n", mk_nodes(a, sid, local_id, iterations_count_param, next_function, next_mask)); else - gen_debug_printf(loop_body_builder, "trace: top loop, thread:%d:%d next_fn=%d next_mask=%lx\n", mk_nodes(a, sid, local_id, next_function, next_mask)); + shd_bld_debug_printf(loop_body_builder, "trace: top loop, thread:%d:%d next_fn=%d next_mask=%lx\n", mk_nodes(a, sid, local_id, next_function, next_mask)); } const Node* iteration_count_plus_one = NULL; @@ -354,7 +354,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { BodyBuilder* zero_if_case_builder = shd_bld_begin(a, shd_get_abstraction_mem(zero_if_true_lam)); if (ctx->config->printf_trace.god_function) { const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); - gen_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); + shd_bld_debug_printf(zero_if_case_builder, "trace: kill thread %d:%d\n", mk_nodes(a, sid, local_id)); } shd_set_abstraction_body(zero_if_true_lam, shd_bld_join(zero_if_case_builder, l.break_jp, shd_empty(a))); @@ -362,7 +362,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { BodyBuilder* zero_false_builder = shd_bld_begin(a, shd_get_abstraction_mem(zero_if_false)); if (ctx->config->printf_trace.god_function) { const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, zero_false_builder, BuiltinSubgroupId); - gen_debug_printf(zero_false_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); + shd_bld_debug_printf(zero_false_builder, "trace: thread %d:%d escaped death!\n", mk_nodes(a, sid, local_id)); } shd_set_abstraction_body(zero_if_false, shd_bld_join(zero_false_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); @@ -391,7 +391,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { BodyBuilder* if_builder = shd_bld_begin(a, shd_get_abstraction_mem(if_true_case)); if (ctx->config->printf_trace.god_function) { const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); - gen_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); + shd_bld_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } gen_call(if_builder, fn_addr_helper(a, shd_rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); shd_set_abstraction_body(if_true_case, shd_bld_join(if_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); @@ -432,7 +432,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { shd_destroy_list(jumps); if (ctx->config->printf_trace.god_function) - gen_debug_printf(dispatcher_body_builder, "trace: end of top\n", shd_empty(a)); + shd_bld_debug_printf(dispatcher_body_builder, "trace: end of top\n", shd_empty(a)); shd_set_abstraction_body(*ctx->top_dispatcher_fn, shd_bld_finish(dispatcher_body_builder, fn_ret(a, (Return) { .args = shd_nodes(a, 0, NULL), diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index c0673e031..8fcb47440 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -57,14 +57,6 @@ const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { return prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, lo, hi)); } -void gen_comment(BodyBuilder* bb, String str) { - shd_bld_add_instruction_extract(bb, comment(shd_get_bb_arena(bb), (Comment) { .string = str, .mem = shd_bb_mem(bb) })); -} - -void gen_debug_printf(BodyBuilder* bb, String pattern, Nodes args) { - shd_bld_add_instruction(bb, debug_printf(shd_get_bb_arena(bb), (DebugPrintf) { .string = pattern, .args = args, .mem = shd_bb_mem(bb) })); -} - const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(src->type); diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 5c9c75a5c..4dba8482a 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -11,9 +11,6 @@ const Node* gen_reinterpret_cast(BodyBuilder*, const Type* dst, const Node* src) const Node* gen_conversion(BodyBuilder*, const Type* dst, const Node* src); const Node* gen_merge_halves(BodyBuilder*, const Node* lo, const Node* hi); -void gen_comment(BodyBuilder*, String str); -void gen_debug_printf(BodyBuilder*, String pattern, Nodes args); - const Node* convert_int_extend_according_to_src_t(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_extend_according_to_dst_t(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_zero_extend(BodyBuilder*, const Type* dst_type, const Node* src); diff --git a/zhady/shady.i b/zhady/shady.i index 1b688b2b4..c2af81e8d 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -5,6 +5,11 @@ %module shady %{ #include "shady/ir.h" + +* bb + +* bb + #include "shady/runtime.h" #include "shady/driver.h" #include "shady/config.h" From a5dc1442f0525c5d962c2b1d3aaf530c973be151 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 15:57:02 +0200 Subject: [PATCH 664/693] remove gen_merge_halves --- src/shady/transform/ir_gen_helpers.c | 18 ------------------ src/shady/transform/ir_gen_helpers.h | 1 - 2 files changed, 19 deletions(-) diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 8fcb47440..1a36db39c 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -39,24 +39,6 @@ const Node* gen_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { return prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = convert_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); } -const Node* gen_merge_halves(BodyBuilder* bb, const Node* lo, const Node* hi) { - IrArena* a = shd_get_bb_arena(bb); - const Type* src_type = shd_get_unqualified_type(lo->type); - assert(shd_get_unqualified_type(hi->type) == src_type); - assert(src_type->tag == Int_TAG); - IntSizes size = src_type->payload.int_type.width; - assert(size != IntSizeMax); - const Type* dst_type = int_type(shd_get_bb_arena(bb), (Int) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed }); - // widen them - lo = gen_conversion(bb, dst_type, lo); - hi = gen_conversion(bb, dst_type, hi); - // shift hi - const Node* shift_by = int_literal(shd_get_bb_arena(bb), (IntLiteral) { .width = size + 1, .is_signed = src_type->payload.int_type.is_signed, .value = shd_get_type_bitwidth(src_type) }); - hi = prim_op_helper(a, lshift_op, shd_empty(a), mk_nodes(a, hi, shift_by)); - // Merge the two - return prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, lo, hi)); -} - const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(src->type); diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 4dba8482a..dbb4e085d 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -9,7 +9,6 @@ const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type const Node* gen_reinterpret_cast(BodyBuilder*, const Type* dst, const Node* src); const Node* gen_conversion(BodyBuilder*, const Type* dst, const Node* src); -const Node* gen_merge_halves(BodyBuilder*, const Node* lo, const Node* hi); const Node* convert_int_extend_according_to_src_t(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_extend_according_to_dst_t(BodyBuilder*, const Type* dst_type, const Node* src); From e581a2f6af227a38cbbe24e5bdcc0f5ad3355f26 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:02:38 +0200 Subject: [PATCH 665/693] move reinterpret & convert to cast.h --- include/shady/ir/cast.h | 13 ++++++ include/shady/ir/type.h | 3 -- src/shady/check.c | 2 +- src/shady/ir/CMakeLists.txt | 1 + src/shady/ir/cast.c | 59 ++++++++++++++++++++++++++ src/shady/ir/type.c | 43 ------------------- src/shady/passes/lower_alloca.c | 3 +- src/shady/passes/lower_generic_ptrs.c | 5 ++- src/shady/passes/lower_lea.c | 10 ++--- src/shady/passes/lower_mask.c | 3 +- src/shady/passes/lower_memcpy.c | 11 ++--- src/shady/passes/lower_nullptr.c | 3 +- src/shady/passes/lower_physical_ptrs.c | 15 ++++--- src/shady/passes/lower_stack.c | 5 ++- src/shady/passes/lower_subgroup_ops.c | 5 ++- src/shady/passes/lower_tailcalls.c | 3 +- src/shady/passes/opt_demote_alloca.c | 6 +-- src/shady/transform/ir_gen_helpers.c | 10 ----- src/shady/transform/ir_gen_helpers.h | 3 -- 19 files changed, 113 insertions(+), 90 deletions(-) create mode 100644 include/shady/ir/cast.h create mode 100644 src/shady/ir/cast.c diff --git a/include/shady/ir/cast.h b/include/shady/ir/cast.h new file mode 100644 index 000000000..6d660ed15 --- /dev/null +++ b/include/shady/ir/cast.h @@ -0,0 +1,13 @@ +#ifndef SHADY_IR_CAST_H +#define SHADY_IR_CAST_H + +#include "shady/ir/base.h" +#include "shady/ir/builder.h" + +const Node* shd_bld_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src); +const Node* shd_bld_conversion(BodyBuilder* bb, const Type* dst, const Node* src); + +bool shd_is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type); +bool shd_is_conversion_legal(const Type* src_type, const Type* dst_type); + +#endif diff --git a/include/shady/ir/type.h b/include/shady/ir/type.h index 06bca8cdc..9c4f9471e 100644 --- a/include/shady/ir/type.h +++ b/include/shady/ir/type.h @@ -34,9 +34,6 @@ bool shd_is_ordered_type(const Type*); bool shd_is_physical_ptr_type(const Type* t); bool shd_is_generic_ptr_type(const Type* t); -bool shd_is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type); -bool shd_is_conversion_legal(const Type* src_type, const Type* dst_type); - /// Returns the (possibly qualified) pointee type from a (possibly qualified) ptr type const Type* shd_get_pointee_type(IrArena*, const Type*); diff --git a/src/shady/check.c b/src/shady/check.c index 019f8a510..14b038b21 100644 --- a/src/shady/check.c +++ b/src/shady/check.c @@ -1,5 +1,5 @@ #include "check.h" -#include "shady/ir/memory_layout.h" +#include "shady/ir/cast.h" #include "log.h" #include "ir_private.h" diff --git a/src/shady/ir/CMakeLists.txt b/src/shady/ir/CMakeLists.txt index d811dcd62..4b0b54cd0 100644 --- a/src/shady/ir/CMakeLists.txt +++ b/src/shady/ir/CMakeLists.txt @@ -13,4 +13,5 @@ target_sources(shady PRIVATE debug.c memory_layout.c stack.c + cast.c ) \ No newline at end of file diff --git a/src/shady/ir/cast.c b/src/shady/ir/cast.c new file mode 100644 index 000000000..a4d7f845d --- /dev/null +++ b/src/shady/ir/cast.c @@ -0,0 +1,59 @@ +#include "shady/ir/cast.h" +#include "shady/ir/grammar.h" +#include "shady/ir/type.h" +#include "shady/ir/memory_layout.h" + +#include + +const Node* shd_bld_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { + assert(is_type(dst)); + return prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = reinterpret_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); +} + +const Node* shd_bld_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { + assert(is_type(dst)); + return prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = convert_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); +} + +bool shd_is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type) { + assert(shd_is_data_type(src_type) && shd_is_data_type(dst_type)); + if (src_type == dst_type) + return true; // folding will eliminate those, but we need to pass type-checking first :) + if (!(shd_is_arithm_type(src_type) || src_type->tag == MaskType_TAG || shd_is_physical_ptr_type(src_type))) + return false; + if (!(shd_is_arithm_type(dst_type) || dst_type->tag == MaskType_TAG || shd_is_physical_ptr_type(dst_type))) + return false; + assert(shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)); + // either both pointers need to be in the generic address space, and we're only casting the element type, OR neither can be + if ((shd_is_physical_ptr_type(src_type) && shd_is_physical_ptr_type(dst_type)) && (shd_is_generic_ptr_type(src_type) != shd_is_generic_ptr_type(dst_type))) + return false; + return true; +} + +bool shd_is_conversion_legal(const Type* src_type, const Type* dst_type) { + assert(shd_is_data_type(src_type) && shd_is_data_type(dst_type)); + if (!(shd_is_arithm_type(src_type) || (shd_is_physical_ptr_type(src_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) + return false; + if (!(shd_is_arithm_type(dst_type) || (shd_is_physical_ptr_type(dst_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) + return false; + // we only allow ptr-ptr conversions, use reinterpret otherwise + if (shd_is_physical_ptr_type(src_type) != shd_is_physical_ptr_type(dst_type)) + return false; + // exactly one of the pointers needs to be in the generic address space + if (shd_is_generic_ptr_type(src_type) && shd_is_generic_ptr_type(dst_type)) + return false; + if (src_type->tag == Int_TAG && dst_type->tag == Int_TAG) { + bool changes_sign = src_type->payload.int_type.is_signed != dst_type->payload.int_type.is_signed; + bool changes_width = src_type->payload.int_type.width != dst_type->payload.int_type.width; + if (changes_sign && changes_width) + return false; + } + // element types have to match (use reinterpret_cast for changing it) + if (shd_is_physical_ptr_type(src_type) && shd_is_physical_ptr_type(dst_type)) { + AddressSpace src_as = src_type->payload.ptr_type.address_space; + AddressSpace dst_as = dst_type->payload.ptr_type.address_space; + if (src_type->payload.ptr_type.pointed_type != dst_type->payload.ptr_type.pointed_type) + return false; + } + return true; +} diff --git a/src/shady/ir/type.c b/src/shady/ir/type.c index 1a5b4da04..2ed45ff35 100644 --- a/src/shady/ir/type.c +++ b/src/shady/ir/type.c @@ -241,49 +241,6 @@ bool shd_is_generic_ptr_type(const Type* t) { return as == AsGeneric; } -bool shd_is_reinterpret_cast_legal(const Type* src_type, const Type* dst_type) { - assert(shd_is_data_type(src_type) && shd_is_data_type(dst_type)); - if (src_type == dst_type) - return true; // folding will eliminate those, but we need to pass type-checking first :) - if (!(shd_is_arithm_type(src_type) || src_type->tag == MaskType_TAG || shd_is_physical_ptr_type(src_type))) - return false; - if (!(shd_is_arithm_type(dst_type) || dst_type->tag == MaskType_TAG || shd_is_physical_ptr_type(dst_type))) - return false; - assert(shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)); - // either both pointers need to be in the generic address space, and we're only casting the element type, OR neither can be - if ((shd_is_physical_ptr_type(src_type) && shd_is_physical_ptr_type(dst_type)) && (shd_is_generic_ptr_type(src_type) != shd_is_generic_ptr_type(dst_type))) - return false; - return true; -} - -bool shd_is_conversion_legal(const Type* src_type, const Type* dst_type) { - assert(shd_is_data_type(src_type) && shd_is_data_type(dst_type)); - if (!(shd_is_arithm_type(src_type) || (shd_is_physical_ptr_type(src_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) - return false; - if (!(shd_is_arithm_type(dst_type) || (shd_is_physical_ptr_type(dst_type) && shd_get_type_bitwidth(src_type) == shd_get_type_bitwidth(dst_type)))) - return false; - // we only allow ptr-ptr conversions, use reinterpret otherwise - if (shd_is_physical_ptr_type(src_type) != shd_is_physical_ptr_type(dst_type)) - return false; - // exactly one of the pointers needs to be in the generic address space - if (shd_is_generic_ptr_type(src_type) && shd_is_generic_ptr_type(dst_type)) - return false; - if (src_type->tag == Int_TAG && dst_type->tag == Int_TAG) { - bool changes_sign = src_type->payload.int_type.is_signed != dst_type->payload.int_type.is_signed; - bool changes_width = src_type->payload.int_type.width != dst_type->payload.int_type.width; - if (changes_sign && changes_width) - return false; - } - // element types have to match (use reinterpret_cast for changing it) - if (shd_is_physical_ptr_type(src_type) && shd_is_physical_ptr_type(dst_type)) { - AddressSpace src_as = src_type->payload.ptr_type.address_space; - AddressSpace dst_as = dst_type->payload.ptr_type.address_space; - if (src_type->payload.ptr_type.pointed_type != dst_type->payload.ptr_type.pointed_type) - return false; - } - return true; -} - bool shd_is_addr_space_uniform(IrArena* arena, AddressSpace as) { switch (as) { case AsGeneric: diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index ac3efd143..f8104ecc5 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -1,6 +1,7 @@ #include "shady/pass.h" #include "shady/visit.h" #include "shady/ir/stack.h" +#include "shady/ir/cast.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -147,7 +148,7 @@ static const Node* process(Context* ctx, const Node* node) { const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); const Node* slot = ptr_array_element_offset(a, (PtrArrayElementOffset) { .ptr = ctx->base_stack_addr_on_entry, .offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)) }); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); - slot = gen_reinterpret_cast(bb, ptr_t, slot); + slot = shd_bld_reinterpret_cast(bb, ptr_t, slot); //bool last = found_slot->i == ctx->num_slots - 1; //if (last) { const Node* updated_stack_ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, ctx->frame_size)); diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index a1f7271b9..a30b8a5d4 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/cast.h" #include "shady/ir/memory_layout.h" #include "../ir_private.h" @@ -61,7 +62,7 @@ static const Node* recover_full_pointer(Context* ctx, BodyBuilder* bb, uint64_t // patched_ptr = patched_ptr | sign_extension_patch patched_ptr = prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, patched_ptr, sign_extension_patch)); const Type* dst_ptr_t = ptr_type(a, (PtrType) { .pointed_type = element_type, .address_space = get_addr_space_from_tag(tag) }); - const Node* reinterpreted_ptr = gen_reinterpret_cast(bb, dst_ptr_t, patched_ptr); + const Node* reinterpreted_ptr = shd_bld_reinterpret_cast(bb, dst_ptr_t, patched_ptr); return reinterpreted_ptr; } @@ -246,7 +247,7 @@ static const Node* process(Context* ctx, const Node* old) { // String x = format_string_arena(a->arena, "Generated generic ptr convert src %d tag %d", src_as, tag); // gen_comment(bb, x); const Node* src_ptr = shd_rewrite_node(&ctx->rewriter, old_src); - const Node* generic_ptr = gen_reinterpret_cast(bb, ctx->generic_ptr_type, src_ptr); + const Node* generic_ptr = shd_bld_reinterpret_cast(bb, ctx->generic_ptr_type, src_ptr); const Node* ptr_mask = size_t_literal(a, (UINT64_MAX >> (uint64_t) (generic_ptr_tag_bitwidth))); // generic_ptr = generic_ptr & 0x001111 ... 111 generic_ptr = prim_op_helper(a, and_op, shd_empty(a), mk_nodes(a, generic_ptr, ptr_mask)); diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 350d7d8d7..ddb0f545f 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -1,11 +1,11 @@ #include "shady/pass.h" +#include "shady/ir/cast.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" -#include "shady/ir.h" #include @@ -128,11 +128,11 @@ static const Node* process(Context* ctx, const Node* old) { break; BodyBuilder* bb = shd_bld_begin_pure(a); // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); - const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, shd_rewrite_node(r, lea.ptr)); + const Node* cast_base = shd_bld_reinterpret_cast(bb, emulated_ptr_t, shd_rewrite_node(r, lea.ptr)); const Type* new_base_t = shd_rewrite_node(&ctx->rewriter, old_base_ptr_t); const Node* result = lower_ptr_offset(ctx, bb, new_base_t, cast_base, shd_rewrite_node(r, lea.offset)); const Type* new_ptr_t = shd_rewrite_node(&ctx->rewriter, old_result_t); - const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); + const Node* cast_result = shd_bld_reinterpret_cast(bb, new_ptr_t, result); return shd_bld_to_instr_yield_values(bb, shd_singleton(cast_result)); } case PtrCompositeElement_TAG: { @@ -151,11 +151,11 @@ static const Node* process(Context* ctx, const Node* old) { break; BodyBuilder* bb = shd_bld_begin_pure(a); // Nodes new_ops = rewrite_nodes(&ctx->rewriter, old_ops); - const Node* cast_base = gen_reinterpret_cast(bb, emulated_ptr_t, shd_rewrite_node(r, lea.ptr)); + const Node* cast_base = shd_bld_reinterpret_cast(bb, emulated_ptr_t, shd_rewrite_node(r, lea.ptr)); const Type* new_base_t = shd_rewrite_node(&ctx->rewriter, old_base_ptr_t); const Node* result = lower_ptr_index(ctx, bb, new_base_t, cast_base, shd_rewrite_node(r, lea.index)); const Type* new_ptr_t = shd_rewrite_node(&ctx->rewriter, old_result_t); - const Node* cast_result = gen_reinterpret_cast(bb, new_ptr_t, result); + const Node* cast_result = shd_bld_reinterpret_cast(bb, new_ptr_t, result); return shd_bld_to_instr_yield_values(bb, shd_singleton(cast_result)); } default: break; diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index a74101750..5d333b3bb 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -1,5 +1,6 @@ #include "shady/pass.h" #include "shady/ir/type.h" +#include "shady/ir/cast.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -28,7 +29,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = shd_bld_begin_pure(a); const Node* mask = shd_rewrite_node(&ctx->rewriter, old_nodes.nodes[0]); const Node* index = shd_rewrite_node(&ctx->rewriter, old_nodes.nodes[1]); - index = gen_conversion(bb, shd_get_actual_mask_type(ctx->rewriter.dst_arena), index); + index = shd_bld_conversion(bb, shd_get_actual_mask_type(ctx->rewriter.dst_arena), index); const Node* acc = mask; // acc >>= index acc = prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, acc, index)); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index 8a0fc2855..a2bd9cbce 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/cast.h" #include "shady/ir/memory_layout.h" #include "../transform/ir_gen_helpers.h" @@ -34,7 +35,7 @@ static const Node* process(Context* ctx, const Node* old) { .address_space = dst_addr_type->payload.ptr_type.address_space, .pointed_type = word_type, }); - dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); + dst_addr = shd_bld_reinterpret_cast(bb, dst_addr_type, dst_addr); const Node* src_addr = shd_rewrite_node(&ctx->rewriter, payload.src); const Type* src_addr_type = src_addr->type; @@ -44,10 +45,10 @@ static const Node* process(Context* ctx, const Node* old) { .address_space = src_addr_type->payload.ptr_type.address_space, .pointed_type = word_type, }); - src_addr = gen_reinterpret_cast(bb, src_addr_type, src_addr); + src_addr = shd_bld_reinterpret_cast(bb, src_addr_type, src_addr); const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), shd_rewrite_node(&ctx->rewriter, payload.count)); - const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num_in_bytes)); + const Node* num_in_words = shd_bld_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num_in_bytes)); begin_loop_helper_t l = shd_bld_begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); @@ -91,10 +92,10 @@ static const Node* process(Context* ctx, const Node* old) { .address_space = dst_addr_type->payload.ptr_type.address_space, .pointed_type = word_type, }); - dst_addr = gen_reinterpret_cast(bb, dst_addr_type, dst_addr); + dst_addr = shd_bld_reinterpret_cast(bb, dst_addr_type, dst_addr); const Node* num = shd_rewrite_node(&ctx->rewriter, payload.count); - const Node* num_in_words = gen_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num)); + const Node* num_in_words = shd_bld_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num)); begin_loop_helper_t l = shd_bld_begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 759c1b271..08516d459 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/cast.h" #include "../ir_private.h" #include "../transform/ir_gen_helpers.h" @@ -19,7 +20,7 @@ static const Node* make_nullptr(Context* ctx, const Type* t) { return *found; BodyBuilder* bb = shd_bld_begin_pure(a); - const Node* nul = gen_reinterpret_cast(bb, t, shd_uint64_literal(a, 0)); + const Node* nul = shd_bld_reinterpret_cast(bb, t, shd_uint64_literal(a, 0)); Node* decl = constant(ctx->rewriter.dst_module, shd_singleton(annotation(a, (Annotation) { .name = "Generated", })), t, shd_fmt_string_irarena(a, "nullptr_%s", shd_get_type_name(a, t))); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 2a21c4d59..bf9a1b958 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/cast.h" #include "shady/ir/memory_layout.h" #include "../ir_private.h" @@ -67,7 +68,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type // TODO: add a per-as size configuration const Type* ptr_int_t = int_type(a, (Int) {.width = a->config.memory.ptr_size, .is_signed = false }); const Node* unsigned_int = gen_deserialisation(ctx, bb, ptr_int_t, arr, address); - return gen_reinterpret_cast(bb, element_type, unsigned_int); + return shd_bld_reinterpret_cast(bb, element_type, unsigned_int); } default: shd_error("TODO") } @@ -81,7 +82,7 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type const Node* word_bitwidth = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = word_size_in_bytes * 8 }); for (size_t byte = 0; byte < length_in_bytes; byte += word_size_in_bytes) { const Node* word = shd_bld_load(bb, lea_helper(a, arr, zero, shd_singleton(offset))); - word = gen_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded + word = shd_bld_conversion(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false }), word); // widen/truncate the word we just loaded word = prim_op_helper(a, lshift_op, shd_empty(a), mk_nodes(a, word, shift)); // shift it acc = prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, acc, word)); @@ -93,16 +94,16 @@ static const Node* gen_deserialisation(Context* ctx, BodyBuilder* bb, const Type String template = shd_fmt_string_irarena(a, "loaded %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", shd_get_address_space_name(as), "%lx"); const Node* widened = acc; if (element_type->payload.int_type.width < IntTy32) - widened = gen_conversion(bb, shd_uint32_type(a), acc); + widened = shd_bld_conversion(bb, shd_uint32_type(a), acc); shd_bld_debug_printf(bb, template, mk_nodes(a, widened, address)); } - acc = gen_reinterpret_cast(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = element_type->payload.int_type.is_signed }), acc);\ + acc = shd_bld_reinterpret_cast(bb, int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = element_type->payload.int_type.is_signed }), acc);\ return acc; } case Float_TAG: { const Type* unsigned_int_t = int_type(a, (Int) {.width = shd_float_to_int_width(element_type->payload.float_type.width), .is_signed = false }); const Node* unsigned_int = gen_deserialisation(ctx, bb, unsigned_int_t, arr, address); - return gen_reinterpret_cast(bb, element_type, unsigned_int); + return shd_bld_reinterpret_cast(bb, element_type, unsigned_int); } case TypeDeclRef_TAG: case RecordType_TAG: { @@ -185,7 +186,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element }*/ const Node* word = value; word = (prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, word, shift))); // shift it - word = gen_conversion(bb, int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }), word); // widen/truncate the word we want to store + word = shd_bld_conversion(bb, int_type(a, (Int) { .width = a->config.memory.word_size, .is_signed = false }), word); // widen/truncate the word we want to store shd_bld_store(bb, lea_helper(a, arr, zero, shd_singleton(offset)), word); offset = (prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, offset, size_t_literal(a, 1)))); @@ -196,7 +197,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element String template = shd_fmt_string_irarena(a, "stored %s at %s:0x%s\n", element_type->payload.int_type.width == IntTy64 ? "%lu" : "%u", shd_get_address_space_name(as), "%lx"); const Node* widened = value; if (element_type->payload.int_type.width < IntTy32) - widened = gen_conversion(bb, shd_uint32_type(a), value); + widened = shd_bld_conversion(bb, shd_uint32_type(a), value); shd_bld_debug_printf(bb, template, mk_nodes(a, widened, address)); } return; diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index 441d6e119..dfc399f5a 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/cast.h" #include "shady/ir/memory_layout.h" #include "../ir_private.h" @@ -46,7 +47,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); const Node* element_size = prim_op_helper(a, size_of_op, shd_singleton(element_type), shd_empty(a)); - element_size = gen_conversion(bb, shd_uint32_type(a), element_size); + element_size = shd_bld_conversion(bb, shd_uint32_type(a), element_size); // TODO somehow annotate the uniform guys as uniform const Node* stack_pointer = ctx->stack_pointer; @@ -61,7 +62,7 @@ static const Node* gen_fn(Context* ctx, const Type* element_type, bool push) { assert(shd_get_unqualified_type(addr->type)->tag == PtrType_TAG); AddressSpace addr_space = shd_get_unqualified_type(addr->type)->payload.ptr_type.address_space; - addr = gen_reinterpret_cast(bb, ptr_type(a, (PtrType) {.address_space = addr_space, .pointed_type = element_type}), addr); + addr = shd_bld_reinterpret_cast(bb, ptr_type(a, (PtrType) { .address_space = addr_space, .pointed_type = element_type }), addr); const Node* popped_value = NULL; if (push) diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 62cf77995..953d47a57 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/cast.h" #include "shady/ir/memory_layout.h" #include "../transform/ir_gen_helpers.h" @@ -75,8 +76,8 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co break; } case Type_PtrType_TAG: { - param = gen_reinterpret_cast(bb, shd_uint64_type(a), param); - return gen_reinterpret_cast(bb, t, generate(ctx, bb, scope, shd_uint64_type(a), param)); + param = shd_bld_reinterpret_cast(bb, shd_uint64_type(a), param); + return shd_bld_reinterpret_cast(bb, t, generate(ctx, bb, scope, shd_uint64_type(a), param)); } default: break; } diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index d043047c0..391e6fd12 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -2,6 +2,7 @@ #include "shady/pass.h" #include "shady/ir/stack.h" +#include "shady/ir/cast.h" #include "../ir_private.h" @@ -215,7 +216,7 @@ static const Node* process(Context* ctx, const Node* old) { BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); shd_bld_stack_push_values(bb, shd_rewrite_nodes(&ctx->rewriter, payload.args)); const Node* target = shd_rewrite_node(&ctx->rewriter, payload.callee); - target = gen_conversion(bb, shd_uint32_type(a), target); + target = shd_bld_conversion(bb, shd_uint32_type(a), target); gen_call(bb, get_fn(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); return shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) })); diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 5ba0c27cb..c6b495048 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -1,6 +1,6 @@ #include "shady/pass.h" - #include "shady/visit.h" +#include "shady/ir/cast.h" #include "../ir_private.h" #include "../check.h" @@ -200,7 +200,7 @@ static const Node* process(Context* ctx, const Node* old) { *ctx->todo |= true; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); const Node* data = shd_bld_load(bb, k.src_alloca->new); - data = gen_reinterpret_cast(bb, access_type, data); + data = shd_bld_reinterpret_cast(bb, access_type, data); return shd_bld_to_instr_yield_value(bb, data); } } @@ -217,7 +217,7 @@ static const Node* process(Context* ctx, const Node* old) { break; *ctx->todo |= true; BodyBuilder* bb = shd_bld_begin(a, shd_rewrite_node(r, payload.mem)); - const Node* data = gen_reinterpret_cast(bb, access_type, shd_rewrite_node(r, payload.value)); + const Node* data = shd_bld_reinterpret_cast(bb, access_type, shd_rewrite_node(r, payload.value)); shd_bld_store(bb, k.src_alloca->new, data); return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 1a36db39c..84a1d9b75 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -29,16 +29,6 @@ const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const T })); } -const Node* gen_reinterpret_cast(BodyBuilder* bb, const Type* dst, const Node* src) { - assert(is_type(dst)); - return prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = reinterpret_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); -} - -const Node* gen_conversion(BodyBuilder* bb, const Type* dst, const Node* src) { - assert(is_type(dst)); - return prim_op(shd_get_bb_arena(bb), (PrimOp) { .op = convert_op, .operands = shd_singleton(src), .type_arguments = shd_singleton(dst)}); -} - const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(src->type); diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index dbb4e085d..3ea6dcd8e 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -7,9 +7,6 @@ Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); -const Node* gen_reinterpret_cast(BodyBuilder*, const Type* dst, const Node* src); -const Node* gen_conversion(BodyBuilder*, const Type* dst, const Node* src); - const Node* convert_int_extend_according_to_src_t(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_extend_according_to_dst_t(BodyBuilder*, const Type* dst_type, const Node* src); const Node* convert_int_zero_extend(BodyBuilder*, const Type* dst_type, const Node* src); From 336796e401bec81eff507d08fa663a873ef85db8 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:05:47 +0200 Subject: [PATCH 666/693] put int conversion stuff in int.h --- include/shady/ir/int.h | 6 +++ src/shady/ir/int.c | 61 +++++++++++++++++++++++++- src/shady/passes/lower_alloca.c | 4 +- src/shady/passes/lower_lea.c | 4 +- src/shady/passes/lower_memcpy.c | 2 +- src/shady/passes/lower_physical_ptrs.c | 2 +- src/shady/passes/lower_subgroup_ops.c | 8 ++-- src/shady/transform/ir_gen_helpers.c | 58 ------------------------ src/shady/transform/ir_gen_helpers.h | 5 --- 9 files changed, 76 insertions(+), 74 deletions(-) diff --git a/include/shady/ir/int.h b/include/shady/ir/int.h index 0ef5679b3..57f65df37 100644 --- a/include/shady/ir/int.h +++ b/include/shady/ir/int.h @@ -2,6 +2,7 @@ #define SHADY_IR_INT_H #include "shady/ir/grammar.h" +#include "shady/ir/builder.h" static inline int int_size_in_bytes(IntSizes s) { switch (s) { @@ -37,4 +38,9 @@ const Node* shd_uint64_literal(IrArena* arena, uint64_t u); const IntLiteral* shd_resolve_to_int_literal(const Node* node); int64_t shd_get_int_literal_value(IntLiteral literal, bool sign_extend); +const Node* shd_bld_convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src); +const Node* shd_bld_convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* dst_type, const Node* src); +const Node* shd_bld_convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const Node* src); +const Node* shd_bld_convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, const Node* src); + #endif diff --git a/src/shady/ir/int.c b/src/shady/ir/int.c index 5cdd8a032..943d83d66 100644 --- a/src/shady/ir/int.c +++ b/src/shady/ir/int.c @@ -1,4 +1,5 @@ #include "shady/ir/int.h" +#include "shady/ir/type.h" #include "shady/analysis/literal.h" @@ -53,4 +54,62 @@ int64_t shd_get_int_literal_value(IntLiteral literal, bool sign_extend) { default: assert(false); } } -} \ No newline at end of file +} + +const Node* shd_bld_convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { + IrArena* a = shd_get_bb_arena(bb); + const Type* src_type = shd_get_unqualified_type(src->type); + assert(src_type->tag == Int_TAG); + assert(dst_type->tag == Int_TAG); + + // first convert to final bitsize then bitcast + const Type* extended_src_t = int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = src_type->payload.int_type.is_signed }); + const Node* val = src; + val = prim_op_helper(a, convert_op, shd_singleton(extended_src_t), shd_singleton(val)); + val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); + return val; +} + +const Node* shd_bld_convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { + IrArena* a = shd_get_bb_arena(bb); + const Type* src_type = shd_get_unqualified_type(src->type); + assert(src_type->tag == Int_TAG); + assert(dst_type->tag == Int_TAG); + + // first bitcast then convert to final bitsize + const Type* reinterpreted_src_t = int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = dst_type->payload.int_type.is_signed }); + const Node* val = src; + val = prim_op_helper(a, reinterpret_op, shd_singleton(reinterpreted_src_t), shd_singleton(val)); + val = prim_op_helper(a, convert_op, shd_singleton(dst_type), shd_singleton(val)); + return val; +} + +const Node* shd_bld_convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { + IrArena* a = shd_get_bb_arena(bb); + const Type* src_type = shd_get_unqualified_type(src->type); + assert(src_type->tag == Int_TAG); + assert(dst_type->tag == Int_TAG); + + const Node* val = src; + val = prim_op_helper(a, reinterpret_op, shd_singleton( + int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); + val = prim_op_helper(a, convert_op, shd_singleton( + int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); + val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); + return val; +} + +const Node* shd_bld_convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { + IrArena* a = shd_get_bb_arena(bb); + const Type* src_type = shd_get_unqualified_type(src->type); + assert(src_type->tag == Int_TAG); + assert(dst_type->tag == Int_TAG); + + const Node* val = src; + val = prim_op_helper(a, reinterpret_op, shd_singleton( + int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); + val = prim_op_helper(a, convert_op, shd_singleton( + int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); + val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); + return val; +} diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index f8104ecc5..9bed08865 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -118,7 +118,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_destroy_list(vctx.members); ctx2.num_slots = vctx.num_slots; ctx2.frame_size = prim_op_helper(a, size_of_op, shd_singleton(type_decl_ref_helper(a, vctx.nom_t)), shd_empty(a)); - ctx2.frame_size = convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); + ctx2.frame_size = shd_bld_convert_int_extend_according_to_src_t(bb, ctx->stack_ptr_t, ctx2.frame_size); // make sure to use the new mem from then on shd_register_processed(r, shd_get_abstraction_mem(node), shd_bb_mem(bb)); @@ -145,7 +145,7 @@ static const Node* process(Context* ctx, const Node* node) { } //const Node* lea_instr = prim_op_helper(a, lea_op, empty(a), mk_nodes(a, rewrite_node(&ctx->rewriter, first(node->payload.prim_op.operands)), found_slot->offset)); - const Node* converted_offset = convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); + const Node* converted_offset = shd_bld_convert_int_extend_according_to_dst_t(bb, ctx->stack_ptr_t, found_slot->offset); const Node* slot = ptr_array_element_offset(a, (PtrArrayElementOffset) { .ptr = ctx->base_stack_addr_on_entry, .offset = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ctx->stack_size_on_entry, converted_offset)) }); const Node* ptr_t = ptr_type(a, (PtrType) { .pointed_type = found_slot->type, .address_space = found_slot->as }); slot = shd_bld_reinterpret_cast(bb, ptr_t, slot); diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index ddb0f545f..24626d97d 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -40,7 +40,7 @@ static const Node* lower_ptr_index(Context* ctx, BodyBuilder* bb, const Type* po const Node* element_t_size = prim_op_helper(a, size_of_op, shd_singleton(element_type), shd_empty(a)); - const Node* new_index = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, index); + const Node* new_index = shd_bld_convert_int_extend_according_to_src_t(bb, emulated_ptr_t, index); const Node* physical_offset = prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, new_index, element_t_size)); ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ptr, physical_offset)); @@ -96,7 +96,7 @@ static const Node* lower_ptr_offset(Context* ctx, BodyBuilder* bb, const Type* p const Node* element_t_size = prim_op_helper(a, size_of_op, shd_singleton(element_type), shd_empty(a)); - const Node* new_offset = convert_int_extend_according_to_src_t(bb, emulated_ptr_t, offset); + const Node* new_offset = shd_bld_convert_int_extend_according_to_src_t(bb, emulated_ptr_t, offset); const Node* physical_offset = prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, new_offset, element_t_size)); ptr = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, ptr, physical_offset)); diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index a2bd9cbce..a6bee73f5 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -47,7 +47,7 @@ static const Node* process(Context* ctx, const Node* old) { }); src_addr = shd_bld_reinterpret_cast(bb, src_addr_type, src_addr); - const Node* num_in_bytes = convert_int_extend_according_to_dst_t(bb, size_t_type(a), shd_rewrite_node(&ctx->rewriter, payload.count)); + const Node* num_in_bytes = shd_bld_convert_int_extend_according_to_dst_t(bb, size_t_type(a), shd_rewrite_node(&ctx->rewriter, payload.count)); const Node* num_in_words = shd_bld_conversion(bb, shd_uint32_type(a), shd_bytes_to_words(bb, num_in_bytes)); begin_loop_helper_t l = shd_bld_begin_loop_helper(bb, shd_empty(a), shd_singleton(shd_uint32_type(a)), shd_singleton(shd_uint32_literal(a, 0))); diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index bf9a1b958..82de6ed89 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -166,7 +166,7 @@ static void gen_serialisation(Context* ctx, BodyBuilder* bb, const Type* element assert(element_type->tag == Int_TAG); // First bitcast to unsigned so we always get zero-extension and not sign-extension afterwards const Type* element_t_unsigned = int_type(a, (Int) { .width = element_type->payload.int_type.width, .is_signed = false}); - value = convert_int_extend_according_to_src_t(bb, element_t_unsigned, value); + value = shd_bld_convert_int_extend_according_to_src_t(bb, element_t_unsigned, value); // const Node* acc = int_literal(a, (IntLiteral) { .width = element_type->payload.int_type.width, .is_signed = false, .value = 0 }); size_t length_in_bytes = int_size_in_bytes(element_type->payload.int_type.width); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 953d47a57..6714a365e 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -63,13 +63,13 @@ static const Node* generate(Context* ctx, BodyBuilder* bb, const Node* scope, co case Type_Int_TAG: { if (t->payload.int_type.width == IntTy64) { const Node* hi = prim_op_helper(a, rshift_logical_op, shd_empty(a), mk_nodes(a, param, shd_int32_literal(a, 32))); - hi = convert_int_zero_extend(bb, shd_int32_type(a), hi); - const Node* lo = convert_int_zero_extend(bb, shd_int32_type(a), param); + hi = shd_bld_convert_int_zero_extend(bb, shd_int32_type(a), hi); + const Node* lo = shd_bld_convert_int_zero_extend(bb, shd_int32_type(a), param); hi = build_subgroup_first(ctx, bb, scope, hi); lo = build_subgroup_first(ctx, bb, scope, lo); const Node* it = int_type(a, (Int) { .width = IntTy64, .is_signed = t->payload.int_type.is_signed }); - hi = convert_int_zero_extend(bb, it, hi); - lo = convert_int_zero_extend(bb, it, lo); + hi = shd_bld_convert_int_zero_extend(bb, it, hi); + lo = shd_bld_convert_int_zero_extend(bb, it, lo); hi = prim_op_helper(a, lshift_op, shd_empty(a), mk_nodes(a, hi, shd_int32_literal(a, 32))); return prim_op_helper(a, or_op, shd_empty(a), mk_nodes(a, lo, hi)); } diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 84a1d9b75..53e2a03d9 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -28,61 +28,3 @@ const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const T .operands = operands, })); } - -const Node* convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { - IrArena* a = shd_get_bb_arena(bb); - const Type* src_type = shd_get_unqualified_type(src->type); - assert(src_type->tag == Int_TAG); - assert(dst_type->tag == Int_TAG); - - // first convert to final bitsize then bitcast - const Type* extended_src_t = int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = src_type->payload.int_type.is_signed }); - const Node* val = src; - val = prim_op_helper(a, convert_op, shd_singleton(extended_src_t), shd_singleton(val)); - val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); - return val; -} - -const Node* convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { - IrArena* a = shd_get_bb_arena(bb); - const Type* src_type = shd_get_unqualified_type(src->type); - assert(src_type->tag == Int_TAG); - assert(dst_type->tag == Int_TAG); - - // first bitcast then convert to final bitsize - const Type* reinterpreted_src_t = int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = dst_type->payload.int_type.is_signed }); - const Node* val = src; - val = prim_op_helper(a, reinterpret_op, shd_singleton(reinterpreted_src_t), shd_singleton(val)); - val = prim_op_helper(a, convert_op, shd_singleton(dst_type), shd_singleton(val)); - return val; -} - -const Node* convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { - IrArena* a = shd_get_bb_arena(bb); - const Type* src_type = shd_get_unqualified_type(src->type); - assert(src_type->tag == Int_TAG); - assert(dst_type->tag == Int_TAG); - - const Node* val = src; - val = prim_op_helper(a, reinterpret_op, shd_singleton( - int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); - val = prim_op_helper(a, convert_op, shd_singleton( - int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = false })), shd_singleton(val)); - val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); - return val; -} - -const Node* convert_int_sign_extend(BodyBuilder* bb, const Type* dst_type, const Node* src) { - IrArena* a = shd_get_bb_arena(bb); - const Type* src_type = shd_get_unqualified_type(src->type); - assert(src_type->tag == Int_TAG); - assert(dst_type->tag == Int_TAG); - - const Node* val = src; - val = prim_op_helper(a, reinterpret_op, shd_singleton( - int_type(shd_get_bb_arena(bb), (Int) { .width = src_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); - val = prim_op_helper(a, convert_op, shd_singleton( - int_type(shd_get_bb_arena(bb), (Int) { .width = dst_type->payload.int_type.width, .is_signed = true })), shd_singleton(val)); - val = prim_op_helper(a, reinterpret_op, shd_singleton(dst_type), shd_singleton(val)); - return val; -} diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 3ea6dcd8e..05248ef85 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -7,9 +7,4 @@ Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); -const Node* convert_int_extend_according_to_src_t(BodyBuilder*, const Type* dst_type, const Node* src); -const Node* convert_int_extend_according_to_dst_t(BodyBuilder*, const Type* dst_type, const Node* src); -const Node* convert_int_zero_extend(BodyBuilder*, const Type* dst_type, const Node* src); -const Node* convert_int_sign_extend(BodyBuilder*, const Type* dst_type, const Node* src); - #endif From 2f2c5a9723766cbc262fa55686d3c3a8862aaaf6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:06:30 +0200 Subject: [PATCH 667/693] put call builder in function.h --- include/shady/ir/function.h | 2 ++ src/shady/ir/function.c | 6 ++++++ src/shady/passes/lower_physical_ptrs.c | 6 +++--- src/shady/passes/lower_stack.c | 4 ++-- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/lower_tailcalls.c | 18 +++++++++--------- src/shady/passes/lower_workgroups.c | 2 +- src/shady/transform/ir_gen_helpers.c | 6 ------ src/shady/transform/ir_gen_helpers.h | 1 - 9 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/shady/ir/function.h b/include/shady/ir/function.h index dfbb2ceea..126eca4a6 100644 --- a/include/shady/ir/function.h +++ b/include/shady/ir/function.h @@ -27,4 +27,6 @@ String shd_get_abstraction_name_safe(const Node* abs); void shd_set_abstraction_body(Node* abs, const Node* body); +Nodes shd_bld_call(BodyBuilder* bb, const Node* callee, Nodes args); + #endif diff --git a/src/shady/ir/function.c b/src/shady/ir/function.c index 75150bf9f..bb37a4b85 100644 --- a/src/shady/ir/function.c +++ b/src/shady/ir/function.c @@ -142,3 +142,9 @@ void shd_set_abstraction_body(Node* abs, const Node* body) { default: assert(false); } } + +Nodes shd_bld_call(BodyBuilder* bb, const Node* callee, Nodes args) { + assert(shd_get_arena_config(shd_get_bb_arena(bb))->check_types); + const Node* instruction = call(shd_get_bb_arena(bb), (Call) { .callee = callee, .args = args, .mem = shd_bb_mem(bb) }); + return shd_bld_add_instruction_extract(bb, instruction); +} diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 82de6ed89..597c456d3 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -302,7 +302,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Type* element_type = shd_rewrite_node(&ctx->rewriter, ptr_type->payload.ptr_type.pointed_type); const Node* pointer_as_offset = shd_rewrite_node(&ctx->rewriter, payload.ptr); const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, false, ptr_type->payload.ptr_type.address_space); - Nodes results = gen_call(bb, fn_addr_helper(a, fn), shd_singleton(pointer_as_offset)); + Nodes results = shd_bld_call(bb, fn_addr_helper(a, fn), shd_singleton(pointer_as_offset)); return shd_bld_to_instr_yield_values(bb, results); } case Store_TAG: { @@ -319,7 +319,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* fn = gen_serdes_fn(ctx, element_type, uniform_ptr, true, ptr_type->payload.ptr_type.address_space); const Node* value = shd_rewrite_node(&ctx->rewriter, payload.value); - gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, pointer_as_offset, value)); + shd_bld_call(bb, fn_addr_helper(a, fn), mk_nodes(a, pointer_as_offset, value)); return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } case StackAlloc_TAG: shd_error("This needs to be lowered (see setup_stack_frames.c)") @@ -435,7 +435,7 @@ static void store_init_data(Context* ctx, AddressSpace as, Nodes collected, Body if (old_init) { const Node* value = shd_rewrite_node(r, old_init); const Node* fn = gen_serdes_fn(ctx, shd_get_unqualified_type(value->type), false, true, old_decl->payload.global_variable.address_space); - gen_call(bb, fn_addr_helper(a, fn), mk_nodes(a, shd_rewrite_node(r, ref_decl_helper(oa, old_decl)), value)); + shd_bld_call(bb, fn_addr_helper(a, fn), mk_nodes(a, shd_rewrite_node(r, ref_decl_helper(oa, old_decl)), value)); } } } diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index dfc399f5a..aa5d6a947 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -147,7 +147,7 @@ static const Node* process_node(Context* ctx, const Node* old) { const Node* fn = gen_fn(ctx, element_type, push); Nodes args = shd_singleton(shd_rewrite_node(&ctx->rewriter, old->payload.push_stack.value)); - gen_call(bb, fn_addr_helper(a, fn), args); + shd_bld_call(bb, fn_addr_helper(a, fn), args); return shd_bld_to_instr_yield_values(bb, shd_empty(a)); } @@ -160,7 +160,7 @@ static const Node* process_node(Context* ctx, const Node* old) { bool push = false; const Node* fn = gen_fn(ctx, element_type, push); - Nodes results = gen_call(bb, fn_addr_helper(a, fn), shd_empty(a)); + Nodes results = shd_bld_call(bb, fn_addr_helper(a, fn), shd_empty(a)); assert(results.count == 1); return shd_bld_to_instr_yield_values(bb, results); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 6714a365e..326991b92 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -125,7 +125,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod build_fn_body(ctx, fn, scope, src_param, t); } - return shd_first(gen_call(bb, fn_addr_helper(a, fn), shd_singleton(src))); + return shd_first(shd_bld_call(bb, fn_addr_helper(a, fn), shd_singleton(src))); } static const Node* process(Context* ctx, const Node* node) { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 391e6fd12..c7b8d5d7c 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -85,8 +85,8 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_entry_pt)); - gen_call(bb, fn_addr_helper(a, ctx->init_fn), shd_empty(a)); - gen_call(bb, get_fn(&ctx->rewriter, "builtin_init_scheduler"), shd_empty(a)); + shd_bld_call(bb, fn_addr_helper(a, ctx->init_fn), shd_empty(a)); + shd_bld_call(bb, get_fn(&ctx->rewriter, "builtin_init_scheduler"), shd_empty(a)); // shove the arguments on the stack for (size_t i = rewritten_params.count - 1; i < rewritten_params.count; i--) { @@ -97,13 +97,13 @@ static void lift_entry_point(Context* ctx, const Node* old, const Node* fun) { const Node* jump_fn = get_fn(&ctx->rewriter, "builtin_fork"); const Node* fn_addr = shd_uint32_literal(a, get_fn_ptr(ctx, old)); // fn_addr = gen_conversion(bb, lowered_fn_type(ctx), fn_addr); - gen_call(bb, jump_fn, shd_singleton(fn_addr)); + shd_bld_call(bb, jump_fn, shd_singleton(fn_addr)); if (!*ctx->top_dispatcher_fn) { *ctx->top_dispatcher_fn = function(ctx->rewriter.dst_module, shd_nodes(a, 0, NULL), "top_dispatcher", mk_nodes(a, annotation(a, (Annotation) { .name = "Generated" }), annotation(a, (Annotation) { .name = "Leaf" })), shd_nodes(a, 0, NULL)); } - gen_call(bb, fn_addr_helper(a, *ctx->top_dispatcher_fn), shd_empty(a)); + shd_bld_call(bb, fn_addr_helper(a, *ctx->top_dispatcher_fn), shd_empty(a)); shd_set_abstraction_body(new_entry_pt, shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_nodes(a, 0, NULL), @@ -130,7 +130,7 @@ static const Node* process(Context* ctx, const Node* old) { if (old->payload.fun.body) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); if (entry_point_annotation) { - gen_call(bb, fn_addr_helper(a, ctx2.init_fn), shd_empty(a)); + shd_bld_call(bb, fn_addr_helper(a, ctx2.init_fn), shd_empty(a)); } shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), shd_bb_mem(bb)); shd_set_abstraction_body(fun, shd_bld_finish(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); @@ -218,7 +218,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* target = shd_rewrite_node(&ctx->rewriter, payload.callee); target = shd_bld_conversion(bb, shd_uint32_type(a), target); - gen_call(bb, get_fn(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); + shd_bld_call(bb, get_fn(&ctx->rewriter, "builtin_fork"), shd_singleton(target)); return shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) })); } case Join_TAG: { @@ -239,7 +239,7 @@ static const Node* process(Context* ctx, const Node* old) { const Node* dst = prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 1))); const Node* tree_node = prim_op_helper(a, extract_op, shd_empty(a), mk_nodes(a, jp, shd_int32_literal(a, 0))); - gen_call(bb, get_fn(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); + shd_bld_call(bb, get_fn(&ctx->rewriter, "builtin_join"), mk_nodes(a, dst, tree_node)); return shd_bld_finish(bb, fn_ret(a, (Return) { .args = shd_empty(a), .mem = shd_bb_mem(bb) })); } case PtrType_TAG: { @@ -309,7 +309,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { const Node* next_function = shd_bld_load(loop_body_builder, ref_decl_helper(a, shd_find_or_process_decl(&ctx->rewriter, "next_fn"))); const Node* get_active_branch_fn = get_fn(&ctx->rewriter, "builtin_get_active_branch"); - const Node* next_mask = shd_first(gen_call(loop_body_builder, get_active_branch_fn, shd_empty(a))); + const Node* next_mask = shd_first(shd_bld_call(loop_body_builder, get_active_branch_fn, shd_empty(a))); const Node* local_id = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupLocalInvocationId); const Node* should_run = prim_op_helper(a, mask_is_thread_active_op, shd_empty(a), mk_nodes(a, next_mask, local_id)); @@ -394,7 +394,7 @@ static void generate_top_level_dispatch_fn(Context* ctx) { const Node* sid = shd_bld_builtin_load(ctx->rewriter.dst_module, loop_body_builder, BuiltinSubgroupId); shd_bld_debug_printf(if_builder, "trace: thread %d:%d will run fn %u with mask = %lx\n", mk_nodes(a, sid, local_id, fn_lit, next_mask)); } - gen_call(if_builder, fn_addr_helper(a, shd_rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); + shd_bld_call(if_builder, fn_addr_helper(a, shd_rewrite_node(&ctx->rewriter, decl)), shd_empty(a)); shd_set_abstraction_body(if_true_case, shd_bld_join(if_builder, l.continue_jp, count_iterations ? shd_singleton(iteration_count_plus_one) : shd_empty(a))); Node* if_false = case_(a, shd_empty(a)); diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index dc55ef30d..fdf882bd2 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -139,7 +139,7 @@ static const Node* process(Context* ctx, const Node* node) { global_id[dim] = prim_op_helper(a, add_op, shd_empty(a), mk_nodes(a, prim_op_helper(a, mul_op, shd_empty(a), mk_nodes(a, shd_uint32_literal(a, a->config.specializations.workgroup_size[dim]), workgroup_id[dim])), local_id[dim])); shd_bld_store(bb2, ref_decl_helper(a, shd_rewrite_node(&ctx->rewriter, shd_get_or_create_builtin(ctx->rewriter.src_module, BuiltinGlobalInvocationId, NULL))), composite_helper(a, pack_type(a, (PackType) { .element_type = shd_uint32_type(a), .width = 3 }), mk_nodes(a, global_id[0], global_id[1], global_id[2]))); // TODO: write the subgroup ID - gen_call(bb2, fn_addr_helper(a, inner), wparams); + shd_bld_call(bb2, fn_addr_helper(a, inner), wparams); // Wrap in 3 loops for iterating over subgroups, then again for workgroups for (unsigned scope = 1; scope < 2; scope--) { diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index 53e2a03d9..c2e2bbc7c 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -13,12 +13,6 @@ #include #include -Nodes gen_call(BodyBuilder* bb, const Node* callee, Nodes args) { - assert(shd_get_arena_config(shd_get_bb_arena(bb))->check_types); - const Node* instruction = call(shd_get_bb_arena(bb), (Call) { .callee = callee, .args = args, .mem = shd_bb_mem(bb) }); - return shd_bld_add_instruction_extract(bb, instruction); -} - const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { return shd_bld_add_instruction(bb, ext_instr(shd_get_bb_arena(bb), (ExtInstr) { .mem = shd_bb_mem(bb), diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 05248ef85..2c1f2ec75 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -4,7 +4,6 @@ #include "shady/ir.h" #include "shady/ir/builtin.h" -Nodes gen_call(BodyBuilder*, const Node* callee, Nodes args); const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); #endif From 4d2b96c636c51000792147c466093f7bef84ab93 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:09:45 +0200 Subject: [PATCH 668/693] add shady/ir/ext.h for external intrinsics --- include/shady/ir/ext.h | 9 +++++++++ src/frontend/slim/parser.c | 2 ++ src/shady/ir/CMakeLists.txt | 1 + src/shady/ir/ext.c | 12 ++++++++++++ src/shady/passes/lift_indirect_targets.c | 1 + src/shady/passes/lower_callf.c | 4 +++- src/shady/passes/lower_subgroup_ops.c | 1 + src/shady/passes/scope_heuristic.c | 1 + src/shady/transform/ir_gen_helpers.c | 12 +----------- src/shady/transform/ir_gen_helpers.h | 2 -- 10 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 include/shady/ir/ext.h create mode 100644 src/shady/ir/ext.c diff --git a/include/shady/ir/ext.h b/include/shady/ir/ext.h new file mode 100644 index 000000000..990728db0 --- /dev/null +++ b/include/shady/ir/ext.h @@ -0,0 +1,9 @@ +#ifndef SHADY_IR_EXT_H +#define SHADY_IR_EXT_H + +#include "shady/ir/base.h" +#include "shady/ir/builder.h" + +const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); + +#endif diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 1ec1230ce..6434ec6b4 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -1,6 +1,8 @@ #include "parser.h" #include "token.h" +#include "shady/ir/ext.h" + #include "list.h" #include "portability.h" #include "log.h" diff --git a/src/shady/ir/CMakeLists.txt b/src/shady/ir/CMakeLists.txt index 4b0b54cd0..875f9e8b8 100644 --- a/src/shady/ir/CMakeLists.txt +++ b/src/shady/ir/CMakeLists.txt @@ -14,4 +14,5 @@ target_sources(shady PRIVATE memory_layout.c stack.c cast.c + ext.c ) \ No newline at end of file diff --git a/src/shady/ir/ext.c b/src/shady/ir/ext.c new file mode 100644 index 000000000..c5b8eab71 --- /dev/null +++ b/src/shady/ir/ext.c @@ -0,0 +1,12 @@ +#include "shady/ir/ext.h" +#include "shady/ir/grammar.h" + +const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { + return shd_bld_add_instruction(bb, ext_instr(shd_get_bb_arena(bb), (ExtInstr) { + .mem = shd_bb_mem(bb), + .set = set, + .opcode = opcode, + .result_t = return_t, + .operands = operands, + })); +} diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 8aa396796..5818eaa40 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -3,6 +3,7 @@ #include "shady/pass.h" #include "shady/visit.h" #include "shady/ir/stack.h" +#include "shady/ir/ext.h" #include "../ir_private.h" diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index bafdfd07a..c97158994 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -1,6 +1,8 @@ -#include "shady/pass.h" #include "join_point_ops.h" +#include "shady/pass.h" +#include "shady/ir/ext.h" + #include "../transform/ir_gen_helpers.h" #include "log.h" diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 326991b92..d939f17b6 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -1,6 +1,7 @@ #include "shady/pass.h" #include "shady/ir/cast.h" #include "shady/ir/memory_layout.h" +#include "shady/ir/ext.h" #include "../transform/ir_gen_helpers.h" diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index e558a4241..22093832a 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -1,4 +1,5 @@ #include "shady/pass.h" +#include "shady/ir/ext.h" #include "../ir_private.h" #include "../analysis/cfg.h" diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c index c2e2bbc7c..2784fafda 100644 --- a/src/shady/transform/ir_gen_helpers.c +++ b/src/shady/transform/ir_gen_helpers.c @@ -11,14 +11,4 @@ #include "util.h" #include -#include - -const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { - return shd_bld_add_instruction(bb, ext_instr(shd_get_bb_arena(bb), (ExtInstr) { - .mem = shd_bb_mem(bb), - .set = set, - .opcode = opcode, - .result_t = return_t, - .operands = operands, - })); -} +#include \ No newline at end of file diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h index 2c1f2ec75..636ca0a97 100644 --- a/src/shady/transform/ir_gen_helpers.h +++ b/src/shady/transform/ir_gen_helpers.h @@ -4,6 +4,4 @@ #include "shady/ir.h" #include "shady/ir/builtin.h" -const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); - #endif From 293fc6d8b2b46e3e702e8378a00656644323621b Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:20:27 +0200 Subject: [PATCH 669/693] removed ir_gen_helper --- src/backend/c/emit_c.c | 1 - src/backend/c/emit_c_value.c | 1 - src/backend/spirv/emit_spv_value.c | 2 +- src/backend/spirv/spirv_lift_globals_ssbo.c | 5 +++-- src/backend/spirv/spirv_map_entrypoint_args.c | 4 ++-- src/frontend/llvm/l2s_instr.c | 2 -- src/frontend/llvm/l2s_value.c | 2 -- src/frontend/slim/infer.c | 1 - src/frontend/slim/parser.c | 1 - src/frontend/spirv/s2s.c | 1 - src/shady/body_builder.c | 7 +++++-- src/shady/fold.c | 1 - src/shady/ir/builtin.c | 4 ++-- src/shady/ir/composite.c | 1 - src/shady/ir/memory_layout.c | 4 ++-- src/shady/passes/lift_everything.c | 1 - src/shady/passes/lift_indirect_targets.c | 1 - src/shady/passes/lower_alloca.c | 1 - src/shady/passes/lower_callf.c | 4 ++-- src/shady/passes/lower_decay_ptrs.c | 2 -- src/shady/passes/lower_entrypoint_args.c | 7 +++++-- src/shady/passes/lower_fill.c | 1 - src/shady/passes/lower_generic_globals.c | 1 - src/shady/passes/lower_generic_ptrs.c | 1 - src/shady/passes/lower_int64.c | 1 - src/shady/passes/lower_lea.c | 1 - src/shady/passes/lower_logical_pointers.c | 1 - src/shady/passes/lower_mask.c | 3 --- src/shady/passes/lower_memcpy.c | 1 - src/shady/passes/lower_nullptr.c | 1 - src/shady/passes/lower_physical_ptrs.c | 1 - src/shady/passes/lower_stack.c | 1 - src/shady/passes/lower_subgroup_ops.c | 5 +++-- src/shady/passes/lower_subgroup_vars.c | 6 ++++-- src/shady/passes/lower_switch_btree.c | 1 - src/shady/passes/lower_tailcalls.c | 3 +-- src/shady/passes/lower_vec_arr.c | 5 +++-- src/shady/passes/lower_workgroups.c | 2 +- src/shady/passes/normalize_builtins.c | 2 +- src/shady/passes/opt_demote_alloca.c | 2 -- src/shady/passes/opt_mem2reg.c | 1 - src/shady/passes/reconvergence_heuristics.c | 1 - src/shady/passes/remove_critical_edges.c | 4 +--- src/shady/passes/restructure.c | 6 ++++-- src/shady/passes/scope2control.c | 1 - src/shady/passes/scope_heuristic.c | 1 - src/shady/passes/setup_stack_frames.c | 9 ++++----- src/shady/passes/specialize_entry_point.c | 2 +- src/shady/passes/specialize_execution_model.c | 2 -- src/shady/transform/CMakeLists.txt | 1 - src/shady/transform/ir_gen_helpers.c | 14 -------------- src/shady/transform/ir_gen_helpers.h | 7 ------- test/test_builder.c | 1 - 53 files changed, 45 insertions(+), 97 deletions(-) delete mode 100644 src/shady/transform/ir_gen_helpers.c delete mode 100644 src/shady/transform/ir_gen_helpers.h diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index e795ebcee..f2e1666da 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -1,7 +1,6 @@ #include "emit_c.h" #include "../shady/ir_private.h" -#include "../shady/transform/ir_gen_helpers.h" #include "../shady/passes/passes.h" #include "../shady/analysis/cfg.h" #include "../shady/analysis/scheduler.h" diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index b21bed171..a5bcef501 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -6,7 +6,6 @@ #include "util.h" #include "../shady/ir_private.h" -#include "../shady/transform/ir_gen_helpers.h" #include "../shady/analysis/scheduler.h" #include diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index c59f0b047..9736219f2 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -1,8 +1,8 @@ #include "emit_spv.h" #include "shady/ir/memory_layout.h" +#include "shady/ir/builtin.h" -#include "../shady/transform/ir_gen_helpers.h" #include "../shady/analysis/cfg.h" #include "../shady/analysis/scheduler.h" diff --git a/src/backend/spirv/spirv_lift_globals_ssbo.c b/src/backend/spirv/spirv_lift_globals_ssbo.c index 711958332..ed8c32390 100644 --- a/src/backend/spirv/spirv_lift_globals_ssbo.c +++ b/src/backend/spirv/spirv_lift_globals_ssbo.c @@ -1,7 +1,8 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" - -#include "../shady/transform/ir_gen_helpers.h" +#include "shady/ir/function.h" +#include "shady/ir/mem.h" +#include "shady/ir/decl.h" #include "dict.h" #include "portability.h" diff --git a/src/backend/spirv/spirv_map_entrypoint_args.c b/src/backend/spirv/spirv_map_entrypoint_args.c index ee77fa133..b08e27451 100644 --- a/src/backend/spirv/spirv_map_entrypoint_args.c +++ b/src/backend/spirv/spirv_map_entrypoint_args.c @@ -1,7 +1,7 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" - -#include "../shady/transform/ir_gen_helpers.h" +#include "shady/ir/decl.h" +#include "shady/ir/annotation.h" #include "portability.h" #include "log.h" diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index b09aae29f..0df76306d 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -2,8 +2,6 @@ #include "shady/ir/memory_layout.h" -#include "../shady/transform/ir_gen_helpers.h" - #include "portability.h" #include "log.h" #include "dict.h" diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index d47e83aa3..f87ea6d99 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -1,7 +1,5 @@ #include "l2s_private.h" -#include "../../shady/transform/ir_gen_helpers.h" - #include "portability.h" #include "log.h" #include "dict.h" diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index db4e45d3a..ea6b9b582 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -1,6 +1,5 @@ #include "shady/pass.h" -#include "../shady/transform/ir_gen_helpers.h" #include "../shady/check.h" #include "log.h" diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 6434ec6b4..1bac0aabb 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -9,7 +9,6 @@ #include "util.h" #include "ir_private.h" -#include "transform/ir_gen_helpers.h" #include #include diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index e0f317dd3..c34b7266d 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -4,7 +4,6 @@ #include "shady/ir/memory_layout.h" #include "../shady/ir_private.h" -#include "../shady/transform/ir_gen_helpers.h" #include "log.h" #include "arena.h" diff --git a/src/shady/body_builder.c b/src/shady/body_builder.c index 11cffadc2..0625ee994 100644 --- a/src/shady/body_builder.c +++ b/src/shady/body_builder.c @@ -1,6 +1,9 @@ #include "shady/ir/builder.h" - -#include "transform/ir_gen_helpers.h" +#include "shady/ir/grammar.h" +#include "shady/ir/function.h" +#include "shady/ir/composite.h" +#include "shady/ir/arena.h" +#include "shady/ir/mem.h" #include "list.h" #include "dict.h" diff --git a/src/shady/fold.c b/src/shady/fold.c index f5a562940..98ef6a7b2 100644 --- a/src/shady/fold.c +++ b/src/shady/fold.c @@ -2,7 +2,6 @@ #include "shady/ir/memory_layout.h" -#include "transform/ir_gen_helpers.h" #include "check.h" #include "portability.h" diff --git a/src/shady/ir/builtin.c b/src/shady/ir/builtin.c index c76531d72..4d7ab6b3c 100644 --- a/src/shady/ir/builtin.c +++ b/src/shady/ir/builtin.c @@ -2,8 +2,8 @@ #include "shady/ir/builder.h" #include "shady/ir/annotation.h" #include "shady/ir/module.h" - -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/mem.h" +#include "shady/ir/decl.h" #include "log.h" #include "portability.h" diff --git a/src/shady/ir/composite.c b/src/shady/ir/composite.c index 33828ab49..281e001c7 100644 --- a/src/shady/ir/composite.c +++ b/src/shady/ir/composite.c @@ -1,7 +1,6 @@ #include "shady/ir/composite.h" #include "ir_private.h" -#include "transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/ir/memory_layout.c b/src/shady/ir/memory_layout.c index 9baadd909..e77257bac 100644 --- a/src/shady/ir/memory_layout.c +++ b/src/shady/ir/memory_layout.c @@ -1,6 +1,6 @@ #include "shady/ir/memory_layout.h" - -#include "transform/ir_gen_helpers.h" +#include "shady/ir/float.h" +#include "shady/ir/type.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index 8a9b026de..a7dae8d41 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" #include "../analysis/scheduler.h" #include "../analysis/free_frontier.h" diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 5818eaa40..5688ccf26 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -7,7 +7,6 @@ #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" #include "../analysis/uses.h" #include "../analysis/leak.h" diff --git a/src/shady/passes/lower_alloca.c b/src/shady/passes/lower_alloca.c index 9bed08865..df5ab2206 100644 --- a/src/shady/passes/lower_alloca.c +++ b/src/shady/passes/lower_alloca.c @@ -4,7 +4,6 @@ #include "shady/ir/cast.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index c97158994..2aebd6194 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -2,8 +2,8 @@ #include "shady/pass.h" #include "shady/ir/ext.h" - -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/annotation.h" +#include "shady/ir/function.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_decay_ptrs.c b/src/shady/passes/lower_decay_ptrs.c index 97496540a..512bc3c3f 100644 --- a/src/shady/passes/lower_decay_ptrs.c +++ b/src/shady/passes/lower_decay_ptrs.c @@ -1,7 +1,5 @@ #include "shady/pass.h" -#include "../transform/ir_gen_helpers.h" - typedef struct { Rewriter rewriter; const CompilerConfig* config; diff --git a/src/shady/passes/lower_entrypoint_args.c b/src/shady/passes/lower_entrypoint_args.c index 99458e34a..745237eab 100644 --- a/src/shady/passes/lower_entrypoint_args.c +++ b/src/shady/passes/lower_entrypoint_args.c @@ -1,7 +1,10 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" - -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/function.h" +#include "shady/ir/debug.h" +#include "shady/ir/decl.h" +#include "shady/ir/annotation.h" +#include "shady/ir/mem.h" #include "portability.h" #include "log.h" diff --git a/src/shady/passes/lower_fill.c b/src/shady/passes/lower_fill.c index 733b8be61..f3492c792 100644 --- a/src/shady/passes/lower_fill.c +++ b/src/shady/passes/lower_fill.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_generic_globals.c b/src/shady/passes/lower_generic_globals.c index 5f647794c..a8b5856f6 100644 --- a/src/shady/passes/lower_generic_globals.c +++ b/src/shady/passes/lower_generic_globals.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_generic_ptrs.c b/src/shady/passes/lower_generic_ptrs.c index a30b8a5d4..bfd3121f3 100644 --- a/src/shady/passes/lower_generic_ptrs.c +++ b/src/shady/passes/lower_generic_ptrs.c @@ -3,7 +3,6 @@ #include "shady/ir/memory_layout.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_int64.c b/src/shady/passes/lower_int64.c index 3be9be8ab..754d5e248 100644 --- a/src/shady/passes/lower_int64.c +++ b/src/shady/passes/lower_int64.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_lea.c b/src/shady/passes/lower_lea.c index 24626d97d..fc154f423 100644 --- a/src/shady/passes/lower_lea.c +++ b/src/shady/passes/lower_lea.c @@ -2,7 +2,6 @@ #include "shady/ir/cast.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_logical_pointers.c b/src/shady/passes/lower_logical_pointers.c index a368a5371..b25bd6ae0 100644 --- a/src/shady/passes/lower_logical_pointers.c +++ b/src/shady/passes/lower_logical_pointers.c @@ -2,7 +2,6 @@ #include "shady/ir/memory_layout.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_mask.c b/src/shady/passes/lower_mask.c index 5d333b3bb..54f95d7a5 100644 --- a/src/shady/passes/lower_mask.c +++ b/src/shady/passes/lower_mask.c @@ -2,9 +2,6 @@ #include "shady/ir/type.h" #include "shady/ir/cast.h" -#include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" - #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_memcpy.c b/src/shady/passes/lower_memcpy.c index a6bee73f5..12901a000 100644 --- a/src/shady/passes/lower_memcpy.c +++ b/src/shady/passes/lower_memcpy.c @@ -2,7 +2,6 @@ #include "shady/ir/cast.h" #include "shady/ir/memory_layout.h" -#include "../transform/ir_gen_helpers.h" #include "../ir_private.h" #include "log.h" diff --git a/src/shady/passes/lower_nullptr.c b/src/shady/passes/lower_nullptr.c index 08516d459..e0c7e471f 100644 --- a/src/shady/passes/lower_nullptr.c +++ b/src/shady/passes/lower_nullptr.c @@ -2,7 +2,6 @@ #include "shady/ir/cast.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_physical_ptrs.c b/src/shady/passes/lower_physical_ptrs.c index 597c456d3..cb187f2e0 100644 --- a/src/shady/passes/lower_physical_ptrs.c +++ b/src/shady/passes/lower_physical_ptrs.c @@ -3,7 +3,6 @@ #include "shady/ir/memory_layout.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_stack.c b/src/shady/passes/lower_stack.c index aa5d6a947..1be80d300 100644 --- a/src/shady/passes/lower_stack.c +++ b/src/shady/passes/lower_stack.c @@ -3,7 +3,6 @@ #include "shady/ir/memory_layout.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index d939f17b6..0eef7e9c2 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -2,8 +2,9 @@ #include "shady/ir/cast.h" #include "shady/ir/memory_layout.h" #include "shady/ir/ext.h" - -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/type.h" +#include "shady/ir/composite.h" +#include "shady/ir/function.h" #include "portability.h" #include "log.h" diff --git a/src/shady/passes/lower_subgroup_vars.c b/src/shady/passes/lower_subgroup_vars.c index 7c92c78a4..38452a8d4 100644 --- a/src/shady/passes/lower_subgroup_vars.c +++ b/src/shady/passes/lower_subgroup_vars.c @@ -1,7 +1,9 @@ #include "shady/pass.h" #include "shady/ir/memory_layout.h" - -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/function.h" +#include "shady/ir/builtin.h" +#include "shady/ir/annotation.h" +#include "shady/ir/decl.h" #include "dict.h" #include "portability.h" diff --git a/src/shady/passes/lower_switch_btree.c b/src/shady/passes/lower_switch_btree.c index 2e2742727..a3d7d12f0 100644 --- a/src/shady/passes/lower_switch_btree.c +++ b/src/shady/passes/lower_switch_btree.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index c7b8d5d7c..7e3ea7d03 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -3,13 +3,12 @@ #include "shady/pass.h" #include "shady/ir/stack.h" #include "shady/ir/cast.h" +#include "shady/ir/builtin.h" #include "../ir_private.h" - #include "../analysis/cfg.h" #include "../analysis/uses.h" #include "../analysis/leak.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/lower_vec_arr.c b/src/shady/passes/lower_vec_arr.c index cbebb3e67..eab656732 100644 --- a/src/shady/passes/lower_vec_arr.c +++ b/src/shady/passes/lower_vec_arr.c @@ -1,6 +1,7 @@ #include "shady/pass.h" - -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/type.h" +#include "shady/ir/composite.h" +#include "shady/ir/primop.h" #include "portability.h" diff --git a/src/shady/passes/lower_workgroups.c b/src/shady/passes/lower_workgroups.c index fdf882bd2..ba9383c49 100644 --- a/src/shady/passes/lower_workgroups.c +++ b/src/shady/passes/lower_workgroups.c @@ -1,7 +1,7 @@ #include "shady/pass.h" +#include "shady/ir/builtin.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "util.h" diff --git a/src/shady/passes/normalize_builtins.c b/src/shady/passes/normalize_builtins.c index f6d3cf016..9a20111e5 100644 --- a/src/shady/passes/normalize_builtins.c +++ b/src/shady/passes/normalize_builtins.c @@ -1,7 +1,7 @@ #include "shady/pass.h" +#include "shady/ir/builtin.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index c6b495048..abb02ecb7 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -4,9 +4,7 @@ #include "../ir_private.h" #include "../check.h" -#include "../transform/ir_gen_helpers.h" #include "../analysis/uses.h" -#include "../analysis/leak.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index be115b58d..5297437d7 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" #include "list.h" diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 79c2a8756..852d04092 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -1,7 +1,6 @@ #include "shady/pass.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "../analysis/cfg.h" #include "../analysis/looptree.h" diff --git a/src/shady/passes/remove_critical_edges.c b/src/shady/passes/remove_critical_edges.c index 3f0d8ad52..199d970e8 100644 --- a/src/shady/passes/remove_critical_edges.c +++ b/src/shady/passes/remove_critical_edges.c @@ -1,7 +1,5 @@ #include "shady/pass.h" - -#include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/function.h" #include "log.h" #include "portability.h" diff --git a/src/shady/passes/restructure.c b/src/shady/passes/restructure.c index c27289807..1d5fa2bf7 100644 --- a/src/shady/passes/restructure.c +++ b/src/shady/passes/restructure.c @@ -1,6 +1,8 @@ #include "shady/pass.h" - -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/function.h" +#include "shady/ir/annotation.h" +#include "shady/ir/mem.h" +#include "shady/ir/debug.h" #include #include diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 08dc00205..4477c1201 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -5,7 +5,6 @@ #include "../ir_private.h" #include "../analysis/cfg.h" #include "../analysis/scheduler.h" -#include "../transform/ir_gen_helpers.h" #include "portability.h" #include "dict.h" diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index 22093832a..ec62ea09f 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -4,7 +4,6 @@ #include "../ir_private.h" #include "../analysis/cfg.h" #include "../analysis/looptree.h" -#include "../transform/ir_gen_helpers.h" #include "log.h" #include "list.h" diff --git a/src/shady/passes/setup_stack_frames.c b/src/shady/passes/setup_stack_frames.c index b28c63825..b2dae8914 100644 --- a/src/shady/passes/setup_stack_frames.c +++ b/src/shady/passes/setup_stack_frames.c @@ -1,14 +1,13 @@ #include "shady/pass.h" #include "shady/visit.h" #include "shady/ir/stack.h" - -#include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" +#include "shady/ir/annotation.h" +#include "shady/ir/function.h" +#include "shady/ir/debug.h" #include "log.h" #include "portability.h" #include "list.h" -#include "util.h" #include @@ -32,7 +31,7 @@ static const Node* process(Context* ctx, const Node* node) { BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(fun)); if (!ctx2.disable_lowering) { ctx2.stack_size_on_entry = shd_bld_get_stack_size(bb); - shd_set_value_name((Node*) ctx2.stack_size_on_entry, shd_format_string_arena(a->arena, "saved_stack_ptr_entering_%s", shd_get_abstraction_name(fun))); + shd_set_value_name((Node*) ctx2.stack_size_on_entry, shd_fmt_string_irarena(a, "saved_stack_ptr_entering_%s", shd_get_abstraction_name(fun))); } shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(node), shd_bb_mem(bb)); if (node->payload.fun.body) diff --git a/src/shady/passes/specialize_entry_point.c b/src/shady/passes/specialize_entry_point.c index cb480ce73..ebf1ee11f 100644 --- a/src/shady/passes/specialize_entry_point.c +++ b/src/shady/passes/specialize_entry_point.c @@ -1,7 +1,7 @@ #include "shady/pass.h" +#include "shady/ir/builtin.h" #include "../ir_private.h" -#include "../transform/ir_gen_helpers.h" #include "portability.h" #include "log.h" diff --git a/src/shady/passes/specialize_execution_model.c b/src/shady/passes/specialize_execution_model.c index 08756b063..55089d0f2 100644 --- a/src/shady/passes/specialize_execution_model.c +++ b/src/shady/passes/specialize_execution_model.c @@ -1,7 +1,5 @@ #include "shady/pass.h" -#include "../transform/ir_gen_helpers.h" - #include "portability.h" #include diff --git a/src/shady/transform/CMakeLists.txt b/src/shady/transform/CMakeLists.txt index 965a6bdd2..0666502db 100644 --- a/src/shady/transform/CMakeLists.txt +++ b/src/shady/transform/CMakeLists.txt @@ -1,4 +1,3 @@ target_sources(shady PRIVATE internal_constants.c - ir_gen_helpers.c ) diff --git a/src/shady/transform/ir_gen_helpers.c b/src/shady/transform/ir_gen_helpers.c deleted file mode 100644 index 2784fafda..000000000 --- a/src/shady/transform/ir_gen_helpers.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "ir_gen_helpers.h" - -#include "shady/rewrite.h" -#include "shady/ir/memory_layout.h" - -#include "../ir_private.h" - -#include "list.h" -#include "portability.h" -#include "log.h" -#include "util.h" - -#include -#include \ No newline at end of file diff --git a/src/shady/transform/ir_gen_helpers.h b/src/shady/transform/ir_gen_helpers.h deleted file mode 100644 index 636ca0a97..000000000 --- a/src/shady/transform/ir_gen_helpers.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef SHADY_IR_GEN_HELPERS_H -#define SHADY_IR_GEN_HELPERS_H - -#include "shady/ir.h" -#include "shady/ir/builtin.h" - -#endif diff --git a/test/test_builder.c b/test/test_builder.c index 445c4a2fe..eddde2ee1 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -2,7 +2,6 @@ #include "shady/driver.h" #include "shady/be/dump.h" -#include "../shady/transform/ir_gen_helpers.h" #include "../shady/analysis/cfg.h" #include "log.h" From e21f114c20b9307ec76d6ab5b8b08e9b2c0c5eb6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:33:02 +0200 Subject: [PATCH 670/693] prefix everything in transform/ --- include/shady/be/dump.h | 4 +-- src/backend/c/emit_c.c | 6 ++-- src/backend/c/emit_c_control_flow.c | 2 +- src/backend/c/emit_c_value.c | 2 +- src/backend/spirv/emit_spv.c | 6 ++-- src/backend/spirv/emit_spv_control_flow.c | 8 ++--- src/backend/spirv/emit_spv_value.c | 2 +- src/driver/driver.c | 4 +-- src/frontend/llvm/l2s.c | 2 +- src/frontend/slim/bind.c | 6 ++-- src/shady/analysis/callgraph.c | 18 +++++------ src/shady/analysis/callgraph.h | 4 +-- src/shady/analysis/cfg.c | 26 +++++++-------- src/shady/analysis/cfg.h | 22 ++++++------- src/shady/analysis/cfg_dump.c | 26 +++++++-------- src/shady/analysis/free_frontier.c | 10 +++--- src/shady/analysis/free_frontier.h | 2 +- src/shady/analysis/leak.c | 14 ++++---- src/shady/analysis/leak.h | 6 ++-- src/shady/analysis/looptree.c | 22 ++++++------- src/shady/analysis/looptree.h | 8 ++--- src/shady/analysis/scheduler.c | 18 +++++------ src/shady/analysis/scheduler.h | 6 ++-- src/shady/analysis/uses.c | 10 +++--- src/shady/analysis/uses.h | 8 ++--- src/shady/analysis/verify.c | 12 +++---- src/shady/analysis/verify.h | 2 +- src/shady/compile.c | 4 +-- src/shady/passes/cleanup.c | 14 ++++---- src/shady/passes/lcssa.c | 22 ++++++------- src/shady/passes/lift_everything.c | 12 +++---- src/shady/passes/lift_indirect_targets.c | 16 ++++----- src/shady/passes/lower_cf_instrs.c | 8 ++--- src/shady/passes/lower_tailcalls.c | 12 +++---- src/shady/passes/mark_leaf_functions.c | 16 ++++----- src/shady/passes/opt_demote_alloca.c | 6 ++-- src/shady/passes/opt_inline.c | 4 +-- src/shady/passes/opt_mem2reg.c | 4 +-- src/shady/passes/reconvergence_heuristics.c | 36 ++++++++++----------- src/shady/passes/scope2control.c | 14 ++++---- src/shady/passes/scope_heuristic.c | 22 ++++++------- src/shady/print.c | 16 ++++----- src/shady/visit.c | 4 +-- test/test_builder.c | 4 +-- 44 files changed, 235 insertions(+), 235 deletions(-) diff --git a/include/shady/be/dump.h b/include/shady/be/dump.h index 197046235..a2dc858aa 100644 --- a/include/shady/be/dump.h +++ b/include/shady/be/dump.h @@ -9,8 +9,8 @@ void shd_dump_module(Module* mod); void shd_dump_node(const Node* node); -void dump_cfgs(FILE* output, Module* mod); -void dump_loop_trees(FILE* output, Module* mod); +void shd_dump_cfgs(FILE* output, Module* mod); +void shd_dump_loop_trees(FILE* output, Module* mod); #endif diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index f2e1666da..6928a8f70 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -308,7 +308,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { .cfg = build_fn_cfg(decl), .emitted_terms = shd_new_dict(Node*, CTerm, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; - fn.scheduler = new_scheduler(fn.cfg); + fn.scheduler = shd_new_scheduler(fn.cfg); fn.instruction_printers = calloc(sizeof(Printer*), fn.cfg->size); // for (size_t i = 0; i < fn.cfg->size; i++) // fn.instruction_printers[i] = open_growy_as_printer(new_growy()); @@ -341,8 +341,8 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { shd_printer_deindent(emitter->fn_defs); shd_print(emitter->fn_defs, "\n}"); - destroy_scheduler(fn.scheduler); - destroy_cfg(fn.cfg); + shd_destroy_scheduler(fn.scheduler); + shd_destroy_cfg(fn.cfg); shd_destroy_dict(fn.emitted_terms); free(fn.instruction_printers); } diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index 99d11df52..f650a84e5 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -13,7 +13,7 @@ String c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { assert(abs && is_abstraction(abs)); const Node* body = get_abstraction_body(abs); assert(body && is_terminator(body)); - CFNode* cf_node = cfg_lookup(fn->cfg, abs); + CFNode* cf_node = shd_cfg_lookup(fn->cfg, abs); Printer* p = shd_new_printer_from_growy(shd_new_growy()); fn->instruction_printers[cf_node->rpo_index] = p; //indent(p); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index a5bcef501..2e9ebe3ae 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -1004,7 +1004,7 @@ CTerm c_emit_value(Emitter* emitter, FnEmitter* fn_builder, const Node* node) { CTerm* found = lookup_existing_term(emitter, fn_builder, node); if (found) return *found; - CFNode* where = fn_builder ? schedule_instruction(fn_builder->scheduler, node) : NULL; + CFNode* where = fn_builder ? shd_schedule_instruction(fn_builder->scheduler, node) : NULL; if (where) { CTerm emitted = c_emit_value_(emitter, fn_builder, fn_builder->instruction_printers[where->rpo_index], node); register_emitted(emitter, fn_builder, node, emitted); diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index e851dcbcc..8b4281864 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -85,7 +85,7 @@ static void emit_function(Emitter* emitter, const Node* node) { .emitted = shd_new_dict(Node*, SpvId, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .cfg = build_fn_cfg(node), }; - fn_builder.scheduler = new_scheduler(fn_builder.cfg); + fn_builder.scheduler = shd_new_scheduler(fn_builder.cfg); fn_builder.per_bb = calloc(sizeof(*fn_builder.per_bb), fn_builder.cfg->size); Nodes params = node->payload.fun.params; @@ -137,8 +137,8 @@ static void emit_function(Emitter* emitter, const Node* node) { } free(fn_builder.per_bb); - destroy_scheduler(fn_builder.scheduler); - destroy_cfg(fn_builder.cfg); + shd_destroy_scheduler(fn_builder.scheduler); + shd_destroy_cfg(fn_builder.cfg); shd_destroy_dict(fn_builder.emitted); } diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 1a0a3999b..9b54dbddb 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -111,8 +111,8 @@ static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_buil spvb_add_phi_source(shd_read_list(SpvbPhi*, spbv_get_phis(body_builder))[i], get_block_builder_id(header_builder), header_phi_id); } - fn_builder->per_bb[cfg_lookup(fn_builder->cfg, loop_instr.body)->rpo_index].continue_id = continue_id; - fn_builder->per_bb[cfg_lookup(fn_builder->cfg, loop_instr.body)->rpo_index].continue_builder = continue_builder; + fn_builder->per_bb[shd_cfg_lookup(fn_builder->cfg, loop_instr.body)->rpo_index].continue_id = continue_id; + fn_builder->per_bb[shd_cfg_lookup(fn_builder->cfg, loop_instr.body)->rpo_index].continue_builder = continue_builder; SpvId tail_id = spv_find_emitted(emitter, fn_builder, loop_instr.tail); @@ -135,7 +135,7 @@ typedef enum { static CFNode* find_surrounding_structured_construct_node(Emitter* emitter, FnBuilder* fn_builder, const Node* abs, Construct construct) { const Node* oabs = abs; - for (CFNode* n = cfg_lookup(fn_builder->cfg, abs); n; oabs = n->node, n = n->idom) { + for (CFNode* n = shd_cfg_lookup(fn_builder->cfg, abs); n; oabs = n->node, n = n->idom) { const Node* terminator = get_abstraction_body(n->node); assert(terminator); if (is_structured_construct(terminator) && get_structured_construct_tail(terminator) == oabs) { @@ -233,7 +233,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi const Node* construct = find_construct(emitter, fn_builder, abs, LoopConstruct); assert(construct); Loop loop_payload = construct->payload.loop_instr; - CFNode* loop_body = cfg_lookup(fn_builder->cfg, loop_payload.body); + CFNode* loop_body = shd_cfg_lookup(fn_builder->cfg, loop_payload.body); assert(loop_body); Nodes args = terminator->payload.merge_continue.args; add_phis(emitter, fn_builder, get_block_builder_id(basic_block_builder), fn_builder->per_bb[loop_body->rpo_index].continue_builder, args); diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index 9736219f2..fc787f514 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -581,7 +581,7 @@ SpvId spv_emit_value(Emitter* emitter, FnBuilder* fn_builder, const Node* node) if (existing) return *existing; - CFNode* where = fn_builder ? schedule_instruction(fn_builder->scheduler, node) : NULL; + CFNode* where = fn_builder ? shd_schedule_instruction(fn_builder->scheduler, node) : NULL; if (where) { BBBuilder bb_builder = spv_find_basic_block_builder(emitter, where->node); SpvId emitted = spv_emit_value_(emitter, fn_builder, bb_builder, node); diff --git a/src/driver/driver.c b/src/driver/driver.c index f96a8cbec..5fcc7237f 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -129,7 +129,7 @@ ShadyErrorCodes shd_driver_compile(DriverConfig* args, Module* mod) { if (args->cfg_output_filename) { FILE* f = fopen(args->cfg_output_filename, "wb"); assert(f); - dump_cfgs(f, mod); + shd_dump_cfgs(f, mod); fclose(f); shd_debug_print("CFG dumped\n"); } @@ -137,7 +137,7 @@ ShadyErrorCodes shd_driver_compile(DriverConfig* args, Module* mod) { if (args->loop_tree_output_filename) { FILE* f = fopen(args->loop_tree_output_filename, "wb"); assert(f); - dump_loop_trees(f, mod); + shd_dump_loop_trees(f, mod); fclose(f); shd_debug_print("Loop tree dumped\n"); } diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 3ad270c2d..3aab87803 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -336,7 +336,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* postprocess(&p, dirty, *dst); shd_log_fmt(DEBUGVV, "Shady module parsed from LLVM, after cleanup:"); shd_log_module(DEBUGVV, config, *dst); - verify_module(config, *dst); + shd_verify_module(config, *dst); shd_destroy_ir_arena(arena); shd_destroy_dict(p.map); diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 8408cbb94..224250c6b 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -249,7 +249,7 @@ static const Node* rewrite_decl(Context* ctx, const Node* decl) { } static bool is_used_as_value(Context* ctx, const Node* node) { - const Use* use = get_first_use(ctx->uses, node); + const Use* use = shd_get_first_use(ctx->uses, node); for (;use;use = use->next_use) { if (use->operand_class != NcMem) { if (use->user->tag == ExtInstr_TAG && strcmp(use->user->payload.ext_instr.set, "shady.frontend") == 0) { @@ -377,11 +377,11 @@ Module* slim_pass_bind(SHADY_UNUSED const CompilerConfig* compiler_config, Modul .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) bind_node), .local_variables = NULL, .current_function = NULL, - .uses = create_module_uses_map(src, 0), + .uses = shd_new_uses_map_module(src, 0), }; shd_rewrite_module(&ctx.rewriter); shd_destroy_rewriter(&ctx.rewriter); - destroy_uses_map(ctx.uses); + shd_destroy_uses_map(ctx.uses); return dst; } diff --git a/src/shady/analysis/callgraph.c b/src/shady/analysis/callgraph.c index 4a255af82..482a8a090 100644 --- a/src/shady/analysis/callgraph.c +++ b/src/shady/analysis/callgraph.c @@ -15,11 +15,11 @@ KeyHash shd_hash_node(const Node**); bool shd_compare_node(const Node**, const Node**); -KeyHash hash_cgedge(CGEdge* n) { +KeyHash shd_hash_cgedge(CGEdge* n) { return shd_hash(n, sizeof(CGEdge)); } -bool compare_cgedge(CGEdge* a, CGEdge* b) { +bool shd_compare_cgedge(CGEdge* a, CGEdge* b) { return (a)->src_fn == (b)->src_fn && (a)->instr == (b)->instr; } @@ -92,8 +92,8 @@ static CGNode* analyze_fn(CallGraph* graph, const Node* fn) { return *found; CGNode* new = calloc(1, sizeof(CGNode)); new->fn = fn; - new->callees = shd_new_set(CGEdge, (HashFn) hash_cgedge, (CmpFn) compare_cgedge); - new->callers = shd_new_set(CGEdge, (HashFn) hash_cgedge, (CmpFn) compare_cgedge); + new->callees = shd_new_set(CGEdge, (HashFn) shd_hash_cgedge, (CmpFn) shd_compare_cgedge); + new->callers = shd_new_set(CGEdge, (HashFn) shd_hash_cgedge, (CmpFn) shd_compare_cgedge); new->tarjan.index = -1; shd_dict_insert_get_key(const Node*, CGNode*, graph->fn2cgn, fn, new); @@ -194,13 +194,13 @@ static void tarjan(struct Dict* verts) { shd_destroy_list(stack); } -CallGraph* new_callgraph(Module* mod) { +CallGraph* shd_new_callgraph(Module* mod) { CallGraph* graph = calloc(sizeof(CallGraph), 1); *graph = (CallGraph) { .fn2cgn = shd_new_dict(const Node*, CGNode*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node) }; - const UsesMap* uses = create_module_uses_map(mod, NcType); + const UsesMap* uses = shd_new_uses_map_module(mod, NcType); Nodes decls = shd_module_get_declarations(mod); for (size_t i = 0; i < decls.count; i++) { @@ -208,7 +208,7 @@ CallGraph* new_callgraph(Module* mod) { if (decl->tag == Function_TAG) { CGNode* node = analyze_fn(graph, decl); - const Use* use = get_first_use(uses, fn_addr_helper(shd_module_get_arena(mod), decl)); + const Use* use = shd_get_first_use(uses, fn_addr_helper(shd_module_get_arena(mod), decl)); for (;use;use = use->next_use) { if (use->user->tag == Call_TAG && strcmp(use->operand_name, "callee") == 0) continue; @@ -237,7 +237,7 @@ CallGraph* new_callgraph(Module* mod) { } } - destroy_uses_map(uses); + shd_destroy_uses_map(uses); shd_debugv_print("CallGraph: done with CFG build, contains %d nodes\n", shd_dict_count(graph->fn2cgn)); @@ -246,7 +246,7 @@ CallGraph* new_callgraph(Module* mod) { return graph; } -void destroy_callgraph(CallGraph* graph) { +void shd_destroy_callgraph(CallGraph* graph) { size_t i = 0; CGNode* node; while (shd_dict_iter(graph->fn2cgn, &i, NULL, &node)) { diff --git a/src/shady/analysis/callgraph.h b/src/shady/analysis/callgraph.h index b28d989c3..bf4a1f437 100644 --- a/src/shady/analysis/callgraph.h +++ b/src/shady/analysis/callgraph.h @@ -31,7 +31,7 @@ typedef struct Callgraph_ { struct Dict* fn2cgn; } CallGraph; -CallGraph* new_callgraph(Module*); -void destroy_callgraph(CallGraph*); +CallGraph* shd_new_callgraph(Module* mod); +void shd_destroy_callgraph(CallGraph* graph); #endif diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 6f95fa507..9d95c5ea5 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -21,7 +21,7 @@ struct List* build_cfgs(Module* mod, CFGBuildConfig config) { for (size_t i = 0; i < decls.count; i++) { const Node* decl = decls.nodes[i]; if (decl->tag != Function_TAG) continue; - CFG* cfg = build_cfg(decl, decl, config); + CFG* cfg = shd_new_cfg(decl, decl, config); shd_list_append(CFG*, cfgs, cfg); } @@ -49,7 +49,7 @@ typedef struct { static void process_cf_node(CfgBuildContext* ctx, CFNode* node); -CFNode* cfg_lookup(CFG* cfg, const Node* abs) { +CFNode* shd_cfg_lookup(CFG* cfg, const Node* abs) { CFNode** found = shd_dict_find_value(const Node*, CFNode*, cfg->map, abs); if (found) { CFNode* cfnode = *found; @@ -90,7 +90,7 @@ static CFNode* get_or_enqueue(CfgBuildContext* ctx, const Node* abs) { } static bool in_loop(LoopTree* lt, const Node* fn, const Node* loopentry, const Node* block) { - LTNode* lt_node = looptree_lookup(lt, block); + LTNode* lt_node = shd_loop_tree_lookup(lt, block); assert(lt_node); LTNode* parent = lt_node->parent; assert(parent); @@ -372,7 +372,7 @@ static void mark_reachable(CFNode* n) { } } -CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { +CFG* shd_new_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { assert(function && function->tag == Function_TAG); assert(is_abstraction(entry)); Arena* arena = shd_new_arena(); @@ -415,13 +415,13 @@ CFG* build_cfg(const Node* function, const Node* entry, CFGBuildConfig config) { if (config.flipped) flip_cfg(cfg); - compute_rpo(cfg); - compute_domtree(cfg); + shd_cfg_compute_rpo(cfg); + shd_cfg_compute_domtree(cfg); return cfg; } -void destroy_cfg(CFG* cfg) { +void shd_destroy_cfg(CFG* cfg) { bool entry_destroyed = false; for (size_t i = 0; i < cfg->size; i++) { CFNode* node = shd_read_list(CFNode*, cfg->contents)[i]; @@ -465,7 +465,7 @@ static size_t post_order_visit(CFG* cfg, CFNode* n, size_t i) { return n->rpo_index; } -void compute_rpo(CFG* cfg) { +void shd_cfg_compute_rpo(CFG* cfg) { /*cfg->reachable_size = 0; for (size_t i = 0; i < entries_count_list(cfg->contents); i++) { CFNode* n = read_list(CFNode*, cfg->contents)[i]; @@ -485,7 +485,7 @@ void compute_rpo(CFG* cfg) { // debug_print("\n"); } -bool is_cfnode_structural_target(CFNode* cfn) { +bool shd_cfg_is_node_structural_target(CFNode* cfn) { for (size_t i = 0; i < shd_list_count(cfn->pred_edges); i++) { if (shd_read_list(CFEdge, cfn->pred_edges)[i].type != JumpEdge) return true; @@ -493,7 +493,7 @@ bool is_cfnode_structural_target(CFNode* cfn) { return false; } -CFNode* least_common_ancestor(CFNode* i, CFNode* j) { +CFNode* shd_cfg_least_common_ancestor(CFNode* i, CFNode* j) { assert(i && j); while (i->rpo_index != j->rpo_index) { while (i->rpo_index < j->rpo_index) j = j->idom; @@ -502,7 +502,7 @@ CFNode* least_common_ancestor(CFNode* i, CFNode* j) { return i; } -bool cfg_is_dominated(CFNode* a, CFNode* b) { +bool shd_cfg_is_dominated(CFNode* a, CFNode* b) { while (a) { if (a == b) return true; @@ -516,7 +516,7 @@ bool cfg_is_dominated(CFNode* a, CFNode* b) { return false; } -void compute_domtree(CFG* cfg) { +void shd_cfg_compute_domtree(CFG* cfg) { for (size_t i = 0; i < cfg->size; i++) { CFNode* n = shd_read_list(CFNode*, cfg->contents)[i]; if (n == cfg->entry/* || !n->reachable*/) @@ -557,7 +557,7 @@ void compute_domtree(CFG* cfg) { if (e.type == StructuredTailEdge) continue; CFNode* p = e.src; - new_idom = new_idom ? least_common_ancestor(new_idom, p) : p; + new_idom = new_idom ? shd_cfg_least_common_ancestor(new_idom, p) : p; } assert(new_idom); if (n->idom != new_idom) { diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index df6e88768..0ff3f15e5 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -15,7 +15,7 @@ typedef enum { /// Join points might leak, and as a consequence, there might be no static edge to the /// tail of the enclosing let, which would make it look like dead code. /// This edge type accounts for that risk, they can be ignored where more precise info is available - /// (see is_control_static for example) + /// (see shd_is_control_static for example) StructuredTailEdge, } CFEdgeType; @@ -100,7 +100,7 @@ struct List* build_cfgs(Module*, CFGBuildConfig); /** Construct the CFG starting in node. */ -CFG* build_cfg(const Node* fn, const Node* entry, CFGBuildConfig); +CFG* shd_new_cfg(const Node* fn, const Node* entry, CFGBuildConfig); /** Construct the CFG starting in node. * Dominance will only be computed with respect to the nodes reachable by @p entry. @@ -128,24 +128,24 @@ static inline CFGBuildConfig flipped_cfg_build(void) { }; } -#define build_fn_cfg(node) build_cfg(node, node, default_forward_cfg_build()) +#define build_fn_cfg(node) shd_new_cfg(node, node, default_forward_cfg_build()) /** Construct the CFG stating in Node. * Dominance will only be computed with respect to the nodes reachable by @p entry. * This CFG will contain post dominance information instead of regular dominance! */ -#define build_fn_cfg_flipped(node) build_cfg(node, node, flipped_cfg_build()) +#define build_fn_cfg_flipped(node) shd_new_cfg(node, node, flipped_cfg_build()) -CFNode* cfg_lookup(CFG* cfg, const Node* abs); -void compute_rpo(CFG*); -void compute_domtree(CFG*); +CFNode* shd_cfg_lookup(CFG* cfg, const Node* abs); +void shd_cfg_compute_rpo(CFG* cfg); +void shd_cfg_compute_domtree(CFG* cfg); -bool cfg_is_dominated(CFNode* dominated, CFNode* by); +bool shd_cfg_is_dominated(CFNode* a, CFNode* b); -bool is_cfnode_structural_target(CFNode*); +bool shd_cfg_is_node_structural_target(CFNode* cfn); -CFNode* least_common_ancestor(CFNode* i, CFNode* j); +CFNode* shd_cfg_least_common_ancestor(CFNode* i, CFNode* j); -void destroy_cfg(CFG* cfg); +void shd_destroy_cfg(CFG* cfg); #endif diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 9615925ee..9fd870433 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -130,7 +130,7 @@ static void dump_cfg(FILE* output, CFG* cfg) { fprintf(output, "}\n"); } -void dump_existing_cfg_auto(CFG* cfg) { +void shd_dump_existing_cfg_auto(CFG* cfg) { FILE* f = fopen("cfg.dot", "wb"); fprintf(f, "digraph G {\n"); dump_cfg(f, cfg); @@ -138,17 +138,17 @@ void dump_existing_cfg_auto(CFG* cfg) { fclose(f); } -void dump_cfg_auto(const Node* fn) { +void shd_dump_cfg_auto(const Node* fn) { FILE* f = fopen("cfg.dot", "wb"); fprintf(f, "digraph G {\n"); CFG* cfg = build_fn_cfg(fn); dump_cfg(f, cfg); - destroy_cfg(cfg); + shd_destroy_cfg(cfg); fprintf(f, "}\n"); fclose(f); } -void dump_cfgs(FILE* output, Module* mod) { +void shd_dump_cfgs(FILE* output, Module* mod) { if (output == NULL) output = stderr; @@ -157,15 +157,15 @@ void dump_cfgs(FILE* output, Module* mod) { for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; dump_cfg(output, cfg); - destroy_cfg(cfg); + shd_destroy_cfg(cfg); } shd_destroy_list(cfgs); fprintf(output, "}\n"); } -void dump_cfgs_auto(Module* mod) { +void shd_dump_cfgs_auto(Module* mod) { FILE* f = fopen("cfg.dot", "wb"); - dump_cfgs(f, mod); + shd_dump_cfgs(f, mod); fclose(f); } @@ -183,28 +183,28 @@ static void dump_domtree_cfnode(Printer* p, CFNode* idom) { } } -void dump_domtree_cfg(Printer* p, CFG* s) { +void shd_dump_domtree_cfg(Printer* p, CFG* s) { shd_print(p, "subgraph cluster_%s {\n", shd_get_abstraction_name_safe(s->entry->node)); dump_domtree_cfnode(p, s->entry); shd_print(p, "}\n"); } -void dump_domtree_module(Printer* p, Module* mod) { +void shd_dump_domtree_module(Printer* p, Module* mod) { shd_print(p, "digraph G {\n"); struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; - dump_domtree_cfg(p, cfg); - destroy_cfg(cfg); + shd_dump_domtree_cfg(p, cfg); + shd_destroy_cfg(cfg); } shd_destroy_list(cfgs); shd_print(p, "}\n"); } -void dump_domtree_auto(Module* mod) { +void shd_dump_domtree_auto(Module* mod) { FILE* f = fopen("domtree.dot", "wb"); Printer* p = shd_new_printer_from_file(f); - dump_domtree_module(p, mod); + shd_dump_domtree_module(p, mod); shd_destroy_printer(p); fclose(f); } diff --git a/src/shady/analysis/free_frontier.c b/src/shady/analysis/free_frontier.c index c252388ff..8df0aa952 100644 --- a/src/shady/analysis/free_frontier.c +++ b/src/shady/analysis/free_frontier.c @@ -16,14 +16,14 @@ static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { if (shd_dict_find_key(const Node*, v->seen, node)) return; shd_set_insert_get_result(const Node*, v->seen, node); - CFNode* where = schedule_instruction(v->scheduler, node); + CFNode* where = shd_schedule_instruction(v->scheduler, node); if (where) { FreeFrontierVisitor vv = *v; - if (cfg_is_dominated(where, v->start)) { + if (shd_cfg_is_dominated(where, v->start)) { shd_visit_node_operands(&vv.v, NcAbstraction | NcDeclaration | NcType, node); } else { if (is_abstraction(node)) { - struct Dict* other_ff = free_frontier(v->scheduler, v->cfg, node); + struct Dict* other_ff = shd_free_frontier(v->scheduler, v->cfg, node); size_t i = 0; const Node* f; while (shd_dict_iter(other_ff, &i, &f, NULL)) { @@ -41,14 +41,14 @@ static void visit_free_frontier(FreeFrontierVisitor* v, const Node* node) { KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); -struct Dict* free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs) { +struct Dict* shd_free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs) { FreeFrontierVisitor ffv = { .v = { .visit_node_fn = (VisitNodeFn) visit_free_frontier, }, .scheduler = scheduler, .cfg = cfg, - .start = cfg_lookup(cfg, abs), + .start = shd_cfg_lookup(cfg, abs), .frontier = shd_new_set(const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), .seen = shd_new_set(const Node*, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), }; diff --git a/src/shady/analysis/free_frontier.h b/src/shady/analysis/free_frontier.h index 3629667b0..ad389df50 100644 --- a/src/shady/analysis/free_frontier.h +++ b/src/shady/analysis/free_frontier.h @@ -5,6 +5,6 @@ #include "cfg.h" #include "scheduler.h" -struct Dict* free_frontier(Scheduler* scheduler, CFG*, const Node* abs); +struct Dict* shd_free_frontier(Scheduler* scheduler, CFG* cfg, const Node* abs); #endif diff --git a/src/shady/analysis/leak.c b/src/shady/analysis/leak.c index 49b9d38a7..db2c52858 100644 --- a/src/shady/analysis/leak.c +++ b/src/shady/analysis/leak.c @@ -5,8 +5,8 @@ #include "shady/visit.h" -void visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, VisitEnclosingAbsCallback fn) { - const Use* use = get_first_use(map, n); +void shd_visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, VisitEnclosingAbsCallback fn) { + const Use* use = shd_get_first_use(map, n); for (;use; use = use->next_use) { if (is_abstraction(use->user)) { fn(uptr, use); @@ -16,17 +16,17 @@ void visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, Visit if (is_declaration(use->user)) continue; - visit_enclosing_abstractions(map, n, uptr, fn); + shd_visit_enclosing_abstractions(map, n, uptr, fn); } } -bool is_control_static(const UsesMap* map, const Node* control) { +bool shd_is_control_static(const UsesMap* map, const Node* control) { assert(control->tag == Control_TAG); const Node* inside = control->payload.control.inside; const Node* jp = shd_first(get_abstraction_params(inside)); bool found_binding_abs = false; - const Use* use = get_first_use(map, jp); + const Use* use = shd_get_first_use(map, jp); assert(use && "we expected at least one use ... "); for (;use; use = use->next_use) { if (use->user == control->payload.control.inside) { @@ -42,13 +42,13 @@ bool is_control_static(const UsesMap* map, const Node* control) { return true; } -const Node* get_control_for_jp(const UsesMap* map, const Node* jp) { +const Node* shd_get_control_for_jp(const UsesMap* map, const Node* jp) { if (!is_param(jp)) return NULL; const Node* abs = jp->payload.param.abs; assert(is_abstraction(abs)); - const Use* use = get_first_use(map, abs); + const Use* use = shd_get_first_use(map, abs); for (;use; use = use->next_use) { if (use->user->tag == Control_TAG && use->operand_class == NcBasic_block && strcmp(use->operand_name, "inside") == 0) return use->user; diff --git a/src/shady/analysis/leak.h b/src/shady/analysis/leak.h index 24b860207..616891352 100644 --- a/src/shady/analysis/leak.h +++ b/src/shady/analysis/leak.h @@ -7,10 +7,10 @@ #include "cfg.h" typedef void (VisitEnclosingAbsCallback)(void*, const Use*); -void visit_enclosing_abstractions(UsesMap*, const Node*, void* uptr, VisitEnclosingAbsCallback fn); +void shd_visit_enclosing_abstractions(UsesMap* map, const Node* n, void* uptr, VisitEnclosingAbsCallback fn); -bool is_control_static(const UsesMap*, const Node* control); +bool shd_is_control_static(const UsesMap* map, const Node* control); /// Returns the Control node that defines the join point, or NULL if it's defined by something else -const Node* get_control_for_jp(const UsesMap*, const Node* jp); +const Node* shd_get_control_for_jp(const UsesMap* map, const Node* jp); #endif diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index 6a3ddff74..73606006c 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -187,13 +187,13 @@ static void build_map_recursive(struct Dict* map, LTNode* n) { } } -LTNode* looptree_lookup(LoopTree* lt, const Node* block) { +LTNode* shd_loop_tree_lookup(LoopTree* lt, const Node* block) { LTNode** found = shd_dict_find_value(const Node*, LTNode*, lt->map, block); if (found) return *found; assert(false); } -LoopTree* build_loop_tree(CFG* s) { +LoopTree* shd_new_loop_tree(CFG* s) { LARRAY(State, states, s->size); for (size_t i = 0; i < s->size; i++) { states[i] = (State) { @@ -236,7 +236,7 @@ static void destroy_lt_node(LTNode* n) { free(n); } -void destroy_loop_tree(LoopTree* lt) { +void shd_destroy_loop_tree(LoopTree* lt) { destroy_lt_node(lt->root); shd_destroy_dict(lt->map); free(lt); @@ -271,7 +271,7 @@ static void dump_lt_node(FILE* f, const LTNode* n) { fprintf(f, "}\n"); } -void dump_loop_tree(FILE* f, LoopTree* lt) { +void shd_dump_loop_tree(FILE* f, LoopTree* lt) { //fprintf(f, "digraph G {\n"); fprintf(f, "subgraph cluster_%d {\n", extra_uniqueness++); dump_lt_node(f, lt->root); @@ -279,7 +279,7 @@ void dump_loop_tree(FILE* f, LoopTree* lt) { //fprintf(f, "}\n"); } -void dump_loop_trees(FILE* output, Module* mod) { +void shd_dump_loop_trees(FILE* output, Module* mod) { if (output == NULL) output = stderr; @@ -287,18 +287,18 @@ void dump_loop_trees(FILE* output, Module* mod) { struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; - LoopTree* lt = build_loop_tree(cfg); - dump_loop_tree(output, lt); - destroy_loop_tree(lt); - destroy_cfg(cfg); + LoopTree* lt = shd_new_loop_tree(cfg); + shd_dump_loop_tree(output, lt); + shd_destroy_loop_tree(lt); + shd_destroy_cfg(cfg); } shd_destroy_list(cfgs); fprintf(output, "}\n"); } -void dump_loop_trees_auto(Module* mod) { +void shd_dump_loop_trees_auto(Module* mod) { FILE* f = fopen("loop_trees.dot", "wb"); - dump_loop_trees(f, mod); + shd_dump_loop_trees(f, mod); fclose(f); } diff --git a/src/shady/analysis/looptree.h b/src/shady/analysis/looptree.h index 65bdb0c36..6ec6db055 100644 --- a/src/shady/analysis/looptree.h +++ b/src/shady/analysis/looptree.h @@ -39,11 +39,11 @@ struct LoopTree_ { /** * Returns the leaf for this node. */ -LTNode* looptree_lookup(LoopTree*, const Node* block); +LTNode* shd_loop_tree_lookup(LoopTree* lt, const Node* block); -void destroy_loop_tree(LoopTree* lt); +void shd_destroy_loop_tree(LoopTree* lt); -LoopTree* build_loop_tree(CFG* s); -void dump_loop_trees(FILE* output, Module* mod); +LoopTree* shd_new_loop_tree(CFG* s); +void shd_dump_loop_trees(FILE* output, Module* mod); #endif // SHADY_LOOPTREE_H diff --git a/src/shady/analysis/scheduler.c b/src/shady/analysis/scheduler.c index 07c2e87cb..7b4955a81 100644 --- a/src/shady/analysis/scheduler.c +++ b/src/shady/analysis/scheduler.c @@ -24,10 +24,10 @@ static void schedule_after(CFNode** scheduled, CFNode* req) { else { // TODO: validate that old post-dominates req if (req->rpo_index > old->rpo_index) { - assert(cfg_is_dominated(req, old)); + assert(shd_cfg_is_dominated(req, old)); *scheduled = req; } else { - assert(cfg_is_dominated(old, req)); + assert(shd_cfg_is_dominated(old, req)); } } } @@ -37,14 +37,14 @@ static void visit_operand(Scheduler* s, NodeClass nc, String opname, const Node* // We only care about mem and value dependencies case NcMem: case NcValue: - schedule_after(&s->result, schedule_instruction(s, op)); + schedule_after(&s->result, shd_schedule_instruction(s, op)); break; default: break; } } -Scheduler* new_scheduler(CFG* cfg) { +Scheduler* shd_new_scheduler(CFG* cfg) { Scheduler* s = calloc(sizeof(Scheduler), 1); *s = (Scheduler) { .v = { @@ -56,7 +56,7 @@ Scheduler* new_scheduler(CFG* cfg) { return s; } -CFNode* schedule_instruction(Scheduler* s, const Node* n) { +CFNode* shd_schedule_instruction(Scheduler* s, const Node* n) { //assert(n && is_instruction(n)); CFNode** found = shd_dict_find_value(const Node*, CFNode*, s->scheduled, n); if (found) @@ -66,11 +66,11 @@ CFNode* schedule_instruction(Scheduler* s, const Node* n) { s2.result = NULL; if (n->tag == Param_TAG) { - schedule_after(&s2.result, cfg_lookup(s->cfg, n->payload.param.abs)); + schedule_after(&s2.result, shd_cfg_lookup(s->cfg, n->payload.param.abs)); } else if (n->tag == BasicBlock_TAG) { - schedule_after(&s2.result, cfg_lookup(s->cfg, n)); + schedule_after(&s2.result, shd_cfg_lookup(s->cfg, n)); } else if (n->tag == AbsMem_TAG) { - schedule_after(&s2.result, cfg_lookup(s->cfg, n->payload.abs_mem.abs)); + schedule_after(&s2.result, shd_cfg_lookup(s->cfg, n->payload.abs_mem.abs)); } shd_visit_node_operands(&s2.v, 0, n); @@ -78,7 +78,7 @@ CFNode* schedule_instruction(Scheduler* s, const Node* n) { return s2.result; } -void destroy_scheduler(Scheduler* s) { +void shd_destroy_scheduler(Scheduler* s) { shd_destroy_dict(s->scheduled); free(s); } diff --git a/src/shady/analysis/scheduler.h b/src/shady/analysis/scheduler.h index 146f54284..f3fedfff4 100644 --- a/src/shady/analysis/scheduler.h +++ b/src/shady/analysis/scheduler.h @@ -6,10 +6,10 @@ typedef struct Scheduler_ Scheduler; -Scheduler* new_scheduler(CFG*); -void destroy_scheduler(Scheduler*); +Scheduler* shd_new_scheduler(CFG* cfg); +void shd_destroy_scheduler(Scheduler* s); /// Returns the CFNode where that instruction should be placed, or NULL if it can be computed at the top-level -CFNode* schedule_instruction(Scheduler*, const Node*); +CFNode* shd_schedule_instruction(Scheduler* s, const Node* n); #endif diff --git a/src/shady/analysis/uses.c b/src/shady/analysis/uses.c index 235fe8391..8b5f953bb 100644 --- a/src/shady/analysis/uses.c +++ b/src/shady/analysis/uses.c @@ -25,7 +25,7 @@ typedef struct { } UsesMapVisitor; static Use* get_last_use(UsesMap* map, const Node* n) { - Use* use = (Use*) get_first_use(map, n); + Use* use = (Use*) shd_get_first_use(map, n); if (!use) return NULL; while (use->next_use) @@ -87,21 +87,21 @@ static const UsesMap* create_uses_map_(const Node* root, const Module* m, NodeCl return uses; } -const UsesMap* create_fn_uses_map(const Node* root, NodeClass exclude) { +const UsesMap* shd_new_uses_map_fn(const Node* root, NodeClass exclude) { return create_uses_map_(root, NULL, exclude); } -const UsesMap* create_module_uses_map(const Module* m, NodeClass exclude) { +const UsesMap* shd_new_uses_map_module(const Module* m, NodeClass exclude) { return create_uses_map_(NULL, m, exclude); } -void destroy_uses_map(const UsesMap* map) { +void shd_destroy_uses_map(const UsesMap* map) { shd_destroy_arena(map->a); shd_destroy_dict(map->map); free((void*) map); } -const Use* get_first_use(const UsesMap* map, const Node* n) { +const Use* shd_get_first_use(const UsesMap* map, const Node* n) { const Use** found = shd_dict_find_value(const Node*, const Use*, map->map, n); if (found) return *found; diff --git a/src/shady/analysis/uses.h b/src/shady/analysis/uses.h index 00e3ce1ac..e6fc21140 100644 --- a/src/shady/analysis/uses.h +++ b/src/shady/analysis/uses.h @@ -9,9 +9,9 @@ typedef struct UsesMap_ UsesMap; -const UsesMap* create_fn_uses_map(const Node* root, NodeClass exclude); -const UsesMap* create_module_uses_map(const Module* m, NodeClass exclude); -void destroy_uses_map(const UsesMap*); +const UsesMap* shd_new_uses_map_fn(const Node* root, NodeClass exclude); +const UsesMap* shd_new_uses_map_module(const Module* m, NodeClass exclude); +void shd_destroy_uses_map(const UsesMap* map); typedef struct Use_ Use; struct Use_ { @@ -22,6 +22,6 @@ struct Use_ { const Use* next_use; }; -const Use* get_first_use(const UsesMap*, const Node*); +const Use* shd_get_first_use(const UsesMap* map, const Node* n); #endif diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 19f790d88..4c5d78c0a 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -47,8 +47,8 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { struct List* cfgs = build_cfgs(mod, structured_scope_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; - Scheduler* scheduler = new_scheduler(cfg); - struct Dict* set = free_frontier(scheduler, cfg, cfg->entry->node); + Scheduler* scheduler = shd_new_scheduler(cfg); + struct Dict* set = shd_free_frontier(scheduler, cfg, cfg->entry->node); if (shd_dict_count(set) > 0) { shd_log_fmt(ERROR, "Leaking variables in "); shd_log_node(ERROR, cfg->entry->node); @@ -66,8 +66,8 @@ static void verify_scoping(const CompilerConfig* config, Module* mod) { shd_error_die(); } shd_destroy_dict(set); - destroy_scheduler(scheduler); - destroy_cfg(cfg); + shd_destroy_scheduler(scheduler); + shd_destroy_cfg(cfg); } shd_destroy_list(cfgs); } @@ -148,7 +148,7 @@ static void verify_bodies(const CompilerConfig* config, Module* mod) { } } - destroy_cfg(cfg); + shd_destroy_cfg(cfg); } shd_destroy_list(cfgs); @@ -159,7 +159,7 @@ static void verify_bodies(const CompilerConfig* config, Module* mod) { } } -void verify_module(const CompilerConfig* config, Module* mod) { +void shd_verify_module(const CompilerConfig* config, Module* mod) { verify_same_arena(mod); // before we normalize the IR, scopes are broken because decls appear where they should not // TODO add a normalized flag to the IR and check grammar is adhered to strictly diff --git a/src/shady/analysis/verify.h b/src/shady/analysis/verify.h index 0a65ff4d4..85fa53682 100644 --- a/src/shady/analysis/verify.h +++ b/src/shady/analysis/verify.h @@ -4,6 +4,6 @@ #include "shady/ir.h" typedef struct CompilerConfig_ CompilerConfig; -void verify_module(const CompilerConfig*, Module*); +void shd_verify_module(const CompilerConfig* config, Module* mod); #endif diff --git a/src/shady/compile.c b/src/shady/compile.c index addf72b34..3ce720f97 100644 --- a/src/shady/compile.c +++ b/src/shady/compile.c @@ -37,7 +37,7 @@ void shd_run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* ini (*pmod)->sealed = true; shd_debugvv_print("After pass %s: \n", pass_name); if (SHADY_RUN_VERIFY) - verify_module(config, *pmod); + shd_verify_module(config, *pmod); if (shd_module_get_arena(old_mod) != shd_module_get_arena(*pmod) && shd_module_get_arena(old_mod) != initial_arena) shd_destroy_ir_arena(shd_module_get_arena(old_mod)); old_mod = *pmod; @@ -45,7 +45,7 @@ void shd_run_pass_impl(const CompilerConfig* config, Module** pmod, IrArena* ini *pmod = shd_cleanup(config, *pmod); shd_log_module(DEBUGVV, config, *pmod); if (SHADY_RUN_VERIFY) - verify_module(config, *pmod); + shd_verify_module(config, *pmod); if (shd_module_get_arena(old_mod) != shd_module_get_arena(*pmod) && shd_module_get_arena(old_mod) != initial_arena) shd_destroy_ir_arena(shd_module_get_arena(old_mod)); if (config->hooks.after_pass.fn) diff --git a/src/shady/passes/cleanup.c b/src/shady/passes/cleanup.c index 4ffc6fe63..466e20b83 100644 --- a/src/shady/passes/cleanup.c +++ b/src/shady/passes/cleanup.c @@ -17,10 +17,10 @@ typedef struct { static size_t count_calls(const UsesMap* map, const Node* bb) { size_t count = 0; - const Use* use = get_first_use(map, bb); + const Use* use = shd_get_first_use(map, bb); for (; use; use = use->next_use) { if (use->user->tag == Jump_TAG) { - const Use* jump_use = get_first_use(map, use->user); + const Use* jump_use = shd_get_first_use(map, use->user); for (; jump_use; jump_use = jump_use->next_use) { if (jump_use->operand_class == NcJump) return SIZE_MAX; // you can never inline conditional jumps @@ -33,7 +33,7 @@ static size_t count_calls(const UsesMap* map, const Node* bb) { } static bool is_used_as_value(const UsesMap* map, const Node* instr) { - const Use* use = get_first_use(map, instr); + const Use* use = shd_get_first_use(map, instr); for (; use; use = use->next_use) { if (use->operand_class == NcValue) return true; @@ -46,9 +46,9 @@ static const Node* process(Context* ctx, const Node* old) { IrArena* a = r->dst_arena; if (old->tag == Function_TAG || old->tag == Constant_TAG) { Context c = *ctx; - c.map = create_fn_uses_map(old, NcType | NcDeclaration); + c.map = shd_new_uses_map_fn(old, NcType | NcDeclaration); const Node* new = shd_recreate_node(&c.rewriter, old); - destroy_uses_map(c.map); + shd_destroy_uses_map(c.map); return new; } @@ -76,7 +76,7 @@ static const Node* process(Context* ctx, const Node* old) { } case Control_TAG: { Control payload = old->payload.control; - if (is_control_static(ctx->map, old)) { + if (shd_is_control_static(ctx->map, old)) { const Node* control_inside = payload.inside; const Node* term = get_abstraction_body(control_inside); if (term->tag == Join_TAG) { @@ -94,7 +94,7 @@ static const Node* process(Context* ctx, const Node* old) { } case Join_TAG: { Join payload = old->payload.join; - const Node* control = get_control_for_jp(ctx->map, payload.join_point); + const Node* control = shd_get_control_for_jp(ctx->map, payload.join_point); if (control) { Control old_control_payload = control->payload.control; // there was a control but now there is not anymore - jump to the tail! diff --git a/src/shady/passes/lcssa.c b/src/shady/passes/lcssa.c index a718193a4..fb4e25ffa 100644 --- a/src/shady/passes/lcssa.c +++ b/src/shady/passes/lcssa.c @@ -52,18 +52,18 @@ static void find_liftable_loop_values(Context* ctx, const Node* old, Nodes* npar IrArena* a = ctx->rewriter.dst_arena; assert(old->tag == BasicBlock_TAG); - const LTNode* bb_loop = get_loop(looptree_lookup(ctx->loop_tree, old)); + const LTNode* bb_loop = get_loop(shd_loop_tree_lookup(ctx->loop_tree, old)); *nparams = shd_empty(a); *lparams = shd_empty(a); *nargs = shd_empty(a); - struct Dict* fvs = free_frontier(ctx->scheduler, ctx->cfg, old); + struct Dict* fvs = shd_free_frontier(ctx->scheduler, ctx->cfg, old); const Node* fv; for (size_t i = 0; shd_dict_iter(fvs, &i, &fv, NULL);) { - const CFNode* defining_cf_node = schedule_instruction(ctx->scheduler, fv); + const CFNode* defining_cf_node = shd_schedule_instruction(ctx->scheduler, fv); assert(defining_cf_node); - const LTNode* defining_loop = get_loop(looptree_lookup(ctx->loop_tree, defining_cf_node->node)); + const LTNode* defining_loop = get_loop(shd_loop_tree_lookup(ctx->loop_tree, defining_cf_node->node)); if (!is_child(defining_loop, bb_loop)) { // that's it, that variable is leaking ! shd_log_fmt(DEBUGV, "lcssa: "); @@ -92,13 +92,13 @@ static const Node* process_abstraction_body(Context* ctx, const Node* old, const shd_log_module(ERROR, ctx->config, ctx->rewriter.src_module); shd_error_die(); } - const CFNode* n = cfg_lookup(ctx->cfg, old); + const CFNode* n = shd_cfg_lookup(ctx->cfg, old); size_t children_count = 0; LARRAY(const Node*, old_children, shd_list_count(n->dominates)); for (size_t i = 0; i < shd_list_count(n->dominates); i++) { CFNode* c = shd_read_list(CFNode*, n->dominates)[i]; - if (is_cfnode_structural_target(c)) + if (shd_cfg_is_node_structural_target(c)) continue; old_children[children_count++] = c->node; } @@ -152,15 +152,15 @@ static const Node* process_node(Context* ctx, const Node* old) { ctx->current_fn = old; ctx->cfg = build_fn_cfg(old); - ctx->scheduler = new_scheduler(ctx->cfg); - ctx->loop_tree = build_loop_tree(ctx->cfg); + ctx->scheduler = shd_new_scheduler(ctx->cfg); + ctx->loop_tree = shd_new_loop_tree(ctx->cfg); Node* new = shd_recreate_node_head(&ctx->rewriter, old); new->payload.fun.body = process_abstraction_body(ctx, old, get_abstraction_body(old)); - destroy_loop_tree(ctx->loop_tree); - destroy_scheduler(ctx->scheduler); - destroy_cfg(ctx->cfg); + shd_destroy_loop_tree(ctx->loop_tree); + shd_destroy_scheduler(ctx->scheduler); + shd_destroy_cfg(ctx->cfg); return new; } case Jump_TAG: { diff --git a/src/shady/passes/lift_everything.c b/src/shady/passes/lift_everything.c index a7dae8d41..99ad3fc1c 100644 --- a/src/shady/passes/lift_everything.c +++ b/src/shady/passes/lift_everything.c @@ -25,20 +25,20 @@ static const Node* process(Context* ctx, const Node* node) { case Function_TAG: { Context fn_ctx = *ctx; fn_ctx.cfg = build_fn_cfg(node); - fn_ctx.scheduler = new_scheduler(fn_ctx.cfg); + fn_ctx.scheduler = shd_new_scheduler(fn_ctx.cfg); Node* new_fn = shd_recreate_node_head(r, node); shd_recreate_node_body(&fn_ctx.rewriter, node, new_fn); - destroy_scheduler(fn_ctx.scheduler); - destroy_cfg(fn_ctx.cfg); + shd_destroy_scheduler(fn_ctx.scheduler); + shd_destroy_cfg(fn_ctx.cfg); return new_fn; } case BasicBlock_TAG: { - CFNode* n = cfg_lookup(ctx->cfg, node); - if (is_cfnode_structural_target(n)) + CFNode* n = shd_cfg_lookup(ctx->cfg, node); + if (shd_cfg_is_node_structural_target(n)) break; - struct Dict* frontier = free_frontier(ctx->scheduler, ctx->cfg, node); + struct Dict* frontier = shd_free_frontier(ctx->scheduler, ctx->cfg, node); // insert_dict(const Node*, Dict*, ctx->lift, node, frontier); Nodes additional_args = shd_empty(a); diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 5688ccf26..10b2ed6e1 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -82,14 +82,14 @@ static LiftedCont* lambda_lift(Context* ctx, CFG* cfg, const Node* liftee) { const Node* obody = get_abstraction_body(liftee); String name = shd_get_abstraction_name_safe(liftee); - Scheduler* scheduler = new_scheduler(cfg); - struct Dict* frontier_set = free_frontier(scheduler, cfg, liftee); + Scheduler* scheduler = shd_new_scheduler(cfg); + struct Dict* frontier_set = shd_free_frontier(scheduler, cfg, liftee); Nodes frontier = set2nodes(a, frontier_set); shd_destroy_dict(frontier_set); size_t recover_context_size = frontier.count; - destroy_scheduler(scheduler); + shd_destroy_scheduler(scheduler); Context lifting_ctx = *ctx; lifting_ctx.rewriter = shd_create_decl_rewriter(&ctx->rewriter); @@ -172,15 +172,15 @@ static const Node* process_node(Context* ctx, const Node* node) { Context fn_ctx = *ctx; fn_ctx.cfg = build_fn_cfg(node); - fn_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); + fn_ctx.uses = shd_new_uses_map_fn(node, (NcDeclaration | NcType)); fn_ctx.disable_lowering = shd_lookup_annotation(node, "Internal"); ctx = &fn_ctx; Node* new = shd_recreate_node_head(&ctx->rewriter, node); shd_recreate_node_body(&ctx->rewriter, node, new); - destroy_uses_map(ctx->uses); - destroy_cfg(ctx->cfg); + shd_destroy_uses_map(ctx->uses); + shd_destroy_cfg(ctx->cfg); return new; } default: @@ -193,7 +193,7 @@ static const Node* process_node(Context* ctx, const Node* node) { switch (node->tag) { case Control_TAG: { const Node* oinside = node->payload.control.inside; - if (!is_control_static(ctx->uses, node) || ctx->config->hacks.force_join_point_lifting) { + if (!shd_is_control_static(ctx->uses, node) || ctx->config->hacks.force_join_point_lifting) { *ctx->todo = true; const Node* otail = get_structured_construct_tail(node); @@ -251,7 +251,7 @@ Module* shd_pass_lift_indirect_targets(const CompilerConfig* config, Module* src } shd_destroy_dict(ctx.lifted); shd_destroy_rewriter(&ctx.rewriter); - verify_module(config, dst); + shd_verify_module(config, dst); src = dst; if (oa) shd_destroy_ir_arena(oa); diff --git a/src/shady/passes/lower_cf_instrs.c b/src/shady/passes/lower_cf_instrs.c index 5143756fd..86def4543 100644 --- a/src/shady/passes/lower_cf_instrs.c +++ b/src/shady/passes/lower_cf_instrs.c @@ -28,7 +28,7 @@ static const Node* process_node(Context* ctx, const Node* node) { sub_ctx.current_fn = fun; sub_ctx.cfg = build_fn_cfg(node); shd_set_abstraction_body(fun, shd_rewrite_node(&sub_ctx.rewriter, node->payload.fun.body)); - destroy_cfg(sub_ctx.cfg); + shd_destroy_cfg(sub_ctx.cfg); return fun; } else if (node->tag == Constant_TAG) { sub_ctx.cfg = NULL; @@ -127,7 +127,7 @@ static const Node* process_node(Context* ctx, const Node* node) { MergeSelection payload = node->payload.merge_selection; const Node* root_mem = shd_get_original_mem(payload.mem); assert(root_mem->tag == AbsMem_TAG); - CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); + CFNode* cfnode = shd_cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; const Node* selection_instr = NULL; while (dom) { @@ -161,7 +161,7 @@ static const Node* process_node(Context* ctx, const Node* node) { MergeContinue payload = node->payload.merge_continue; const Node* root_mem = shd_get_original_mem(payload.mem); assert(root_mem->tag == AbsMem_TAG); - CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); + CFNode* cfnode = shd_cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; const Node* loop_start = NULL; while (dom) { @@ -195,7 +195,7 @@ static const Node* process_node(Context* ctx, const Node* node) { MergeBreak payload = node->payload.merge_break; const Node* root_mem = shd_get_original_mem(payload.mem); assert(root_mem->tag == AbsMem_TAG); - CFNode* cfnode = cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); + CFNode* cfnode = shd_cfg_lookup(ctx->cfg, root_mem->payload.abs_mem.abs); CFNode* dom = cfnode->idom; const Node* loop_start = NULL; while (dom) { diff --git a/src/shady/passes/lower_tailcalls.c b/src/shady/passes/lower_tailcalls.c index 7e3ea7d03..c5e8c03ca 100644 --- a/src/shady/passes/lower_tailcalls.c +++ b/src/shady/passes/lower_tailcalls.c @@ -117,7 +117,7 @@ static const Node* process(Context* ctx, const Node* old) { case Function_TAG: { Context ctx2 = *ctx; ctx2.cfg = build_fn_cfg(old); - ctx2.uses = create_fn_uses_map(old, (NcDeclaration | NcType)); + ctx2.uses = shd_new_uses_map_fn(old, (NcDeclaration | NcType)); ctx = &ctx2; const Node* entry_point_annotation = shd_lookup_annotation_list(old->payload.fun.annotations, "EntryPoint"); @@ -135,8 +135,8 @@ static const Node* process(Context* ctx, const Node* old) { shd_set_abstraction_body(fun, shd_bld_finish(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); } - destroy_uses_map(ctx2.uses); - destroy_cfg(ctx2.cfg); + shd_destroy_uses_map(ctx2.uses); + shd_destroy_cfg(ctx2.cfg); return fun; } @@ -169,8 +169,8 @@ static const Node* process(Context* ctx, const Node* old) { } shd_register_processed(&ctx2.rewriter, shd_get_abstraction_mem(old), shd_bb_mem(bb)); shd_set_abstraction_body(fun, shd_bld_finish(bb, shd_rewrite_node(&ctx2.rewriter, get_abstraction_body(old)))); - destroy_uses_map(ctx2.uses); - destroy_cfg(ctx2.cfg); + shd_destroy_uses_map(ctx2.uses); + shd_destroy_cfg(ctx2.cfg); return fun; } case FnAddr_TAG: return lower_fn_addr(ctx, old->payload.fn_addr.fn); @@ -251,7 +251,7 @@ static const Node* process(Context* ctx, const Node* old) { } case Control_TAG: { Control payload = old->payload.control; - if (is_control_static(ctx->uses, old)) { + if (shd_is_control_static(ctx->uses, old)) { // const Node* old_inside = old->payload.control.inside; const Node* old_jp = shd_first(get_abstraction_params(payload.inside)); assert(old_jp->tag == Param_TAG); diff --git a/src/shady/passes/mark_leaf_functions.c b/src/shady/passes/mark_leaf_functions.c index f348d6230..2e5b84442 100644 --- a/src/shady/passes/mark_leaf_functions.c +++ b/src/shady/passes/mark_leaf_functions.c @@ -99,7 +99,7 @@ static const Node* process(Context* ctx, const Node* node) { CGNode* fn_node = *shd_dict_find_value(const Node*, CGNode*, ctx->graph->fn2cgn, node); fn_ctx.is_leaf = is_leaf_fn(ctx, fn_node); fn_ctx.cfg = build_fn_cfg(node); - fn_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); + fn_ctx.uses = shd_new_uses_map_fn(node, (NcDeclaration | NcType)); ctx = &fn_ctx; Nodes annotations = shd_rewrite_nodes(&ctx->rewriter, node->payload.fun.annotations); @@ -116,12 +116,12 @@ static const Node* process(Context* ctx, const Node* node) { })); } - destroy_uses_map(fn_ctx.uses); - destroy_cfg(fn_ctx.cfg); + shd_destroy_uses_map(fn_ctx.uses); + shd_destroy_cfg(fn_ctx.cfg); return new; } case Control_TAG: { - if (!is_control_static(ctx->uses, node)) { + if (!shd_is_control_static(ctx->uses, node)) { shd_debugv_print("Function %s can't be a leaf function because the join point ", shd_get_abstraction_name(ctx->cfg->entry->node)); shd_log_node(DEBUGV, shd_first(get_abstraction_params(node->payload.control.inside))); shd_debugv_print("escapes its control block, preventing restructuring.\n"); @@ -132,8 +132,8 @@ static const Node* process(Context* ctx, const Node* node) { case Join_TAG: { const Node* old_jp = node->payload.join.join_point; if (old_jp->tag == Param_TAG) { - const Node* control = get_control_for_jp(ctx->uses, old_jp); - if (control && is_control_static(ctx->uses, control)) + const Node* control = shd_get_control_for_jp(ctx->uses, old_jp); + if (control && shd_is_control_static(ctx->uses, control)) break; } shd_debugv_print("Function %s can't be a leaf function because it joins with ", shd_get_abstraction_name(ctx->cfg->entry->node)); @@ -158,11 +158,11 @@ Module* shd_pass_mark_leaf_functions(SHADY_UNUSED const CompilerConfig* config, Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), .fns = shd_new_dict(const Node*, FnInfo, (HashFn) shd_hash_node, (CmpFn) shd_compare_node), - .graph = new_callgraph(src) + .graph = shd_new_callgraph(src) }; shd_rewrite_module(&ctx.rewriter); shd_destroy_dict(ctx.fns); - destroy_callgraph(ctx.graph); + shd_destroy_callgraph(ctx.graph); shd_destroy_rewriter(&ctx.rewriter); return dst; } diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index abb02ecb7..4923e0f18 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -45,7 +45,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca bool ptr_u = shd_deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); - const Use* use = get_first_use(map, ptr_value); + const Use* use = shd_get_first_use(map, ptr_value); for (;use; use = use->next_use) { if (is_abstraction(use->user) && use->operand_class == NcParam) continue; @@ -174,11 +174,11 @@ static const Node* process(Context* ctx, const Node* old) { case Function_TAG: { Node* fun = shd_recreate_node_head(&ctx->rewriter, old); Context fun_ctx = *ctx; - fun_ctx.uses = create_fn_uses_map(old, (NcDeclaration | NcType)); + fun_ctx.uses = shd_new_uses_map_fn(old, (NcDeclaration | NcType)); fun_ctx.disable_lowering = shd_lookup_annotation_with_string_payload(old, "DisableOpt", "demote_alloca"); if (old->payload.fun.body) shd_set_abstraction_body(fun, shd_rewrite_node(&fun_ctx.rewriter, old->payload.fun.body)); - destroy_uses_map(fun_ctx.uses); + shd_destroy_uses_map(fun_ctx.uses); return fun; } case Constant_TAG: { diff --git a/src/shady/passes/opt_inline.c b/src/shady/passes/opt_inline.c index d561e6686..6cb4e099d 100644 --- a/src/shady/passes/opt_inline.c +++ b/src/shady/passes/opt_inline.c @@ -231,11 +231,11 @@ static void simplify_cf(const CompilerConfig* config, Module* src, Module* dst) .fun = NULL, .inlined_call = NULL, }; - ctx.graph = new_callgraph(src); + ctx.graph = shd_new_callgraph(src); shd_rewrite_module(&ctx.rewriter); if (ctx.graph) - destroy_callgraph(ctx.graph); + shd_destroy_callgraph(ctx.graph); shd_destroy_rewriter(&ctx.rewriter); } diff --git a/src/shady/passes/opt_mem2reg.c b/src/shady/passes/opt_mem2reg.c index 5297437d7..e0b178cb8 100644 --- a/src/shady/passes/opt_mem2reg.c +++ b/src/shady/passes/opt_mem2reg.c @@ -59,7 +59,7 @@ static const Node* get_last_stored_value(Context* ctx, const Node* ptr, const No switch (mem->tag) { case AbsMem_TAG: { const Node* abs = mem->payload.abs_mem.abs; - CFNode* n = cfg_lookup(ctx->cfg, abs); + CFNode* n = shd_cfg_lookup(ctx->cfg, abs); if (shd_list_count(n->pred_edges) == 1) { CFEdge e = shd_read_list(CFEdge, n->pred_edges)[0]; mem = get_terminator_mem(e.terminator); @@ -91,7 +91,7 @@ static const Node* process(Context* ctx, const Node* node) { Context fun_ctx = *ctx; fun_ctx.cfg = build_fn_cfg(node); shd_recreate_node_body(&fun_ctx.rewriter, node, new); - destroy_cfg(fun_ctx.cfg); + shd_destroy_cfg(fun_ctx.cfg); return new; } case Load_TAG: { diff --git a/src/shady/passes/reconvergence_heuristics.c b/src/shady/passes/reconvergence_heuristics.c index 852d04092..15f192ce4 100644 --- a/src/shady/passes/reconvergence_heuristics.c +++ b/src/shady/passes/reconvergence_heuristics.c @@ -24,7 +24,7 @@ typedef struct Context_ { } Context; static bool in_loop(LoopTree* lt, const Node* entry, const Node* block) { - LTNode* lt_node = looptree_lookup(lt, block); + LTNode* lt_node = shd_loop_tree_lookup(lt, block); assert(lt_node); LTNode* parent = lt_node->parent; assert(parent); @@ -92,8 +92,8 @@ static const Node* process_abstraction(Context* ctx, const Node* node) { Rewriter* rewriter = &ctx->rewriter; IrArena* arena = rewriter->dst_arena; - CFNode* current_node = cfg_lookup(ctx->fwd_cfg, node); - LTNode* lt_node = looptree_lookup(ctx->current_looptree, node); + CFNode* current_node = shd_cfg_lookup(ctx->fwd_cfg, node); + LTNode* lt_node = shd_loop_tree_lookup(ctx->current_looptree, node); LTNode* loop_header = NULL; assert(current_node); @@ -315,13 +315,13 @@ static const Node* process_node(Context* ctx, const Node* node) { ctx->current_fn = node; ctx->fwd_cfg = build_fn_cfg(ctx->current_fn); ctx->rev_cfg = build_fn_cfg_flipped(ctx->current_fn); - ctx->current_looptree = build_loop_tree(ctx->fwd_cfg); + ctx->current_looptree = shd_new_loop_tree(ctx->fwd_cfg); const Node* new = process_abstraction(ctx, node);; - destroy_cfg(ctx->fwd_cfg); - destroy_cfg(ctx->rev_cfg); - destroy_loop_tree(ctx->current_looptree); + shd_destroy_cfg(ctx->fwd_cfg); + shd_destroy_cfg(ctx->rev_cfg); + shd_destroy_loop_tree(ctx->current_looptree); return new; } case Constant_TAG: { @@ -340,18 +340,18 @@ static const Node* process_node(Context* ctx, const Node* node) { break; assert(ctx->fwd_cfg); - CFNode* cfnode = cfg_lookup(ctx->rev_cfg, ctx->current_abstraction); + CFNode* cfnode = shd_cfg_lookup(ctx->rev_cfg, ctx->current_abstraction); const Node* post_dominator = NULL; - LTNode* current_loop = looptree_lookup(ctx->current_looptree, ctx->current_abstraction)->parent; + LTNode* current_loop = shd_loop_tree_lookup(ctx->current_looptree, ctx->current_abstraction)->parent; assert(current_loop); if (shd_list_count(current_loop->cf_nodes)) { bool leaves_loop = false; - CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); + CFNode* current_node = shd_cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); for (size_t i = 0; i < shd_list_count(current_node->succ_edges); i++) { CFEdge edge = shd_read_list(CFEdge, current_node->succ_edges)[i]; - LTNode* lt_target = looptree_lookup(ctx->current_looptree, edge.dst->node); + LTNode* lt_target = shd_loop_tree_lookup(ctx->current_looptree, edge.dst->node); if (lt_target->parent != current_loop) { leaves_loop = true; @@ -361,15 +361,15 @@ static const Node* process_node(Context* ctx, const Node* node) { if (!leaves_loop) { const Node* current_loop_head = shd_read_list(CFNode*, current_loop->cf_nodes)[0]->node; - CFG* loop_cfg = build_cfg(ctx->current_fn, current_loop_head, (CFGBuildConfig) { + CFG* loop_cfg = shd_new_cfg(ctx->current_fn, current_loop_head, (CFGBuildConfig) { .include_structured_tails = true, .lt = ctx->current_looptree, .flipped = true }); - CFNode* idom_cf = cfg_lookup(loop_cfg, ctx->current_abstraction)->idom; + CFNode* idom_cf = shd_cfg_lookup(loop_cfg, ctx->current_abstraction)->idom; if (idom_cf) post_dominator = idom_cf->node; - destroy_cfg(loop_cfg); + shd_destroy_cfg(loop_cfg); } } else { post_dominator = cfnode->idom->node; @@ -379,14 +379,14 @@ static const Node* process_node(Context* ctx, const Node* node) { break; } - if (cfg_lookup(ctx->fwd_cfg, post_dominator)->idom->node != ctx->current_abstraction) + if (shd_cfg_lookup(ctx->fwd_cfg, post_dominator)->idom->node != ctx->current_abstraction) break; assert(is_abstraction(post_dominator) && post_dominator->tag != Function_TAG); - LTNode* lt_node = looptree_lookup(ctx->current_looptree, ctx->current_abstraction); - LTNode* idom_lt_node = looptree_lookup(ctx->current_looptree, post_dominator); - CFNode* current_node = cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); + LTNode* lt_node = shd_loop_tree_lookup(ctx->current_looptree, ctx->current_abstraction); + LTNode* idom_lt_node = shd_loop_tree_lookup(ctx->current_looptree, post_dominator); + CFNode* current_node = shd_cfg_lookup(ctx->fwd_cfg, ctx->current_abstraction); assert(lt_node); assert(idom_lt_node); diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 4477c1201..03dd58da8 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -79,7 +79,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab if (!obody) return; - CFNode* n = cfg_lookup(cfg, oabs); + CFNode* n = shd_cfg_lookup(cfg, oabs); size_t num_dom = shd_list_count(n->dominates); LARRAY(Node*, nbbs, num_dom); for (size_t i = 0; i < num_dom; i++) { @@ -184,9 +184,9 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed } else if (lexical_scope_is_nested(*src_lexical_scope, *dst_lexical_scope)) { shd_debug_print("Jump from %s to %s exits one or more nested lexical scopes, it might reconverge.\n", shd_get_abstraction_name_safe(src), shd_get_abstraction_name_safe(dst)); - CFNode* src_cfnode = cfg_lookup(cfg, src); + CFNode* src_cfnode = shd_cfg_lookup(cfg, src); assert(src_cfnode->node); - CFNode* dst_cfnode = cfg_lookup(cfg, dst); + CFNode* dst_cfnode = shd_cfg_lookup(cfg, dst); assert(src_cfnode && dst_cfnode); // if(!cfg_is_dominated(dst_cfnode, src_cfnode)) @@ -204,7 +204,7 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed shd_error_print("We went up too far: %s is a parent of the jump destination scope.\n", shd_get_abstraction_name_safe(dom->node)); } else if (shd_compare_nodes(dom_lexical_scope, dst_lexical_scope)) { // if (cfg_is_dominated(target_cfnode, dom)) { - if (!cfg_is_dominated(dom, dst_cfnode) && dst_cfnode != dom) { + if (!shd_cfg_is_dominated(dom, dst_cfnode) && dst_cfnode != dom) { // assert(false); } @@ -253,14 +253,14 @@ static void process_edge(Context* ctx, CFG* cfg, Scheduler* scheduler, CFEdge ed } static void prepare_function(Context* ctx, CFG* cfg, const Node* old_fn) { - Scheduler* scheduler = new_scheduler(cfg); + Scheduler* scheduler = shd_new_scheduler(cfg); for (size_t i = 0; i < cfg->size; i++) { CFNode* n = cfg->rpo[i]; for (size_t j = 0; j < shd_list_count(n->succ_edges); j++) { process_edge(ctx, cfg, scheduler, shd_read_list(CFEdge, n->succ_edges)[j]); } } - destroy_scheduler(scheduler); + shd_destroy_scheduler(scheduler); } static const Node* process_node(Context* ctx, const Node* node) { @@ -272,7 +272,7 @@ static const Node* process_node(Context* ctx, const Node* node) { prepare_function(ctx, cfg, node); Node* decl = shd_recreate_node_head(r, node); wrap_in_controls(ctx, cfg, decl, node); - destroy_cfg(cfg); + shd_destroy_cfg(cfg); return decl; } case BasicBlock_TAG: { diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index ec62ea09f..e138aa854 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -60,7 +60,7 @@ static void paint_dominated_up_to_postdom(CFNode* n, IrArena* a, Nodes* arr, con } static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* flipped, LTNode* loop, LoopTree* lt) { - LTNode* ltn = looptree_lookup(lt, n->node); + LTNode* ltn = shd_loop_tree_lookup(lt, n->node); if (ltn->parent != loop) return; @@ -74,7 +74,7 @@ static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* fl if (shd_list_count(src->succ_edges) < 2) return; // no divergence, no bother - CFNode* f_src = cfg_lookup(flipped, src->node); + CFNode* f_src = shd_cfg_lookup(flipped, src->node); CFNode* f_src_ipostdom = f_src->idom; if (!f_src_ipostdom) return; @@ -82,8 +82,8 @@ static void visit_acyclic_cfg_domtree(CFNode* n, IrArena* a, Nodes* arr, CFG* fl // your post-dominator can't be yourself... can it ? assert(f_src_ipostdom->node != src->node); - LTNode* src_lt = looptree_lookup(lt, src->node); - LTNode* pst_lt = looptree_lookup(lt, f_src_ipostdom->node); + LTNode* src_lt = shd_loop_tree_lookup(lt, src->node); + LTNode* pst_lt = shd_loop_tree_lookup(lt, f_src_ipostdom->node); assert(src_lt->type == LF_LEAF && pst_lt->type == LF_LEAF); if (src_lt->parent == pst_lt->parent) { shd_log_fmt(DEBUGVV, "We have a candidate for reconvergence: a branch starts at %d and ends at %d\n", src->node->id, f_src_ipostdom->node->id); @@ -107,7 +107,7 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, } assert(shd_list_count(node->cf_nodes) < 2); - CFG* sub_cfg = build_cfg(fn, is_loop ? shd_read_list(CFNode*, node->cf_nodes)[0]->node : fn, (CFGBuildConfig) { + CFG* sub_cfg = shd_new_cfg(fn, is_loop ? shd_read_list(CFNode*, node->cf_nodes)[0]->node : fn, (CFGBuildConfig) { .include_structured_tails = true, .lt = lt }); @@ -126,7 +126,7 @@ static void visit_looptree(IrArena* a, Nodes* arr, const Node* fn, CFG* flipped, arr[n->rpo_index] = shd_nodes(a, old.count - 1, &old.nodes[0]); } - destroy_cfg(sub_cfg); + shd_destroy_cfg(sub_cfg); } } @@ -145,7 +145,7 @@ static bool loop_depth(LTNode* a) { static Nodes* compute_scope_depth(IrArena* a, CFG* cfg) { CFG* flipped = build_fn_cfg_flipped(cfg->entry->node); - LoopTree* lt = build_loop_tree(cfg); + LoopTree* lt = shd_new_loop_tree(cfg); Nodes* arr = calloc(sizeof(Nodes), cfg->size); for (size_t i = 0; i < cfg->size; i++) @@ -157,8 +157,8 @@ static Nodes* compute_scope_depth(IrArena* a, CFG* cfg) { for (size_t i = 0; i < cfg->size; i++) arr[i] = to_ids(a, arr[i]); - destroy_loop_tree(lt); - destroy_cfg(flipped); + shd_destroy_loop_tree(lt); + shd_destroy_cfg(flipped); return arr; } @@ -176,7 +176,7 @@ static const Node* process(Context* ctx, const Node* node) { gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), shd_empty(a)); shd_register_processed(r, shd_get_abstraction_mem(node), shd_bb_mem(bb)); shd_set_abstraction_body(new_fn, shd_bld_finish(bb, shd_rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); - destroy_cfg(fn_ctx.cfg); + shd_destroy_cfg(fn_ctx.cfg); free(fn_ctx.depth_per_rpo); return new_fn; } @@ -186,7 +186,7 @@ static const Node* process(Context* ctx, const Node* node) { Node* new_bb = basic_block(a, nparams, shd_get_abstraction_name_unsafe(node)); shd_register_processed(r, node, new_bb); BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_bb)); - CFNode* n = cfg_lookup(ctx->cfg, node); + CFNode* n = shd_cfg_lookup(ctx->cfg, node); gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); shd_register_processed(r, shd_get_abstraction_mem(node), shd_bb_mem(bb)); shd_set_abstraction_body(new_bb, shd_bld_finish(bb, shd_rewrite_node(r, get_abstraction_body(node)))); diff --git a/src/shady/print.c b/src/shady/print.c index 18c49e75e..fdec1190a 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -265,7 +265,7 @@ static void print_basic_block(PrinterCtx* ctx, const CFNode* node) { static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { Growy* g = shd_new_growy(); Printer* p = shd_new_printer_from_growy(g); - CFNode* cfnode = ctx->cfg ? cfg_lookup(ctx->cfg, abs) : NULL; + CFNode* cfnode = ctx->cfg ? shd_cfg_lookup(ctx->cfg, abs) : NULL; if (cfnode) ctx->bb_printers[cfnode->rpo_index] = p; @@ -305,13 +305,13 @@ static void print_function(PrinterCtx* ctx, const Node* node) { sub_ctx.fn = node; if (node->arena->config.name_bound) { CFGBuildConfig cfg_config = structured_scope_cfg_build(); - CFG* cfg = build_cfg(node, node, cfg_config); + CFG* cfg = shd_new_cfg(node, node, cfg_config); sub_ctx.cfg = cfg; - sub_ctx.scheduler = new_scheduler(cfg); + sub_ctx.scheduler = shd_new_scheduler(cfg); sub_ctx.bb_growies = calloc(sizeof(size_t), cfg->size); sub_ctx.bb_printers = calloc(sizeof(size_t), cfg->size); if (node->arena->config.check_types && node->arena->config.allow_fold) { - sub_ctx.uses = create_fn_uses_map(node, (NcDeclaration | NcType)); + sub_ctx.uses = shd_new_uses_map_fn(node, (NcDeclaration | NcType)); } } ctx = &sub_ctx; @@ -333,11 +333,11 @@ static void print_function(PrinterCtx* ctx, const Node* node) { if (sub_ctx.cfg) { if (sub_ctx.uses) - destroy_uses_map(sub_ctx.uses); + shd_destroy_uses_map(sub_ctx.uses); free(sub_ctx.bb_printers); free(sub_ctx.bb_growies); - destroy_cfg(sub_ctx.cfg); - destroy_scheduler(sub_ctx.scheduler); + shd_destroy_cfg(sub_ctx.cfg); + shd_destroy_scheduler(sub_ctx.scheduler); } } @@ -1038,7 +1038,7 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { String s = shd_printer_growy_unwrap(ctx2.printer); Printer* p = ctx->root_printer; if (ctx->scheduler) { - CFNode* dst = schedule_instruction(ctx->scheduler, node); + CFNode* dst = shd_schedule_instruction(ctx->scheduler, node); if (dst) p = ctx2.bb_printers[dst->rpo_index]; } diff --git a/src/shady/visit.c b/src/shady/visit.c index 5c4d6da54..29cabb205 100644 --- a/src/shady/visit.c +++ b/src/shady/visit.c @@ -39,7 +39,7 @@ void shd_visit_function_rpo(Visitor* visitor, const Node* function) { const Node* node = cfg->rpo[i]->node; shd_visit_node(visitor, node); } - destroy_cfg(cfg); + shd_destroy_cfg(cfg); } void shd_visit_function_bodies_rpo(Visitor* visitor, const Node* function) { @@ -52,7 +52,7 @@ void shd_visit_function_bodies_rpo(Visitor* visitor, const Node* function) { if (get_abstraction_body(node)) shd_visit_node(visitor, get_abstraction_body(node)); } - destroy_cfg(cfg); + shd_destroy_cfg(cfg); } #pragma GCC diagnostic error "-Wswitch" diff --git a/test/test_builder.c b/test/test_builder.c index eddde2ee1..51efa033b 100644 --- a/test/test_builder.c +++ b/test/test_builder.c @@ -65,7 +65,7 @@ static void test_body_builder_fun_body(IrArena* a) { break; mem = omem; CHECK(mem->tag == AbsMem_TAG, exit(-1)); - CFNode* n = cfg_lookup(cfg, mem->payload.abs_mem.abs); + CFNode* n = shd_cfg_lookup(cfg, mem->payload.abs_mem.abs); if (n->idom) { mem = get_terminator_mem(get_abstraction_body(n->idom->node)); continue; @@ -78,7 +78,7 @@ static void test_body_builder_fun_body(IrArena* a) { } while (1); mem = shd_get_original_mem(mem); CHECK(mem == shd_get_abstraction_mem(fun), exit(-1)); - destroy_cfg(cfg); + shd_destroy_cfg(cfg); } /// There is some "magic" code in body_builder and shd_set_abstraction_body to enable inserting control-flow From a482d7cf4d3e0d04f9f6bb425a37ae8582a076d1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:37:38 +0200 Subject: [PATCH 671/693] check.c: prefix with _shd_ --- src/shady/api/generator_type.c | 4 +- src/shady/check.c | 112 ++++++++++++++++----------------- src/shady/generator_type.c | 4 +- 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/shady/api/generator_type.c b/src/shady/api/generator_type.c index aa72bda2e..8445c591b 100644 --- a/src/shady/api/generator_type.c +++ b/src/shady/api/generator_type.c @@ -21,9 +21,9 @@ void generate(Growy* g, json_object* src) { if (!t || json_object_get_boolean(t)) { json_object* ops = json_object_object_get(node, "ops"); if (ops) - shd_growy_append_formatted(g, "const Type* check_type_%s(IrArena*, %s);\n", snake_name, name); + shd_growy_append_formatted(g, "const Type* _shd_check_type_%s(IrArena*, %s);\n", snake_name, name); else - shd_growy_append_formatted(g, "const Type* check_type_%s(IrArena*);\n", snake_name); + shd_growy_append_formatted(g, "const Type* _shd_check_type_%s(IrArena*);\n", snake_name); } if (alloc) diff --git a/src/shady/check.c b/src/shady/check.c index 14b038b21..fe4cce8ce 100644 --- a/src/shady/check.c +++ b/src/shady/check.c @@ -24,14 +24,14 @@ static bool are_types_identical(size_t num_types, const Type* types[]) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" -const Type* check_type_join_point_type(IrArena* arena, JoinPointType type) { +const Type* _shd_check_type_join_point_type(IrArena* arena, JoinPointType type) { for (size_t i = 0; i < type.yield_types.count; i++) { assert(shd_is_data_type(type.yield_types.nodes[i])); } return NULL; } -const Type* check_type_record_type(IrArena* arena, RecordType type) { +const Type* _shd_check_type_record_type(IrArena* arena, RecordType type) { assert(type.names.count == 0 || type.names.count == type.members.count); for (size_t i = 0; i < type.members.count; i++) { // member types are value types iff this is a return tuple @@ -43,23 +43,23 @@ const Type* check_type_record_type(IrArena* arena, RecordType type) { return NULL; } -const Type* check_type_qualified_type(IrArena* arena, QualifiedType qualified_type) { +const Type* _shd_check_type_qualified_type(IrArena* arena, QualifiedType qualified_type) { assert(shd_is_data_type(qualified_type.type)); assert(arena->config.is_simt || qualified_type.is_uniform); return NULL; } -const Type* check_type_arr_type(IrArena* arena, ArrType type) { +const Type* _shd_check_type_arr_type(IrArena* arena, ArrType type) { assert(shd_is_data_type(type.element_type)); return NULL; } -const Type* check_type_pack_type(IrArena* arena, PackType pack_type) { +const Type* _shd_check_type_pack_type(IrArena* arena, PackType pack_type) { assert(shd_is_data_type(pack_type.element_type)); return NULL; } -const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { +const Type* _shd_check_type_ptr_type(IrArena* arena, PtrType ptr_type) { if (!arena->config.address_spaces[ptr_type.address_space].allowed) { shd_error_print("Address space %s is not allowed in this arena\n", shd_get_address_space_name(ptr_type.address_space)); shd_error_die(); @@ -85,33 +85,33 @@ const Type* check_type_ptr_type(IrArena* arena, PtrType ptr_type) { return NULL; } -const Type* check_type_param(IrArena* arena, Param variable) { +const Type* _shd_check_type_param(IrArena* arena, Param variable) { assert(shd_is_value_type(variable.type)); return variable.type; } -const Type* check_type_untyped_number(IrArena* arena, UntypedNumber untyped) { +const Type* _shd_check_type_untyped_number(IrArena* arena, UntypedNumber untyped) { shd_error("should never happen"); } -const Type* check_type_int_literal(IrArena* arena, IntLiteral lit) { +const Type* _shd_check_type_int_literal(IrArena* arena, IntLiteral lit) { return qualified_type(arena, (QualifiedType) { .is_uniform = true, .type = int_type(arena, (Int) { .width = lit.width, .is_signed = lit.is_signed }) }); } -const Type* check_type_float_literal(IrArena* arena, FloatLiteral lit) { +const Type* _shd_check_type_float_literal(IrArena* arena, FloatLiteral lit) { return qualified_type(arena, (QualifiedType) { .is_uniform = true, .type = float_type(arena, (Float) { .width = lit.width }) }); } -const Type* check_type_true_lit(IrArena* arena) { return qualified_type(arena, (QualifiedType) { .type = bool_type(arena), .is_uniform = true }); } -const Type* check_type_false_lit(IrArena* arena) { return qualified_type(arena, (QualifiedType) { .type = bool_type(arena), .is_uniform = true }); } +const Type* _shd_check_type_true_lit(IrArena* arena) { return qualified_type(arena, (QualifiedType) { .type = bool_type(arena), .is_uniform = true }); } +const Type* _shd_check_type_false_lit(IrArena* arena) { return qualified_type(arena, (QualifiedType) { .type = bool_type(arena), .is_uniform = true }); } -const Type* check_type_string_lit(IrArena* arena, StringLiteral str_lit) { +const Type* _shd_check_type_string_lit(IrArena* arena, StringLiteral str_lit) { const Type* t = arr_type(arena, (ArrType) { .element_type = shd_int8_type(arena), .size = shd_int32_literal(arena, strlen(str_lit.string)) @@ -122,12 +122,12 @@ const Type* check_type_string_lit(IrArena* arena, StringLiteral str_lit) { }); } -const Type* check_type_null_ptr(IrArena* a, NullPtr payload) { +const Type* _shd_check_type_null_ptr(IrArena* a, NullPtr payload) { assert(shd_is_data_type(payload.ptr_type) && payload.ptr_type->tag == PtrType_TAG); return shd_as_qualified_type(payload.ptr_type, true); } -const Type* check_type_composite(IrArena* arena, Composite composite) { +const Type* _shd_check_type_composite(IrArena* arena, Composite composite) { if (composite.type) { assert(shd_is_data_type(composite.type)); Nodes expected_member_types = shd_get_composite_type_element_types(composite.type); @@ -158,7 +158,7 @@ const Type* check_type_composite(IrArena* arena, Composite composite) { }); } -const Type* check_type_fill(IrArena* arena, Fill payload) { +const Type* _shd_check_type_fill(IrArena* arena, Fill payload) { assert(shd_is_data_type(payload.type)); const Node* element_t = shd_get_fill_type_element_type(payload.type); const Node* value_t = payload.value->type; @@ -170,7 +170,7 @@ const Type* check_type_fill(IrArena* arena, Fill payload) { }); } -const Type* check_type_undef(IrArena* arena, Undef payload) { +const Type* _shd_check_type_undef(IrArena* arena, Undef payload) { assert(shd_is_data_type(payload.type)); return qualified_type(arena, (QualifiedType) { .is_uniform = true, @@ -178,11 +178,11 @@ const Type* check_type_undef(IrArena* arena, Undef payload) { }); } -const Type* check_type_mem_and_value(IrArena* arena, MemAndValue mav) { +const Type* _shd_check_type_mem_and_value(IrArena* arena, MemAndValue mav) { return mav.value->type; } -const Type* check_type_fn_addr(IrArena* arena, FnAddr fn_addr) { +const Type* _shd_check_type_fn_addr(IrArena* arena, FnAddr fn_addr) { assert(fn_addr.fn->type->tag == FnType_TAG); assert(fn_addr.fn->tag == Function_TAG); return qualified_type(arena, (QualifiedType) { @@ -194,7 +194,7 @@ const Type* check_type_fn_addr(IrArena* arena, FnAddr fn_addr) { }); } -const Type* check_type_ref_decl(IrArena* arena, RefDecl ref_decl) { +const Type* _shd_check_type_ref_decl(IrArena* arena, RefDecl ref_decl) { const Type* t = ref_decl.decl->type; assert(t && "RefDecl needs to be applied on a decl with a non-null type. Did you forget to set 'type' on a constant ?"); switch (ref_decl.decl->tag) { @@ -209,7 +209,7 @@ const Type* check_type_ref_decl(IrArena* arena, RefDecl ref_decl) { }); } -const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { +const Type* _shd_check_type_prim_op(IrArena* arena, PrimOp prim_op) { for (size_t i = 0; i < prim_op.type_arguments.count; i++) { const Node* ta = prim_op.type_arguments.nodes[i]; assert(ta && is_type(ta)); @@ -576,7 +576,7 @@ const Type* check_type_prim_op(IrArena* arena, PrimOp prim_op) { } } -const Type* check_type_ext_instr(IrArena* arena, ExtInstr payload) { +const Type* _shd_check_type_ext_instr(IrArena* arena, ExtInstr payload) { return payload.result_t; } @@ -604,7 +604,7 @@ static Nodes check_value_call(const Node* callee, Nodes argument_types) { return fn_type->return_types; } -const Type* check_type_call(IrArena* arena, Call call) { +const Type* _shd_check_type_call(IrArena* arena, Call call) { Nodes args = call.args; for (size_t i = 0; i < args.count; i++) { const Node* argument = args.nodes[i]; @@ -626,7 +626,7 @@ static void ensure_types_are_value_types(const Nodes* yield_types) { } } -const Type* check_type_if_instr(IrArena* arena, If if_instr) { +const Type* _shd_check_type_if_instr(IrArena* arena, If if_instr) { assert(if_instr.tail && is_abstraction(if_instr.tail)); ensure_types_are_data_types(&if_instr.yield_types); if (shd_get_unqualified_type(if_instr.condition->type) != bool_type(arena)) @@ -639,21 +639,21 @@ const Type* check_type_if_instr(IrArena* arena, If if_instr) { return noret_type(arena); } -const Type* check_type_match_instr(IrArena* arena, Match match_instr) { +const Type* _shd_check_type_match_instr(IrArena* arena, Match match_instr) { ensure_types_are_data_types(&match_instr.yield_types); // TODO check param against initial_args // TODO check the contained Merge instrs return noret_type(arena); } -const Type* check_type_loop_instr(IrArena* arena, Loop loop_instr) { +const Type* _shd_check_type_loop_instr(IrArena* arena, Loop loop_instr) { ensure_types_are_data_types(&loop_instr.yield_types); // TODO check param against initial_args // TODO check the contained Merge instrs return noret_type(arena); } -const Type* check_type_control(IrArena* arena, Control control) { +const Type* _shd_check_type_control(IrArena* arena, Control control) { ensure_types_are_data_types(&control.yield_types); // TODO check it then ! const Node* join_point = shd_first(get_abstraction_params(control.inside)); @@ -673,11 +673,11 @@ const Type* check_type_control(IrArena* arena, Control control) { return noret_type(arena); } -const Type* check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { +const Type* _shd_check_type_comment(IrArena* arena, SHADY_UNUSED Comment payload) { return empty_multiple_return_type(arena); } -const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { +const Type* _shd_check_type_stack_alloc(IrArena* a, StackAlloc alloc) { assert(is_type(alloc.type)); return qualified_type(a, (QualifiedType) { .is_uniform = shd_is_addr_space_uniform(a, AsPrivate), @@ -689,7 +689,7 @@ const Type* check_type_stack_alloc(IrArena* a, StackAlloc alloc) { }); } -const Type* check_type_local_alloc(IrArena* a, LocalAlloc alloc) { +const Type* _shd_check_type_local_alloc(IrArena* a, LocalAlloc alloc) { assert(is_type(alloc.type)); return qualified_type(a, (QualifiedType) { .is_uniform = shd_is_addr_space_uniform(a, AsFunction), @@ -701,7 +701,7 @@ const Type* check_type_local_alloc(IrArena* a, LocalAlloc alloc) { }); } -const Type* check_type_load(IrArena* a, Load load) { +const Type* _shd_check_type_load(IrArena* a, Load load) { const Node* ptr_type = load.ptr->type; bool ptr_uniform = shd_deconstruct_qualified_type(&ptr_type); size_t width = shd_deconstruct_maybe_packed_type(&ptr_type); @@ -714,7 +714,7 @@ const Type* check_type_load(IrArena* a, Load load) { ptr_uniform && shd_is_addr_space_uniform(a, ptr_type->payload.ptr_type.address_space)); } -const Type* check_type_store(IrArena* a, Store store) { +const Type* _shd_check_type_store(IrArena* a, Store store) { const Node* ptr_type = store.ptr->type; bool ptr_uniform = shd_deconstruct_qualified_type(&ptr_type); size_t width = shd_deconstruct_maybe_packed_type(&ptr_type); @@ -733,7 +733,7 @@ const Type* check_type_store(IrArena* a, Store store) { return empty_multiple_return_type(a); } -const Type* check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffset lea) { +const Type* _shd_check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffset lea) { const Type* base_ptr_type = lea.ptr->type; bool uniform = shd_deconstruct_qualified_type(&base_ptr_type); assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); @@ -760,7 +760,7 @@ const Type* check_type_ptr_array_element_offset(IrArena* a, PtrArrayElementOffse }); } -const Type* check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea) { +const Type* _shd_check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea) { const Type* base_ptr_type = lea.ptr->type; bool uniform = shd_deconstruct_qualified_type(&base_ptr_type); assert(base_ptr_type->tag == PtrType_TAG && "lea expects a ptr or ref as a base"); @@ -778,7 +778,7 @@ const Type* check_type_ptr_composite_element(IrArena* a, PtrCompositeElement lea }); } -const Type* check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { +const Type* _shd_check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { const Type* dst_t = copy_bytes.dst->type; shd_deconstruct_qualified_type(&dst_t); assert(dst_t->tag == PtrType_TAG); @@ -791,7 +791,7 @@ const Type* check_type_copy_bytes(IrArena* a, CopyBytes copy_bytes) { return empty_multiple_return_type(a); } -const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { +const Type* _shd_check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { const Type* dst_t = fill_bytes.dst->type; shd_deconstruct_qualified_type(&dst_t); assert(dst_t->tag == PtrType_TAG); @@ -804,34 +804,34 @@ const Type* check_type_fill_bytes(IrArena* a, FillBytes fill_bytes) { return empty_multiple_return_type(a); } -const Type* check_type_push_stack(IrArena* a, PushStack payload) { +const Type* _shd_check_type_push_stack(IrArena* a, PushStack payload) { assert(payload.value); return empty_multiple_return_type(a); } -const Type* check_type_pop_stack(IrArena* a, PopStack payload) { +const Type* _shd_check_type_pop_stack(IrArena* a, PopStack payload) { return shd_as_qualified_type(payload.type, false); } -const Type* check_type_set_stack_size(IrArena* a, SetStackSize payload) { +const Type* _shd_check_type_set_stack_size(IrArena* a, SetStackSize payload) { assert(shd_get_unqualified_type(payload.value->type) == shd_uint32_type(a)); return shd_as_qualified_type(unit_type(a), true); } -const Type* check_type_get_stack_size(IrArena* a, SHADY_UNUSED GetStackSize ss) { +const Type* _shd_check_type_get_stack_size(IrArena* a, SHADY_UNUSED GetStackSize ss) { return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = shd_uint32_type(a) }); } -const Type* check_type_get_stack_base_addr(IrArena* a, SHADY_UNUSED GetStackBaseAddr gsba) { +const Type* _shd_check_type_get_stack_base_addr(IrArena* a, SHADY_UNUSED GetStackBaseAddr gsba) { const Node* ptr = ptr_type(a, (PtrType) { .pointed_type = shd_uint8_type(a), .address_space = AsPrivate}); return qualified_type(a, (QualifiedType) { .is_uniform = false, .type = ptr }); } -const Type* check_type_debug_printf(IrArena* a, DebugPrintf payload) { +const Type* _shd_check_type_debug_printf(IrArena* a, DebugPrintf payload) { return empty_multiple_return_type(a); } -const Type* check_type_tail_call(IrArena* arena, TailCall tail_call) { +const Type* _shd_check_type_tail_call(IrArena* arena, TailCall tail_call) { Nodes args = tail_call.args; for (size_t i = 0; i < args.count; i++) { const Node* argument = args.nodes[i]; @@ -848,7 +848,7 @@ static void check_basic_block_call(const Node* block, Nodes argument_types) { check_arguments_types_against_parameters_helper(bb_type.param_types, argument_types); } -const Type* check_type_jump(IrArena* arena, Jump jump) { +const Type* _shd_check_type_jump(IrArena* arena, Jump jump) { for (size_t i = 0; i < jump.args.count; i++) { const Node* argument = jump.args.nodes[i]; assert(is_value(argument)); @@ -858,13 +858,13 @@ const Type* check_type_jump(IrArena* arena, Jump jump) { return noret_type(arena); } -const Type* check_type_branch(IrArena* arena, Branch payload) { +const Type* _shd_check_type_branch(IrArena* arena, Branch payload) { assert(payload.true_jump->tag == Jump_TAG); assert(payload.false_jump->tag == Jump_TAG); return noret_type(arena); } -const Type* check_type_br_switch(IrArena* arena, Switch payload) { +const Type* _shd_check_type_br_switch(IrArena* arena, Switch payload) { for (size_t i = 0; i < payload.case_jumps.count; i++) assert(payload.case_jumps.nodes[i]->tag == Jump_TAG); assert(payload.case_values.count == payload.case_jumps.count); @@ -872,7 +872,7 @@ const Type* check_type_br_switch(IrArena* arena, Switch payload) { return noret_type(arena); } -const Type* check_type_join(IrArena* arena, Join join) { +const Type* _shd_check_type_join(IrArena* arena, Join join) { for (size_t i = 0; i < join.args.count; i++) { const Node* argument = join.args.nodes[i]; assert(is_value(argument)); @@ -891,43 +891,43 @@ const Type* check_type_join(IrArena* arena, Join join) { return noret_type(arena); } -const Type* check_type_unreachable(IrArena* arena, SHADY_UNUSED Unreachable u) { +const Type* _shd_check_type_unreachable(IrArena* arena, SHADY_UNUSED Unreachable u) { return noret_type(arena); } -const Type* check_type_merge_continue(IrArena* arena, MergeContinue mc) { +const Type* _shd_check_type_merge_continue(IrArena* arena, MergeContinue mc) { // TODO check it return noret_type(arena); } -const Type* check_type_merge_break(IrArena* arena, MergeBreak mc) { +const Type* _shd_check_type_merge_break(IrArena* arena, MergeBreak mc) { // TODO check it return noret_type(arena); } -const Type* check_type_merge_selection(IrArena* arena, SHADY_UNUSED MergeSelection payload) { +const Type* _shd_check_type_merge_selection(IrArena* arena, SHADY_UNUSED MergeSelection payload) { // TODO check it return noret_type(arena); } -const Type* check_type_fn_ret(IrArena* arena, Return ret) { +const Type* _shd_check_type_fn_ret(IrArena* arena, Return ret) { // assert(ret.fn); // TODO check it then ! return noret_type(arena); } -const Type* check_type_fun(IrArena* arena, Function fn) { +const Type* _shd_check_type_fun(IrArena* arena, Function fn) { for (size_t i = 0; i < fn.return_types.count; i++) { assert(shd_is_value_type(fn.return_types.nodes[i])); } return fn_type(arena, (FnType) { .param_types = shd_get_param_types(arena, (&fn)->params), .return_types = (&fn)->return_types }); } -const Type* check_type_basic_block(IrArena* arena, BasicBlock bb) { +const Type* _shd_check_type_basic_block(IrArena* arena, BasicBlock bb) { return bb_type(arena, (BBType) { .param_types = shd_get_param_types(arena, (&bb)->params) }); } -const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_variable) { +const Type* _shd_check_type_global_variable(IrArena* arena, GlobalVariable global_variable) { assert(is_type(global_variable.type)); const Node* ba = shd_lookup_annotation_list(global_variable.annotations, "Builtin"); @@ -954,7 +954,7 @@ const Type* check_type_global_variable(IrArena* arena, GlobalVariable global_var }); } -const Type* check_type_constant(IrArena* arena, Constant cnst) { +const Type* _shd_check_type_constant(IrArena* arena, Constant cnst) { assert(shd_is_data_type(cnst.type_hint)); return cnst.type_hint; } diff --git a/src/shady/generator_type.c b/src/shady/generator_type.c index eb247892c..11043b6b3 100644 --- a/src/shady/generator_type.c +++ b/src/shady/generator_type.c @@ -25,9 +25,9 @@ void generate(Growy* g, json_object* src) { shd_growy_append_formatted(g, "\t\tcase %s_TAG: ", name); json_object* ops = json_object_object_get(node, "ops"); if (ops) - shd_growy_append_formatted(g, "return check_type_%s(a, node->payload.%s);\n", snake_name, snake_name); + shd_growy_append_formatted(g, "return _shd_check_type_%s(a, node->payload.%s);\n", snake_name, snake_name); else - shd_growy_append_formatted(g, "return check_type_%s(a);\n", snake_name); + shd_growy_append_formatted(g, "return _shd_check_type_%s(a);\n", snake_name); } if (alloc) From 0c09c3f36cdf221d2d60f9ed8191204e016d7200 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:48:03 +0200 Subject: [PATCH 672/693] grammar_generator: use more static inline functions --- src/shady/api/generator_grammar.c | 59 +++++++++++++++++++++--- src/shady/generator/generator.h | 1 + src/shady/generator/generator_common.c | 14 ++++++ src/shady/generator_node.c | 63 +------------------------- 4 files changed, 69 insertions(+), 68 deletions(-) diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index ddc4d1761..7126304c2 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -118,6 +118,23 @@ static void generate_node_tags_for_class(Growy* g, json_object* nodes, String cl shd_growy_append_formatted(g, "} %sTag;\n\n", capitalized_class); } +static void generate_isa_for_class(Growy* g, json_object* nodes, String class, String capitalized_class, bool use_enum) { + assert(json_object_get_type(nodes) == json_type_array); + if (use_enum) + shd_growy_append_formatted(g, "static inline %sTag is_%s(const Node* node) {\n", capitalized_class, class); + else + shd_growy_append_formatted(g, "static inline bool is_%s(const Node* node) {\n", class); + shd_growy_append_formatted(g, "\tif (get_node_class_from_tag(node->tag) & Nc%s)\n", capitalized_class); + if (use_enum) { + shd_growy_append_formatted(g, "\t\treturn (%sTag) node->tag;\n", capitalized_class); + shd_growy_append_formatted(g, "\treturn (%sTag) 0;\n", capitalized_class); + } else { + shd_growy_append_formatted(g, "\t\treturn true;\n", capitalized_class); + shd_growy_append_formatted(g, "\treturn false;\n", capitalized_class); + } + shd_growy_append_formatted(g, "}\n\n"); +} + static void generate_header_getters_for_class(Growy* g, json_object* src, json_object* node_class) { String class_name = json_object_get_string(json_object_object_get(node_class, "name")); json_object* class_ops = json_object_object_get(node_class, "ops"); @@ -199,6 +216,35 @@ void generate_node_ctor(Growy* g, json_object* src, json_object* nodes) { shd_growy_append_formatted(g, "\n"); } +static void generate_getters_for_class(Growy* g, json_object* src, json_object* nodes, json_object* node_class) { + String class_name = json_object_get_string(json_object_object_get(node_class, "name")); + json_object* class_ops = json_object_object_get(node_class, "ops"); + if (!class_ops) + return; + assert(json_object_get_type(class_ops) == json_type_array); + for (size_t i = 0; i < json_object_array_length(class_ops); i++) { + json_object* operand = json_object_array_get_idx(class_ops, i); + String operand_name = json_object_get_string(json_object_object_get(operand, "name")); + assert(operand_name); + shd_growy_append_formatted(g, "static inline %s get_%s_%s(const Node* node) {\n", get_type_for_operand(src, operand), class_name, operand_name); + shd_growy_append_formatted(g, "\tswitch(node->tag) {\n"); + for (size_t j = 0; j < json_object_array_length(nodes); j++) { + json_object* node = json_object_array_get_idx(nodes, j); + if (find_in_set(json_object_object_get(node, "class"), class_name)) { + String node_name = json_object_get_string(json_object_object_get(node, "name")); + shd_growy_append_formatted(g, "\t\tcase %s_TAG: ", node_name); + String node_snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); + assert(node_snake_name); + shd_growy_append_formatted(g, "return node->payload.%s.%s;\n", node_snake_name, operand_name); + } + } + shd_growy_append_formatted(g, "\t\tdefault: break;\n"); + shd_growy_append_formatted(g, "\t}\n"); + shd_growy_append_formatted(g, "\tassert(false);\n"); + shd_growy_append_formatted(g, "}\n\n"); + } +} + void generate(Growy* g, json_object* src) { generate_header(g, src); @@ -214,6 +260,7 @@ void generate(Growy* g, json_object* src) { generate_node_type(g, nodes); shd_growy_append_formatted(g, "#include \n"); + shd_growy_append_formatted(g, "#include \n"); shd_growy_append_formatted(g, "Node* _shd_create_node_helper(IrArena* arena, Node node, bool* pfresh);\n"); generate_node_ctor(g, src, nodes); @@ -222,15 +269,15 @@ void generate(Growy* g, json_object* src) { String name = json_object_get_string(json_object_object_get(node_class, "name")); assert(name); json_object* generate_enum = json_object_object_get(node_class, "generate-enum"); + String capitalized = capitalize(name); + if (!generate_enum || json_object_get_boolean(generate_enum)) { - String capitalized = capitalize(name); generate_node_tags_for_class(g, nodes, name, capitalized); - shd_growy_append_formatted(g, "%sTag is_%s(const Node*);\n", capitalized, name); - free((void*) capitalized); - } else { - shd_growy_append_formatted(g, "bool is_%s(const Node*);\n", name); } - generate_header_getters_for_class(g, src, node_class); + //generate_header_getters_for_class(g, src, node_class); + generate_getters_for_class(g, src, nodes, node_class); + generate_isa_for_class(g, nodes, name, capitalized, !generate_enum || json_object_get_boolean(generate_enum)); + free((void*) capitalized); } } diff --git a/src/shady/generator/generator.h b/src/shady/generator/generator.h index a9facaef1..7c9e72fbb 100644 --- a/src/shady/generator/generator.h +++ b/src/shady/generator/generator.h @@ -24,6 +24,7 @@ bool starts_with_vowel(String str); bool has_custom_ctor(json_object* node); json_object* lookup_node_class(json_object* src, String name); +bool find_in_set(json_object* node, String class_name); String class_to_type(json_object* src, String class, bool list); String get_type_for_operand(json_object* src, json_object* op); diff --git a/src/shady/generator/generator_common.c b/src/shady/generator/generator_common.c index 3b915b8d3..3cad55662 100644 --- a/src/shady/generator/generator_common.c +++ b/src/shady/generator/generator_common.c @@ -33,6 +33,20 @@ String class_to_type(json_object* src, String class, bool list) { return list ? "Nodes" : "const Node*"; } +bool find_in_set(json_object* node, String class_name) { + switch (json_object_get_type(node)) { + case json_type_array: { + for (size_t i = 0; i < json_object_array_length(node); i++) + if (find_in_set(json_object_array_get_idx(node, i), class_name)) + return true; + break; + } + case json_type_string: return strcmp(json_object_get_string(node), class_name) == 0; + default: break; + } + return false; +} + String get_type_for_operand(json_object* src, json_object* op) { String op_type = json_object_get_string(json_object_object_get(op, "type")); bool list = json_object_get_boolean(json_object_object_get(op, "list")); diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 5b6661992..8b1554ea6 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -128,66 +128,6 @@ static void generate_node_is_nominal(Growy* g, json_object* nodes) { shd_growy_append_formatted(g, "}\n"); } -static void generate_isa_for_class(Growy* g, json_object* nodes, String class, String capitalized_class, bool use_enum) { - assert(json_object_get_type(nodes) == json_type_array); - if (use_enum) - shd_growy_append_formatted(g, "%sTag is_%s(const Node* node) {\n", capitalized_class, class); - else - shd_growy_append_formatted(g, "bool is_%s(const Node* node) {\n", class); - shd_growy_append_formatted(g, "\tif (get_node_class_from_tag(node->tag) & Nc%s)\n", capitalized_class); - if (use_enum) { - shd_growy_append_formatted(g, "\t\treturn (%sTag) node->tag;\n", capitalized_class); - shd_growy_append_formatted(g, "\treturn (%sTag) 0;\n", capitalized_class); - } else { - shd_growy_append_formatted(g, "\t\treturn true;\n", capitalized_class); - shd_growy_append_formatted(g, "\treturn false;\n", capitalized_class); - } - shd_growy_append_formatted(g, "}\n\n"); -} - -static bool is_of(json_object* node, String class_name) { - switch (json_object_get_type(node)) { - case json_type_array: { - for (size_t i = 0; i < json_object_array_length(node); i++) - if (is_of(json_object_array_get_idx(node, i), class_name)) - return true; - break; - } - case json_type_string: return strcmp(json_object_get_string(node), class_name) == 0; - default: break; - } - return false; -} - -static void generate_getters_for_class(Growy* g, json_object* src, json_object* nodes, json_object* node_class) { - String class_name = json_object_get_string(json_object_object_get(node_class, "name")); - json_object* class_ops = json_object_object_get(node_class, "ops"); - if (!class_ops) - return; - assert(json_object_get_type(class_ops) == json_type_array); - for (size_t i = 0; i < json_object_array_length(class_ops); i++) { - json_object* operand = json_object_array_get_idx(class_ops, i); - String operand_name = json_object_get_string(json_object_object_get(operand, "name")); - assert(operand_name); - shd_growy_append_formatted(g, "%s get_%s_%s(const Node* node) {\n", get_type_for_operand(src, operand), class_name, operand_name); - shd_growy_append_formatted(g, "\tswitch(node->tag) {\n"); - for (size_t j = 0; j < json_object_array_length(nodes); j++) { - json_object* node = json_object_array_get_idx(nodes, j); - if (is_of(json_object_object_get(node, "class"), class_name)) { - String node_name = json_object_get_string(json_object_object_get(node, "name")); - shd_growy_append_formatted(g, "\t\tcase %s_TAG: ", node_name); - String node_snake_name = json_object_get_string(json_object_object_get(node, "snake_name")); - assert(node_snake_name); - shd_growy_append_formatted(g, "return node->payload.%s.%s;\n", node_snake_name, operand_name); - } - } - shd_growy_append_formatted(g, "\t\tdefault: break;\n"); - shd_growy_append_formatted(g, "\t}\n"); - shd_growy_append_formatted(g, "\tassert(false);\n"); - shd_growy_append_formatted(g, "}\n\n"); - } -} - void generate_address_space_name_fn(Growy* g, json_object* address_spaces) { shd_growy_append_formatted(g, "String shd_get_address_space_name(AddressSpace as) {\n"); shd_growy_append_formatted(g, "\tswitch (as) {\n"); @@ -218,11 +158,10 @@ void generate(Growy* g, json_object* src) { String name = json_object_get_string(json_object_object_get(node_class, "name")); assert(name); - generate_getters_for_class(g, src, nodes, node_class); + //generate_getters_for_class(g, src, nodes, node_class); json_object* generate_enum = json_object_object_get(node_class, "generate-enum"); String capitalized = capitalize(name); - generate_isa_for_class(g, nodes, name, capitalized, !generate_enum || json_object_get_boolean(generate_enum)); free((void*) capitalized); } } From d2f9fa907f3835b39df8b8854a943d7c532342d0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:51:46 +0200 Subject: [PATCH 673/693] s2s: make everything static --- src/frontend/spirv/s2s.c | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index c34b7266d..d3c8007fc 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -95,16 +95,16 @@ typedef struct { struct Dict* phi_arguments; } SpvParser; -SpvDef* get_definition_by_id(SpvParser* parser, size_t id); +static SpvDef* get_definition_by_id(SpvParser* parser, size_t id); -SpvDef* new_def(SpvParser* parser) { +static SpvDef* new_def(SpvParser* parser) { SpvDef* interned = shd_arena_alloc(parser->decorations_arena, sizeof(SpvDef)); SpvDef empty = {0}; memcpy(interned, &empty, sizeof(SpvDef)); return interned; } -void add_decoration(SpvParser* parser, SpvId id, SpvDeco decoration) { +static void add_decoration(SpvParser* parser, SpvId id, SpvDeco decoration) { SpvDef* tgt_def = &parser->defs[id]; while (tgt_def->next_decoration) { tgt_def = &tgt_def->next_decoration->payload; @@ -114,7 +114,7 @@ void add_decoration(SpvParser* parser, SpvId id, SpvDeco decoration) { tgt_def->next_decoration = interned; } -SpvDeco* find_decoration(SpvParser* parser, SpvId id, int member, SpvDecoration tag) { +static SpvDeco* find_decoration(SpvParser* parser, SpvId id, int member, SpvDecoration tag) { SpvDef* tgt_def = &parser->defs[id]; while (tgt_def->next_decoration) { if (tgt_def->next_decoration->decoration == tag && (member < 0 || tgt_def->next_decoration->member == member)) @@ -124,21 +124,21 @@ SpvDeco* find_decoration(SpvParser* parser, SpvId id, int member, SpvDecoration return NULL; } -String get_name(SpvParser* parser, SpvId id) { +static String get_name(SpvParser* parser, SpvId id) { SpvDeco* deco = find_decoration(parser, id, -1, ShdDecorationName); if (!deco) return NULL; return deco->payload.str; } -String get_member_name(SpvParser* parser, SpvId id, int member_id) { +static String get_member_name(SpvParser* parser, SpvId id, int member_id) { SpvDeco* deco = find_decoration(parser, id, member_id, ShdDecorationName); if (!deco) return NULL; return deco->payload.str; } -const Type* get_def_type(SpvParser* parser, SpvId id) { +static const Type* get_def_type(SpvParser* parser, SpvId id) { SpvDef* def = get_definition_by_id(parser, id); assert(def->type == Typ); const Node* t = def->node; @@ -146,7 +146,7 @@ const Type* get_def_type(SpvParser* parser, SpvId id) { return t; } -const Type* get_def_decl(SpvParser* parser, SpvId id) { +static const Type* get_def_decl(SpvParser* parser, SpvId id) { SpvDef* def = get_definition_by_id(parser, id); assert(def->type == Decl); const Node* n = def->node; @@ -154,13 +154,13 @@ const Type* get_def_decl(SpvParser* parser, SpvId id) { return n; } -String get_def_string(SpvParser* parser, SpvId id) { +static String get_def_string(SpvParser* parser, SpvId id) { SpvDef* def = get_definition_by_id(parser, id); assert(def->type == Str); return def->str; } -const Type* get_def_ssa_value(SpvParser* parser, SpvId id) { +static const Type* get_def_ssa_value(SpvParser* parser, SpvId id) { SpvDef* def = get_definition_by_id(parser, id); const Node* n = def->node; if (is_declaration(n)) @@ -169,7 +169,7 @@ const Type* get_def_ssa_value(SpvParser* parser, SpvId id) { return n; } -const Type* get_def_block(SpvParser* parser, SpvId id) { +static const Type* get_def_block(SpvParser* parser, SpvId id) { SpvDef* def = get_definition_by_id(parser, id); assert(def->type == BB); const Node* n = def->node; @@ -177,7 +177,7 @@ const Type* get_def_block(SpvParser* parser, SpvId id) { return n; } -bool parse_spv_header(SpvParser* parser) { +static bool parse_spv_header(SpvParser* parser) { assert(parser->cursor == 0); assert(parser->len >= 4); assert(parser->words[0] == SpvMagicNumber); @@ -192,12 +192,12 @@ bool parse_spv_header(SpvParser* parser) { return true; } -String decode_spv_string_literal(SpvParser* parser, uint32_t* at) { +static String decode_spv_string_literal(SpvParser* parser, uint32_t* at) { // TODO: assumes little endian return string(shd_module_get_arena(parser->mod), (const char*) at); } -AddressSpace convert_storage_class(SpvStorageClass class) { +static AddressSpace convert_storage_class(SpvStorageClass class) { switch (class) { case SpvStorageClassInput: return AsInput; case SpvStorageClassOutput: return AsOutput; @@ -330,7 +330,7 @@ static SpvShdOpMapping spv_shd_op_mapping[] = { // honestly none of those are implemented ... }; -const SpvShdOpMapping* convert_spv_op(SpvOp src) { +static const SpvShdOpMapping* convert_spv_op(SpvOp src) { const int nentries = sizeof(spv_shd_op_mapping) / sizeof(*spv_shd_op_mapping); if (src >= nentries) return NULL; @@ -339,7 +339,7 @@ const SpvShdOpMapping* convert_spv_op(SpvOp src) { return NULL; } -SpvId get_result_defined_at(SpvParser* parser, size_t instruction_offset) { +static SpvId get_result_defined_at(SpvParser* parser, size_t instruction_offset) { uint32_t* instruction = parser->words + instruction_offset; SpvOp op = instruction[0] & 0xFFFF; @@ -356,7 +356,7 @@ SpvId get_result_defined_at(SpvParser* parser, size_t instruction_offset) { shd_error("no result defined at offset %zu", instruction_offset); } -void scan_definitions(SpvParser* parser) { +static void scan_definitions(SpvParser* parser) { size_t old_cursor = parser->cursor; while (true) { size_t available = parser->len - parser->cursor; @@ -384,7 +384,7 @@ void scan_definitions(SpvParser* parser) { parser->cursor = old_cursor; } -Nodes get_args_from_phi(SpvParser* parser, SpvId block, SpvId predecessor) { +static Nodes get_args_from_phi(SpvParser* parser, SpvId block, SpvId predecessor) { SpvDef* block_def = get_definition_by_id(parser, block); assert(block_def->type == BB && block_def->node); int params_count = block_def->node->payload.basic_block.params.count; @@ -416,7 +416,7 @@ Nodes get_args_from_phi(SpvParser* parser, SpvId block, SpvId predecessor) { return shd_nodes(parser->arena, params_count, params); } -size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { +static size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { IrArena* a = parser->arena; uint32_t* instruction = parser->words + instruction_offset; SpvOp op = instruction[0] & 0xFFFF; @@ -1322,7 +1322,7 @@ size_t parse_spv_instruction_at(SpvParser* parser, size_t instruction_offset) { return size; } -SpvDef* get_definition_by_id(SpvParser* parser, size_t id) { +static SpvDef* get_definition_by_id(SpvParser* parser, size_t id) { assert(id > 0 && id < parser->header.bound); if (parser->defs[id].type == Nothing) shd_error("there is no Op that defines result %zu", id); @@ -1332,11 +1332,11 @@ SpvDef* get_definition_by_id(SpvParser* parser, size_t id) { return &parser->defs[id]; } -KeyHash hash_spvid(SpvId* p) { +static KeyHash hash_spvid(SpvId* p) { return shd_hash(p, sizeof(SpvId)); } -bool compare_spvid(SpvId* pa, SpvId* pb) { +static bool compare_spvid(SpvId* pa, SpvId* pb) { if (pa == pb) return true; if (!pa || !pb) return false; return *pa == *pb; From e687f63cc3943baaeb6e692806800a0b7528bc76 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:53:46 +0200 Subject: [PATCH 674/693] spvb: fix issues with namespacing --- src/backend/spirv/emit_spv.c | 2 +- src/backend/spirv/emit_spv_control_flow.c | 12 ++++++------ src/backend/spirv/spirv_builder.c | 4 ++-- src/backend/spirv/spirv_builder.h | 4 ++-- src/frontend/llvm/l2s_instr.c | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 8b4281864..2d159b8c4 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -57,7 +57,7 @@ static void emit_basic_block(Emitter* emitter, FnBuilder* fn_builder, const CFNo // Find the preassigned ID to this BBBuilder bb_builder = spv_find_basic_block_builder(emitter, bb_node); - SpvId bb_id = get_block_builder_id(bb_builder); + SpvId bb_id = spvb_get_block_builder_id(bb_builder); spvb_add_bb(fn_builder->base, bb_builder); String name = shd_get_abstraction_name_safe(bb_node); diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 9b54dbddb..cdc027d6d 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -16,7 +16,7 @@ BBBuilder spv_find_basic_block_builder(Emitter* emitter, const Node* bb) { } static void add_phis(Emitter* emitter, FnBuilder* fn_builder, SpvId src, BBBuilder dst_builder, Nodes args) { - struct List* phis = spbv_get_phis(dst_builder); + struct List* phis = spvb_get_phis(dst_builder); assert(shd_list_count(phis) == args.count); for (size_t i = 0; i < args.count; i++) { SpvbPhi* phi = shd_read_list(SpvbPhi*, phis)[i]; @@ -29,7 +29,7 @@ static void add_branch_phis(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b // (which is actually a Function in this IR, not a BasicBlock) // we assert that the destination must be an actual BasicBlock assert(is_basic_block(dst)); - add_phis(emitter, fn_builder, get_block_builder_id(bb_builder), spv_find_basic_block_builder(emitter, dst), args); + add_phis(emitter, fn_builder, spvb_get_block_builder_id(bb_builder), spv_find_basic_block_builder(emitter, dst), args); } static void add_branch_phis_from_jump(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Jump jump) { @@ -104,11 +104,11 @@ static void emit_loop(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_buil SpvId header_phi_id = spvb_fresh_id(emitter->file_builder); SpvbPhi* header_phi = spvb_add_phi(header_builder, loop_param_type, header_phi_id); SpvId param_initial_value = spv_emit_value(emitter, fn_builder, loop_instr.initial_args.nodes[i]); - spvb_add_phi_source(header_phi, get_block_builder_id(bb_builder), param_initial_value); - spvb_add_phi_source(header_phi, get_block_builder_id(continue_builder), continue_phi_id); + spvb_add_phi_source(header_phi, spvb_get_block_builder_id(bb_builder), param_initial_value); + spvb_add_phi_source(header_phi, spvb_get_block_builder_id(continue_builder), continue_phi_id); BBBuilder body_builder = spv_find_basic_block_builder(emitter, loop_instr.body); - spvb_add_phi_source(shd_read_list(SpvbPhi*, spbv_get_phis(body_builder))[i], get_block_builder_id(header_builder), header_phi_id); + spvb_add_phi_source(shd_read_list(SpvbPhi*, spvb_get_phis(body_builder))[i], spvb_get_block_builder_id(header_builder), header_phi_id); } fn_builder->per_bb[shd_cfg_lookup(fn_builder->cfg, loop_instr.body)->rpo_index].continue_id = continue_id; @@ -236,7 +236,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi CFNode* loop_body = shd_cfg_lookup(fn_builder->cfg, loop_payload.body); assert(loop_body); Nodes args = terminator->payload.merge_continue.args; - add_phis(emitter, fn_builder, get_block_builder_id(basic_block_builder), fn_builder->per_bb[loop_body->rpo_index].continue_builder, args); + add_phis(emitter, fn_builder, spvb_get_block_builder_id(basic_block_builder), fn_builder->per_bb[loop_body->rpo_index].continue_builder, args); spvb_branch(basic_block_builder, fn_builder->per_bb[loop_body->rpo_index].continue_id); return; } diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index a8e4ce52a..5e3cfa9fe 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -660,7 +660,7 @@ void spvb_add_bb(SpvbFnBuilder* fn_builder, SpvbBasicBlockBuilder* bb_builder) { shd_list_append(SpvbBasicBlockBuilder*, fn_builder->bbs, bb_builder); } -SpvId get_block_builder_id(SpvbBasicBlockBuilder* basic_block_builder) { +SpvId spvb_get_block_builder_id(SpvbBasicBlockBuilder* basic_block_builder) { return basic_block_builder->label; } SpvbPhi* spvb_add_phi(SpvbBasicBlockBuilder* bb_builder, SpvId type, SpvId id) { @@ -677,7 +677,7 @@ void spvb_add_phi_source(SpvbPhi* phi, SpvId source_block, SpvId value) { shd_list_append(SpvbPhi, phi->preds, op); } -struct List* spbv_get_phis(SpvbBasicBlockBuilder* bb_builder) { +struct List* spvb_get_phis(SpvbBasicBlockBuilder* bb_builder) { return bb_builder->phis; } diff --git a/src/backend/spirv/spirv_builder.h b/src/backend/spirv/spirv_builder.h index 024648232..11fd4b0b6 100644 --- a/src/backend/spirv/spirv_builder.h +++ b/src/backend/spirv/spirv_builder.h @@ -77,11 +77,11 @@ SpvbFnBuilder* spvb_get_fn_builder(SpvbBasicBlockBuilder*); /// Actually adds the basic block to the function /// This is a separate action from begin_bb because the ordering in which the basic blocks are written matters... void spvb_add_bb(SpvbFnBuilder*, SpvbBasicBlockBuilder*); -SpvId get_block_builder_id(SpvbBasicBlockBuilder*); +SpvId spvb_get_block_builder_id(SpvbBasicBlockBuilder* basic_block_builder); SpvbPhi* spvb_add_phi(SpvbBasicBlockBuilder*, SpvId type, SpvId id); void spvb_add_phi_source(SpvbPhi*, SpvId source_block, SpvId value); -struct List* spbv_get_phis(SpvbBasicBlockBuilder*); +struct List* spvb_get_phis(SpvbBasicBlockBuilder* bb_builder); // Normal instructions SpvId spvb_op(SpvbBasicBlockBuilder*, SpvOp op, SpvId result_type, size_t operands_count, SpvId operands[]); diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index 0df76306d..b8d8bb7f0 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -41,7 +41,7 @@ static Nodes reinterpret_operands(BodyBuilder* b, Nodes ops, const Type* dst_t) return shd_nodes(a, ops.count, nops); } -LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { +static LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { while (true) { if (LLVMIsAInstruction(v) || LLVMIsAConstantExpr(v)) { if (LLVMGetInstructionOpcode(v) == LLVMBitCast) { From b0da0819da88c709fa4993ac5ef325ff4bca59b6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 16:58:38 +0200 Subject: [PATCH 675/693] c: prefix everything with shd_ --- include/shady/be/c.h | 2 +- src/backend/c/emit_c.c | 94 ++++++------- src/backend/c/emit_c.h | 54 +++---- src/backend/c/emit_c_builtin.c | 2 +- src/backend/c/emit_c_control_flow.c | 52 +++---- src/backend/c/emit_c_type.c | 46 +++--- src/backend/c/emit_c_value.c | 210 ++++++++++++++-------------- src/driver/cli.c | 2 +- 8 files changed, 231 insertions(+), 231 deletions(-) diff --git a/include/shady/be/c.h b/include/shady/be/c.h index db18d4c7d..d16a7292f 100644 --- a/include/shady/be/c.h +++ b/include/shady/be/c.h @@ -18,7 +18,7 @@ typedef struct { int glsl_version; } CEmitterConfig; -CEmitterConfig default_c_emitter_config(void); +CEmitterConfig shd_default_c_emitter_config(void); typedef struct CompilerConfig_ CompilerConfig; void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Module* mod, size_t* output_size, char** output, Module** new_mod); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 6928a8f70..dd1611071 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -24,12 +24,12 @@ KeyHash shd_hash_node(Node** pnode); bool shd_compare_node(Node** pa, Node** pb); -void register_emitted(Emitter* emitter, FnEmitter* fn, const Node* node, CTerm as) { +void shd_c_register_emitted(Emitter* emitter, FnEmitter* fn, const Node* node, CTerm as) { //assert(as.value || as.var); shd_dict_insert(const Node*, CTerm, fn ? fn->emitted_terms : emitter->emitted_terms, node, as); } -CTerm* lookup_existing_term(Emitter* emitter, FnEmitter* fn, const Node* node) { +CTerm* shd_c_lookup_existing_term(Emitter* emitter, FnEmitter* fn, const Node* node) { CTerm* found = NULL; if (fn) found = shd_dict_find_value(const Node*, CTerm, fn->emitted_terms, node); @@ -38,16 +38,16 @@ CTerm* lookup_existing_term(Emitter* emitter, FnEmitter* fn, const Node* node) { return found; } -void register_emitted_type(Emitter* emitter, const Node* node, String as) { +void shd_c_register_emitted_type(Emitter* emitter, const Node* node, String as) { shd_dict_insert(const Node*, String, emitter->emitted_types, node, as); } -CType* lookup_existing_type(Emitter* emitter, const Type* node) { +CType* shd_c_lookup_existing_type(Emitter* emitter, const Type* node) { CType* found = shd_dict_find_value(const Node*, CType, emitter->emitted_types, node); return found; } -CValue to_cvalue(SHADY_UNUSED Emitter* e, CTerm term) { +CValue shd_c_to_ssa(SHADY_UNUSED Emitter* e, CTerm term) { if (term.value) return term.value; if (term.var) @@ -55,7 +55,7 @@ CValue to_cvalue(SHADY_UNUSED Emitter* e, CTerm term) { assert(false); } -CAddr deref_term(Emitter* e, CTerm term) { +CAddr shd_c_deref(Emitter* e, CTerm term) { if (term.value) return shd_format_string_arena(e->arena->arena, "(*%s)", term.value); if (term.var) @@ -64,7 +64,7 @@ CAddr deref_term(Emitter* e, CTerm term) { } // TODO: utf8 -static bool c_is_legal_identifier_char(char c) { +static bool is_legal_identifier_char(char c) { if (c >= '0' && c <= '9') return true; if (c >= 'a' && c <= 'z') @@ -76,7 +76,7 @@ static bool c_is_legal_identifier_char(char c) { return false; } -String c_legalize_identifier(Emitter* e, String src) { +String shd_c_legalize_identifier(Emitter* e, String src) { if (!src) return "unnamed"; size_t len = strlen(src); @@ -84,7 +84,7 @@ String c_legalize_identifier(Emitter* e, String src) { size_t i; for (i = 0; i < len; i++) { char c = src[i]; - if (c_is_legal_identifier_char(c)) + if (is_legal_identifier_char(c)) dst[i] = c; else dst[i] = '_'; @@ -105,17 +105,17 @@ static bool has_forward_declarations(CDialect dialect) { } /// hack for ISPC: there is no nice way to get a set of varying pointers (instead of a "pointer to a varying") pointing to a varying global -CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term) { +CTerm shd_ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term) { String interm = shd_make_unique_name(emitter->arena, "intermediary_ptr_value"); assert(ptr_type->tag == PtrType_TAG); const Type* ut = shd_as_qualified_type(ptr_type, true); const Type* vt = shd_as_qualified_type(ptr_type, false); - String lhs = c_emit_type(emitter, vt, interm); - shd_print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, c_emit_type(emitter, ut, NULL), to_cvalue(emitter, term)); + String lhs = shd_c_emit_type(emitter, vt, interm); + shd_print(block_printer, "\n%s = ((%s) %s) + programIndex;", lhs, shd_c_emit_type(emitter, ut, NULL), shd_c_to_ssa(emitter, term)); return term_from_cvalue(interm); } -void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer) { +void shd_c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer) { assert((mut || initializer != NULL) && "unbound results are only allowed when creating a mutable local variable"); String prefix = ""; @@ -136,26 +136,26 @@ void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const break; } - String decl = c_emit_type(emitter, t, center); + String decl = shd_c_emit_type(emitter, t, center); if (initializer) - shd_print(block_printer, "\n%s%s = %s;", prefix, decl, to_cvalue(emitter, *initializer)); + shd_print(block_printer, "\n%s%s = %s;", prefix, decl, shd_c_to_ssa(emitter, *initializer)); else shd_print(block_printer, "\n%s%s;", prefix, decl); } -void c_emit_pack_code(Printer* p, Strings src, String dst) { +void shd_c_emit_pack_code(Printer* p, Strings src, String dst) { for (size_t i = 0; i < src.count; i++) { shd_print(p, "\n%s->_%d = %s", dst, src.strings[i], i); } } -void c_emit_unpack_code(Printer* p, String src, Strings dst) { +void shd_c_emit_unpack_code(Printer* p, String src, Strings dst) { for (size_t i = 0; i < dst.count; i++) { shd_print(p, "\n%s = %s->_%d", dst.strings[i], src, i); } } -void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String name, const Type* type, bool constant, String init) { +void shd_c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String name, const Type* type, bool constant, String init) { String prefix = NULL; bool is_fs = emitter->compiler_config->specialization.execution_model == EmFragment; @@ -229,9 +229,9 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String } if (init) - shd_print(emitter->fn_decls, "\n%s%s = %s;", prefix, c_emit_type(emitter, type, name), init); + shd_print(emitter->fn_decls, "\n%s%s = %s;", prefix, shd_c_emit_type(emitter, type, name), init); else - shd_print(emitter->fn_decls, "\n%s%s;", prefix, c_emit_type(emitter, type, name)); + shd_print(emitter->fn_decls, "\n%s%s;", prefix, shd_c_emit_type(emitter, type, name)); //if (!has_forward_declarations(emitter->config.dialect) || !init) // return; @@ -240,16 +240,16 @@ void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String //shd_print(emitter->fn_decls, "\n%s;", declaration); } -void c_emit_decl(Emitter* emitter, const Node* decl) { +void shd_c_emit_decl(Emitter* emitter, const Node* decl) { assert(is_declaration(decl)); - CTerm* found = lookup_existing_term(emitter, NULL, decl); + CTerm* found = shd_c_lookup_existing_term(emitter, NULL, decl); if (found) return; - CType* found2 = lookup_existing_type(emitter, decl); + CType* found2 = shd_c_lookup_existing_type(emitter, decl); if (found2) return; - const char* name = c_legalize_identifier(emitter, get_declaration_name(decl)); + const char* name = shd_c_legalize_identifier(emitter, get_declaration_name(decl)); const Type* decl_type = decl->type; const char* decl_center = name; CTerm emit_as; @@ -258,7 +258,7 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { case GlobalVariable_TAG: { String init = NULL; if (decl->payload.global_variable.init) - init = to_cvalue(emitter, c_emit_value(emitter, NULL, decl->payload.global_variable.init)); + init = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, NULL, decl->payload.global_variable.init)); AddressSpace ass = decl->payload.global_variable.address_space; if (ass == AsInput || ass == AsOutput) init = NULL; @@ -266,15 +266,15 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { const GlobalVariable* gvar = &decl->payload.global_variable; if (shd_is_decl_builtin(decl)) { Builtin b = shd_get_decl_builtin(decl); - CTerm t = c_emit_builtin(emitter, b); - register_emitted(emitter, NULL, decl, t); + CTerm t = shd_c_emit_builtin(emitter, b); + shd_c_register_emitted(emitter, NULL, decl, t); return; } if (ass == AsOutput && emitter->compiler_config->specialization.execution_model == EmFragment) { int location = shd_get_int_literal_value(*shd_resolve_to_int_literal(shd_get_annotation_value(shd_lookup_annotation(decl, "Location"))), false); CTerm t = term_from_cvar(shd_fmt_string_irarena(emitter->arena, "gl_FragData[%d]", location)); - register_emitted(emitter, NULL, decl, t); + shd_c_register_emitted(emitter, NULL, decl, t); return; } @@ -283,25 +283,25 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { emit_as = term_from_cvar(name); if ((decl->payload.global_variable.address_space == AsPrivate) && emitter->config.dialect == CDialect_CUDA) { if (emitter->use_private_globals) { - register_emitted(emitter, NULL, decl, term_from_cvar(shd_format_string_arena(emitter->arena->arena, "__shady_private_globals->%s", name))); + shd_c_register_emitted(emitter, NULL, decl, term_from_cvar(shd_format_string_arena(emitter->arena->arena, "__shady_private_globals->%s", name))); // HACK return; } emit_as = term_from_cvar(shd_fmt_string_irarena(emitter->arena, "__shady_thread_local_access(%s)", name)); if (init) init = shd_fmt_string_irarena(emitter->arena, "__shady_replicate_thread_local(%s)", init); - register_emitted(emitter, NULL, decl, emit_as); + shd_c_register_emitted(emitter, NULL, decl, emit_as); } - register_emitted(emitter, NULL, decl, emit_as); + shd_c_register_emitted(emitter, NULL, decl, emit_as); AddressSpace as = decl->payload.global_variable.address_space; - c_emit_global_variable_definition(emitter, as, decl_center, decl_type, false, init); + shd_c_emit_global_variable_definition(emitter, as, decl_center, decl_type, false, init); return; } case Function_TAG: { emit_as = term_from_cvalue(name); - register_emitted(emitter, NULL, decl, emit_as); - String head = c_emit_fn_head(emitter, decl->type, name, decl); + shd_c_register_emitted(emitter, NULL, decl, emit_as); + String head = shd_c_emit_fn_head(emitter, decl->type, name, decl); const Node* body = decl->payload.fun.body; if (body) { FnEmitter fn = { @@ -316,11 +316,11 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { for (size_t i = 0; i < decl->payload.fun.params.count; i++) { String param_name; String variable_name = shd_get_value_name_unsafe(decl->payload.fun.params.nodes[i]); - param_name = shd_fmt_string_irarena(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); - register_emitted(emitter, &fn, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); + param_name = shd_fmt_string_irarena(emitter->arena, "%s_%d", shd_c_legalize_identifier(emitter, variable_name), decl->payload.fun.params.nodes[i]->id); + shd_c_register_emitted(emitter, &fn, decl->payload.fun.params.nodes[i], term_from_cvalue(param_name)); } - String fn_body = c_emit_body(emitter, &fn, decl); + String fn_body = shd_c_emit_body(emitter, &fn, decl); if (emitter->config.dialect == CDialect_ISPC) { // ISPC hack: This compiler (like seemingly all LLVM-based compilers) has broken handling of the execution mask - it fails to generated masked stores for the entry BB of a function that may be called non-uniformingly // therefore we must tell ISPC to please, pretty please, mask everything by branching on what the mask should be @@ -352,19 +352,19 @@ void c_emit_decl(Emitter* emitter, const Node* decl) { } case Constant_TAG: { emit_as = term_from_cvalue(name); - register_emitted(emitter, NULL, decl, emit_as); + shd_c_register_emitted(emitter, NULL, decl, emit_as); - String init = to_cvalue(emitter, c_emit_value(emitter, NULL, decl->payload.constant.value)); - c_emit_global_variable_definition(emitter, AsGlobal, decl_center, decl->type, true, init); + String init = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, NULL, decl->payload.constant.value)); + shd_c_emit_global_variable_definition(emitter, AsGlobal, decl_center, decl->type, true, init); return; } case NominalType_TAG: { CType emitted = name; - register_emitted_type(emitter, decl, emitted); + shd_c_register_emitted_type(emitter, decl, emitted); switch (emitter->config.dialect) { case CDialect_ISPC: - default: shd_print(emitter->type_decls, "\ntypedef %s;", c_emit_type(emitter, decl->payload.nom_type.body, emitted)); break; - case CDialect_GLSL: c_emit_nominal_type_body(emitter, shd_format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; + default: shd_print(emitter->type_decls, "\ntypedef %s;", shd_c_emit_type(emitter, decl->payload.nom_type.body, emitted)); break; + case CDialect_GLSL: shd_c_emit_nominal_type_body(emitter, shd_format_string_arena(emitter->arena->arena, "struct %s /* nominal */", emitted), decl->payload.nom_type.body); break; } return; } @@ -401,7 +401,7 @@ static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { AddressSpace as = decl->payload.global_variable.address_space; if (as != AsPrivate) continue; - shd_print(p, "%s;\n", c_emit_type(emitter, decl->payload.global_variable.type, decl->payload.global_variable.name)); + shd_print(p, "%s;\n", shd_c_emit_type(emitter, decl->payload.global_variable.type, decl->payload.global_variable.name)); count++; } shd_print(p, "} __shady_PrivateGlobals;\n"); @@ -414,7 +414,7 @@ static String collect_private_globals_in_struct(Emitter* emitter, Module* m) { return shd_printer_growy_unwrap(p); } -CEmitterConfig default_c_emitter_config(void) { +CEmitterConfig shd_default_c_emitter_config(void) { return (CEmitterConfig) { .glsl_version = 420, }; @@ -479,7 +479,7 @@ void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Mo shd_print(finalp, "}\n"); shd_print(finalp, shady_cuda_prelude_src); - shd_print(emitter.type_decls, "\ntypedef %s;\n", c_emit_type(&emitter, arr_type(arena, (ArrType) { + shd_print(emitter.type_decls, "\ntypedef %s;\n", shd_c_emit_type(&emitter, arr_type(arena, (ArrType) { .size = shd_int32_literal(arena, 3), .element_type = shd_uint32_type(arena) }), "uvec3")); @@ -498,7 +498,7 @@ void shd_emit_c(const CompilerConfig* compiler_config, CEmitterConfig config, Mo Nodes decls = shd_module_get_declarations(mod); for (size_t i = 0; i < decls.count; i++) - c_emit_decl(&emitter, decls.nodes[i]); + shd_c_emit_decl(&emitter, decls.nodes[i]); shd_print(finalp, "\n/* types: */\n"); shd_growy_append_bytes(final, shd_growy_size(type_decls_g), shd_growy_data(type_decls_g)); diff --git a/src/backend/c/emit_c.h b/src/backend/c/emit_c.h index 0aa0f3a5f..6075ae334 100644 --- a/src/backend/c/emit_c.h +++ b/src/backend/c/emit_c.h @@ -58,33 +58,33 @@ typedef struct { Scheduler* scheduler; } FnEmitter; -void register_emitted(Emitter*, FnEmitter* fn, const Node*, CTerm); -void register_emitted_type(Emitter*, const Type*, String); - -CTerm* lookup_existing_term(Emitter* emitter, FnEmitter* fn, const Node*); -CType* lookup_existing_type(Emitter* emitter, const Type*); - -String c_legalize_identifier(Emitter*, String); -CValue to_cvalue(Emitter*, CTerm); -CAddr deref_term(Emitter*, CTerm); -void c_emit_pack_code(Printer*, Strings, String dst); -void c_emit_unpack_code(Printer*, String src, Strings dst); -CTerm c_bind_intermediary_result(Emitter*, Printer* p, const Type* t, CTerm term); -void c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer); -CTerm ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term); - -void c_emit_decl(Emitter* emitter, const Node* decl); -void c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String name, const Type* type, bool constant, String init); -CTerm c_emit_builtin(Emitter*, Builtin); - -CType c_emit_type(Emitter* emitter, const Type*, const char* identifier); -String c_get_record_field_name(const Type* t, size_t i); -String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn); -void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type); - -CTerm c_emit_value(Emitter* emitter, FnEmitter* fn, const Node* value); -CTerm c_emit_mem(Emitter* e, FnEmitter* b, const Node* mem); -String c_emit_body(Emitter*, FnEmitter* fn, const Node*); +void shd_c_register_emitted(Emitter* emitter, FnEmitter* fn, const Node* node, CTerm as); +void shd_c_register_emitted_type(Emitter* emitter, const Node* node, String as); + +CTerm* shd_c_lookup_existing_term(Emitter* emitter, FnEmitter* fn, const Node* node); +CType* shd_c_lookup_existing_type(Emitter* emitter, const Type* node); + +String shd_c_legalize_identifier(Emitter* e, String src); +CValue shd_c_to_ssa(Emitter* e, CTerm term); +CAddr shd_c_deref(Emitter* e, CTerm term); +void shd_c_emit_pack_code(Printer* p, Strings src, String dst); +void shd_c_emit_unpack_code(Printer* p, String src, Strings dst); +CTerm shd_c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term); +void shd_c_emit_variable_declaration(Emitter* emitter, Printer* block_printer, const Type* t, String variable_name, bool mut, const CTerm* initializer); +CTerm shd_ispc_varying_ptr_helper(Emitter* emitter, Printer* block_printer, const Type* ptr_type, CTerm term); + +void shd_c_emit_decl(Emitter* emitter, const Node* decl); +void shd_c_emit_global_variable_definition(Emitter* emitter, AddressSpace as, String name, const Type* type, bool constant, String init); +CTerm shd_c_emit_builtin(Emitter* emitter, Builtin b); + +CType shd_c_emit_type(Emitter* emitter, const Type* type, const char* center); +String shd_c_get_record_field_name(const Type* t, size_t i); +String shd_c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn); +void shd_c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type); + +CTerm shd_c_emit_value(Emitter* emitter, FnEmitter* fn_builder, const Node* node); +CTerm shd_c_emit_mem(Emitter* e, FnEmitter* b, const Node* mem); +String shd_c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs); #define free_tmp_str(s) free((char*) (s)) diff --git a/src/backend/c/emit_c_builtin.c b/src/backend/c/emit_c_builtin.c index 78307363e..d1fd395be 100644 --- a/src/backend/c/emit_c_builtin.c +++ b/src/backend/c/emit_c_builtin.c @@ -18,7 +18,7 @@ static String glsl_builtins[BuiltinsCount] = { [BuiltinPosition] = "gl_Position", }; -CTerm c_emit_builtin(Emitter* emitter, Builtin b) { +CTerm shd_c_emit_builtin(Emitter* emitter, Builtin b) { String name = NULL; switch(emitter->config.dialect) { case CDialect_ISPC: name = ispc_builtins[b]; break; diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index f650a84e5..178e86511 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -9,7 +9,7 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_printer, const Node* terminator); -String c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { +String shd_c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { assert(abs && is_abstraction(abs)); const Node* body = get_abstraction_body(abs); assert(body && is_terminator(body)); @@ -46,10 +46,10 @@ static Strings emit_variable_declarations(Emitter* emitter, FnEmitter* fn, Print assert(name); names[i] = shd_make_unique_name(emitter->arena, name); if (init_values) { - CTerm initializer = c_emit_value(emitter, fn, init_values->nodes[i]); - c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); + CTerm initializer = shd_c_emit_value(emitter, fn, init_values->nodes[i]); + shd_c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, &initializer); } else - c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); + shd_c_emit_variable_declaration(emitter, p, types.nodes[i], names[i], mut, NULL); } return shd_strings(emitter->arena, types.count, names); } @@ -60,10 +60,10 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { sub_emiter.phis.selection = ephis; assert(get_abstraction_params(if_.if_true).count == 0); - String true_body = c_emit_body(&sub_emiter, fn, if_.if_true); - String false_body = if_.if_false ? c_emit_body(&sub_emiter, fn, if_.if_false) : NULL; - String tail = c_emit_body(emitter, fn, if_.tail); - CValue condition = to_cvalue(emitter, c_emit_value(emitter, fn, if_.condition)); + String true_body = shd_c_emit_body(&sub_emiter, fn, if_.if_true); + String false_body = if_.if_false ? shd_c_emit_body(&sub_emiter, fn, if_.if_false) : NULL; + String tail = shd_c_emit_body(emitter, fn, if_.tail); + CValue condition = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, if_.condition)); shd_print(p, "\nif (%s) { ", condition); shd_printer_indent(p); shd_print(p, "%s", true_body); @@ -80,7 +80,7 @@ static void emit_if(Emitter* emitter, FnEmitter* fn, Printer* p, If if_) { Nodes results = get_abstraction_params(if_.tail); for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); + shd_c_register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } shd_print(p, "%s", tail); @@ -100,15 +100,15 @@ static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) // We could do GOTO for C, but at the cost of arguably even more noise in the output, and two different codepaths. // I don't think it's quite worth it, just like it's not worth doing some data-flow based solution either. - CValue inspectee = to_cvalue(emitter, c_emit_value(emitter, fn, match.inspect)); + CValue inspectee = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, match.inspect)); bool first = true; LARRAY(CValue, literals, match.cases.count); LARRAY(String, bodies, match.cases.count); - String default_case_body = c_emit_body(&sub_emiter, fn, match.default_case); - String tail = c_emit_body(emitter, fn, match.tail); + String default_case_body = shd_c_emit_body(&sub_emiter, fn, match.default_case); + String tail = shd_c_emit_body(emitter, fn, match.tail); for (size_t i = 0; i < match.cases.count; i++) { - literals[i] = to_cvalue(emitter, c_emit_value(emitter, fn, match.literals.nodes[i])); - bodies[i] = c_emit_body(&sub_emiter, fn, match.cases.nodes[i]); + literals[i] = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, match.literals.nodes[i])); + bodies[i] = shd_c_emit_body(&sub_emiter, fn, match.cases.nodes[i]); } for (size_t i = 0; i < match.cases.count; i++) { shd_print(p, "\n"); @@ -131,7 +131,7 @@ static void emit_match(Emitter* emitter, FnEmitter* fn, Printer* p, Match match) Nodes results = get_abstraction_params(match.tail); for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); + shd_c_register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } shd_print(p, "%s", tail); @@ -150,14 +150,14 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { Strings param_names = shd_strings(emitter->arena, variables.count, arr); Strings eparams = emit_variable_declarations(emitter, fn, p, NULL, ¶m_names, shd_get_param_types(emitter->arena, params), true, &loop.initial_args); for (size_t i = 0; i < params.count; i++) - register_emitted(&sub_emiter, fn, params.nodes[i], term_from_cvalue(eparams.strings[i])); + shd_c_register_emitted(&sub_emiter, fn, params.nodes[i], term_from_cvalue(eparams.strings[i])); sub_emiter.phis.loop_continue = eparams; Strings ephis = emit_variable_declarations(emitter, fn, p, "loop_break_phi", NULL, loop.yield_types, true, NULL); sub_emiter.phis.loop_break = ephis; - String body = c_emit_body(&sub_emiter, fn, loop.body); - String tail = c_emit_body(emitter, fn, loop.tail); + String body = shd_c_emit_body(&sub_emiter, fn, loop.body); + String tail = shd_c_emit_body(emitter, fn, loop.tail); shd_print(p, "\nwhile(true) { "); shd_printer_indent(p); shd_print(p, "%s", body); @@ -166,14 +166,14 @@ static void emit_loop(Emitter* emitter, FnEmitter* fn, Printer* p, Loop loop) { Nodes results = get_abstraction_params(loop.tail); for (size_t i = 0; i < ephis.count; i++) { - register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); + shd_c_register_emitted(emitter, fn, results.nodes[i], term_from_cvalue(ephis.strings[i])); } shd_print(p, "%s", tail); } static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_printer, const Node* terminator) { - c_emit_mem(emitter, fn, get_terminator_mem(terminator)); + shd_c_emit_mem(emitter, fn, get_terminator_mem(terminator)); switch (is_terminator(terminator)) { case NotATerminator: assert(false); case Join_TAG: shd_error("this must be lowered away!"); @@ -190,13 +190,13 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin if (args.count == 0) { shd_print(block_printer, "\nreturn;"); } else if (args.count == 1) { - shd_print(block_printer, "\nreturn %s;", to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[0]))); + shd_print(block_printer, "\nreturn %s;", shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, args.nodes[0]))); } else { String packed = shd_make_unique_name(emitter->arena, "pack_return"); LARRAY(CValue, values, args.count); for (size_t i = 0; i < args.count; i++) - values[i] = to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i])); - c_emit_pack_code(block_printer, shd_strings(emitter->arena, args.count, values), packed); + values[i] = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, args.nodes[i])); + shd_c_emit_pack_code(block_printer, shd_strings(emitter->arena, args.count, values), packed); shd_print(block_printer, "\nreturn %s;", packed); } break; @@ -206,7 +206,7 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin Phis phis = emitter->phis.selection; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - shd_print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); + shd_print(block_printer, "\n%s = %s;", phis.strings[i], shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, args.nodes[i]))); break; } @@ -215,7 +215,7 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin Phis phis = emitter->phis.loop_continue; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - shd_print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); + shd_print(block_printer, "\n%s = %s;", phis.strings[i], shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, args.nodes[i]))); shd_print(block_printer, "\ncontinue;"); break; } @@ -224,7 +224,7 @@ static void emit_terminator(Emitter* emitter, FnEmitter* fn, Printer* block_prin Phis phis = emitter->phis.loop_break; assert(phis.count == args.count); for (size_t i = 0; i < phis.count; i++) - shd_print(block_printer, "\n%s = %s;", phis.strings[i], to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); + shd_print(block_printer, "\n%s = %s;", phis.strings[i], shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, args.nodes[i]))); shd_print(block_printer, "\nbreak;"); break; } diff --git a/src/backend/c/emit_c_type.c b/src/backend/c/emit_c_type.c index c08d87640..b8cef8b67 100644 --- a/src/backend/c/emit_c_type.c +++ b/src/backend/c/emit_c_type.c @@ -12,7 +12,7 @@ #pragma GCC diagnostic error "-Wswitch" -String c_get_record_field_name(const Type* t, size_t i) { +String shd_c_get_record_field_name(const Type* t, size_t i) { assert(t->tag == RecordType_TAG); RecordType r = t->payload.record_type; assert(i < r.members.count); @@ -22,7 +22,7 @@ String c_get_record_field_name(const Type* t, size_t i) { return r.names.strings[i]; } -void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { +void shd_c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { assert(type->tag == RecordType_TAG); Growy* g = shd_new_growy(); Printer* p = shd_new_printer_from_growy(g); @@ -30,8 +30,8 @@ void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { shd_print(p, "\n%s {", name); shd_printer_indent(p); for (size_t i = 0; i < type->payload.record_type.members.count; i++) { - String member_identifier = c_get_record_field_name(type, i); - shd_print(p, "\n%s;", c_emit_type(emitter, type->payload.record_type.members.nodes[i], member_identifier)); + String member_identifier = shd_c_get_record_field_name(type, i); + shd_print(p, "\n%s;", shd_c_emit_type(emitter, type->payload.record_type.members.nodes[i], member_identifier)); } shd_printer_deindent(p); shd_print(p, "\n};\n"); @@ -42,7 +42,7 @@ void c_emit_nominal_type_body(Emitter* emitter, String name, const Type* type) { shd_destroy_printer(p); } -String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn) { +String shd_c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, const Node* fn) { assert(fn_type->tag == FnType_TAG); assert(!fn || fn->type == fn_type); Nodes codom = fn_type->payload.fn_type.return_types; @@ -65,8 +65,8 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons for (size_t i = 0; i < dom.count; i++) { String param_name; String variable_name = shd_get_value_name_unsafe(fn->payload.fun.params.nodes[i]); - param_name = shd_fmt_string_irarena(emitter->arena, "%s_%d", c_legalize_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); - shd_print(paramp, c_emit_type(emitter, params.nodes[i]->type, param_name)); + param_name = shd_fmt_string_irarena(emitter->arena, "%s_%d", shd_c_legalize_identifier(emitter, variable_name), fn->payload.fun.params.nodes[i]->id); + shd_print(paramp, shd_c_emit_type(emitter, params.nodes[i]->type, param_name)); if (i + 1 < dom.count) { shd_print(paramp, ", "); } @@ -78,7 +78,7 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons shd_print(paramp, ", "); } for (size_t i = 0; i < dom.count; i++) { - shd_print(paramp, c_emit_type(emitter, dom.nodes[i], "")); + shd_print(paramp, shd_c_emit_type(emitter, dom.nodes[i], "")); if (i + 1 < dom.count) { shd_print(paramp, ", "); } @@ -98,7 +98,7 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons } free_tmp_str(parameters); - String c_decl = c_emit_type(emitter, shd_maybe_multiple_return(emitter->arena, codom), center); + String c_decl = shd_c_emit_type(emitter, shd_maybe_multiple_return(emitter->arena, codom), center); if (entry_point) { switch (emitter->config.dialect) { case CDialect_C11: @@ -119,12 +119,12 @@ String c_emit_fn_head(Emitter* emitter, const Node* fn_type, String center, cons return c_decl; } -String c_emit_type(Emitter* emitter, const Type* type, const char* center) { +String shd_c_emit_type(Emitter* emitter, const Type* type, const char* center) { if (center == NULL) center = ""; String emitted = NULL; - CType* found = lookup_existing_type(emitter, type); + CType* found = shd_c_lookup_existing_type(emitter, type); if (found) { emitted = *found; goto type_goes_on_left; @@ -215,7 +215,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { emitted = shd_make_unique_name(emitter->arena, "Record"); String prefixed = shd_format_string_arena(emitter->arena->arena, "struct %s", emitted); - c_emit_nominal_type_body(emitter, prefixed, type); + shd_c_emit_nominal_type_body(emitter, prefixed, type); // C puts structs in their own namespace so we always need the prefix if (emitter->config.dialect == CDialect_C11) emitted = prefixed; @@ -229,22 +229,22 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { } switch (emitter->config.dialect) { default: - return c_emit_type(emitter, type->payload.qualified_type.type, center); + return shd_c_emit_type(emitter, type->payload.qualified_type.type, center); case CDialect_ISPC: if (type->payload.qualified_type.is_uniform) - return c_emit_type(emitter, type->payload.qualified_type.type, shd_format_string_arena(emitter->arena->arena, "uniform %s", center)); + return shd_c_emit_type(emitter, type->payload.qualified_type.type, shd_format_string_arena(emitter->arena->arena, "uniform %s", center)); else - return c_emit_type(emitter, type->payload.qualified_type.type, shd_format_string_arena(emitter->arena->arena, "varying %s", center)); + return shd_c_emit_type(emitter, type->payload.qualified_type.type, shd_format_string_arena(emitter->arena->arena, "varying %s", center)); } case Type_PtrType_TAG: { - CType t = c_emit_type(emitter, type->payload.ptr_type.pointed_type, shd_format_string_arena(emitter->arena->arena, "* %s", center)); + CType t = shd_c_emit_type(emitter, type->payload.ptr_type.pointed_type, shd_format_string_arena(emitter->arena->arena, "* %s", center)); // we always emit pointers to _uniform_ data, no exceptions if (emitter->config.dialect == CDialect_ISPC) t = shd_format_string_arena(emitter->arena->arena, "uniform %s", t); return t; } case Type_FnType_TAG: { - return c_emit_fn_head(emitter, type, center, NULL); + return shd_c_emit_fn_head(emitter, type, center, NULL); } case Type_ArrType_TAG: { emitted = shd_make_unique_name(emitter->arena, "Array"); @@ -254,7 +254,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { const Node* size = type->payload.arr_type.size; if (!size && emitter->config.decay_unsized_arrays) - return c_emit_type(emitter, type->payload.arr_type.element_type, center); + return shd_c_emit_type(emitter, type->payload.arr_type.element_type, center); shd_print(p, "\n%s {", prefixed); shd_printer_indent(p); @@ -263,7 +263,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[%zu]", shd_get_int_literal_value(*shd_resolve_to_int_literal(size), false)); else inner_decl_rhs = shd_format_string_arena(emitter->arena->arena, "arr[0]"); - shd_print(p, "\n%s;", c_emit_type(emitter, type->payload.arr_type.element_type, inner_decl_rhs)); + shd_print(p, "\n%s;", shd_c_emit_type(emitter, type->payload.arr_type.element_type, inner_decl_rhs)); shd_printer_deindent(p); shd_print(p, "\n};\n"); shd_growy_append_bytes(g, 1, (char[]) { '\0' }); @@ -302,7 +302,7 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { } case CDialect_ISPC: shd_error("Please lower to something else") case CDialect_C11: { - emitted = c_emit_type(emitter, element_type, NULL); + emitted = shd_c_emit_type(emitter, element_type, NULL); emitted = shd_format_string_arena(emitter->arena->arena, "__attribute__ ((vector_size (%d * sizeof(%s) ))) %s", width, emitted, emitted); break; } @@ -310,13 +310,13 @@ String c_emit_type(Emitter* emitter, const Type* type, const char* center) { break; } case Type_TypeDeclRef_TAG: { - c_emit_decl(emitter, type->payload.type_decl_ref.decl); - emitted = *lookup_existing_type(emitter, type->payload.type_decl_ref.decl); + shd_c_emit_decl(emitter, type->payload.type_decl_ref.decl); + emitted = *shd_c_lookup_existing_type(emitter, type->payload.type_decl_ref.decl); goto type_goes_on_left; } } assert(emitted != NULL); - register_emitted_type(emitter, type, emitted); + shd_c_register_emitted_type(emitter, type, emitted); type_goes_on_left: assert(emitted != NULL); diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 2e9ebe3ae..91bbdb219 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -45,7 +45,7 @@ static enum { ObjectsList, StringLit, CharsLit } array_insides_helper(Emitter* e return is_stringy ? StringLit : CharsLit; } else { for (size_t i = 0; i < c.count; i++) { - shd_print(p, to_cvalue(e, c_emit_value(e, fn, c.nodes[i]))); + shd_print(p, shd_c_to_ssa(e, shd_c_emit_value(e, fn, c.nodes[i]))); if (i + 1 < c.count) shd_print(p, ", "); } @@ -109,10 +109,10 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No case Value_False_TAG: return term_from_cvalue("false"); case Value_Undef_TAG: { if (emitter->config.dialect == CDialect_GLSL) - return c_emit_value(emitter, fn, shd_get_default_value(emitter->arena, value->payload.undef.type)); + return shd_c_emit_value(emitter, fn, shd_get_default_value(emitter->arena, value->payload.undef.type)); String name = shd_make_unique_name(emitter->arena, "undef"); // c_emit_variable_declaration(emitter, block_printer, value->type, name, true, NULL); - c_emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); + shd_c_emit_global_variable_definition(emitter, AsGlobal, name, value->payload.undef.type, true, NULL); emitted = name; break; } @@ -139,7 +139,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No } } else { for (size_t i = 0; i < elements.count; i++) { - shd_print(p, "%s", to_cvalue(emitter, c_emit_value(emitter, fn, elements.nodes[i]))); + shd_print(p, "%s", shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, elements.nodes[i]))); if (i + 1 < elements.count) shd_print(p, ", "); } @@ -156,7 +156,7 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No if (p2) { String tmp = shd_make_unique_name(emitter->arena, "composite"); - shd_print(p2, "\n%s = { %s };", c_emit_type(emitter, value->type, tmp), emitted); + shd_print(p2, "\n%s = { %s };", shd_c_emit_type(emitter, value->type, tmp), emitted); emitted = tmp; } else { // this requires us to end up in the initialisation side of a declaration @@ -169,13 +169,13 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No // If we're C89 (ew) if (!emitter->config.allow_compound_literals) goto no_compound_literals; - emitted = shd_format_string_arena(emitter->arena->arena, "((%s) { %s })", c_emit_type(emitter, value->type, NULL), emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "((%s) { %s })", shd_c_emit_type(emitter, value->type, NULL), emitted); break; case CDialect_GLSL: if (type->tag != PackType_TAG) goto no_compound_literals; // GLSL doesn't have compound literals, but it does have constructor syntax for vectors - emitted = shd_format_string_arena(emitter->arena->arena, "%s(%s)", c_emit_type(emitter, value->type, NULL), emitted); + emitted = shd_format_string_arena(emitter->arena->arena, "%s(%s)", shd_c_emit_type(emitter, value->type, NULL), emitted); break; } @@ -207,23 +207,23 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No break; } case Value_FnAddr_TAG: { - emitted = c_legalize_identifier(emitter, get_declaration_name(value->payload.fn_addr.fn)); + emitted = shd_c_legalize_identifier(emitter, get_declaration_name(value->payload.fn_addr.fn)); emitted = shd_format_string_arena(emitter->arena->arena, "(&%s)", emitted); break; } case Value_RefDecl_TAG: { const Node* decl = value->payload.ref_decl.decl; - c_emit_decl(emitter, decl); + shd_c_emit_decl(emitter, decl); if (emitter->config.dialect == CDialect_ISPC && decl->tag == GlobalVariable_TAG) { if (!shd_is_addr_space_uniform(emitter->arena, decl->payload.global_variable.address_space) && !shd_is_decl_builtin( decl)) { assert(fn && "ISPC backend cannot statically refer to a varying variable"); - return ispc_varying_ptr_helper(emitter, fn->instruction_printers[0], decl->type, *lookup_existing_term(emitter, NULL, decl)); + return shd_ispc_varying_ptr_helper(emitter, fn->instruction_printers[0], decl->type, *shd_c_lookup_existing_term(emitter, NULL, decl)); } } - return *lookup_existing_term(emitter, NULL, decl); + return *shd_c_lookup_existing_term(emitter, NULL, decl); } } @@ -231,15 +231,15 @@ static CTerm c_emit_value_(Emitter* emitter, FnEmitter* fn, Printer* p, const No return term_from_cvalue(emitted); } -CTerm c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { +CTerm shd_c_bind_intermediary_result(Emitter* emitter, Printer* p, const Type* t, CTerm term) { if (is_term_empty(term)) return term; if (t == empty_multiple_return_type(emitter->arena)) { - shd_print(p, "%s;", to_cvalue(emitter, term)); + shd_print(p, "%s;", shd_c_to_ssa(emitter, term)); return empty_term(); } String bind_to = shd_make_unique_name(emitter->arena, ""); - c_emit_variable_declaration(emitter, p, t, bind_to, false, &term); + shd_c_emit_variable_declaration(emitter, p, t, bind_to, false, &term); return term_from_cvalue(bind_to); } @@ -366,28 +366,28 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, FnEmitter* fn, Printe switch (entry->style) { case OsInfix: { - CTerm a = c_emit_value(emitter, fn, operands.nodes[0]); - CTerm b = c_emit_value(emitter, fn, operands.nodes[1]); - *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s %s %s", to_cvalue(emitter, a), operator_str, to_cvalue(emitter, b))); + CTerm a = shd_c_emit_value(emitter, fn, operands.nodes[0]); + CTerm b = shd_c_emit_value(emitter, fn, operands.nodes[1]); + *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s %s %s", shd_c_to_ssa(emitter, a), operator_str, shd_c_to_ssa(emitter, b))); break; } case OsPrefix: { - CTerm operand = c_emit_value(emitter, fn, operands.nodes[0]); - *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s%s", operator_str, to_cvalue(emitter, operand))); + CTerm operand = shd_c_emit_value(emitter, fn, operands.nodes[0]); + *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s%s", operator_str, shd_c_to_ssa(emitter, operand))); break; } case OsCall: { LARRAY(CTerm, cops, operands.count); for (size_t i = 0; i < operands.count; i++) - cops[i] = c_emit_value(emitter, fn, operands.nodes[i]); + cops[i] = shd_c_emit_value(emitter, fn, operands.nodes[i]); if (operands.count == 1) - *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", operator_str, to_cvalue(emitter, cops[0]))); + *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", operator_str, shd_c_to_ssa(emitter, cops[0]))); else { Growy* g = shd_new_growy(); shd_growy_append_string(g, operator_str); shd_growy_append_string_literal(g, "("); for (size_t i = 0; i < operands.count; i++) { - shd_growy_append_string(g, to_cvalue(emitter, cops[i])); + shd_growy_append_string(g, shd_c_to_ssa(emitter, cops[i])); if (i + 1 < operands.count) shd_growy_append_string_literal(g, ", "); } @@ -421,11 +421,11 @@ static const ISelTableEntry* lookup_entry(Emitter* emitter, Op op) { static String index_into_array(Emitter* emitter, const Type* arr_type, CTerm expr, CTerm index) { IrArena* arena = emitter->arena; - String index2 = emitter->config.dialect == CDialect_GLSL ? shd_format_string_arena(arena->arena, "int(%s)", to_cvalue(emitter, index)) : to_cvalue(emitter, index); + String index2 = emitter->config.dialect == CDialect_GLSL ? shd_format_string_arena(arena->arena, "int(%s)", shd_c_to_ssa(emitter, index)) : shd_c_to_ssa(emitter, index); if (emitter->config.decay_unsized_arrays && !arr_type->payload.arr_type.size) - return shd_format_string_arena(arena->arena, "((&%s)[%s])", deref_term(emitter, expr), index2); + return shd_format_string_arena(arena->arena, "((&%s)[%s])", shd_c_deref(emitter, expr), index2); else - return shd_format_string_arena(arena->arena, "(%s.arr[%s])", deref_term(emitter, expr), index2); + return shd_format_string_arena(arena->arena, "(%s.arr[%s])", shd_c_deref(emitter, expr), index2); } static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* node) { @@ -444,36 +444,36 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case fract_op: { CTerm floored; emit_using_entry(&floored, emitter, fn, p, lookup_entry(emitter, floor_op), prim_op->operands); - term = term_from_cvalue(shd_format_string_arena(arena->arena, "1 - %s", to_cvalue(emitter, floored))); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "1 - %s", shd_c_to_ssa(emitter, floored))); break; } case inv_sqrt_op: { CTerm floored; emit_using_entry(&floored, emitter, fn, p, lookup_entry(emitter, sqrt_op), prim_op->operands); - term = term_from_cvalue(shd_format_string_arena(arena->arena, "1.0f / %s", to_cvalue(emitter, floored))); + term = term_from_cvalue(shd_format_string_arena(arena->arena, "1.0f / %s", shd_c_to_ssa(emitter, floored))); break; } case min_op: { - CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); - CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); + CValue a = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, shd_first(prim_op->operands))); + CValue b = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[1])); term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, b, a)); break; } case max_op: { - CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); - CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); + CValue a = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, shd_first(prim_op->operands))); + CValue b = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[1])); term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > %s ? %s : %s)", a, b, a, b)); break; } case sign_op: { - CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); + CValue src = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, shd_first(prim_op->operands))); term = term_from_cvalue(shd_format_string_arena(arena->arena, "(%s > 0 ? 1 : -1)", src)); break; } case fma_op: { - CValue a = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[0])); - CValue b = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); - CValue c = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[2])); + CValue a = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[0])); + CValue b = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[1])); + CValue c = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[2])); switch (emitter->config.dialect) { case CDialect_C11: case CDialect_CUDA: { @@ -490,9 +490,9 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case lshift_op: case rshift_arithm_op: case rshift_logical_op: { - CValue src = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); + CValue src = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, shd_first(prim_op->operands))); const Node* offset = prim_op->operands.nodes[1]; - CValue c_offset = to_cvalue(emitter, c_emit_value(emitter, fn, offset)); + CValue c_offset = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, offset)); if (emitter->config.dialect == CDialect_GLSL) { if (shd_get_unqualified_type(offset->type)->payload.int_type.width == IntTy64) c_offset = shd_format_string_arena(arena->arena, "int(%s)", c_offset); @@ -501,10 +501,10 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } case size_of_op: - term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "sizeof(%s)", c_emit_type(emitter, shd_first(prim_op->type_arguments), NULL))); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "sizeof(%s)", shd_c_emit_type(emitter, shd_first(prim_op->type_arguments), NULL))); break; case align_of_op: - term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "alignof(%s)", c_emit_type(emitter, shd_first(prim_op->type_arguments), NULL))); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "alignof(%s)", shd_c_emit_type(emitter, shd_first(prim_op->type_arguments), NULL))); break; case offset_of_op: { const Type* t = shd_first(prim_op->type_arguments); @@ -513,35 +513,35 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } const Node* index = shd_first(prim_op->operands); uint64_t index_literal = shd_get_int_literal_value(*shd_resolve_to_int_literal(index), false); - String member_name = c_get_record_field_name(t, index_literal); - term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "offsetof(%s, %s)", c_emit_type(emitter, t, NULL), member_name)); + String member_name = shd_c_get_record_field_name(t, index_literal); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "offsetof(%s, %s)", shd_c_emit_type(emitter, t, NULL), member_name)); break; } case select_op: { assert(prim_op->operands.count == 3); - CValue condition = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[0])); - CValue l = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); - CValue r = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[2])); + CValue condition = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[0])); + CValue l = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[1])); + CValue r = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[2])); term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "(%s) ? (%s) : (%s)", condition, l, r)); break; } case convert_op: { - CTerm src = c_emit_value(emitter, fn, shd_first(prim_op->operands)); + CTerm src = shd_c_emit_value(emitter, fn, shd_first(prim_op->operands)); const Type* src_type = shd_get_unqualified_type(shd_first(prim_op->operands)->type); const Type* dst_type = shd_first(prim_op->type_arguments); if (emitter->config.dialect == CDialect_GLSL) { if (is_glsl_scalar_type(src_type) && is_glsl_scalar_type(dst_type)) { - CType t = c_emit_type(emitter, dst_type, NULL); - term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", t, to_cvalue(emitter, src))); + CType t = shd_c_emit_type(emitter, dst_type, NULL); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", t, shd_c_to_ssa(emitter, src))); } else assert(false); } else { - CType t = c_emit_type(emitter, dst_type, NULL); - term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src))); + CType t = shd_c_emit_type(emitter, dst_type, NULL); + term = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "((%s) %s)", t, shd_c_to_ssa(emitter, src))); } break; } case reinterpret_op: { - CTerm src_value = c_emit_value(emitter, fn, shd_first(prim_op->operands)); + CTerm src_value = shd_c_emit_value(emitter, fn, shd_first(prim_op->operands)); const Type* src_type = shd_get_unqualified_type(shd_first(prim_op->operands)->type); const Type* dst_type = shd_first(prim_op->type_arguments); switch (emitter->config.dialect) { @@ -549,8 +549,8 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case CDialect_C11: { String src = shd_make_unique_name(arena, "bitcast_src"); String dst = shd_make_unique_name(arena, "bitcast_result"); - shd_print(p, "\n%s = %s;", c_emit_type(emitter, src_type, src), to_cvalue(emitter, src_value)); - shd_print(p, "\n%s;", c_emit_type(emitter, dst_type, dst)); + shd_print(p, "\n%s = %s;", shd_c_emit_type(emitter, src_type, src), shd_c_to_ssa(emitter, src_value)); + shd_print(p, "\n%s;", shd_c_emit_type(emitter, dst_type, dst)); shd_print(p, "\nmemcpy(&%s, &%s, sizeof(%s));", dst, src, src); return term_from_cvalue(dst); } @@ -578,7 +578,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } } if (conv_fn) { - return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, to_cvalue(emitter, src_value))); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", conv_fn, shd_c_to_ssa(emitter, src_value))); } shd_error_print("glsl: unsupported bit cast from "); shd_log_node(ERROR, src_type); @@ -599,14 +599,14 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case FloatTy64: n = "doublebits"; break; } - return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", n, to_cvalue(emitter, src_value))); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", n, shd_c_to_ssa(emitter, src_value))); } else if (src_type->tag == Float_TAG) { assert(dst_type->tag == Int_TAG); - return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "intbits(%s)", to_cvalue(emitter, src_value))); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "intbits(%s)", shd_c_to_ssa(emitter, src_value))); } - CType t = c_emit_type(emitter, dst_type, NULL); - return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "((%s) %s)", t, to_cvalue(emitter, src_value))); + CType t = shd_c_emit_type(emitter, dst_type, NULL); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "((%s) %s)", t, shd_c_to_ssa(emitter, src_value))); } } SHADY_UNREACHABLE; @@ -614,12 +614,12 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node case insert_op: case extract_dynamic_op: case extract_op: { - CValue acc = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(prim_op->operands))); + CValue acc = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, shd_first(prim_op->operands))); bool insert = prim_op->op == insert_op; if (insert) { String dst = shd_make_unique_name(arena, "modified"); - shd_print(p, "\n%s = %s;", c_emit_type(emitter, node->type, dst), acc); + shd_print(p, "\n%s = %s;", shd_c_emit_type(emitter, node->type, dst), acc); acc = dst; term = term_from_cvalue(dst); } @@ -653,7 +653,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; } case Type_ArrType_TAG: { - acc = index_into_array(emitter, t, term_from_cvar(acc), c_emit_value(emitter, fn, index)); + acc = index_into_array(emitter, t, term_from_cvar(acc), shd_c_emit_value(emitter, fn, index)); break; } default: @@ -662,7 +662,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } if (insert) { - shd_print(p, "\n%s = %s;", acc, to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1]))); + shd_print(p, "\n%s = %s;", acc, shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[1]))); break; } @@ -673,8 +673,8 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node String dst = shd_make_unique_name(arena, "shuffled"); const Node* lhs = prim_op->operands.nodes[0]; const Node* rhs = prim_op->operands.nodes[1]; - String lhs_e = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[0])); - String rhs_e = to_cvalue(emitter, c_emit_value(emitter, fn, prim_op->operands.nodes[1])); + String lhs_e = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[0])); + String rhs_e = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[1])); const Type* lhs_t = lhs->type; const Type* rhs_t = rhs->type; bool lhs_u = shd_deconstruct_qualified_type(&lhs_t); @@ -682,7 +682,7 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node size_t left_size = lhs_t->payload.pack_type.width; // size_t total_size = lhs_t->payload.pack_type.width + rhs_t->payload.pack_type.width; String suffixes = "xyzw"; - shd_print(p, "\n%s = vec%d(", c_emit_type(emitter, node->type, dst), prim_op->operands.count - 2); + shd_print(p, "\n%s = vec%d(", shd_c_emit_type(emitter, node->type, dst), prim_op->operands.count - 2); for (size_t i = 2; i < prim_op->operands.count; i++) { const IntLiteral* selector = shd_resolve_to_int_literal(prim_op->operands.nodes[i]); if (selector->value < left_size) @@ -698,10 +698,10 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } case subgroup_assume_uniform_op: { if (emitter->config.dialect == CDialect_ISPC) { - CTerm value = c_emit_value(emitter, fn, prim_op->operands.nodes[0]); + CTerm value = shd_c_emit_value(emitter, fn, prim_op->operands.nodes[0]); return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; } - return c_emit_value(emitter, fn, prim_op->operands.nodes[0]); + return shd_c_emit_value(emitter, fn, prim_op->operands.nodes[0]); } case empty_mask_op: case mask_is_thread_active_op: shd_error("lower_me"); @@ -716,11 +716,11 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, ExtInstr instr) { - c_emit_mem(emitter, fn, instr.mem); + shd_c_emit_mem(emitter, fn, instr.mem); if (strcmp(instr.set, "spirv.core") == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { - CValue value = to_cvalue(emitter, c_emit_value(emitter, fn, shd_first(instr.operands))); + CValue value = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, shd_first(instr.operands))); switch (emitter->config.dialect) { case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); @@ -753,7 +753,7 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* call) { Call payload = call->payload.call; - c_emit_mem(emitter, fn, payload.mem); + shd_c_emit_mem(emitter, fn, payload.mem); Nodes args; if (call->tag == Call_TAG) args = call->payload.call.args; @@ -768,7 +768,7 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* shd_print(paramsp, ", "); } for (size_t i = 0; i < args.count; i++) { - shd_print(paramsp, to_cvalue(emitter, c_emit_value(emitter, fn, args.nodes[i]))); + shd_print(paramsp, shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, args.nodes[i]))); if (i + 1 < args.count) shd_print(paramsp, ", "); } @@ -778,12 +778,12 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* if (callee->tag == FnAddr_TAG) e_callee = get_declaration_name(callee->payload.fn_addr.fn); else - e_callee = to_cvalue(emitter, c_emit_value(emitter, fn, callee)); + e_callee = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, callee)); String params = shd_printer_growy_unwrap(paramsp); CTerm called = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); - called = c_bind_intermediary_result(emitter, p, call->type, called); + called = shd_c_bind_intermediary_result(emitter, p, call->type, called); free_tmp_str(params); return called; @@ -791,7 +791,7 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer* p, PtrCompositeElement lea) { IrArena* arena = emitter->arena; - CTerm acc = c_emit_value(emitter, fn, lea.ptr); + CTerm acc = shd_c_emit_value(emitter, fn, lea.ptr); const Type* src_qtype = lea.ptr->type; bool uniform = shd_is_qualified_type_uniform(src_qtype); @@ -803,7 +803,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer uniform &= shd_is_qualified_type_uniform(selector->type); switch (is_type(pointee_type)) { case ArrType_TAG: { - CTerm index = c_emit_value(emitter, fn, selector); + CTerm index = shd_c_emit_value(emitter, fn, selector); acc = term_from_cvar(index_into_array(emitter, pointee_type, acc, index)); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.arr_type.element_type, @@ -822,14 +822,14 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer // See https://github.com/ispc/ispc/issues/2496 if (emitter->config.dialect == CDialect_ISPC) { String interm = shd_make_unique_name(arena, "lea_intermediary_ptr_value"); - shd_print(p, "\n%s = %s;", c_emit_type(emitter, shd_as_qualified_type(curr_ptr_type, uniform), interm), to_cvalue(emitter, acc)); + shd_print(p, "\n%s = %s;", shd_c_emit_type(emitter, shd_as_qualified_type(curr_ptr_type, uniform), interm), shd_c_to_ssa(emitter, acc)); acc = term_from_cvalue(interm); } assert(selector->tag == IntLiteral_TAG && "selectors when indexing into a record need to be constant"); size_t static_index = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); - String field_name = c_get_record_field_name(pointee_type, static_index); - acc = term_from_cvar(shd_format_string_arena(arena->arena, "(%s.%s)", deref_term(emitter, acc), field_name)); + String field_name = shd_c_get_record_field_name(pointee_type, static_index); + acc = term_from_cvar(shd_format_string_arena(arena->arena, "(%s.%s)", shd_c_deref(emitter, acc), field_name)); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.record_type.members.nodes[static_index], .address_space = curr_ptr_type->payload.ptr_type.address_space @@ -839,7 +839,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer case Type_PackType_TAG: { size_t static_index = shd_get_int_literal_value(*shd_resolve_to_int_literal(selector), false); String suffixes = "xyzw"; - acc = term_from_cvar(shd_format_string_arena(emitter->arena->arena, "(%s.%c)", deref_term(emitter, acc), suffixes[static_index])); + acc = term_from_cvar(shd_format_string_arena(emitter->arena->arena, "(%s.%c)", shd_c_deref(emitter, acc), suffixes[static_index])); curr_ptr_type = ptr_type(arena, (PtrType) { .pointed_type = pointee_type->payload.pack_type.element_type, .address_space = curr_ptr_type->payload.ptr_type.address_space @@ -857,7 +857,7 @@ static CTerm emit_ptr_composite_element(Emitter* emitter, FnEmitter* fn, Printer static CTerm emit_ptr_array_element_offset(Emitter* emitter, FnEmitter* fn, Printer* p, PtrArrayElementOffset lea) { IrArena* arena = emitter->arena; - CTerm acc = c_emit_value(emitter, fn, lea.ptr); + CTerm acc = shd_c_emit_value(emitter, fn, lea.ptr); const Type* src_qtype = lea.ptr->type; bool uniform = shd_is_qualified_type_uniform(src_qtype); @@ -866,17 +866,17 @@ static CTerm emit_ptr_array_element_offset(Emitter* emitter, FnEmitter* fn, Prin const IntLiteral* offset_static_value = shd_resolve_to_int_literal(lea.offset); if (!offset_static_value || offset_static_value->value != 0) { - CTerm offset = c_emit_value(emitter, fn, lea.offset); + CTerm offset = shd_c_emit_value(emitter, fn, lea.offset); // we sadly need to drop to the value level (aka explicit pointer arithmetic) to do this // this means such code is never going to be legal in GLSL // also the cast is to account for our arrays-in-structs hack const Type* pointee_type = shd_get_pointee_type(arena, curr_ptr_type); - acc = term_from_cvalue(shd_format_string_arena(arena->arena, "((%s) &(%s)[%s])", c_emit_type(emitter, curr_ptr_type, NULL), to_cvalue(emitter, acc), to_cvalue(emitter, offset))); + acc = term_from_cvalue(shd_format_string_arena(arena->arena, "((%s) &(%s)[%s])", shd_c_emit_type(emitter, curr_ptr_type, NULL), shd_c_to_ssa(emitter, acc), shd_c_to_ssa(emitter, offset))); uniform &= shd_is_qualified_type_uniform(lea.offset->type); } if (emitter->config.dialect == CDialect_ISPC) - acc = c_bind_intermediary_result(emitter, p, curr_ptr_type, acc); + acc = shd_c_bind_intermediary_result(emitter, p, curr_ptr_type, acc); return acc; } @@ -892,12 +892,12 @@ static const Type* get_allocated_type(const Node* alloc) { static CTerm emit_alloca(Emitter* emitter, Printer* p, const Type* instr) { String variable_name = shd_make_unique_name(emitter->arena, "alloca"); CTerm variable = (CTerm) { .value = NULL, .var = variable_name }; - c_emit_variable_declaration(emitter, p, get_allocated_type(instr), variable_name, true, NULL); + shd_c_emit_variable_declaration(emitter, p, get_allocated_type(instr), variable_name, true, NULL); const Type* ptr_type = instr->type; shd_deconstruct_qualified_type(&ptr_type); assert(ptr_type->tag == PtrType_TAG); if (emitter->config.dialect == CDialect_ISPC && !ptr_type->payload.ptr_type.is_reference) { - variable = ispc_varying_ptr_helper(emitter, p, shd_get_unqualified_type(instr->type), variable); + variable = shd_ispc_varying_ptr_helper(emitter, p, shd_get_unqualified_type(instr->type), variable); } return variable; } @@ -914,28 +914,28 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case Instruction_SetStackSize_TAG: case Instruction_GetStackBaseAddr_TAG: shd_error("Stack operations need to be lowered."); case Instruction_ExtInstr_TAG: return emit_ext_instruction(emitter, fn, p, instruction->payload.ext_instr); - case Instruction_PrimOp_TAG: return c_bind_intermediary_result(emitter, p, instruction->type, emit_primop(emitter, fn, p, instruction)); + case Instruction_PrimOp_TAG: return shd_c_bind_intermediary_result(emitter, p, instruction->type, emit_primop(emitter, fn, p, instruction)); case Instruction_Call_TAG: return emit_call(emitter, fn, p, instruction); case Instruction_Comment_TAG: shd_print(p, "/* %s */", instruction->payload.comment.string); return empty_term(); - case Instruction_StackAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); - case Instruction_LocalAlloc_TAG: c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); + case Instruction_StackAlloc_TAG: shd_c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); + case Instruction_LocalAlloc_TAG: shd_c_emit_mem(emitter, fn, instruction->payload.local_alloc.mem); return emit_alloca(emitter, p, instruction); case Instruction_PtrArrayElementOffset_TAG: return emit_ptr_array_element_offset(emitter, fn, p, instruction->payload.ptr_array_element_offset); case Instruction_PtrCompositeElement_TAG: return emit_ptr_composite_element(emitter, fn, p, instruction->payload.ptr_composite_element); case Instruction_Load_TAG: { Load payload = instruction->payload.load; - c_emit_mem(emitter, fn, payload.mem); - CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, fn, payload.ptr)); + shd_c_emit_mem(emitter, fn, payload.mem); + CAddr dereferenced = shd_c_deref(emitter, shd_c_emit_value(emitter, fn, payload.ptr)); return term_from_cvalue(dereferenced); } case Instruction_Store_TAG: { Store payload = instruction->payload.store; - c_emit_mem(emitter, fn, payload.mem); + shd_c_emit_mem(emitter, fn, payload.mem); const Type* addr_type = payload.ptr->type; bool addr_uniform = shd_deconstruct_qualified_type(&addr_type); bool value_uniform = shd_is_qualified_type_uniform(payload.value->type); assert(addr_type->tag == PtrType_TAG); - CAddr dereferenced = deref_term(emitter, c_emit_value(emitter, fn, payload.ptr)); - CValue cvalue = to_cvalue(emitter, c_emit_value(emitter, fn, payload.value)); + CAddr dereferenced = shd_c_deref(emitter, shd_c_emit_value(emitter, fn, payload.ptr)); + CValue cvalue = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, payload.value)); // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this if (emitter->config.dialect == CDialect_ISPC && addr_uniform && shd_is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) cvalue = shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); @@ -945,22 +945,22 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const } case Instruction_CopyBytes_TAG: { CopyBytes payload = instruction->payload.copy_bytes; - c_emit_mem(emitter, fn, payload.mem); - shd_print(p, "\nmemcpy(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, fn, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.src)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.count))); + shd_c_emit_mem(emitter, fn, payload.mem); + shd_print(p, "\nmemcpy(%s, %s, %s);", shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, payload.dst)), shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, payload.src)), shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, payload.count))); return empty_term(); } case Instruction_FillBytes_TAG:{ FillBytes payload = instruction->payload.fill_bytes; - c_emit_mem(emitter, fn, payload.mem); - shd_print(p, "\nmemset(%s, %s, %s);", to_cvalue(emitter, c_emit_value(emitter, fn, payload.dst)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.src)), to_cvalue(emitter, c_emit_value(emitter, fn, payload.count))); + shd_c_emit_mem(emitter, fn, payload.mem); + shd_print(p, "\nmemset(%s, %s, %s);", shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, payload.dst)), shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, payload.src)), shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, payload.count))); return empty_term(); } case Instruction_DebugPrintf_TAG: { DebugPrintf payload = instruction->payload.debug_printf; - c_emit_mem(emitter, fn, payload.mem); + shd_c_emit_mem(emitter, fn, payload.mem); String args_list = shd_fmt_string_irarena(emitter->arena, "\"%s\"", instruction->payload.debug_printf.string); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) { - CValue str = to_cvalue(emitter, c_emit_value(emitter, fn, instruction->payload.debug_printf.args.nodes[i])); + CValue str = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, instruction->payload.debug_printf.args.nodes[i])); if (emitter->config.dialect == CDialect_ISPC && i > 0) str = shd_format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); @@ -1000,14 +1000,14 @@ static bool can_appear_at_top_level(Emitter* emitter, const Node* node) { return true; } -CTerm c_emit_value(Emitter* emitter, FnEmitter* fn_builder, const Node* node) { - CTerm* found = lookup_existing_term(emitter, fn_builder, node); +CTerm shd_c_emit_value(Emitter* emitter, FnEmitter* fn_builder, const Node* node) { + CTerm* found = shd_c_lookup_existing_term(emitter, fn_builder, node); if (found) return *found; CFNode* where = fn_builder ? shd_schedule_instruction(fn_builder->scheduler, node) : NULL; if (where) { CTerm emitted = c_emit_value_(emitter, fn_builder, fn_builder->instruction_printers[where->rpo_index], node); - register_emitted(emitter, fn_builder, node, emitted); + shd_c_register_emitted(emitter, fn_builder, node, emitted); return emitted; } else if (!can_appear_at_top_level(emitter, node)) { if (!fn_builder) { @@ -1017,21 +1017,21 @@ CTerm c_emit_value(Emitter* emitter, FnEmitter* fn_builder, const Node* node) { } // Pick the entry block of the current fn CTerm emitted = c_emit_value_(emitter, fn_builder, fn_builder->instruction_printers[0], node); - register_emitted(emitter, fn_builder, node, emitted); + shd_c_register_emitted(emitter, fn_builder, node, emitted); return emitted; } else { assert(!is_mem(node)); CTerm emitted = c_emit_value_(emitter, NULL, NULL, node); - register_emitted(emitter, NULL, node, emitted); + shd_c_register_emitted(emitter, NULL, node, emitted); return emitted; } } -CTerm c_emit_mem(Emitter* e, FnEmitter* b, const Node* mem) { +CTerm shd_c_emit_mem(Emitter* e, FnEmitter* b, const Node* mem) { assert(is_mem(mem)); if (mem->tag == AbsMem_TAG) return empty_term(); if (is_instruction(mem)) - return c_emit_value(e, b, mem); + return shd_c_emit_value(e, b, mem); shd_error("What sort of mem is this ?"); } diff --git a/src/driver/cli.c b/src/driver/cli.c index c706fb3e9..c136a5b56 100644 --- a/src/driver/cli.c +++ b/src/driver/cli.c @@ -211,7 +211,7 @@ DriverConfig shd_default_driver_config(void) { .output_filename = NULL, .cfg_output_filename = NULL, .shd_output_filename = NULL, - .c_emitter_config = default_c_emitter_config(), + .c_emitter_config = shd_default_c_emitter_config(), }; } From 0b20045157eababa7406ac04b21a0bb9034bdaee Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 17:04:23 +0200 Subject: [PATCH 676/693] spvb: fix another namespacing issue --- src/backend/spirv/emit_spv_control_flow.c | 2 +- src/backend/spirv/spirv_builder.c | 2 +- src/backend/spirv/spirv_builder.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index cdc027d6d..46161b47e 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -170,7 +170,7 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi LARRAY(SpvId, arr, ret_values->count); for (size_t i = 0; i < ret_values->count; i++) arr[i] = spv_emit_value(emitter, fn_builder, ret_values->nodes[i]); - SpvId return_that = spvb_composite(basic_block_builder, fn_ret_type_id(fn_builder->base), ret_values->count, arr); + SpvId return_that = spvb_composite(basic_block_builder, spvb_fn_ret_type_id(fn_builder->base), ret_values->count, arr); spvb_return_value(basic_block_builder, return_that); return; } diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index 5e3cfa9fe..a7ee26f78 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -515,7 +515,7 @@ SpvbFnBuilder* spvb_begin_fn(SpvbFileBuilder* file_builder, SpvId fn_id, SpvId f return fnb; } -SpvId fn_ret_type_id(SpvbFnBuilder* fnb){ +SpvId spvb_fn_ret_type_id(SpvbFnBuilder* fnb){ return fnb->fn_ret_type; } diff --git a/src/backend/spirv/spirv_builder.h b/src/backend/spirv/spirv_builder.h index 11fd4b0b6..69de36ed5 100644 --- a/src/backend/spirv/spirv_builder.h +++ b/src/backend/spirv/spirv_builder.h @@ -66,7 +66,7 @@ SpvId spvb_global_variable(SpvbFileBuilder*, SpvId id, SpvId type, SpvStorageCla // Function building stuff SpvbFnBuilder* spvb_begin_fn(SpvbFileBuilder*, SpvId fn_id, SpvId fn_type, SpvId fn_ret_type); -SpvId fn_ret_type_id(SpvbFnBuilder*); +SpvId spvb_fn_ret_type_id(SpvbFnBuilder* fnb); SpvId spvb_parameter(SpvbFnBuilder* fn_builder, SpvId param_type); SpvId spvb_local_variable(SpvbFnBuilder* fn_builder, SpvId type, SpvStorageClass storage_class); void spvb_declare_function(SpvbFileBuilder*, SpvbFnBuilder* fn_builder); From be140ffb947e6881313da53f5d89f58327c20cb3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 17:04:51 +0200 Subject: [PATCH 677/693] l2s: prefix --- src/driver/driver.c | 2 +- src/frontend/llvm/generator_l2s.c | 2 +- src/frontend/llvm/l2s.c | 38 ++++++++++---------- src/frontend/llvm/l2s.h | 2 +- src/frontend/llvm/l2s_annotations.c | 12 +++---- src/frontend/llvm/l2s_instr.c | 54 ++++++++++++++--------------- src/frontend/llvm/l2s_meta.c | 8 ++--- src/frontend/llvm/l2s_postprocess.c | 6 ++-- src/frontend/llvm/l2s_private.h | 29 ++++++++-------- src/frontend/llvm/l2s_type.c | 14 ++++---- src/frontend/llvm/l2s_value.c | 24 ++++++------- 11 files changed, 95 insertions(+), 96 deletions(-) diff --git a/src/driver/driver.c b/src/driver/driver.c index 5fcc7237f..d73cbbc8e 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -43,7 +43,7 @@ ShadyErrorCodes shd_driver_load_source_file(const CompilerConfig* config, Source switch (lang) { case SrcLLVM: { #ifdef LLVM_PARSER_PRESENT - bool ok = parse_llvm_into_shady(config, len, file_contents, name, mod); + bool ok = shd_parse_llvm(config, len, file_contents, name, mod); assert(ok); #else assert(false && "LLVM front-end missing in this version"); diff --git a/src/frontend/llvm/generator_l2s.c b/src/frontend/llvm/generator_l2s.c index 9c3f8429e..49b8f1fe0 100644 --- a/src/frontend/llvm/generator_l2s.c +++ b/src/frontend/llvm/generator_l2s.c @@ -1,7 +1,7 @@ #include "generator.h" void generate_llvm_shady_address_space_conversion(Growy* g, json_object* address_spaces) { - shd_growy_append_formatted(g, "AddressSpace convert_llvm_address_space(unsigned as) {\n"); + shd_growy_append_formatted(g, "AddressSpace l2s_convert_llvm_address_space(unsigned as) {\n"); shd_growy_append_formatted(g, "\tstatic bool warned = false;\n"); shd_growy_append_formatted(g, "\tswitch (as) {\n"); for (size_t i = 0; i < json_object_array_length(address_spaces); i++) { diff --git a/src/frontend/llvm/l2s.c b/src/frontend/llvm/l2s.c index 3aab87803..6c7209e38 100644 --- a/src/frontend/llvm/l2s.c +++ b/src/frontend/llvm/l2s.c @@ -53,7 +53,7 @@ static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { // printf("\n"); if (LLVMIsATerminatorInst(instr)) return; - const Node* emitted = convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr); + const Node* emitted = l2s_convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr); if (!emitted) continue; shd_dict_insert(LLVMValueRef, const Node*, p->map, instr, emitted); @@ -65,7 +65,7 @@ static void write_bb_body(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { static void write_bb_tail(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* bb_ctx) { LLVMBasicBlockRef bb = bb_ctx->bb; LLVMValueRef instr = LLVMGetLastInstruction(bb); - shd_set_abstraction_body(bb_ctx->nbb, shd_bld_finish(bb_ctx->builder, convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr))); + shd_set_abstraction_body(bb_ctx->nbb, shd_bld_finish(bb_ctx->builder, l2s_convert_instruction(p, fn_ctx, bb_ctx->nbb, bb_ctx->builder, instr))); } static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasicBlockRef bb) { @@ -80,7 +80,7 @@ static void prepare_bb(Parser* p, FnParseCtx* fn_ctx, BBParseCtx* ctx, LLVMBasic while (instr) { switch (LLVMGetInstructionOpcode(instr)) { case LLVMPHI: { - const Node* nparam = param(a, shd_as_qualified_type(convert_type(p, LLVMTypeOf(instr)), false), "phi"); + const Node* nparam = param(a, shd_as_qualified_type(l2s_convert_type(p, LLVMTypeOf(instr)), false), "phi"); shd_dict_insert(LLVMValueRef, const Node*, p->map, instr, nparam); shd_list_append(LLVMValueRef, phis, instr); params = shd_nodes_append(a, params, nparam); @@ -117,7 +117,7 @@ static BBParseCtx* get_bb_ctx(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef b return ctx; } -const Node* convert_basic_block_header(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { +const Node* l2s_convert_basic_block_header(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { const Node** found = shd_dict_find_value(LLVMValueRef, const Node*, p->map, bb); if (found) return *found; @@ -125,7 +125,7 @@ const Node* convert_basic_block_header(Parser* p, FnParseCtx* fn_ctx, LLVMBasicB return ctx->nbb; } -const Node* convert_basic_block_body(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { +const Node* l2s_convert_basic_block_body(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { BBParseCtx* ctx = get_bb_ctx(p, fn_ctx, bb); if (ctx->translated) return ctx->nbb; @@ -136,7 +136,7 @@ const Node* convert_basic_block_body(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlo return ctx->nbb; } -const Node* convert_function(Parser* p, LLVMValueRef fn) { +const Node* l2s_convert_function(Parser* p, LLVMValueRef fn) { if (is_llvm_intrinsic(fn)) { shd_warn_print("Skipping unknown LLVM intrinsic function: %s\n", LLVMGetValueName(fn)); return NULL; @@ -154,14 +154,14 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { Nodes params = shd_empty(a); for (LLVMValueRef oparam = LLVMGetFirstParam(fn); oparam; oparam = LLVMGetNextParam(oparam)) { LLVMTypeRef ot = LLVMTypeOf(oparam); - const Type* t = convert_type(p, ot); + const Type* t = l2s_convert_type(p, ot); const Node* nparam = param(a, shd_as_qualified_type(t, false), LLVMGetValueName(oparam)); shd_dict_insert(LLVMValueRef, const Node*, p->map, oparam, nparam); params = shd_nodes_append(a, params, nparam); if (oparam == LLVMGetLastParam(fn)) break; } - const Type* fn_type = convert_type(p, LLVMGlobalGetValueType(fn)); + const Type* fn_type = l2s_convert_type(p, LLVMGlobalGetValueType(fn)); assert(fn_type->tag == FnType_TAG); assert(fn_type->payload.fn_type.param_types.count == params.count); Nodes annotations = shd_empty(a); @@ -234,7 +234,7 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { return r; } -const Node* convert_global(Parser* p, LLVMValueRef global) { +const Node* l2s_convert_global(Parser* p, LLVMValueRef global) { const Node** found = shd_dict_find_value(LLVMValueRef, const Node*, p->map, global); if (found) return *found; IrArena* a = shd_module_get_arena(p->dst); @@ -254,14 +254,14 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { if (LLVMIsAGlobalVariable(global)) { LLVMValueRef value = LLVMGetInitializer(global); - const Type* type = convert_type(p, LLVMGlobalGetValueType(global)); + const Type* type = l2s_convert_type(p, LLVMGlobalGetValueType(global)); // nb: even if we have untyped pointers, they still carry useful address space info - const Type* ptr_t = convert_type(p, LLVMTypeOf(global)); + const Type* ptr_t = l2s_convert_type(p, LLVMTypeOf(global)); assert(ptr_t->tag == PtrType_TAG); AddressSpace as = ptr_t->payload.ptr_type.address_space; decl = global_var(p->dst, shd_empty(a), type, name, as); if (value && as != AsUniformConstant) - decl->payload.global_variable.init = convert_value(p, value); + decl->payload.global_variable.init = l2s_convert_value(p, value); if (UNTYPED_POINTERS) { Node* untyped_wrapper = constant(p->dst, shd_singleton(annotation(a, (Annotation) { .name = "Inline" })), ptr_t, shd_fmt_string_irarena(a, "%s_untyped", name)); @@ -270,9 +270,9 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { decl = untyped_wrapper; } } else { - const Type* type = convert_type(p, LLVMTypeOf(global)); + const Type* type = l2s_convert_type(p, LLVMTypeOf(global)); decl = constant(p->dst, shd_empty(a), type, name); - decl->payload.constant.value = convert_value(p, global); + decl->payload.constant.value = l2s_convert_value(p, global); } assert(decl && is_declaration(decl)); @@ -282,7 +282,7 @@ const Node* convert_global(Parser* p, LLVMValueRef global) { return r; } -bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { +bool shd_parse_llvm(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst) { LLVMContextRef context = LLVMContextCreate(); LLVMModuleRef src; LLVMMemoryBufferRef mem = LLVMCreateMemoryBufferWithMemoryRange(data, len, "my_great_buffer", false); @@ -313,15 +313,15 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* LLVMValueRef global_annotations = LLVMGetNamedGlobal(src, "llvm.global.annotations"); if (global_annotations) - process_llvm_annotations(&p, global_annotations); + l2s_process_llvm_annotations(&p, global_annotations); for (LLVMValueRef fn = LLVMGetFirstFunction(src); fn; fn = LLVMGetNextFunction(fn)) { - convert_function(&p, fn); + l2s_convert_function(&p, fn); } LLVMValueRef global = LLVMGetFirstGlobal(src); while (global) { - convert_global(&p, global); + l2s_convert_global(&p, global); if (global == LLVMGetLastGlobal(src)) break; global = LLVMGetNextGlobal(global); @@ -333,7 +333,7 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* aconfig.allow_fold = true; IrArena* arena2 = shd_new_ir_arena(&aconfig); *dst = shd_new_module(arena2, name); - postprocess(&p, dirty, *dst); + l2s_postprocess(&p, dirty, *dst); shd_log_fmt(DEBUGVV, "Shady module parsed from LLVM, after cleanup:"); shd_log_module(DEBUGVV, config, *dst); shd_verify_module(config, *dst); diff --git a/src/frontend/llvm/l2s.h b/src/frontend/llvm/l2s.h index 4e076224a..ec9b8e59b 100644 --- a/src/frontend/llvm/l2s.h +++ b/src/frontend/llvm/l2s.h @@ -5,6 +5,6 @@ #include typedef struct CompilerConfig_ CompilerConfig; -bool parse_llvm_into_shady(const CompilerConfig*, size_t len, const char* data, String name, Module** dst); +bool shd_parse_llvm(const CompilerConfig* config, size_t len, const char* data, String name, Module** dst); #endif diff --git a/src/frontend/llvm/l2s_annotations.c b/src/frontend/llvm/l2s_annotations.c index 23f999383..40573f98e 100644 --- a/src/frontend/llvm/l2s_annotations.c +++ b/src/frontend/llvm/l2s_annotations.c @@ -5,11 +5,11 @@ #include -ParsedAnnotation* find_annotation(Parser* p, const Node* n) { +ParsedAnnotation* l2s_find_annotation(Parser* p, const Node* n) { return shd_dict_find_value(const Node*, ParsedAnnotation, p->annotations, n); } -void add_annotation(Parser* p, const Node* n, ParsedAnnotation a) { +static void add_annotation(Parser* p, const Node* n, ParsedAnnotation a) { ParsedAnnotation* found = shd_dict_find_value(const Node*, ParsedAnnotation, p->annotations, n); if (found) { ParsedAnnotation* data = shd_arena_alloc(p->annotations_arena, sizeof(a)); @@ -60,13 +60,13 @@ static bool is_io_as(AddressSpace as) { return false; } -void process_llvm_annotations(Parser* p, LLVMValueRef global) { +void l2s_process_llvm_annotations(Parser* p, LLVMValueRef global) { IrArena* a = shd_module_get_arena(p->dst); - const Type* t = convert_type(p, LLVMGlobalGetValueType(global)); + const Type* t = l2s_convert_type(p, LLVMGlobalGetValueType(global)); assert(t->tag == ArrType_TAG); size_t arr_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(t->payload.arr_type.size), false); assert(arr_size > 0); - const Node* value = convert_value(p, LLVMGetInitializer(global)); + const Node* value = l2s_convert_value(p, LLVMGetInitializer(global)); assert(value->tag == Composite_TAG && value->payload.composite.contents.count == arr_size); for (size_t i = 0; i < arr_size; i++) { const Node* entry = value->payload.composite.contents.nodes[i]; @@ -144,7 +144,7 @@ void process_llvm_annotations(Parser* p, LLVMValueRef global) { }); } else if (strcmp(keyword, "extern") == 0) { assert(target->tag == GlobalVariable_TAG); - AddressSpace as = convert_llvm_address_space(strtol(strtok(NULL, "::"), NULL, 10)); + AddressSpace as = l2s_convert_llvm_address_space(strtol(strtok(NULL, "::"), NULL, 10)); if (is_io_as(as)) ((Node*) target)->payload.global_variable.init = NULL; add_annotation(p, target, (ParsedAnnotation) { diff --git a/src/frontend/llvm/l2s_instr.c b/src/frontend/llvm/l2s_instr.c index b8d8bb7f0..5f03484c0 100644 --- a/src/frontend/llvm/l2s_instr.c +++ b/src/frontend/llvm/l2s_instr.c @@ -17,7 +17,7 @@ static Nodes convert_operands(Parser* p, size_t num_ops, LLVMValueRef v) { if (LLVMIsAFunction(op) && (is_llvm_intrinsic(op) || is_shady_intrinsic(op))) ops[i] = NULL; else - ops[i] = convert_value(p, op); + ops[i] = l2s_convert_value(p, op); } Nodes operands = shd_nodes(a, num_ops, ops); return operands; @@ -57,7 +57,7 @@ static LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, LLVMBasicBlockRef dst, const Node* mem) { IrArena* a = fn_ctx->fn->arena; - const Node* dst_bb = convert_basic_block_body(p, fn_ctx, dst); + const Node* dst_bb = l2s_convert_basic_block_body(p, fn_ctx, dst); struct List* phis = *shd_dict_find_value(const Node*, struct List*, fn_ctx->phis, dst_bb); assert(phis); size_t params_count = shd_list_count(phis); @@ -65,8 +65,8 @@ static const Node* convert_jump(Parser* p, FnParseCtx* fn_ctx, const Node* src, for (size_t i = 0; i < params_count; i++) { LLVMValueRef phi = shd_read_list(LLVMValueRef, phis)[i]; for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { - if (convert_basic_block_header(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == src) { - params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); + if (l2s_convert_basic_block_header(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == src) { + params[i] = l2s_convert_value(p, LLVMGetIncomingValue(phi, j)); goto next; } } @@ -86,7 +86,7 @@ static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* eleme } /// instr may be an instruction or a constantexpr -const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { +const Node* l2s_convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { Node* fn = fn_ctx ? fn_ctx->fn : NULL; IrArena* a = shd_module_get_arena(p->dst); @@ -103,7 +103,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B else assert(false); - const Type* t = convert_type(p, LLVMTypeOf(instr)); + const Type* t = l2s_convert_type(p, LLVMTypeOf(instr)); #define BIND_PREV_R(t) shd_bld_add_instruction_extract_count(b, r, 1) @@ -115,7 +115,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B if (dbgloc) { //Nodes* found = find_value_dict(const Node*, Nodes, p->scopes, fn_or_bb); //if (!found) { - Nodes str = scope_to_string(p, dbgloc); + Nodes str = l2s_scope_to_string(p, dbgloc); //insert_dict(const Node*, Nodes, p->scopes, fn_or_bb, str); shd_debugv_print("Found a debug location for "); shd_log_node(DEBUGV, fn_or_bb); @@ -148,7 +148,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B targets[i] = LLVMGetSuccessor(instr, i); if (LLVMIsConditional(instr)) { assert(n_targets == 2); - const Node* condition = convert_value(p, LLVMGetCondition(instr)); + const Node* condition = l2s_convert_value(p, LLVMGetCondition(instr)); return branch(a, (Branch) { .condition = condition, .true_jump = convert_jump(p, fn_ctx, fn_or_bb, targets[0], shd_bb_mem(b)), @@ -161,13 +161,13 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B } } case LLVMSwitch: { - const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); + const Node* inspectee = l2s_convert_value(p, LLVMGetOperand(instr, 0)); const Node* default_jump = convert_jump(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, 1), shd_bb_mem(b)); int n_targets = LLVMGetNumOperands(instr) / 2 - 1; LARRAY(const Node*, targets, n_targets); LARRAY(const Node*, literals, n_targets); for (size_t i = 0; i < n_targets; i++) { - literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); + literals[i] = l2s_convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); targets[i] = convert_jump(p, fn_ctx, fn_or_bb, (LLVMBasicBlockRef) LLVMGetOperand(instr, i * 2 + 3), shd_bb_mem(b)); } return br_switch(a, (Switch) { @@ -200,14 +200,14 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B case LLVMFDiv: return prim_op_helper(a, div_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMSDiv: { - const Type* int_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* int_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* signed_t = change_int_t_sign(int_t, true); return prim_op_helper(a, reinterpret_op, shd_singleton(int_t), shd_singleton(prim_op_helper(a, div_op, shd_empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)))); } case LLVMURem: case LLVMFRem: return prim_op_helper(a, mod_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMSRem: { - const Type* int_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* int_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* signed_t = change_int_t_sign(int_t, true); return prim_op_helper(a, reinterpret_op, shd_singleton(int_t), shd_singleton(prim_op_helper(a, mod_op, shd_empty(a), reinterpret_operands(b, convert_operands(p, num_ops, instr), signed_t)))); } case LLVMShl: @@ -224,7 +224,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B return prim_op_helper(a, xor_op, shd_empty(a), convert_operands(p, num_ops, instr)); case LLVMAlloca: { assert(t->tag == PtrType_TAG); - const Type* allocated_t = convert_type(p, LLVMGetAllocatedType(instr)); + const Type* allocated_t = l2s_convert_type(p, LLVMGetAllocatedType(instr)); const Type* allocated_ptr_t = ptr_type(a, (PtrType) { .pointed_type = allocated_t, .address_space = AsPrivate }); const Node* r = shd_first(shd_bld_add_instruction_extract_count(b, stack_alloc(a, (StackAlloc) { .type = allocated_t, .mem = shd_bb_mem(b) }), 1)); if (UNTYPED_POINTERS) { @@ -239,7 +239,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B const Node* ptr = shd_first(ops); if (UNTYPED_POINTERS) { const Type* element_t = t; - const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* untyped_ptr_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = shd_first(shd_bld_add_instruction_extract_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } @@ -251,8 +251,8 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B assert(ops.count == 2); const Node* ptr = ops.nodes[1]; if (UNTYPED_POINTERS) { - const Type* element_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); - const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 1))); + const Type* element_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* untyped_ptr_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 1))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = shd_first(shd_bld_add_instruction_extract_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } @@ -262,16 +262,16 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B Nodes ops = convert_operands(p, num_ops, instr); const Node* ptr = shd_first(ops); if (UNTYPED_POINTERS) { - const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); - const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* element_t = l2s_convert_type(p, LLVMGetGEPSourceElementType(instr)); + const Type* untyped_ptr_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); const Type* typed_ptr = type_untyped_ptr(untyped_ptr_t, element_t); ptr = shd_first(shd_bld_add_instruction_extract_count(b, prim_op_helper(a, reinterpret_op, shd_singleton(typed_ptr), shd_singleton(ptr)), 1)); } ops = shd_change_node_at_index(a, ops, 0, ptr); const Node* r = lea_helper(a, ops.nodes[0], ops.nodes[1], shd_nodes(a, ops.count - 2, &ops.nodes[2])); if (UNTYPED_POINTERS) { - const Type* element_t = convert_type(p, LLVMGetGEPSourceElementType(instr)); - const Type* untyped_ptr_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* element_t = l2s_convert_type(p, LLVMGetGEPSourceElementType(instr)); + const Type* untyped_ptr_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); bool idk; //element_t = shd_as_qualified_type(element_t, false); shd_enter_composite_type_indices(&element_t, &idk, shd_nodes(a, ops.count - 2, &ops.nodes[2]), true); @@ -282,7 +282,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B } case LLVMTrunc: case LLVMZExt: { - const Type* src_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* src_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); Nodes ops = convert_operands(p, num_ops, instr); const Node* r; if (src_t->tag == Bool_TAG) { @@ -306,7 +306,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B } case LLVMSExt: { const Node* r; // reinterpret as signed, convert to change size, reinterpret back to target T - const Type* src_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* src_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); Nodes ops = convert_operands(p, num_ops, instr); if (src_t->tag == Bool_TAG) { assert(t->tag == Int_TAG); @@ -338,7 +338,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B assert(num_ops == 1); const Node* src = shd_first(convert_operands(p, num_ops, instr)); Op op = reinterpret_op; - const Type* src_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* src_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); if (src_t->tag == PtrType_TAG && t->tag == PtrType_TAG) { if ((t->payload.ptr_type.address_space == AsGeneric)) { switch (src_t->payload.ptr_type.address_space) { @@ -396,7 +396,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B } Nodes ops = convert_operands(p, num_ops, instr); if (cast_to_signed) { - const Type* unsigned_t = convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); + const Type* unsigned_t = l2s_convert_type(p, LLVMTypeOf(LLVMGetOperand(instr, 0))); assert(unsigned_t->tag == Int_TAG); const Type* signed_t = change_int_t_sign(unsigned_t, true); ops = reinterpret_operands(b, ops, signed_t); @@ -456,8 +456,8 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B if (intrinsic) { assert(LLVMIsAFunction(callee)); if (strcmp(intrinsic, "llvm.dbg.declare") == 0) { - const Node* target = convert_value(p, LLVMGetOperand(instr, 0)); - const Node* meta = convert_value(p, LLVMGetOperand(instr, 1)); + const Node* target = l2s_convert_value(p, LLVMGetOperand(instr, 0)); + const Node* meta = l2s_convert_value(p, LLVMGetOperand(instr, 1)); assert(meta->tag == RefDecl_TAG); meta = meta->payload.ref_decl.decl; assert(meta->tag == GlobalVariable_TAG); @@ -592,7 +592,7 @@ const Node* convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, B .mem = shd_bb_mem(b), .callee = prim_op_helper(a, reinterpret_op, shd_singleton(ptr_type(a, (PtrType) { .address_space = AsGeneric, - .pointed_type = convert_type(p, callee_type) + .pointed_type = l2s_convert_type(p, callee_type) })), shd_singleton(ops.nodes[num_args])), .args = shd_nodes(a, num_args, ops.nodes), })); diff --git a/src/frontend/llvm/l2s_meta.c b/src/frontend/llvm/l2s_meta.c index 113d14905..914672d82 100644 --- a/src/frontend/llvm/l2s_meta.c +++ b/src/frontend/llvm/l2s_meta.c @@ -16,7 +16,7 @@ static Nodes convert_mdnode_operands(Parser* p, LLVMValueRef mdnode) { LARRAY(const Node*, cops, count); for (size_t i = 0; i < count; i++) - cops[i] = ops[i] ? convert_value(p, ops[i]) : string_lit_helper(a, "null"); + cops[i] = ops[i] ? l2s_convert_value(p, ops[i]) : string_lit_helper(a, "null"); Nodes args = shd_nodes(a, count, cops); return args; } @@ -101,7 +101,7 @@ LLVM_DI_WITH_PARENT_SCOPES(N) return ops[1]; } -Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { +Nodes l2s_scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { IrArena* a = shd_module_get_arena(p->dst); Nodes str = shd_empty(a); @@ -109,7 +109,7 @@ Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { while (true) { if (!scope) break; - str = shd_nodes_prepend(a, str, shd_uint32_literal(a, convert_metadata(p, scope)->id)); + str = shd_nodes_prepend(a, str, shd_uint32_literal(a, l2s_convert_metadata(p, scope)->id)); // LLVMDumpValue(LLVMMetadataAsValue(p->ctx, scope)); // printf("\n"); @@ -122,7 +122,7 @@ Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc) { return str; } -const Node* convert_metadata(Parser* p, LLVMMetadataRef meta) { +const Node* l2s_convert_metadata(Parser* p, LLVMMetadataRef meta) { IrArena* a = shd_module_get_arena(p->dst); LLVMMetadataKind kind = LLVMGetMetadataKind(meta); LLVMValueRef v = LLVMMetadataAsValue(p->ctx, meta); diff --git a/src/frontend/llvm/l2s_postprocess.c b/src/frontend/llvm/l2s_postprocess.c index 6e7050a65..85bde99c5 100644 --- a/src/frontend/llvm/l2s_postprocess.c +++ b/src/frontend/llvm/l2s_postprocess.c @@ -55,7 +55,7 @@ static const Node* process_node(Context* ctx, const Node* node) { case Function_TAG: { Nodes new_params = remake_params(ctx, node->payload.fun.params); Nodes old_annotations = node->payload.fun.annotations; - ParsedAnnotation* an = find_annotation(ctx->p, node); + ParsedAnnotation* an = l2s_find_annotation(ctx->p, node); Op primop_intrinsic = PRIMOPS_COUNT; while (an) { if (strcmp(get_annotation_name(an->payload), "PrimOpIntrinsic") == 0) { @@ -98,7 +98,7 @@ static const Node* process_node(Context* ctx, const Node* node) { const Node* old_init = node->payload.global_variable.init; Nodes annotations = shd_rewrite_nodes(r, node->payload.global_variable.annotations); const Type* type = shd_rewrite_node(r, node->payload.global_variable.type); - ParsedAnnotation* an = find_annotation(ctx->p, node); + ParsedAnnotation* an = l2s_find_annotation(ctx->p, node); AddressSpace old_as = as; while (an) { annotations = shd_nodes_append(a, annotations, shd_rewrite_node(r, an->payload)); @@ -131,7 +131,7 @@ static const Node* process_node(Context* ctx, const Node* node) { return shd_recreate_node(&ctx->rewriter, node); } -void postprocess(Parser* p, Module* src, Module* dst) { +void l2s_postprocess(Parser* p, Module* src, Module* dst) { assert(src != dst); Context ctx = { .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process_node), diff --git a/src/frontend/llvm/l2s_private.h b/src/frontend/llvm/l2s_private.h index 682ad167a..68ce8cf0f 100644 --- a/src/frontend/llvm/l2s_private.h +++ b/src/frontend/llvm/l2s_private.h @@ -49,21 +49,20 @@ typedef struct ParsedAnnotationContents_ { struct ParsedAnnotationContents_* next; } ParsedAnnotation; -ParsedAnnotation* find_annotation(Parser*, const Node*); +ParsedAnnotation* l2s_find_annotation(Parser* p, const Node* n); ParsedAnnotation* next_annotation(ParsedAnnotation*); -void add_annotation(Parser*, const Node*, ParsedAnnotation); -void process_llvm_annotations(Parser* p, LLVMValueRef global); +void l2s_process_llvm_annotations(Parser* p, LLVMValueRef global); -AddressSpace convert_llvm_address_space(unsigned); -const Node* convert_value(Parser* p, LLVMValueRef v); -const Node* convert_function(Parser* p, LLVMValueRef fn); -const Type* convert_type(Parser* p, LLVMTypeRef t); -const Node* convert_metadata(Parser* p, LLVMMetadataRef meta); -const Node* convert_global(Parser* p, LLVMValueRef global); -const Node* convert_function(Parser* p, LLVMValueRef fn); -const Node* convert_basic_block_header(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); -const Node* convert_basic_block_body(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); +AddressSpace l2s_convert_llvm_address_space(unsigned); +const Node* l2s_convert_value(Parser* p, LLVMValueRef v); +const Node* l2s_convert_function(Parser* p, LLVMValueRef fn); +const Type* l2s_convert_type(Parser* p, LLVMTypeRef t); +const Node* l2s_convert_metadata(Parser* p, LLVMMetadataRef meta); +const Node* l2s_convert_global(Parser* p, LLVMValueRef global); +const Node* l2s_convert_function(Parser* p, LLVMValueRef fn); +const Node* l2s_convert_basic_block_header(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); +const Node* l2s_convert_basic_block_body(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); typedef struct { struct List* list; @@ -76,11 +75,11 @@ typedef struct { } JumpTodo; void convert_jump_finish(Parser* p, FnParseCtx*, JumpTodo todo); -const Node* convert_instruction(Parser* p, FnParseCtx*, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); +const Node* l2s_convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); -Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc); +Nodes l2s_scope_to_string(Parser* p, LLVMMetadataRef dbgloc); -void postprocess(Parser*, Module* src, Module* dst); +void l2s_postprocess(Parser* p, Module* src, Module* dst); inline static String is_llvm_intrinsic(LLVMValueRef fn) { assert(LLVMIsAFunction(fn) || LLVMIsConstant(fn)); diff --git a/src/frontend/llvm/l2s_type.c b/src/frontend/llvm/l2s_type.c index 5d9fa1fd6..bebaf087c 100644 --- a/src/frontend/llvm/l2s_type.c +++ b/src/frontend/llvm/l2s_type.c @@ -5,7 +5,7 @@ #include "dict.h" #include "util.h" -const Type* convert_type(Parser* p, LLVMTypeRef t) { +const Type* l2s_convert_type(Parser* p, LLVMTypeRef t) { const Type** found = shd_dict_find_value(LLVMTypeRef, const Type*, p->map, t); if (found) return *found; IrArena* a = shd_module_get_arena(p->dst); @@ -35,8 +35,8 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { LLVMGetParamTypes(t, param_types); LARRAY(const Type*, cparam_types, num_params); for (size_t i = 0; i < num_params; i++) - cparam_types[i] = shd_as_qualified_type(convert_type(p, param_types[i]), false); - const Type* ret_type = convert_type(p, LLVMGetReturnType(t)); + cparam_types[i] = shd_as_qualified_type(l2s_convert_type(p, param_types[i]), false); + const Type* ret_type = l2s_convert_type(p, LLVMGetReturnType(t)); if (LLVMGetTypeKind(LLVMGetReturnType(t)) == LLVMVoidTypeKind) ret_type = empty_multiple_return_type(a); else @@ -61,7 +61,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { LLVMGetStructElementTypes(t, elements); LARRAY(const Type*, celements, size); for (size_t i = 0; i < size; i++) { - celements[i] = convert_type(p, elements[i]); + celements[i] = l2s_convert_type(p, elements[i]); } const Node* product = record_type(a, (RecordType) { @@ -75,7 +75,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { } case LLVMArrayTypeKind: { unsigned length = LLVMGetArrayLength(t); - const Type* elem_t = convert_type(p, LLVMGetElementType(t)); + const Type* elem_t = l2s_convert_type(p, LLVMGetElementType(t)); return arr_type(a, (ArrType) { .element_type = elem_t, .size = shd_uint32_literal(a, length)}); } case LLVMPointerTypeKind: { @@ -104,7 +104,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { .imageformat = 0 })}); } - AddressSpace as = convert_llvm_address_space(llvm_as); + AddressSpace as = l2s_convert_llvm_address_space(llvm_as); const Type* pointee = NULL; #if !UNTYPED_POINTERS LLVMTypeRef element_type = LLVMGetElementType(t); @@ -119,7 +119,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t) { } case LLVMVectorTypeKind: { unsigned width = LLVMGetVectorSize(t); - const Type* elem_t = convert_type(p, LLVMGetElementType(t)); + const Type* elem_t = l2s_convert_type(p, LLVMGetElementType(t)); return pack_type(a, (PackType) { .element_type = elem_t, .width = (size_t) width }); } case LLVMMetadataTypeKind: diff --git a/src/frontend/llvm/l2s_value.c b/src/frontend/llvm/l2s_value.c index f87ea6d99..bdf228e7a 100644 --- a/src/frontend/llvm/l2s_value.c +++ b/src/frontend/llvm/l2s_value.c @@ -41,13 +41,13 @@ static const Node* data_composite(const Type* t, size_t size, LLVMValueRef v) { return composite_helper(a, t, shd_nodes(a, size, elements)); } -const Node* convert_value(Parser* p, LLVMValueRef v) { +const Node* l2s_convert_value(Parser* p, LLVMValueRef v) { const Type** found = shd_dict_find_value(LLVMTypeRef, const Type*, p->map, v); if (found) return *found; IrArena* a = shd_module_get_arena(p->dst); const Node* r = NULL; - const Type* t = LLVMGetValueKind(v) != LLVMMetadataAsValueValueKind ? convert_type(p, LLVMTypeOf(v)) : NULL; + const Type* t = LLVMGetValueKind(v) != LLVMMetadataAsValueValueKind ? l2s_convert_type(p, LLVMTypeOf(v)) : NULL; switch (LLVMGetValueKind(v)) { case LLVMArgumentValueKind: @@ -61,14 +61,14 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { case LLVMMemoryPhiValueKind: break; case LLVMFunctionValueKind: - r = convert_function(p, v); + r = l2s_convert_function(p, v); break; case LLVMGlobalAliasValueKind: break; case LLVMGlobalIFuncValueKind: break; case LLVMGlobalVariableValueKind: - r = convert_global(p, v); + r = l2s_convert_global(p, v); break; case LLVMBlockAddressValueKind: break; @@ -82,7 +82,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { r = ref_decl_helper(a, decl); shd_dict_insert(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = shd_bld_begin_pure(a); - decl->payload.constant.value = shd_bld_to_instr_yield_value(bb, convert_instruction(p, NULL, NULL, bb, v)); + decl->payload.constant.value = shd_bld_to_instr_yield_value(bb, l2s_convert_instruction(p, NULL, NULL, bb, v)); return r; } case LLVMConstantDataArrayValueKind: { @@ -105,7 +105,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { for (size_t i = 0; i < size; i++) { LLVMValueRef value = LLVMGetOperand(v, i); assert(value); - elements[i] = convert_value(p, value); + elements[i] = l2s_convert_value(p, value); } return composite_helper(a, t, shd_nodes(a, size, elements)); } @@ -116,14 +116,14 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { for (size_t i = 0; i < size; i++) { LLVMValueRef value = LLVMGetOperand(v, i); assert(value); - elements[i] = convert_value(p, value); + elements[i] = l2s_convert_value(p, value); } return composite_helper(a, t, shd_nodes(a, size, elements)); } case LLVMUndefValueValueKind: - return undef(a, (Undef) { .type = convert_type(p, LLVMTypeOf(v)) }); + return undef(a, (Undef) { .type = l2s_convert_type(p, LLVMTypeOf(v)) }); case LLVMConstantAggregateZeroValueKind: - return shd_get_default_value(a, convert_type(p, LLVMTypeOf(v))); + return shd_get_default_value(a, l2s_convert_type(p, LLVMTypeOf(v))); case LLVMConstantArrayValueKind: { assert(t->tag == ArrType_TAG); size_t arr_size = shd_get_int_literal_value(*shd_resolve_to_int_literal(t->payload.arr_type.size), false); @@ -132,7 +132,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { for (size_t i = 0; i < arr_size; i++) { LLVMValueRef value = LLVMGetOperand(v, i); assert(value); - elements[i] = convert_value(p, value); + elements[i] = l2s_convert_value(p, value); } return composite_helper(a, t, shd_nodes(a, arr_size, elements)); } @@ -177,14 +177,14 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { break; case LLVMMetadataAsValueValueKind: { LLVMMetadataRef meta = LLVMValueAsMetadata(v); - r = convert_metadata(p, meta); + r = l2s_convert_metadata(p, meta); } case LLVMInlineAsmValueKind: break; case LLVMInstructionValueKind: break; case LLVMPoisonValueValueKind: - return undef(a, (Undef) { .type = convert_type(p, LLVMTypeOf(v)) }); + return undef(a, (Undef) { .type = l2s_convert_type(p, LLVMTypeOf(v)) }); } if (r) { From d1c691ce5cf05ebe282754fa74b3738f4d1a22fd Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 17:07:04 +0200 Subject: [PATCH 678/693] fix misc symbols --- include/shady/be/spirv.h | 2 +- src/backend/spirv/emit_spv.c | 2 +- src/driver/driver.c | 2 +- src/runtime/vulkan/vk_runtime_program.c | 2 +- src/shady/analysis/cfg.c | 2 +- src/shady/analysis/cfg.h | 2 +- src/shady/analysis/cfg_dump.c | 4 ++-- src/shady/analysis/looptree.c | 4 ++-- src/shady/analysis/verify.c | 4 ++-- src/shady/passes/import.c | 2 +- src/shady/passes/opt_demote_alloca.c | 2 +- src/shady/passes/scope2control.c | 2 +- zhady/shady.i | 3 +++ 13 files changed, 18 insertions(+), 15 deletions(-) diff --git a/include/shady/be/spirv.h b/include/shady/be/spirv.h index 7f70e1dad..a66b0dd31 100644 --- a/include/shady/be/spirv.h +++ b/include/shady/be/spirv.h @@ -4,7 +4,7 @@ #include "shady/ir/base.h" typedef struct CompilerConfig_ CompilerConfig; -void emit_spirv(const CompilerConfig* config, Module*, size_t* output_size, char** output, Module** new_mod); +void shd_emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, char** output, Module** new_mod); #endif diff --git a/src/backend/spirv/emit_spv.c b/src/backend/spirv/emit_spv.c index 2d159b8c4..bf3ae9821 100644 --- a/src/backend/spirv/emit_spv.c +++ b/src/backend/spirv/emit_spv.c @@ -325,7 +325,7 @@ static Module* run_backend_specific_passes(const CompilerConfig* config, Module* return *pmod; } -void emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, char** output, Module** new_mod) { +void shd_emit_spirv(const CompilerConfig* config, Module* mod, size_t* output_size, char** output, Module** new_mod) { IrArena* initial_arena = shd_module_get_arena(mod); mod = run_backend_specific_passes(config, mod); IrArena* arena = shd_module_get_arena(mod); diff --git a/src/driver/driver.c b/src/driver/driver.c index d73cbbc8e..9edf18124 100644 --- a/src/driver/driver.c +++ b/src/driver/driver.c @@ -162,7 +162,7 @@ ShadyErrorCodes shd_driver_compile(DriverConfig* args, Module* mod) { char* output_buffer; switch (args->target) { case TgtAuto: SHADY_UNREACHABLE; - case TgtSPV: emit_spirv(&args->config, mod, &output_size, &output_buffer, NULL); break; + case TgtSPV: shd_emit_spirv(&args->config, mod, &output_size, &output_buffer, NULL); break; case TgtC: args->c_emitter_config.dialect = CDialect_C11; shd_emit_c(&args->config, args->c_emitter_config, mod, &output_size, &output_buffer, NULL); diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index 2c8faf7ed..fdab0e0bb 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -381,7 +381,7 @@ static bool compile_specialized_program(VkrSpecProgram* spec) { CHECK(shd_run_compiler_passes(&config, &spec->specialized_module) == CompilationNoError, return false); Module* final_mod; - emit_spirv(&config, spec->specialized_module, &spec->spirv_size, &spec->spirv_bytes, &final_mod); + shd_emit_spirv(&config, spec->specialized_module, &spec->spirv_size, &spec->spirv_bytes, &final_mod); CHECK(extract_parameters_info(&spec->parameters, final_mod), return false); diff --git a/src/shady/analysis/cfg.c b/src/shady/analysis/cfg.c index 9d95c5ea5..4bd123339 100644 --- a/src/shady/analysis/cfg.c +++ b/src/shady/analysis/cfg.c @@ -14,7 +14,7 @@ #pragma GCC diagnostic error "-Wswitch" -struct List* build_cfgs(Module* mod, CFGBuildConfig config) { +struct List* shd_build_cfgs(Module* mod, CFGBuildConfig config) { struct List* cfgs = shd_new_list(CFG*); Nodes decls = shd_module_get_declarations(mod); diff --git a/src/shady/analysis/cfg.h b/src/shady/analysis/cfg.h index 0ff3f15e5..29d9af834 100644 --- a/src/shady/analysis/cfg.h +++ b/src/shady/analysis/cfg.h @@ -96,7 +96,7 @@ typedef struct CFG_ { /** * @returns @ref List of @ref CFG* */ -struct List* build_cfgs(Module*, CFGBuildConfig); +struct List* shd_build_cfgs(Module* mod, CFGBuildConfig config); /** Construct the CFG starting in node. */ diff --git a/src/shady/analysis/cfg_dump.c b/src/shady/analysis/cfg_dump.c index 9fd870433..e681b9985 100644 --- a/src/shady/analysis/cfg_dump.c +++ b/src/shady/analysis/cfg_dump.c @@ -153,7 +153,7 @@ void shd_dump_cfgs(FILE* output, Module* mod) { output = stderr; fprintf(output, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); + struct List* cfgs = shd_build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; dump_cfg(output, cfg); @@ -191,7 +191,7 @@ void shd_dump_domtree_cfg(Printer* p, CFG* s) { void shd_dump_domtree_module(Printer* p, Module* mod) { shd_print(p, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); + struct List* cfgs = shd_build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; shd_dump_domtree_cfg(p, cfg); diff --git a/src/shady/analysis/looptree.c b/src/shady/analysis/looptree.c index 73606006c..785375a4d 100644 --- a/src/shady/analysis/looptree.c +++ b/src/shady/analysis/looptree.c @@ -26,7 +26,7 @@ typedef struct { KeyHash shd_hash_node(const Node**); bool shd_compare_node(const Node**, const Node**); -LTNode* new_lf_node(int type, LTNode* parent, int depth, struct List* cf_nodes) { +static LTNode* new_lf_node(int type, LTNode* parent, int depth, struct List* cf_nodes) { LTNode* n = calloc(sizeof(LTNode), 1); n->parent = parent; n->type = type; @@ -284,7 +284,7 @@ void shd_dump_loop_trees(FILE* output, Module* mod) { output = stderr; fprintf(output, "digraph G {\n"); - struct List* cfgs = build_cfgs(mod, default_forward_cfg_build()); + struct List* cfgs = shd_build_cfgs(mod, default_forward_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; LoopTree* lt = shd_new_loop_tree(cfg); diff --git a/src/shady/analysis/verify.c b/src/shady/analysis/verify.c index 4c5d78c0a..cd5ec63ad 100644 --- a/src/shady/analysis/verify.c +++ b/src/shady/analysis/verify.c @@ -44,7 +44,7 @@ static void verify_same_arena(Module* mod) { } static void verify_scoping(const CompilerConfig* config, Module* mod) { - struct List* cfgs = build_cfgs(mod, structured_scope_cfg_build()); + struct List* cfgs = shd_build_cfgs(mod, structured_scope_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; Scheduler* scheduler = shd_new_scheduler(cfg); @@ -137,7 +137,7 @@ static void verify_schedule_visitor(ScheduleContext* ctx, const Node* node) { } static void verify_bodies(const CompilerConfig* config, Module* mod) { - struct List* cfgs = build_cfgs(mod, structured_scope_cfg_build()); + struct List* cfgs = shd_build_cfgs(mod, structured_scope_cfg_build()); for (size_t i = 0; i < shd_list_count(cfgs); i++) { CFG* cfg = shd_read_list(CFG*, cfgs)[i]; diff --git a/src/shady/passes/import.c b/src/shady/passes/import.c index 588cfb66b..02dd87872 100644 --- a/src/shady/passes/import.c +++ b/src/shady/passes/import.c @@ -17,7 +17,7 @@ static void replace_or_compare(const Node** dst, const Node* with) { } } -const Node* import_node(Rewriter* r, const Node* node) { +static const Node* import_node(Rewriter* r, const Node* node) { if (is_declaration(node)) { Node* existing = shd_module_get_declaration(r->dst_module, get_declaration_name(node)); if (existing) { diff --git a/src/shady/passes/opt_demote_alloca.c b/src/shady/passes/opt_demote_alloca.c index 4923e0f18..b70d0adf2 100644 --- a/src/shady/passes/opt_demote_alloca.c +++ b/src/shady/passes/opt_demote_alloca.c @@ -100,7 +100,7 @@ static void visit_ptr_uses(const Node* ptr_value, const Type* slice_type, Alloca } } -PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { +static PtrSourceKnowledge get_ptr_source_knowledge(Context* ctx, const Node* ptr) { PtrSourceKnowledge k = { 0 }; while (ptr) { assert(is_value(ptr)); diff --git a/src/shady/passes/scope2control.c b/src/shady/passes/scope2control.c index 03dd58da8..b6b9a010c 100644 --- a/src/shady/passes/scope2control.c +++ b/src/shady/passes/scope2control.c @@ -135,7 +135,7 @@ static void wrap_in_controls(Context* ctx, CFG* cfg, Node* nabs, const Node* oab shd_set_abstraction_body(nabs, body); } -bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { +static bool lexical_scope_is_nested(Nodes scope, Nodes parentMaybe) { if (scope.count <= parentMaybe.count) return false; for (size_t i = 0; i < parentMaybe.count; i++) { diff --git a/zhady/shady.i b/zhady/shady.i index c2af81e8d..f2db06444 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -12,6 +12,9 @@ #include "shady/runtime.h" #include "shady/driver.h" + +* mod + #include "shady/config.h" #include "shady/be/c.h" #include "shady/be/spirv.h" From aeb43e9f13d8895c2b443bd45c1cb40c4b6e22d1 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 17:08:35 +0200 Subject: [PATCH 679/693] prefix get_node_class_from_tag --- src/shady/api/generator_grammar.c | 4 ++-- src/shady/generator_node.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shady/api/generator_grammar.c b/src/shady/api/generator_grammar.c index 7126304c2..454627aba 100644 --- a/src/shady/api/generator_grammar.c +++ b/src/shady/api/generator_grammar.c @@ -124,7 +124,7 @@ static void generate_isa_for_class(Growy* g, json_object* nodes, String class, S shd_growy_append_formatted(g, "static inline %sTag is_%s(const Node* node) {\n", capitalized_class, class); else shd_growy_append_formatted(g, "static inline bool is_%s(const Node* node) {\n", class); - shd_growy_append_formatted(g, "\tif (get_node_class_from_tag(node->tag) & Nc%s)\n", capitalized_class); + shd_growy_append_formatted(g, "\tif (shd_get_node_class_from_tag(node->tag) & Nc%s)\n", capitalized_class); if (use_enum) { shd_growy_append_formatted(g, "\t\treturn (%sTag) node->tag;\n", capitalized_class); shd_growy_append_formatted(g, "\treturn (%sTag) 0;\n", capitalized_class); @@ -255,7 +255,7 @@ void generate(Growy* g, json_object* src) { json_object* nodes = json_object_object_get(src, "nodes"); generate_node_tags(g, nodes); - shd_growy_append_formatted(g, "NodeClass get_node_class_from_tag(NodeTag tag);\n\n"); + shd_growy_append_formatted(g, "NodeClass shd_get_node_class_from_tag(NodeTag tag);\n\n"); generate_node_payloads(g, src, nodes); generate_node_type(g, nodes); diff --git a/src/shady/generator_node.c b/src/shady/generator_node.c index 8b1554ea6..59e2b2c11 100644 --- a/src/shady/generator_node.c +++ b/src/shady/generator_node.c @@ -150,7 +150,7 @@ void generate(Growy* g, json_object* src) { generate_node_has_payload_array(g, nodes); generate_node_payload_hash_fn(g, src, nodes); generate_node_payload_cmp_fn(g, src, nodes); - generate_bit_enum_classifier(g, "get_node_class_from_tag", "NodeClass", "Nc", "NodeTag", "", "_TAG", nodes); + generate_bit_enum_classifier(g, "shd_get_node_class_from_tag", "NodeClass", "Nc", "NodeTag", "", "_TAG", nodes); json_object* node_classes = json_object_object_get(src, "node-classes"); for (size_t i = 0; i < json_object_array_length(node_classes); i++) { From a9f93792bd94b9757db79af3e25d6f8b15086837 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 17:09:04 +0200 Subject: [PATCH 680/693] rename ext.h fns --- include/shady/ir/ext.h | 2 +- src/frontend/slim/parser.c | 6 +++--- src/shady/ir/ext.c | 2 +- src/shady/passes/lift_indirect_targets.c | 4 ++-- src/shady/passes/lower_callf.c | 4 ++-- src/shady/passes/lower_subgroup_ops.c | 2 +- src/shady/passes/scope_heuristic.c | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/shady/ir/ext.h b/include/shady/ir/ext.h index 990728db0..75faf2166 100644 --- a/include/shady/ir/ext.h +++ b/include/shady/ir/ext.h @@ -4,6 +4,6 @@ #include "shady/ir/base.h" #include "shady/ir/builder.h" -const Node* gen_ext_instruction(BodyBuilder*, String set, int opcode, const Type* return_t, Nodes operands); +const Node* shd_bld_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands); #endif diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 1bac0aabb..14b751aa8 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -859,13 +859,13 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); - gen_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(arena), shd_nodes_prepend(arena, strings2nodes(arena, ids), instruction)); + shd_bld_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(arena), shd_nodes_prepend(arena, strings2nodes(arena, ids), instruction)); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); - gen_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(arena), shd_nodes_prepend(arena, shd_concat_nodes(arena, strings2nodes(arena, ids), types), instruction)); + shd_bld_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(arena), shd_nodes_prepend(arena, shd_concat_nodes(arena, strings2nodes(arena, ids), types), instruction)); } else { const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; @@ -1047,7 +1047,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t } } - gen_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), shd_concat_nodes(arena, ids, conts)); + shd_bld_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), shd_concat_nodes(arena, ids, conts)); expect(accept_token(ctx, rbracket_tok), "']'"); shd_set_abstraction_body(cont_wrapper_case, shd_bld_jump(cont_wrapper_bb, terminator_case, shd_empty(arena))); diff --git a/src/shady/ir/ext.c b/src/shady/ir/ext.c index c5b8eab71..b10c8fcab 100644 --- a/src/shady/ir/ext.c +++ b/src/shady/ir/ext.c @@ -1,7 +1,7 @@ #include "shady/ir/ext.h" #include "shady/ir/grammar.h" -const Node* gen_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { +const Node* shd_bld_ext_instruction(BodyBuilder* bb, String set, int opcode, const Type* return_t, Nodes operands) { return shd_bld_add_instruction(bb, ext_instr(shd_get_bb_arena(bb), (ExtInstr) { .mem = shd_bb_mem(bb), .set = set, diff --git a/src/shady/passes/lift_indirect_targets.c b/src/shady/passes/lift_indirect_targets.c index 10b2ed6e1..9fca55226 100644 --- a/src/shady/passes/lift_indirect_targets.c +++ b/src/shady/passes/lift_indirect_targets.c @@ -205,8 +205,8 @@ static const Node* process_node(Context* ctx, const Node* node) { const Type* jp_type = join_point_type(a, (JoinPointType) { .yield_types = shd_rewrite_nodes(&ctx->rewriter, node->payload.control.yield_types), }); - const Node* jp = gen_ext_instruction(bb, "shady.internal", ShadyOpCreateJoinPoint, - shd_as_qualified_type(jp_type, true), mk_nodes(a, tail_ptr, sp)); + const Node* jp = shd_bld_ext_instruction(bb, "shady.internal", ShadyOpCreateJoinPoint, + shd_as_qualified_type(jp_type, true), mk_nodes(a, tail_ptr, sp)); // dumbass hack jp = prim_op_helper(a, subgroup_assume_uniform_op, shd_empty(a), shd_singleton(jp)); diff --git a/src/shady/passes/lower_callf.c b/src/shady/passes/lower_callf.c index 2aebd6194..2abed36fe 100644 --- a/src/shady/passes/lower_callf.c +++ b/src/shady/passes/lower_callf.c @@ -45,8 +45,8 @@ static const Node* lower_callf_process(Context* ctx, const Node* old) { }); if (shd_lookup_annotation_list(old->payload.fun.annotations, "EntryPoint")) { - ctx2.return_jp = gen_ext_instruction(bb, "shady.internal", ShadyOpDefaultJoinPoint, - shd_as_qualified_type(jp_type, true), shd_empty(a)); + ctx2.return_jp = shd_bld_ext_instruction(bb, "shady.internal", ShadyOpDefaultJoinPoint, + shd_as_qualified_type(jp_type, true), shd_empty(a)); } else { const Node* jp_variable = param(a, shd_as_qualified_type(jp_type, false), "return_jp"); nparams = shd_nodes_append(a, nparams, jp_variable); diff --git a/src/shady/passes/lower_subgroup_ops.c b/src/shady/passes/lower_subgroup_ops.c index 0eef7e9c2..190cc5810 100644 --- a/src/shady/passes/lower_subgroup_ops.c +++ b/src/shady/passes/lower_subgroup_ops.c @@ -109,7 +109,7 @@ static const Node* build_subgroup_first(Context* ctx, BodyBuilder* bb, const Nod Module* m = ctx->rewriter.dst_module; const Node* t = shd_get_unqualified_type(src->type); if (is_supported_natively(ctx, t)) - return gen_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, shd_as_qualified_type(t, true), mk_nodes(a, scope, src)); + return shd_bld_ext_instruction(bb, "spirv.core", SpvOpGroupNonUniformBroadcastFirst, shd_as_qualified_type(t, true), mk_nodes(a, scope, src)); if (shd_resolve_to_int_literal(scope)->value != SpvScopeSubgroup) shd_error("TODO") diff --git a/src/shady/passes/scope_heuristic.c b/src/shady/passes/scope_heuristic.c index e138aa854..e833e1abf 100644 --- a/src/shady/passes/scope_heuristic.c +++ b/src/shady/passes/scope_heuristic.c @@ -173,7 +173,7 @@ static const Node* process(Context* ctx, const Node* node) { fn_ctx.depth_per_rpo = compute_scope_depth(a, fn_ctx.cfg); Node* new_fn = shd_recreate_node_head(r, node); BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_fn)); - gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), shd_empty(a)); + shd_bld_ext_instruction(bb, "shady.scope", 0, unit_type(a), shd_empty(a)); shd_register_processed(r, shd_get_abstraction_mem(node), shd_bb_mem(bb)); shd_set_abstraction_body(new_fn, shd_bld_finish(bb, shd_rewrite_node(&fn_ctx.rewriter, get_abstraction_body(node)))); shd_destroy_cfg(fn_ctx.cfg); @@ -187,7 +187,7 @@ static const Node* process(Context* ctx, const Node* node) { shd_register_processed(r, node, new_bb); BodyBuilder* bb = shd_bld_begin(a, shd_get_abstraction_mem(new_bb)); CFNode* n = shd_cfg_lookup(ctx->cfg, node); - gen_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); + shd_bld_ext_instruction(bb, "shady.scope", 0, unit_type(a), ctx->depth_per_rpo[n->rpo_index]); shd_register_processed(r, shd_get_abstraction_mem(node), shd_bb_mem(bb)); shd_set_abstraction_body(new_bb, shd_bld_finish(bb, shd_rewrite_node(r, get_abstraction_body(node)))); return new_bb; From 1242fe1dc38986137fa4076b5f4e31a442884832 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 17:12:01 +0200 Subject: [PATCH 681/693] rename string and string_sized --- include/shady/ir/base.h | 4 ++-- src/backend/c/emit_c.c | 2 +- src/backend/c/emit_c_control_flow.c | 2 +- src/frontend/slim/bind.c | 2 +- src/frontend/slim/infer.c | 4 ++-- src/frontend/slim/parser.c | 10 +++++----- src/frontend/spirv/s2s.c | 2 +- src/shady/analysis/literal.c | 2 +- src/shady/generator_constructors.c | 2 +- src/shady/generator_rewrite.c | 2 +- src/shady/ir.c | 6 +++--- src/shady/ir/debug.c | 2 +- src/shady/ir/decl.c | 4 ++-- src/shady/ir/function.c | 2 +- src/shady/ir/module.c | 2 +- src/shady/ir/type.c | 2 +- src/shady/print.c | 4 ++-- 17 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/shady/ir/base.h b/include/shady/ir/base.h index d6fdfe4e5..aeaf97364 100644 --- a/include/shady/ir/base.h +++ b/include/shady/ir/base.h @@ -44,8 +44,8 @@ Nodes shd_concat_nodes(IrArena* arena, Nodes a, Nodes b); Nodes shd_change_node_at_index(IrArena* arena, Nodes old, size_t i, const Node* n); bool shd_find_in_nodes(Nodes nodes, const Node* n); -String string_sized(IrArena*, size_t size, const char* start); -String string(IrArena*, const char*); +String shd_string_sized(IrArena*, size_t size, const char* start); +String shd_string(IrArena*, const char*); // see also: format_string in util.h String shd_fmt_string_irarena(IrArena* arena, const char* str, ...); diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index dd1611071..146d41fb4 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -91,7 +91,7 @@ String shd_c_legalize_identifier(Emitter* e, String src) { } dst[i] = '\0'; // TODO: collision handling using a dict - return string(e->arena, dst); + return shd_string(e->arena, dst); } static bool has_forward_declarations(CDialect dialect) { diff --git a/src/backend/c/emit_c_control_flow.c b/src/backend/c/emit_c_control_flow.c index 178e86511..1aa947473 100644 --- a/src/backend/c/emit_c_control_flow.c +++ b/src/backend/c/emit_c_control_flow.c @@ -30,7 +30,7 @@ String shd_c_emit_body(Emitter* emitter, FnEmitter* fn, const Node* abs) { fn->instruction_printers[cf_node->rpo_index] = NULL; String s2 = shd_printer_growy_unwrap(p); - String s = string(emitter->arena, s2); + String s = shd_string(emitter->arena, s2); free((void*)s2); return s; } diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index 224250c6b..a839205a2 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -75,7 +75,7 @@ static void add_binding(Context* ctx, bool is_var, String name, const Node* node assert(name); NamedBindEntry* entry = shd_arena_alloc(ctx->rewriter.dst_arena->arena, sizeof(NamedBindEntry)); *entry = (NamedBindEntry) { - .name = string(ctx->rewriter.dst_arena, name), + .name = shd_string(ctx->rewriter.dst_arena, name), .is_var = is_var, .node = (Node*) node, .next = NULL diff --git a/src/frontend/slim/infer.c b/src/frontend/slim/infer.c index ea6b9b582..5f22073a7 100644 --- a/src/frontend/slim/infer.c +++ b/src/frontend/slim/infer.c @@ -101,7 +101,7 @@ static const Node* infer_decl(Context* ctx, const Node* node) { } Nodes nret_types = annotate_all_types(a, infer_nodes(ctx, node->payload.fun.return_types), false); - Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, node->payload.fun.params.count, nparams), string(a, node->payload.fun.name), infer_nodes(ctx, node->payload.fun.annotations), nret_types); + Node* fun = function(ctx->rewriter.dst_module, shd_nodes(a, node->payload.fun.params.count, nparams), shd_string(a, node->payload.fun.name), infer_nodes(ctx, node->payload.fun.annotations), nret_types); shd_register_processed(&ctx->rewriter, node, fun); body_context.current_fn = fun; shd_set_abstraction_body(fun, infer(&body_context, node->payload.fun.body, NULL)); @@ -228,7 +228,7 @@ static const Node* infer_value(Context* ctx, const Node* node, const Type* expec } case True_TAG: return true_lit(a); case False_TAG: return false_lit(a); - case StringLiteral_TAG: return string_lit(a, (StringLiteral) { .string = string(a, node->payload.string_lit.string )}); + case StringLiteral_TAG: return string_lit(a, (StringLiteral) { .string = shd_string(a, node->payload.string_lit.string )}); case RefDecl_TAG: break; case FnAddr_TAG: break; case Value_Undef_TAG: break; diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 14b751aa8..dfd2c721c 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -151,7 +151,7 @@ static const char* accept_identifier(ctxparams) { if (tok.tag == identifier_tok) { shd_next_token(tokenizer); size_t size = tok.end - tok.start; - return string_sized(arena, (int) size, &contents[tok.start]); + return shd_string_sized(arena, (int) size, &contents[tok.start]); } return NULL; } @@ -198,7 +198,7 @@ static const Node* accept_numerical_literal(ctxparams) { Token tok = shd_curr_token(tokenizer); size_t size = tok.end - tok.start; - String str = string_sized(arena, (int) size, &contents[tok.start]); + String str = shd_string_sized(arena, (int) size, &contents[tok.start]); switch (tok.tag) { case hex_lit_tok: @@ -267,7 +267,7 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { switch (tok.tag) { case identifier_tok: { - const char* id = string_sized(arena, (int) size, &contents[tok.start]); + const char* id = shd_string_sized(arena, (int) size, &contents[tok.start]); shd_next_token(tokenizer); Op op = PRIMOPS_COUNT; @@ -330,14 +330,14 @@ static const Node* accept_value(ctxparams, BodyBuilder* bb) { case dec_lit_tok: { shd_next_token(tokenizer); return untyped_number(arena, (UntypedNumber) { - .plaintext = string_sized(arena, (int) size, &contents[tok.start]) + .plaintext = shd_string_sized(arena, (int) size, &contents[tok.start]) }); } case string_lit_tok: { shd_next_token(tokenizer); char* unescaped = calloc(size + 1, 1); size_t j = shd_apply_escape_codes(&contents[tok.start], size, unescaped); - const Node* lit = string_lit(arena, (StringLiteral) {.string = string_sized(arena, (int) j, unescaped) }); + const Node* lit = string_lit(arena, (StringLiteral) {.string = shd_string_sized(arena, (int) j, unescaped) }); free(unescaped); return lit; } diff --git a/src/frontend/spirv/s2s.c b/src/frontend/spirv/s2s.c index d3c8007fc..f0618169e 100644 --- a/src/frontend/spirv/s2s.c +++ b/src/frontend/spirv/s2s.c @@ -194,7 +194,7 @@ static bool parse_spv_header(SpvParser* parser) { static String decode_spv_string_literal(SpvParser* parser, uint32_t* at) { // TODO: assumes little endian - return string(shd_module_get_arena(parser->mod), (const char*) at); + return shd_string(shd_module_get_arena(parser->mod), (const char*) at); } static AddressSpace convert_storage_class(SpvStorageClass class) { diff --git a/src/shady/analysis/literal.c b/src/shady/analysis/literal.c index 2be2a6e85..632e662e9 100644 --- a/src/shady/analysis/literal.c +++ b/src/shady/analysis/literal.c @@ -175,7 +175,7 @@ const char* shd_get_string_literal(IrArena* arena, const Node* node) { chars[i] = (unsigned char) shd_get_int_literal_value(*shd_resolve_to_int_literal(value), false); } assert(chars[contents.count - 1] == 0); - return string(arena, chars); + return shd_string(arena, chars); } default: break; } diff --git a/src/shady/generator_constructors.c b/src/shady/generator_constructors.c index a0e27c447..467ed3bd0 100644 --- a/src/shady/generator_constructors.c +++ b/src/shady/generator_constructors.c @@ -27,7 +27,7 @@ static void generate_pre_construction_validation(Growy* g, json_object* src) { bool list = json_object_get_boolean(json_object_object_get(op, "list")); if (strcmp(class, "string") == 0) { if (!list) - shd_growy_append_formatted(g, "\t\tnode->payload.%s.%s = string(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); + shd_growy_append_formatted(g, "\t\tnode->payload.%s.%s = shd_string(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); else shd_growy_append_formatted(g, "\t\tnode->payload.%s.%s = _shd_import_strings(arena, node->payload.%s.%s);\n", snake_name, op_name, snake_name, op_name); } else { diff --git a/src/shady/generator_rewrite.c b/src/shady/generator_rewrite.c index 73b42cda3..1a3172c34 100644 --- a/src/shady/generator_rewrite.c +++ b/src/shady/generator_rewrite.c @@ -57,7 +57,7 @@ static void generate_rewriter_default_fns(Growy* g, json_object* nodes) { if (list) shd_growy_append_formatted(g, "\t\t\tpayload.%s = shd_strings(rewriter->dst_arena, old_payload.%s.count, old_payload.%s.strings);\n", op_name, op_name, op_name); else - shd_growy_append_formatted(g, "\t\t\tpayload.%s = string(rewriter->dst_arena, old_payload.%s);\n", op_name, op_name); + shd_growy_append_formatted(g, "\t\t\tpayload.%s = shd_string(rewriter->dst_arena, old_payload.%s);\n", op_name, op_name); continue; } diff --git a/src/shady/ir.c b/src/shady/ir.c index 931b08afe..b32f5abe9 100644 --- a/src/shady/ir.c +++ b/src/shady/ir.c @@ -181,7 +181,7 @@ static const char* string_impl(IrArena* arena, size_t size, const char* zero_ter return new_str; } -const char* string_sized(IrArena* arena, size_t size, const char* str) { +const char* shd_string_sized(IrArena* arena, size_t size, const char* str) { LARRAY(char, new_str, size + 1); strncpy(new_str, str, size); @@ -190,7 +190,7 @@ const char* string_sized(IrArena* arena, size_t size, const char* str) { return string_impl(arena, size, str); } -const char* string(IrArena* arena, const char* str) { +const char* shd_string(IrArena* arena, const char* str) { if (!str) return NULL; return string_impl(arena, strlen(str), str); @@ -201,7 +201,7 @@ Strings _shd_import_strings(IrArena* dst_arena, Strings old_strings) { size_t count = old_strings.count; LARRAY(String, arr, count); for (size_t i = 0; i < count; i++) - arr[i] = string(dst_arena, old_strings.strings[i]); + arr[i] = shd_string(dst_arena, old_strings.strings[i]); return shd_strings(dst_arena, count, arr); } diff --git a/src/shady/ir/debug.c b/src/shady/ir/debug.c index 42690cab9..92584c192 100644 --- a/src/shady/ir/debug.c +++ b/src/shady/ir/debug.c @@ -23,7 +23,7 @@ String shd_get_value_name_safe(const Node* v) { void shd_set_value_name(const Node* var, String name) { // TODO: annotations // if (var->tag == Variablez_TAG) - // var->payload.varz.name = string(var->arena, name); + // var->payload.varz.name = shd_string(var->arena, name); } void shd_bld_comment(BodyBuilder* bb, String str) { diff --git a/src/shady/ir/decl.c b/src/shady/ir/decl.c index f1b8d8ae3..50add0afc 100644 --- a/src/shady/ir/decl.c +++ b/src/shady/ir/decl.c @@ -11,7 +11,7 @@ Node* _shd_constant(Module* mod, Nodes annotations, const Type* hint, String nam IrArena* arena = mod->arena; Constant cnst = { .annotations = annotations, - .name = string(arena, name), + .name = shd_string(arena, name), .type_hint = hint, .value = NULL, }; @@ -40,7 +40,7 @@ Node* _shd_global_var(Module* mod, Nodes annotations, const Type* type, const ch IrArena* arena = mod->arena; GlobalVariable gvar = { .annotations = annotations, - .name = string(arena, name), + .name = shd_string(arena, name), .type = type, .address_space = as, .init = NULL, diff --git a/src/shady/ir/function.c b/src/shady/ir/function.c index bb37a4b85..b5dee81cb 100644 --- a/src/shady/ir/function.c +++ b/src/shady/ir/function.c @@ -7,7 +7,7 @@ Node* _shd_param(IrArena* arena, const Type* type, const char* name) { Param param = { .type = type, - .name = string(arena, name), + .name = shd_string(arena, name), }; Node node; diff --git a/src/shady/ir/module.c b/src/shady/ir/module.c index f31e48fc5..1ec2586db 100644 --- a/src/shady/ir/module.c +++ b/src/shady/ir/module.c @@ -9,7 +9,7 @@ Module* shd_new_module(IrArena* arena, String name) { Module* m = shd_arena_alloc(arena->arena, sizeof(Module)); *m = (Module) { .arena = arena, - .name = string(arena, name), + .name = shd_string(arena, name), .decls = shd_new_list(Node*), }; shd_list_append(Module*, arena->modules, m); diff --git a/src/shady/ir/type.c b/src/shady/ir/type.c index 2ed45ff35..1d5d4c3cd 100644 --- a/src/shady/ir/type.c +++ b/src/shady/ir/type.c @@ -513,7 +513,7 @@ const Node* shd_get_fill_type_size(const Type* composite_t) { Type* _shd_nominal_type(Module* mod, Nodes annotations, String name) { IrArena* arena = shd_module_get_arena(mod); NominalType payload = { - .name = string(arena, name), + .name = shd_string(arena, name), .module = mod, .annotations = annotations, .body = NULL, diff --git a/src/shady/print.c b/src/shady/print.c index fdec1190a..c1eb77089 100644 --- a/src/shady/print.c +++ b/src/shady/print.c @@ -291,7 +291,7 @@ static String emit_abs_body(PrinterCtx* ctx, const Node* abs) { } String s = shd_printer_growy_unwrap(p); - String s2 = string(ctx->fn->arena, s); + String s2 = shd_string(ctx->fn->arena, s); if (cfnode) ctx->bb_printers[cfnode->rpo_index] = NULL; free((void*) s); @@ -1047,7 +1047,7 @@ static String emit_node(PrinterCtx* ctx, const Node* node) { shd_print(p, "%%%d = %s\n", node->id, s); if (print_inline) { - String is = string(node->arena, s); + String is = shd_string(node->arena, s); shd_dict_insert(const Node*, String, ctx->emitted, node, is); free((void*) s); return is; From 9859232fb799d11e123cbad43808a512d616d661 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 17:21:24 +0200 Subject: [PATCH 682/693] runtime: prefix the world too --- include/shady/runtime.h | 38 +++++++++--------- samples/aobench/ao_main.c | 26 ++++++------- samples/checkerboard/checkerboard.c | 24 ++++++------ src/runtime/cuda/cuda_runtime.c | 10 ++--- src/runtime/cuda/cuda_runtime_buffer.c | 6 +-- src/runtime/cuda/cuda_runtime_private.h | 10 ++--- src/runtime/cuda/cuda_runtime_program.c | 4 +- src/runtime/runtime.c | 49 +++++++++++------------- src/runtime/runtime_cli.c | 4 +- src/runtime/runtime_private.h | 6 +-- src/runtime/runtime_program.c | 12 +++--- src/runtime/runtime_test.c | 26 ++++++------- src/runtime/vulkan/vk_runtime.c | 4 +- src/runtime/vulkan/vk_runtime_buffer.c | 48 +++++++++++------------ src/runtime/vulkan/vk_runtime_device.c | 12 +++--- src/runtime/vulkan/vk_runtime_dispatch.c | 24 ++++++------ src/runtime/vulkan/vk_runtime_private.h | 26 ++++++------- src/runtime/vulkan/vk_runtime_program.c | 26 ++++++------- zhady/shady.i | 7 ++++ 19 files changed, 182 insertions(+), 180 deletions(-) diff --git a/include/shady/runtime.h b/include/shady/runtime.h index 509ed7fdc..68aa75a80 100644 --- a/include/shady/runtime.h +++ b/include/shady/runtime.h @@ -11,8 +11,8 @@ typedef struct { bool allow_no_devices; } RuntimeConfig; -RuntimeConfig default_runtime_config(); -void cli_parse_runtime_config(RuntimeConfig* config, int* pargc, char** argv); +RuntimeConfig shd_rt_default_config(); +void shd_rt_cli_parse_runtime_config(RuntimeConfig* config, int* pargc, char** argv); typedef struct Runtime_ Runtime; typedef struct Device_ Device; @@ -20,35 +20,35 @@ typedef struct Program_ Program; typedef struct Command_ Command; typedef struct Buffer_ Buffer; -Runtime* initialize_runtime(RuntimeConfig config); -void shutdown_runtime(Runtime*); +Runtime* shd_rt_initialize(RuntimeConfig config); +void shd_rt_shutdown(Runtime* runtime); -size_t device_count(Runtime*); -Device* get_device(Runtime*, size_t i); -Device* get_an_device(Runtime*); -const char* get_device_name(Device*); +size_t shd_rt_device_count(Runtime* r); +Device* shd_rt_get_device(Runtime* r, size_t i); +Device* shd_rt_get_an_device(Runtime* r); +const char* shd_rt_get_device_name(Device* d); typedef struct CompilerConfig_ CompilerConfig; typedef struct Module_ Module; -Program* new_program_from_module(Runtime*, const CompilerConfig*, Module*); +Program* shd_rt_new_program_from_module(Runtime* runtime, const CompilerConfig* base_config, Module* mod); typedef struct { uint64_t* profiled_gpu_time; } ExtraKernelOptions; -Command* launch_kernel(Program*, Device*, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions*); -bool wait_completion(Command*); +Command* shd_rt_launch_kernel(Program* p, Device* d, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* extra_options); +bool shd_rt_wait_completion(Command* cmd); -Buffer* allocate_buffer_device(Device*, size_t); -bool can_import_host_memory(Device*); -Buffer* import_buffer_host(Device*, void*, size_t); -void destroy_buffer(Buffer*); +Buffer* shd_rt_allocate_buffer_device(Device* device, size_t bytes); +bool shd_rt_can_import_host_memory(Device* device); +Buffer* shd_rt_import_buffer_host(Device* device, void* ptr, size_t bytes); +void shd_rt_destroy_buffer(Buffer* buf); -void* get_buffer_host_pointer(Buffer* buf); -uint64_t get_buffer_device_pointer(Buffer* buf); +void* shd_rt_get_buffer_host_pointer(Buffer* buf); +uint64_t shd_rt_get_buffer_device_pointer(Buffer* buf); -bool copy_to_buffer(Buffer* dst, size_t buffer_offset, void* src, size_t size); -bool copy_from_buffer(Buffer* src, size_t buffer_offset, void* dst, size_t size); +bool shd_rt_copy_to_buffer(Buffer* dst, size_t buffer_offset, void* src, size_t size); +bool shd_rt_copy_from_buffer(Buffer* src, size_t buffer_offset, void* dst, size_t size); #endif diff --git a/samples/aobench/ao_main.c b/samples/aobench/ao_main.c index b5ba969a7..aa57a9a5f 100644 --- a/samples/aobench/ao_main.c +++ b/samples/aobench/ao_main.c @@ -98,8 +98,8 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri shd_info_print("Shady checkerboard test starting...\n"); - Runtime* runtime = initialize_runtime(args->runtime_config); - Device* device = get_device(runtime, args->common_app_args.device); + Runtime* runtime = shd_rt_initialize(args->runtime_config); + Device* device = shd_rt_get_device(runtime, args->common_app_args.device); assert(device); img[0] = 69; @@ -107,49 +107,49 @@ void render_device(Args* args, TEXEL_T *img, int w, int h, int nsubsamples, Stri Buffer* buf; if (import_memory) - buf = import_buffer_host(device, img, sizeof(*img) * WIDTH * HEIGHT * 3); + buf = shd_rt_import_buffer_host(device, img, sizeof(*img) * WIDTH * HEIGHT * 3); else - buf = allocate_buffer_device(device, sizeof(*img) * WIDTH * HEIGHT * 3); + buf = shd_rt_allocate_buffer_device(device, sizeof(*img) * WIDTH * HEIGHT * 3); - uint64_t buf_addr = get_buffer_device_pointer(buf); + uint64_t buf_addr = shd_rt_get_buffer_device_pointer(buf); shd_info_print("Device-side address is: %zu\n", buf_addr); Module* m; CHECK(shd_driver_load_source_file_from_filename(&args->compiler_config, path, "aobench", &m) == NoError, return); - Program* program = new_program_from_module(runtime, &args->compiler_config, m); + Program* program = shd_rt_new_program_from_module(runtime, &args->compiler_config, m); // run it twice to compile everything and benefit from caches - wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, NULL)); + shd_rt_wait_completion(shd_rt_launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void* []) { &buf_addr }, NULL)); uint64_t tsn = shd_get_time_nano(); uint64_t profiled_gpu_time = 0; ExtraKernelOptions extra_kernel_options = { .profiled_gpu_time = &profiled_gpu_time }; - wait_completion(launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void*[]) { &buf_addr }, &extra_kernel_options)); + shd_rt_wait_completion(shd_rt_launch_kernel(program, device, "aobench_kernel", WIDTH / BLOCK_SIZE, HEIGHT / BLOCK_SIZE, 1, 1, (void* []) { &buf_addr }, &extra_kernel_options)); uint64_t tpn = shd_get_time_nano(); shd_info_print("device rendering took %dus (gpu time: %dus)\n", (tpn - tsn) / 1000, profiled_gpu_time / 1000); if (!import_memory) - copy_from_buffer(buf, 0, img, sizeof(*img) * WIDTH * HEIGHT * 3); + shd_rt_copy_from_buffer(buf, 0, img, sizeof(*img) * WIDTH * HEIGHT * 3); shd_debug_print("data %d\n", (int) img[0]); - destroy_buffer(buf); + shd_rt_destroy_buffer(buf); - shutdown_runtime(runtime); + shd_rt_shutdown(runtime); } int main(int argc, char **argv) { shd_log_set_level(INFO); Args args = { .compiler_config = shd_default_compiler_config(), - .runtime_config = default_runtime_config(), + .runtime_config = shd_rt_default_config(), }; args.compiler_config.input_cf.restructure_with_heuristics = true; shd_parse_common_args(&argc, argv); shd_parse_compiler_config_args(&args.compiler_config, &argc, argv); - cli_parse_runtime_config(&args.runtime_config, &argc, argv); + shd_rt_cli_parse_runtime_config(&args.runtime_config, &argc, argv); cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); bool do_host = false, do_ispc = false, do_device = false, do_all = true; diff --git a/samples/checkerboard/checkerboard.c b/samples/checkerboard/checkerboard.c index 214eb6e01..42a9905e8 100644 --- a/samples/checkerboard/checkerboard.c +++ b/samples/checkerboard/checkerboard.c @@ -44,25 +44,25 @@ int main(int argc, char **argv) shd_log_set_level(INFO); CompilerConfig compiler_config = shd_default_compiler_config(); - RuntimeConfig runtime_config = default_runtime_config(); + RuntimeConfig runtime_config = shd_rt_default_config(); shd_parse_common_args(&argc, argv); shd_parse_compiler_config_args(&compiler_config, &argc, argv); - cli_parse_runtime_config(&runtime_config, &argc, argv); + shd_rt_cli_parse_runtime_config(&runtime_config, &argc, argv); shd_info_print("Shady checkerboard test starting...\n"); - Runtime* runtime = initialize_runtime(runtime_config); - Device* device = get_device(runtime, 0); + Runtime* runtime = shd_rt_initialize(runtime_config); + Device* device = shd_rt_get_device(runtime, 0); assert(device); img[0] = 69; shd_info_print("malloc'd address is: %zu\n", (size_t) img); int buf_size = sizeof(uint8_t) * WIDTH * HEIGHT * 3; - Buffer* buf = allocate_buffer_device(device, buf_size); - copy_to_buffer(buf, 0, img, buf_size); - uint64_t buf_addr = get_buffer_device_pointer(buf); + Buffer* buf = shd_rt_allocate_buffer_device(device, buf_size); + shd_rt_copy_to_buffer(buf, 0, img, buf_size); + uint64_t buf_addr = shd_rt_get_buffer_device_pointer(buf); shd_info_print("Device-side address is: %zu\n", buf_addr); @@ -72,16 +72,16 @@ int main(int argc, char **argv) if (shd_driver_load_source_file(&compiler_config, SrcSlim, sizeof(checkerboard_kernel_src), checkerboard_kernel_src, "checkerboard", &m) != NoError) shd_error("Failed to load checkerboard module"); - Program* program = new_program_from_module(runtime, &compiler_config, m); + Program* program = shd_rt_new_program_from_module(runtime, &compiler_config, m); - wait_completion(launch_kernel(program, device, "checkerboard", 16, 16, 1, 1, (void*[]) { &buf_addr }, NULL)); + shd_rt_wait_completion(shd_rt_launch_kernel(program, device, "checkerboard", 16, 16, 1, 1, (void* []) { &buf_addr }, NULL)); - copy_from_buffer(buf, 0, img, buf_size); + shd_rt_copy_from_buffer(buf, 0, img, buf_size); shd_info_print("data %d\n", (int) img[0]); - destroy_buffer(buf); + shd_rt_destroy_buffer(buf); - shutdown_runtime(runtime); + shd_rt_shutdown(runtime); saveppm("checkerboard.ppm", WIDTH, HEIGHT, img); shd_destroy_ir_arena(a); free(img); diff --git a/src/runtime/cuda/cuda_runtime.c b/src/runtime/cuda/cuda_runtime.c index 225943a1a..6d079528d 100644 --- a/src/runtime/cuda/cuda_runtime.c +++ b/src/runtime/cuda/cuda_runtime.c @@ -34,7 +34,7 @@ bool cuda_command_wait(CudaCommand* command) { return true; } -CudaCommand* shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* options) { +static CudaCommand* shd_cuda_launch_kernel(CudaDevice* device, Program* p, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* options) { CudaKernel* kernel = shd_cuda_get_specialized_program(device, p, entry_point); CudaCommand* cmd = calloc(sizeof(CudaCommand), 1); @@ -76,9 +76,9 @@ static CudaDevice* create_cuda_device(CudaBackend* b, int ordinal) { .base = { .get_name = (const char*(*)(Device*)) cuda_device_get_name, .cleanup = (void(*)(Device*)) cuda_device_cleanup, - .allocate_buffer = (Buffer* (*)(Device*, size_t)) shd_cuda_allocate_buffer, - .can_import_host_memory = (bool (*)(Device*)) shd_cuda_can_import_host_memory, - .import_host_memory_as_buffer = (Buffer* (*)(Device*, void*, size_t)) shd_cuda_import_host_memory, + .allocate_buffer = (Buffer* (*)(Device*, size_t)) shd_rt_cuda_allocate_buffer, + .can_import_host_memory = (bool (*)(Device*)) shd_rt_cuda_can_import_host_memory, + .import_host_memory_as_buffer = (Buffer* (*)(Device*, void*, size_t)) shd_rt_cuda_import_host_memory, .launch_kernel = (Command*(*)(Device*, Program*, String, int, int, int, int, void**, ExtraKernelOptions*)) shd_cuda_launch_kernel, }, .handle = handle, @@ -108,7 +108,7 @@ static bool probe_cuda_devices(CudaBackend* b) { return true; } -Backend* initialize_cuda_backend(Runtime* base) { +Backend* shd_rt_initialize_cuda_backend(Runtime* base) { CudaBackend* backend = malloc(sizeof(CudaBackend)); memset(backend, 0, sizeof(CudaBackend)); backend->base = (Backend) { diff --git a/src/runtime/cuda/cuda_runtime_buffer.c b/src/runtime/cuda/cuda_runtime_buffer.c index dd9991bac..c1af084ca 100644 --- a/src/runtime/cuda/cuda_runtime_buffer.c +++ b/src/runtime/cuda/cuda_runtime_buffer.c @@ -45,7 +45,7 @@ static CudaBuffer* new_buffer_common(size_t size) { return buffer; } -CudaBuffer* shd_cuda_allocate_buffer(CudaDevice* device, size_t size) { +CudaBuffer* shd_rt_cuda_allocate_buffer(CudaDevice* device, size_t size) { CUdeviceptr device_ptr; CHECK_CUDA(cuMemAlloc(&device_ptr, size), return NULL); CudaBuffer* buffer = new_buffer_common(size); @@ -56,7 +56,7 @@ CudaBuffer* shd_cuda_allocate_buffer(CudaDevice* device, size_t size) { return buffer; } -CudaBuffer* shd_cuda_import_host_memory(CudaDevice* device, void* host_ptr, size_t size) { +CudaBuffer* shd_rt_cuda_import_host_memory(CudaDevice* device, void* host_ptr, size_t size) { CUdeviceptr device_ptr; CHECK_CUDA(cuMemHostRegister(host_ptr, size, CU_MEMHOSTREGISTER_DEVICEMAP), return NULL); CHECK_CUDA(cuMemHostGetDevicePointer(&device_ptr, host_ptr, 0), return NULL); @@ -68,6 +68,6 @@ CudaBuffer* shd_cuda_import_host_memory(CudaDevice* device, void* host_ptr, size return buffer; } -bool shd_cuda_can_import_host_memory(CudaDevice* d) { +bool shd_rt_cuda_can_import_host_memory(CudaDevice* d) { return true; } diff --git a/src/runtime/cuda/cuda_runtime_private.h b/src/runtime/cuda/cuda_runtime_private.h index db8fc4687..6e17f677d 100644 --- a/src/runtime/cuda/cuda_runtime_private.h +++ b/src/runtime/cuda/cuda_runtime_private.h @@ -62,11 +62,11 @@ typedef struct { CUfunction entry_point_function; } CudaKernel; -CudaBuffer* shd_cuda_allocate_buffer(CudaDevice*, size_t size); -CudaBuffer* shd_cuda_import_host_memory(CudaDevice*, void* host_ptr, size_t size); -bool shd_cuda_can_import_host_memory(CudaDevice*); +CudaBuffer* shd_rt_cuda_allocate_buffer(CudaDevice*, size_t size); +CudaBuffer* shd_rt_cuda_import_host_memory(CudaDevice*, void* host_ptr, size_t size); +bool shd_rt_cuda_can_import_host_memory(CudaDevice*); -CudaKernel* shd_cuda_get_specialized_program(CudaDevice*, Program*, String ep); -bool shd_cuda_destroy_specialized_kernel(CudaKernel*); +CudaKernel* shd_rt_cuda_get_specialized_program(CudaDevice*, Program*, String ep); +bool shd_rt_cuda_destroy_specialized_kernel(CudaKernel*); #endif diff --git a/src/runtime/cuda/cuda_runtime_program.c b/src/runtime/cuda/cuda_runtime_program.c index 2cf520191..4c3a460e4 100644 --- a/src/runtime/cuda/cuda_runtime_program.c +++ b/src/runtime/cuda/cuda_runtime_program.c @@ -146,7 +146,7 @@ static CudaKernel* create_specialized_program(CudaDevice* device, SpecProgramKey return kernel; } -CudaKernel* shd_cuda_get_specialized_program(CudaDevice* device, Program* program, String entry_point) { +CudaKernel* shd_rt_cuda_get_specialized_program(CudaDevice* device, Program* program, String entry_point) { SpecProgramKey key = { .base = program, .entry_point = entry_point }; CudaKernel** found = find_value_dict(SpecProgramKey, CudaKernel*, device->specialized_programs, key); if (found) @@ -157,7 +157,7 @@ CudaKernel* shd_cuda_get_specialized_program(CudaDevice* device, Program* progra return spec; } -bool shd_cuda_destroy_specialized_kernel(CudaKernel* kernel) { +bool shd_rt_cuda_destroy_specialized_kernel(CudaKernel* kernel) { free(kernel->cuda_code); free(kernel->ptx); CHECK_CUDA(cuModuleUnload(kernel->cuda_module), return false); diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 6a1185bed..a3e8d08db 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -6,7 +6,7 @@ #include #include -Runtime* initialize_runtime(RuntimeConfig config) { +Runtime* shd_rt_initialize(RuntimeConfig config) { Runtime* runtime = malloc(sizeof(Runtime)); memset(runtime, 0, sizeof(Runtime)); runtime->config = config; @@ -15,12 +15,12 @@ Runtime* initialize_runtime(RuntimeConfig config) { runtime->programs = shd_new_list(Program*); #if VK_BACKEND_PRESENT - Backend* vk_backend = initialize_vk_backend(runtime); + Backend* vk_backend = shd_rt_initialize_vk_backend(runtime); CHECK(vk_backend, goto init_fail_free); shd_list_append(Backend*, runtime->backends, vk_backend); #endif #if CUDA_BACKEND_PRESENT - Backend* cuda_backend = initialize_cuda_backend(runtime); + Backend* cuda_backend = shd_rt_initialize_cuda_backend(runtime); CHECK(cuda_backend, goto init_fail_free); append_list(Backend*, runtime->backends, cuda_backend); #endif @@ -34,7 +34,7 @@ Runtime* initialize_runtime(RuntimeConfig config) { return NULL; } -void shutdown_runtime(Runtime* runtime) { +void shd_rt_shutdown(Runtime* runtime) { if (!runtime) return; // TODO force wait outstanding dispatches ? @@ -45,7 +45,7 @@ void shutdown_runtime(Runtime* runtime) { shd_destroy_list(runtime->devices); for (size_t i = 0; i < shd_list_count(runtime->programs); i++) { - unload_program(shd_read_list(Program*, runtime->programs)[i]); + shd_rt_unload_program(shd_read_list(Program*, runtime->programs)[i]); } shd_destroy_list(runtime->programs); @@ -56,44 +56,39 @@ void shutdown_runtime(Runtime* runtime) { free(runtime); } -size_t device_count(Runtime* r) { +size_t shd_rt_device_count(Runtime* r) { return shd_list_count(r->devices); } -Device* get_device(Runtime* r, size_t i) { - assert(i < device_count(r)); +Device* shd_rt_get_device(Runtime* r, size_t i) { + assert(i < shd_rt_device_count(r)); return shd_read_list(Device*, r->devices)[i]; } -Device* get_an_device(Runtime* r) { - assert(device_count(r) > 0); - return get_device(r, 0); +Device* shd_rt_get_an_device(Runtime* r) { + assert(shd_rt_device_count(r) > 0); + return shd_rt_get_device(r, 0); } // Virtual functions ... -const char* get_device_name(Device* d) { return d->get_name(d); } +const char* shd_rt_get_device_name(Device* d) { return d->get_name(d); } -Command* launch_kernel(Program* p, Device* d, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* extra_options) { +Command* shd_rt_launch_kernel(Program* p, Device* d, const char* entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* extra_options) { return d->launch_kernel(d, p, entry_point, dimx, dimy, dimz, args_count, args, extra_options); } -bool wait_completion(Command* cmd) { return cmd->wait_for_completion(cmd); } +bool shd_rt_wait_completion(Command* cmd) { return cmd->wait_for_completion(cmd); } -bool can_import_host_memory(Device* device) { return device->can_import_host_memory(device); } +bool shd_rt_can_import_host_memory(Device* device) { return device->can_import_host_memory(device); } -Buffer* allocate_buffer_device(Device* device, size_t bytes) { return device->allocate_buffer(device, bytes); } -Buffer* import_buffer_host(Device* device, void* ptr, size_t bytes) { return device->import_host_memory_as_buffer(device, ptr, bytes); } +Buffer* shd_rt_allocate_buffer_device(Device* device, size_t bytes) { return device->allocate_buffer(device, bytes); } +Buffer* shd_rt_import_buffer_host(Device* device, void* ptr, size_t bytes) { return device->import_host_memory_as_buffer(device, ptr, bytes); } -void destroy_buffer(Buffer* buf) { buf->destroy(buf); } +void shd_rt_destroy_buffer(Buffer* buf) { buf->destroy(buf); } -void* get_buffer_host_pointer(Buffer* buf) { return buf->get_host_ptr(buf); } -uint64_t get_buffer_device_pointer(Buffer* buf) { return buf->get_device_ptr(buf); } +void* shd_rt_get_buffer_host_pointer(Buffer* buf) { return buf->get_host_ptr(buf); } +uint64_t shd_rt_get_buffer_device_pointer(Buffer* buf) { return buf->get_device_ptr(buf); } -bool copy_to_buffer(Buffer* dst, size_t buffer_offset, void* src, size_t size) { - return dst->copy_into(dst, buffer_offset, src, size); -} - -bool copy_from_buffer(Buffer* src, size_t buffer_offset, void* dst, size_t size) { - return src->copy_from(src, buffer_offset, dst, size); -} +bool shd_rt_copy_to_buffer(Buffer* dst, size_t buffer_offset, void* src, size_t size) { return dst->copy_into(dst, buffer_offset, src, size); } +bool shd_rt_copy_from_buffer(Buffer* src, size_t buffer_offset, void* dst, size_t size) { return src->copy_from(src, buffer_offset, dst, size); } diff --git a/src/runtime/runtime_cli.c b/src/runtime/runtime_cli.c index 7762f7b23..8c9f53e09 100644 --- a/src/runtime/runtime_cli.c +++ b/src/runtime/runtime_cli.c @@ -3,7 +3,7 @@ #include "log.h" -RuntimeConfig default_runtime_config() { +RuntimeConfig shd_rt_default_config() { return (RuntimeConfig) { #ifndef NDEBUG .dump_spv = true, @@ -18,7 +18,7 @@ RuntimeConfig default_runtime_config() { F(config->use_validation, api-validation) \ F(config->dump_spv, dump-spv) \ -void cli_parse_runtime_config(RuntimeConfig* config, int* pargc, char** argv) { +void shd_rt_cli_parse_runtime_config(RuntimeConfig* config, int* pargc, char** argv) { int argc = *pargc; bool help = false; diff --git a/src/runtime/runtime_private.h b/src/runtime/runtime_private.h index 988bdfe7c..8b8a504a4 100644 --- a/src/runtime/runtime_private.h +++ b/src/runtime/runtime_private.h @@ -64,9 +64,9 @@ struct Buffer_ { bool (*copy_from)(Buffer* src, size_t buffer_offset, void* dst, size_t bytes); }; -void unload_program(Program*); +void shd_rt_unload_program(Program* program); -Backend* initialize_vk_backend(Runtime*); -Backend* initialize_cuda_backend(Runtime*); +Backend* shd_rt_initialize_vk_backend(Runtime*); +Backend* shd_rt_shd_rt_initialize_cuda_backend(Runtime*); #endif diff --git a/src/runtime/runtime_program.c b/src/runtime/runtime_program.c index 0641b826f..8f8792689 100644 --- a/src/runtime/runtime_program.c +++ b/src/runtime/runtime_program.c @@ -10,7 +10,7 @@ #include #include -Program* new_program_from_module(Runtime* runtime, const CompilerConfig* base_config, Module* mod) { +Program* shd_rt_new_program_from_module(Runtime* runtime, const CompilerConfig* base_config, Module* mod) { Program* program = calloc(1, sizeof(Program)); program->runtime = runtime; program->base_config = base_config; @@ -22,7 +22,7 @@ Program* new_program_from_module(Runtime* runtime, const CompilerConfig* base_co return program; } -Program* load_program(Runtime* runtime, const CompilerConfig* base_config, const char* program_src) { +Program* shd_rt_load_program(Runtime* runtime, const CompilerConfig* base_config, const char* program_src) { Module* module; int err = shd_driver_load_source_file(base_config, SrcShadyIR, strlen(program_src), program_src, "my_module", @@ -31,12 +31,12 @@ Program* load_program(Runtime* runtime, const CompilerConfig* base_config, const return NULL; } - Program* program = new_program_from_module(runtime, base_config, module); + Program* program = shd_rt_new_program_from_module(runtime, base_config, module); program->arena = shd_module_get_arena(module); return program; } -Program* load_program_from_disk(Runtime* runtime, const CompilerConfig* base_config, const char* path) { +Program* shd_rt_load_program_from_disk(Runtime* runtime, const CompilerConfig* base_config, const char* path) { Module* module; int err = shd_driver_load_source_file_from_filename(base_config, path, "my_module", &module); @@ -44,12 +44,12 @@ Program* load_program_from_disk(Runtime* runtime, const CompilerConfig* base_con return NULL; } - Program* program = new_program_from_module(runtime, base_config, module); + Program* program = shd_rt_new_program_from_module(runtime, base_config, module); program->arena = shd_module_get_arena(module); return program; } -void unload_program(Program* program) { +void shd_rt_unload_program(Program* program) { // TODO iterate over the specialized stuff if (program->arena) // if the program owns an arena shd_destroy_ir_arena(program->arena); diff --git a/src/runtime/runtime_test.c b/src/runtime/runtime_test.c index 29aad2219..a5ce05432 100644 --- a/src/runtime/runtime_test.c +++ b/src/runtime/runtime_test.c @@ -32,18 +32,18 @@ int main(int argc, char* argv[]) { shd_log_set_level(INFO); Args args = { .driver_config = shd_default_driver_config(), - .runtime_config = default_runtime_config(), + .runtime_config = shd_rt_default_config(), }; cli_parse_common_app_arguments(&args.common_app_args, &argc, argv); shd_parse_common_args(&argc, argv); - cli_parse_runtime_config(&args.runtime_config, &argc, argv); + shd_rt_cli_parse_runtime_config(&args.runtime_config, &argc, argv); shd_parse_compiler_config_args(&args.driver_config.config, &argc, argv); shd_driver_parse_input_files(args.driver_config.input_filenames, &argc, argv); shd_info_print("Shady runtime test starting...\n"); - Runtime* runtime = initialize_runtime(args.runtime_config); - Device* device = get_device(runtime, args.common_app_args.device); + Runtime* runtime = shd_rt_initialize(args.runtime_config); + Device* device = shd_rt_get_device(runtime, args.common_app_args.device); assert(device); Program* program; @@ -54,27 +54,27 @@ int main(int argc, char* argv[]) { Module* module; shd_driver_load_source_file(&args.driver_config.config, SrcSlim, strlen(default_shader), default_shader, "runtime_test", &module); - program = new_program_from_module(runtime, &args.driver_config.config, module); + program = shd_rt_new_program_from_module(runtime, &args.driver_config.config, module); } else { Module* module = shd_new_module(arena, "my_module"); int err = shd_driver_load_source_files(&args.driver_config, module); if (err) return err; - program = new_program_from_module(runtime, &args.driver_config.config, module); + program = shd_rt_new_program_from_module(runtime, &args.driver_config.config, module); } int32_t stuff[] = { 42, 42, 42, 42 }; - Buffer* buffer = allocate_buffer_device(device, sizeof(stuff)); - copy_to_buffer(buffer, 0, stuff, sizeof(stuff)); - copy_from_buffer(buffer, 0, stuff, sizeof(stuff)); + Buffer* buffer = shd_rt_allocate_buffer_device(device, sizeof(stuff)); + shd_rt_copy_to_buffer(buffer, 0, stuff, sizeof(stuff)); + shd_rt_copy_from_buffer(buffer, 0, stuff, sizeof(stuff)); int32_t a0 = 42; - uint64_t a1 = get_buffer_device_pointer(buffer); - wait_completion(launch_kernel(program, device, args.driver_config.config.specialization.entry_point ? args.driver_config.config.specialization.entry_point : "my_kernel", 1, 1, 1, 2, (void*[]) { &a0, &a1 }, NULL)); + uint64_t a1 = shd_rt_get_buffer_device_pointer(buffer); + shd_rt_wait_completion(shd_rt_launch_kernel(program, device, args.driver_config.config.specialization.entry_point ? args.driver_config.config.specialization.entry_point : "my_kernel", 1, 1, 1, 2, (void* []) { &a0, &a1 }, NULL)); - destroy_buffer(buffer); + shd_rt_destroy_buffer(buffer); - shutdown_runtime(runtime); + shd_rt_shutdown(runtime); if (arena) shd_destroy_ir_arena(arena); shd_destroy_driver_config(&args.driver_config); diff --git a/src/runtime/vulkan/vk_runtime.c b/src/runtime/vulkan/vk_runtime.c index ac694126f..dcb324dde 100644 --- a/src/runtime/vulkan/vk_runtime.c +++ b/src/runtime/vulkan/vk_runtime.c @@ -134,7 +134,7 @@ static void shutdown_vulkan_runtime(VkrBackend* backend) { free(backend); } -Backend* initialize_vk_backend(Runtime* base) { +Backend* shd_rt_initialize_vk_backend(Runtime* base) { VkrBackend* backend = malloc(sizeof(VkrBackend)); memset(backend, 0, sizeof(VkrBackend)); backend->base = (Backend) { @@ -143,7 +143,7 @@ Backend* initialize_vk_backend(Runtime* base) { }; CHECK(initialize_vk_instance(backend), goto init_fail_free) - probe_vkr_devices(backend); + shd_rt_vk_probe_devices(backend); shd_info_print("Shady Vulkan backend successfully initialized !\n"); return &backend->base; diff --git a/src/runtime/vulkan/vk_runtime_buffer.c b/src/runtime/vulkan/vk_runtime_buffer.c index 211dc88c5..ccbdea544 100644 --- a/src/runtime/vulkan/vk_runtime_buffer.c +++ b/src/runtime/vulkan/vk_runtime_buffer.c @@ -37,7 +37,7 @@ static uint32_t find_suitable_memory_type(VkrDevice* device, uint32_t memory_typ static Buffer make_base_buffer(VkrDevice*); -VkrBuffer* vkr_allocate_buffer_device_(VkrDevice* device, size_t size, AllocHeap heap) { +static VkrBuffer* vkr_allocate_buffer_device_(VkrDevice* device, size_t size, AllocHeap heap) { if (!device->caps.features.buffer_device_address.bufferDeviceAddress) { shd_error_print("device buffers require VK_KHR_buffer_device_address\n"); return NULL; @@ -102,7 +102,7 @@ VkrBuffer* vkr_allocate_buffer_device_(VkrDevice* device, size_t size, AllocHeap return NULL; } -VkrBuffer* vkr_allocate_buffer_device(VkrDevice* device, size_t size) { +VkrBuffer* shd_rt_vk_allocate_buffer_device(VkrDevice* device, size_t size) { return vkr_allocate_buffer_device_(device, size, AllocDeviceLocal); } @@ -120,11 +120,11 @@ static bool vkr_can_import_host_memory_(VkrDevice* device, bool log) { return true; } -bool vkr_can_import_host_memory(VkrDevice* device) { +bool shd_rt_vk_can_import_host_memory(VkrDevice* device) { return vkr_can_import_host_memory_(device, false); } -VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { +VkrBuffer* shd_rt_vk_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { if (!vkr_can_import_host_memory_(device, true)) { shd_error_die(); } @@ -218,7 +218,7 @@ VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size) { return NULL; } -void vkr_destroy_buffer(VkrBuffer* buffer) { +void shd_rt_vk_destroy_buffer(VkrBuffer* buffer) { vkDestroyBuffer(buffer->device->device, buffer->buffer, NULL); vkFreeMemory(buffer->device->device, buffer->memory, NULL); } @@ -236,19 +236,19 @@ static void* vkr_get_buffer_host_pointer(VkrBuffer* buf) { } static VkrCommand* submit_buffer_copy(VkrDevice* device, VkBuffer src, size_t src_offset, VkBuffer dst, size_t dst_offset, size_t size) { - VkrCommand* commands = vkr_begin_command(device); + VkrCommand* commands = shd_rt_vk_begin_command(device); if (!commands) return NULL; vkCmdCopyBuffer(commands->cmd_buf, src, dst, 1, (VkBufferCopy[]) { { .srcOffset = src_offset, .dstOffset = dst_offset, .size = size } }); - if (!vkr_submit_command(commands)) + if (!shd_rt_vk_submit_command(commands)) goto err_post_commands_create; return commands; err_post_commands_create: - vkr_destroy_command(commands); + shd_rt_vk_destroy_command(commands); return NULL; } @@ -264,15 +264,15 @@ static bool vkr_copy_to_buffer_fallback(VkrBuffer* dst, size_t buffer_offset, vo CHECK_VK(vkMapMemory(device->device, src_buf->memory, src_buf->offset, src_buf->size, 0, &mapped), goto err_post_buffer_create); memcpy(mapped, src, size); - if (!wait_completion((Command*) submit_buffer_copy(device, src_buf->buffer, src_buf->offset, dst->buffer, dst->offset + buffer_offset, size))) + if (!shd_rt_wait_completion((Command*) submit_buffer_copy(device, src_buf->buffer, src_buf->offset, dst->buffer, dst->offset + buffer_offset, size))) goto err_post_buffer_create; vkUnmapMemory(device->device, src_buf->memory); - vkr_destroy_buffer(src_buf); + shd_rt_vk_destroy_buffer(src_buf); return true; err_post_buffer_create: - vkr_destroy_buffer(src_buf); + shd_rt_vk_destroy_buffer(src_buf); return false; } @@ -287,16 +287,16 @@ static bool vkr_copy_from_buffer_fallback(VkrBuffer* src, size_t buffer_offset, void* mapped; CHECK_VK(vkMapMemory(device->device, dst_buf->memory, dst_buf->offset, dst_buf->size, 0, &mapped), goto err_post_buffer_create); - if (!wait_completion((Command*) submit_buffer_copy(device, src->buffer, src->offset + buffer_offset, dst_buf->buffer, dst_buf->offset, size))) + if (!shd_rt_wait_completion((Command*) submit_buffer_copy(device, src->buffer, src->offset + buffer_offset, dst_buf->buffer, dst_buf->offset, size))) goto err_post_buffer_create; memcpy(dst, mapped, size); vkUnmapMemory(device->device, dst_buf->memory); - vkr_destroy_buffer(dst_buf); + shd_rt_vk_destroy_buffer(dst_buf); return true; err_post_buffer_create: - vkr_destroy_buffer(dst_buf); + shd_rt_vk_destroy_buffer(dst_buf); return false; } @@ -304,18 +304,18 @@ static bool vkr_copy_to_buffer_importing(VkrBuffer* dst, size_t buffer_offset, v CHECK(dst->base.backend_tag == VulkanRuntimeBackend, return false); VkrDevice* device = dst->device; - VkrBuffer* src_buf = vkr_import_buffer_host(device, src, size); + VkrBuffer* src_buf = shd_rt_vk_import_buffer_host(device, src, size); if (!src_buf) return false; - if (!wait_completion((Command*) submit_buffer_copy(device, src_buf->buffer, src_buf->offset, dst->buffer, dst->offset + buffer_offset, size))) + if (!shd_rt_wait_completion((Command*) submit_buffer_copy(device, src_buf->buffer, src_buf->offset, dst->buffer, dst->offset + buffer_offset, size))) goto err_post_buffer_import; - vkr_destroy_buffer(src_buf); + shd_rt_vk_destroy_buffer(src_buf); return true; err_post_buffer_import: - vkr_destroy_buffer(src_buf); + shd_rt_vk_destroy_buffer(src_buf); return false; } @@ -323,31 +323,31 @@ static bool vkr_copy_from_buffer_importing(VkrBuffer* src, size_t buffer_offset, CHECK(src->base.backend_tag == VulkanRuntimeBackend, return false); VkrDevice* device = src->device; - VkrBuffer* dst_buf = vkr_import_buffer_host(device, dst, size); + VkrBuffer* dst_buf = shd_rt_vk_import_buffer_host(device, dst, size); if (!dst_buf) return false; - if (!wait_completion((Command*) submit_buffer_copy(device, src->buffer, src->offset + buffer_offset, dst_buf->buffer, dst_buf->offset, size))) + if (!shd_rt_wait_completion((Command*) submit_buffer_copy(device, src->buffer, src->offset + buffer_offset, dst_buf->buffer, dst_buf->offset, size))) goto err_post_buffer_import; - vkr_destroy_buffer(dst_buf); + shd_rt_vk_destroy_buffer(dst_buf); return true; err_post_buffer_import: - vkr_destroy_buffer(dst_buf); + shd_rt_vk_destroy_buffer(dst_buf); return false; } static Buffer make_base_buffer(VkrDevice* device) { Buffer buffer = { .backend_tag = VulkanRuntimeBackend, - .destroy = (void(*)(Buffer*)) vkr_destroy_buffer, + .destroy = (void (*)(Buffer*)) shd_rt_vk_destroy_buffer, .get_device_ptr = (uint64_t(*)(Buffer*)) vkr_get_buffer_device_pointer, .get_host_ptr = (void*(*)(Buffer*)) vkr_get_buffer_host_pointer, .copy_into = (bool(*)(Buffer*, size_t, void*, size_t)) vkr_copy_to_buffer_fallback, .copy_from = (bool(*)(Buffer*, size_t, void*, size_t)) vkr_copy_from_buffer_fallback, }; - if (vkr_can_import_host_memory(device)) { + if (shd_rt_vk_can_import_host_memory(device)) { buffer.copy_from = (bool(*)(Buffer*, size_t, void*, size_t)) vkr_copy_from_buffer_importing; buffer.copy_into = (bool(*)(Buffer*, size_t, void*, size_t)) vkr_copy_to_buffer_importing; } diff --git a/src/runtime/vulkan/vk_runtime_device.c b/src/runtime/vulkan/vk_runtime_device.c index 662069586..b03e9c569 100644 --- a/src/runtime/vulkan/vk_runtime_device.c +++ b/src/runtime/vulkan/vk_runtime_device.c @@ -291,7 +291,7 @@ static void shutdown_vkr_device(VkrDevice* device) { SpecProgramKey k; VkrSpecProgram* sp; while (shd_dict_iter(device->specialized_programs, &i, &k, &sp)) { - destroy_specialized_program(sp); + shd_rt_vk_destroy_specialized_program(sp); } shd_destroy_dict(device->specialized_programs); vkDestroyCommandPool(device->device, device->cmd_pool, NULL); @@ -301,7 +301,7 @@ static void shutdown_vkr_device(VkrDevice* device) { static const char* get_vkr_device_name(VkrDevice* device) { return device->caps.properties.base.properties.deviceName; } -bool probe_vkr_devices(VkrBackend* runtime) { +bool shd_rt_vk_probe_devices(VkrBackend* runtime) { uint32_t devices_count; CHECK_VK(vkEnumeratePhysicalDevices(runtime->instance, &devices_count, NULL), return false) LARRAY(VkPhysicalDevice, available_devices, devices_count); @@ -321,10 +321,10 @@ bool probe_vkr_devices(VkrBackend* runtime) { device->base = (Device) { .cleanup = (void(*)(Device*)) shutdown_vkr_device, .get_name = (String(*)(Device*)) get_vkr_device_name, - .allocate_buffer = (Buffer*(*)(Device*, size_t)) vkr_allocate_buffer_device, - .import_host_memory_as_buffer = (Buffer*(*)(Device*, void*, size_t)) vkr_import_buffer_host, - .launch_kernel = (Command*(*)(Device*, Program*, String, int, int, int, int, void**, ExtraKernelOptions*)) vkr_launch_kernel, - .can_import_host_memory = (bool(*)(Device*)) vkr_can_import_host_memory, + .allocate_buffer = (Buffer* (*)(Device*, size_t)) shd_rt_vk_allocate_buffer_device, + .import_host_memory_as_buffer = (Buffer* (*)(Device*, void*, size_t)) shd_rt_vk_import_buffer_host, + .launch_kernel = (Command* (*)(Device*, Program*, String, int, int, int, int, void**, ExtraKernelOptions*)) shd_rt_vk_launch_kernel, + .can_import_host_memory = (bool (*)(Device*)) shd_rt_vk_can_import_host_memory, }; shd_list_append(Device*, runtime->base.runtime->devices, device); } diff --git a/src/runtime/vulkan/vk_runtime_dispatch.c b/src/runtime/vulkan/vk_runtime_dispatch.c index bcf69f244..3207410f5 100644 --- a/src/runtime/vulkan/vk_runtime_dispatch.c +++ b/src/runtime/vulkan/vk_runtime_dispatch.c @@ -30,7 +30,7 @@ static void bind_program_resources(VkrCommand* cmd, VkrSpecProgram* prog) { write_descriptor_sets[write_descriptor_sets_count] = (VkWriteDescriptorSet) { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .pNext = NULL, - .descriptorType = as_to_descriptor_type(resource->as), + .descriptorType = shd_rt_vk_as_to_descriptor_type(resource->as), .descriptorCount = 1, .dstSet = prog->sets[resource->set], .dstBinding = resource->binding, @@ -53,18 +53,18 @@ static void bind_program_resources(VkrCommand* cmd, VkrSpecProgram* prog) { static Command make_command_base() { return (Command) { - .wait_for_completion = (bool(*)(Command*)) vkr_wait_completion, + .wait_for_completion = (bool (*)(Command*)) shd_rt_vk_wait_completion, }; } -VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* options) { +VkrCommand* shd_rt_vk_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* options) { assert(program && device); - VkrSpecProgram* prog = get_specialized_program(program, entry_point, device); + VkrSpecProgram* prog = shd_rt_vk_get_specialized_program(program, entry_point, device); shd_debug_print("Dispatching kernel on %s\n", device->caps.properties.base.properties.deviceName); - VkrCommand* cmd = vkr_begin_command(device); + VkrCommand* cmd = shd_rt_vk_begin_command(device); if (!cmd) return NULL; @@ -102,17 +102,17 @@ VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_ vkCmdWriteTimestamp(cmd->cmd_buf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, cmd->query_pool, 1); } - if (!vkr_submit_command(cmd)) + if (!shd_rt_vk_submit_command(cmd)) goto err_post_commands_create; return cmd; err_post_commands_create: - vkr_destroy_command(cmd); + shd_rt_vk_destroy_command(cmd); return NULL; } -VkrCommand* vkr_begin_command(VkrDevice* device) { +VkrCommand* shd_rt_vk_begin_command(VkrDevice* device) { VkrCommand* cmd = calloc(1, sizeof(VkrCommand)); cmd->base = make_command_base(); cmd->device = device; @@ -141,7 +141,7 @@ VkrCommand* vkr_begin_command(VkrDevice* device) { return NULL; } -bool vkr_submit_command(VkrCommand* cmd) { +bool shd_rt_vk_submit_command(VkrCommand* cmd) { CHECK_VK(vkEndCommandBuffer(cmd->cmd_buf), return false); CHECK_VK(vkCreateFence(cmd->device->device, &(VkFenceCreateInfo) { @@ -168,7 +168,7 @@ bool vkr_submit_command(VkrCommand* cmd) { return false; } -bool vkr_wait_completion(VkrCommand* cmd) { +bool shd_rt_vk_wait_completion(VkrCommand* cmd) { assert(cmd->submitted && "Command must be submitted before they can be waited on"); CHECK_VK(vkWaitForFences(cmd->device->device, 1, (VkFence[]) { cmd->done_fence }, true, UINT32_MAX), return false); if (cmd->profiled_gpu_time) { @@ -176,11 +176,11 @@ bool vkr_wait_completion(VkrCommand* cmd) { CHECK_VK(vkGetQueryPoolResults(cmd->device->device, cmd->query_pool, 0, 2, sizeof(uint64_t) * 2, ts, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT), {}); *cmd->profiled_gpu_time = (ts[1] - ts[0]) * cmd->device->caps.properties.base.properties.limits.timestampPeriod; } - vkr_destroy_command(cmd); + shd_rt_vk_destroy_command(cmd); return true; } -void vkr_destroy_command(VkrCommand* cmd) { +void shd_rt_vk_destroy_command(VkrCommand* cmd) { if (cmd->submitted) vkDestroyFence(cmd->device->device, cmd->done_fence, NULL); if (cmd->query_pool) diff --git a/src/runtime/vulkan/vk_runtime_private.h b/src/runtime/vulkan/vk_runtime_private.h index 62fa6dd7a..4625cf1e6 100644 --- a/src/runtime/vulkan/vk_runtime_private.h +++ b/src/runtime/vulkan/vk_runtime_private.h @@ -156,7 +156,7 @@ struct VkrDevice_ { struct Dict* specialized_programs; }; -bool probe_vkr_devices(VkrBackend*); +bool shd_rt_vk_probe_devices(VkrBackend* runtime); typedef struct VkrBuffer_ { Buffer base; @@ -169,10 +169,10 @@ typedef struct VkrBuffer_ { void* host_ptr; } VkrBuffer; -VkrBuffer* vkr_allocate_buffer_device(VkrDevice* device, size_t size); -VkrBuffer* vkr_import_buffer_host(VkrDevice* device, void* ptr, size_t size); -bool vkr_can_import_host_memory(VkrDevice* device); -void vkr_destroy_buffer(VkrBuffer* buffer); +VkrBuffer* shd_rt_vk_allocate_buffer_device(VkrDevice* device, size_t size); +VkrBuffer* shd_rt_vk_import_buffer_host(VkrDevice* device, void* ptr, size_t size); +bool shd_rt_vk_can_import_host_memory(VkrDevice* device); +void shd_rt_vk_destroy_buffer(VkrBuffer* buffer); typedef struct VkrCommand_ VkrCommand; @@ -187,12 +187,12 @@ struct VkrCommand_ { VkQueryPool query_pool; }; -VkrCommand* vkr_begin_command(VkrDevice* device); -bool vkr_submit_command(VkrCommand* commands); -void vkr_destroy_command(VkrCommand* commands); -bool vkr_wait_completion(VkrCommand* cmd); +VkrCommand* shd_rt_vk_begin_command(VkrDevice* device); +bool shd_rt_vk_submit_command(VkrCommand* cmd); +void shd_rt_vk_destroy_command(VkrCommand* cmd); +bool shd_rt_vk_wait_completion(VkrCommand* cmd); -VkrCommand* vkr_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions*); +VkrCommand* shd_rt_vk_launch_kernel(VkrDevice* device, Program* program, String entry_point, int dimx, int dimy, int dimz, int args_count, void** args, ExtraKernelOptions* options); typedef struct ProgramResourceInfo_ ProgramResourceInfo; struct ProgramResourceInfo_ { @@ -221,7 +221,7 @@ typedef struct { #define MAX_DESCRIPTOR_SETS 4 -VkDescriptorType as_to_descriptor_type(AddressSpace as); +VkDescriptorType shd_rt_vk_as_to_descriptor_type(AddressSpace as); struct VkrSpecProgram_ { SpecProgramKey key; @@ -248,8 +248,8 @@ struct VkrSpecProgram_ { VkDescriptorSet sets[MAX_DESCRIPTOR_SETS]; }; -VkrSpecProgram* get_specialized_program(Program*, String ep, VkrDevice*); -void destroy_specialized_program(VkrSpecProgram*); +VkrSpecProgram* shd_rt_vk_get_specialized_program(Program* program, String entry_point, VkrDevice* device); +void shd_rt_vk_destroy_specialized_program(VkrSpecProgram* spec); static inline void append_pnext(VkBaseOutStructure* s, void* n) { while (s->pNext != NULL) diff --git a/src/runtime/vulkan/vk_runtime_program.c b/src/runtime/vulkan/vk_runtime_program.c index fdab0e0bb..a60354969 100644 --- a/src/runtime/vulkan/vk_runtime_program.c +++ b/src/runtime/vulkan/vk_runtime_program.c @@ -33,7 +33,7 @@ static void add_binding(VkDescriptorSetLayoutCreateInfo* layout_create_info, Gro shd_growy_append_object(bindings_lists[set], binding); } -VkDescriptorType as_to_descriptor_type(AddressSpace as) { +VkDescriptorType shd_rt_vk_as_to_descriptor_type(AddressSpace as) { switch (as) { case AsUniform: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; case AsShaderStorageBufferObject: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; @@ -145,14 +145,14 @@ static bool extract_resources_layout(VkrSpecProgram* program, VkDescriptorSetLay } } - if (vkr_can_import_host_memory(program->device)) + if (shd_rt_vk_can_import_host_memory(program->device)) res_info->host_backed_allocation = true; else res_info->staging = calloc(1, res_info->size); VkDescriptorSetLayoutBinding vk_binding = { .binding = binding, - .descriptorType = as_to_descriptor_type(as), + .descriptorType = shd_rt_vk_as_to_descriptor_type(as), .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_ALL, .pImmutableSamplers = NULL, @@ -432,7 +432,7 @@ static void flush_staged_data(VkrSpecProgram* program) { for (size_t i = 0; i < program->resources.num_resources; i++) { ProgramResourceInfo* resource = program->resources.resources[i]; if (resource->staging) { - copy_to_buffer((Buffer*) resource->buffer, 0, resource->buffer, resource->size); + shd_rt_copy_to_buffer((Buffer*) resource->buffer, 0, resource->buffer, resource->size); free(resource->staging); } } @@ -443,18 +443,18 @@ static bool prepare_resources(VkrSpecProgram* program) { ProgramResourceInfo* resource = program->resources.resources[i]; if (resource->host_backed_allocation) { - assert(vkr_can_import_host_memory(program->device)); + assert(shd_rt_vk_can_import_host_memory(program->device)); resource->host_ptr = shd_alloc_aligned(resource->size, program->device->caps.properties.external_memory_host.minImportedHostPointerAlignment); - resource->buffer = vkr_import_buffer_host(program->device, resource->host_ptr, resource->size); + resource->buffer = shd_rt_vk_import_buffer_host(program->device, resource->host_ptr, resource->size); } else { - resource->buffer = vkr_allocate_buffer_device(program->device, resource->size); + resource->buffer = shd_rt_vk_allocate_buffer_device(program->device, resource->size); } if (resource->default_data) { - copy_to_buffer((Buffer*) resource->buffer, 0, resource->default_data, resource->size); + shd_rt_copy_to_buffer((Buffer*) resource->buffer, 0, resource->default_data, resource->size); } else { char* zeroes = calloc(1, resource->size); - copy_to_buffer((Buffer*) resource->buffer, 0, zeroes, resource->size); + shd_rt_copy_to_buffer((Buffer*) resource->buffer, 0, zeroes, resource->size); free(zeroes); } @@ -464,7 +464,7 @@ static bool prepare_resources(VkrSpecProgram* program) { dst = resource->parent->staging; } assert(dst); - *((uint64_t*) (dst + resource->offset)) = get_buffer_device_pointer((Buffer*) resource->buffer); + *((uint64_t*) (dst + resource->offset)) = shd_rt_get_buffer_device_pointer((Buffer*) resource->buffer); } } @@ -491,7 +491,7 @@ static VkrSpecProgram* create_specialized_program(SpecProgramKey key, VkrDevice* return spec_program; } -VkrSpecProgram* get_specialized_program(Program* program, String entry_point, VkrDevice* device) { +VkrSpecProgram* shd_rt_vk_get_specialized_program(Program* program, String entry_point, VkrDevice* device) { SpecProgramKey key = { .base = program, .entry_point = entry_point }; VkrSpecProgram** found = shd_dict_find_value(SpecProgramKey, VkrSpecProgram*, device->specialized_programs, key); if (found) @@ -502,7 +502,7 @@ VkrSpecProgram* get_specialized_program(Program* program, String entry_point, Vk return spec; } -void destroy_specialized_program(VkrSpecProgram* spec) { +void shd_rt_vk_destroy_specialized_program(VkrSpecProgram* spec) { vkDestroyPipeline(spec->device->device, spec->pipeline, NULL); for (size_t set = 0; set < MAX_DESCRIPTOR_SETS; set++) vkDestroyDescriptorSetLayout(spec->device->device, spec->set_layouts[set], NULL); @@ -515,7 +515,7 @@ void destroy_specialized_program(VkrSpecProgram* spec) { for (size_t i = 0; i < spec->resources.num_resources; i++) { ProgramResourceInfo* resource = spec->resources.resources[i]; if (resource->buffer) - vkr_destroy_buffer(resource->buffer); + shd_rt_vk_destroy_buffer(resource->buffer); if (resource->host_ptr && resource->host_backed_allocation) shd_free_aligned(resource->host_ptr); } diff --git a/zhady/shady.i b/zhady/shady.i index f2db06444..58d910071 100644 --- a/zhady/shady.i +++ b/zhady/shady.i @@ -11,6 +11,13 @@ * bb #include "shady/runtime.h" + +* d + +* r + +* runtime + #include "shady/driver.h" * mod From 3ea8f8f1b30686639c8dfa00080cbe2bf6139e66 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 14 Oct 2024 17:23:40 +0200 Subject: [PATCH 683/693] updated codestyle --- doc/code_style.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/code_style.md b/doc/code_style.md index 60545ef20..6db664898 100644 --- a/doc/code_style.md +++ b/doc/code_style.md @@ -12,7 +12,7 @@ If you have a good reason for breaking any of those rules we're happy to conside * `{ spaces, surrounding, initializer, lists }` * Unless you're literally contributing using a 80-column display (for which I'll ask visual proof), don't format your code as if you do. * Include order: - * If appropriate, (Private) `self.h` should always come first + * If appropriate, (Private) `self.h` should always come first, with other local headers in the same group * Then other `shady/` headers * Then in-project utility headers * Then external headers @@ -26,6 +26,7 @@ Due to C not having namespaces, we have to deal with this painfully automatable * Avoid exposing any symbols that don't need to be exposed (use `static` wherever you can) * Prefixes: * `shd_` in front of API functions (in the root `include` folder) + * `slim_`, `l2s_`, `spv_` and `vcc_` are used in various sub-projects * `subsystem_` is acceptable for internal use * `shd_subsystem_` is preferable where a clear delineation can be made * `shd_new_thing` and `shd_destroy_thing` for constructors and destructors From 702161618f8c0395cc389b13f785a78dfb63d4c3 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 21 Oct 2024 16:33:41 +0200 Subject: [PATCH 684/693] ir/int: added an unsafe function to resolve a node to a literal directly --- include/shady/ir/int.h | 2 ++ src/shady/ir/int.c | 8 ++++++++ src/shady/passes/lower_inclusive_scan.c | 0 3 files changed, 10 insertions(+) create mode 100644 src/shady/passes/lower_inclusive_scan.c diff --git a/include/shady/ir/int.h b/include/shady/ir/int.h index 57f65df37..8248fae7a 100644 --- a/include/shady/ir/int.h +++ b/include/shady/ir/int.h @@ -38,6 +38,8 @@ const Node* shd_uint64_literal(IrArena* arena, uint64_t u); const IntLiteral* shd_resolve_to_int_literal(const Node* node); int64_t shd_get_int_literal_value(IntLiteral literal, bool sign_extend); +int64_t shd_get_int_value(const Node* node, bool sign_extend); + const Node* shd_bld_convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src); const Node* shd_bld_convert_int_extend_according_to_dst_t(BodyBuilder* bb, const Type* dst_type, const Node* src); const Node* shd_bld_convert_int_zero_extend(BodyBuilder* bb, const Type* dst_type, const Node* src); diff --git a/src/shady/ir/int.c b/src/shady/ir/int.c index 943d83d66..b055f5648 100644 --- a/src/shady/ir/int.c +++ b/src/shady/ir/int.c @@ -3,6 +3,8 @@ #include "shady/analysis/literal.h" +#include "log.h" + #include const Type* shd_int_type_helper(IrArena* a, bool s, IntSizes w) { return int_type(a, (Int) { .width = w, .is_signed = s }); } @@ -56,6 +58,12 @@ int64_t shd_get_int_literal_value(IntLiteral literal, bool sign_extend) { } } +int64_t shd_get_int_value(const Node* node, bool sign_extend) { + const IntLiteral* lit = shd_resolve_to_int_literal(node); + if (!lit) shd_error("Not a literal"); + return shd_get_int_literal_value(*lit, sign_extend); +} + const Node* shd_bld_convert_int_extend_according_to_src_t(BodyBuilder* bb, const Type* dst_type, const Node* src) { IrArena* a = shd_get_bb_arena(bb); const Type* src_type = shd_get_unqualified_type(src->type); diff --git a/src/shady/passes/lower_inclusive_scan.c b/src/shady/passes/lower_inclusive_scan.c new file mode 100644 index 000000000..e69de29bb From a8e0d32e881a0a9ad54e16173b91718c6eb24d32 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 21 Oct 2024 16:34:15 +0200 Subject: [PATCH 685/693] added lower_inclusive_scan pass --- src/backend/c/emit_c.c | 1 + src/shady/passes/lower_inclusive_scan.c | 135 ++++++++++++++++++++++++ src/shady/passes/passes.h | 1 + 3 files changed, 137 insertions(+) diff --git a/src/backend/c/emit_c.c b/src/backend/c/emit_c.c index 146d41fb4..7099c460c 100644 --- a/src/backend/c/emit_c.c +++ b/src/backend/c/emit_c.c @@ -380,6 +380,7 @@ static Module* run_backend_specific_passes(const CompilerConfig* config, CEmitte RUN_PASS(shd_pass_eliminate_constants) if (econfig->dialect == CDialect_ISPC) { RUN_PASS(shd_pass_lower_workgroups) + RUN_PASS(shd_pass_lower_inclusive_scan) } if (econfig->dialect != CDialect_GLSL) { RUN_PASS(shd_pass_lower_vec_arr) diff --git a/src/shady/passes/lower_inclusive_scan.c b/src/shady/passes/lower_inclusive_scan.c index e69de29bb..39b26fb30 100644 --- a/src/shady/passes/lower_inclusive_scan.c +++ b/src/shady/passes/lower_inclusive_scan.c @@ -0,0 +1,135 @@ +#include "shady/pass.h" +#include "shady/ir/type.h" + +#include "log.h" +#include "portability.h" + +#include + +#include + +typedef struct { + Rewriter rewriter; +} Context; + +typedef struct { + SpvOp spv_op; + Op scalar; + const Node* (*I)(IrArena*, const Type* t); +} GroupOp; + +static const Node* zero(IrArena* a, const Type* t) { + t = shd_get_unqualified_type(t); + assert(t->tag == Int_TAG); + Int t_payload = t->payload.int_type; + IntLiteral lit = { + .width = t_payload.width, + .is_signed = t_payload.is_signed, + .value = 0 + }; + return int_literal(a, lit); +} + +static const Node* one(IrArena* a, const Type* t) { + t = shd_get_unqualified_type(t); + assert(t->tag == Int_TAG); + Int t_payload = t->payload.int_type; + IntLiteral lit = { + .width = t_payload.width, + .is_signed = t_payload.is_signed, + .value = 1 + }; + return int_literal(a, lit); +} + +static GroupOp group_operations[] = { + { SpvOpGroupIAdd, add_op }, + { SpvOpGroupFAdd, add_op }, + { SpvOpGroupFMin, min_op }, + { SpvOpGroupUMin, min_op }, + { SpvOpGroupSMin, min_op }, + { SpvOpGroupFMax, max_op, }, + { SpvOpGroupUMax, max_op }, + { SpvOpGroupSMax, max_op }, + { SpvOpGroupNonUniformBallotBitCount, /* todo */ }, + { SpvOpGroupNonUniformIAdd, add_op }, + { SpvOpGroupNonUniformFAdd, add_op }, + { SpvOpGroupNonUniformIMul, mul_op }, + { SpvOpGroupNonUniformFMul, mul_op }, + { SpvOpGroupNonUniformSMin, min_op }, + { SpvOpGroupNonUniformUMin, min_op }, + { SpvOpGroupNonUniformFMin, min_op }, + { SpvOpGroupNonUniformSMax, max_op }, + { SpvOpGroupNonUniformUMax, max_op }, + { SpvOpGroupNonUniformFMax, max_op }, + { SpvOpGroupNonUniformBitwiseAnd, and_op }, + { SpvOpGroupNonUniformBitwiseOr, or_op }, + { SpvOpGroupNonUniformBitwiseXor, xor_op }, + { SpvOpGroupNonUniformLogicalAnd, and_op }, + { SpvOpGroupNonUniformLogicalOr, or_op }, + { SpvOpGroupNonUniformLogicalXor, xor_op }, + { SpvOpGroupIAddNonUniformAMD, /* todo: map to std */ }, + { SpvOpGroupFAddNonUniformAMD, /* todo: map to std */ }, + { SpvOpGroupFMinNonUniformAMD, /* todo: map to std */ }, + { SpvOpGroupUMinNonUniformAMD, /* todo: map to std */ }, + { SpvOpGroupSMinNonUniformAMD, /* todo: map to std */ }, + { SpvOpGroupFMaxNonUniformAMD, /* todo: map to std */ }, + { SpvOpGroupUMaxNonUniformAMD, /* todo: map to std */ }, + { SpvOpGroupSMaxNonUniformAMD, /* todo: map to std */ }, + { SpvOpGroupIMulKHR, /* todo: map to std */ }, + { SpvOpGroupFMulKHR, /* todo: map to std */ }, + { SpvOpGroupBitwiseAndKHR, /* todo: map to std */ }, + { SpvOpGroupBitwiseOrKHR, /* todo: map to std */ }, + { SpvOpGroupBitwiseXorKHR, /* todo: map to std */ }, + { SpvOpGroupLogicalAndKHR, /* todo: map to std */ }, + { SpvOpGroupLogicalOrKHR, /* todo: map to std */ }, + { SpvOpGroupLogicalXorKHR, /* todo: map to std */ }, +}; + +enum { + NumGroupOps = sizeof(group_operations) / sizeof(group_operations[0]) +}; + +static const Node* process(Context* ctx, const Node* node) { + Rewriter* r = &ctx->rewriter; + IrArena* a = r->dst_arena; + switch (node->tag) { + case ExtInstr_TAG: { + ExtInstr payload = node->payload.ext_instr; + if (strcmp(payload.set, "spirv.core") == 0) { + for (size_t i = 0; i < NumGroupOps; i++) { + if (payload.opcode == group_operations[i].spv_op) { + if (shd_get_int_value(payload.operands.nodes[1], false) == SpvGroupOperationInclusiveScan) { + //assert(group_operations[i].I); + IrArena* oa = node->arena; + payload.operands = shd_change_node_at_index(oa, payload.operands, 1, shd_uint32_literal(a, SpvGroupOperationReduce)); + const Node* new = shd_recreate_node(r, ext_instr(oa, payload)); + // new = prim_op_helper(a, group_operations[i].scalar, shd_empty(a), mk_nodes(a, new, group_operations[i].I(a, new->type) )); + new = prim_op_helper(a, group_operations[i].scalar, shd_empty(a), mk_nodes(a, new, shd_recreate_node(r, payload.operands.nodes[2]) )); + return new; + } + } + } + } + } + default: break; + } + + return shd_recreate_node(r, node); +} + +/// Transforms +/// SpvOpGroupXXX(Scope, 'GroupOperationInclusiveScan', v) +/// into +/// SpvOpGroupXXX(Scope, 'GroupOperationExclusiveScan', v) op v +Module* shd_pass_lower_inclusive_scan(SHADY_UNUSED const CompilerConfig* config, Module* src) { + ArenaConfig aconfig = *shd_get_arena_config(shd_module_get_arena(src)); + IrArena* a = shd_new_ir_arena(&aconfig); + Module* dst = shd_new_module(a, shd_module_get_name(src)); + Context ctx = { + .rewriter = shd_create_node_rewriter(src, dst, (RewriteNodeFn) process), + }; + shd_rewrite_module(&ctx.rewriter); + shd_destroy_rewriter(&ctx.rewriter); + return dst; +} diff --git a/src/shady/passes/passes.h b/src/shady/passes/passes.h index a718d6a43..d2d3f8fb2 100644 --- a/src/shady/passes/passes.h +++ b/src/shady/passes/passes.h @@ -92,6 +92,7 @@ RewritePass shd_pass_lower_vec_arr; RewritePass shd_pass_lower_workgroups; RewritePass shd_pass_lower_fill; RewritePass shd_pass_lower_nullptr; +RewritePass shd_pass_lower_inclusive_scan; /// @} From 543aa62969d22cd753ad0a5ba3dedf952aa8e5ab Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 21 Oct 2024 16:34:38 +0200 Subject: [PATCH 686/693] c: improved codegen for ExtInstr --- src/backend/c/emit_c_value.c | 139 +++++++++++++++++++++++------- src/shady/internal/scheduler.slim | 2 +- src/shady/passes/CMakeLists.txt | 1 + 3 files changed, 111 insertions(+), 31 deletions(-) diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 91bbdb219..7baff121c 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -344,10 +344,10 @@ static const ISelTableEntry isel_table_ispc[PRIMOPS_COUNT] = { [pow_op] = { IsMono, OsCall, "pow" }, }; -static bool emit_using_entry(CTerm* out, Emitter* emitter, FnEmitter* fn, Printer* p, const ISelTableEntry* entry, Nodes operands) { +static CTerm emit_using_entry(Emitter* emitter, FnEmitter* fn, Printer* p, const ISelTableEntry* entry, Nodes operands) { String operator_str = NULL; switch (entry->isel_mechanism) { - case IsNone: return false; + case IsNone: return empty_term(); case IsMono: operator_str = entry->op; break; case IsPoly: { const Type* t = get_first_op_scalar_type(operands); @@ -361,27 +361,27 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, FnEmitter* fn, Printe } } - if (!operator_str) - return false; + if (!operator_str) { + shd_log_fmt(ERROR, "emit_c: Missing or unsupported operands for this entry"); + return empty_term(); + } switch (entry->style) { case OsInfix: { CTerm a = shd_c_emit_value(emitter, fn, operands.nodes[0]); CTerm b = shd_c_emit_value(emitter, fn, operands.nodes[1]); - *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s %s %s", shd_c_to_ssa(emitter, a), operator_str, shd_c_to_ssa(emitter, b))); - break; + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s %s %s", shd_c_to_ssa(emitter, a), operator_str, shd_c_to_ssa(emitter, b))); } case OsPrefix: { CTerm operand = shd_c_emit_value(emitter, fn, operands.nodes[0]); - *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s%s", operator_str, shd_c_to_ssa(emitter, operand))); - break; + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s%s", operator_str, shd_c_to_ssa(emitter, operand))); } case OsCall: { LARRAY(CTerm, cops, operands.count); for (size_t i = 0; i < operands.count; i++) cops[i] = shd_c_emit_value(emitter, fn, operands.nodes[i]); if (operands.count == 1) - *out = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", operator_str, shd_c_to_ssa(emitter, cops[0]))); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", operator_str, shd_c_to_ssa(emitter, cops[0]))); else { Growy* g = shd_new_growy(); shd_growy_append_string(g, operator_str); @@ -392,12 +392,13 @@ static bool emit_using_entry(CTerm* out, Emitter* emitter, FnEmitter* fn, Printe shd_growy_append_string_literal(g, ", "); } shd_growy_append_string_literal(g, ")"); - *out = term_from_cvalue(shd_growy_deconstruct(g)); + return term_from_cvalue(shd_growy_deconstruct(g)); } break; } } - return true; + + SHADY_UNREACHABLE; } static const ISelTableEntry* lookup_entry(Emitter* emitter, Op op) { @@ -442,14 +443,12 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node break; // MATH OPS case fract_op: { - CTerm floored; - emit_using_entry(&floored, emitter, fn, p, lookup_entry(emitter, floor_op), prim_op->operands); + CTerm floored = emit_using_entry(emitter, fn, p, lookup_entry(emitter, floor_op), prim_op->operands); term = term_from_cvalue(shd_format_string_arena(arena->arena, "1 - %s", shd_c_to_ssa(emitter, floored))); break; } case inv_sqrt_op: { - CTerm floored; - emit_using_entry(&floored, emitter, fn, p, lookup_entry(emitter, sqrt_op), prim_op->operands); + CTerm floored = emit_using_entry(emitter, fn, p, lookup_entry(emitter, sqrt_op), prim_op->operands); term = term_from_cvalue(shd_format_string_arena(arena->arena, "1.0f / %s", shd_c_to_ssa(emitter, floored))); break; } @@ -710,11 +709,90 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } if (isel_entry->isel_mechanism != IsNone) - emit_using_entry(&term, emitter, fn, p, isel_entry, prim_op->operands); + return emit_using_entry(emitter, fn, p, isel_entry, prim_op->operands); return term; } +typedef struct { + String set; + SpvOp op; + size_t prefix_len; + uint32_t* prefix; +} ExtISelPattern; + +#define mk_prefix(...) .prefix_len = sizeof((uint32_t[]) {__VA_ARGS__}) / sizeof(uint32_t), .prefix = (uint32_t[]) {__VA_ARGS__} +#define subgroup_reduction mk_prefix(SpvScopeSubgroup, SpvGroupOperationReduce) + +typedef struct { + ExtISelPattern match; + ISelTableEntry payload; +} ExtISelEntry; + +ExtISelEntry ext_isel_ispc_entries[] = { + // reduce add + {{ "spirv.core", SpvOpGroupIAdd, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_add" }}, + {{ "spirv.core", SpvOpGroupFAdd, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_add" }}, + {{ "spirv.core", SpvOpGroupNonUniformIAdd, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_add" }}, + {{ "spirv.core", SpvOpGroupNonUniformFAdd, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_add" }}, + // min + {{ "spirv.core", SpvOpGroupSMin, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_min" }}, + {{ "spirv.core", SpvOpGroupUMin, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_min" }}, + {{ "spirv.core", SpvOpGroupFMin, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_min" }}, + {{ "spirv.core", SpvOpGroupNonUniformSMin, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_min" }}, + {{ "spirv.core", SpvOpGroupNonUniformUMin, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_min" }}, + {{ "spirv.core", SpvOpGroupNonUniformFMin, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_min" }}, + // max + {{ "spirv.core", SpvOpGroupSMax, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_max" }}, + {{ "spirv.core", SpvOpGroupUMax, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_max" }}, + {{ "spirv.core", SpvOpGroupFMax, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_max" }}, + {{ "spirv.core", SpvOpGroupNonUniformSMax, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_max" }}, + {{ "spirv.core", SpvOpGroupNonUniformUMax, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_max" }}, + {{ "spirv.core", SpvOpGroupNonUniformFMax, subgroup_reduction }, { IsMono, OsCall, .op = "reduce_max" }}, + // rest + {{ "spirv.core", SpvOpGroupNonUniformAllEqual, mk_prefix(SpvScopeSubgroup) }, { IsMono, OsCall, .op = "reduce_equal" }}, + {{ "spirv.core", SpvOpGroupNonUniformBallot, mk_prefix(SpvScopeSubgroup) }, { IsMono, OsCall, .op = "packmask" }}, +}; + +ExtISelEntry ext_isel_entries[] = { + {{ "spirv.core", SpvOpGroupNonUniformBroadcastFirst, mk_prefix(SpvScopeSubgroup) }, { IsMono, OsCall, .op = "__shady_broadcast_first" }}, + {{ "spirv.core", SpvOpGroupNonUniformElect, mk_prefix(SpvScopeSubgroup) }, { IsMono, OsCall, .op = "__shady_elect_first" }}, +}; + +static bool check_ext_entry(const ExtISelPattern* entry, ExtInstr instr) { + if (strcmp(entry->set, instr.set) != 0 || entry->op != instr.opcode) + return false; + for (size_t i = 0; i < entry->prefix_len; i++) { + if (i >= instr.operands.count) + return false; + const IntLiteral* lit = shd_resolve_to_int_literal(instr.operands.nodes[i]); + if (!lit) + return false; + if (shd_get_int_literal_value(*lit, false) != entry->prefix[i]) + return false; + } + return true; +} + +static const ExtISelEntry* find_ext_entry_in_list(const ExtISelEntry table[], size_t size, ExtInstr instr) { + for (size_t i = 0; i < size; i++) { + if (check_ext_entry(&table[i].match, instr)) + return &table[i]; + } + return NULL; +} + +#define scan_entries(name) { const ExtISelEntry* f = find_ext_entry_in_list(name, sizeof(name) / sizeof(name[0]), instr); if (f) return f; } + +static const ExtISelEntry* find_ext_entry(Emitter* e, ExtInstr instr) { + switch (e->config.dialect) { + case CDialect_ISPC: scan_entries(ext_isel_ispc_entries); break; + default: break; + } + scan_entries(ext_isel_entries); + return NULL; +} + static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, ExtInstr instr) { shd_c_emit_mem(emitter, fn, instr.mem); if (strcmp(instr.set, "spirv.core") == 0) { @@ -722,10 +800,8 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E case SpvOpGroupNonUniformBroadcastFirst: { CValue value = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, shd_first(instr.operands))); switch (emitter->config.dialect) { - case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_broadcast_first(%s)", value)); case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); - case CDialect_C11: - case CDialect_GLSL: shd_error("TODO") + default: break; } break; } @@ -734,20 +810,23 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E const IntLiteral* scope = shd_resolve_to_int_literal(shd_first(instr.operands)); assert(scope && scope->value == SpvScopeSubgroup); switch (emitter->config.dialect) { - case CDialect_CUDA: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "__shady_elect_first()")); case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "(programIndex == count_trailing_zeros(lanemask()))")); - case CDialect_C11: - case CDialect_GLSL: shd_error("TODO") + default: break; } break; } - // [subgroup_active_mask_op] = { IsMono, OsCall, "lanemask" }, - // [subgroup_ballot_op] = { IsMono, OsCall, "packmask" }, - // [subgroup_reduce_sum_op] = { IsMono, OsCall, "reduce_add" }, - default: shd_error("Unsupported core spir-v instruction: %d", instr.opcode); + default: break; } + } + + const ExtISelEntry* entry = find_ext_entry(emitter, instr); + if (entry) { + Nodes operands = instr.operands; + if (entry->match.prefix_len > 0) + operands = shd_nodes(emitter->arena, operands.count - entry->match.prefix_len, &operands.nodes[entry->match.prefix_len]); + return emit_using_entry(emitter, fn, p, &entry->payload, operands); } else { - shd_error("Unsupported extended instruction set: %s", instr.set); + shd_error("Unsupported extended instruction: (set = %s, opcode = %d )", instr.set, instr.opcode); } } @@ -776,13 +855,13 @@ static CTerm emit_call(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* CValue e_callee; const Node* callee = call->payload.call.callee; if (callee->tag == FnAddr_TAG) - e_callee = get_declaration_name(callee->payload.fn_addr.fn); + e_callee = shd_c_legalize_identifier(emitter, get_declaration_name(callee->payload.fn_addr.fn)); else e_callee = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, callee)); String params = shd_printer_growy_unwrap(paramsp); - CTerm called = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "%s(%s)", e_callee, params)); + CTerm called = term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "\n%s(%s)", e_callee, params)); called = shd_c_bind_intermediary_result(emitter, p, call->type, called); free_tmp_str(params); @@ -968,7 +1047,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const args_list = shd_format_string_arena(emitter->arena->arena, "%s, %s", args_list, str); } switch (emitter->config.dialect) { - case CDialect_ISPC:shd_print(p, "\nforeach_active(printf_thread_index) { shd_print(%s); }", args_list); + case CDialect_ISPC:shd_print(p, "\nforeach_active(printf_thread_index) { print(%s); }", args_list); break; case CDialect_CUDA: case CDialect_C11:shd_print(p, "\nprintf(%s);", args_list); diff --git a/src/shady/internal/scheduler.slim b/src/shady/internal/scheduler.slim index 8742a5a68..e0a521212 100644 --- a/src/shady/internal/scheduler.slim +++ b/src/shady/internal/scheduler.slim @@ -49,7 +49,7 @@ fn builtin_init_scheduler() { scheduler_vector#(subgroup_local_id) = tree_node1; active_branch = tree_node1; - actual_subgroup_size = (ext_instr["spirv.core", 349, varying u32](3, u32 1, 0)); + actual_subgroup_size = (ext_instr["spirv.core", 349, varying u32](3, u32 1, u32 0)); } @Internal @Exported diff --git a/src/shady/passes/CMakeLists.txt b/src/shady/passes/CMakeLists.txt index 7b329ad78..34cb94de5 100644 --- a/src/shady/passes/CMakeLists.txt +++ b/src/shady/passes/CMakeLists.txt @@ -41,4 +41,5 @@ target_sources(shady PRIVATE reconvergence_heuristics.c lcssa.c remove_critical_edges.c + lower_inclusive_scan.c ) From c43ba10413904bd1c5bd6c0fbbe73e3ae8ca70a4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 22 Oct 2024 11:27:19 +0200 Subject: [PATCH 687/693] added printer escape/unescape functions, plus testing --- src/common/CMakeLists.txt | 4 +++ src/common/printer.h | 2 ++ src/common/test_util.c | 62 +++++++++++++++++++++++++++++++++++++++ src/common/util.c | 42 ++++++++++++++++++++++++-- 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 src/common/test_util.c diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8d4ee5353..552960de1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -26,4 +26,8 @@ if (BUILD_TESTING) add_executable(test_dict test_dict.c) target_link_libraries(test_dict PRIVATE common) add_test(NAME test_dict COMMAND test_dict) + + add_executable(test_util test_util.c) + target_link_libraries(test_util PRIVATE common) + add_test(NAME test_util COMMAND test_util) endif () \ No newline at end of file diff --git a/src/common/printer.h b/src/common/printer.h index d1c087caf..aff7b9d54 100644 --- a/src/common/printer.h +++ b/src/common/printer.h @@ -15,6 +15,8 @@ void shd_newline(Printer* p); void shd_printer_indent(Printer* p); void shd_printer_deindent(Printer* p); void shd_printer_flush(Printer* p); +void shd_printer_escape(Printer* p, const char*); +void shd_printer_unescape(Printer* p, const char*); const char* shd_printer_growy_unwrap(Printer* p); Growy* shd_new_growy(void); diff --git a/src/common/test_util.c b/src/common/test_util.c new file mode 100644 index 000000000..49373d880 --- /dev/null +++ b/src/common/test_util.c @@ -0,0 +1,62 @@ +#include "util.h" +#include "printer.h" + +#undef NDEBUG +#include +#include +#include +#include + +const char escaped[] = "hi\nthis is a backslash\\, \tthis is a tab and this backspace character ends it all\b"; +const char double_escaped[] = "hi\\nthis is a backslash\\\\, \\tthis is a tab and this backspace character ends it all\\b"; + +enum { + Len = sizeof(escaped), + DoubleLen = sizeof(double_escaped), + MaxLen = DoubleLen +}; + +void test_escape_unescape_basic(void) { + char output[MaxLen] = { 0 }; + + printf("escaped: %s\n---------------------\n", escaped); + printf("double_escaped: %s\n---------------------\n", double_escaped); + shd_apply_escape_codes(double_escaped, DoubleLen, output); + printf("shd_apply_escape_codes(double_escaped): %s\n---------------------\n", output); + assert(strcmp(output, escaped) == 0); + memset(output, 0, MaxLen); + shd_unapply_escape_codes(escaped, Len, output); + printf("shd_apply_escape_codes(escaped): %s\n---------------------\n", output); + assert(strcmp(output, double_escaped) == 0); +} + +void test_escape_printer(void) { + Printer* p = shd_new_printer_from_growy(shd_new_growy()); + shd_printer_escape(p, double_escaped); + const char* output = shd_printer_growy_unwrap(p); + printf("shd_printer_escape(escaped): %s\n---------------------\n", output); + assert(strlen(output) == Len - 1); + assert(strcmp(output, escaped) == 0); + free((char*) output); +} + +void test_unescape_printer(void) { + Printer* p = shd_new_printer_from_growy(shd_new_growy()); + shd_printer_unescape(p, escaped); + const char* output = shd_printer_growy_unwrap(p); + printf("shd_printer_unescape(escaped): %s\n---------------------\n", output); + assert(strlen(output) == DoubleLen - 1); + assert(strcmp(output, double_escaped) == 0); + free((char*) output); +} + +int main(int argc, char** argv) { + assert(strlen(double_escaped) == DoubleLen - 1); + assert(strlen(escaped) == Len - 1); + + test_escape_unescape_basic(); + test_escape_printer(); + test_unescape_printer(); + + return 0; +} \ No newline at end of file diff --git a/src/common/util.c b/src/common/util.c index 7cf30608e..8ed07ed7b 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1,4 +1,5 @@ #include "util.h" +#include "printer.h" #include "arena.h" #include @@ -20,13 +21,13 @@ X( 'a', '\a') \ X( 'v', '\v') \ size_t shd_apply_escape_codes(const char* src, size_t size, char* dst) { - char p, c = '\0'; + char prev, c = '\0'; size_t j = 0; for (size_t i = 0; i < size; i++) { - p = c; + prev = c; c = src[i]; -#define ESCAPE_CASE(m, s) if (p == '\\' && c == m) { \ +#define ESCAPE_CASE(m, s) if (prev == '\\' && c == m) { \ dst[j - 1] = s; \ continue; \ } \ @@ -59,6 +60,41 @@ size_t shd_unapply_escape_codes(const char* src, size_t size, char* dst) { return j; } +void shd_printer_escape(Printer* p, const char* src) { + size_t size = strlen(src); + for (size_t i = 0; i < size; i++) { + char c = src[i]; + char next = i + 1 < size ? src[i + 1] : '\0'; + +#define ESCAPE_CASE(m, s) if (c == '\\' && next == m) { \ + char code = s; \ + shd_print(p, "%c", code); \ + i++; \ + continue; \ + } \ + + ESCAPE_SEQS(ESCAPE_CASE) +#undef ESCAPE_CASE + shd_print(p, "%c", c); + } +} + +void shd_printer_unescape(Printer* p, const char* src) { + size_t size = strlen(src); + for (size_t i = 0; i < size; i++) { + char c = src[i]; + +#define ESCAPE_CASE(m, s) if (c == s) { \ + shd_print(p, "\\%c", m); \ + continue; \ + } \ + + ESCAPE_SEQS(ESCAPE_CASE) +#undef ESCAPE_CASE + shd_print(p, "%c", c); + } +} + static long get_file_size(FILE* f) { if (fseek(f, 0, SEEK_END) != 0) return -1; From 29cc0eac7b9566c0a2bd15b9529d4ea5e6977af2 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 22 Oct 2024 11:27:41 +0200 Subject: [PATCH 688/693] emit_c: fix escape code sequence for debug printf --- src/backend/c/emit_c_value.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 7baff121c..5aefab505 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -798,7 +798,8 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E if (strcmp(instr.set, "spirv.core") == 0) { switch (instr.opcode) { case SpvOpGroupNonUniformBroadcastFirst: { - CValue value = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, shd_first(instr.operands))); + assert(instr.operands.count == 2); + CValue value = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, instr.operands.nodes[1])); switch (emitter->config.dialect) { case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); default: break; @@ -1037,15 +1038,20 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case Instruction_DebugPrintf_TAG: { DebugPrintf payload = instruction->payload.debug_printf; shd_c_emit_mem(emitter, fn, payload.mem); - String args_list = shd_fmt_string_irarena(emitter->arena, "\"%s\"", instruction->payload.debug_printf.string); + Printer* args_printer = shd_new_printer_from_growy(shd_new_growy()); + shd_print(args_printer, "\""); + shd_printer_unescape(args_printer, instruction->payload.debug_printf.string); + shd_print(args_printer, "\""); for (size_t i = 0; i < instruction->payload.debug_printf.args.count; i++) { CValue str = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, instruction->payload.debug_printf.args.nodes[i])); - if (emitter->config.dialect == CDialect_ISPC && i > 0) - str = shd_format_string_arena(emitter->arena->arena, "extract(%s, printf_thread_index)", str); - - args_list = shd_format_string_arena(emitter->arena->arena, "%s, %s", args_list, str); + // special casing for the special child + if (emitter->config.dialect == CDialect_ISPC) + shd_print(args_printer, ", extract(%s, printf_thread_index)", str); + else + shd_print(args_printer, ", %s", str); } + String args_list = shd_printer_growy_unwrap(args_printer); switch (emitter->config.dialect) { case CDialect_ISPC:shd_print(p, "\nforeach_active(printf_thread_index) { print(%s); }", args_list); break; @@ -1055,6 +1061,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const case CDialect_GLSL: shd_warn_print("printf is not supported in GLSL"); break; } + free((char*) args_list); return empty_term(); } From 5abaaf60ca16235c60c3c182eca73953c0bfbb59 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 22 Oct 2024 14:07:25 +0200 Subject: [PATCH 689/693] turn slim's extended ops into a proper extinst using standard tooling --- include/shady/fe/slim.h | 11 --- src/frontend/slim/CMakeLists.txt | 3 + src/frontend/slim/bind.c | 30 +++++---- ...tinst.spv-shady-slim-frontend.grammar.json | 67 +++++++++++++++++++ src/frontend/slim/parser.c | 17 ++--- src/shady/api/CMakeLists.txt | 11 +++ 6 files changed, 106 insertions(+), 33 deletions(-) create mode 100644 src/frontend/slim/extinst.spv-shady-slim-frontend.grammar.json diff --git a/include/shady/fe/slim.h b/include/shady/fe/slim.h index 34502654e..f5dd20d37 100644 --- a/include/shady/fe/slim.h +++ b/include/shady/fe/slim.h @@ -4,17 +4,6 @@ #include "shady/ir/module.h" #include "shady/config.h" -typedef enum { - SlimOpDereference, - SlimOpAssign, - SlimOpAddrOf, - SlimOpSubscript, - SlimOpBindVal, - SlimOpBindVar, - SlimOpBindContinuations, - SlimOpUnbound, -} SlimFrontEndOpCodes; - typedef struct { bool front_end; } SlimParserConfig; diff --git a/src/frontend/slim/CMakeLists.txt b/src/frontend/slim/CMakeLists.txt index eb55eafc9..1ca8a23a1 100644 --- a/src/frontend/slim/CMakeLists.txt +++ b/src/frontend/slim/CMakeLists.txt @@ -3,3 +3,6 @@ target_link_libraries(slim_parser PUBLIC common api) target_link_libraries(slim_parser PRIVATE shady) target_include_directories(slim_parser PUBLIC $) target_link_libraries(shady PRIVATE "$") + +generate_extinst_headers(SlimFrontendOps extinst.spv-shady-slim-frontend.grammar.json) +target_link_libraries(slim_parser PRIVATE SlimFrontendOps) diff --git a/src/frontend/slim/bind.c b/src/frontend/slim/bind.c index a839205a2..c95557656 100644 --- a/src/frontend/slim/bind.c +++ b/src/frontend/slim/bind.c @@ -1,3 +1,5 @@ +#include "SlimFrontendOps.h" + #include "shady/pass.h" #include "shady/fe/slim.h" @@ -93,7 +95,7 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { case ExtInstr_TAG: { ExtInstr payload = node->payload.ext_instr; if (strcmp(payload.set, "shady.frontend") == 0) { - if (payload.opcode == SlimOpSubscript) { + if (payload.opcode == SlimFrontendOpsSlimSubscriptSHADY) { assert(payload.operands.count == 2); const Node* src_ptr = get_node_address_maybe(ctx, shd_first(payload.operands)); if (src_ptr == NULL) @@ -103,13 +105,13 @@ static const Node* get_node_address_maybe(Context* ctx, const Node* node) { .mem = shd_rewrite_node(r, payload.mem), .value = ptr_composite_element(a, (PtrCompositeElement) { .ptr = src_ptr, .index = index }), }); - } else if (payload.opcode == SlimOpDereference) { + } else if (payload.opcode == SlimFrontendOpsSlimDereferenceSHADY) { assert(payload.operands.count == 1); return mem_and_value(a, (MemAndValue) { .mem = shd_rewrite_node(r, payload.mem), .value = shd_rewrite_node(&ctx->rewriter, shd_first(payload.operands)), }); - } else if (payload.opcode == SlimOpUnbound) { + } else if (payload.opcode == SlimFrontendOpsSlimUnboundSHADY) { if (payload.mem) shd_rewrite_node(&ctx->rewriter, payload.mem); Resolved entry = resolve_using_name(ctx, shd_get_string_literal(a, shd_first(payload.operands))); @@ -138,7 +140,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { BodyBuilder* bb = instr.mem ? shd_bld_begin(a, shd_rewrite_node(r, instr.mem)) : shd_bld_begin_pure(a); switch (instr.opcode) { - case SlimOpBindVal: { + case SlimFrontendOpsSlimBindValSHADY: { size_t names_count = instr.operands.count - 1; const Node** names = &instr.operands.nodes[1]; const Node* value = shd_rewrite_node(r, shd_first(instr.operands)); @@ -150,7 +152,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { } break; } - case SlimOpBindVar: { + case SlimFrontendOpsSlimBindVarSHADY: { size_t names_count = (instr.operands.count - 1) / 2; const Node** names = &instr.operands.nodes[1]; const Node** types = &instr.operands.nodes[1 + names_count]; @@ -170,7 +172,7 @@ static const Node* desugar_bind_identifiers(Context* ctx, ExtInstr instr) { } break; } - case SlimOpBindContinuations: { + case SlimFrontendOpsSlimBindContinuationsSHADY: { size_t names_count = (instr.operands.count ) / 2; const Node** names = &instr.operands.nodes[0]; const Node** conts = &instr.operands.nodes[0 + names_count]; @@ -253,9 +255,9 @@ static bool is_used_as_value(Context* ctx, const Node* node) { for (;use;use = use->next_use) { if (use->operand_class != NcMem) { if (use->user->tag == ExtInstr_TAG && strcmp(use->user->payload.ext_instr.set, "shady.frontend") == 0) { - if (use->user->payload.ext_instr.opcode == SlimOpAssign && use->operand_index == 0) + if (use->user->payload.ext_instr.opcode == SlimFrontendOpsSlimAssignSHADY && use->operand_index == 0) continue; - if (use->user->payload.ext_instr.opcode == SlimOpSubscript && use->operand_index == 0) { + if (use->user->payload.ext_instr.opcode == SlimFrontendOpsSlimSubscriptSHADY && use->operand_index == 0) { const Node* ptr = get_node_address_maybe(ctx, node); if (ptr) continue; @@ -308,25 +310,25 @@ static const Node* bind_node(Context* ctx, const Node* node) { case ExtInstr_TAG: { ExtInstr payload = node->payload.ext_instr; if (strcmp("shady.frontend", payload.set) == 0) { - switch ((SlimFrontEndOpCodes) payload.opcode) { - case SlimOpDereference: + switch ((enum SlimFrontendOpsInstructions) payload.opcode) { + case SlimFrontendOpsSlimDereferenceSHADY: if (!is_used_as_value(ctx, node)) return shd_rewrite_node(r, payload.mem); return load(a, (Load) { .ptr = shd_rewrite_node(r, shd_first(payload.operands)), .mem = shd_rewrite_node(r, payload.mem), }); - case SlimOpAssign: { + case SlimFrontendOpsSlimAssignSHADY: { const Node* target_ptr = get_node_address(ctx, payload.operands.nodes[0]); assert(target_ptr); const Node* value = shd_rewrite_node(r, payload.operands.nodes[1]); return store(a, (Store) { .ptr = target_ptr, .value = value, .mem = shd_rewrite_node(r, payload.mem) }); } - case SlimOpAddrOf: { + case SlimFrontendOpsSlimAddrOfSHADY: { const Node* target_ptr = get_node_address(ctx, payload.operands.nodes[0]); return mem_and_value(a, (MemAndValue) { .value = target_ptr, .mem = shd_rewrite_node(r, payload.mem) }); } - case SlimOpSubscript: { + case SlimFrontendOpsSlimSubscriptSHADY: { const Node* ptr = get_node_address_maybe(ctx, node); if (ptr) return load(a, (Load) { @@ -341,7 +343,7 @@ static const Node* bind_node(Context* ctx, const Node* node) { .mem = shd_rewrite_node(r, payload.mem) } ); } - case SlimOpUnbound: { + case SlimFrontendOpsSlimUnboundSHADY: { const Node* mem = NULL; if (payload.mem) { if (!is_used_as_value(ctx, node)) diff --git a/src/frontend/slim/extinst.spv-shady-slim-frontend.grammar.json b/src/frontend/slim/extinst.spv-shady-slim-frontend.grammar.json new file mode 100644 index 000000000..bca5b1323 --- /dev/null +++ b/src/frontend/slim/extinst.spv-shady-slim-frontend.grammar.json @@ -0,0 +1,67 @@ +{ + "revision" : 1, + "instructions" : [ + { + "opname" : "SlimDereferenceSHADY", + "opcode" : 1, + "operands" : [ + { "kind" : "IdRef", "name" : "'Target'" } + ] + }, + { + "opname" : "SlimAssignSHADY", + "opcode" : 2, + "operands" : [ + { "kind" : "IdRef", "name" : "'Target'" }, + { "kind" : "IdRef", "name" : "'Value'" } + ] + }, + { + "opname" : "SlimAddrOfSHADY", + "opcode" : 3, + "operands" : [ + { "kind" : "IdRef", "name" : "'Target'" } + ] + }, + { + "opname" : "SlimSubscriptSHADY", + "opcode" : 4, + "operands" : [ + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Index'" } + ] + }, + { + "opname" : "SlimBindValSHADY", + "opcode" : 5, + "operands" : [ + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Names'", "quantifier" : "*" } + ] + }, + { + "opname" : "SlimBindVarSHADY", + "opcode" : 6, + "operands" : [ + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Names'", "quantifier" : "*" }, + { "kind" : "IdRef", "name" : "'Types'", "quantifier" : "*" } + ] + }, + { + "opname" : "SlimBindContinuationsSHADY", + "opcode" : 7, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Continuations'", "quantifier" : "*" } + ] + }, + { + "opname" : "SlimUnboundSHADY", + "opcode" : 8, + "operands" : [ + { "kind" : "IdRef", "name" : "'Identifier'" } + ] + } + ] +} diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index dfd2c721c..75064dbaa 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -1,5 +1,6 @@ #include "parser.h" #include "token.h" +#include "SlimFrontendOps.h" #include "shady/ir/ext.h" @@ -251,7 +252,7 @@ static const Node* make_unbound(IrArena* a, const Node* mem, String identifier) return ext_instr(a, (ExtInstr) { .mem = mem, .set = "shady.frontend", - .opcode = SlimOpUnbound, + .opcode = SlimFrontendOpsSlimUnboundSHADY, .result_t = unit_type(a), .operands = shd_singleton(string_lit_helper(a, identifier)), }); @@ -617,14 +618,14 @@ static const Node* accept_primary_expr(ctxparams, BodyBuilder* bb) { } else if (accept_token(ctx, star_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr, "expression"); - return shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimOpDereference, .operands = shd_singleton(expr), .mem = shd_bb_mem(bb) })); + return shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), .opcode = SlimFrontendOpsSlimDereferenceSHADY, .operands = shd_singleton(expr), .mem = shd_bb_mem(bb) })); } else if (accept_token(ctx, infix_and_tok)) { const Node* expr = accept_primary_expr(ctx, bb); expect(expr, "expression"); return shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", .result_t = unit_type(arena), - .opcode = SlimOpAddrOf, + .opcode = SlimFrontendOpsSlimAddrOfSHADY, .operands = shd_singleton(expr), .mem = shd_bb_mem(bb), })); @@ -655,7 +656,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) case InfixAss: { expr = shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", - .opcode = SlimOpAssign, + .opcode = SlimFrontendOpsSlimAssignSHADY, .result_t = unit_type(arena), .operands = shd_nodes(arena, 2, (const Node* []) { expr, rhs }), .mem = shd_bb_mem(bb), @@ -665,7 +666,7 @@ static const Node* accept_expr(ctxparams, BodyBuilder* bb, int outer_precedence) case InfixSbs: { expr = shd_bld_add_instruction(bb, ext_instr(arena, (ExtInstr) { .set = "shady.frontend", - .opcode = SlimOpSubscript, + .opcode = SlimFrontendOpsSlimSubscriptSHADY, .result_t = unit_type(arena), .operands = shd_nodes(arena, 2, (const Node* []) { expr, rhs }), .mem = shd_bb_mem(bb), @@ -859,13 +860,13 @@ static bool accept_statement(ctxparams, BodyBuilder* bb) { expect_identifiers(ctx, &ids); expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); - shd_bld_ext_instruction(bb, "shady.frontend", SlimOpBindVal, unit_type(arena), shd_nodes_prepend(arena, strings2nodes(arena, ids), instruction)); + shd_bld_ext_instruction(bb, "shady.frontend", SlimFrontendOpsSlimBindValSHADY, unit_type(arena), shd_nodes_prepend(arena, strings2nodes(arena, ids), instruction)); } else if (accept_token(ctx, var_tok)) { Nodes types; expect_types_and_identifiers(ctx, &ids, &types); expect(accept_token(ctx, equal_tok), "'='"); const Node* instruction = accept_instruction(ctx, bb); - shd_bld_ext_instruction(bb, "shady.frontend", SlimOpBindVar, unit_type(arena), shd_nodes_prepend(arena, shd_concat_nodes(arena, strings2nodes(arena, ids), types), instruction)); + shd_bld_ext_instruction(bb, "shady.frontend", SlimFrontendOpsSlimBindVarSHADY, unit_type(arena), shd_nodes_prepend(arena, shd_concat_nodes(arena, strings2nodes(arena, ids), types), instruction)); } else { const Node* instr = accept_instruction(ctx, bb); if (!instr) return false; @@ -1047,7 +1048,7 @@ static const Node* expect_body(ctxparams, const Node* mem, const Node* default_t } } - shd_bld_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimOpBindContinuations, unit_type(arena), shd_concat_nodes(arena, ids, conts)); + shd_bld_ext_instruction(cont_wrapper_bb, "shady.frontend", SlimFrontendOpsSlimBindContinuationsSHADY, unit_type(arena), shd_concat_nodes(arena, ids, conts)); expect(accept_token(ctx, rbracket_tok), "']'"); shd_set_abstraction_body(cont_wrapper_case, shd_bld_jump(cont_wrapper_bb, terminator_case, shd_empty(arena))); diff --git a/src/shady/api/CMakeLists.txt b/src/shady/api/CMakeLists.txt index d63fefe47..ed82a1e99 100644 --- a/src/shady/api/CMakeLists.txt +++ b/src/shady/api/CMakeLists.txt @@ -18,3 +18,14 @@ add_dependencies(api INTERFACE generate-type-headers) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/type_generated.h DESTINATION include) install(TARGETS api EXPORT shady_export_set) + +find_package(Python COMPONENTS Interpreter REQUIRED) +function(generate_extinst_headers NAME SRC) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.h COMMAND ${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/SPIRV-Headers/tools/buildHeaders/bin/generate_language_headers.py --extinst-name=${NAME} --extinst-grammar=${CMAKE_CURRENT_SOURCE_DIR}/${SRC} --extinst-output-base=${NAME} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${SRC} VERBATIM) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${NAME}.h PROPERTIES GENERATED TRUE) + add_custom_target("${NAME}_h" DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.h) + + add_library(${NAME} INTERFACE) + add_dependencies(${NAME} "${NAME}_h") + target_include_directories(${NAME} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) +endfunction() From f034ee155f7c7e5d72be97bfb2e3bd7a289708d0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 26 Oct 2024 23:11:07 +0200 Subject: [PATCH 690/693] ispc: add workarround to broadcast ptrs --- src/backend/c/emit_c_value.c | 24 ++++++++++++++++-------- src/backend/c/runtime.ispc | 4 ++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/backend/c/emit_c_value.c b/src/backend/c/emit_c_value.c index 5aefab505..ea44c22c1 100644 --- a/src/backend/c/emit_c_value.c +++ b/src/backend/c/emit_c_value.c @@ -429,6 +429,18 @@ static String index_into_array(Emitter* emitter, const Type* arr_type, CTerm exp return shd_format_string_arena(arena->arena, "(%s.arr[%s])", shd_c_deref(emitter, expr), index2); } +static CTerm broadcast_first(Emitter* emitter, CValue value, const Type* value_type) { + switch (emitter->config.dialect) { + case CDialect_ISPC: { + const Type* t = shd_get_unqualified_type(value_type); + if (t->tag == PtrType_TAG) + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract_ptr(%s, count_trailing_zeros(lanemask()))", value)); + return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); + } + default: shd_error("TODO"); + } +} + static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node* node) { assert(node->tag == PrimOp_TAG); IrArena* arena = emitter->arena; @@ -697,8 +709,8 @@ static CTerm emit_primop(Emitter* emitter, FnEmitter* fn, Printer* p, const Node } case subgroup_assume_uniform_op: { if (emitter->config.dialect == CDialect_ISPC) { - CTerm value = shd_c_emit_value(emitter, fn, prim_op->operands.nodes[0]); - return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); break; + CValue value = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, prim_op->operands.nodes[0])); + return broadcast_first(emitter, value, prim_op->operands.nodes[0]->type); } return shd_c_emit_value(emitter, fn, prim_op->operands.nodes[0]); } @@ -800,11 +812,7 @@ static CTerm emit_ext_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, E case SpvOpGroupNonUniformBroadcastFirst: { assert(instr.operands.count == 2); CValue value = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, instr.operands.nodes[1])); - switch (emitter->config.dialect) { - case CDialect_ISPC: return term_from_cvalue(shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", value)); - default: break; - } - break; + return broadcast_first(emitter, value, instr.operands.nodes[1]->type); } case SpvOpGroupNonUniformElect: { assert(instr.operands.count == 1); @@ -1018,7 +1026,7 @@ static CTerm emit_instruction(Emitter* emitter, FnEmitter* fn, Printer* p, const CValue cvalue = shd_c_to_ssa(emitter, shd_c_emit_value(emitter, fn, payload.value)); // ISPC lets you broadcast to a uniform address space iff the address is non-uniform, otherwise we need to do this if (emitter->config.dialect == CDialect_ISPC && addr_uniform && shd_is_addr_space_uniform(a, addr_type->payload.ptr_type.address_space) && !value_uniform) - cvalue = shd_format_string_arena(emitter->arena->arena, "extract(%s, count_trailing_zeros(lanemask()))", cvalue); + cvalue = shd_format_string_arena(emitter->arena->arena, "extract_ptr(%s, count_trailing_zeros(lanemask()))", cvalue); shd_print(p, "\n%s = %s;", dereferenced, cvalue); return empty_term(); diff --git a/src/backend/c/runtime.ispc b/src/backend/c/runtime.ispc index e69de29bb..cd6b3cba9 100644 --- a/src/backend/c/runtime.ispc +++ b/src/backend/c/runtime.ispc @@ -0,0 +1,4 @@ +template +T uniform* uniform extract_ptr(uniform T* varying t, uniform int i) { + return (uniform T* uniform) extract((intptr_t) t, i); +} From 7a339c9e2c70e591540d1a9a7e45bf7153a55566 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 27 Oct 2024 08:06:29 +0100 Subject: [PATCH 691/693] updated SPIRV-Headers --- .gitmodules | 4 +--- SPIRV-Headers | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0c1f5d5f4..e24b50ab0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,4 @@ -[submodule "murmur3"] - path = murmur3 - url = https://github.com/PeterScott/murmur3 [submodule "SPIRV-Headers"] path = SPIRV-Headers url = https://github.com/shady-gang/SPIRV-Headers.git + branch = main diff --git a/SPIRV-Headers b/SPIRV-Headers index 1c9115b56..22c4d1b1e 160000 --- a/SPIRV-Headers +++ b/SPIRV-Headers @@ -1 +1 @@ -Subproject commit 1c9115b562bab79ee2160fbd845f41b815b9f21f +Subproject commit 22c4d1b1e9d1c7d9aa5086c93e6491f21080019b From 57dca391b94e3f965005dbeef941da9eabd08a64 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 27 Oct 2024 11:17:24 +0100 Subject: [PATCH 692/693] added draft support for SPV_SHADY_indirect_tail_calls --- SPIRV-Headers | 2 +- src/backend/spirv/emit_spv_control_flow.c | 12 ++++++++++- src/backend/spirv/emit_spv_value.c | 26 ++++++++++++++++------- src/backend/spirv/spirv_builder.c | 16 ++++++++++++++ src/backend/spirv/spirv_builder.h | 2 ++ 5 files changed, 48 insertions(+), 10 deletions(-) diff --git a/SPIRV-Headers b/SPIRV-Headers index 22c4d1b1e..1453552cf 160000 --- a/SPIRV-Headers +++ b/SPIRV-Headers @@ -1 +1 @@ -Subproject commit 22c4d1b1e9d1c7d9aa5086c93e6491f21080019b +Subproject commit 1453552cfe66d4aaf58d083372e6bf81f715e4a8 diff --git a/src/backend/spirv/emit_spv_control_flow.c b/src/backend/spirv/emit_spv_control_flow.c index 46161b47e..9b943ccbd 100644 --- a/src/backend/spirv/emit_spv_control_flow.c +++ b/src/backend/spirv/emit_spv_control_flow.c @@ -252,7 +252,17 @@ void spv_emit_terminator(Emitter* emitter, FnBuilder* fn_builder, BBBuilder basi return; } case Terminator_Control_TAG: - case TailCall_TAG: + case TailCall_TAG: { + TailCall payload = terminator->payload.tail_call; + spv_emit_mem(emitter, fn_builder, payload.mem); + LARRAY(SpvId, args, payload.args.count + 1); + args[0] = spv_emit_value(emitter, fn_builder, payload.callee); + for (size_t i = 0; i < payload.args.count; i++) + args[i + 1] = spv_emit_value(emitter, fn_builder, payload.args.nodes[i]); + spvb_capability(emitter->file_builder, SpvCapabilityIndirectTailCallsSHADY); + spvb_terminator(basic_block_builder, SpvOpIndirectTailCallSHADY, payload.args.count + 1, args); + return; + } case Join_TAG: shd_error("Lower me"); case NotATerminator: shd_error("TODO: emit terminator %s", shd_get_node_tag_string(terminator->tag)); } diff --git a/src/backend/spirv/emit_spv_value.c b/src/backend/spirv/emit_spv_value.c index fc787f514..28dabb7c5 100644 --- a/src/backend/spirv/emit_spv_value.c +++ b/src/backend/spirv/emit_spv_value.c @@ -337,21 +337,27 @@ static SpvId emit_ext_instr(Emitter* emitter, FnBuilder* fn_builder, BBBuilder b return spvb_ext_instruction(bb_builder, spv_emit_type(emitter, instr.result_t), set_id, instr.opcode, instr.operands.count, ops); } -static SpvId emit_leaf_call(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Call call) { +static SpvId emit_fn_call(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, Call call) { spv_emit_mem(emitter, fn_builder, call.mem); - const Node* fn = call.callee; - assert(fn->tag == FnAddr_TAG); - fn = fn->payload.fn_addr.fn; - SpvId callee = spv_emit_decl(emitter, fn); + const Node* fn = call.callee; const Type* callee_type = fn->type; assert(callee_type->tag == FnType_TAG); Nodes return_types = callee_type->payload.fn_type.return_types; SpvId return_type = spv_types_to_codom(emitter, return_types); + LARRAY(SpvId, args, call.args.count); for (size_t i = 0; i < call.args.count; i++) args[i] = spv_emit_value(emitter, fn_builder, call.args.nodes[i]); - return spvb_call(bb_builder, return_type, callee, call.args.count, args); + + if (fn->tag == FnAddr_TAG) { + fn = fn->payload.fn_addr.fn; + SpvId callee = spv_emit_decl(emitter, fn); + return spvb_call(bb_builder, return_type, callee, call.args.count, args); + } else { + spvb_capability(emitter->file_builder, SpvCapabilityFunctionPointersINTEL); + return spvb_op(bb_builder, SpvOpFunctionPointerCallINTEL, return_type, call.args.count, args); + } } static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBuilder bb_builder, const Node* instruction) { @@ -368,7 +374,7 @@ static SpvId spv_emit_instruction(Emitter* emitter, FnBuilder* fn_builder, BBBui case Instruction_FillBytes_TAG: case Instruction_StackAlloc_TAG: shd_error("Should be lowered elsewhere") case Instruction_ExtInstr_TAG: return emit_ext_instr(emitter, fn_builder, bb_builder, instruction->payload.ext_instr); - case Instruction_Call_TAG: return emit_leaf_call(emitter, fn_builder, bb_builder, instruction->payload.call); + case Instruction_Call_TAG: return emit_fn_call(emitter, fn_builder, bb_builder, instruction->payload.call); case PrimOp_TAG: return emit_primop(emitter, fn_builder, bb_builder, instruction); case Comment_TAG: { spv_emit_mem(emitter, fn_builder, instruction->payload.comment.mem); @@ -466,7 +472,11 @@ static SpvId spv_emit_value_(Emitter* emitter, FnBuilder* fn_builder, BBBuilder case Param_TAG: shd_error("tried to emit a param: all params should be emitted by their binding abstraction !"); case Value_ConstrainedValue_TAG: case Value_UntypedNumber_TAG: - case Value_FnAddr_TAG: shd_error("Should be lowered away earlier!"); + case Value_FnAddr_TAG: { + spvb_capability(emitter->file_builder, SpvCapabilityInModuleFunctionAddressSHADY); + SpvId fn = spv_emit_decl(emitter, node->payload.fn_addr.fn); + return spvb_constant_op(emitter->file_builder, spv_emit_type(emitter, node->type), SpvOpConstantFunctionPointerINTEL, 1, &fn); + } case IntLiteral_TAG: { new = spvb_fresh_id(emitter->file_builder); SpvId ty = spv_emit_type(emitter, node->type); diff --git a/src/backend/spirv/spirv_builder.c b/src/backend/spirv/spirv_builder.c index a7ee26f78..d1ff6a051 100644 --- a/src/backend/spirv/spirv_builder.c +++ b/src/backend/spirv/spirv_builder.c @@ -479,6 +479,16 @@ SpvId spvb_global_variable(SpvbFileBuilder* file_builder, SpvId id, SpvId type, return id; } +SpvId spvb_constant_op(SpvbFileBuilder* file_builder, SpvId type, SpvOp op, size_t operands_count, SpvId operands[]) { + op(op, 3 + operands_count); + SpvId id = spvb_fresh_id(file_builder); + ref_id(type); + ref_id(id); + for (size_t i = 0; i < operands_count; i++) + literal_int(operands[i]); + return id; +} + SpvId spvb_undef(SpvbFileBuilder* file_builder, SpvId type) { op(SpvOpUndef, 3); ref_id(type); @@ -942,4 +952,10 @@ void spvb_unreachable(SpvbBasicBlockBuilder* bb_builder) { op(SpvOpUnreachable, 1); } +void spvb_terminator(SpvbBasicBlockBuilder* bb_builder, SpvOp op, size_t operands_count, SpvId operands[]) { + op(op, 1 + operands_count); + for (size_t i = 0; i < operands_count; i++) + ref_id(operands[i]); +} + #undef target_data diff --git a/src/backend/spirv/spirv_builder.h b/src/backend/spirv/spirv_builder.h index 69de36ed5..7d8bee7c3 100644 --- a/src/backend/spirv/spirv_builder.h +++ b/src/backend/spirv/spirv_builder.h @@ -63,6 +63,7 @@ void spvb_constant(SpvbFileBuilder*, SpvId result, SpvId type, size_t bit_patter SpvId spvb_constant_composite(SpvbFileBuilder*, SpvId type, size_t ops_count, SpvId ops[]); SpvId spvb_constant_null(SpvbFileBuilder*, SpvId type); SpvId spvb_global_variable(SpvbFileBuilder*, SpvId id, SpvId type, SpvStorageClass storage_class, bool has_initializer, SpvId initializer); +SpvId spvb_constant_op(SpvbFileBuilder*, SpvId type, SpvOp, size_t operands_count, SpvId operands[]); // Function building stuff SpvbFnBuilder* spvb_begin_fn(SpvbFileBuilder*, SpvId fn_id, SpvId fn_type, SpvId fn_ret_type); @@ -113,5 +114,6 @@ SpvId spvb_ext_instruction(SpvbBasicBlockBuilder*, SpvId return_type, SpvId set, void spvb_return_void(SpvbBasicBlockBuilder*) ; void spvb_return_value(SpvbBasicBlockBuilder*, SpvId value); void spvb_unreachable(SpvbBasicBlockBuilder*); +void spvb_terminator(SpvbBasicBlockBuilder*, SpvOp, size_t operands_count, SpvId operands[]); #endif From 2554b70577b377bc664993dbae9e06985a898f56 Mon Sep 17 00:00:00 2001 From: Gobrosse Date: Sun, 27 Oct 2024 11:18:32 +0100 Subject: [PATCH 693/693] slim: added a 'tailcall' token --- src/frontend/slim/parser.c | 28 ++++++++++++++++++++++++++++ src/frontend/slim/token.h | 1 + 2 files changed, 29 insertions(+) diff --git a/src/frontend/slim/parser.c b/src/frontend/slim/parser.c index 75064dbaa..ae5af81a0 100644 --- a/src/frontend/slim/parser.c +++ b/src/frontend/slim/parser.c @@ -797,6 +797,22 @@ static const Node* accept_control_flow_instruction(ctxparams, BodyBuilder* bb) { static const Node* accept_instruction(ctxparams, BodyBuilder* bb) { const Node* instr = accept_expr(ctx, bb, max_precedence()); + switch(shd_curr_token(tokenizer).tag) { + case call_tok: { + shd_next_token(tokenizer); + expect(accept_token(ctx, lpar_tok), "'('"); + const Node* callee = accept_operand(ctx, bb); + expect(accept_token(ctx, rpar_tok), "')'"); + Nodes args = expect_operands(ctx, bb); + return call(arena, (Call) { + .callee = callee, + .args = args, + .mem = shd_bb_mem(bb) + }); + } + default: break; + } + if (instr) expect(accept_token(ctx, semi_tok), "';'"); @@ -992,6 +1008,18 @@ static const Node* accept_terminator(ctxparams, BodyBuilder* bb) { .mem = shd_bb_mem(bb) }); } + case tailcall_tok: { + shd_next_token(tokenizer); + expect(accept_token(ctx, lpar_tok), "'('"); + const Node* callee = accept_operand(ctx, bb); + expect(accept_token(ctx, rpar_tok), "')'"); + Nodes args = expect_operands(ctx, bb); + return tail_call(arena, (TailCall) { + .callee = callee, + .args = args, + .mem = shd_bb_mem(bb) + }); + } case unreachable_tok: { shd_next_token(tokenizer); expect(accept_token(ctx, lpar_tok), "'('"); diff --git a/src/frontend/slim/token.h b/src/frontend/slim/token.h index 12e161642..b53d9e348 100644 --- a/src/frontend/slim/token.h +++ b/src/frontend/slim/token.h @@ -67,6 +67,7 @@ TOKEN(case, "case") \ TOKEN(default, "default") \ TEXT_TOKEN(join) \ TEXT_TOKEN(call) \ +TEXT_TOKEN(tailcall) \ TOKEN(return, "return") \ TEXT_TOKEN(unreachable) \ TOKEN(infix_rshift_logical, ">>>") \