From fe3cac7ac3d9e7977f6d191c7f08ccf921077f99 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 12 May 2025 11:56:57 -0700 Subject: [PATCH] parameterize irtree generation path with identifier resolution rules; in most cases, we want the usual order: implicit accesses -> locals -> registers -> globals/tlocals/types/procedures -> macros; but if we are specifically evaluating a call expression tree, we want to prefer callables - in this case, macros should be prioritized. --- project.4coder | 9 +- src/eval/eval_core.c | 12 +- src/eval/eval_ir.c | 883 +++++++++--------- src/eval/eval_ir.h | 74 +- src/eval/eval_types.c | 2 +- src/mule/mule_main.cpp | 8 +- .../opengl/generated/render_opengl.meta.c | 76 +- .../opengl/generated/render_opengl.meta.h | 552 +++++------ 8 files changed, 863 insertions(+), 753 deletions(-) diff --git a/project.4coder b/project.4coder index 275657ca..22f59d81 100644 --- a/project.4coder +++ b/project.4coder @@ -46,7 +46,7 @@ load_paths = commands = { //- rjf: [raddbg] - // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [textperf] // .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta telemetry textperf && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, @@ -54,13 +54,10 @@ commands = //- rjf: [tester] // .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta tester", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - //- rjf: [ryan_scratch] - .f1 = { .win = "raddbg_stable --ipc kill_all && wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - //- rjf: running target - // .f3 = { .win = "raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f3 = { .win = "raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f3 = { .win = "C:/devel/raddebugger/build/raddbg.exe --capture --user:C:/devel/raddebugger/build/local_dev.raddbg_user --project:C:/devel/raddebugger/build/local_dev.raddbg_project", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - .f3 = { .win = "wsl_launch /mnt/c/devel/raddebugger/build/raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + // .f3 = { .win = "wsl_launch /mnt/c/devel/raddebugger/build/raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: local target builds .build_raddbg = { .win = "build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/src/eval/eval_core.c b/src/eval/eval_core.c index 61e90d0d..1a5d11cf 100644 --- a/src/eval/eval_core.c +++ b/src/eval/eval_core.c @@ -849,7 +849,7 @@ e_irtree_from_bundle(E_CacheBundle *bundle) bundle->flags |= E_CacheBundleFlag_IRTree; E_IRTreeAndType parent = e_irtree_from_key(bundle->parent_key); E_Parse parse = e_parse_from_bundle(bundle); - bundle->irtree = e_push_irtree_and_type_from_expr(e_cache->arena, &parent, 0, 0, parse.expr); + bundle->irtree = e_push_irtree_and_type_from_expr(e_cache->arena, &parent, &e_default_identifier_resolution_rule, 0, 0, parse.expr); E_MsgList msgs_copy = e_msg_list_copy(e_cache->arena, &bundle->irtree.msgs); e_msg_list_concat_in_place(&bundle->msgs, &msgs_copy); } @@ -1243,8 +1243,12 @@ e_range_size_from_eval(E_Eval eval) Temp scratch = scratch_begin(0, 0); U64 element_size = e_type_byte_size_from_key(e_type_key_unwrap(type_core, E_TypeUnwrapFlag_All)); E_TypeExpandInfo expand_info = expand_rule->info(scratch.arena, eval, str8_zero()); - result = expand_info.expr_count * element_size; - got_size = 1; + U64 new_result_maybe = expand_info.expr_count * element_size; + if(new_result_maybe != 0) + { + result = new_result_maybe; + got_size = 1; + } scratch_end(scratch); } } @@ -1332,7 +1336,7 @@ e_debug_log_from_expr_string(Arena *arena, String8 string) } //- rjf: type - E_IRTreeAndType irtree = e_push_irtree_and_type_from_expr(scratch.arena, 0, 0, 0, parse.expr); + E_IRTreeAndType irtree = e_push_irtree_and_type_from_expr(scratch.arena, 0, &e_default_identifier_resolution_rule, 0, 0, parse.expr); { str8_list_pushf(scratch.arena, &strings, " type:\n"); S32 indent = 2; diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 4f3104c3..9ec5976c 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -497,7 +497,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) E_Expr *exprl = expr->first; E_Expr *exprr = exprl->next; E_IRTreeAndType l = *lhs_irtree; - E_IRTreeAndType r = e_push_irtree_and_type_from_expr(arena, overridden, 0, 1, exprr); + E_IRTreeAndType r = e_push_irtree_and_type_from_expr(arena, overridden, &e_default_identifier_resolution_rule, 0, 1, exprr); e_msg_list_concat_in_place(&result.msgs, &r.msgs); E_TypeKey l_restype = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKey r_restype = e_type_key_unwrap(r.type_key, E_TypeUnwrapFlag_AllDecorative); @@ -588,7 +588,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) } internal E_IRTreeAndType -e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr) +e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_IdentifierResolutionRule *identifier_resolution_rule, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); @@ -632,7 +632,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 { // rjf: unpack left-hand-side E_Expr *lhs = expr->first; - E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, parent, 0, 1, lhs); + E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, 0, 1, lhs); e_msg_list_concat_in_place(&result.msgs, &lhs_irtree.msgs); // rjf: try all IR trees in chain @@ -715,7 +715,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 String8 full_qualified_name = str8_list_join(scratch.arena, &parts, &(StringJoin){.sep = str8_lit(".")}); E_Expr *leaf_expr_name = e_push_expr(scratch.arena, E_ExprKind_LeafIdentifier, r1u64(0, 0)); leaf_expr_name->string = full_qualified_name; - result = e_push_irtree_and_type_from_expr(arena, root_parent, disallow_autohooks, disallow_autohooks, leaf_expr_name); + result = e_push_irtree_and_type_from_expr(arena, root_parent, &e_default_identifier_resolution_rule, disallow_autohooks, disallow_autohooks, leaf_expr_name); } } }break; @@ -725,7 +725,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 { // rjf: unpack operand E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, r_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); @@ -784,7 +784,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 { // rjf: unpack operand E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, r_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = r_tree.type_key; E_TypeKey r_type_unwrapped = e_type_key_unwrap(r_type, E_TypeUnwrapFlag_AllDecorative); @@ -812,12 +812,12 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 // rjf: unpack operands E_Expr *cast_type_expr = expr->first; E_Expr *casted_expr = cast_type_expr->next; - E_IRTreeAndType cast_irtree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, cast_type_expr); + E_IRTreeAndType cast_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, cast_type_expr); e_msg_list_concat_in_place(&result.msgs, &cast_irtree.msgs); E_TypeKey cast_type = cast_irtree.type_key; E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type); U64 cast_type_byte_size = e_type_byte_size_from_key(cast_type); - E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, casted_expr); + E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, casted_expr); e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs); E_TypeKey casted_type = e_type_key_unwrap(casted_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind casted_type_kind = e_type_kind_from_key(casted_type); @@ -872,7 +872,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 E_Expr *r_expr = expr->first; E_TypeKey r_type = zero_struct; E_Space space = r_expr->space; - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, 1, 1, r_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, 1, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); r_type = r_tree.type_key; @@ -900,7 +900,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 { // rjf: evaluate operand tree E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, 1, 1, r_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, 1, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); // rjf: fill output @@ -914,7 +914,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 { // rjf: unpack operand E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, r_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); @@ -942,14 +942,14 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 //- rjf: unary operations case E_ExprKind_Pos: { - result = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, expr->first); + result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); }break; case E_ExprKind_Neg: case E_ExprKind_BitNot: { // rjf: unpack operand E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, r_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); @@ -982,7 +982,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 { // rjf: unpack operand E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, r_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); @@ -1037,8 +1037,8 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 B32 is_comparison = e_expr_kind_is_comparison(kind); E_Expr *l_expr = expr->first; E_Expr *r_expr = l_expr->next; - E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, l_expr); - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, r_expr); + E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, l_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey l_type = e_type_key_unwrap(l_tree.type_key, E_TypeUnwrapFlag_AllDecorative); @@ -1279,9 +1279,9 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 E_Expr *c_expr = expr->first; E_Expr *l_expr = c_expr->next; E_Expr *r_expr = l_expr->next; - E_IRTreeAndType c_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, c_expr); - E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, l_expr); - E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, r_expr); + E_IRTreeAndType c_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, c_expr); + E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, l_expr); + E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &c_tree.msgs); e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); @@ -1350,7 +1350,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 { B32 strip_lenses = 0; E_Expr *lhs = expr->first; - E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, lhs); + E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_callable_identifier_resolution_rule, disallow_autohooks, 1, lhs); e_msg_list_concat_in_place(&result.msgs, &lhs_irtree.msgs); E_TypeKey lhs_type_key = lhs_irtree.type_key; E_Type *lhs_type = e_type_from_key(lhs_type_key); @@ -1358,7 +1358,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 // rjf: calling a type? -> treat as a cast of that type if(lhs_irtree.mode == E_Mode_Null && lhs_type != &e_type_nil && lhs_type->kind != E_TypeKind_Lens && lhs_type->kind != E_TypeKind_LensSpec) { - E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, expr->first->next); + E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first->next); e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs); E_TypeKey cast_type = lhs_irtree.type_key; E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type); @@ -1430,7 +1430,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 strip_lenses = 1; disallow_autohooks = 1; } - result = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, call); + result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, call); // NOTE(rjf): we do not want to accumulate messages from the original left-hand-side evaluation in this case, because // this path only occurs if the member access fails specifically. } @@ -1448,7 +1448,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 } // rjf: generate result via first argument to lens - result = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, lhs->next); + result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, lhs->next); // rjf: if not raw, wrap resultant type with lens type if(!strip_lenses) @@ -1576,448 +1576,479 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 String8 qualifier = expr->qualifier; String8 string = expr->string; String8 string__redirected = string; + String8List namespaceified_strings = {0}; B32 string_mapped = 0; + B32 string_is_implicit_member_name = 0; E_TypeKey mapped_type_key = zero_struct; E_Module *mapped_location_block_module = &e_module_nil; RDI_LocationBlock *mapped_location_block = 0; E_Mode mapped_bytecode_mode = E_Mode_Offset; E_Space mapped_bytecode_space = zero_struct; String8 mapped_bytecode = {0}; + B32 generated = 0; - //- rjf: try to map name as parent expression signifier ('$') - if(qualifier.size == 0 && !string_mapped && str8_match(string, str8_lit("$"), 0) && parent != 0 && (parent->root != &e_irnode_nil || parent->msgs.first != 0)) + //- rjf: iterate identifier resolution rule paths, try to resolve + // identifier in that order. + for(U64 path_idx = 0; !generated && path_idx < identifier_resolution_rule->count; path_idx += 1) { - E_IRTreeAndType *parent_irtree = parent; - if(disallow_autohooks) + //- rjf: try to map identifier via this path + E_IdentifierResolutionPath path = identifier_resolution_rule->paths[path_idx]; + switch(path) { - for(E_IRTreeAndType *prev = parent_irtree->prev; prev != 0; prev = prev->prev) - { - parent_irtree = prev; - } - } - E_OpList oplist = e_oplist_from_irtree(arena, parent_irtree->root); - string_mapped = 1; - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = parent_irtree->mode; - mapped_type_key = parent_irtree->type_key; - disallow_autohooks = 1; - E_MsgList msgs = e_msg_list_copy(arena, &parent_irtree->msgs); - e_msg_list_concat_in_place(&result.msgs, &msgs); - } - - //- rjf: try to map name as implicit access of overridden expression ('$.member_name', where the $. prefix is omitted) - if(qualifier.size == 0 && !string_mapped && parent != 0 && parent->root != &e_irnode_nil) - { - for(E_IRTreeAndType *prev = parent; prev != 0; prev = prev->prev) - { - E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, prev, string); - E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, prev, disallow_autohooks, 1, access); - if(access_irtree.root != &e_irnode_nil) - { - string_mapped = 1; - E_OpList oplist = e_oplist_from_irtree(scratch.arena, access_irtree.root); - mapped_type_key = access_irtree.type_key; - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = access_irtree.mode; - e_msg_list_concat_in_place(&result.msgs, &access_irtree.msgs); - break; - } - } - } - - //- rjf: try to map name as member of `this` - if found, string__redirected := "this", and turn - // on later implicit-member-lookup generation - B32 string_is_implicit_member_name = 0; - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("member"), 0))) - { - E_Module *module = e_base_ctx->primary_module; - U32 module_idx = (U32)(module - e_base_ctx->modules); - RDI_Parsed *rdi = module->rdi; - RDI_Procedure *procedure = e_cache->thread_ip_procedure; - RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure); - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); - E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module_idx); - E_Member member = e_type_member_from_key_name__cached(container_type_key, string); - if(member.kind != E_MemberKind_Null) - { - string_is_implicit_member_name = 1; - string__redirected = str8_lit("this"); - } - } - - //- rjf: try locals - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("local"), 0))) - { - E_Module *module = e_base_ctx->primary_module; - U32 module_idx = (U32)(module - e_base_ctx->modules); - RDI_Parsed *rdi = module->rdi; - U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string__redirected); - if(local_num != 0) - { - RDI_Local *local = rdi_element_from_name_idx(rdi, Locals, local_num-1); + default:{}break; - // rjf: extract local's type key - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, local->type_idx); - mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module_idx); - - // rjf: extract local's location block - U64 ip_voff = e_base_ctx->thread_ip_voff; - for(U32 loc_block_idx = local->location_first; - loc_block_idx < local->location_opl; - loc_block_idx += 1) + //- rjf: try to map name as parent expression signifier ('$') + case E_IdentifierResolutionPath_ParentExpr: + if(qualifier.size == 0 && !string_mapped && str8_match(string, str8_lit("$"), 0) && parent != 0 && (parent->root != &e_irnode_nil || parent->msgs.first != 0)) { - RDI_LocationBlock *block = rdi_element_from_name_idx(rdi, LocationBlocks, loc_block_idx); - if(block->scope_off_first <= ip_voff && ip_voff < block->scope_off_opl) + E_IRTreeAndType *parent_irtree = parent; + if(disallow_autohooks) { - mapped_location_block_module = module; - mapped_location_block = block; - } - } - } - } - - //- rjf: mapped to location block -> extract or produce bytecode for this mapping - if(mapped_location_block != 0) - { - E_Module *module = mapped_location_block_module; - E_Space space = module->space; - Arch arch = module->arch; - RDI_Parsed *rdi = module->rdi; - RDI_LocationBlock *block = mapped_location_block; - U64 all_location_data_size = 0; - U8 *all_location_data = rdi_table_from_name(rdi, LocationData, &all_location_data_size); - if(block->location_data_off + sizeof(RDI_LocationKind) <= all_location_data_size) - { - RDI_LocationKind loc_kind = *((RDI_LocationKind *)(all_location_data + block->location_data_off)); - switch(loc_kind) - { - default:{}break; - case RDI_LocationKind_ValBytecodeStream: {mapped_bytecode_mode = E_Mode_Value;}goto bytecode_stream; - case RDI_LocationKind_AddrBytecodeStream:{mapped_bytecode_mode = E_Mode_Offset;}goto bytecode_stream; - bytecode_stream:; - { - string_mapped = 1; - U64 bytecode_size = 0; - U64 off_first = block->location_data_off + sizeof(RDI_LocationKind); - U64 off_opl = all_location_data_size; - for(U64 off = off_first, next_off = off_opl; - off < all_location_data_size; - off = next_off) + for(E_IRTreeAndType *prev = parent_irtree->prev; prev != 0; prev = prev->prev) { - next_off = off_opl; - U8 op = all_location_data[off]; - if(op == 0) + parent_irtree = prev; + } + } + E_OpList oplist = e_oplist_from_irtree(arena, parent_irtree->root); + string_mapped = 1; + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = parent_irtree->mode; + mapped_type_key = parent_irtree->type_key; + disallow_autohooks = 1; + E_MsgList msgs = e_msg_list_copy(arena, &parent_irtree->msgs); + e_msg_list_concat_in_place(&result.msgs, &msgs); + } + break; + + //- rjf: try to map name as implicit access of overridden expression ('$.member_name', where the $. prefix is omitted) + case E_IdentifierResolutionPath_ParentExprMember: + if(qualifier.size == 0 && !string_mapped && parent != 0 && parent->root != &e_irnode_nil) + { + for(E_IRTreeAndType *prev = parent; prev != 0; prev = prev->prev) + { + E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, prev, string); + E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, prev, &e_default_identifier_resolution_rule, disallow_autohooks, 1, access); + if(access_irtree.root != &e_irnode_nil) + { + string_mapped = 1; + E_OpList oplist = e_oplist_from_irtree(scratch.arena, access_irtree.root); + mapped_type_key = access_irtree.type_key; + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = access_irtree.mode; + e_msg_list_concat_in_place(&result.msgs, &access_irtree.msgs); + break; + } + } + }break; + + //- rjf: try to map name as member of `this` - if found, string__redirected := "this", and turn + // on later implicit-member-lookup generation + case E_IdentifierResolutionPath_ImplicitThisMember: + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("member"), 0))) + { + E_Module *module = e_base_ctx->primary_module; + U32 module_idx = (U32)(module - e_base_ctx->modules); + RDI_Parsed *rdi = module->rdi; + RDI_Procedure *procedure = e_cache->thread_ip_procedure; + RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); + E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module_idx); + E_Member member = e_type_member_from_key_name__cached(container_type_key, string); + if(member.kind != E_MemberKind_Null) + { + string_is_implicit_member_name = 1; + string__redirected = str8_lit("this"); + } + }break; + + //- rjf: try locals + case E_IdentifierResolutionPath_Local: + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("local"), 0))) + { + E_Module *module = e_base_ctx->primary_module; + U32 module_idx = (U32)(module - e_base_ctx->modules); + RDI_Parsed *rdi = module->rdi; + U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string__redirected); + if(local_num != 0) + { + RDI_Local *local = rdi_element_from_name_idx(rdi, Locals, local_num-1); + + // rjf: extract local's type key + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, local->type_idx); + mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module_idx); + + // rjf: extract local's location block + U64 ip_voff = e_base_ctx->thread_ip_voff; + for(U32 loc_block_idx = local->location_first; + loc_block_idx < local->location_opl; + loc_block_idx += 1) + { + RDI_LocationBlock *block = rdi_element_from_name_idx(rdi, LocationBlocks, loc_block_idx); + if(block->scope_off_first <= ip_voff && ip_voff < block->scope_off_opl) + { + mapped_location_block_module = module; + mapped_location_block = block; + } + } + } + }break; + + //- rjf: globals / procedures / types + case E_IdentifierResolutionPath_Globals: + case E_IdentifierResolutionPath_Procedures: + case E_IdentifierResolutionPath_ThreadLocals: + { + //- rjf: form namespaceified fallback versions of this lookup string + if(!string_mapped) + { + E_Module *module = e_base_ctx->primary_module; + RDI_Parsed *rdi = module->rdi; + RDI_Procedure *procedure = e_cache->thread_ip_procedure; + U64 name_size = 0; + U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); + String8 containing_procedure_name = str8(name_ptr, name_size); + U64 last_past_scope_resolution_pos = 0; + for(;;) + { + U64 past_next_dbl_colon_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("::"), 0)+2; + U64 past_next_dot_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("."), 0)+1; + U64 past_next_scope_resolution_pos = Min(past_next_dbl_colon_pos, past_next_dot_pos); + if(past_next_scope_resolution_pos >= containing_procedure_name.size) { break; } - U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; - U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); - bytecode_size += (1 + p_size); - next_off = (off + 1 + p_size); + String8 new_namespace_prefix_possibility = str8_prefix(containing_procedure_name, past_next_scope_resolution_pos); + String8 namespaceified_string = push_str8f(scratch.arena, "%S%S", new_namespace_prefix_possibility, string); + str8_list_push_front(scratch.arena, &namespaceified_strings, namespaceified_string); + last_past_scope_resolution_pos = past_next_scope_resolution_pos; } - mapped_bytecode = str8(all_location_data + off_first, bytecode_size); - }break; - case RDI_LocationKind_AddrRegPlusU16: - if(block->location_data_off + sizeof(RDI_LocationRegPlusU16) <= all_location_data_size) + } + + //- rjf: try globals + if(path == E_IdentifierResolutionPath_Globals && !string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("global"), 0))) + { + for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1) + { + E_Module *module = &e_base_ctx->modules[module_idx]; + RDI_Parsed *rdi = module->rdi; + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); + for(String8Node *n = namespaceified_strings.first; + n != 0 && matches_count == 0; + n = n->next) + { + node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[matches_count-1]; + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, match_idx); + U32 type_idx = global_var->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff)); + string_mapped = 1; + mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = module->space; + break; + } + } + } + + //- rjf: try thread-locals + if(path == E_IdentifierResolutionPath_ThreadLocals && !string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("thread_local"), 0))) + { + for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1) + { + E_Module *module = &e_base_ctx->modules[module_idx]; + RDI_Parsed *rdi = module->rdi; + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_ThreadVariables); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); + for(String8Node *n = namespaceified_strings.first; + n != 0 && matches_count == 0; + n = n->next) + { + node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[matches_count-1]; + RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(rdi, ThreadVariables, match_idx); + U32 type_idx = thread_var->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off)); + string_mapped = 1; + mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = module->space; + break; + } + } + } + + //- rjf: try procedures + if(path == E_IdentifierResolutionPath_Procedures && !string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("procedure"), 0))) + { + for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1) + { + E_Module *module = &e_base_ctx->modules[module_idx]; + RDI_Parsed *rdi = module->rdi; + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); + for(String8Node *n = namespaceified_strings.first; + n != 0 && matches_count == 0; + n = n->next) + { + node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[matches_count-1]; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, match_idx); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); + U64 voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); + U32 type_idx = procedure->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff)); + string_mapped = 1; + mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Value; + mapped_bytecode_space = module->space; + break; + } + } + } + }break; + + //- rjf: try types + case E_IdentifierResolutionPath_Types: + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("type"), 0))) + { + mapped_type_key = e_leaf_type_from_name(string); + if(!e_type_key_match(e_type_key_zero(), mapped_type_key)) { string_mapped = 1; - RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); + } + }break; + + + //- rjf: try registers + case E_IdentifierResolutionPath_Registers: + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) + { + U64 reg_num = e_num_from_string(e_ir_ctx->regs_map, string); + if(reg_num != 0) + { + string_mapped = 1; + REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(e_base_ctx->primary_module->arch)[reg_num]; E_OpList oplist = {0}; - U64 byte_size = bit_size_from_arch(arch)/8; - U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); + e_oplist_push_uconst(arena, &oplist, reg_rng.byte_off); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = space; - }break; - case RDI_LocationKind_AddrAddrRegPlusU16: + mapped_bytecode_space = e_base_ctx->thread_reg_space; + mapped_type_key = e_type_key_reg(e_base_ctx->primary_module->arch, reg_num); + } + }break; + + //- rjf: try register aliases + case E_IdentifierResolutionPath_RegisterAliases: + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) + { + U64 alias_num = e_num_from_string(e_ir_ctx->reg_alias_map, string); + if(alias_num != 0) { string_mapped = 1; - RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); + REGS_Slice alias_slice = regs_alias_code_slice_table_from_arch(e_base_ctx->primary_module->arch)[alias_num]; + REGS_Rng alias_reg_rng = regs_reg_code_rng_table_from_arch(e_base_ctx->primary_module->arch)[alias_slice.code]; E_OpList oplist = {0}; - U64 byte_size = bit_size_from_arch(arch)/8; - U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_MemRead, e_value_u64(bit_size_from_arch(arch)/8)); + e_oplist_push_uconst(arena, &oplist, alias_reg_rng.byte_off + alias_slice.byte_off); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = space; - }break; - case RDI_LocationKind_ValReg: - if(block->location_data_off + sizeof(RDI_LocationReg) <= all_location_data_size) - { - string_mapped = 1; - RDI_LocationReg loc = *(RDI_LocationReg *)(all_location_data + block->location_data_off); - - REGS_RegCode regs_reg_code = regs_reg_code_from_arch_rdi_code(arch, loc.reg_code); - REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(arch)[regs_reg_code]; - E_OpList oplist = {0}; - U64 byte_size = (U64)reg_rng.byte_size; - U64 byte_pos = 0; - U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, byte_pos); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Value; - mapped_bytecode_space = space; - }break; - } - } - } - - //- rjf: form namespaceified fallback versions of this lookup string - String8List namespaceified_strings = {0}; - if(!string_mapped) - { - E_Module *module = e_base_ctx->primary_module; - RDI_Parsed *rdi = module->rdi; - RDI_Procedure *procedure = e_cache->thread_ip_procedure; - U64 name_size = 0; - U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); - String8 containing_procedure_name = str8(name_ptr, name_size); - U64 last_past_scope_resolution_pos = 0; - for(;;) - { - U64 past_next_dbl_colon_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("::"), 0)+2; - U64 past_next_dot_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("."), 0)+1; - U64 past_next_scope_resolution_pos = Min(past_next_dbl_colon_pos, past_next_dot_pos); - if(past_next_scope_resolution_pos >= containing_procedure_name.size) + mapped_bytecode_space = e_base_ctx->thread_reg_space; + mapped_type_key = e_type_key_reg_alias(e_base_ctx->primary_module->arch, alias_num); + } + }break; + + //- rjf: try basic constants + case E_IdentifierResolutionPath_Constants: + if(!string_mapped && str8_match(string, str8_lit("true"), 0)) { - break; - } - String8 new_namespace_prefix_possibility = str8_prefix(containing_procedure_name, past_next_scope_resolution_pos); - String8 namespaceified_string = push_str8f(scratch.arena, "%S%S", new_namespace_prefix_possibility, string); - str8_list_push_front(scratch.arena, &namespaceified_strings, namespaceified_string); - last_past_scope_resolution_pos = past_next_scope_resolution_pos; - } - } - - //- rjf: try globals - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("global"), 0))) - { - for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1) - { - E_Module *module = &e_base_ctx->modules[module_idx]; - RDI_Parsed *rdi = module->rdi; - RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables); - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); - for(String8Node *n = namespaceified_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[matches_count-1]; - RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, match_idx); - U32 type_idx = global_var->type_idx; - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); - E_OpList oplist = {0}; - e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff)); string_mapped = 1; - mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = module->space; - break; - } - } - } - - //- rjf: try thread-locals - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("thread_local"), 0))) - { - for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1) - { - E_Module *module = &e_base_ctx->modules[module_idx]; - RDI_Parsed *rdi = module->rdi; - RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_ThreadVariables); - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); - for(String8Node *n = namespaceified_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[matches_count-1]; - RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(rdi, ThreadVariables, match_idx); - U32 type_idx = thread_var->type_idx; - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); E_OpList oplist = {0}; - e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off)); - string_mapped = 1; - mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = module->space; - break; - } - } - } - - //- rjf: try procedures - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("procedure"), 0))) - { - for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1) - { - E_Module *module = &e_base_ctx->modules[module_idx]; - RDI_Parsed *rdi = module->rdi; - RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); - for(String8Node *n = namespaceified_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[matches_count-1]; - RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, match_idx); - RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); - U64 voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); - U32 type_idx = procedure->type_idx; - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); - E_OpList oplist = {0}; - e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff)); - string_mapped = 1; - mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); + e_oplist_push_uconst(arena, &oplist, 1); + mapped_type_key = e_type_key_basic(E_TypeKind_Bool); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Value; - mapped_bytecode_space = module->space; - break; + } + if(!string_mapped && str8_match(string, str8_lit("false"), 0)) + { + string_mapped = 1; + E_OpList oplist = {0}; + e_oplist_push_uconst(arena, &oplist, 0); + mapped_type_key = e_type_key_basic(E_TypeKind_Bool); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Value; + }break; + + //- rjf: try macros + case E_IdentifierResolutionPath_Macros: + { + if(!generated) + { + E_Expr *macro_expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, string); + if(macro_expr != &e_expr_nil) + { + generated = 1; + e_string2expr_map_inc_poison(e_ir_ctx->macro_map, string); + result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, macro_expr); + e_string2expr_map_dec_poison(e_ir_ctx->macro_map, string); + } + } + }break; + } + + //- rjf: mapped to location block -> extract or produce bytecode for this mapping + if(!generated && mapped_location_block != 0) + { + E_Module *module = mapped_location_block_module; + E_Space space = module->space; + Arch arch = module->arch; + RDI_Parsed *rdi = module->rdi; + RDI_LocationBlock *block = mapped_location_block; + U64 all_location_data_size = 0; + U8 *all_location_data = rdi_table_from_name(rdi, LocationData, &all_location_data_size); + if(block->location_data_off + sizeof(RDI_LocationKind) <= all_location_data_size) + { + RDI_LocationKind loc_kind = *((RDI_LocationKind *)(all_location_data + block->location_data_off)); + switch(loc_kind) + { + default:{}break; + case RDI_LocationKind_ValBytecodeStream: {mapped_bytecode_mode = E_Mode_Value;}goto bytecode_stream; + case RDI_LocationKind_AddrBytecodeStream:{mapped_bytecode_mode = E_Mode_Offset;}goto bytecode_stream; + bytecode_stream:; + { + string_mapped = 1; + U64 bytecode_size = 0; + U64 off_first = block->location_data_off + sizeof(RDI_LocationKind); + U64 off_opl = all_location_data_size; + for(U64 off = off_first, next_off = off_opl; + off < all_location_data_size; + off = next_off) + { + next_off = off_opl; + U8 op = all_location_data[off]; + if(op == 0) + { + break; + } + U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; + U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); + bytecode_size += (1 + p_size); + next_off = (off + 1 + p_size); + } + mapped_bytecode = str8(all_location_data + off_first, bytecode_size); + }break; + case RDI_LocationKind_AddrRegPlusU16: + if(block->location_data_off + sizeof(RDI_LocationRegPlusU16) <= all_location_data_size) + { + string_mapped = 1; + RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); + E_OpList oplist = {0}; + U64 byte_size = bit_size_from_arch(arch)/8; + U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = space; + }break; + case RDI_LocationKind_AddrAddrRegPlusU16: + { + string_mapped = 1; + RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); + E_OpList oplist = {0}; + U64 byte_size = bit_size_from_arch(arch)/8; + U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_MemRead, e_value_u64(bit_size_from_arch(arch)/8)); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = space; + }break; + case RDI_LocationKind_ValReg: + if(block->location_data_off + sizeof(RDI_LocationReg) <= all_location_data_size) + { + string_mapped = 1; + RDI_LocationReg loc = *(RDI_LocationReg *)(all_location_data + block->location_data_off); + + REGS_RegCode regs_reg_code = regs_reg_code_from_arch_rdi_code(arch, loc.reg_code); + REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(arch)[regs_reg_code]; + E_OpList oplist = {0}; + U64 byte_size = (U64)reg_rng.byte_size; + U64 byte_pos = 0; + U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, byte_pos); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Value; + mapped_bytecode_space = space; + }break; + } } } - } - - //- rjf: try types - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("type"), 0))) - { - mapped_type_key = e_leaf_type_from_name(string); - if(!e_type_key_match(e_type_key_zero(), mapped_type_key)) - { - string_mapped = 1; - } - } - - //- rjf: try registers - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) - { - U64 reg_num = e_num_from_string(e_ir_ctx->regs_map, string); - if(reg_num != 0) - { - string_mapped = 1; - REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(e_base_ctx->primary_module->arch)[reg_num]; - E_OpList oplist = {0}; - e_oplist_push_uconst(arena, &oplist, reg_rng.byte_off); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = e_base_ctx->thread_reg_space; - mapped_type_key = e_type_key_reg(e_base_ctx->primary_module->arch, reg_num); - } - } - - //- rjf: try register aliases - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) - { - U64 alias_num = e_num_from_string(e_ir_ctx->reg_alias_map, string); - if(alias_num != 0) - { - string_mapped = 1; - REGS_Slice alias_slice = regs_alias_code_slice_table_from_arch(e_base_ctx->primary_module->arch)[alias_num]; - REGS_Rng alias_reg_rng = regs_reg_code_rng_table_from_arch(e_base_ctx->primary_module->arch)[alias_slice.code]; - E_OpList oplist = {0}; - e_oplist_push_uconst(arena, &oplist, alias_reg_rng.byte_off + alias_slice.byte_off); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = e_base_ctx->thread_reg_space; - mapped_type_key = e_type_key_reg_alias(e_base_ctx->primary_module->arch, alias_num); - } - } - - //- rjf: try basic constants - if(!string_mapped && str8_match(string, str8_lit("true"), 0)) - { - string_mapped = 1; - E_OpList oplist = {0}; - e_oplist_push_uconst(arena, &oplist, 1); - mapped_type_key = e_type_key_basic(E_TypeKind_Bool); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Value; - } - if(!string_mapped && str8_match(string, str8_lit("false"), 0)) - { - string_mapped = 1; - E_OpList oplist = {0}; - e_oplist_push_uconst(arena, &oplist, 0); - mapped_type_key = e_type_key_basic(E_TypeKind_Bool); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Value; - } - - //- rjf: generate IR trees for bytecode - B32 generated = 0; - if(!generated && mapped_bytecode.size != 0) - { - generated = 1; - E_IRNode *root = e_irtree_bytecode_no_copy(arena, mapped_bytecode); - root->space = mapped_bytecode_space; - result.root = root; - result.type_key = mapped_type_key; - result.mode = mapped_bytecode_mode; - } - - //- rjf: generate nil-IR trees w/ type for types - if(!generated && !e_type_key_match(e_type_key_zero(), mapped_type_key)) - { - generated = 1; - result.root = e_irtree_const_u(arena, 0); - result.type_key = mapped_type_key; - result.mode = E_Mode_Null; - } - - //- rjf: generate IR trees for macros - if(!generated) - { - E_Expr *macro_expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, string); - if(macro_expr != &e_expr_nil) + + //- rjf: generate IR trees for bytecode + if(!generated && mapped_bytecode.size != 0) { generated = 1; - e_string2expr_map_inc_poison(e_ir_ctx->macro_map, string); - result = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, macro_expr); - e_string2expr_map_dec_poison(e_ir_ctx->macro_map, string); + E_IRNode *root = e_irtree_bytecode_no_copy(arena, mapped_bytecode); + root->space = mapped_bytecode_space; + result.root = root; + result.type_key = mapped_type_key; + result.mode = mapped_bytecode_mode; + } + + //- rjf: generate nil-IR trees w/ type for types + if(!generated && !e_type_key_match(e_type_key_zero(), mapped_type_key)) + { + generated = 1; + result.root = e_irtree_const_u(arena, 0); + result.type_key = mapped_type_key; + result.mode = E_Mode_Null; } } //- rjf: extend generated result, if result was generated by an implicit member access - if(string_is_implicit_member_name) + if(generated && string_is_implicit_member_name) { E_Expr *access = e_expr_irext_member_access(arena, &e_expr_nil, &result, string); - result = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, access); + result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, access); } //- rjf: error on failure-to-generate @@ -2089,7 +2120,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 }break; case E_ExprKind_Unsigned: { - E_IRTreeAndType direct_irtree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, expr->first); + E_IRTreeAndType direct_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); result = direct_irtree; E_TypeKey direct_type_key = result.type_key; E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); @@ -2119,13 +2150,13 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 }break; case E_ExprKind_Ptr: { - E_IRTreeAndType ptee_irtree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, expr->first); + E_IRTreeAndType ptee_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); result = ptee_irtree; result.type_key = e_type_key_cons_ptr(e_base_ctx->primary_module->arch, result.type_key, 1, 0); }break; case E_ExprKind_Array: { - E_IRTreeAndType element_irtree = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, expr->first); + E_IRTreeAndType element_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); result = element_irtree; result.type_key = e_type_key_cons_array(result.type_key, expr->value.u64, 0); }break; @@ -2139,7 +2170,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 { E_Expr *lhs = expr->first; E_Expr *rhs = lhs->next; - result = e_push_irtree_and_type_from_expr(arena, parent, disallow_autohooks, 1, rhs); + result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, rhs); if(lhs->kind != E_ExprKind_LeafIdentifier) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, "Left side of assignment must be an unused identifier."); diff --git a/src/eval/eval_ir.h b/src/eval/eval_ir.h index afcf793d..c7b9e338 100644 --- a/src/eval/eval_ir.h +++ b/src/eval/eval_ir.h @@ -4,6 +4,33 @@ #ifndef EVAL_IR_H #define EVAL_IR_H +//////////////////////////////// +//~ rjf: Identifier Resolution Rule Types + +typedef enum E_IdentifierResolutionPath +{ + E_IdentifierResolutionPath_ParentExpr, + E_IdentifierResolutionPath_ParentExprMember, + E_IdentifierResolutionPath_ImplicitThisMember, + E_IdentifierResolutionPath_Local, + E_IdentifierResolutionPath_Globals, + E_IdentifierResolutionPath_ThreadLocals, + E_IdentifierResolutionPath_Procedures, + E_IdentifierResolutionPath_Types, + E_IdentifierResolutionPath_Registers, + E_IdentifierResolutionPath_RegisterAliases, + E_IdentifierResolutionPath_Constants, + E_IdentifierResolutionPath_Macros, +} +E_IdentifierResolutionPath; + +typedef struct E_IdentifierResolutionRule E_IdentifierResolutionRule; +struct E_IdentifierResolutionRule +{ + E_IdentifierResolutionPath *paths; + U64 count; +}; + //////////////////////////////// //~ rjf: IR State @@ -49,6 +76,51 @@ struct E_IRState E_IRCacheSlot *ir_cache_slots; }; +//////////////////////////////// +//~ rjf: Globals + +E_IdentifierResolutionPath e_default_identifier_resolution_paths[] = +{ + E_IdentifierResolutionPath_ParentExpr, + E_IdentifierResolutionPath_ParentExprMember, + E_IdentifierResolutionPath_ImplicitThisMember, + E_IdentifierResolutionPath_Local, + E_IdentifierResolutionPath_Globals, + E_IdentifierResolutionPath_ThreadLocals, + E_IdentifierResolutionPath_Procedures, + E_IdentifierResolutionPath_Types, + E_IdentifierResolutionPath_Registers, + E_IdentifierResolutionPath_RegisterAliases, + E_IdentifierResolutionPath_Constants, + E_IdentifierResolutionPath_Macros, +}; +E_IdentifierResolutionRule e_default_identifier_resolution_rule = +{ + e_default_identifier_resolution_paths, + ArrayCount(e_default_identifier_resolution_paths), +}; + +E_IdentifierResolutionPath e_callable_identifier_resolution_paths[] = +{ + E_IdentifierResolutionPath_Macros, + E_IdentifierResolutionPath_ParentExpr, + E_IdentifierResolutionPath_ParentExprMember, + E_IdentifierResolutionPath_ImplicitThisMember, + E_IdentifierResolutionPath_Local, + E_IdentifierResolutionPath_Globals, + E_IdentifierResolutionPath_ThreadLocals, + E_IdentifierResolutionPath_Procedures, + E_IdentifierResolutionPath_Types, + E_IdentifierResolutionPath_Registers, + E_IdentifierResolutionPath_RegisterAliases, + E_IdentifierResolutionPath_Constants, +}; +E_IdentifierResolutionRule e_callable_identifier_resolution_rule = +{ + e_callable_identifier_resolution_paths, + ArrayCount(e_callable_identifier_resolution_paths), +}; + //////////////////////////////// //~ rjf: IR-ization Functions @@ -88,7 +160,7 @@ internal void e_expr_unpoison(E_Expr *expr); //- rjf: top-level irtree/type extraction E_TYPE_ACCESS_FUNCTION_DEF(default); -internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr); +internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_IdentifierResolutionRule *identifier_resolution_rule, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr); //- rjf: irtree -> linear ops/bytecode internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out); diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index 6493b55e..d6babada 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -2661,7 +2661,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(slice) E_IRNode *idxed_base_tree = &e_irnode_nil; if(base_ptr_tree != &e_irnode_nil) { - E_IRTreeAndType idx_irtree = e_push_irtree_and_type_from_expr(arena, 0, 0, 1, expr->first->next); + E_IRTreeAndType idx_irtree = e_push_irtree_and_type_from_expr(arena, 0, &e_default_identifier_resolution_rule, 0, 1, expr->first->next); E_IRNode *idx_root = e_irtree_resolve_to_value(arena, idx_irtree.mode, idx_irtree.root, idx_irtree.type_key); E_IRNode *off_root = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, idx_root, e_irtree_const_u(arena, e_type_byte_size_from_key(e_type_key_unwrap(ext->base_ptr_member->type_key, E_TypeUnwrapFlag_All)))); idxed_base_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Add, base_ptr_tree, off_root); diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index cc199519..ba936b4b 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -1952,6 +1952,12 @@ fancy_viz_eval_tests(void) Bitmap foo = {(unsigned char *)&pixels[0], 18, 18}; raddbg_pin(foo); + //- rjf: name collisions with debugger rules + Function_Few_Params_Type *raw = 0; + char *text = "some_important_text_here\n"; + Bitmap bitmap = foo; + int x3 = 0; + //- rjf: 3D geometry float vertex_data[] = // pos.x, pos.y, pos.z, nor.x, nor.y, nor.z, tex.u, tex.v, col.r, col.g, col.b, ... { @@ -2143,7 +2149,7 @@ fancy_viz_eval_tests(void) float *vtx = vertex_data; int vtx_size = sizeof vertex_data; raddbg_pin(geo3d(index_data, count = count, vtx = vtx, vtx_size = vtx_size)); - int x3 = 0; + int x4 = 0; } //////////////////////////////// diff --git a/src/render/opengl/generated/render_opengl.meta.c b/src/render/opengl/generated/render_opengl.meta.c index 60c10194..7084ac1b 100644 --- a/src/render/opengl/generated/render_opengl.meta.c +++ b/src/render/opengl/generated/render_opengl.meta.c @@ -1,38 +1,38 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//- GENERATED CODE - -C_LINKAGE_BEGIN -String8 r_ogl_shader_kind_name_table[2] = -{ -str8_lit_comp("rect"), -str8_lit_comp("blur"), -}; - -String8 * r_ogl_shader_kind_vshad_src_table[2] = -{ -&r_ogl_rect_vshad_src, -&r_ogl_blur_vshad_src, -}; - -String8 * r_ogl_shader_kind_pshad_src_table[2] = -{ -&r_ogl_rect_pshad_src, -&r_ogl_blur_pshad_src, -}; - -R_OGL_AttributeArray r_ogl_shader_kind_input_attributes_table[2] = -{ -{ r_ogl_rect_input_attributes, ArrayCount(r_ogl_rect_input_attributes) }, -{ 0, }, -}; - -R_OGL_AttributeArray r_ogl_shader_kind_output_attributes_table[2] = -{ -{ r_ogl_single_color_output_attributes, ArrayCount(r_ogl_single_color_output_attributes) }, -{ r_ogl_single_color_output_attributes, ArrayCount(r_ogl_single_color_output_attributes) }, -}; - -C_LINKAGE_END - +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//- GENERATED CODE + +C_LINKAGE_BEGIN +String8 r_ogl_shader_kind_name_table[2] = +{ +str8_lit_comp("rect"), +str8_lit_comp("blur"), +}; + +String8 * r_ogl_shader_kind_vshad_src_table[2] = +{ +&r_ogl_rect_vshad_src, +&r_ogl_blur_vshad_src, +}; + +String8 * r_ogl_shader_kind_pshad_src_table[2] = +{ +&r_ogl_rect_pshad_src, +&r_ogl_blur_pshad_src, +}; + +R_OGL_AttributeArray r_ogl_shader_kind_input_attributes_table[2] = +{ +{ r_ogl_rect_input_attributes, ArrayCount(r_ogl_rect_input_attributes) }, +{ 0, }, +}; + +R_OGL_AttributeArray r_ogl_shader_kind_output_attributes_table[2] = +{ +{ r_ogl_single_color_output_attributes, ArrayCount(r_ogl_single_color_output_attributes) }, +{ r_ogl_single_color_output_attributes, ArrayCount(r_ogl_single_color_output_attributes) }, +}; + +C_LINKAGE_END + diff --git a/src/render/opengl/generated/render_opengl.meta.h b/src/render/opengl/generated/render_opengl.meta.h index 6e7f6024..9f33f24d 100644 --- a/src/render/opengl/generated/render_opengl.meta.h +++ b/src/render/opengl/generated/render_opengl.meta.h @@ -1,276 +1,276 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//- GENERATED CODE - -#ifndef RENDER_OPENGL_META_H -#define RENDER_OPENGL_META_H - -typedef enum R_OGL_ShaderKind -{ -R_OGL_ShaderKind_Rect, -R_OGL_ShaderKind_Blur, -R_OGL_ShaderKind_COUNT, -} R_OGL_ShaderKind; - -C_LINKAGE_BEGIN -extern String8 r_ogl_shader_kind_name_table[2]; -extern String8 * r_ogl_shader_kind_vshad_src_table[2]; -extern String8 * r_ogl_shader_kind_pshad_src_table[2]; -extern R_OGL_AttributeArray r_ogl_shader_kind_input_attributes_table[2]; -extern R_OGL_AttributeArray r_ogl_shader_kind_output_attributes_table[2]; -read_only global String8 r_ogl_rect_vshad_src = -str8_lit_comp( -"" -"\n" -"#version 330 core\n" -"\n" -"in vec4 c2v_dst_rect;\n" -"in vec4 c2v_src_rect;\n" -"in vec4 c2v_colors_0;\n" -"in vec4 c2v_colors_1;\n" -"in vec4 c2v_colors_2;\n" -"in vec4 c2v_colors_3;\n" -"in vec4 c2v_corner_radii;\n" -"in vec4 c2v_style; // x: border_thickness_px, y: softness_px, z: omit_texture, w: unused\n" -"\n" -"out vec2 v2p_sdf_sample_pos;\n" -"out vec2 v2p_texcoord_pct;\n" -"out vec2 v2p_rect_half_size_px;\n" -"out vec4 v2p_tint;\n" -"out float v2p_corner_radius;\n" -"out float v2p_border_thickness;\n" -"out float v2p_softness;\n" -"out float v2p_omit_texture;\n" -"\n" -"uniform sampler2D u_tex_color;\n" -"uniform vec2 u_viewport_size_px;\n" -"\n" -"void main(void)\n" -"{\n" -" // rjf: constants\n" -" vec2 vertices[] = vec2[](vec2(-1, -1), vec2(-1, +1), vec2(+1, -1), vec2(+1, +1));\n" -" \n" -" // rjf: find dst position\n" -" vec2 dst_half_size = (c2v_dst_rect.zw - c2v_dst_rect.xy) / 2;\n" -" vec2 dst_center = (c2v_dst_rect.zw + c2v_dst_rect.xy) / 2;\n" -" vec2 dst_position = vertices[gl_VertexID] * dst_half_size + dst_center;\n" -" \n" -" // rjf: find src position\n" -" vec2 src_half_size = (c2v_src_rect.zw - c2v_src_rect.xy) / 2;\n" -" vec2 src_center = (c2v_src_rect.zw + c2v_src_rect.xy) / 2;\n" -" vec2 src_position = vertices[gl_VertexID] * src_half_size + src_center;\n" -" \n" -" // rjf: find color\n" -" vec4 colors[] = vec4[](c2v_colors_0, c2v_colors_1, c2v_colors_2, c2v_colors_3);\n" -" vec4 color = colors[gl_VertexID];\n" -" \n" -" // rjf: find corner radius\n" -" float corner_radii[] = float[](c2v_corner_radii.x, c2v_corner_radii.y, c2v_corner_radii.z, c2v_corner_radii.w);\n" -" float corner_radius = corner_radii[gl_VertexID];\n" -" \n" -" // rjf: fill outputs\n" -" vec2 dst_verts_pct = vec2(((gl_VertexID >> 1) != 1) ? 1.f : 0.f,\n" -" ((gl_VertexID & 1) != 0) ? 0.f : 1.f);\n" -" ivec2 u_tex_color_size_i = textureSize(u_tex_color, 0);\n" -" vec2 u_tex_color_size = vec2(float(u_tex_color_size_i.x), float(u_tex_color_size_i.y));\n" -" {\n" -" gl_Position = vec4(2 * dst_position.x / u_viewport_size_px.x - 1,\n" -" 2 * (1 - dst_position.y / u_viewport_size_px.y) - 1,\n" -" 0.0, 1.0);\n" -" v2p_sdf_sample_pos = (2.f * dst_verts_pct - 1.f) * dst_half_size;\n" -" v2p_texcoord_pct = src_position / u_tex_color_size;\n" -" v2p_rect_half_size_px = dst_half_size;\n" -" v2p_tint = color;\n" -" v2p_corner_radius = corner_radius;\n" -" v2p_border_thickness = c2v_style.x;\n" -" v2p_softness = c2v_style.y;\n" -" v2p_omit_texture = c2v_style.z;\n" -" }\n" -"}\n" -"" -); - -read_only global String8 r_ogl_rect_pshad_src = -str8_lit_comp( -"" -"\n" -"#version 330 core\n" -"\n" -"in vec2 v2p_sdf_sample_pos;\n" -"in vec2 v2p_texcoord_pct;\n" -"in vec2 v2p_rect_half_size_px;\n" -"in vec4 v2p_tint;\n" -"in float v2p_corner_radius;\n" -"in float v2p_border_thickness;\n" -"in float v2p_softness;\n" -"in float v2p_omit_texture;\n" -"\n" -"out vec4 final_color;\n" -"\n" -"uniform float u_opacity;\n" -"uniform sampler2D u_tex_color;\n" -"uniform mat4 u_texture_sample_channel_map;\n" -"\n" -"float rect_sdf(vec2 sample_pos, vec2 rect_half_size, float r)\n" -"{\n" -" return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n" -"}\n" -"\n" -"float linear_from_srgb_f32(float x)\n" -"{\n" -" return x < 0.0404482362771082 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);\n" -"}\n" -"\n" -"vec4 linear_from_srgba(vec4 v)\n" -"{\n" -" vec4 result = vec4(linear_from_srgb_f32(v.x),\n" -" linear_from_srgb_f32(v.y),\n" -" linear_from_srgb_f32(v.z),\n" -" v.w);\n" -" return result;\n" -"}\n" -"\n" -"void main(void)\n" -"{\n" -" // rjf: sample texture\n" -" vec4 albedo_sample = vec4(1, 1, 1, 1);\n" -" if(v2p_omit_texture < 1)\n" -" {\n" -" albedo_sample = u_texture_sample_channel_map * texture(u_tex_color, v2p_texcoord_pct);\n" -" albedo_sample = linear_from_srgba(albedo_sample);\n" -" }\n" -" \n" -" // rjf: sample for borders\n" -" float border_sdf_t = 1;\n" -" if(v2p_border_thickness > 0)\n" -" {\n" -" float border_sdf_s = rect_sdf(v2p_sdf_sample_pos,\n" -" v2p_rect_half_size_px - vec2(v2p_softness*2.f, v2p_softness*2.f) - v2p_border_thickness,\n" -" max(v2p_corner_radius-v2p_border_thickness, 0));\n" -" border_sdf_t = smoothstep(0, 2*v2p_softness, border_sdf_s);\n" -" }\n" -" if(border_sdf_t < 0.001f)\n" -" {\n" -" discard;\n" -" }\n" -" \n" -" // rjf: sample for corners\n" -" float corner_sdf_t = 1;\n" -" if(v2p_corner_radius > 0 || v2p_softness > 0.75f)\n" -" {\n" -" float corner_sdf_s = rect_sdf(v2p_sdf_sample_pos,\n" -" v2p_rect_half_size_px - vec2(v2p_softness*2.f, v2p_softness*2.f),\n" -" v2p_corner_radius);\n" -" corner_sdf_t = 1-smoothstep(0, 2*v2p_softness, corner_sdf_s);\n" -" }\n" -" \n" -" // rjf: form+return final color\n" -" final_color = albedo_sample;\n" -" final_color *= v2p_tint;\n" -" final_color.a *= u_opacity;\n" -" final_color.a *= corner_sdf_t;\n" -" final_color.a *= border_sdf_t;\n" -"}\n" -"" -); - -read_only global String8 r_ogl_blur_vshad_src = -str8_lit_comp( -"" -"\n" -"#version 330 core\n" -"\n" -"uniform vec4 rect;\n" -"uniform vec4 corner_radii_px;\n" -"uniform vec2 viewport_size;\n" -"uniform uint blur_count;\n" -"\n" -"out vec2 texcoord;\n" -"out vec2 sdf_sample_pos;\n" -"out vec2 rect_half_size;\n" -"out float corner_radius;\n" -"\n" -"void main(void)\n" -"{\n" -" vec2 vertex_positions_scrn[] = vec2[](rect.xw,\n" -" rect.xy,\n" -" rect.zw,\n" -" rect.zy);\n" -" float corner_radii_px[] = float[](corner_radii_px.y,\n" -" corner_radii_px.x,\n" -" corner_radii_px.w,\n" -" corner_radii_px.z);\n" -" vec2 cornercoords_pct = vec2((gl_VertexID >> 1) != 0 ? 1.f : 0.f,\n" -" (gl_VertexID & 1) != 0 ? 0.f : 1.f);\n" -" \n" -" vec2 vertex_position_pct = vertex_positions_scrn[gl_VertexID] / viewport_size;\n" -" vec2 vertex_position_scr = 2.f * vertex_position_pct - 1.f;\n" -" \n" -" vec2 rect_half_size = vec2((rect.z-rect.x)/2, (rect.w-rect.y)/2);\n" -" \n" -" gl_Position = vec4(vertex_position_scr.x, -vertex_position_scr.y, 0.f, 1.f);\n" -" texcoord = vertex_position_pct;\n" -" sdf_sample_pos = (2.f * cornercoords_pct - 1.f) * rect_half_size;\n" -" rect_half_size = rect_half_size - 2.f;\n" -" corner_radius = corner_radii_px[gl_VertexID];\n" -"}\n" -"" -); - -read_only global String8 r_ogl_blur_pshad_src = -str8_lit_comp( -"" -"\n" -"#version 330 core\n" -"\n" -"uniform sampler2D tex;\n" -"uniform vec4 kernel[32];\n" -"uniform int blur_count;\n" -"uniform vec2 direction;\n" -"\n" -"in vec2 texcoord;\n" -"in vec2 sdf_sample_pos;\n" -"in vec2 rect_half_size;\n" -"in float corner_radius;\n" -"\n" -"out vec4 final_color;\n" -"\n" -"float rect_sdf(vec2 sample_pos, vec2 rect_half_size, float r)\n" -"{\n" -" return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n" -"}\n" -"\n" -"void main(void)\n" -"{\n" -" // rjf: blend weighted texture samples into color\n" -" vec3 color = kernel[0].x * texture(tex, texcoord).rgb;\n" -" \n" -" for(int i = 1; i < blur_count; i += 1)\n" -" {\n" -" float weight = kernel[i].x;\n" -" float offset = kernel[i].y;\n" -" color += weight * texture(tex, texcoord - offset * direction).rgb;\n" -" color += weight * texture(tex, texcoord + offset * direction).rgb;\n" -" }\n" -" \n" -" // rjf: sample for corners\n" -" float corner_sdf_s = rect_sdf(sdf_sample_pos, rect_half_size, corner_radius);\n" -" float corner_sdf_t = 1-smoothstep(0, 2, corner_sdf_s);\n" -" \n" -" // rjf: weight output color by sdf\n" -" // this is doing alpha testing, leave blurring only where mostly opaque pixels are\n" -" if(corner_sdf_t < 0.9f)\n" -" {\n" -" discard;\n" -" }\n" -" \n" -" final_color = vec4(color, 1.f);\n" -"}\n" -"" -); - - -C_LINKAGE_END - -#endif // RENDER_OPENGL_META_H +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//- GENERATED CODE + +#ifndef RENDER_OPENGL_META_H +#define RENDER_OPENGL_META_H + +typedef enum R_OGL_ShaderKind +{ +R_OGL_ShaderKind_Rect, +R_OGL_ShaderKind_Blur, +R_OGL_ShaderKind_COUNT, +} R_OGL_ShaderKind; + +C_LINKAGE_BEGIN +extern String8 r_ogl_shader_kind_name_table[2]; +extern String8 * r_ogl_shader_kind_vshad_src_table[2]; +extern String8 * r_ogl_shader_kind_pshad_src_table[2]; +extern R_OGL_AttributeArray r_ogl_shader_kind_input_attributes_table[2]; +extern R_OGL_AttributeArray r_ogl_shader_kind_output_attributes_table[2]; +read_only global String8 r_ogl_rect_vshad_src = +str8_lit_comp( +"" +"\n" +"#version 330 core\n" +"\n" +"in vec4 c2v_dst_rect;\n" +"in vec4 c2v_src_rect;\n" +"in vec4 c2v_colors_0;\n" +"in vec4 c2v_colors_1;\n" +"in vec4 c2v_colors_2;\n" +"in vec4 c2v_colors_3;\n" +"in vec4 c2v_corner_radii;\n" +"in vec4 c2v_style; // x: border_thickness_px, y: softness_px, z: omit_texture, w: unused\n" +"\n" +"out vec2 v2p_sdf_sample_pos;\n" +"out vec2 v2p_texcoord_pct;\n" +"out vec2 v2p_rect_half_size_px;\n" +"out vec4 v2p_tint;\n" +"out float v2p_corner_radius;\n" +"out float v2p_border_thickness;\n" +"out float v2p_softness;\n" +"out float v2p_omit_texture;\n" +"\n" +"uniform sampler2D u_tex_color;\n" +"uniform vec2 u_viewport_size_px;\n" +"\n" +"void main(void)\n" +"{\n" +" // rjf: constants\n" +" vec2 vertices[] = vec2[](vec2(-1, -1), vec2(-1, +1), vec2(+1, -1), vec2(+1, +1));\n" +" \n" +" // rjf: find dst position\n" +" vec2 dst_half_size = (c2v_dst_rect.zw - c2v_dst_rect.xy) / 2;\n" +" vec2 dst_center = (c2v_dst_rect.zw + c2v_dst_rect.xy) / 2;\n" +" vec2 dst_position = vertices[gl_VertexID] * dst_half_size + dst_center;\n" +" \n" +" // rjf: find src position\n" +" vec2 src_half_size = (c2v_src_rect.zw - c2v_src_rect.xy) / 2;\n" +" vec2 src_center = (c2v_src_rect.zw + c2v_src_rect.xy) / 2;\n" +" vec2 src_position = vertices[gl_VertexID] * src_half_size + src_center;\n" +" \n" +" // rjf: find color\n" +" vec4 colors[] = vec4[](c2v_colors_0, c2v_colors_1, c2v_colors_2, c2v_colors_3);\n" +" vec4 color = colors[gl_VertexID];\n" +" \n" +" // rjf: find corner radius\n" +" float corner_radii[] = float[](c2v_corner_radii.x, c2v_corner_radii.y, c2v_corner_radii.z, c2v_corner_radii.w);\n" +" float corner_radius = corner_radii[gl_VertexID];\n" +" \n" +" // rjf: fill outputs\n" +" vec2 dst_verts_pct = vec2(((gl_VertexID >> 1) != 1) ? 1.f : 0.f,\n" +" ((gl_VertexID & 1) != 0) ? 0.f : 1.f);\n" +" ivec2 u_tex_color_size_i = textureSize(u_tex_color, 0);\n" +" vec2 u_tex_color_size = vec2(float(u_tex_color_size_i.x), float(u_tex_color_size_i.y));\n" +" {\n" +" gl_Position = vec4(2 * dst_position.x / u_viewport_size_px.x - 1,\n" +" 2 * (1 - dst_position.y / u_viewport_size_px.y) - 1,\n" +" 0.0, 1.0);\n" +" v2p_sdf_sample_pos = (2.f * dst_verts_pct - 1.f) * dst_half_size;\n" +" v2p_texcoord_pct = src_position / u_tex_color_size;\n" +" v2p_rect_half_size_px = dst_half_size;\n" +" v2p_tint = color;\n" +" v2p_corner_radius = corner_radius;\n" +" v2p_border_thickness = c2v_style.x;\n" +" v2p_softness = c2v_style.y;\n" +" v2p_omit_texture = c2v_style.z;\n" +" }\n" +"}\n" +"" +); + +read_only global String8 r_ogl_rect_pshad_src = +str8_lit_comp( +"" +"\n" +"#version 330 core\n" +"\n" +"in vec2 v2p_sdf_sample_pos;\n" +"in vec2 v2p_texcoord_pct;\n" +"in vec2 v2p_rect_half_size_px;\n" +"in vec4 v2p_tint;\n" +"in float v2p_corner_radius;\n" +"in float v2p_border_thickness;\n" +"in float v2p_softness;\n" +"in float v2p_omit_texture;\n" +"\n" +"out vec4 final_color;\n" +"\n" +"uniform float u_opacity;\n" +"uniform sampler2D u_tex_color;\n" +"uniform mat4 u_texture_sample_channel_map;\n" +"\n" +"float rect_sdf(vec2 sample_pos, vec2 rect_half_size, float r)\n" +"{\n" +" return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n" +"}\n" +"\n" +"float linear_from_srgb_f32(float x)\n" +"{\n" +" return x < 0.0404482362771082 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);\n" +"}\n" +"\n" +"vec4 linear_from_srgba(vec4 v)\n" +"{\n" +" vec4 result = vec4(linear_from_srgb_f32(v.x),\n" +" linear_from_srgb_f32(v.y),\n" +" linear_from_srgb_f32(v.z),\n" +" v.w);\n" +" return result;\n" +"}\n" +"\n" +"void main(void)\n" +"{\n" +" // rjf: sample texture\n" +" vec4 albedo_sample = vec4(1, 1, 1, 1);\n" +" if(v2p_omit_texture < 1)\n" +" {\n" +" albedo_sample = u_texture_sample_channel_map * texture(u_tex_color, v2p_texcoord_pct);\n" +" albedo_sample = linear_from_srgba(albedo_sample);\n" +" }\n" +" \n" +" // rjf: sample for borders\n" +" float border_sdf_t = 1;\n" +" if(v2p_border_thickness > 0)\n" +" {\n" +" float border_sdf_s = rect_sdf(v2p_sdf_sample_pos,\n" +" v2p_rect_half_size_px - vec2(v2p_softness*2.f, v2p_softness*2.f) - v2p_border_thickness,\n" +" max(v2p_corner_radius-v2p_border_thickness, 0));\n" +" border_sdf_t = smoothstep(0, 2*v2p_softness, border_sdf_s);\n" +" }\n" +" if(border_sdf_t < 0.001f)\n" +" {\n" +" discard;\n" +" }\n" +" \n" +" // rjf: sample for corners\n" +" float corner_sdf_t = 1;\n" +" if(v2p_corner_radius > 0 || v2p_softness > 0.75f)\n" +" {\n" +" float corner_sdf_s = rect_sdf(v2p_sdf_sample_pos,\n" +" v2p_rect_half_size_px - vec2(v2p_softness*2.f, v2p_softness*2.f),\n" +" v2p_corner_radius);\n" +" corner_sdf_t = 1-smoothstep(0, 2*v2p_softness, corner_sdf_s);\n" +" }\n" +" \n" +" // rjf: form+return final color\n" +" final_color = albedo_sample;\n" +" final_color *= v2p_tint;\n" +" final_color.a *= u_opacity;\n" +" final_color.a *= corner_sdf_t;\n" +" final_color.a *= border_sdf_t;\n" +"}\n" +"" +); + +read_only global String8 r_ogl_blur_vshad_src = +str8_lit_comp( +"" +"\n" +"#version 330 core\n" +"\n" +"uniform vec4 rect;\n" +"uniform vec4 corner_radii_px;\n" +"uniform vec2 viewport_size;\n" +"uniform uint blur_count;\n" +"\n" +"out vec2 texcoord;\n" +"out vec2 sdf_sample_pos;\n" +"out vec2 rect_half_size;\n" +"out float corner_radius;\n" +"\n" +"void main(void)\n" +"{\n" +" vec2 vertex_positions_scrn[] = vec2[](rect.xw,\n" +" rect.xy,\n" +" rect.zw,\n" +" rect.zy);\n" +" float corner_radii_px[] = float[](corner_radii_px.y,\n" +" corner_radii_px.x,\n" +" corner_radii_px.w,\n" +" corner_radii_px.z);\n" +" vec2 cornercoords_pct = vec2((gl_VertexID >> 1) != 0 ? 1.f : 0.f,\n" +" (gl_VertexID & 1) != 0 ? 0.f : 1.f);\n" +" \n" +" vec2 vertex_position_pct = vertex_positions_scrn[gl_VertexID] / viewport_size;\n" +" vec2 vertex_position_scr = 2.f * vertex_position_pct - 1.f;\n" +" \n" +" vec2 rect_half_size = vec2((rect.z-rect.x)/2, (rect.w-rect.y)/2);\n" +" \n" +" gl_Position = vec4(vertex_position_scr.x, -vertex_position_scr.y, 0.f, 1.f);\n" +" texcoord = vertex_position_pct;\n" +" sdf_sample_pos = (2.f * cornercoords_pct - 1.f) * rect_half_size;\n" +" rect_half_size = rect_half_size - 2.f;\n" +" corner_radius = corner_radii_px[gl_VertexID];\n" +"}\n" +"" +); + +read_only global String8 r_ogl_blur_pshad_src = +str8_lit_comp( +"" +"\n" +"#version 330 core\n" +"\n" +"uniform sampler2D tex;\n" +"uniform vec4 kernel[32];\n" +"uniform int blur_count;\n" +"uniform vec2 direction;\n" +"\n" +"in vec2 texcoord;\n" +"in vec2 sdf_sample_pos;\n" +"in vec2 rect_half_size;\n" +"in float corner_radius;\n" +"\n" +"out vec4 final_color;\n" +"\n" +"float rect_sdf(vec2 sample_pos, vec2 rect_half_size, float r)\n" +"{\n" +" return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n" +"}\n" +"\n" +"void main(void)\n" +"{\n" +" // rjf: blend weighted texture samples into color\n" +" vec3 color = kernel[0].x * texture(tex, texcoord).rgb;\n" +" \n" +" for(int i = 1; i < blur_count; i += 1)\n" +" {\n" +" float weight = kernel[i].x;\n" +" float offset = kernel[i].y;\n" +" color += weight * texture(tex, texcoord - offset * direction).rgb;\n" +" color += weight * texture(tex, texcoord + offset * direction).rgb;\n" +" }\n" +" \n" +" // rjf: sample for corners\n" +" float corner_sdf_s = rect_sdf(sdf_sample_pos, rect_half_size, corner_radius);\n" +" float corner_sdf_t = 1-smoothstep(0, 2, corner_sdf_s);\n" +" \n" +" // rjf: weight output color by sdf\n" +" // this is doing alpha testing, leave blurring only where mostly opaque pixels are\n" +" if(corner_sdf_t < 0.9f)\n" +" {\n" +" discard;\n" +" }\n" +" \n" +" final_color = vec4(color, 1.f);\n" +"}\n" +"" +); + + +C_LINKAGE_END + +#endif // RENDER_OPENGL_META_H